Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TProfile.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Rene Brun 29/09/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TProfile.h"
13 #include "TBuffer.h"
14 #include "TMath.h"
15 #include "TF1.h"
16 #include "THLimitsFinder.h"
17 #include "Riostream.h"
18 #include "TVirtualPad.h"
19 #include "TError.h"
20 #include "TClass.h"
21 
22 #include "TProfileHelper.h"
23 
24 Bool_t TProfile::fgApproximate = kFALSE;
25 
26 ClassImp(TProfile);
27 
28 /** \class TProfile
29  \ingroup Hist
30  Profile Histogram.
31  Profile histograms are used to display the mean
32  value of Y and its error for each bin in X. The displayed error is by default the
33  standard error on the mean (i.e. the standard deviation divided by the sqrt(n) )
34  Profile histograms are in many cases an
35  elegant replacement of two-dimensional histograms : the inter-relation of two
36  measured quantities X and Y can always be visualized by a two-dimensional
37  histogram or scatter-plot; its representation on the line-printer is not particularly
38  satisfactory, except for sparse data. If Y is an unknown (but single-valued)
39  approximate function of X, this function is displayed by a profile histogram with
40  much better precision than by a scatter-plot.
41 
42  The following formulae show the cumulated contents (capital letters) and the values
43  displayed by the printing or plotting routines (small letters) of the elements for bin J.
44 
45  2
46  H(J) = sum Y E(J) = sum Y
47  l(J) = sum l L(J) = sum l
48  h(J) = H(J)/L(J) mean of Y,
49  s(J) = sqrt(E(J)/L(J)- h(J)**2) standard deviation of Y (e.g. RMS)
50  e(J) = s(J)/sqrt(L(J)) standard error on the mean
51 
52  The displayed bin content for bin J of a TProfile is always h(J). The corresponding bin error is by default
53  e(J). In case the option "s" is used (in the constructor or by calling TProfile::BuildOptions)
54  the displayed error is s(J)
55 
56  In the special case where s(J) is zero (eg, case of 1 entry only in one bin)
57  the bin error e(J) is computed from the average of the s(J) for all bins if
58  the static function TProfile::Approximate has been called.
59  This simple/crude approximation was suggested in order to keep the bin
60  during a fit operation. But note that this approximation is not the default behaviour.
61  See also TProfile::BuildOptions for other error options and more detailed explanations
62 
63  Example of a profile histogram with its graphics output
64 ~~~{.cpp}
65 {
66  auto c1 = new TCanvas("c1","Profile histogram example",200,10,700,500);
67  auto hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
68  Float_t px, py, pz;
69  for ( Int_t i=0; i<25000; i++) {
70  gRandom->Rannor(px,py);
71  pz = px*px + py*py;
72  hprof->Fill(px,pz,1);
73  }
74  hprof->Draw();
75 }
76 ~~~
77 */
78 
79 ////////////////////////////////////////////////////////////////////////////////
80 /// Default constructor for Profile histograms
81 
82 TProfile::TProfile() : TH1D()
83 {
84  BuildOptions(0,0,"");
85 }
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Default destructor for Profile histograms
89 
90 TProfile::~TProfile()
91 {
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// Normal Constructor for Profile histograms.
96 ///
97 /// The first five parameters are similar to TH1D::TH1D.
98 /// All values of y are accepted at filling time.
99 /// To fill a profile histogram, one must use TProfile::Fill function.
100 ///
101 /// Note that when filling the profile histogram the function Fill
102 /// checks if the variable y is between fYmin and fYmax.
103 /// If a minimum or maximum value is set for the Y scale before filling,
104 /// then all values below ymin or above ymax will be discarded.
105 /// Setting the minimum or maximum value for the Y scale before filling
106 /// has the same effect as calling the special TProfile constructor below
107 /// where ymin and ymax are specified.
108 ///
109 /// H(J) is printed as the channel contents. The errors displayed are s(J) if CHOPT='S'
110 /// (spread option), or e(J) if CHOPT=' ' (error on mean).
111 ///
112 /// See TProfile::BuildOptions for explanation of parameters
113 ///
114 /// see also comments in the TH1 base class constructors
115 
116 TProfile::TProfile(const char *name,const char *title,Int_t nbins,Double_t xlow,Double_t xup,Option_t *option)
117 : TH1D(name,title,nbins,xlow,xup)
118 {
119  BuildOptions(0,0,option);
120 }
121 
122 ////////////////////////////////////////////////////////////////////////////////
123 /// Constructor for Profile histograms with variable bin size.
124 ///
125 /// See TProfile::BuildOptions for more explanations on errors
126 /// see also comments in the TH1 base class constructors
127 
128 TProfile::TProfile(const char *name,const char *title,Int_t nbins,const Float_t *xbins,Option_t *option)
129 : TH1D(name,title,nbins,xbins)
130 {
131  BuildOptions(0,0,option);
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Constructor for Profile histograms with variable bin size.
136 ///
137 /// See TProfile::BuildOptions for more explanations on errors
138 /// see also comments in the TH1 base class constructors
139 
140 TProfile::TProfile(const char *name,const char *title,Int_t nbins,const Double_t *xbins,Option_t *option)
141 : TH1D(name,title,nbins,xbins)
142 {
143  BuildOptions(0,0,option);
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Constructor for Profile histograms with variable bin size.
148 /// See TProfile::BuildOptions for more explanations on errors
149 ///
150 /// see also comments in the TH1 base class constructors
151 
152 TProfile::TProfile(const char *name,const char *title,Int_t nbins,const Double_t *xbins,Double_t ylow,Double_t yup,Option_t *option)
153 : TH1D(name,title,nbins,xbins)
154 {
155  BuildOptions(ylow,yup,option);
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Constructor for Profile histograms with range in y.
160 ///
161 /// The first five parameters are similar to TH1D::TH1D.
162 /// Only the values of Y between ylow and yup will be considered at filling time.
163 /// ylow and yup will also be the maximum and minimum values
164 /// on the y scale when drawing the profile.
165 ///
166 /// See TProfile::BuildOptions for more explanations on errors
167 ///
168 /// see also comments in the TH1 base class constructors
169 
170 TProfile::TProfile(const char *name,const char *title,Int_t nbins,Double_t xlow,Double_t xup,Double_t ylow,Double_t yup,Option_t *option)
171 : TH1D(name,title,nbins,xlow,xup)
172 {
173  BuildOptions(ylow,yup,option);
174 }
175 
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Set Profile histogram structure and options.
179 ///
180 /// \param[in] ymin minimum value allowed for y
181 /// \param[in] ymax maximum value allowed for y
182 /// if (ymin = ymax = 0) there are no limits on the allowed y values (ymin = -inf, ymax = +inf)
183 /// \param[in] option this is the option for the computation of the y error of the profile ( TProfile::GetBinError )
184 /// possible values for the options are:
185 /// - ' ' (Default) the bin errors are the standard error on the mean of Y = S(Y)/SQRT(N)
186 /// where S(Y) is the standard deviation (RMS) of the Y data in the bin
187 /// and N is the number of bin entries (from TProfile::GetBinEntries(ibin) )
188 /// (i.e the errors are the standard error on the bin content of the profile)
189 /// - 's' Errors are the standard deviation of Y, S(Y)
190 /// - 'i' Errors are S(Y)/SQRT(N) (standard error on the mean as in the default)
191 /// The only difference is only when the standard deviation in Y is zero.
192 /// In this case the error a standard deviation = 1/SQRT(12) is assumed and the error is
193 /// 1./SQRT(12*N).
194 /// This approximation assumes that the Y values are integer (e.g. ADC counts)
195 /// and have an implicit uncertainty of y +/- 0.5. With the assumption that the probability that y
196 /// takes any value between y-0.5 and y+0.5 is uniform, its standard error is 1/SQRT(12)
197 /// - 'g' Errors are 1./SQRT(W) where W is the sum of the weights for the bin J
198 /// W is obtained as from TProfile::GetBinEntries(ibin)
199 /// This errors corresponds to the standard deviation of weighted mean where each
200 /// measurement Y is uncorrelated and has an error sigma, which is expressed in the
201 /// weight used to fill the Profile: w = 1/sigma^2
202 /// The resulting error in TProfile is then 1./SQRT( Sum(1./sigma^2) )
203 ///
204 /// In the case of Profile filled weights and with TProfile::Sumw2() called,
205 /// STD(Y) is the standard deviation of the weighted sample Y and N is in this case the
206 /// number of effective entries (TProfile::GetBinEffectiveEntries(ibin) )
207 ///
208 /// If a bin has N data points all with the same value Y (especially
209 /// possible when dealing with integers), the spread in Y for that bin
210 /// is zero, and the uncertainty assigned is also zero, and the bin is
211 /// ignored in making subsequent fits.
212 /// To avoid this problem one can use an approximation for the standard deviation S(Y),
213 /// by using the average of all the S(Y) of the other Profile bins. To use this approximation
214 /// one must call before TProfile::Approximate
215 /// This approximation applies only for the default and the 's' options
216 
217 void TProfile::BuildOptions(Double_t ymin, Double_t ymax, Option_t *option)
218 {
219  SetErrorOption(option);
220 
221  // create extra profile data structure (bin entries/ y^2 and sum of weight square)
222  TProfileHelper::BuildArray(this);
223 
224  fYmin = ymin;
225  fYmax = ymax;
226  fScaling = kFALSE;
227  fTsumwy = fTsumwy2 = 0;
228 
229 }
230 
231 ////////////////////////////////////////////////////////////////////////////////
232 /// Copy constructor.
233 
234 TProfile::TProfile(const TProfile &profile) : TH1D()
235 {
236  ((TProfile&)profile).Copy(*this);
237 }
238 
239 TProfile &TProfile::operator=(const TProfile &profile)
240 {
241  ((TProfile &)profile).Copy(*this);
242  return *this;
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Performs the operation: this = this + c1*f1
247 
248 Bool_t TProfile::Add(TF1 *, Double_t, Option_t * )
249 {
250  Error("Add","Function not implemented for TProfile");
251  return kFALSE;
252 }
253 
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Performs the operation: this = this + c1*h1
257 
258 Bool_t TProfile::Add(const TH1 *h1, Double_t c1)
259 {
260  if (!h1) {
261  Error("Add","Attempt to add a non-existing profile");
262  return kFALSE;
263  }
264  if (!h1->InheritsFrom(TProfile::Class())) {
265  Error("Add","Attempt to add a non-profile object");
266  return kFALSE;
267  }
268 
269  return TProfileHelper::Add(this, this, h1, 1, c1);
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// Replace contents of this profile by the addition of h1 and h2.
274 ///
275 /// `this = c1*h1 + c2*h2`
276 ///
277 /// c1 and c2 are considered as weights applied to the two summed profiles.
278 /// The operation acts therefore like merging the two profiles with a weight c1 and c2
279 
280 Bool_t TProfile::Add(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2)
281 {
282  if (!h1 || !h2) {
283  Error("Add","Attempt to add a non-existing profile");
284  return kFALSE;
285  }
286  if (!h1->InheritsFrom(TProfile::Class())) {
287  Error("Add","Attempt to add a non-profile object");
288  return kFALSE;
289  }
290  if (!h2->InheritsFrom(TProfile::Class())) {
291  Error("Add","Attempt to add a non-profile object");
292  return kFALSE;
293  }
294  return TProfileHelper::Add(this, h1, h2, c1, c2);
295 }
296 
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Static function to set the fgApproximate flag.
300 ///
301 ///When the flag is true, the function GetBinError
302 /// will approximate the bin error with the average profile error on all bins
303 /// in the following situation only
304 ///
305 /// - the number of bins in the profile is less than 1002
306 /// - the bin number of entries is small ( <5)
307 /// - the estimated bin error is extremely small compared to the bin content
308 /// (see TProfile::GetBinError)
309 
310 void TProfile::Approximate(Bool_t approx)
311 {
312  fgApproximate = approx;
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// Fill histogram with all entries in the buffer.
317 ///
318 /// - action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
319 /// - action = 0 histogram is filled from the buffer
320 /// - action = 1 histogram is filled and buffer is deleted
321 /// The buffer is automatically deleted when the number of entries
322 /// in the buffer is greater than the number of entries in the histogram
323 
324 Int_t TProfile::BufferEmpty(Int_t action)
325 {
326  // do we need to compute the bin size?
327  if (!fBuffer) return 0;
328  Int_t nbentries = (Int_t)fBuffer[0];
329  if (!nbentries) return 0;
330  Double_t *buffer = fBuffer;
331  if (nbentries < 0) {
332  if (action == 0) return 0;
333  nbentries = -nbentries;
334  fBuffer=0;
335  Reset("ICES"); // reset without deleting the functions
336  fBuffer = buffer;
337  }
338  if (CanExtendAllAxes() || fXaxis.GetXmax() <= fXaxis.GetXmin()) {
339  //find min, max of entries in buffer
340  Double_t xmin = fBuffer[2];
341  Double_t xmax = xmin;
342  for (Int_t i=1;i<nbentries;i++) {
343  Double_t x = fBuffer[3*i+2];
344  if (x < xmin) xmin = x;
345  if (x > xmax) xmax = x;
346  }
347  if (fXaxis.GetXmax() <= fXaxis.GetXmin()) {
348  THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this,xmin,xmax);
349  } else {
350  fBuffer = 0;
351  Int_t keep = fBufferSize; fBufferSize = 0;
352  if (xmin < fXaxis.GetXmin()) ExtendAxis(xmin,&fXaxis);
353  if (xmax >= fXaxis.GetXmax()) ExtendAxis(xmax,&fXaxis);
354  fBuffer = buffer;
355  fBufferSize = keep;
356  }
357  }
358 
359  fBuffer = 0;
360 
361  for (Int_t i=0;i<nbentries;i++) {
362  Fill(buffer[3*i+2],buffer[3*i+3],buffer[3*i+1]);
363  }
364  fBuffer = buffer;
365 
366  if (action > 0) { delete [] fBuffer; fBuffer = 0; fBufferSize = 0;}
367  else {
368  if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
369  else fBuffer[0] = 0;
370  }
371  return nbentries;
372 }
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 /// accumulate arguments in buffer. When buffer is full, empty the buffer.
376 ///
377 /// - fBuffer[0] = number of entries in buffer
378 /// - fBuffer[1] = w of first entry
379 /// - fBuffer[2] = x of first entry
380 /// - fBuffer[3] = y of first entry
381 
382 Int_t TProfile::BufferFill(Double_t x, Double_t y, Double_t w)
383 {
384  if (!fBuffer) return -2;
385  Int_t nbentries = (Int_t)fBuffer[0];
386  if (nbentries < 0) {
387  nbentries = -nbentries;
388  fBuffer[0] = nbentries;
389  if (fEntries > 0) {
390  Double_t *buffer = fBuffer; fBuffer=0;
391  Reset("ICES"); // reset without deleting the functions
392  fBuffer = buffer;
393  }
394  }
395  if (3*nbentries+3 >= fBufferSize) {
396  BufferEmpty(1);
397  return Fill(x,y,w);
398  }
399  fBuffer[3*nbentries+1] = w;
400  fBuffer[3*nbentries+2] = x;
401  fBuffer[3*nbentries+3] = y;
402  fBuffer[0] += 1;
403  return -2;
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Copy a Profile histogram to a new profile histogram.
408 
409 void TProfile::Copy(TObject &obj) const
410 {
411  try {
412  TProfile & pobj = dynamic_cast<TProfile&>(obj);
413  TH1D::Copy(pobj);
414  fBinEntries.Copy(pobj.fBinEntries);
415  fBinSumw2.Copy(pobj.fBinSumw2);
416  for (int bin=0;bin<fNcells;bin++) {
417  pobj.fArray[bin] = fArray[bin];
418  pobj.fSumw2.fArray[bin] = fSumw2.fArray[bin];
419  }
420 
421  pobj.fYmin = fYmin;
422  pobj.fYmax = fYmax;
423  pobj.fScaling = fScaling;
424  pobj.fErrorMode = fErrorMode;
425  pobj.fTsumwy = fTsumwy;
426  pobj.fTsumwy2 = fTsumwy2;
427 
428  } catch(...) {
429  Fatal("Copy","Cannot copy a TProfile in a %s",obj.IsA()->GetName());
430  }
431 
432 }
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Performs the operation: `this = this/(c1*f1)`.
436 ///
437 /// This function is not implemented for the TProfile
438 
439 Bool_t TProfile::Divide(TF1 *, Double_t )
440 {
441  Error("Divide","Function not implemented for TProfile");
442  return kFALSE;
443 }
444 
445 ////////////////////////////////////////////////////////////////////////////////
446 /// Divide this profile by h1.
447 ///
448 /// `this = this/h1`
449 ///
450 /// This function accepts to divide a TProfile by a histogram
451 ///
452 /// The function return kFALSE if the divide operation failed
453 
454 Bool_t TProfile::Divide(const TH1 *h1)
455 {
456  if (!h1) {
457  Error("Divide","Attempt to divide a non-existing profile");
458  return kFALSE;
459  }
460  if (!h1->InheritsFrom(TH1::Class())) {
461  Error("Divide","Attempt to divide by a non-profile or non-histogram object");
462  return kFALSE;
463  }
464  TProfile *p1 = (TProfile*)h1;
465 
466  // delete buffer if it is there since it will become invalid
467  if (fBuffer) BufferEmpty(1);
468 
469 
470  Int_t nbinsx = GetNbinsX();
471  //- Check profile compatibility
472  if (nbinsx != p1->GetNbinsX()) {
473  Error("Divide","Attempt to divide profiles with different number of bins");
474  return kFALSE;
475  }
476 
477  //- Reset statistics
478  fEntries = fTsumw = fTsumw2 = fTsumwx = fTsumwx2 = fTsumwy = fTsumwy2 = 0;
479 
480  //- Loop on bins (including underflows/overflows)
481  Int_t bin;
482  Double_t *cu1=0, *er1=0, *en1=0;
483  Double_t e0,e1,c12;
484  if (h1->InheritsFrom(TProfile::Class())) {
485  cu1 = p1->GetW();
486  er1 = p1->GetW2();
487  en1 = p1->GetB();
488  }
489  Double_t c0,c1,w,z,x;
490  for (bin=0;bin<=nbinsx+1;bin++) {
491  c0 = fArray[bin];
492  if (cu1) c1 = cu1[bin];
493  else c1 = h1->GetBinContent(bin);
494  if (c1) w = c0/c1;
495  else w = 0;
496  fArray[bin] = w;
497  z = TMath::Abs(w);
498  x = fXaxis.GetBinCenter(bin);
499  fEntries++;
500  fTsumw += z;
501  fTsumw2 += z*z;
502  fTsumwx += z*x;
503  fTsumwx2 += z*x*x;
504  fTsumwy += z*c1;
505  fTsumwx2 += z*c1*c1;
506  e0 = fSumw2.fArray[bin];
507  if (er1) e1 = er1[bin];
508  else {e1 = h1->GetBinError(bin); e1*=e1;}
509  c12= c1*c1;
510  if (!c1) fSumw2.fArray[bin] = 0;
511  else fSumw2.fArray[bin] = (e0*c1*c1 + e1*c0*c0)/(c12*c12);
512  if (!en1) continue;
513  if (!en1[bin]) fBinEntries.fArray[bin] = 0;
514  else fBinEntries.fArray[bin] /= en1[bin];
515  }
516  // maintaining the correct sum of weights square is not supported when dividing
517  // bin error resulting from division of profile needs to be checked
518  if (fBinSumw2.fN) {
519  Warning("Divide","Cannot preserve during the division of profiles the sum of bin weight square");
520  fBinSumw2 = TArrayD();
521  }
522 
523  return kTRUE;
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Replace contents of this profile by the division of h1 by h2.
528 ///
529 /// `this = c1*h1/(c2*h2)`
530 ///
531 /// The function return kFALSE if the divide operation failed
532 
533 Bool_t TProfile::Divide(const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2, Option_t *option)
534 {
535  TString opt = option;
536  opt.ToLower();
537  Bool_t binomial = kFALSE;
538  if (opt.Contains("b")) binomial = kTRUE;
539  if (!h1 || !h2) {
540  Error("Divide","Attempt to divide a non-existing profile");
541  return kFALSE;
542  }
543  if (!h1->InheritsFrom(TProfile::Class())) {
544  Error("Divide","Attempt to divide a non-profile object");
545  return kFALSE;
546  }
547  TProfile *p1 = (TProfile*)h1;
548  if (!h2->InheritsFrom(TProfile::Class())) {
549  Error("Divide","Attempt to divide by a non-profile object");
550  return kFALSE;
551  }
552  TProfile *p2 = (TProfile*)h2;
553 
554  // delete buffer if it is there since it will become invalid
555  if (fBuffer) BufferEmpty(1);
556 
557  Int_t nbinsx = GetNbinsX();
558  //- Check histogram compatibility
559  if (nbinsx != p1->GetNbinsX() || nbinsx != p2->GetNbinsX()) {
560  Error("Divide","Attempt to divide profiles with different number of bins");
561  return kFALSE;
562  }
563  if (!c2) {
564  Error("Divide","Coefficient of dividing profile cannot be zero");
565  return kFALSE;
566  }
567 
568  //THE ALGORITHM COMPUTING THE ERRORS IS WRONG. HELP REQUIRED
569  printf("WARNING!!: The algorithm in TProfile::Divide computing the errors is not accurate\n");
570  printf(" Instead of Divide(TProfile *h1, TProfile *h2, do:\n");
571  printf(" TH1D *p1 = h1->ProjectionX();\n");
572  printf(" TH1D *p2 = h2->ProjectionX();\n");
573  printf(" p1->Divide(p2);\n");
574 
575  //- Reset statistics
576  fEntries = fTsumw = fTsumw2 = fTsumwx = fTsumwx2 = 0;
577 
578  //- Loop on bins (including underflows/overflows)
579  Int_t bin;
580  Double_t *cu1 = p1->GetW();
581  Double_t *cu2 = p2->GetW();
582  Double_t *er1 = p1->GetW2();
583  Double_t *er2 = p2->GetW2();
584  Double_t *en1 = p1->GetB();
585  Double_t *en2 = p2->GetB();
586  Double_t b1,b2,w,z,x,ac1,ac2;
587  //d1 = c1*c1;
588  //d2 = c2*c2;
589  ac1 = TMath::Abs(c1);
590  ac2 = TMath::Abs(c2);
591  for (bin=0;bin<=nbinsx+1;bin++) {
592  b1 = cu1[bin];
593  b2 = cu2[bin];
594  if (b2) w = c1*b1/(c2*b2);
595  else w = 0;
596  fArray[bin] = w;
597  z = TMath::Abs(w);
598  x = fXaxis.GetBinCenter(bin);
599  fEntries++;
600  fTsumw += z;
601  fTsumw2 += z*z;
602  fTsumwx += z*x;
603  fTsumwx2 += z*x*x;
604  //fTsumwy += z*x;
605  //fTsumwy2 += z*x*x;
606  Double_t e1 = er1[bin];
607  Double_t e2 = er2[bin];
608  //Double_t b22= b2*b2*d2;
609  Double_t b22= b2*b2*TMath::Abs(c2);
610  if (!b2) fSumw2.fArray[bin] = 0;
611  else {
612  if (binomial) {
613  fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/b2);
614  } else {
615  //fSumw2.fArray[bin] = d1*d2*(e1*b2*b2 + e2*b1*b1)/(b22*b22);
616  fSumw2.fArray[bin] = ac1*ac2*(e1*b2*b2 + e2*b1*b1)/(b22*b22);
617  }
618  }
619  if (en2[bin]) fBinEntries.fArray[bin] = en1[bin]/en2[bin];
620  else fBinEntries.fArray[bin] = 0;
621  }
622 
623  // maintaining the correct sum of weights square is not supported when dividing
624  // bin error resulting from division of profile needs to be checked
625  if (fBinSumw2.fN) {
626  Warning("Divide","Cannot preserve during the division of profiles the sum of bin weight square");
627  fBinSumw2 = TArrayD();
628  }
629 
630  return kTRUE;
631 }
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// Fill a Profile histogram (no weights).
635 
636 Int_t TProfile::Fill(Double_t x, Double_t y)
637 {
638  if (fBuffer) return BufferFill(x,y,1);
639 
640  Int_t bin;
641  if (fYmin != fYmax) {
642  if (y <fYmin || y> fYmax || TMath::IsNaN(y) ) return -1;
643  }
644 
645  fEntries++;
646  bin =fXaxis.FindBin(x);
647  AddBinContent(bin, y);
648  fSumw2.fArray[bin] += (Double_t)y*y;
649  fBinEntries.fArray[bin] += 1;
650  if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
651  if (bin == 0 || bin > fXaxis.GetNbins()) {
652  if (!GetStatOverflowsBehaviour()) return -1;
653  }
654  fTsumw++;
655  fTsumw2++;
656  fTsumwx += x;
657  fTsumwx2 += x*x;
658  fTsumwy += y;
659  fTsumwy2 += y*y;
660  return bin;
661 }
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 /// Fill a Profile histogram (no weights).
665 
666 Int_t TProfile::Fill(const char *namex, Double_t y)
667 {
668  Int_t bin;
669  if (fYmin != fYmax) {
670  if (y <fYmin || y> fYmax || TMath::IsNaN(y) ) return -1;
671  }
672 
673  fEntries++;
674  bin =fXaxis.FindBin(namex);
675  AddBinContent(bin, y);
676  fSumw2.fArray[bin] += (Double_t)y*y;
677  fBinEntries.fArray[bin] += 1;
678  if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
679  if (bin == 0 || bin > fXaxis.GetNbins()) {
680  if (!GetStatOverflowsBehaviour()) return -1;
681  }
682  Double_t x = fXaxis.GetBinCenter(bin);
683  fTsumw++;
684  fTsumw2++;
685  fTsumwx += x;
686  fTsumwx2 += x*x;
687  fTsumwy += y;
688  fTsumwy2 += y*y;
689  return bin;
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 /// Fill a Profile histogram with weights.
694 
695 Int_t TProfile::Fill(Double_t x, Double_t y, Double_t w)
696 {
697  if (fBuffer) return BufferFill(x,y,w);
698 
699  Int_t bin;
700  if (fYmin != fYmax) {
701  if (y <fYmin || y> fYmax || TMath::IsNaN(y) ) return -1;
702  }
703 
704  Double_t u= w;
705  fEntries++;
706  bin =fXaxis.FindBin(x);
707  AddBinContent(bin, u*y);
708  fSumw2.fArray[bin] += u*y*y;
709  if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before accumulating the entries
710  if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u*u;
711  fBinEntries.fArray[bin] += u;
712  if (bin == 0 || bin > fXaxis.GetNbins()) {
713  if (!GetStatOverflowsBehaviour()) return -1;
714  }
715  fTsumw += u;
716  fTsumw2 += u*u;
717  fTsumwx += u*x;
718  fTsumwx2 += u*x*x;
719  fTsumwy += u*y;
720  fTsumwy2 += u*y*y;
721  return bin;
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////////
725 /// Fill a Profile histogram with weights.
726 
727 Int_t TProfile::Fill(const char *namex, Double_t y, Double_t w)
728 {
729  Int_t bin;
730 
731  if (fYmin != fYmax) {
732  if (y <fYmin || y> fYmax || TMath::IsNaN(y) ) return -1;
733  }
734 
735  Double_t u= w; // (w > 0 ? w : -w);
736  fEntries++;
737  bin =fXaxis.FindBin(namex);
738  AddBinContent(bin, u*y);
739  fSumw2.fArray[bin] += u*y*y;
740  if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before accumulating the entries
741  if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u*u;
742  fBinEntries.fArray[bin] += u;
743  if (bin == 0 || bin > fXaxis.GetNbins()) {
744  if (!GetStatOverflowsBehaviour()) return -1;
745  }
746  Double_t x = fXaxis.GetBinCenter(bin);
747  fTsumw += u;
748  fTsumw2 += u*u;
749  fTsumwx += u*x;
750  fTsumwx2 += u*x*x;
751  fTsumwy += u*y;
752  fTsumwy2 += u*y*y;
753  return bin;
754 }
755 
756 ////////////////////////////////////////////////////////////////////////////////
757 /// Fill a Profile histogram with weights.
758 
759 void TProfile::FillN(Int_t ntimes, const Double_t *x, const Double_t *y, const Double_t *w, Int_t stride)
760 {
761  Int_t bin,i;
762  ntimes *= stride;
763  Int_t ifirst = 0;
764  //If a buffer is activated, fill buffer
765  // (note that this function must not be called from TH2::BufferEmpty)
766  if (fBuffer) {
767  for (i=0;i<ntimes;i+=stride) {
768  if (!fBuffer) break; // buffer can be deleted in BufferFill when is empty
769  if (w) BufferFill(x[i],y[i],w[i]);
770  else BufferFill(x[i], y[i], 1.);
771  }
772  // fill the remaining entries if the buffer has been deleted
773  if (i < ntimes && fBuffer==0)
774  ifirst = i; // start from i
775  else
776  return;
777  }
778 
779  for (i=ifirst;i<ntimes;i+=stride) {
780  if (fYmin != fYmax) {
781  if (y[i] <fYmin || y[i]> fYmax || TMath::IsNaN(y[i])) continue;
782  }
783 
784  Double_t u = (w) ? w[i] : 1; // (w[i] > 0 ? w[i] : -w[i]);
785  fEntries++;
786  bin =fXaxis.FindBin(x[i]);
787  AddBinContent(bin, u*y[i]);
788  fSumw2.fArray[bin] += u*y[i]*y[i];
789  if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before accumulating the entries
790  if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u*u;
791  fBinEntries.fArray[bin] += u;
792  if (bin == 0 || bin > fXaxis.GetNbins()) {
793  if (!GetStatOverflowsBehaviour()) continue;
794  }
795  fTsumw += u;
796  fTsumw2 += u*u;
797  fTsumwx += u*x[i];
798  fTsumwx2 += u*x[i]*x[i];
799  fTsumwy += u*y[i];
800  fTsumwy2 += u*y[i]*y[i];
801  }
802 }
803 
804 ////////////////////////////////////////////////////////////////////////////////
805 /// Return bin content of a Profile histogram.
806 
807 Double_t TProfile::GetBinContent(Int_t bin) const
808 {
809  if (fBuffer) ((TProfile*)this)->BufferEmpty();
810 
811  if (bin < 0 || bin >= fNcells) return 0;
812  if (fBinEntries.fArray[bin] == 0) return 0;
813  if (!fArray) return 0;
814  return fArray[bin]/fBinEntries.fArray[bin];
815 }
816 
817 ////////////////////////////////////////////////////////////////////////////////
818 /// Return bin entries of a Profile histogram.
819 
820 Double_t TProfile::GetBinEntries(Int_t bin) const
821 {
822  if (fBuffer) ((TProfile*)this)->BufferEmpty();
823 
824  if (bin < 0 || bin >= fNcells) return 0;
825  return fBinEntries.fArray[bin];
826 }
827 
828 ////////////////////////////////////////////////////////////////////////////////
829 /// Return bin effective entries for a weighted filled Profile histogram.
830 /// In case of an unweighted profile, it is equivalent to the number of entries per bin
831 /// The effective entries is defined as the square of the sum of the weights divided by the
832 /// sum of the weights square.
833 /// TProfile::Sumw2() must be called before filling the profile with weights.
834 /// Only by calling this method the sum of the square of the weights per bin is stored.
835 
836 Double_t TProfile::GetBinEffectiveEntries(Int_t bin) const
837 {
838  return TProfileHelper::GetBinEffectiveEntries((TProfile*)this, bin);
839 }
840 
841 ////////////////////////////////////////////////////////////////////////////////
842 /// Return bin error of a Profile histogram
843 ///
844 /// Computing errors: A moving field
845 ///
846 /// The computation of errors for a TProfile has evolved with the versions
847 /// of ROOT. The difficulty is in computing errors for bins with low statistics.
848 ///
849 /// - prior to version 3.00, we had no special treatment of low statistic bins.
850 /// As a result, these bins had huge errors. The reason is that the
851 /// expression eprim2 is very close to 0 (rounding problems) or 0.
852 /// - in version 3.00 (18 Dec 2000), the algorithm is protected for values of
853 /// eprim2 very small and the bin errors set to the average bin errors, following
854 /// recommendations from a group of users.
855 /// - in version 3.01 (19 Apr 2001), it is realized that the algorithm above
856 /// should be applied only to low statistic bins.
857 /// - in version 3.02 (26 Sep 2001), the same group of users recommend instead
858 /// to take two times the average error on all bins for these low
859 /// statistics bins giving a very small value for eprim2.
860 /// - in version 3.04 (Nov 2002), the algorithm is modified/protected for the case
861 /// when a TProfile is projected (ProjectionX). The previous algorithm
862 /// generated a N^2 problem when projecting a TProfile with a large number of
863 /// bins (eg 100000).
864 /// - in version 3.05/06, a new static function TProfile::Approximate
865 /// is introduced to enable or disable (default) the approximation.
866 ///
867 /// Ideas for improvements of this algorithm are welcome. No suggestions
868 /// received since our call for advice to roottalk in Jul 2002.
869 /// see for instance: http://root.cern.ch/root/roottalk/roottalk02/2916.html
870 
871 Double_t TProfile::GetBinError(Int_t bin) const
872 {
873  return TProfileHelper::GetBinError((TProfile*)this, bin);
874 }
875 
876 ////////////////////////////////////////////////////////////////////////////////
877 /// Return option to compute profile errors
878 
879 Option_t *TProfile::GetErrorOption() const
880 {
881  if (fErrorMode == kERRORSPREAD) return "s";
882  if (fErrorMode == kERRORSPREADI) return "i";
883  if (fErrorMode == kERRORSPREADG) return "g";
884  return "";
885 }
886 
887 ////////////////////////////////////////////////////////////////////////////////
888 /// fill the array stats from the contents of this profile.
889 ///
890 /// The array stats must be correctly dimensioned in the calling program.
891 ///
892 /// - stats[0] = sumw
893 /// - stats[1] = sumw2
894 /// - stats[2] = sumwx
895 /// - stats[3] = sumwx2
896 /// - stats[4] = sumwy
897 /// - stats[5] = sumwy2
898 ///
899 /// If no axis-subrange is specified (via TAxis::SetRange), the array stats
900 /// is simply a copy of the statistics quantities computed at filling time.
901 /// If a sub-range is specified, the function recomputes these quantities
902 /// from the bin contents in the current axis range.
903 
904 void TProfile::GetStats(Double_t *stats) const
905 {
906  if (fBuffer) ((TProfile*)this)->BufferEmpty();
907 
908  // Loop on bins
909  Int_t bin, binx;
910  if (fTsumw == 0 || fXaxis.TestBit(TAxis::kAxisRange)) {
911  for (bin=0;bin<6;bin++) stats[bin] = 0;
912  if (!fBinEntries.fArray) return;
913  Int_t firstBinX = fXaxis.GetFirst();
914  Int_t lastBinX = fXaxis.GetLast();
915  // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
916  if (GetStatOverflowsBehaviour() && !fXaxis.TestBit(TAxis::kAxisRange)) {
917  if (firstBinX == 1) firstBinX = 0;
918  if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
919  }
920  for (binx = firstBinX; binx <= lastBinX; binx++) {
921  Double_t w = fBinEntries.fArray[binx];
922  Double_t w2 = (fBinSumw2.fN ? fBinSumw2.fArray[binx] : w);
923  Double_t x = fXaxis.GetBinCenter(binx);
924  stats[0] += w;
925  stats[1] += w2;
926  stats[2] += w*x;
927  stats[3] += w*x*x;
928  stats[4] += fArray[binx];
929  stats[5] += fSumw2.fArray[binx];
930  }
931  } else {
932  if (fTsumwy == 0 && fTsumwy2 == 0) {
933  //this case may happen when processing TProfiles with version <=3
934  TProfile *p = (TProfile*)this; // cheating with const
935  for (binx=fXaxis.GetFirst();binx<=fXaxis.GetLast();binx++) {
936  p->fTsumwy += fArray[binx];
937  p->fTsumwy2 += fSumw2.fArray[binx];
938  }
939  }
940  stats[0] = fTsumw;
941  stats[1] = fTsumw2;
942  stats[2] = fTsumwx;
943  stats[3] = fTsumwx2;
944  stats[4] = fTsumwy;
945  stats[5] = fTsumwy2;
946  }
947 }
948 
949 ////////////////////////////////////////////////////////////////////////////////
950 /// Reduce the number of bins for this axis to the number of bins having a label.
951 
952 void TProfile::LabelsDeflate(Option_t *option)
953 {
954  TProfileHelper::LabelsDeflate(this, option);
955 }
956 
957 ////////////////////////////////////////////////////////////////////////////////
958 /// Double the number of bins for axis.
959 /// Refill histogram
960 /// This function is called by TAxis::FindBin(const char *label)
961 
962 void TProfile::LabelsInflate(Option_t *options)
963 {
964  TProfileHelper::LabelsInflate(this, options);
965 }
966 
967 ////////////////////////////////////////////////////////////////////////////////
968 /// Set option(s) to draw axis with labels.
969 ///
970 /// option might have the following values:
971 ///
972 /// - "a" sort by alphabetic order
973 /// - ">" sort by decreasing values
974 /// - "<" sort by increasing values
975 /// - "h" draw labels horizontal
976 /// - "v" draw labels vertical
977 /// - "u" draw labels up (end of label right adjusted)
978 /// - "d" draw labels down (start of label left adjusted)
979 
980 void TProfile::LabelsOption(Option_t *option, Option_t * /*ax */)
981 {
982  THashList *labels = fXaxis.GetLabels();
983  if (!labels) {
984  Warning("LabelsOption","Cannot sort. No labels");
985  return;
986  }
987  TString opt = option;
988  opt.ToLower();
989  if (opt.Contains("h")) {
990  fXaxis.SetBit(TAxis::kLabelsHori);
991  fXaxis.ResetBit(TAxis::kLabelsVert);
992  fXaxis.ResetBit(TAxis::kLabelsDown);
993  fXaxis.ResetBit(TAxis::kLabelsUp);
994  }
995  if (opt.Contains("v")) {
996  fXaxis.SetBit(TAxis::kLabelsVert);
997  fXaxis.ResetBit(TAxis::kLabelsHori);
998  fXaxis.ResetBit(TAxis::kLabelsDown);
999  fXaxis.ResetBit(TAxis::kLabelsUp);
1000  }
1001  if (opt.Contains("u")) {
1002  fXaxis.SetBit(TAxis::kLabelsUp);
1003  fXaxis.ResetBit(TAxis::kLabelsVert);
1004  fXaxis.ResetBit(TAxis::kLabelsDown);
1005  fXaxis.ResetBit(TAxis::kLabelsHori);
1006  }
1007  if (opt.Contains("d")) {
1008  fXaxis.SetBit(TAxis::kLabelsDown);
1009  fXaxis.ResetBit(TAxis::kLabelsVert);
1010  fXaxis.ResetBit(TAxis::kLabelsHori);
1011  fXaxis.ResetBit(TAxis::kLabelsUp);
1012  }
1013  Int_t sort = -1;
1014  if (opt.Contains("a")) sort = 0;
1015  if (opt.Contains(">")) sort = 1;
1016  if (opt.Contains("<")) sort = 2;
1017  if (sort < 0) return;
1018 
1019  Int_t n = TMath::Min(fXaxis.GetNbins(), labels->GetSize());
1020  Int_t *a = new Int_t[n+2];
1021  Int_t i,j;
1022  Double_t *cont = new Double_t[n+2];
1023  Double_t *sumw = new Double_t[n+2];
1024  Double_t *errors = new Double_t[n+2];
1025  Double_t *ent = new Double_t[n+2];
1026  THashList *labold = new THashList(labels->GetSize(),1);
1027  TIter nextold(labels);
1028  TObject *obj;
1029  while ((obj=nextold())) {
1030  labold->Add(obj);
1031  }
1032  labels->Clear();
1033  if (sort > 0) {
1034  //---sort by values of bins
1035  for (i=1;i<=n;i++) {
1036  sumw[i-1] = fArray[i];
1037  errors[i-1] = fSumw2.fArray[i];
1038  ent[i-1] = fBinEntries.fArray[i];
1039  if (fBinEntries.fArray[i] == 0) cont[i-1] = 0;
1040  else cont[i-1] = fArray[i]/fBinEntries.fArray[i];
1041  }
1042  if (sort ==1) TMath::Sort(n,cont,a,kTRUE); //sort by decreasing values
1043  else TMath::Sort(n,cont,a,kFALSE); //sort by increasing values
1044  for (i=1;i<=n;i++) {
1045  fArray[i] = sumw[a[i-1]];
1046  fSumw2.fArray[i] = errors[a[i-1]];
1047  fBinEntries.fArray[i] = ent[a[i-1]];
1048  }
1049  for (i=1;i<=n;i++) {
1050  obj = labold->At(a[i-1]);
1051  labels->Add(obj);
1052  obj->SetUniqueID(i);
1053  }
1054  } else {
1055  //---alphabetic sort
1056  const UInt_t kUsed = 1<<18;
1057  TObject *objk=0;
1058  a[0] = 0;
1059  a[n+1] = n+1;
1060  for (i=1;i<=n;i++) {
1061  const char *label = "zzzzzzzzzzzz";
1062  for (j=1;j<=n;j++) {
1063  obj = labold->At(j-1);
1064  if (!obj) continue;
1065  if (obj->TestBit(kUsed)) continue;
1066  //use strcasecmp for case non-sensitive sort (may be an option)
1067  if (strcmp(label,obj->GetName()) < 0) continue;
1068  objk = obj;
1069  a[i] = j;
1070  label = obj->GetName();
1071  }
1072  if (objk) {
1073  objk->SetUniqueID(i);
1074  labels->Add(objk);
1075  objk->SetBit(kUsed);
1076  }
1077  }
1078  for (i=1;i<=n;i++) {
1079  obj = labels->At(i-1);
1080  if (!obj) continue;
1081  obj->ResetBit(kUsed);
1082  }
1083 
1084  for (i=1;i<=n;i++) {
1085  sumw[i] = fArray[a[i]];
1086  errors[i] = fSumw2.fArray[a[i]];
1087  ent[i] = fBinEntries.fArray[a[i]];
1088  }
1089  for (i=1;i<=n;i++) {
1090  fArray[i] = sumw[i];
1091  fSumw2.fArray[i] = errors[i];
1092  fBinEntries.fArray[i] = ent[i];
1093  }
1094  }
1095  delete labold;
1096  if (a) delete [] a;
1097  if (sumw) delete [] sumw;
1098  if (cont) delete [] cont;
1099  if (errors) delete [] errors;
1100  if (ent) delete [] ent;
1101 }
1102 
1103 ////////////////////////////////////////////////////////////////////////////////
1104 ///Merge all histograms in the collection in this histogram.
1105 ///
1106 /// This function computes the min/max for the x axis,
1107 /// compute a new number of bins, if necessary,
1108 /// add bin contents, errors and statistics.
1109 /// If overflows are present and limits are different the function will fail.
1110 /// The function returns the total number of entries in the result histogram
1111 /// if the merge is successfull, -1 otherwise.
1112 ///
1113 /// IMPORTANT remark. The axis x may have different number
1114 /// of bins and different limits, BUT the largest bin width must be
1115 /// a multiple of the smallest bin width and the upper limit must also
1116 /// be a multiple of the bin width.
1117 
1118 Long64_t TProfile::Merge(TCollection *li)
1119 {
1120  return TProfileHelper::Merge(this, li);
1121 }
1122 
1123 ////////////////////////////////////////////////////////////////////////////////
1124 /// Performs the operation: this = this*c1*f1
1125 ///
1126 /// The function return kFALSE if the Multiply operation failed
1127 
1128 Bool_t TProfile::Multiply(TF1 *f1, Double_t c1)
1129 {
1130 
1131  if (!f1) {
1132  Error("Multiply","Attempt to multiply by a null function");
1133  return kFALSE;
1134  }
1135 
1136  Int_t nbinsx = GetNbinsX();
1137 
1138  //- Add statistics
1139  Double_t xx[1], cf1, ac1 = TMath::Abs(c1);
1140  Double_t s1[10];
1141  Int_t i;
1142  for (i=0;i<10;i++) {s1[i] = 0;}
1143  PutStats(s1);
1144 
1145  SetMinimum();
1146  SetMaximum();
1147 
1148  //- Loop on bins (including underflows/overflows)
1149  Int_t bin;
1150  for (bin=0;bin<=nbinsx+1;bin++) {
1151  xx[0] = fXaxis.GetBinCenter(bin);
1152  if (!f1->IsInside(xx)) continue;
1153  TF1::RejectPoint(kFALSE);
1154  cf1 = f1->EvalPar(xx);
1155  if (TF1::RejectedPoint()) continue;
1156  fArray[bin] *= c1*cf1;
1157  //see http://savannah.cern.ch/bugs/?func=detailitem&item_id=14851
1158  //fSumw2.fArray[bin] *= c1*c1*cf1*cf1;
1159  fSumw2.fArray[bin] *= ac1*cf1*cf1;
1160  //fBinEntries.fArray[bin] *= ac1*TMath::Abs(cf1);
1161  }
1162  return kTRUE;
1163 }
1164 
1165 ////////////////////////////////////////////////////////////////////////////////
1166 /// Multiply this profile by h1.
1167 ///
1168 /// `this = this*h1`
1169 
1170 Bool_t TProfile::Multiply(const TH1 *)
1171 {
1172  Error("Multiply","Multiplication of profile histograms not implemented");
1173  return kFALSE;
1174 }
1175 
1176 
1177 ////////////////////////////////////////////////////////////////////////////////
1178 /// Replace contents of this profile by multiplication of h1 by h2.
1179 ///
1180 /// `this = (c1*h1)*(c2*h2)`
1181 
1182 Bool_t TProfile::Multiply(const TH1 *, const TH1 *, Double_t, Double_t, Option_t *)
1183 {
1184  Error("Multiply","Multiplication of profile histograms not implemented");
1185  return kFALSE;
1186 }
1187 
1188 ////////////////////////////////////////////////////////////////////////////////
1189 /// Project this profile into a 1-D histogram along X
1190 ///
1191 /// The projection is always of the type TH1D.
1192 ///
1193 /// - if option "E" is specified the errors of the projected histogram are computed and set
1194 /// to be equal to the errors of the profile.
1195 /// Option "E" is defined as the default one in the header file.
1196 /// - if option "" is specified the histogram errors are simply the sqrt of its content
1197 /// - if option "B" is specified, the content of bin of the returned histogram
1198 /// will be equal to the GetBinEntries(bin) of the profile,
1199 /// otherwise (default) it will be equal to GetBinContent(bin)
1200 /// - if option "C=E" the bin contents of the projection are set to the
1201 /// bin errors of the profile
1202 /// - if option "W" is specified the bin content of the projected histogram is set to the
1203 /// product of the bin content of the profile and the entries.
1204 /// With this option the returned histogram will be equivalent to the one obtained by
1205 /// filling directly a TH1D using the 2-nd value as a weight.
1206 /// This makes sense only for profile filled with weights =1. If not, the error of the
1207 /// projected histogram obtained with this option will not be correct.
1208 
1209 TH1D *TProfile::ProjectionX(const char *name, Option_t *option) const
1210 {
1211 
1212  TString opt = option;
1213  opt.ToLower();
1214  Int_t nx = fXaxis.GetNbins();
1215 
1216  // Create the projection histogram
1217  TString pname = name;
1218  if (pname == "_px") {
1219  pname = GetName();
1220  pname.Append("_px");
1221  }
1222  TH1D *h1;
1223  const TArrayD *bins = fXaxis.GetXbins();
1224  if (bins->fN == 0) {
1225  h1 = new TH1D(pname,GetTitle(),nx,fXaxis.GetXmin(),fXaxis.GetXmax());
1226  } else {
1227  h1 = new TH1D(pname,GetTitle(),nx,bins->fArray);
1228  }
1229  Bool_t computeErrors = kFALSE;
1230  Bool_t cequalErrors = kFALSE;
1231  Bool_t binEntries = kFALSE;
1232  Bool_t binWeight = kFALSE;
1233  if (opt.Contains("b")) binEntries = kTRUE;
1234  if (opt.Contains("e")) computeErrors = kTRUE;
1235  if (opt.Contains("w")) binWeight = kTRUE;
1236  if (opt.Contains("c=e")) {cequalErrors = kTRUE; computeErrors=kFALSE;}
1237  if (computeErrors || binWeight || (binEntries && fBinSumw2.fN) ) h1->Sumw2();
1238 
1239  // Fill the projected histogram
1240  Double_t cont;
1241  for (Int_t bin =0;bin<=nx+1;bin++) {
1242 
1243  if (binEntries) cont = GetBinEntries(bin);
1244  else if (cequalErrors) cont = GetBinError(bin);
1245  else if (binWeight) cont = fArray[bin]; // bin content * bin entries
1246  else cont = GetBinContent(bin); // default case
1247 
1248  h1->SetBinContent(bin ,cont);
1249 
1250  // if option E projected histogram errors are same as profile
1251  if (computeErrors ) h1->SetBinError(bin , GetBinError(bin) );
1252  // in case of option W bin error is deduced from bin sum of z**2 values of profile
1253  // this is correct only if the profile is filled with weights =1
1254  if (binWeight) h1->GetSumw2()->fArray[bin] = fSumw2.fArray[bin];
1255  // in case of bin entries and profile is weighted, we need to set also the bin error
1256  if (binEntries && fBinSumw2.fN ) {
1257  R__ASSERT( h1->GetSumw2() );
1258  h1->GetSumw2()->fArray[bin] = fBinSumw2.fArray[bin];
1259  }
1260 
1261  }
1262 
1263  // Copy the axis attributes and the axis labels if needed.
1264  h1->GetXaxis()->ImportAttributes(this->GetXaxis());
1265  h1->GetYaxis()->ImportAttributes(this->GetYaxis());
1266  THashList* labels=this->GetXaxis()->GetLabels();
1267  if (labels) {
1268  TIter iL(labels);
1269  TObjString* lb;
1270  Int_t i = 1;
1271  while ((lb=(TObjString*)iL())) {
1272  h1->GetXaxis()->SetBinLabel(i,lb->String().Data());
1273  i++;
1274  }
1275  }
1276 
1277  h1->SetEntries(fEntries);
1278  return h1;
1279 }
1280 
1281 ////////////////////////////////////////////////////////////////////////////////
1282 /// Replace current statistics with the values in array stats.
1283 
1284 void TProfile::PutStats(Double_t *stats)
1285 {
1286  fTsumw = stats[0];
1287  fTsumw2 = stats[1];
1288  fTsumwx = stats[2];
1289  fTsumwx2 = stats[3];
1290  fTsumwy = stats[4];
1291  fTsumwy2 = stats[5];
1292 }
1293 
1294 ////////////////////////////////////////////////////////////////////////////////
1295 /// Rebin this profile grouping ngroup bins together.
1296 ///
1297 /// ## case 1 xbins=0
1298 /// if newname is not blank a new temporary profile hnew is created.
1299 /// else the current profile is modified (default)
1300 /// The parameter ngroup indicates how many bins of this have to me merged
1301 /// into one bin of hnew
1302 /// If the original profile has errors stored (via Sumw2), the resulting
1303 /// profile has new errors correctly calculated.
1304 ///
1305 /// examples: if hp is an existing TProfile histogram with 100 bins
1306 ///
1307 /// ~~~ {.cpp}
1308 /// hp->Rebin(); //merges two bins in one in hp: previous contents of hp are lost
1309 /// hp->Rebin(5); //merges five bins in one in hp
1310 /// TProfile *hnew = hp->Rebin(5,"hnew"); // creates a new profile hnew
1311 /// //merging 5 bins of hp in one bin
1312 /// ~~~
1313 ///
1314 /// NOTE: If ngroup is not an exact divider of the number of bins,
1315 /// the top limit of the rebinned profile is changed
1316 /// to the upper edge of the bin=newbins*ngroup and the corresponding
1317 /// bins are added to the overflow bin.
1318 /// Statistics will be recomputed from the new bin contents.
1319 ///
1320 /// ## case 2 xbins!=0
1321 /// a new profile is created (you should specify newname).
1322 /// The parameter ngroup is the number of variable size bins in the created profile
1323 /// The array xbins must contain ngroup+1 elements that represent the low-edge
1324 /// of the bins.
1325 /// The data of the old bins are added to the new bin which contains the bin center
1326 /// of the old bins. It is possible that information from the old binning are attached
1327 /// to the under-/overflow bins of the new binning.
1328 ///
1329 /// examples: if hp is an existing TProfile with 100 bins
1330 ///
1331 /// ~~~ {.cpp}
1332 /// Double_t xbins[25] = {...} array of low-edges (xbins[25] is the upper edge of last bin
1333 /// hp->Rebin(24,"hpnew",xbins); //creates a new variable bin size profile hpnew
1334 /// ~~~
1335 
1336 TH1 *TProfile::Rebin(Int_t ngroup, const char*newname, const Double_t *xbins)
1337 {
1338  Int_t nbins = fXaxis.GetNbins();
1339  Double_t xmin = fXaxis.GetXmin();
1340  Double_t xmax = fXaxis.GetXmax();
1341  if ((ngroup <= 0) || (ngroup > nbins)) {
1342  Error("Rebin", "Illegal value of ngroup=%d",ngroup);
1343  return 0;
1344  }
1345  if (!newname && xbins) {
1346  Error("Rebin","if xbins is specified, newname must be given");
1347  return 0;
1348  }
1349 
1350  Int_t newbins = nbins/ngroup;
1351  if (!xbins) {
1352  Int_t nbg = nbins/ngroup;
1353  if (nbg*ngroup != nbins) {
1354  Warning("Rebin", "ngroup=%d must be an exact divider of nbins=%d",ngroup,nbins);
1355  }
1356  }
1357  else {
1358  // in the case of xbins given (rebinning in variable bins) ngroup is the new number of bins.
1359  // and number of grouped bins is not constant.
1360  // when looping for setting the contents for the new histogram we
1361  // need to loop on all bins of original histogram. Set then ngroup=nbins
1362  newbins = ngroup;
1363  ngroup = nbins;
1364  }
1365 
1366  // Save old bin contents into a new array
1367  Double_t *oldBins = new Double_t[nbins+2];
1368  Double_t *oldCount = new Double_t[nbins+2];
1369  Double_t *oldErrors = new Double_t[nbins+2];
1370  Double_t *oldBinw2 = (fBinSumw2.fN ? new Double_t[nbins+2] : 0 );
1371  Int_t bin, i;
1372  Double_t *cu1 = GetW();
1373  Double_t *er1 = GetW2();
1374  Double_t *en1 = GetB();
1375  Double_t *ew1 = GetB2();
1376 
1377  for (bin=0;bin<=nbins+1;bin++) {
1378  oldBins[bin] = cu1[bin];
1379  oldCount[bin] = en1[bin];
1380  oldErrors[bin] = er1[bin];
1381  if (ew1 && fBinSumw2.fN) oldBinw2[bin] = ew1[bin];
1382  }
1383 
1384  // create a clone of the old histogram if newname is specified
1385  TProfile *hnew = this;
1386  if ((newname && strlen(newname) > 0) || xbins) {
1387  hnew = (TProfile*)Clone(newname);
1388  }
1389 
1390  // in case of ngroup not an excat divider of nbins,
1391  // top limit is changed (see NOTE in method comment)
1392  if(!xbins && (newbins*ngroup != nbins)) {
1393  xmax = fXaxis.GetBinUpEdge(newbins*ngroup);
1394  hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
1395  }
1396 
1397  // set correctly the axis and resizes the bin arrays
1398  if(!xbins && (fXaxis.GetXbins()->GetSize() > 0)){
1399  // for rebinning of variable bins in a constant group
1400  Double_t *bins = new Double_t[newbins+1];
1401  for(i = 0; i <= newbins; ++i) bins[i] = fXaxis.GetBinLowEdge(1+i*ngroup);
1402  hnew->SetBins(newbins,bins); //this also changes the bin array's
1403  delete [] bins;
1404  } else if (xbins) {
1405  // when rebinning in variable bins
1406  hnew->SetBins(newbins,xbins);
1407  } else {
1408  hnew->SetBins(newbins,xmin,xmax);
1409  }
1410 
1411  // merge bin contents ignoring now underflow/overflows
1412  if (fBinSumw2.fN) hnew->Sumw2();
1413 
1414  // Start merging only once the new lowest edge is reached
1415  Int_t startbin = 1;
1416  const Double_t newxmin = hnew->GetXaxis()->GetBinLowEdge(1);
1417  while( fXaxis.GetBinCenter(startbin) < newxmin && startbin <= nbins ) {
1418  startbin++;
1419  }
1420 
1421  Double_t *cu2 = hnew->GetW();
1422  Double_t *er2 = hnew->GetW2();
1423  Double_t *en2 = hnew->GetB();
1424  Double_t *ew2 = hnew->GetB2();
1425  Int_t oldbin = startbin;
1426  Double_t binContent, binCount, binError, binSumw2;
1427  for (bin = 1;bin<=newbins;bin++) {
1428  binContent = 0;
1429  binCount = 0;
1430  binError = 0;
1431  binSumw2 = 0;
1432 
1433  //for xbins != 0: ngroup == nbins
1434  Int_t imax = ngroup;
1435  Double_t xbinmax = hnew->GetXaxis()->GetBinUpEdge(bin);
1436  for (i=0;i<ngroup;i++) {
1437  if((hnew == this && (oldbin+i > nbins)) ||
1438  (hnew != this && (fXaxis.GetBinCenter(oldbin+i) > xbinmax)))
1439  {
1440  imax = i;
1441  break;
1442  }
1443 
1444  binContent += oldBins[oldbin+i];
1445  binCount += oldCount[oldbin+i];
1446  binError += oldErrors[oldbin+i];
1447  if (fBinSumw2.fN) binSumw2 += oldBinw2[oldbin+i];
1448  }
1449 
1450  cu2[bin] = binContent;
1451  er2[bin] = binError;
1452  en2[bin] = binCount;
1453  if (fBinSumw2.fN) ew2[bin] = binSumw2;
1454  oldbin += imax;
1455  }
1456  // set bin statistics for underflow bin
1457  binContent = 0;
1458  binCount = 0;
1459  binError = 0;
1460  binSumw2 = 0;
1461  for(i=0;i<startbin;i++)
1462  {
1463  binContent += oldBins[i];
1464  binCount += oldCount[i];
1465  binError += oldErrors[i];
1466  if (fBinSumw2.fN) binSumw2 += oldBinw2[i];
1467  }
1468  hnew->fArray[0] = binContent;
1469  hnew->fBinEntries[0] = binCount;
1470  hnew->fSumw2[0] = binError;
1471  if ( fBinSumw2.fN ) hnew->fBinSumw2[0] = binSumw2;
1472 
1473  // set bin statistics for overflow bin
1474  binContent = 0;
1475  binCount = 0;
1476  binError = 0;
1477  binSumw2 = 0;
1478  for(i=oldbin;i<=nbins+1;i++)
1479  {
1480  binContent += oldBins[i];
1481  binCount += oldCount[i];
1482  binError += oldErrors[i];
1483  if (fBinSumw2.fN) binSumw2 += oldBinw2[i];
1484  }
1485  hnew->fArray[newbins+1] = binContent;
1486  hnew->fBinEntries[newbins+1] = binCount;
1487  hnew->fSumw2[newbins+1] = binError;
1488  if ( fBinSumw2.fN ) hnew->fBinSumw2[newbins+1] = binSumw2;
1489 
1490 
1491  delete [] oldBins;
1492  delete [] oldCount;
1493  delete [] oldErrors;
1494  if (oldBinw2) delete [] oldBinw2;
1495  return hnew;
1496 }
1497 
1498 ////////////////////////////////////////////////////////////////////////////////
1499 /// Profile histogram is resized along x axis such that x is in the axis range.
1500 /// The new axis limits are recomputed by doubling iteratively
1501 /// the current axis range until the specified value x is within the limits.
1502 /// The algorithm makes a copy of the histogram, then loops on all bins
1503 /// of the old histogram to fill the extended histogram.
1504 /// Takes into account errors (Sumw2) if any.
1505 /// The axis must be extendable before invoking this function.
1506 ///
1507 /// Ex: `h->GetXaxis()->SetCanExtend(kTRUE)`
1508 
1509 void TProfile::ExtendAxis(Double_t x, TAxis *axis)
1510 {
1511  TProfile* hold = TProfileHelper::ExtendAxis(this, x, axis);
1512  if ( hold ) {
1513  fTsumwy = hold->fTsumwy;
1514  fTsumwy2 = hold->fTsumwy2;
1515 
1516  delete hold;
1517  }
1518 }
1519 
1520 ////////////////////////////////////////////////////////////////////////////////
1521 /// Reset contents of a Profile histogram.
1522 
1523 void TProfile::Reset(Option_t *option)
1524 {
1525  TH1D::Reset(option);
1526  fBinEntries.Reset();
1527  fBinSumw2.Reset();
1528  TString opt = option;
1529  opt.ToUpper();
1530  if (opt.Contains("ICE") && !opt.Contains("S")) return;
1531  fTsumwy = 0;
1532  fTsumwy2 = 0;
1533 }
1534 
1535 ////////////////////////////////////////////////////////////////////////////////
1536 /// Save primitive as a C++ statement(s) on output stream out.
1537 
1538 void TProfile::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1539 {
1540  //Note the following restrictions in the code generated:
1541  // - variable bin size not implemented
1542  // - SetErrorOption not implemented
1543 
1544  Bool_t nonEqiX = kFALSE;
1545  Int_t i;
1546  // Check if the profile has equidistant X bins or not. If not, we
1547  // create an array holding the bins.
1548  if (GetXaxis()->GetXbins()->fN && GetXaxis()->GetXbins()->fArray) {
1549  nonEqiX = kTRUE;
1550  out << " Double_t xAxis[" << GetXaxis()->GetXbins()->fN
1551  << "] = {";
1552  for (i = 0; i < GetXaxis()->GetXbins()->fN; i++) {
1553  if (i != 0) out << ", ";
1554  out << GetXaxis()->GetXbins()->fArray[i];
1555  }
1556  out << "}; " << std::endl;
1557  }
1558 
1559  char quote = '"';
1560  out<<" "<<std::endl;
1561  out<<" "<<ClassName()<<" *";
1562 
1563  //histogram pointer has by default teh histogram name.
1564  //however, in case histogram has no directory, it is safer to add a incremental suffix
1565  static Int_t hcounter = 0;
1566  TString histName = GetName();
1567  if (!fDirectory) {
1568  hcounter++;
1569  histName += "__";
1570  histName += hcounter;
1571  }
1572  const char *hname = histName.Data();
1573 
1574  out<<hname<<" = new "<<ClassName()<<"("<<quote<<GetName()<<quote<<","<<quote<<GetTitle()<<quote
1575  <<","<<GetXaxis()->GetNbins();
1576  if (nonEqiX)
1577  out << ", xAxis";
1578  else
1579  out << "," << GetXaxis()->GetXmin()
1580  << "," << GetXaxis()->GetXmax()
1581  <<","<<quote<<GetErrorOption()<<quote<<");"<<std::endl;
1582 
1583  // save bin entries
1584  Int_t bin;
1585  for (bin=0;bin<fNcells;bin++) {
1586  Double_t bi = GetBinEntries(bin);
1587  if (bi) {
1588  out<<" "<<hname<<"->SetBinEntries("<<bin<<","<<bi<<");"<<std::endl;
1589  }
1590  }
1591  //save bin contents
1592  for (bin=0;bin<fNcells;bin++) {
1593  Double_t bc = fArray[bin];
1594  if (bc) {
1595  out<<" "<<hname<<"->SetBinContent("<<bin<<","<<bc<<");"<<std::endl;
1596  }
1597  }
1598  // save bin errors
1599  if (fSumw2.fN) {
1600  for (bin=0;bin<fNcells;bin++) {
1601  Double_t be = TMath::Sqrt(fSumw2.fArray[bin]);
1602  if (be) {
1603  out<<" "<<hname<<"->SetBinError("<<bin<<","<<be<<");"<<std::endl;
1604  }
1605  }
1606  }
1607 
1608  TH1::SavePrimitiveHelp(out, hname, option);
1609 }
1610 
1611 ////////////////////////////////////////////////////////////////////////////////
1612 /// Multiply this profile by a constant c1.
1613 ///
1614 /// `this = c1*this`
1615 ///
1616 /// This function uses the services of TProfile::Add
1617 
1618 void TProfile::Scale(Double_t c1, Option_t * option)
1619 {
1620  TProfileHelper::Scale(this, c1, option);
1621 }
1622 
1623 ////////////////////////////////////////////////////////////////////////////////
1624 /// Set the number of entries in bin.
1625 
1626 void TProfile::SetBinEntries(Int_t bin, Double_t w)
1627 {
1628  TProfileHelper::SetBinEntries(this, bin, w);
1629 }
1630 
1631 ////////////////////////////////////////////////////////////////////////////////
1632 /// Redefine x axis parameters.
1633 
1634 void TProfile::SetBins(Int_t nx, Double_t xmin, Double_t xmax)
1635 {
1636  fXaxis.Set(nx,xmin,xmax);
1637  fNcells = nx+2;
1638  SetBinsLength(fNcells);
1639 }
1640 
1641 ////////////////////////////////////////////////////////////////////////////////
1642 /// Redefine x axis parameters.
1643 
1644 void TProfile::SetBins(Int_t nx, const Double_t *xbins)
1645 {
1646  fXaxis.Set(nx,xbins);
1647  fNcells = nx+2;
1648  SetBinsLength(fNcells);
1649 }
1650 
1651 ////////////////////////////////////////////////////////////////////////////////
1652 /// Set total number of bins including under/overflow.
1653 /// Reallocate bin contents array
1654 
1655 void TProfile::SetBinsLength(Int_t n)
1656 {
1657  TH1D::SetBinsLength(n);
1658  TProfileHelper::BuildArray(this);
1659 }
1660 
1661 ////////////////////////////////////////////////////////////////////////////////
1662 /// Set the buffer size in units of 8 bytes (double).
1663 
1664 void TProfile::SetBuffer(Int_t buffersize, Option_t *)
1665 {
1666  if (fBuffer) {
1667  BufferEmpty();
1668  delete [] fBuffer;
1669  fBuffer = 0;
1670  }
1671  if (buffersize <= 0) {
1672  fBufferSize = 0;
1673  return;
1674  }
1675  if (buffersize < 100) buffersize = 100;
1676  fBufferSize = 1 + 3*buffersize;
1677  fBuffer = new Double_t[fBufferSize];
1678  memset(fBuffer,0,sizeof(Double_t)*fBufferSize);
1679 }
1680 
1681 ////////////////////////////////////////////////////////////////////////////////
1682 /// Set option to compute profile errors.
1683 ///
1684 /// The computation of the bin errors is based on the parameter option:
1685 ///
1686 /// -' ' (Default) The bin errors are the standard error on the mean of the bin profiled values (Y),
1687 /// i.e. the standard error of the bin contents.
1688 /// Note that if TProfile::Approximate() is called, an approximation is used when
1689 /// the spread in Y is 0 and the number of bin entries is > 0
1690 /// -'s' The bin errors are the standard deviations of the Y bin values
1691 /// Note that if TProfile::Approximate() is called, an approximation is used when
1692 /// the spread in Y is 0 and the number of bin entries is > 0
1693 /// -'i' Errors are as in default case (standard errors of the bin contents)
1694 /// The only difference is for the case when the spread in Y is zero.
1695 /// In this case for N > 0 the error is 1./SQRT(12.*N)
1696 /// -'g' Errors are 1./SQRT(W) for W not equal to 0 and 0 for W = 0.
1697 /// W is the sum in the bin of the weights of the profile.
1698 /// This option is for combining measurements y +/- dy,
1699 /// and the profile is filled with values y and weights w = 1/dy**2
1700 ///
1701 /// See TProfile::BuildOptions for a detailed explanation of all options
1702 
1703 void TProfile::SetErrorOption(Option_t *option)
1704 {
1705  TProfileHelper::SetErrorOption(this, option);
1706 }
1707 
1708 ////////////////////////////////////////////////////////////////////////////////
1709 /// Stream an object of class TProfile.
1710 
1711 void TProfile::Streamer(TBuffer &R__b)
1712 {
1713  if (R__b.IsReading()) {
1714  UInt_t R__s, R__c;
1715  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1716  if (R__v > 2) {
1717  R__b.ReadClassBuffer(TProfile::Class(), this, R__v, R__s, R__c);
1718  return;
1719  }
1720  //====process old versions before automatic schema evolution
1721  TH1D::Streamer(R__b);
1722  fBinEntries.Streamer(R__b);
1723  Int_t errorMode;
1724  R__b >> errorMode;
1725  fErrorMode = (EErrorType)errorMode;
1726  if (R__v < 2) {
1727  Float_t ymin,ymax;
1728  R__b >> ymin; fYmin = ymin;
1729  R__b >> ymax; fYmax = ymax;
1730  } else {
1731  R__b >> fYmin;
1732  R__b >> fYmax;
1733  }
1734  R__b.CheckByteCount(R__s, R__c, TProfile::IsA());
1735  //====end of old versions
1736 
1737  } else {
1738  R__b.WriteClassBuffer(TProfile::Class(),this);
1739  }
1740 }
1741 ////////////////////////////////////////////////////////////////////////////////
1742 /// Create/delete structure to store sum of squares of weights per bin.
1743 ///
1744 /// This is needed to compute the correct statistical quantities
1745 /// of a profile filled with weights
1746 ///
1747 /// This function is automatically called when the histogram is created
1748 /// if the static function TH1::SetDefaultSumw2 has been called before.
1749 /// If flag is false the structure is deleted
1750 
1751 void TProfile::Sumw2(Bool_t flag)
1752 {
1753  TProfileHelper::Sumw2(this, flag);
1754 }