// #sqrt{#frac{p(1-p)}{N}}.
//End_Latex
#include "TBinomialEfficiencyFitter.h"
#include "TMath.h"
#include "TPluginManager.h"
#include "TROOT.h"
#include "TH1.h"
#include "TF1.h"
#include "TF2.h"
#include "TF3.h"
#include "TVirtualFitter.h"
#include "TEnv.h"
#include <limits>
TVirtualFitter *TBinomialEfficiencyFitter::fgFitter = 0;
const Double_t kDefaultEpsilon = 1E-12;
ClassImp(TBinomialEfficiencyFitter)
TBinomialEfficiencyFitter::TBinomialEfficiencyFitter() {
fNumerator = 0;
fDenominator = 0;
fFunction = 0;
fFitDone = kFALSE;
fAverage = kFALSE;
fRange = kFALSE;
}
TBinomialEfficiencyFitter::TBinomialEfficiencyFitter(const TH1 *numerator, const TH1 *denominator) {
fEpsilon = kDefaultEpsilon;
Set(numerator,denominator);
}
TBinomialEfficiencyFitter::~TBinomialEfficiencyFitter() {
delete fgFitter; fgFitter = 0;
}
void TBinomialEfficiencyFitter::Set(const TH1 *numerator, const TH1 *denominator)
{
fNumerator = (TH1*)numerator;
fDenominator = (TH1*)denominator;
fFitDone = kFALSE;
fAverage = kFALSE;
fRange = kFALSE;
}
void TBinomialEfficiencyFitter::SetPrecision(Double_t epsilon)
{
fEpsilon = epsilon;
}
TVirtualFitter* TBinomialEfficiencyFitter::GetFitter()
{
return fgFitter;
}
Int_t TBinomialEfficiencyFitter::Fit(TF1 *f1, Option_t* option)
{
TString opt = option;
opt.ToUpper();
fAverage = opt.Contains("I");
fRange = opt.Contains("R");
Bool_t verbose = opt.Contains("V");
fFunction = (TF1*)f1;
Int_t i, npar;
npar = f1->GetNpar();
if (npar <= 0) {
Error("Fit", "function %s has illegal number of parameters = %d",
f1->GetName(), npar);
return -3;
}
if (!f1) return -1;
if (!fNumerator || !fDenominator) {
Error("Fit","No numerator or denominator histograms set");
return -5;
}
if (f1->GetNdim() != fNumerator->GetDimension()) {
Error("Fit","function %s dimension, %d, does not match histogram dimension, %d",
f1->GetName(), f1->GetNdim(), fNumerator->GetDimension());
return -4;
}
if (fNumerator->GetNbinsX() != fDenominator->GetNbinsX() ||
(f1->GetNdim() > 1 && fNumerator->GetNbinsY() != fDenominator->GetNbinsY()) ||
(f1->GetNdim() > 2 && fNumerator->GetNbinsZ() != fDenominator->GetNbinsZ())) {
Error("Fit", "numerator and denominator histograms do not have identical numbers of bins");
return -6;
}
Int_t maxpar = npar;
if (!fgFitter) {
TPluginHandler *h;
TString fitterName = TVirtualFitter::GetDefaultFitter();
if (fitterName == "")
fitterName = gEnv->GetValue("Root.Fitter","Minuit");
if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualFitter", fitterName ))) {
if (h->LoadPlugin() == -1)
return 0;
fgFitter = (TVirtualFitter*) h->ExecPlugin(1, maxpar);
}
if (!fgFitter) printf("ERROR fgFitter is NULL\n");
}
fgFitter->SetObjectFit(this);
fgFitter->Clear();
fgFitter->SetFCN(BinomialEfficiencyFitterFCN);
Int_t nfixed = 0;
Double_t al,bl,we,arglist[100];
for (i = 0; i < npar; i++) {
f1->GetParLimits(i,al,bl);
if (al*bl != 0 && al >= bl) {
al = bl = 0;
arglist[nfixed] = i+1;
nfixed++;
}
we = f1->GetParError(i);
if (we <= 0) we = 0.3*TMath::Abs(f1->GetParameter(i));
if (we == 0) we = 0.01;
fgFitter->SetParameter(i, f1->GetParName(i),
f1->GetParameter(i),
we, al,bl);
}
if (nfixed > 0) fgFitter->ExecuteCommand("FIX",arglist,nfixed);
Double_t plist[2];
plist[0] = 0.5;
fgFitter->ExecuteCommand("SET ERRDEF",plist,1);
if (verbose) {
plist[0] = 3;
fgFitter->ExecuteCommand("SET PRINT",plist,1);
}
fFitDone = kTRUE;
plist[0] = TVirtualFitter::GetMaxIterations();
plist[1] = TVirtualFitter::GetPrecision();
Int_t result = fgFitter->ExecuteCommand("MINIMIZE",plist,2);
char parName[50];
Double_t par;
Double_t eplus,eminus,eparab,globcc,werr;
for (i = 0; i < npar; ++i) {
fgFitter->GetParameter(i,parName, par,we,al,bl);
fgFitter->GetErrors(i,eplus,eminus,eparab,globcc);
if (eplus > 0 && eminus < 0) werr = 0.5*(eplus-eminus);
else werr = we;
f1->SetParameter(i,par);
f1->SetParError(i,werr);
}
f1->SetNDF(f1->GetNumberFitPoints()-npar+nfixed);
return result;
}
void TBinomialEfficiencyFitter::ComputeFCN(Int_t& , Double_t* ,
Double_t& f, Double_t* par, Int_t )
{
int nDim = fDenominator->GetDimension();
int xlowbin = fDenominator->GetXaxis()->GetFirst();
int xhighbin = fDenominator->GetXaxis()->GetLast();
int ylowbin = 0, yhighbin = 0, zlowbin = 0, zhighbin = 0;
if (nDim > 1) {
ylowbin = fDenominator->GetYaxis()->GetFirst();
yhighbin = fDenominator->GetYaxis()->GetLast();
if (nDim > 2) {
zlowbin = fDenominator->GetZaxis()->GetFirst();
zhighbin = fDenominator->GetZaxis()->GetLast();
}
}
fFunction->SetParameters(par);
if (fRange) {
double xmin, xmax, ymin, ymax, zmin, zmax;
if (nDim == 1) {
fFunction->GetRange(xmin, xmax);
xlowbin = fDenominator->GetXaxis()->FindBin(xmin);
xhighbin = fDenominator->GetXaxis()->FindBin(xmax);
} else if (nDim == 2) {
fFunction->GetRange(xmin, ymin, xmax, ymax);
xlowbin = fDenominator->GetXaxis()->FindBin(xmin);
xhighbin = fDenominator->GetXaxis()->FindBin(xmax);
ylowbin = fDenominator->GetYaxis()->FindBin(ymin);
yhighbin = fDenominator->GetYaxis()->FindBin(ymax);
} else if (nDim == 3) {
fFunction->GetRange(xmin, ymin, zmin, xmax, ymax, zmax);
xlowbin = fDenominator->GetXaxis()->FindBin(xmin);
xhighbin = fDenominator->GetXaxis()->FindBin(xmax);
ylowbin = fDenominator->GetYaxis()->FindBin(ymin);
yhighbin = fDenominator->GetYaxis()->FindBin(ymax);
zlowbin = fDenominator->GetZaxis()->FindBin(zmin);
zhighbin = fDenominator->GetZaxis()->FindBin(zmax);
}
}
f = 0.;
Int_t npoints = 0;
Double_t nmax = 0;
for (int xbin = xlowbin; xbin <= xhighbin; ++xbin) {
Double_t xlow = fDenominator->GetXaxis()->GetBinLowEdge(xbin);
Double_t xup = fDenominator->GetXaxis()->GetBinLowEdge(xbin+1);
for (int ybin = ylowbin; ybin <= yhighbin; ++ybin) {
Double_t ylow = (nDim > 1) ? fDenominator->GetYaxis()->GetBinLowEdge(ybin) : 0;
Double_t yup = (nDim > 1) ? fDenominator->GetYaxis()->GetBinLowEdge(ybin+1) : 0;
for (int zbin = zlowbin; zbin <= zhighbin; ++zbin) {
Double_t zlow = (nDim > 2) ? fDenominator->GetZaxis()->GetBinLowEdge(zbin) : 0;
Double_t zup = (nDim > 2) ? fDenominator->GetZaxis()->GetBinLowEdge(zbin+1) : 0;
int bin = fDenominator->GetBin(xbin, ybin, zbin);
Double_t nDen = fDenominator->GetBinContent(bin);
Double_t nNum = fNumerator->GetBinContent(bin);
if (nDen> nmax) nmax = nDen;
if (nDen <= 0.) continue;
npoints++;
Double_t mu = 0;
switch (nDim) {
case 1:
mu = (fAverage) ?
fFunction->Integral(xlow, xup, (Double_t*)0, fEpsilon)
/ (xup-xlow) :
fFunction->Eval(fDenominator->GetBinCenter(bin));
break;
case 2:
{
TF2* f2 = dynamic_cast<TF2*>(fFunction);
mu = (fAverage) ?
f2->Integral(xlow, xup, ylow, yup, fEpsilon)
/ ((xup-xlow)*(yup-ylow)) :
f2->Eval(fDenominator->GetXaxis()->GetBinCenter(xbin),
fDenominator->GetYaxis()->GetBinCenter(ybin));
}
break;
case 3:
{
TF3* f3 = dynamic_cast<TF3*>(fFunction);
mu = (fAverage) ?
f3->Integral(xlow, xup, ylow, yup, zlow, zup, fEpsilon)
/ ((xup-xlow)*(yup-ylow)*(zup-zlow)) :
f3->Eval(fDenominator->GetXaxis()->GetBinCenter(xbin),
fDenominator->GetYaxis()->GetBinCenter(ybin),
fDenominator->GetZaxis()->GetBinCenter(zbin));
}
}
if (nNum != 0.) {
if (mu > 0.)
f -= nNum * TMath::Log(mu*nDen/nNum);
else
f -= nmax * -1E30;
}
if (nDen - nNum != 0.) {
if (1. - mu > 0.)
f -= (nDen - nNum) * TMath::Log((1. - mu)*nDen/(nDen-nNum));
else
f -= nmax * -1E30;
}
}
}
}
fFunction->SetNumberFitPoints(npoints);
fFunction->SetChisquare(2.*f);
}
void BinomialEfficiencyFitterFCN(Int_t& npar, Double_t* gin, Double_t& f,
Double_t* par, Int_t flag)
{
TBinomialEfficiencyFitter* fitter = dynamic_cast<TBinomialEfficiencyFitter*>(TBinomialEfficiencyFitter::GetFitter()->GetObjectFit());
if (!fitter) {
fitter->Error("binomialFCN","Invalid fit object encountered!");
return;
}
fitter->ComputeFCN(npar, gin, f, par, flag);
}
Last change: Mon Sep 22 15:41:18 2008
Last generated: 2008-09-22 15:41
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.