ROOT  6.06/09
Reference Guide
TFractionFitter.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Frank Filthaut F.Filthaut@science.ru.nl 20/05/2002
3 // with additions by Bram Wijngaarden <dwijngaa@hef.kun.nl>
4 
5 /** \class TFractionFitter
6 Fits MC fractions to data histogram. A la HMCMLL, see R. Barlow and C. Beeston,
7 Comp. Phys. Comm. 77 (1993) 219-228, and http://www.hep.man.ac.uk/~roger/hfrac.f
8 
9 The virtue of this fit is that it takes into account both data and Monte Carlo
10 statistical uncertainties. The way in which this is done is through a standard
11 likelihood fit using Poisson statistics; however, the template (MC) predictions
12 are also varied within statistics, leading to additional contributions to the
13 overall likelihood. This leads to many more fit parameters (one per bin per
14 template), but the minimisation with respect to these additional parameters is
15 done analytically rather than introducing them as formal fit parameters. Some
16 special care needs to be taken in the case of bins with zero content. For more
17 details please see the original publication cited above.
18 
19 An example application of this fit is given below. For a TH1* histogram
20 ("data") fitted as the sum of three Monte Carlo sources ("mc"):
21 
22 ~~~{.cpp}
23 {
24  TH1F *data; //data histogram
25  TH1F *mc0; // first MC histogram
26  TH1F *mc1; // second MC histogram
27  TH1F *mc2; // third MC histogram
28  .... // retrieve histograms
29  TObjArray *mc = new TObjArray(3); // MC histograms are put in this array
30  mc->Add(mc0);
31  mc->Add(mc1);
32  mc->Add(mc2);
33  TFractionFitter* fit = new TFractionFitter(data, mc); // initialise
34  fit->Constrain(1,0.0,1.0); // constrain fraction 1 to be between 0 and 1
35  fit->SetRangeX(1,15); // use only the first 15 bins in the fit
36  Int_t status = fit->Fit(); // perform the fit
37  std::cout << "fit status: " << status << std::endl;
38  if (status == 0) { // check on fit status
39  TH1F* result = (TH1F*) fit->GetPlot();
40  data->Draw("Ep");
41  result->Draw("same");
42  }
43 }
44 ~~~
45 
46 ## Assumptions
47 A few assumptions need to be made for the fit procedure to be carried out:
48  1 The total number of events in each template is not too small
49  (so that its Poisson uncertainty can be neglected).
50  2 The number of events in each bin is much smaller than the total
51  number of events in each template (so that multinomial
52  uncertainties can be replaced with Poisson uncertainties).
53 
54 Biased fit uncertainties may result if these conditions are not fulfilled
55 (see e.g. arXiv:0803.2711).
56 
57 ## Instantiation
58 A fit object is instantiated through
59  TFractionFitter* fit = new TFractionFitter(data, mc);
60 A number of basic checks (intended to ensure that the template histograms
61 represent the same "kind" of distribution as the data one) are carried out.
62 The TVirtualFitter object is then addressed and all fit parameters (the
63 template fractions) declared (initially unbounded).
64 
65 ## Applying constraints
66 Fit parameters can be constrained through
67 
68  fit->Constrain(parameter #, lower bound, upper bound);
69 
70 Setting lower bound = upper bound = 0 removes the constraint (a la Minuit);
71 however, a function
72 
73  fit->Unconstrain(parameter #)
74 
75 is also provided to simplify this.
76 
77 ## Setting parameter values
78 The function
79 
80  TVirtualFitter* vFit = fit->GetFitter();
81 
82 is provided for direct access to the TVirtualFitter object. This allows to
83 set and fix parameter values, and set step sizes directly.
84 
85 ## Restricting the fit range
86 The fit range can be restricted through
87 
88  fit->SetRangeX(first bin #, last bin #);
89 and freed using
90 
91  fit->ReleaseRangeX();
92 For 2D histograms the Y range can be similarly restricted using
93 
94  fit->SetRangeY(first bin #, last bin #);
95  fit->ReleaseRangeY();
96 and for 3D histograms also
97 
98  fit->SetRangeZ(first bin #, last bin #);
99  fit->ReleaseRangeZ();
100 It is also possible to exclude individual bins from the fit through
101 
102  fit->ExcludeBin(bin #);
103 where the given bin number is assumed to follow the TH1::GetBin() numbering.
104 Any bins excluded in this way can be included again using the corresponding
105 
106  fit->IncludeBin(bin #);
107 
108 ## Weights histograms
109 Weights histograms (for a motivation see the above publication) can be specified
110 for the individual MC sources through
111 
112  fit->SetWeight(parameter #, pointer to weights histogram);
113 and unset by specifying a null pointer.
114 
115 ## Obtaining fit results
116 The fit is carried out through
117 
118  Int_t status = fit->Fit();
119 where status is the code returned from the "MINIMIZE" command. For fits
120 that converged, parameter values and errors can be obtained through
121 
122  fit->GetResult(parameter #, value, error);
123 and the histogram corresponding to the total Monte Carlo prediction (which
124 is not the same as a simple weighted sum of the input Monte Carlo distributions)
125 can be obtained by
126 
127  TH1* result = fit->GetPlot();
128 ## Using different histograms
129 It is possible to change the histogram being fitted through
130 
131  fit->SetData(TH1* data);
132 and to change the template histogram for a given parameter number through
133 
134  fit->SetMC(parameter #, TH1* MC);
135 This can speed up code in case of multiple data or template histograms;
136 however, it should be done with care as any settings are taken over from
137 the previous fit. In addition, neither the dimensionality nor the numbers of
138 bins of the histograms should change (in that case it is better to instantiate
139 a new TFractionFitter object).
140 
141 ## Errors
142 Any serious inconsistency results in an error.
143 */
144 
145 #include "Riostream.h"
146 #include "TH1.h"
147 #include "TMath.h"
148 #include "TClass.h"
149 
150 #include "Fit/Fitter.h"
151 #include "TFitResult.h"
152 #include "Math/Functor.h"
153 #include "TFractionFitter.h"
154 
156 
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// TFractionFitter default constructor.
160 
162 fFitDone(kFALSE),
163 fLowLimitX(0), fHighLimitX(0),
164 fLowLimitY(0), fHighLimitY(0),
165 fLowLimitZ(0), fHighLimitZ(0),
166 fData(0), fIntegralData(0),
167 fPlot(0)
168 {
169  fFractionFitter = 0;
170  fIntegralMCs = 0;
171  fFractions = 0;
172 
173  fNpfits = 0;
174  fNDF = 0;
175  fChisquare = 0;
176  fNpar = 0;
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// TFractionFitter constructor. Does a complete initialisation (including
181 /// consistency checks, default fit range as the whole histogram but without
182 /// under- and overflows, and declaration of the fit parameters). Note that
183 /// the histograms are not copied, only references are used.
184 /// \param[in] data histogram to be fitted
185 /// \param[in] MCs array of TH1* corresponding template distributions
186 /// \param[in] option can be used to control the print level of the minimization algorithm
187 /// - option = "Q" : quite - no message is printed
188 /// - option = "V" : verbose - max print out
189 /// - option = "" : default: print initial fraction values and result
190 
192 fFitDone(kFALSE), fChisquare(0), fPlot(0) {
193  fData = data;
194  // Default: include all of the histogram (but without under- and overflows)
195  fLowLimitX = 1;
197  if (fData->GetDimension() > 1) {
198  fLowLimitY = 1;
200  if (fData->GetDimension() > 2) {
201  fLowLimitZ = 1;
203  }
204  }
205  fNpar = MCs->GetEntries();
206  Int_t par;
207  for (par = 0; par < fNpar; ++par) {
208  fMCs.Add(MCs->At(par));
209  // Histogram containing template prediction
210  TString s = Form("Prediction for MC sample %i",par);
211  TH1* pred = (TH1*) ((TH1*)MCs->At(par))->Clone(s);
212  pred->SetTitle(s);
213  fAji.Add(pred);
214  }
215  fIntegralMCs = new Double_t[fNpar];
216  fFractions = new Double_t[fNpar];
217 
219  fWeights.Expand(fNpar);
220 
222 
223  // set print level
224  TString opt(option);
225  opt.ToUpper();
226  if (opt.Contains("Q") ) {
228  }
229  else if (opt.Contains("V") ) {
231  }
232  else
234 
235  Double_t defaultFraction = 1.0/((Double_t)fNpar);
236  Double_t defaultStep = 0.01;
237  // set the parameters
238  std::vector<ROOT::Fit::ParameterSettings> & parameters = fFractionFitter->Config().ParamsSettings();
239  parameters.reserve(fNpar);
240  for (par = 0; par < fNpar; ++par) {
241  TString name("frac"); name += par;
242  parameters.push_back(ROOT::Fit::ParameterSettings(name.Data(), defaultFraction, defaultStep) );
243  }
244 
245  if (fFractionFitter->Config().MinimizerOptions().ErrorDef() == 1.0 )
247 
248 }
249 
250 ////////////////////////////////////////////////////////////////////////////////
251 /// TFractionFitter default destructor
252 
254  if (fFractionFitter) delete fFractionFitter;
255  delete[] fIntegralMCs;
256  delete[] fFractions;
257  if (fPlot) delete fPlot;
258  fAji.Delete();
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Change the histogram to be fitted to. Notes:
263 /// - Parameter constraints and settings are retained from a possible previous fit.
264 /// - Modifying the dimension or number of bins results in an error (in this case
265 /// rather instantiate a new TFractionFitter object)
266 
268  fData = data;
269  fFitDone = kFALSE;
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 /// Change the histogram for template number <parm>. Notes:
275 /// - Parameter constraints and settings are retained from a possible previous fit.
276 /// - Modifying the dimension or number of bins results in an error (in this case
277 /// rather instantiate a new TFractionFitter object)
278 
280  CheckParNo(parm);
281  fMCs.RemoveAt(parm);
282  fMCs.AddAt(MC,parm);
283  fFitDone = kFALSE;
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Set bin by bin weights for template number <parm> (the parameter numbering
289 /// follows that of the input template vector).
290 /// Weights can be "unset" by passing a null pointer.
291 /// Consistency of the weights histogram with the data histogram is checked at
292 /// this point, and an error in case of problems.
293 
294 void TFractionFitter::SetWeight(Int_t parm, TH1* weight) {
295  CheckParNo(parm);
296  if (fWeights[parm]) {
297  fWeights.RemoveAt(parm);
298  }
299  if (weight) {
300  if (weight->GetNbinsX() != fData->GetNbinsX() ||
301  (fData->GetDimension() > 1 && weight->GetNbinsY() != fData->GetNbinsY()) ||
302  (fData->GetDimension() > 2 && weight->GetNbinsZ() != fData->GetNbinsZ())) {
303  Error("SetWeight","Inconsistent weights histogram for source %d", parm);
304  return;
305  }
306  TString ts = "weight hist: "; ts += weight->GetName();
307  fWeights.AddAt(weight,parm);
308  }
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Give direct access to the underlying fitter class. This can be
313 /// used e.g. to modify parameter values or step sizes.
314 
316  return fFractionFitter;
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Function for internal use, checking parameter validity
321 /// An invalid parameter results in an error.
322 
324  if (parm < 0 || parm > fNpar) {
325  Error("CheckParNo","Invalid parameter number %d",parm);
326  }
327 }
328 
329 ////////////////////////////////////////////////////////////////////////////////
330 /// Set the X range of the histogram to be used in the fit.
331 /// Use ReleaseRangeX() to go back to fitting the full histogram.
332 /// The consistency check ensures that no empty fit range occurs (and also
333 /// recomputes the bin content integrals).
334 /// \param[in] low lower X bin number
335 /// \param[in] high upper X bin number
336 
338  fLowLimitX = (low > 0 ) ? low : 1;
339  fHighLimitX = ( high > 0 && high <= fData->GetNbinsX()) ? high : fData->GetNbinsX();
341 }
342 
343 ////////////////////////////////////////////////////////////////////////////////
344 /// Release restrictions on the X range of the histogram to be used in the fit.
345 
347  fLowLimitX = 1;
350 }
351 
352 ////////////////////////////////////////////////////////////////////////////////
353 /// Set the Y range of the histogram to be used in the fit (2D or 3D histograms only).
354 /// Use ReleaseRangeY() to go back to fitting the full histogram.
355 /// The consistency check ensures that no empty fit range occurs (and also
356 /// recomputes the bin content integrals).
357 /// \param[in] low lower X bin number
358 /// \param[in] high upper X bin number
359 
361  if (fData->GetDimension() < 2) {
362  Error("SetRangeY","Y range cannot be set for 1D histogram");
363  return;
364  }
365 
366  fLowLimitY = (low > 0) ? low : 1;
367  fHighLimitY = (high > 0 && high <= fData->GetNbinsY()) ? high : fData->GetNbinsY();
369 }
370 
371 ////////////////////////////////////////////////////////////////////////////////
372 /// Release restrictions on the Y range of the histogram to be used in the fit.
373 
375  fLowLimitY = 1;
378 }
379 
380 
381 ////////////////////////////////////////////////////////////////////////////////
382 /// Set the Z range of the histogram to be used in the fit (3D histograms only).
383 /// Use ReleaseRangeY() to go back to fitting the full histogram.
384 /// The consistency check ensures that no empty fit range occurs (and also
385 /// recomputes the bin content integrals).
386 /// \param[in] low lower X bin number
387 /// \param[in] high upper X bin number
388 
390  if (fData->GetDimension() < 3) {
391  Error("SetRangeZ","Z range cannot be set for 1D or 2D histogram");
392  return;
393  }
394 
395 
396  fLowLimitZ = (low > 0) ? low : 1;
397  fHighLimitZ = (high > 0 && high <= fData->GetNbinsZ()) ? high : fData->GetNbinsZ();
399 }
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// Release restrictions on the Z range of the histogram to be used in the fit.
403 
405  fLowLimitZ = 1;
408 }
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// Exclude the given bin from the fit. The bin numbering to be used is that
412 /// of TH1::GetBin().
413 
415  int excluded = fExcludedBins.size();
416  for (int b = 0; b < excluded; ++b) {
417  if (fExcludedBins[b] == bin) {
418  Error("ExcludeBin", "bin %d already excluded", bin);
419  return;
420  }
421  }
422  fExcludedBins.push_back(bin);
423  // This call serves to properly (re)determine the number of degrees of freeom
425 }
426 
427 ////////////////////////////////////////////////////////////////////////////////
428 /// Include the given bin in the fit, if it was excluded before using ExcludeBin().
429 /// The bin numbering to be used is that of TH1::GetBin().
430 
432  for (std::vector<Int_t>::iterator it = fExcludedBins.begin();
433  it != fExcludedBins.end(); ++it) {
434  if (*it == bin) {
435  fExcludedBins.erase(it);
436  // This call serves to properly (re)determine the number of degrees of freeom
438  return;
439  }
440  }
441  Error("IncludeBin", "bin %d was not excluded", bin);
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 /// Function for internal use, checking whether the given bin is
446 /// excluded from the fit or not.
447 
449  for (unsigned int b = 0; b < fExcludedBins.size(); ++b)
450  if (fExcludedBins[b] == bin) return true;
451  return false;
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Constrain the values of parameter number <parm> (the parameter numbering
456 /// follows that of the input template vector).
457 /// Use UnConstrain() to remove this constraint.
458 
460  CheckParNo(parm);
461  assert( parm >= 0 && parm < (int) fFractionFitter->Config().ParamsSettings().size() );
462  fFractionFitter->Config().ParSettings(parm).SetLimits(low,high);
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 /// Remove the constraints on the possible values of parameter <parm>.
467 
469  CheckParNo(parm);
471 }
472 
473 ////////////////////////////////////////////////////////////////////////////////
474 /// Function used internally to check the consistency between the
475 /// various histograms. Checks are performed on nonexistent or empty
476 /// histograms, the precise histogram class, and the number of bins.
477 /// In addition, integrals over the "allowed" bin ranges are computed.
478 /// Any inconsistency results in a error.
479 
481  if (! fData) {
482  Error("CheckConsistency","Nonexistent data histogram");
483  return;
484  }
485  Int_t minX, maxX, minY, maxY, minZ, maxZ;
486  Int_t x,y,z,par;
487  GetRanges(minX, maxX, minY, maxY, minZ, maxZ);
488  fIntegralData = 0;
489  fNpfits = 0;
490  for (z = minZ; z <= maxZ; ++z) {
491  for (y = minY; y <= maxY; ++y) {
492  for (x = minX; x <= maxX; ++x) {
493  if (IsExcluded(fData->GetBin(x, y, z))) continue;
494  fNpfits++;
495  fIntegralData += fData->GetBinContent(x, y, z);
496  }
497  }
498  }
499  if (fIntegralData <= 0) {
500  Error("CheckConsistency","Empty data histogram");
501  return;
502  }
503  TClass* cl = fData->Class();
504 
505  fNDF = fNpfits - fNpar;
506 
507  if (fNpar < 2) {
508  Error("CheckConsistency","Need at least two MC histograms");
509  return;
510  }
511 
512  for (par = 0; par < fNpar; ++par) {
513  TH1 *h = (TH1*)fMCs.At(par);
514  if (! h) {
515  Error("CheckConsistency","Nonexistent MC histogram for source #%d",par);
516  return;
517  }
518  if ((! h->Class()->InheritsFrom(cl)) || h->GetNbinsX() != fData->GetNbinsX() ||
519  (fData->GetDimension() > 1 && h->GetNbinsY() != fData->GetNbinsY()) ||
520  (fData->GetDimension() > 2 && h->GetNbinsZ() != fData->GetNbinsZ())) {
521  Error("CheckConsistency","Histogram inconsistency for source #%d",par);
522  return;
523  }
524  fIntegralMCs[par] = 0;
525  for (z = minZ; z <= maxZ; ++z) {
526  for (y = minY; y <= maxY; ++y) {
527  for (x = minX; x <= maxX; ++x) {
528  Int_t bin = fData->GetBin(x, y, z);
529  if (IsExcluded(bin)) continue;
530  Double_t MCEvents = h->GetBinContent(bin);
531  if (MCEvents < 0) {
532  Error("CheckConsistency", "Number of MC events (bin = %d, par = %d) cannot be negative: "
533  " their distribution is binomial (see paper)", bin, par);
534  }
535  fIntegralMCs[par] += MCEvents;
536  }
537  }
538  }
539  if (fIntegralMCs[par] <= 0) {
540  Error("CheckConsistency","Empty MC histogram #%d",par);
541  }
542  }
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 /// Perform the fit with the default UP value.
547 /// The value returned is the minimisation status.
548 
550 
551  // remove any existing output histogram
552  if (fPlot) {
553  delete fPlot; fPlot = 0;
554  }
555 
556  // Make sure the correct likelihood computation is used
558  fFractionFitter->SetFCN(static_cast<ROOT::Math::IMultiGenFunction&>(fcnFunction));
559 
560  // fit
562  if (!status) Warning("Fit","Abnormal termination of minimization.");
563 
564  fFitDone = kTRUE;
565 
566  // determine goodness of fit
568 
569  // create a new result class
571  TString name = TString::Format("TFractionFitter_result_of_%s",fData->GetName() );
572  fr->SetName(name); fr->SetTitle(name);
573  return TFitResultPtr(fr);
574 }
575 
576 ////////////////////////////////////////////////////////////////////////////////
577 /// Set UP to the given value (see class TMinuit), and perform a MINOS minimisation.
578 
580  if (! fFitDone) {
581  Error("ErrorAnalysis","Fit not yet performed");
582  return;
583  }
584 
585 
586  Double_t up = UP > 0 ? UP : 0.5;
589  if (!status) {
590  Error("ErrorAnalysis","Error return from MINOS: %d",fFractionFitter->Result().Status());
591  }
592 }
593 
594 ////////////////////////////////////////////////////////////////////////////////
595 /// Obtain the fit result for parameter <parm> (the parameter numbering
596 /// follows that of the input template vector).
597 
599  CheckParNo(parm);
600  if (! fFitDone) {
601  Error("GetResult","Fit not yet performed");
602  return;
603  }
604  value = fFractionFitter->Result().Parameter(parm);
605  error = fFractionFitter->Result().Error(parm);
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////////
609 /// Return the "template prediction" corresponding to the fit result (this is not
610 /// the same as the weighted sum of template distributions, as template statistical
611 /// uncertainties are taken into account).
612 /// Note that the name of this histogram will simply be the same as that of the
613 /// "data" histogram, prefixed with the string "Fraction fit to hist: ".
614 /// Note also that the histogram is managed by the TFractionFitter class, so the returned pointer will be invalid if
615 /// the class is deleted
616 
618  if (! fFitDone) {
619  Error("GetPlot","Fit not yet performed");
620  return 0;
621  }
622  if (! fPlot) {
623  Double_t f = 0;
624  const Double_t * par = fFractionFitter->Result().GetParams();
625  assert(par);
626  ComputeFCN(f, par, 3);
627  }
628  return fPlot;
629 }
630 
631 ////////////////////////////////////////////////////////////////////////////////
632 /// Used internally to obtain the bin ranges according to the dimensionality of
633 /// the histogram and the limits set by hand.
634 
635 void TFractionFitter::GetRanges(Int_t& minX, Int_t& maxX, Int_t& minY, Int_t& maxY,
636  Int_t& minZ, Int_t& maxZ) const {
637  if (fData->GetDimension() < 2) {
638  minY = maxY = minZ = maxZ = 0;
639  minX = fLowLimitX;
640  maxX = fHighLimitX;
641  } else if (fData->GetDimension() < 3) {
642  minZ = maxZ = 0;
643  minX = fLowLimitX;
644  maxX = fHighLimitX;
645  minY = fLowLimitY;
646  maxY = fHighLimitY;
647  } else {
648  minX = fLowLimitX;
649  maxX = fHighLimitX;
650  minY = fLowLimitY;
651  maxY = fHighLimitY;
652  minZ = fLowLimitZ;
653  maxZ = fHighLimitZ;
654  }
655 }
656 
657 ////////////////////////////////////////////////////////////////////////////////
658 /// Used internally to compute the likelihood value.
659 
661 {
662  // normalise the fit parameters
663  Int_t bin, mc;
664  Int_t minX, maxX, minY, maxY, minZ, maxZ;
665  Int_t x,y,z;
666  GetRanges(minX, maxX, minY, maxY, minZ, maxZ);
667  for (mc = 0; mc < fNpar; ++mc) {
668  Double_t tot;
669  TH1 *h = (TH1*)fMCs[mc];
670  TH1 *hw = (TH1*)fWeights[mc];
671  if (hw) {
672  tot = 0;
673  for (z = minZ; z <= maxZ; ++z) {
674  for (y = minY; y <= maxY; ++y) {
675  for (x = minX; x <= maxX; ++x) {
676  if (IsExcluded(fData->GetBin(x, y, z))) continue;
677  Double_t weight = hw->GetBinContent(x, y, z);
678  if (weight <= 0) {
679  Error("ComputeFCN","Invalid weight encountered for MC source %d",mc);
680  return;
681  }
682  tot += weight * h->GetBinContent(x, y, z);
683  }
684  }
685  }
686  } else tot = fIntegralMCs[mc];
687  fFractions[mc] = xx[mc] * fIntegralData / tot;
688  }
689 
690  if (flag == 3) {
691  TString ts = "Fraction fit to hist: "; ts += fData->GetName();
692  fPlot = (TH1*) fData->Clone(ts.Data());
693  fPlot->Reset();
694  }
695  // likelihood computation
696  Double_t result = 0;
697  for (z = minZ; z <= maxZ; ++z) {
698  for (y = minY; y <= maxY; ++y) {
699  for (x = minX; x <= maxX; ++x) {
700  bin = fData->GetBin(x, y, z);
701  if (IsExcluded(bin)) continue;
702 
703  // Solve for the "predictions"
704  int k0 = 0;
705  Double_t ti = 0.0; Double_t aki = 0.0;
706  FindPrediction(bin, ti, k0, aki);
707 
708  Double_t prediction = 0;
709  for (mc = 0; mc < fNpar; ++mc) {
710  TH1 *h = (TH1*)fMCs[mc];
711  TH1 *hw = (TH1*)fWeights[mc];
712  Double_t binPrediction;
713  Double_t binContent = h->GetBinContent(bin);
714  Double_t weight = hw ? hw->GetBinContent(bin) : 1;
715  if (k0 >= 0 && fFractions[mc] == fFractions[k0]) {
716  binPrediction = aki;
717  } else {
718  binPrediction = binContent > 0 ? binContent / (1+weight*fFractions[mc]*ti) : 0;
719  }
720 
721  prediction += fFractions[mc]*weight*binPrediction;
722  result -= binPrediction;
723  if (binContent > 0 && binPrediction > 0)
724  result += binContent*TMath::Log(binPrediction);
725 
726  if (flag == 3) {
727  ((TH1*)fAji.At(mc))->SetBinContent(bin, binPrediction);
728  }
729  }
730 
731  if (flag == 3) {
732  fPlot->SetBinContent(bin, prediction);
733  }
734 
735  result -= prediction;
736  Double_t found = fData->GetBinContent(bin);
737  if (found > 0 && prediction > 0)
738  result += found*TMath::Log(prediction);
739  }
740  }
741  }
742 
743  f = -result;
744 }
745 
746 ////////////////////////////////////////////////////////////////////////////////
747 /// Function used internally to obtain the template prediction in the individual bins
748 /// 'bin' <=> 'i' (paper)
749 /// 'par' <=> 'j' (paper)
750 
751 void TFractionFitter::FindPrediction(int bin, Double_t &t_i, int& k_0, Double_t &A_ki) const {
752  std::vector<Double_t> wgtFrac(fNpar); // weighted fractions (strengths of the sources)
753  std::vector<Double_t> a_ji(fNpar); // number of observed MC events for bin 'i' and par (source) 'j'
754  Double_t d_i = fData->GetBinContent(bin); // number of events in the real data for bin 'i'
755 
756  // Cache the weighted fractions and the number of observed MC events
757  // Sanity check: none of the fractions should be == 0
758  for (Int_t par = 0; par < fNpar; ++par) {
759  a_ji[par] = ((TH1*)fMCs.At(par))->GetBinContent(bin);
760  TH1* hw = (TH1*)fWeights.At(par);
761  wgtFrac[par] = hw ? hw->GetBinContent(bin) * fFractions[par] : fFractions[par];
762  if (wgtFrac[par] == 0) {
763  Error("FindPrediction", "Fraction[%d] = 0!", par);
764  return;
765  }
766  }
767 
768  // Case data = 0
769  if (TMath::Nint(d_i) == 0) {
770  t_i = 1;
771  k_0 = -1;
772  A_ki = 0;
773  return;
774  }
775 
776  // Case one or more of the MC bin contents == 0 -> find largest fraction
777  // k_0 stores the source index of the largest fraction
778  k_0 = 0;
779  Double_t maxWgtFrac = wgtFrac[0];
780  for (Int_t par = 1; par < fNpar; ++par) {
781  if (wgtFrac[par] > maxWgtFrac) {
782  k_0 = par;
783  maxWgtFrac = wgtFrac[par];
784  }
785  }
786  Double_t t_min = -1 / maxWgtFrac; // t_i cannot be smaller than this value (see paper, par 5)
787 
788  // Determine if there are more sources which have the same maximum contribution (fraction)
789  Int_t nMax = 1; Double_t contentsMax = a_ji[k_0];
790  for (Int_t par = 0; par < fNpar; ++par) {
791  if (par == k_0) continue;
792  if (wgtFrac[par] == maxWgtFrac) {
793  nMax++;
794  contentsMax += a_ji[par];
795  }
796  }
797 
798  // special action if there is a zero in the number of entries for the MC source with
799  // the largest strength (fraction) -> See Paper, Paragraph 5
800  if (contentsMax == 0) {
801  A_ki = d_i / (1.0 + maxWgtFrac);
802  for (Int_t par = 0; par < fNpar; ++par) {
803  if (par == k_0 || wgtFrac[par] == maxWgtFrac) continue;
804  A_ki -= a_ji[par] * wgtFrac[par] / (maxWgtFrac - wgtFrac[par]);
805  }
806  if (A_ki > 0) {
807  A_ki /= nMax;
808  t_i = t_min;
809  return;
810  }
811  }
812  k_0 = -1;
813 
814  // Case of nonzero histogram contents: solve for t_i using Newton's method
815  // The equation that needs to be solved:
816  // func(t_i) = \sum\limits_j{\frac{ p_j a_{ji} }{1 + p_j t_i}} - \frac{d_i}{1 - t_i} = 0
817  t_i = 0; Double_t step = 0.2;
818  Int_t maxIter = 100000; // maximum number of iterations
819  for(Int_t i = 0; i < maxIter; ++i) {
820  if (t_i >= 1 || t_i < t_min) {
821  step /= 10;
822  t_i = 0;
823  }
824  Double_t func = - d_i / (1.0 - t_i);
825  Double_t deriv = func / (1.0 - t_i);
826  for (Int_t par = 0; par < fNpar; ++par) {
827  Double_t r = 1.0 / (t_i + 1.0 / wgtFrac[par]);
828  func += a_ji[par] * r;
829  deriv -= a_ji[par] * r * r;
830  }
831  if (TMath::Abs(func) < 1e-12) return; // solution found
832  Double_t delta = - func / deriv; // update delta
833  if (TMath::Abs(delta) > step)
834  delta = (delta > 0) ? step : -step; // correct delta if it becomes too large
835  t_i += delta;
836  if (TMath::Abs(delta) < 1e-13) return; // solution found
837  } // the loop breaks when the solution is found, or when the maximum number of iterations is exhausted
838 
839  Warning("FindPrediction", "Did not find solution for t_i in %d iterations", maxIter);
840 
841  return;
842 }
843 
844 #ifdef OLD
845 ////////////////////////////////////////////////////////////////////////////////
846 /// Function called by the minimisation package. The actual functionality is passed
847 /// on to the TFractionFitter::ComputeFCN member function.
848 
849 void TFractionFitFCN(Int_t& npar, Double_t* gin, Double_t& f, Double_t* par, Int_t flag) {
850  TFractionFitter* fitter = dynamic_cast<TFractionFitter*>(fFractionFitter->GetObjectFit());
851  if (!fitter) {
852  Error("TFractionFitFCN","Invalid fit object encountered!");
853  return;
854  }
855  fitter->ComputeFCN(npar, gin, f, par, flag);
856 }
857 #endif
858 
859 ////////////////////////////////////////////////////////////////////////////////
860 /// Return the likelihood ratio Chi-squared (chi2) for the fit.
861 /// The value is computed when the fit is executed successfully.
862 /// Chi2 calculation is based on the "likelihood ratio" lambda,
863 /// lambda = L(y;n) / L(m;n),
864 /// where L(y;n) is the likelihood of the fit result <y> describing the data <n>
865 /// and L(m;n) is the likelihood of an unknown "true" underlying distribution
866 /// <m> describing the data <n>. Since <m> is unknown, the data distribution is
867 /// used instead,
868 /// lambda = L(y;n) / L(n;n).
869 /// Note that this ratio is 1 if the fit is perfect. The chi2 value is then
870 /// computed according to
871 /// chi2 = -2*ln(lambda).
872 /// This parameter can be shown to follow a Chi-square distribution. See for
873 /// example S. Baker and R. Cousins, "Clarification of the use of chi-square
874 /// and likelihood functions in fits to histograms", Nucl. Instr. Meth. A221,
875 /// pp. 437-442 (1984)
876 
878 {
879  return fChisquare;
880 }
881 
882 ////////////////////////////////////////////////////////////////////////////////
883 /// return the number of degrees of freedom in the fit
884 /// the fNDF parameter has been previously computed during a fit.
885 /// The number of degrees of freedom corresponds to the number of points
886 /// used in the fit minus the number of templates.
887 
889 {
890  if (fNDF == 0) return fNpfits-fNpar;
891  return fNDF;
892 }
893 
894 ////////////////////////////////////////////////////////////////////////////////
895 /// return the fit probability
896 
898 {
899  Int_t ndf = fNpfits - fNpar;
900  if (ndf <= 0) return 0;
901  return TMath::Prob(fChisquare,ndf);
902 }
903 
904 ////////////////////////////////////////////////////////////////////////////////
905 /// Method used internally to compute the likelihood ratio chi2
906 /// See the function GetChisquare() for details
907 
909 {
910  if ( !fFitDone ) {
911  Error("ComputeChisquareLambda","Fit not yet (successfully) performed");
912  fChisquare = 0;
913  return;
914  }
915 
916  // fPlot must be initialized and filled. Leave this to the GetPlot() method.
917  if (! fPlot)
918  GetPlot();
919 
920  Int_t minX, maxX, minY, maxY, minZ, maxZ;
921  GetRanges(minX, maxX, minY, maxY, minZ, maxZ);
922 
923  Double_t logLyn = 0; // likelihood of prediction
924  Double_t logLmn = 0; // likelihood of data ("true" distribution)
925  for(Int_t x = minX; x <= maxX; x++) {
926  for(Int_t y = minY; y <= maxY; y++) {
927  for(Int_t z = minZ; z <= maxZ; z++) {
928  if (IsExcluded(fData->GetBin(x, y, z))) continue;
929  Double_t di = fData->GetBinContent(x, y, z);
930  Double_t fi = fPlot->GetBinContent(x, y, z);
931  if(fi != 0) logLyn += di * TMath::Log(fi) - fi;
932  if(di != 0) logLmn += di * TMath::Log(di) - di;
933  for(Int_t j = 0; j < fNpar; j++) {
934  Double_t aji = ((TH1*)fMCs.At(j))->GetBinContent(x, y, z);
935  Double_t bji = ((TH1*)fAji.At(j))->GetBinContent(x, y, z);
936  if(bji != 0) logLyn += aji * TMath::Log(bji) - bji;
937  if(aji != 0) logLmn += aji * TMath::Log(aji) - aji;
938  }
939  }
940  }
941  }
942 
943  fChisquare = -2*logLyn + 2*logLmn;
944 
945  return;
946 }
947 
948 ////////////////////////////////////////////////////////////////////////////////
949 /// Return the adjusted MC template (Aji) for template (parm).
950 /// Note that the (Aji) times fractions only sum to the total prediction
951 /// of the fit if all weights are 1.
952 /// Note also that the histogram is managed by the TFractionFitter class, so the returned pointer will be invalid if
953 /// the class is deleted
954 
956 {
957  CheckParNo(parm);
958  if ( !fFitDone ) {
959  Error("GetMCPrediction","Fit not yet performed");
960  return 0;
961  }
962  return (TH1*) fAji.At(parm);
963 }
const FitConfig & Config() const
access to the fit configuration (const method)
Definition: Fitter.h:382
Double_t EvaluateFCN(const Double_t *par)
void GetResult(Int_t parm, Double_t &value, Double_t &error) const
Obtain the fit result for parameter (the parameter numbering follows that of the input templat...
double par[1]
Definition: unuranDistr.cxx:38
virtual ~TFractionFitter()
TFractionFitter default destructor.
void RemoveLimits()
remove all limit
void Constrain(Int_t parm, Double_t low, Double_t high)
Constrain the values of parameter number (the parameter numbering follows that of the input te...
Double_t fIntegralData
An array of TObjects.
Definition: TObjArray.h:39
void FindPrediction(int bin, double &t_i, int &k_0, double &A_ki) const
Function used internally to obtain the template prediction in the individual bins 'bin' <=> 'i' (pape...
void SetPrintLevel(int level)
set print level
void ReleaseRangeX()
Release restrictions on the X range of the histogram to be used in the fit.
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
Double_t Log(Double_t x)
Definition: TMath.h:526
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
bool CalculateMinosErrors()
perform an error analysis on the result using MINOS To be called only after fitting and when a minimi...
Definition: Fitter.cxx:594
const char Option_t
Definition: RtypesCore.h:62
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:328
Documentation for class Functor class.
Definition: Functor.h:394
#define assert(cond)
Definition: unittest.h:542
Class, describing value, limits and step size of the parameters Provides functionality also to set/re...
virtual Int_t GetDimension() const
Definition: TH1.h:283
virtual void SetName(const char *name)
Change (i.e.
Definition: TNamed.cxx:128
TH1 * h
Definition: legend2.C:5
std::vector< Int_t > fExcludedBins
bool FitFCN(unsigned int npar, Function &fcn, const double *params=0, unsigned int dataSize=0, bool chi2fit=false)
Fit using the a generic FCN function as a C++ callable object implementing double () (const double *)...
Definition: Fitter.h:538
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1101
ClassImp(TFractionFitter) TFractionFitter
TFractionFitter default constructor.
Basic string class.
Definition: TString.h:137
void TFractionFitFCN(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t flag)
TAlienJobStatus * status
Definition: TAlienJob.cxx:51
int Int_t
Definition: RtypesCore.h:41
double ErrorDef() const
error definition
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Int_t GetNbinsX() const
Definition: TH1.h:296
ROOT::Math::MinimizerOptions & MinimizerOptions()
access to the minimizer control parameter (non const method)
Definition: FitConfig.h:138
void SetErrorDef(double err)
set error def
TH1 * GetMCPrediction(Int_t parm) const
Return the adjusted MC template (Aji) for template (parm).
void ReleaseRangeY()
Release restrictions on the Y range of the histogram to be used in the fit.
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition: TMath.cxx:619
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:6669
TObject * Clone(const char *newname=0) const
Make a complete copy of the underlying object.
Definition: TH1.cxx:2565
const char * Data() const
Definition: TString.h:349
void SetRangeZ(Int_t low, Int_t high)
Set the Z range of the histogram to be used in the fit (3D histograms only).
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TObject.cxx:203
Double_t x[n]
Definition: legend1.C:17
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2334
Extends the ROOT::Fit::Result class with a TNamed inheritance providing easy possibility for I/O...
Definition: TFitResult.h:36
const FitResult & Result() const
get fit result
Definition: Fitter.h:354
void CheckConsistency()
Function used internally to check the consistency between the various histograms. ...
const std::vector< ROOT::Fit::ParameterSettings > & ParamsSettings() const
get the vector of parameter settings (const method)
Definition: FitConfig.h:90
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition: TH1.cxx:4535
ROOT::Fit::Fitter * fFractionFitter
void UnConstrain(Int_t parm)
Remove the constraints on the possible values of parameter .
void SetData(TH1 *data)
Change the histogram to be fitted to.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
void SetMC(Int_t parm, TH1 *MC)
Change the histogram for template number .
void Error(const char *location, const char *msgfmt,...)
const double * GetParams() const
parameter values (return const pointer)
Definition: FitResult.h:181
ROOT::R::TRInterface & r
Definition: Object.C:4
bool IsExcluded(Int_t bin) const
Function for internal use, checking whether the given bin is excluded from the fit or not...
int Status() const
minimizer status code
Definition: FitResult.h:142
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:629
Fitter class, entry point for performing all type of fits.
Definition: Fitter.h:94
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
Definition: TFitResultPtr.h:33
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition: TH1.cxx:8543
const ParameterSettings & ParSettings(unsigned int i) const
get the parameter settings for the i-th parameter (const method)
Definition: FitConfig.h:80
void SetRangeX(Int_t low, Int_t high)
Set the X range of the histogram to be used in the fit.
Double_t GetProb() const
return the fit probability
char * Form(const char *fmt,...)
virtual Int_t GetNbinsZ() const
Definition: TH1.h:298
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:238
Int_t GetNDF() const
return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
void ComputeFCN(Double_t &f, const Double_t *par, Int_t flag)
Used internally to compute the likelihood value.
Double_t * fFractions
TH1 * GetPlot()
Return the "template prediction" corresponding to the fit result (this is not the same as the weighte...
Double_t GetChisquare() const
Return the likelihood ratio Chi-squared (chi2) for the fit.
double Double_t
Definition: RtypesCore.h:55
void ComputeChisquareLambda()
Method used internally to compute the likelihood ratio chi2 See the function GetChisquare() for detai...
double Error(unsigned int i) const
parameter error by index
Definition: FitResult.h:191
Double_t y[n]
Definition: legend1.C:17
double func(double *x, double *p)
Definition: stressTF1.cxx:213
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
Definition: TObjArray.cxx:369
void SetRangeY(Int_t low, Int_t high)
Set the Y range of the histogram to be used in the fit (2D or 3D histograms only).
The TH1 histogram class.
Definition: TH1.h:80
Double_t * fIntegralMCs
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:493
void ErrorAnalysis(Double_t UP)
Set UP to the given value (see class TMinuit), and perform a MINOS minimisation.
#define name(a, b)
Definition: linkTestLib0.cpp:5
void CheckParNo(Int_t parm) const
Function for internal use, checking parameter validity An invalid parameter results in an error...
virtual Int_t GetNbinsY() const
Definition: TH1.h:297
Fits MC fractions to data histogram.
bool SetFCN(unsigned int npar, Function &fcn, const double *params=0, unsigned int dataSize=0, bool chi2fit=false)
Set a generic FCN function as a C++ callable object implementing double () (const double *) Note that...
Definition: Fitter.h:543
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
TFitResultPtr Fit()
Perform the fit with the default UP value.
void GetRanges(Int_t &minX, Int_t &maxX, Int_t &minY, Int_t &maxY, Int_t &minZ, Int_t &maxZ) const
Used internally to obtain the bin ranges according to the dimensionality of the histogram and the lim...
void SetLimits(double low, double up)
set a double side limit, if low == up the parameter is fixed if low > up the limits are removed ...
void Add(TObject *obj)
Definition: TObjArray.h:75
void ExcludeBin(Int_t bin)
Exclude the given bin from the fit.
double result[121]
virtual void SetTitle(const char *title)
Change (i.e.
Definition: TH1.cxx:6268
ROOT::Fit::Fitter * GetFitter() const
Give direct access to the underlying fitter class.
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
double Parameter(unsigned int i) const
parameter value by index
Definition: FitResult.h:186
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void SetTitle(const char *title="")
Change (i.e. set) the title of the TNamed.
Definition: TNamed.cxx:152
float value
Definition: math.cpp:443
Int_t Nint(T x)
Definition: TMath.h:480
void IncludeBin(Int_t bin)
Include the given bin in the fit, if it was excluded before using ExcludeBin().
void SetWeight(Int_t parm, TH1 *weight)
Set bin by bin weights for template number (the parameter numbering follows that of the input ...
void ReleaseRangeZ()
Release restrictions on the Z range of the histogram to be used in the fit.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904