00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #include "TBinomialEfficiencyFitter.h"
00074
00075 #include "TMath.h"
00076 #include "TPluginManager.h"
00077 #include "TROOT.h"
00078 #include "TH1.h"
00079 #include "TF1.h"
00080 #include "TF2.h"
00081 #include "TF3.h"
00082 #include "TVirtualFitter.h"
00083 #include "TEnv.h"
00084
00085 #include <limits>
00086
00087 TVirtualFitter *TBinomialEfficiencyFitter::fgFitter = 0;
00088
00089 const Double_t kDefaultEpsilon = 1E-12;
00090
00091 ClassImp(TBinomialEfficiencyFitter)
00092
00093
00094
00095 TBinomialEfficiencyFitter::TBinomialEfficiencyFitter() {
00096
00097
00098 fNumerator = 0;
00099 fDenominator = 0;
00100 fFunction = 0;
00101 fFitDone = kFALSE;
00102 fAverage = kFALSE;
00103 fRange = kFALSE;
00104 fEpsilon = kDefaultEpsilon;
00105 }
00106
00107
00108 TBinomialEfficiencyFitter::TBinomialEfficiencyFitter(const TH1 *numerator, const TH1 *denominator) {
00109
00110
00111
00112
00113
00114
00115
00116
00117 fEpsilon = kDefaultEpsilon;
00118 fFunction = 0;
00119 Set(numerator,denominator);
00120 }
00121
00122
00123 TBinomialEfficiencyFitter::~TBinomialEfficiencyFitter() {
00124
00125
00126 delete fgFitter; fgFitter = 0;
00127 }
00128
00129
00130 void TBinomialEfficiencyFitter::Set(const TH1 *numerator, const TH1 *denominator)
00131 {
00132
00133
00134 fNumerator = (TH1*)numerator;
00135 fDenominator = (TH1*)denominator;
00136
00137 fFitDone = kFALSE;
00138 fAverage = kFALSE;
00139 fRange = kFALSE;
00140 }
00141
00142
00143 void TBinomialEfficiencyFitter::SetPrecision(Double_t epsilon)
00144 {
00145
00146 fEpsilon = epsilon;
00147 }
00148
00149
00150 TVirtualFitter* TBinomialEfficiencyFitter::GetFitter()
00151 {
00152
00153
00154
00155
00156 return fgFitter;
00157 }
00158
00159
00160 Int_t TBinomialEfficiencyFitter::Fit(TF1 *f1, Option_t* option)
00161 {
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 TString opt = option;
00185 opt.ToUpper();
00186 fAverage = opt.Contains("I");
00187 fRange = opt.Contains("R");
00188 Bool_t verbose = opt.Contains("V");
00189 if (!f1) return -1;
00190 fFunction = (TF1*)f1;
00191 Int_t i, npar;
00192 npar = f1->GetNpar();
00193 if (npar <= 0) {
00194 Error("Fit", "function %s has illegal number of parameters = %d",
00195 f1->GetName(), npar);
00196 return -3;
00197 }
00198
00199
00200 if (!fNumerator || !fDenominator) {
00201 Error("Fit","No numerator or denominator histograms set");
00202 return -5;
00203 }
00204 if (f1->GetNdim() != fNumerator->GetDimension()) {
00205 Error("Fit","function %s dimension, %d, does not match histogram dimension, %d",
00206 f1->GetName(), f1->GetNdim(), fNumerator->GetDimension());
00207 return -4;
00208 }
00209
00210 if (fNumerator->GetNbinsX() != fDenominator->GetNbinsX() ||
00211 (f1->GetNdim() > 1 && fNumerator->GetNbinsY() != fDenominator->GetNbinsY()) ||
00212 (f1->GetNdim() > 2 && fNumerator->GetNbinsZ() != fDenominator->GetNbinsZ())) {
00213 Error("Fit", "numerator and denominator histograms do not have identical numbers of bins");
00214 return -6;
00215 }
00216
00217
00218
00219 Int_t maxpar = npar;
00220 if (!fgFitter) {
00221 TPluginHandler *h;
00222 TString fitterName = TVirtualFitter::GetDefaultFitter();
00223 if (fitterName == "")
00224 fitterName = gEnv->GetValue("Root.Fitter","Minuit");
00225 if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualFitter", fitterName ))) {
00226 if (h->LoadPlugin() == -1)
00227 return 0;
00228 fgFitter = (TVirtualFitter*) h->ExecPlugin(1, maxpar);
00229 }
00230 if (!fgFitter) printf("ERROR fgFitter is NULL\n");
00231 }
00232
00233 fgFitter->SetObjectFit(this);
00234 fgFitter->Clear();
00235 fgFitter->SetFCN(BinomialEfficiencyFitterFCN);
00236 Int_t nfixed = 0;
00237 Double_t al,bl,we,arglist[100];
00238 for (i = 0; i < npar; i++) {
00239 f1->GetParLimits(i,al,bl);
00240 if (al*bl != 0 && al >= bl) {
00241 al = bl = 0;
00242 arglist[nfixed] = i+1;
00243 nfixed++;
00244 }
00245
00246 we = f1->GetParError(i);
00247 if (we <= 0) we = 0.3*TMath::Abs(f1->GetParameter(i));
00248 if (we == 0) we = 0.01;
00249 fgFitter->SetParameter(i, f1->GetParName(i),
00250 f1->GetParameter(i),
00251 we, al,bl);
00252 }
00253 if (nfixed > 0) fgFitter->ExecuteCommand("FIX",arglist,nfixed);
00254
00255 Double_t plist[2];
00256 plist[0] = 0.5;
00257 fgFitter->ExecuteCommand("SET ERRDEF",plist,1);
00258
00259 if (verbose) {
00260 plist[0] = 3;
00261 fgFitter->ExecuteCommand("SET PRINT",plist,1);
00262 }
00263
00264
00265
00266 fFitDone = kTRUE;
00267 plist[0] = TVirtualFitter::GetMaxIterations();
00268 plist[1] = TVirtualFitter::GetPrecision();
00269 Int_t result = fgFitter->ExecuteCommand("MINIMIZE",plist,2);
00270
00271
00272 char parName[50];
00273 Double_t par;
00274 Double_t eplus,eminus,eparab,globcc,werr;
00275 for (i = 0; i < npar; ++i) {
00276 fgFitter->GetParameter(i,parName, par,we,al,bl);
00277 fgFitter->GetErrors(i,eplus,eminus,eparab,globcc);
00278 if (eplus > 0 && eminus < 0) werr = 0.5*(eplus-eminus);
00279 else werr = we;
00280 f1->SetParameter(i,par);
00281 f1->SetParError(i,werr);
00282 }
00283 f1->SetNDF(f1->GetNumberFitPoints()-npar+nfixed);
00284 return result;
00285 }
00286
00287
00288 void TBinomialEfficiencyFitter::ComputeFCN(Int_t& , Double_t* ,
00289 Double_t& f, Double_t* par, Int_t )
00290 {
00291
00292
00293 int nDim = fDenominator->GetDimension();
00294
00295 int xlowbin = fDenominator->GetXaxis()->GetFirst();
00296 int xhighbin = fDenominator->GetXaxis()->GetLast();
00297 int ylowbin = 0, yhighbin = 0, zlowbin = 0, zhighbin = 0;
00298 if (nDim > 1) {
00299 ylowbin = fDenominator->GetYaxis()->GetFirst();
00300 yhighbin = fDenominator->GetYaxis()->GetLast();
00301 if (nDim > 2) {
00302 zlowbin = fDenominator->GetZaxis()->GetFirst();
00303 zhighbin = fDenominator->GetZaxis()->GetLast();
00304 }
00305 }
00306
00307 fFunction->SetParameters(par);
00308
00309 if (fRange) {
00310 double xmin, xmax, ymin, ymax, zmin, zmax;
00311
00312
00313
00314
00315 if (nDim == 1) {
00316 fFunction->GetRange(xmin, xmax);
00317 xlowbin = fDenominator->GetXaxis()->FindBin(xmin);
00318 xhighbin = fDenominator->GetXaxis()->FindBin(xmax);
00319 } else if (nDim == 2) {
00320 fFunction->GetRange(xmin, ymin, xmax, ymax);
00321 xlowbin = fDenominator->GetXaxis()->FindBin(xmin);
00322 xhighbin = fDenominator->GetXaxis()->FindBin(xmax);
00323 ylowbin = fDenominator->GetYaxis()->FindBin(ymin);
00324 yhighbin = fDenominator->GetYaxis()->FindBin(ymax);
00325 } else if (nDim == 3) {
00326 fFunction->GetRange(xmin, ymin, zmin, xmax, ymax, zmax);
00327 xlowbin = fDenominator->GetXaxis()->FindBin(xmin);
00328 xhighbin = fDenominator->GetXaxis()->FindBin(xmax);
00329 ylowbin = fDenominator->GetYaxis()->FindBin(ymin);
00330 yhighbin = fDenominator->GetYaxis()->FindBin(ymax);
00331 zlowbin = fDenominator->GetZaxis()->FindBin(zmin);
00332 zhighbin = fDenominator->GetZaxis()->FindBin(zmax);
00333 }
00334 }
00335
00336
00337
00338
00339 f = 0.;
00340
00341 Int_t npoints = 0;
00342 Double_t nmax = 0;
00343 for (int xbin = xlowbin; xbin <= xhighbin; ++xbin) {
00344
00345
00346 Double_t xlow = fDenominator->GetXaxis()->GetBinLowEdge(xbin);
00347 Double_t xup = fDenominator->GetXaxis()->GetBinLowEdge(xbin+1);
00348
00349 for (int ybin = ylowbin; ybin <= yhighbin; ++ybin) {
00350
00351
00352 Double_t ylow = (nDim > 1) ? fDenominator->GetYaxis()->GetBinLowEdge(ybin) : 0;
00353 Double_t yup = (nDim > 1) ? fDenominator->GetYaxis()->GetBinLowEdge(ybin+1) : 0;
00354
00355 for (int zbin = zlowbin; zbin <= zhighbin; ++zbin) {
00356
00357
00358 Double_t zlow = (nDim > 2) ? fDenominator->GetZaxis()->GetBinLowEdge(zbin) : 0;
00359 Double_t zup = (nDim > 2) ? fDenominator->GetZaxis()->GetBinLowEdge(zbin+1) : 0;
00360
00361 int bin = fDenominator->GetBin(xbin, ybin, zbin);
00362 Double_t nDen = fDenominator->GetBinContent(bin);
00363 Double_t nNum = fNumerator->GetBinContent(bin);
00364
00365
00366
00367 if (nDen> nmax) nmax = nDen;
00368 if (nDen <= 0.) continue;
00369 npoints++;
00370
00371
00372
00373
00374
00375
00376 Double_t mu = 0;
00377 switch (nDim) {
00378 case 1:
00379 mu = (fAverage) ?
00380 fFunction->Integral(xlow, xup, (Double_t*)0, fEpsilon)
00381 / (xup-xlow) :
00382 fFunction->Eval(fDenominator->GetBinCenter(bin));
00383 break;
00384 case 2:
00385 {
00386 mu = (fAverage) ?
00387 fFunction->Integral(xlow, xup, ylow, yup, fEpsilon)
00388 / ((xup-xlow)*(yup-ylow)) :
00389 fFunction->Eval(fDenominator->GetXaxis()->GetBinCenter(xbin),
00390 fDenominator->GetYaxis()->GetBinCenter(ybin));
00391 }
00392 break;
00393 case 3:
00394 {
00395 mu = (fAverage) ?
00396 fFunction->Integral(xlow, xup, ylow, yup, zlow, zup, fEpsilon)
00397 / ((xup-xlow)*(yup-ylow)*(zup-zlow)) :
00398 fFunction->Eval(fDenominator->GetXaxis()->GetBinCenter(xbin),
00399 fDenominator->GetYaxis()->GetBinCenter(ybin),
00400 fDenominator->GetZaxis()->GetBinCenter(zbin));
00401 }
00402 }
00403
00404
00405 if (nNum != 0.) {
00406 if (mu > 0.)
00407 f -= nNum * TMath::Log(mu*nDen/nNum);
00408 else
00409 f -= nmax * -1E30;
00410 }
00411 if (nDen - nNum != 0.) {
00412 if (1. - mu > 0.)
00413 f -= (nDen - nNum) * TMath::Log((1. - mu)*nDen/(nDen-nNum));
00414 else
00415 f -= nmax * -1E30;
00416 }
00417 }
00418 }
00419 }
00420
00421 fFunction->SetNumberFitPoints(npoints);
00422 fFunction->SetChisquare(2.*f);
00423 }
00424
00425
00426 void BinomialEfficiencyFitterFCN(Int_t& npar, Double_t* gin, Double_t& f,
00427 Double_t* par, Int_t flag)
00428 {
00429
00430
00431
00432 TBinomialEfficiencyFitter* fitter = dynamic_cast<TBinomialEfficiencyFitter*>(TBinomialEfficiencyFitter::GetFitter()->GetObjectFit());
00433 if (!fitter) {
00434 Error("binomialFCN","Invalid fit object encountered!");
00435 return;
00436 }
00437 fitter->ComputeFCN(npar, gin, f, par, flag);
00438 }