Logo ROOT   6.10/09
Reference Guide
HFitInterface.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: L. Moneta Thu Aug 31 10:40:20 2006
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Implementation file for class TH1Interface
12 
13 #include "HFitInterface.h"
14 
15 #include "Fit/BinData.h"
16 #include "Fit/SparseData.h"
17 #include "Fit/FitResult.h"
18 #include "Math/IParamFunction.h"
19 
20 #include <vector>
21 
22 #include <cassert>
23 #include <cmath>
24 
25 #include "TH1.h"
26 #include "THnBase.h"
27 #include "TF1.h"
28 #include "TGraph2D.h"
29 #include "TGraph.h"
30 #include "TGraphErrors.h"
31 // #include "TGraphErrors.h"
32 // #include "TGraphBentErrors.h"
33 // #include "TGraphAsymmErrors.h"
34 #include "TMultiGraph.h"
35 #include "TList.h"
36 #include "TError.h"
37 
38 
39 //#define DEBUG
40 #ifdef DEBUG
41 #include "TClass.h"
42 #include <iostream>
43 #endif
44 
45 
46 namespace ROOT {
47 
48 namespace Fit {
49 
50 // add a namespace to distinguish from the Graph functions
51 namespace HFitInterface {
52 
53 
54 bool IsPointOutOfRange(const TF1 * func, const double * x) {
55  // function to check if a point is outside range
56  if (func ==0) return false;
57  return !func->IsInside(x);
58 }
59 
60 bool AdjustError(const DataOptions & option, double & error, double value = 1) {
61  // adjust the given error according to the option
62  // return false when point must be skipped.
63  // When point error = 0, the point is kept if the option UseEmpty is set or if
64  // fErrors1 is set and the point value is not zero.
65  // The value should be used only for points representing counts (histograms), not for the graph.
66  // In the graph points with zero errors are by default skipped indepentently of the value.
67  // If one wants to keep the points, the option fUseEmpty must be set
68 
69  if (error <= 0) {
70  if (option.fUseEmpty || (option.fErrors1 && std::abs(value) > 0 ) )
71  error = 1.; // set error to 1
72  else
73  return false; // skip bins with zero errors or empty
74  } else if (option.fErrors1)
75  error = 1; // set all error to 1 for non-empty bins
76  return true;
77 }
78 
79 void ExamineRange(const TAxis * axis, std::pair<double,double> range,int &hxfirst,int &hxlast) {
80  // examine the range given with the pair on the given histogram axis
81  // correct in case the bin values hxfirst hxlast
82  double xlow = range.first;
83  double xhigh = range.second;
84 #ifdef DEBUG
85  std::cout << "xlow " << xlow << " xhigh = " << xhigh << std::endl;
86 #endif
87  // ignore ranges specified outside histogram range
88  int ilow = axis->FindFixBin(xlow);
89  int ihigh = axis->FindFixBin(xhigh);
90  if (ilow > hxlast || ihigh < hxfirst) {
91  Warning("ROOT::Fit::FillData","fit range is outside histogram range, no fit data for %s",axis->GetName());
92  }
93  // consider only range defined with-in histogram not oustide. Always exclude underflow/overflow
94  hxfirst = std::min( std::max( ilow, hxfirst), hxlast+1) ;
95  hxlast = std::max( std::min( ihigh, hxlast), hxfirst-1) ;
96  // exclude bins where range coverage is less than half bin width
97  if (hxfirst < hxlast) {
98  if ( axis->GetBinCenter(hxfirst) < xlow) hxfirst++;
99  if ( axis->GetBinCenter(hxlast) > xhigh) hxlast--;
100  }
101 }
102 
103 
104 } // end namespace HFitInterface
105 
106 
107 void FillData(BinData & dv, const TH1 * hfit, TF1 * func)
108 {
109  // Function to fill the binned Fit data structure from a TH1
110  // The dimension of the data is the same of the histogram dimension
111  // The function pointer is need in case of integral is used and to reject points
112  // rejected in the function
113 
114  // the TF1 pointer cannot be constant since EvalPar and InitArgs are not const methods
115 
116  // get fit option
117  const DataOptions & fitOpt = dv.Opt();
118 
119 
120  // store instead of bin center the bin edges
121  bool useBinEdges = fitOpt.fIntegral || fitOpt.fBinVolume;
122 
123  assert(hfit != 0);
124 
125  //std::cout << "creating Fit Data from histogram " << hfit->GetName() << std::endl;
126 
127  int hxfirst = hfit->GetXaxis()->GetFirst();
128  int hxlast = hfit->GetXaxis()->GetLast();
129 
130  int hyfirst = hfit->GetYaxis()->GetFirst();
131  int hylast = hfit->GetYaxis()->GetLast();
132 
133  int hzfirst = hfit->GetZaxis()->GetFirst();
134  int hzlast = hfit->GetZaxis()->GetLast();
135 
136  // function by default has same range (use that one if requested otherwise use data one)
137 
138 
139  // get the range (add the function range ??)
140  // to check if inclusion/exclusion at end/point
141  const DataRange & range = dv.Range();
142  if (range.Size(0) != 0) {
143  HFitInterface::ExamineRange( hfit->GetXaxis(), range(0), hxfirst, hxlast);
144  if (range.Size(0) > 1 ) {
145  Warning("ROOT::Fit::FillData","support only one range interval for X coordinate");
146  }
147  }
148 
149  if (hfit->GetDimension() > 1 && range.Size(1) != 0) {
150  HFitInterface::ExamineRange( hfit->GetYaxis(), range(1), hyfirst, hylast);
151  if (range.Size(1) > 1 )
152  Warning("ROOT::Fit::FillData","support only one range interval for Y coordinate");
153  }
154 
155  if (hfit->GetDimension() > 2 && range.Size(2) != 0) {
156  HFitInterface::ExamineRange( hfit->GetZaxis(), range(2), hzfirst, hzlast);
157  if (range.Size(2) > 1 )
158  Warning("ROOT::Fit::FillData","support only one range interval for Z coordinate");
159  }
160 
161 
162  int n = (hxlast-hxfirst+1)*(hylast-hyfirst+1)*(hzlast-hzfirst+1);
163 
164 #ifdef DEBUG
165  std::cout << "THFitInterface: ifirst = " << hxfirst << " ilast = " << hxlast
166  << " total bins " << n
167  << std::endl;
168 #endif
169 
170  // reserve n for more efficient usage
171  //dv.Data().reserve(n);
172 
173  int hdim = hfit->GetDimension();
174  int ndim = hdim;
175  // case of function dimension less than histogram
176  if (func !=0 && func->GetNdim() == hdim-1) ndim = hdim-1;
177 
178  assert( ndim > 0 );
179  //typedef BinPoint::CoordData CoordData;
180  //CoordData x = CoordData( hfit->GetDimension() );
181  dv.Initialize(n,ndim);
182 
183  double x[3];
184  double s[3];
185 
186  int binx = 0;
187  int biny = 0;
188  int binz = 0;
189 
190  const TAxis *xaxis = hfit->GetXaxis();
191  const TAxis *yaxis = hfit->GetYaxis();
192  const TAxis *zaxis = hfit->GetZaxis();
193 
194  for ( binx = hxfirst; binx <= hxlast; ++binx) {
195  if (useBinEdges) {
196  x[0] = xaxis->GetBinLowEdge(binx);
197  s[0] = xaxis->GetBinUpEdge(binx);
198  }
199  else
200  x[0] = xaxis->GetBinCenter(binx);
201 
202 
203  for ( biny = hyfirst; biny <= hylast; ++biny) {
204  if (useBinEdges) {
205  x[1] = yaxis->GetBinLowEdge(biny);
206  s[1] = yaxis->GetBinUpEdge(biny);
207  }
208  else
209  x[1] = yaxis->GetBinCenter(biny);
210 
211  for ( binz = hzfirst; binz <= hzlast; ++binz) {
212  if (useBinEdges) {
213  x[2] = zaxis->GetBinLowEdge(binz);
214  s[2] = zaxis->GetBinUpEdge(binz);
215  }
216  else
217  x[2] = zaxis->GetBinCenter(binz);
218 
219  // need to evaluate function to know about rejected points
220  // hugly but no other solutions
221  if (func != 0) {
222  TF1::RejectPoint(false);
223  (*func)( &x[0] ); // evaluate using stored function parameters
224  if (TF1::RejectedPoint() ) continue;
225  }
226 
227 
228  double value = hfit->GetBinContent(binx, biny, binz);
229  double error = hfit->GetBinError(binx, biny, binz);
230  if (!HFitInterface::AdjustError(fitOpt,error,value) ) continue;
231 
232  if (ndim == hdim -1) {
233  // case of fitting a function with dimension -1
234  // point error is bin width y / sqrt(N) where N is nuber of entries in the bin
235  // normalization of error will be wrong - but they will be rescaled in the fit
236  if (hdim == 2) dv.Add( x, x[1], yaxis->GetBinWidth(biny) / error );
237  if (hdim == 3) dv.Add( x, x[2], zaxis->GetBinWidth(binz) / error );
238  } else {
239  dv.Add( x, value, error );
240  if (useBinEdges) {
241  dv.AddBinUpEdge( s );
242  }
243  }
244 
245 
246 #ifdef DEBUG
247  std::cout << "bin " << binx << " add point " << x[0] << " " << hfit->GetBinContent(binx) << std::endl;
248 #endif
249 
250  } // end loop on z bins
251  } // end loop on y bins
252  } // end loop on x axis
253 
254 
255 #ifdef DEBUG
256  std::cout << "THFitInterface::FillData: Hist FitData size is " << dv.Size() << std::endl;
257 #endif
258 
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// -*-*-*-*Compute rough values of parameters for an exponential
263 /// ===================================================
264 
266 {
267  unsigned int n = data.Size();
268  if (n == 0) return;
269 
270  // find xmin and xmax of the data
271  double valxmin;
272  double xmin = *(data.GetPoint(0,valxmin));
273  double xmax = xmin;
274  double valxmax = valxmin;
275 
276  for (unsigned int i = 1; i < n; ++ i) {
277  double val;
278  double x = *(data.GetPoint(i,val) );
279  if (x < xmin) {
280  xmin = x;
281  valxmin = val;
282  }
283  else if (x > xmax) {
284  xmax = x;
285  valxmax = val;
286  }
287  }
288 
289  // avoid negative values of valxmin/valxmax
290  if (valxmin <= 0 && valxmax > 0 ) valxmin = valxmax;
291  else if (valxmax <=0 && valxmin > 0) valxmax = valxmin;
292  else if (valxmin <=0 && valxmax <= 0) { valxmin = 1; valxmax = 1; }
293 
294  double slope = std::log( valxmax/valxmin) / (xmax - xmin);
295  double constant = std::log(valxmin) - slope * xmin;
296  f1->SetParameters(constant, slope);
297 }
298 
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// -*-*-*-*Compute Initial values of parameters for a gaussian
302 /// derivaed from function H1InitGaus defined in TH1.cxx
303 /// ===================================================
304 
306 {
307 
308  static const double sqrtpi = 2.506628;
309 
310  // - Compute mean value and RMS of the data
311  unsigned int n = data.Size();
312  if (n == 0) return;
313  double sumx = 0;
314  double sumx2 = 0;
315  double allcha = 0;
316  double valmax = 0;
317  double rangex = data.Coords(n-1)[0] - data.Coords(0)[0];
318  // to avoid binwidth = 0 set arbitrarly to 1
319  double binwidth = 1;
320  if ( rangex > 0) binwidth = rangex;
321  double x0 = 0;
322  for (unsigned int i = 0; i < n; ++ i) {
323  double val;
324  double x = *(data.GetPoint(i,val) );
325  sumx += val*x;
326  sumx2 += val*x*x;
327  allcha += val;
328  if (val > valmax) valmax = val;
329  if (i > 0) {
330  double dx = x - x0;
331  if (dx < binwidth) binwidth = dx;
332  }
333  x0 = x;
334  }
335 
336  if (allcha <= 0) return;
337  double mean = sumx/allcha;
338  double rms = sumx2/allcha - mean*mean;
339 
340 
341  if (rms > 0)
342  rms = std::sqrt(rms);
343  else
344  rms = binwidth*n/4;
345 
346 
347  //if the distribution is really gaussian, the best approximation
348  //is binwidx*allcha/(sqrtpi*rms)
349  //However, in case of non-gaussian tails, this underestimates
350  //the normalisation constant. In this case the maximum value
351  //is a better approximation.
352  //We take the average of both quantities
353 
354 // printf("valmax %f other %f bw %f allcha %f rms %f \n",valmax, binwidth*allcha/(sqrtpi*rms),
355 // binwidth, allcha,rms );
356 
357  double constant = 0.5*(valmax+ binwidth*allcha/(sqrtpi*rms));
358 
359 
360  //In case the mean value is outside the histo limits and
361  //the RMS is bigger than the range, we take
362  // mean = center of bins
363  // rms = half range
364 // Double_t xmin = curHist->GetXaxis()->GetXmin();
365 // Double_t xmax = curHist->GetXaxis()->GetXmax();
366 // if ((mean < xmin || mean > xmax) && rms > (xmax-xmin)) {
367 // mean = 0.5*(xmax+xmin);
368 // rms = 0.5*(xmax-xmin);
369 // }
370 
371  f1->SetParameter(0,constant);
372  f1->SetParameter(1,mean);
373  f1->SetParameter(2,rms);
374  f1->SetParLimits(2,0,10*rms);
375 
376 
377 #ifdef DEBUG
378  std::cout << "Gaussian initial par values" << constant << " " << mean << " " << rms << std::endl;
379 #endif
380 
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// -*-*-*-*Compute Initial values of parameters for a gaussian
385 /// derivaed from function H1InitGaus defined in TH1.cxx
386 /// ===================================================
387 
389 {
390 
391  static const double sqrtpi = 2.506628;
392 
393  // - Compute mean value and RMS of the data
394  unsigned int n = data.Size();
395  if (n == 0) return;
396  double sumx = 0, sumy = 0;
397  double sumx2 = 0, sumy2 = 0;
398  double allcha = 0;
399  double valmax = 0;
400  double rangex = data.Coords(n-1)[0] - data.Coords(0)[0];
401  double rangey = data.Coords(n-1)[1] - data.Coords(0)[1];
402  // to avoid binwidthx = 0 set arbitrarly to 1
403  double binwidthx = 1, binwidthy = 1;
404  if ( rangex > 0) binwidthx = rangex;
405  if ( rangey > 0) binwidthy = rangey;
406  double x0 = 0, y0 = 0;
407  for (unsigned int i = 0; i < n; ++i) {
408  double val;
409  const double *coords = data.GetPoint(i,val);
410  double x = coords[0], y = coords[1];
411  sumx += val*x;
412  sumy += val*y;
413  sumx2 += val*x*x;
414  sumy2 += val*y*y;
415  allcha += val;
416  if (val > valmax) valmax = val;
417  if (i > 0) {
418  double dx = x - x0;
419  if (dx < binwidthx) binwidthx = dx;
420  double dy = y - y0;
421  if (dy < binwidthy) binwidthy = dy;
422  }
423  x0 = x;
424  y0 = y;
425  }
426 
427  if (allcha <= 0) return;
428  double meanx = sumx/allcha, meany = sumy/allcha;
429  double rmsx = sumx2/allcha - meanx*meanx;
430  double rmsy = sumy2/allcha - meany*meany;
431 
432 
433  if (rmsx > 0)
434  rmsx = std::sqrt(rmsx);
435  else
436  rmsx = binwidthx*n/4;
437 
438  if (rmsy > 0)
439  rmsy = std::sqrt(rmsy);
440  else
441  rmsy = binwidthy*n/4;
442 
443 
444  //if the distribution is really gaussian, the best approximation
445  //is binwidx*allcha/(sqrtpi*rmsx)
446  //However, in case of non-gaussian tails, this underestimates
447  //the normalisation constant. In this case the maximum value
448  //is a better approximation.
449  //We take the average of both quantities
450 
451  double constant = 0.5 * (valmax+ binwidthx*allcha/(sqrtpi*rmsx))*
452  (valmax+ binwidthy*allcha/(sqrtpi*rmsy));
453 
454  f1->SetParameter(0,constant);
455  f1->SetParameter(1,meanx);
456  f1->SetParameter(2,rmsx);
457  f1->SetParLimits(2,0,10*rmsx);
458  f1->SetParameter(3,meany);
459  f1->SetParameter(4,rmsy);
460  f1->SetParLimits(4,0,10*rmsy);
461 
462 #ifdef DEBUG
463  std::cout << "2D Gaussian initial par values"
464  << constant << " "
465  << meanx << " "
466  << rmsx
467  << meany << " "
468  << rmsy
469  << std::endl;
470 #endif
471 
472 }
473 
474 // filling fit data from TGraph objects
475 
477  // get type of data for TGraph objects
478  double *ex = gr->GetEX();
479  double *ey = gr->GetEY();
480  double * eyl = gr->GetEYlow();
481  double * eyh = gr->GetEYhigh();
482 
483 
484  // default case for graphs (when they have errors)
486  // if all errors are zero set option of using errors to 1
487  if (fitOpt.fErrors1 || ( ey == 0 && ( eyl == 0 || eyh == 0 ) ) ) {
488  type = BinData::kNoError;
489  }
490  // need to treat case when all errors are zero
491  // note that by default fitOpt.fCoordError is true
492  else if ( ex != 0 && fitOpt.fCoordErrors) {
493  // check that all errors are not zero
494  int i = 0;
495  while (i < gr->GetN() && type != BinData::kCoordError) {
496  if (ex[i] > 0) type = BinData::kCoordError;
497  ++i;
498  }
499  }
500  // case of asymmetric errors (by default fAsymErrors is true)
501  else if ( ( eyl != 0 && eyh != 0) && fitOpt.fAsymErrors) {
502  // check also if that all errors are non zero's
503  int i = 0;
504  bool zeroErrorX = true;
505  bool zeroErrorY = true;
506  while (i < gr->GetN() && (zeroErrorX || zeroErrorY)) {
507  double e2X = ( gr->GetErrorXlow(i) + gr->GetErrorXhigh(i) );
508  double e2Y = eyl[i] + eyh[i];
509  zeroErrorX &= (e2X <= 0);
510  zeroErrorY &= (e2Y <= 0);
511  ++i;
512  }
513  if (zeroErrorX && zeroErrorY)
514  type = BinData::kNoError;
515  else if (!zeroErrorX && zeroErrorY)
516  type = BinData::kCoordError;
517  else if (zeroErrorX && !zeroErrorY) {
518  type = BinData::kAsymError;
519  fitOpt.fCoordErrors = false;
520  }
521  else {
522  type = BinData::kAsymError;
523  }
524  }
525 
526  // need to look also a case when all errors in y are zero
527  if ( ey != 0 && type != BinData::kCoordError ) {
528  int i = 0;
529  bool zeroError = true;
530  while (i < gr->GetN() && zeroError) {
531  if (ey[i] > 0) zeroError = false;;
532  ++i;
533  }
534  if (zeroError) type = BinData::kNoError;
535  }
536 
537 
538 #ifdef DEBUG
539  std::cout << "type is " << type << " graph type is " << gr->IsA()->GetName() << std::endl;
540 #endif
541 
542  return type;
543 }
544 
546  // get type of data for TGraph2D object
547  double *ex = gr->GetEX();
548  double *ey = gr->GetEY();
549  double *ez = gr->GetEZ();
550 
551  // default case for graphs (when they have errors)
553  // if all errors are zero set option of using errors to 1
554  if (fitOpt.fErrors1 || ez == 0 ) {
555  type = BinData::kNoError;
556  }
557  else if ( ex != 0 && ey!=0 && fitOpt.fCoordErrors) {
558  // check that all errors are not zero
559  int i = 0;
560  while (i < gr->GetN() && type != BinData::kCoordError) {
561  if (ex[i] > 0 || ey[i] > 0) type = BinData::kCoordError;
562  ++i;
563  }
564  }
565 
566 
567 #ifdef DEBUG
568  std::cout << "type is " << type << " graph2D type is " << gr->IsA()->GetName() << std::endl;
569 #endif
570 
571  return type;
572 }
573 
574 
575 
577  // internal method to do the actual filling of the data
578  // given a graph and a multigraph
579 
580  // get fit option
581  DataOptions & fitOpt = dv.Opt();
582 
583  int nPoints = gr->GetN();
584  double *gx = gr->GetX();
585  double *gy = gr->GetY();
586 
587  const DataRange & range = dv.Range();
588  bool useRange = ( range.Size(0) > 0);
589  double xmin = 0;
590  double xmax = 0;
591  range.GetRange(xmin,xmax);
592 
593  dv.Initialize(nPoints,1, type);
594 
595 #ifdef DEBUG
596  std::cout << "DoFillData: graph npoints = " << nPoints << " type " << type << std::endl;
597  if (func) {
598  double a1,a2; func->GetRange(a1,a2); std::cout << "func range " << a1 << " " << a2 << std::endl;
599  }
600 #endif
601 
602  double x[1];
603  for ( int i = 0; i < nPoints; ++i) {
604 
605  x[0] = gx[i];
606 
607 
608  if (useRange && ( x[0] < xmin || x[0] > xmax) ) continue;
609 
610  // need to evaluate function to know about rejected points
611  // hugly but no other solutions
612  if (func) {
613  TF1::RejectPoint(false);
614  (*func)( x ); // evaluate using stored function parameters
615  if (TF1::RejectedPoint() ) continue;
616  }
617 
618 
619  if (fitOpt.fErrors1)
620  dv.Add( gx[i], gy[i] );
621 
622  // for the errors use the getters by index to avoid cases when the arrays are zero
623  // (like in a case of a graph)
624  else if (type == BinData::kValueError) {
625  double errorY = gr->GetErrorY(i);
626  // should consider error = 0 as 1 ? Decide to skip points with zero errors
627  // in case want to keep points with error = 0 as errrors=1 need to set the option UseEmpty
628  if (!HFitInterface::AdjustError(fitOpt,errorY) ) continue;
629  dv.Add( gx[i], gy[i], errorY );
630 
631 #ifdef DEBUG
632  std::cout << "Point " << i << " " << gx[i] << " " << gy[i] << " " << errorY << std::endl;
633 #endif
634 
635 
636  }
637  else { // case use error in x or asym errors
638  double errorX = 0;
639  if (fitOpt.fCoordErrors)
640  // shoulkd take combined average (sqrt(0.5(e1^2+e2^2)) or math average ?
641  // gr->GetErrorX(i) returns combined average
642  // use math average for same behaviour as before
643  errorX = std::max( 0.5 * ( gr->GetErrorXlow(i) + gr->GetErrorXhigh(i) ) , 0. ) ;
644 
645 
646  // adjust error in y according to option
647  double errorY = std::max(gr->GetErrorY(i), 0.);
648  // we do not check the return value since we check later if error in X and Y is zero for skipping the point
649  HFitInterface::AdjustError(fitOpt, errorY);
650 
651  // skip points with total error = 0
652  if ( errorX <=0 && errorY <= 0 ) continue;
653 
654 
655  if (type == BinData::kAsymError) {
656  // asymmetric errors
657  dv.Add( gx[i], gy[i], errorX, gr->GetErrorYlow(i), gr->GetErrorYhigh(i) );
658  }
659  else {
660  // case symmetric Y errors
661  dv.Add( gx[i], gy[i], errorX, errorY );
662  }
663  }
664 
665  }
666 
667 #ifdef DEBUG
668  std::cout << "TGraphFitInterface::FillData Graph FitData size is " << dv.Size() << std::endl;
669 #endif
670 
671 }
672 
673 void FillData(SparseData & dv, const TH1 * h1, TF1 * /*func*/)
674 {
675  const int dim = h1->GetDimension();
676  std::vector<double> min(dim);
677  std::vector<double> max(dim);
678 
679  int ncells = h1->GetNcells();
680  for ( int i = 0; i < ncells; ++i ) {
681 // printf("i: %d; OF: %d; UF: %d; C: %f\n"
682 // , i
683 // , h1->IsBinOverflow(i) , h1->IsBinUnderflow(i)
684 // , h1->GetBinContent(i));
685  if ( !( h1->IsBinOverflow(i) || h1->IsBinUnderflow(i) )
686  && h1->GetBinContent(i))
687  {
688  int x,y,z;
689  h1->GetBinXYZ(i, x, y, z);
690 
691 // std::cout << "FILLDATA: h1(" << i << ")"
692 // << "[" << h1->GetXaxis()->GetBinLowEdge(x) << "-" << h1->GetXaxis()->GetBinUpEdge(x) << "]";
693 // if ( dim >= 2 )
694 // std::cout << "[" << h1->GetYaxis()->GetBinLowEdge(y) << "-" << h1->GetYaxis()->GetBinUpEdge(y) << "]";
695 // if ( dim >= 3 )
696 // std::cout << "[" << h1->GetZaxis()->GetBinLowEdge(z) << "-" << h1->GetZaxis()->GetBinUpEdge(z) << "]";
697 
698 // std::cout << h1->GetBinContent(i) << std::endl;
699 
700  min[0] = h1->GetXaxis()->GetBinLowEdge(x);
701  max[0] = h1->GetXaxis()->GetBinUpEdge(x);
702  if ( dim >= 2 )
703  {
704  min[1] = h1->GetYaxis()->GetBinLowEdge(y);
705  max[1] = h1->GetYaxis()->GetBinUpEdge(y);
706  }
707  if ( dim >= 3 ) {
708  min[2] = h1->GetZaxis()->GetBinLowEdge(z);
709  max[2] = h1->GetZaxis()->GetBinUpEdge(z);
710  }
711 
712  dv.Add(min, max, h1->GetBinContent(i), h1->GetBinError(i));
713  }
714  }
715 }
716 
717 void FillData(SparseData & dv, const THnBase * h1, TF1 * /*func*/)
718 {
719  const int dim = h1->GetNdimensions();
720  std::vector<double> min(dim);
721  std::vector<double> max(dim);
722  std::vector<Int_t> coord(dim);
723 
724  ULong64_t nEntries = h1->GetNbins();
725  for ( ULong64_t i = 0; i < nEntries; i++ )
726  {
727  double value = h1->GetBinContent( i, &coord[0] );
728  if ( !value ) continue;
729 
730 // std::cout << "FILLDATA(SparseData): h1(" << i << ")";
731 
732  // Exclude underflows and oveflows! (defect behaviour with the TH1*)
733  bool insertBox = true;
734  for ( int j = 0; j < dim && insertBox; ++j )
735  {
736  TAxis* axis = h1->GetAxis(j);
737  if ( ( axis->GetBinLowEdge(coord[j]) < axis->GetXmin() ) ||
738  ( axis->GetBinUpEdge(coord[j]) > axis->GetXmax() ) ) {
739  insertBox = false;
740  }
741  min[j] = h1->GetAxis(j)->GetBinLowEdge(coord[j]);
742  max[j] = h1->GetAxis(j)->GetBinUpEdge(coord[j]);
743  }
744  if ( !insertBox ) {
745 // std::cout << "NOT INSERTED!"<< std::endl;
746  continue;
747  }
748 
749 // for ( int j = 0; j < dim; ++j )
750 // {
751 // std::cout << "[" << h1->GetAxis(j)->GetBinLowEdge(coord[j])
752 // << "-" << h1->GetAxis(j)->GetBinUpEdge(coord[j]) << "]";
753 // }
754 // std::cout << h1->GetBinContent(i) << std::endl;
755 
756  dv.Add(min, max, value, h1->GetBinError(i));
757  }
758 }
759 
760 void FillData(BinData & dv, const THnBase * s1, TF1 * func)
761 {
762  // Fill the Range of the THnBase
763  unsigned int const ndim = s1->GetNdimensions();
764  std::vector<double> xmin(ndim);
765  std::vector<double> xmax(ndim);
766  for ( unsigned int i = 0; i < ndim; ++i ) {
767  TAxis* axis = s1->GetAxis(i);
768  xmin[i] = axis->GetXmin();
769  xmax[i] = axis->GetXmax();
770  }
771 
772  // Put default options, needed for the likelihood fitting of sparse
773  // data.
774  ROOT::Fit::DataOptions& dopt = dv.Opt();
775  dopt.fUseEmpty = true;
776  // when using sparse data need to set option to use normalized bin volume, because sparse bins are merged together
777  //if (!dopt.fIntegral) dopt.fBinVolume = true;
778  dopt.fBinVolume = true;
779  dopt.fNormBinVolume = true;
780 
781  // Get the sparse data
782  ROOT::Fit::SparseData d(ndim, &xmin[0], &xmax[0]);
783  ROOT::Fit::FillData(d, s1, func);
784 
785 // std::cout << "FillData(BinData & dv, const THnBase * s1, TF1 * func) (1)" << std::endl;
786 
787  // Create the bin data from the sparse data
788  d.GetBinDataIntegral(dv);
789 
790 }
791 
792 void FillData ( BinData & dv, const TGraph * gr, TF1 * func ) {
793  // fill the data vector from a TGraph. Pass also the TF1 function which is
794  // needed in case to exclude points rejected by the function
795  assert(gr != 0);
796 
797  // get fit option
798  DataOptions & fitOpt = dv.Opt();
799 
800  BinData::ErrorType type = GetDataType(gr,fitOpt);
801  // adjust option according to type
802  fitOpt.fErrors1 = (type == BinData::kNoError);
803  // set this if we want to have error=1 for points with zero errors (by default they are skipped)
804  // fitOpt.fUseEmpty = true;
805 
806  // use coordinate or asym errors in case option is set and type is consistent
807  fitOpt.fCoordErrors &= (type == BinData::kCoordError) || (type == BinData::kAsymError) ;
808  fitOpt.fAsymErrors &= (type == BinData::kAsymError);
809 
810 
811  // if data are filled already check if there are consistent - otherwise do nothing
812  if (dv.Size() > 0 && dv.NDim() == 1 ) {
813  // check if size is correct otherwise flag an errors
814  if ( dv.GetErrorType() != type ) {
815  Error("FillData","Inconsistent TGraph with previous data set- skip all graph data");
816  return;
817  }
818  }
819 
820  DoFillData(dv, gr, type, func);
821 
822 }
823 
824 void FillData ( BinData & dv, const TMultiGraph * mg, TF1 * func ) {
825  // fill the data vector from a TMultiGraph. Pass also the TF1 function which is
826  // needed in case to exclude points rejected by the function
827  assert(mg != 0);
828 
829  TList * grList = mg->GetListOfGraphs();
830  assert(grList != 0);
831 
832 #ifdef DEBUG
833 // grList->Print();
834  TIter itr(grList, kIterBackward);
835  TObject *obj;
836  std::cout << "multi-graph list of graps: " << std::endl;
837  while ((obj = itr())) {
838  std::cout << obj->IsA()->GetName() << std::endl;
839  }
840 
841 #endif
842 
843  // get fit option
844  DataOptions & fitOpt = dv.Opt();
845 
846  // loop on the graphs to get the data type (use maximum)
847  TIter next(grList);
848 
850  TGraph *gr = 0;
851  while ((gr = (TGraph*) next())) {
852  BinData::ErrorType t = GetDataType(gr,fitOpt);
853  if (t > type ) type = t;
854  }
855  // adjust option according to type
856  fitOpt.fErrors1 = (type == BinData::kNoError);
857  fitOpt.fCoordErrors = (type == BinData::kCoordError);
858  fitOpt.fAsymErrors = (type == BinData::kAsymError);
859 
860 
861 #ifdef DEBUG
862  std::cout << "Fitting MultiGraph of type " << type << std::endl;
863 #endif
864 
865  // fill the data now
866  next = grList;
867  while ((gr = (TGraph*) next())) {
868  DoFillData( dv, gr, type, func);
869  }
870 
871 #ifdef DEBUG
872  std::cout << "TGraphFitInterface::FillData MultiGraph FitData size is " << dv.Size() << std::endl;
873 #endif
874 
875 }
876 
877 void FillData ( BinData & dv, const TGraph2D * gr, TF1 * func ) {
878  // fill the data vector from a TGraph2D. Pass also the TF1 function which is
879  // needed in case to exclude points rejected by the function
880  // in case of a pure TGraph
881  assert(gr != 0);
882 
883  // get fit option
884  DataOptions & fitOpt = dv.Opt();
885  BinData::ErrorType type = GetDataType(gr,fitOpt);
886  // adjust option according to type
887  fitOpt.fErrors1 = (type == BinData::kNoError);
888  fitOpt.fCoordErrors = (type == BinData::kCoordError);
889  fitOpt.fAsymErrors = false; // a TGraph2D with asymmetric errors does not exist
890 
891  int nPoints = gr->GetN();
892  double *gx = gr->GetX();
893  double *gy = gr->GetY();
894  double *gz = gr->GetZ();
895 
896  // if all errors are zero set option of using errors to 1
897  if ( gr->GetEZ() == 0) fitOpt.fErrors1 = true;
898 
899  double x[2];
900  double ex[2];
901 
902  // look at data range
903  const DataRange & range = dv.Range();
904  bool useRangeX = ( range.Size(0) > 0);
905  bool useRangeY = ( range.Size(1) > 0);
906  double xmin = 0;
907  double xmax = 0;
908  double ymin = 0;
909  double ymax = 0;
910  range.GetRange(xmin,xmax,ymin,ymax);
911 
912  dv.Initialize(nPoints,2, type);
913 
914  for ( int i = 0; i < nPoints; ++i) {
915 
916  x[0] = gx[i];
917  x[1] = gy[i];
918 
919  //if (fitOpt.fUseRange && HFitInterface::IsPointOutOfRange(func, x) ) continue;
920  if (useRangeX && ( x[0] < xmin || x[0] > xmax) ) continue;
921  if (useRangeY && ( x[1] < ymin || x[1] > ymax) ) continue;
922 
923  // need to evaluate function to know about rejected points
924  // hugly but no other solutions
925  if (func) {
926  TF1::RejectPoint(false);
927  (*func)( x ); // evaluate using stored function parameters
928  if (TF1::RejectedPoint() ) continue;
929  }
930 
931  if (type == BinData::kNoError) {
932  dv.Add( x, gz[i] );
933  continue;
934  }
935 
936  double errorZ = gr->GetErrorZ(i);
937  if (!HFitInterface::AdjustError(fitOpt,errorZ) ) continue;
938 
939  if (type == BinData::kValueError) {
940  dv.Add( x, gz[i], errorZ );
941  }
942  else if (type == BinData::kCoordError) { // case use error in coordinates (x and y)
943  ex[0] = std::max(gr->GetErrorX(i), 0.);
944  ex[1] = std::max(gr->GetErrorY(i), 0.);
945  dv.Add( x, gz[i], ex, errorZ );
946  }
947  else
948  assert(0); // should not go here
949 
950 #ifdef DEBUG
951  std::cout << "Point " << i << " " << gx[i] << " " << gy[i] << " " << errorZ << std::endl;
952 #endif
953 
954  }
955 
956 #ifdef DEBUG
957  std::cout << "THFitInterface::FillData Graph2D FitData size is " << dv.Size() << std::endl;
958 #endif
959 
960 }
961 
962 
963 // confidence intervals
964 bool GetConfidenceIntervals(const TH1 * h1, const ROOT::Fit::FitResult & result, TGraphErrors * gr, double cl ) {
965  if (h1->GetDimension() != 1) {
966  Error("GetConfidenceIntervals","Invalid object used for storing confidence intervals");
967  return false;
968  }
969  // fill fit data sets with points to estimate cl.
970  BinData d;
971  FillData(d,h1,0);
972  gr->Set(d.NPoints() );
973  double * ci = gr->GetEY(); // make CL values error of the graph
974  result.GetConfidenceIntervals(d,ci,cl);
975  // put function value as abscissa of the graph
976  for (unsigned int ipoint = 0; ipoint < d.NPoints(); ++ipoint) {
977  const double * x = d.Coords(ipoint);
979  gr->SetPoint(ipoint, x[0], (*func)(x) );
980  }
981  return true;
982 }
983 
984 
985 } // end namespace Fit
986 
987 } // end namespace ROOT
988 
Double_t GetBinError(const Int_t *idx) const
Definition: THnBase.h:159
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Int_t GetNcells() const
Definition: TH1.h:280
virtual Double_t GetErrorYhigh(Int_t bin) const
This function is called by GraphFitChisquare.
Definition: TGraph.cxx:1436
virtual void SetParameters(const Double_t *params)
Definition: TF1.h:588
float xmin
Definition: THbookFile.cxx:93
virtual Double_t * GetEX() const
Definition: TGraph.h:131
Bool_t IsBinUnderflow(Int_t bin, Int_t axis=0) const
Return true if the bin is underflow.
Definition: TH1.cxx:4773
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:444
virtual Double_t GetErrorZ(Int_t bin) const
This function is called by Graph2DFitChisquare.
Definition: TGraph2D.cxx:1019
virtual Double_t GetErrorY(Int_t bin) const
This function is called by GraphFitChisquare.
Definition: TGraph.cxx:1406
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Bool_t IsBinOverflow(Int_t bin, Int_t axis=0) const
Return true if the bin is overflow.
Definition: TH1.cxx:4741
virtual Long64_t GetNbins() const =0
void GetConfidenceIntervals(unsigned int n, unsigned int stride1, unsigned int stride2, const double *x, double *ci, double cl=0.95, bool norm=true) const
get confidence intervals for an array of n points x.
Definition: FitResult.cxx:560
ErrorType GetErrorType() const
retrieve the errortype
Definition: BinData.h:522
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:504
float ymin
Definition: THbookFile.cxx:93
virtual Double_t * GetEYlow() const
Definition: TGraph.h:136
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4639
Double_t GetBinContent(const Int_t *idx) const
Definition: THnBase.h:167
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition: TMultiGraph.h:35
virtual Double_t * GetEY() const
Definition: TGraph.h:132
virtual void GetBinXYZ(Int_t binglobal, Int_t &binx, Int_t &biny, Int_t &binz) const
Return binx, biny, binz corresponding to the global bin number globalbin see TH1::GetBin function abo...
Definition: TH1.cxx:4554
void ExamineRange(const TAxis *axis, std::pair< double, double > range, int &hxfirst, int &hxlast)
const IModelFunction * FittedFunction() const
fitting quantities
Definition: FitResult.h:149
void AddBinUpEdge(const double *xup)
add the bin width data, a pointer to an array with the bin upper edge information.
Definition: BinData.cxx:596
virtual Double_t GetErrorYlow(Int_t bin) const
This function is called by GraphFitChisquare.
Definition: TGraph.cxx:1446
bool GetConfidenceIntervals(const TH1 *h1, const ROOT::Fit::FitResult &r, TGraphErrors *gr, double cl=0.95)
compute confidence intervals at level cl for a fitted histogram h1 in a TGraphErrors gr ...
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:514
const double * Coords(unsigned int ipoint) const
return a pointer to the coordinates data for the given fit point
Definition: FitData.h:245
const double * GetPoint(unsigned int ipoint, double &value) const
retrieve at the same time a pointer to the coordinate data and the fit value More efficient than call...
Definition: BinData.h:347
virtual Int_t GetDimension() const
Definition: TH1.h:263
double sqrt(double)
Double_t GetXmin() const
Definition: TAxis.h:133
Double_t x[n]
Definition: legend1.C:17
void GetRange(unsigned int irange, unsigned int icoord, double &xmin, double &xmax) const
get the i-th range for given coordinate.
Definition: DataRange.h:103
virtual Double_t * GetEY() const
Definition: TGraph2D.h:122
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:464
void Initialize(unsigned int newPoints, unsigned int dim=1, ErrorType err=kValueError)
Definition: BinData.cxx:345
bool AdjustError(const DataOptions &option, double &error, double value=1)
virtual Int_t GetNdim() const
Definition: TF1.h:439
TH1F * h1
Definition: legend1.C:5
virtual Double_t * GetEZ() const
Definition: TGraph2D.h:123
unsigned int Size() const
return number of fit points
Definition: FitData.h:302
A doubly linked list.
Definition: TList.h:43
virtual Double_t GetErrorY(Int_t bin) const
This function is called by Graph2DFitChisquare.
Definition: TGraph2D.cxx:1009
void InitGaus(const ROOT::Fit::BinData &data, TF1 *f1)
compute initial parameter for gaussian function given the fit data Set the sigma limits for zero top ...
float ymax
Definition: THbookFile.cxx:93
virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
Set limits for parameter ipar.
Definition: TF1.cxx:3267
virtual Double_t GetErrorXlow(Int_t bin) const
This function is called by GraphFitChisquare.
Definition: TGraph.cxx:1426
void FillData(BinData &dv, const TH1 *hist, TF1 *func=0)
fill the data vector from a TH1.
TAxis * GetAxis(Int_t dim) const
Definition: THnBase.h:125
BinData::ErrorType GetDataType(const TGraph *gr, DataOptions &fitOpt)
DataOptions : simple structure holding the options on how the data are filled.
Definition: DataOptions.h:28
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:455
Class to manage histogram axis.
Definition: TAxis.h:30
void DoFillData(BinData &dv, const TGraph *gr, BinData::ErrorType type, TF1 *func)
unsigned int Size(unsigned int icoord=0) const
return range size for coordinate icoord (starts from zero) Size == 0 indicates no range is present [-...
Definition: DataRange.h:70
void GetBinDataIntegral(BinData &) const
Definition: SparseData.cxx:320
const DataOptions & Opt() const
access to options
Definition: FitData.h:318
Int_t GetN() const
Definition: TGraph.h:122
static void RejectPoint(Bool_t reject=kTRUE)
Static function to set the global flag to reject points the fgRejectPoint global flag is tested by al...
Definition: TF1.cxx:3459
TAxis * GetYaxis()
Definition: TH1.h:301
Double_t * GetEY() const
Definition: TGraphErrors.h:67
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition: BinData.h:53
float xmax
Definition: THbookFile.cxx:93
void InitExpo(const ROOT::Fit::BinData &data, TF1 *f1)
compute initial parameter for an exponential function given the fit data Set the constant and slope a...
void Warning(const char *location, const char *msgfmt,...)
TGraphErrors * gr
Definition: legend1.C:25
virtual Double_t * GetEX() const
Definition: TGraph2D.h:121
Double_t * GetY() const
Definition: TGraph2D.h:119
Double_t * GetX() const
Definition: TGraph.h:129
class containg the result of the fit and all the related information (fitted parameter values...
Definition: FitResult.h:48
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition: DataRange.h:34
void Init2DGaus(const ROOT::Fit::BinData &data, TF1 *f1)
compute initial parameter for 2D gaussian function given the fit data Set the sigma limits for zero t...
void Add(double x, double y)
add one dim data with only coordinate and values
Definition: BinData.cxx:418
TFitResultPtr Fit(FitObject *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
Definition: HFitImpl.cxx:134
int type
Definition: TGX11.cxx:120
unsigned long long ULong64_t
Definition: RtypesCore.h:70
Double_t y[n]
Definition: legend1.C:17
double func(double *x, double *p)
Definition: stressTF1.cxx:213
Double_t ey[n]
Definition: legend1.C:17
Double_t * GetZ() const
Definition: TGraph2D.h:120
The TH1 histogram class.
Definition: TH1.h:56
virtual Double_t GetErrorX(Int_t bin) const
This function is called by Graph2DFitChisquare.
Definition: TGraph2D.cxx:999
Int_t GetNdimensions() const
Definition: THnBase.h:135
TAxis * GetZaxis()
Definition: TH1.h:302
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:405
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
virtual Bool_t IsInside(const Double_t *x) const
return kTRUE if the point is inside the function range
Definition: TF1.h:542
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition: TAxis.cxx:526
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Set x and y values for point number i.
Definition: TGraph.cxx:2156
TList * GetListOfGraphs() const
Definition: TMultiGraph.h:69
Double_t * GetY() const
Definition: TGraph.h:130
static Bool_t RejectedPoint()
See TF1::RejectPoint above.
Definition: TF1.cxx:3468
bool IsPointOutOfRange(const TF1 *func, const double *x)
virtual void GetRange(Double_t *xmin, Double_t *xmax) const
Return range of a generic N-D function.
Definition: TF1.cxx:2012
1-Dim function class
Definition: TF1.h:150
A Graph is a graphics object made of two arrays X and Y with npoints each.
Definition: TGraph.h:41
Int_t GetN() const
Definition: TGraph2D.h:117
TF1 * f1
Definition: legend1.C:11
A TGraphErrors is a TGraph with error bars.
Definition: TGraphErrors.h:26
Multidimensional histogram base.
Definition: THnBase.h:43
double result[121]
virtual void SetParameter(Int_t param, Double_t value)
Definition: TF1.h:578
unsigned int NPoints() const
return number of fit points
Definition: FitData.h:294
unsigned int NDim() const
return coordinate data dimension
Definition: FitData.h:310
const DataRange & Range() const
access to range
Definition: FitData.h:330
virtual Double_t * GetEYhigh() const
Definition: TGraph.h:135
const Bool_t kIterBackward
Definition: TCollection.h:38
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition: TGraph2D.h:40
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:364
virtual void Set(Int_t n)
Set number of points in the graph Existing coordinates are preserved New coordinates above fNpoints a...
Definition: TGraph.cxx:2105
Double_t GetXmax() const
Definition: TAxis.h:134
Double_t ex[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
virtual Double_t GetErrorXhigh(Int_t bin) const
This function is called by GraphFitChisquare.
Definition: TGraph.cxx:1416
void Add(std::vector< double > &min, std::vector< double > &max, const double content, const double error=1.0)
Definition: SparseData.cxx:231
double log(double)
TAxis * GetXaxis()
Definition: TH1.h:300
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
Double_t * GetX() const
Definition: TGraph2D.h:118
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8175