Logo ROOT   6.12/07
Reference Guide
TH1Merger.cxx
Go to the documentation of this file.
1 // Helper clas implementing some of the TH1 functionality
2 
3 #include "TH1Merger.h"
4 #include "TH1.h"
5 #include "TH2.h"
6 #include "TH3.h"
7 #include "TAxis.h"
8 #include "TError.h"
9 #include "THashList.h"
10 #include "TClass.h"
11 #include <iostream>
12 #include <limits>
13 #include <utility>
14 
15 #define PRINTRANGE(a, b, bn) \
16  Printf(" base: %f %f %d, %s: %f %f %d", a->GetXmin(), a->GetXmax(), a->GetNbins(), bn, b->GetXmin(), b->GetXmax(), \
17  b->GetNbins());
18 
20  Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
21  if (h->GetDimension() > 1) hasLimits &= h->GetYaxis()->GetXmin() < h->GetYaxis()->GetXmax();
22  if (h->GetDimension() > 2) hasLimits &= h->GetZaxis()->GetXmin() < h->GetZaxis()->GetXmax();
23  return hasLimits;
24 }
25 
26 /// Function performing the actual merge
28 
29 
31 
32  if (gDebug) Info("Merge","Histogram Merge type is %d and new axis flag is %d",(int) type,(int) fNewAxisFlag);
33 
34  if (type == kNotCompatible) return kFALSE;
35 
36  if (type == kAllSameAxes)
37  return SameAxesMerge();
38 
39  if (type == kAllLabel)
40  return LabelMerge();
41 
42  if (type == kAllNoLimits)
43  return BufferMerge();
44 
45  if (type == kAutoP2HaveLimits || (type == kAutoP2NeedLimits && AutoP2BufferMerge()))
46  return AutoP2Merge();
47 
48  // this is the mixed case - more complicated
49  if (type == kHasNewLimits) {
50  // we need to define some new axes
51  DefineNewAxes();
52  // we might need to merge some histogram using the buffer
53  Bool_t ret = BufferMerge();
54  // if ret is true the merge is completed and we can exit
55  if (ret) return kTRUE;
56  // in the other cases then we merge using FindBin
57  return DifferentAxesMerge();
58  }
59  Error("TH1Merger","Unknown type of Merge for histogram %s",fH0->GetName());
60  return kFALSE;
61 }
62 
63 /////////////////////////////////////////////////////////////////////////////////////////
64 /// Determine final boundaries and number of bins for histograms created in power-of-2
65 /// autobin mode.
66 ///
67 /// Return kTRUE if compatible, updating fNewXaxis accordingly; return kFALSE if something
68 /// wrong.
69 ///
70 /// The histograms are not merge-compatible if
71 ///
72 /// 1. have different variable-size bins
73 /// 2. larger bin size is not an integer multiple of the smaller one
74 /// 3. the final estimated range is smalle then the bin size
75 ///
76 
78 {
79  // They must be both defined
80  if (!h) {
81  Error("AutoP2BuildAxes", "undefined histogram: %p", h);
82  return kFALSE;
83  }
84 
85  // They must be created in power-of-2 autobin mode
86  if (!h->TestBit(TH1::kAutoBinPTwo)) {
87  Error("AutoP2BuildAxes", "not in autobin-power-of-2 mode!");
88  return kFALSE;
89  }
90 
91  // Point to axes
92  TAxis *a0 = &fNewXAxis, *a1 = h->GetXaxis();
93 
94  // This is for future merging of detached ranges (only possible if no over/underflows)
95  Bool_t canextend = (h->GetBinContent(0) > 0 || h->GetBinContent(a1->GetNbins() + 1) > 0) ? kFALSE : kTRUE;
96 
97  // The first time we just copy the boundaries and bins
98  if (a0->GetFirst() == a0->GetLast()) {
99  a0->Set(a1->GetNbins(), a1->GetXmin(), a1->GetXmax());
100  // This is for future merging of detached ranges (only possible if no over/underflows)
101  a0->SetCanExtend(canextend);
102  return kTRUE;
103  }
104 
105  // Bin sizes must be in integer ratio
106  Double_t bwmax = (a0->GetXmax() - a0->GetXmin()) / a0->GetNbins();
107  Double_t bwmin = (a1->GetXmax() - a1->GetXmin()) / a1->GetNbins();
108  Bool_t b0 = kTRUE;
109  if (bwmin > bwmax) {
110  std::swap(bwmax, bwmin);
111  b0 = kFALSE;
112  }
113  if (!(bwmin > 0.)) {
114  PRINTRANGE(a0, a1, h->GetName());
115  Error("AutoP2BuildAxes", "minimal bin width negative or null: %f", bwmin);
116  return kFALSE;
117  }
118 
119  Double_t rt;
120  Double_t re = std::modf(bwmax / bwmin, &rt);
122  PRINTRANGE(a0, a1, h->GetName());
123  Error("AutoP2BuildAxes", "bin widths not in integer ratio: %f", re);
124  return kFALSE;
125  }
126 
127  // Range of the merged histogram, taking into account overlaps
128  Bool_t domax = kFALSE;
129  Double_t xmax, xmin;
130  if (a0->GetXmin() < a1->GetXmin()) {
131  if (a0->GetXmax() < a1->GetXmin()) {
132  if (!a0->CanExtend() || !canextend) {
133  PRINTRANGE(a0, a1, h->GetName());
134  Error("AutoP2BuildAxes", "ranges are disconnected and under/overflows: cannot merge");
135  return kFALSE;
136  }
137  xmax = a1->GetXmax();
138  xmin = a0->GetXmin();
139  domax = b0 ? kTRUE : kFALSE;
140  } else {
141  if (a0->GetXmax() >= a1->GetXmax()) {
142  xmax = a1->GetXmax();
143  xmin = a1->GetXmin();
144  domax = !b0 ? kTRUE : kFALSE;
145  } else {
146  xmax = a0->GetXmax();
147  xmin = a1->GetXmin();
148  domax = !b0 ? kTRUE : kFALSE;
149  }
150  }
151  } else {
152  if (a1->GetXmax() < a0->GetXmin()) {
153  if (!a0->CanExtend() || !canextend) {
154  PRINTRANGE(a0, a1, h->GetName());
155  Error("AutoP2BuildAxes", "ranges are disconnected and under/overflows: cannot merge");
156  return kFALSE;
157  }
158  xmax = a0->GetXmax();
159  xmin = a1->GetXmin();
160  domax = !b0 ? kTRUE : kFALSE;
161  } else {
162  if (a1->GetXmax() >= a0->GetXmax()) {
163  xmax = a0->GetXmax();
164  xmin = a0->GetXmin();
165  domax = b0 ? kTRUE : kFALSE;
166  } else {
167  xmax = a1->GetXmax();
168  xmin = a0->GetXmin();
169  domax = b0 ? kTRUE : kFALSE;
170  }
171  }
172  }
173  Double_t range = xmax - xmin;
174 
175  re = std::modf(range / bwmax, &rt);
176  if (rt < 1.) {
177  PRINTRANGE(a0, a1, h->GetName());
178  Error("MergeCompatibleHistograms", "range smaller than bin width: %f %f %f", range, bwmax, rt);
179  return kFALSE;
180  }
182  if (domax) {
183  xmax -= bwmax * re;
184  } else {
185  xmin += bwmax * re;
186  }
187  }
188  // Number of bins
189  Int_t nb = (Int_t)rt;
190 
191  // Set the result
192  a0->Set(nb, xmin, xmax);
193 
194  // This is for future merging of detached ranges (only possible if no over/underflows)
195  if (!a0->CanExtend())
196  a0->SetCanExtend(canextend);
197 
198  // Done
199  return kTRUE;
200 }
201 
202 /**
203  Examine the list of histograms to find out which type of Merge we need to do
204  Pass the input list containing the histogram to merge and h0 which is the initial histogram
205  on which all the histogram of the list will be merged
206  This are the possible cases:
207  - 1. All histogram have the same axis (allSameLimits = true)
208  - 2. Histogram have different axis but compatible (allSameLimits = false) and sameLimitsX,Y,Z specifies which axis
209  has different limits
210  - 3. Histogram do not have limits (so the Buffer is used) allHaveLimits = false
211  - 3b. One histogram has limits the other not : allHaveLimits = false AND initialLimitsFound = true
212  - 4. Histogram Have labels = allHaveLabels = true
213 
214 
215 */
217 
218 
219 
220  Bool_t initialLimitsFound = kFALSE;
221  Bool_t allHaveLabels = kTRUE; // assume all histo have labels and check later
222  Bool_t allHaveLimits = kTRUE;
223  Bool_t allSameLimits = kTRUE;
224  Bool_t sameLimitsX = kTRUE;
225  Bool_t sameLimitsY = kTRUE;
226  Bool_t sameLimitsZ = kTRUE;
227  Bool_t foundLabelHist = kFALSE;
228  Bool_t haveWeights = kFALSE;
229 
230  Bool_t isAutoP2 = kFALSE;
231 
232  // TAxis newXAxis;
233  // TAxis newYAxis;
234  // TAxis newZAxis;
235 
236  TIter next(&fInputList);
237  TH1 * h = fH0; // start with fH0
238 
239  int dimension = fH0->GetDimension();
240 
241  isAutoP2 = fH0->TestBit(TH1::kAutoBinPTwo) ? kTRUE : kFALSE;
242 
243  // start looping on the histograms
244 
245  do {
246 
247  // check first histogram compatibility
248  if (h != fH0) {
249  if (h->GetDimension() != dimension) {
250  Error("Merge", "Cannot merge histogram - dimensions are different\n "
251  "%s has dim=%d and %s has dim=%d",fH0->GetName(),dimension,h->GetName(),h->GetDimension());
252  return kNotCompatible;
253  }
254  }
255 
256  // check if one of the histogram is weighted
257  haveWeights |= h->GetSumw2N() != 0;
258 
259  // do not skip anymore empty histograms
260  // since are used to set the limits
261  Bool_t hasLimits = TH1Merger::AxesHaveLimits(h);
262  allHaveLimits = allHaveLimits && hasLimits;
263  allSameLimits &= allHaveLimits;
264 
265  if (isAutoP2 && !h->TestBit(TH1::kAutoBinPTwo)) {
266  Error("Merge", "Cannot merge histogram - some are in autobin-power-of-2 mode, but not %s!", h->GetName());
267  return kNotCompatible;
268  }
269  if (!isAutoP2 && h->TestBit(TH1::kAutoBinPTwo)) {
270  Error("Merge", "Cannot merge histogram - %s is in autobin-power-of-2 mode, but not the previous ones",
271  h->GetName());
272  return kNotCompatible;
273  }
274 
275  if (hasLimits) {
276  h->BufferEmpty();
277 
278 // // this is done in case the first histograms are empty and
279 // // the histogram have different limits
280 // #ifdef LATER
281 // if (firstHistWithLimits ) {
282 // // set axis limits in the case the first histogram did not have limits
283 // if (h != this && !SameLimitsAndNBins( fXaxis, *h->GetXaxis()) ) {
284 // if (h->GetXaxis()->GetXbins()->GetSize() != 0) fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
285 // else fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
286 // }
287 // firstHistWithLimits = kFALSE;
288 // }
289 // #endif
290 
291  // this is executed the first time an histogram with limits is found
292  // to set some initial values on the new axis
293  if (!initialLimitsFound) {
294  initialLimitsFound = kTRUE;
295  if (h->GetXaxis()->GetXbins()->GetSize() != 0)
296  fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
297  else
298  fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
299  if (dimension > 1) {
300  if (h->GetYaxis()->GetXbins()->GetSize() != 0)
301  fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXbins()->GetArray());
302  else
303  fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
304  }
305  if (dimension > 2) {
306  if (h->GetZaxis()->GetXbins()->GetSize() != 0)
307  fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXbins()->GetArray());
308  else
309  fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(), h->GetZaxis()->GetXmax());
310 
311  }
312  }
313  else {
314  // check first if histograms have same bins in X
315  if (!TH1::SameLimitsAndNBins(fNewXAxis, *(h->GetXaxis())) ) {
316  sameLimitsX = kFALSE;
317  // recompute the limits in this case the optimal limits
318  // The condition to works is that the histogram have same bin with
319  // and one common bin edge
321  Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
322  "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
324  h->GetName(),h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
325  h->GetXaxis()->GetXmax());
326  return kNotCompatible;
327  }
328  }
329  // check first if histograms have same bins in Y
330  if (dimension > 1 && !TH1::SameLimitsAndNBins(fNewYAxis, *(h->GetYaxis()))) {
331  sameLimitsY = kFALSE;
332  // recompute in this case the optimal limits
333  // The condition to works is that the histogram have same bin with
334  // and one common bin edge
336  Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
337  "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
339  h->GetName(), h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
340  h->GetYaxis()->GetXmax());
341  return kNotCompatible;
342  }
343  }
344  if(dimension > 2 && !fH0->SameLimitsAndNBins(fNewZAxis, *(h->GetZaxis()))) {
345  sameLimitsZ = kFALSE;
347  Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
348  "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
350  h->GetName(),h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
351  h->GetZaxis()->GetXmax());
352  return kNotCompatible;
353  }
354  }
355  allSameLimits = sameLimitsX && sameLimitsY && sameLimitsZ;
356 
357 
358  }
359  }
360  Bool_t histoIsEmpty = h->IsEmpty();
361  // std::cout << "considering histo " << h->GetName() << " labels - " << allHaveLabels << " is empty "
362  // << histoIsEmpty << std::endl;
363 
364  // if histogram is empty it does not matter if it has label or not
365  if (allHaveLabels && !histoIsEmpty) {
366  THashList* hlabels=h->GetXaxis()->GetLabels();
367  Bool_t haveOneLabel = (hlabels != nullptr);
368  // do here to print message only one time
369  if (foundLabelHist && allHaveLabels && !haveOneLabel) {
370  Warning("Merge","Not all histograms have labels. I will ignore labels,"
371  " falling back to bin numbering mode.");
372  }
373 
374  allHaveLabels &= (haveOneLabel);
375  // for the error message
376  if (haveOneLabel) foundLabelHist = kTRUE;
377 
378  if (foundLabelHist && gDebug)
379  Info("TH1Merger::ExamineHistogram","Histogram %s has labels",h->GetName() );
380 
381  // If histograms have labels but CanExtendAllAxes() is false
382  // use bin center mode
383  if (allHaveLabels && !fH0->CanExtendAllAxes()) {
384  // special case for this histogram when is empty
385  // and axis cannot be extended (because it is the default)
386  if ( fH0->IsEmpty() ) {
387  if (gDebug)
388  Info("TH1Merger::ExamineHistogram","Histogram %s to be merged is empty and we are merging with %s that has labels. Force the axis to be extended",fH0->GetName(),h->GetName());
389  UInt_t bitMaskX = fH0->GetXaxis()->CanBeAlphanumeric() & TH1::kXaxis;
390  UInt_t bitMaskY = (fH0->GetYaxis()->CanBeAlphanumeric() << 1 ) & TH1::kYaxis;
391  UInt_t bitMaskZ = (fH0->GetZaxis()->CanBeAlphanumeric() << 2 ) & TH1::kZaxis;
392  fH0->SetCanExtend(bitMaskX | bitMaskY | bitMaskZ );
393  }
394  if (!fH0->CanExtendAllAxes()) {
395  if (gDebug)
396  Info("TH1Merger::ExamineHistogram","Histogram %s to be merged has label but axis cannot be extended - using bin numeric mode to merge. Call TH1::SetExtendAllAxes() if want to merge using label mode",fH0->GetName());
397  allHaveLabels = kFALSE;
398  }
399  }
400  // I could add a check if histogram contains bins without a label
401  // and with non-zero bin content
402  // Do we want to support this ???
403  // only in case the !h->CanExtendAllAxes()
404  if (allHaveLabels && !h->CanExtendAllAxes()) {
405  // count number of bins with non-null content
406  Int_t non_zero_bins = 0;
407  Int_t nbins = h->GetXaxis()->GetNbins();
408  if (nbins > hlabels->GetEntries() ) {
409  for (Int_t i = 1; i <= nbins; i++) {
410  if (h->RetrieveBinContent(i) != 0 || (fH0->fSumw2.fN && h->GetBinError(i) != 0) ) {
411  non_zero_bins++;
412  }
413  }
414  if (non_zero_bins > hlabels->GetEntries() ) {
415  Warning("TH1Merger::ExamineHistograms","Histogram %s contains non-empty bins without labels - falling back to bin numbering mode",h->GetName() );
416  allHaveLabels = kFALSE;
417  }
418  }
419  }
420  }
421  if (gDebug)
422  Info("TH1Merger::ExamineHistogram","Examine histogram %s - labels %d - same limits %d - axis found %d",h->GetName(),allHaveLabels,allSameLimits,initialLimitsFound );
423 
424  } while ( ( h = dynamic_cast<TH1*> ( next() ) ) != NULL );
425 
426  if (!h && (*next) ) {
427  Error("Merge","Attempt to merge object of class: %s to a %s",
428  (*next)->ClassName(),fH0->ClassName());
429  return kNotCompatible;
430  }
431 
432  // in case of weighted histogram set Sumw2() on fH0 is is not weighted
433  if (haveWeights && fH0->GetSumw2N() == 0)
434  fH0->Sumw2();
435 
436  // AutoP2
437  if (isAutoP2) {
438  if (allHaveLimits)
439  return kAutoP2HaveLimits;
440  return kAutoP2NeedLimits;
441  }
442 
443  // return the type of merge
444  if (allHaveLabels) return kAllLabel;
445  if (allSameLimits) return kAllSameAxes;
446  if (!initialLimitsFound) {
447  R__ASSERT(!allHaveLimits);
448  // case where no limits are found and the buffer is used
449  return kAllNoLimits;
450  }
451  // remaining case should be the mixed one. Some histogram have limits some not
452  fNewAxisFlag = 0;
453  if (!sameLimitsX) fNewAxisFlag |= TH1::kXaxis;
454  if (!sameLimitsY) fNewAxisFlag |= TH1::kYaxis;
455  if (!sameLimitsZ) fNewAxisFlag |= TH1::kZaxis;
456 
457  // we need to set the flag also in case this histogram has no limits
458  // we need to set explicitly the flag to re-define a new axis
460  if (dimension > 1 && fH0->GetYaxis()->GetXmin() >= fH0->GetYaxis()->GetXmax()) fNewAxisFlag |= TH1::kYaxis;
461  if (dimension > 2 && fH0->GetZaxis()->GetXmin() >= fH0->GetZaxis()->GetXmax()) fNewAxisFlag |= TH1::kZaxis;
462 
463 
464  return kHasNewLimits;
465 
466 }
467 
468 /**
469  Function to define new histogram axis when merging
470  It is call only in case of merging with different axis or with the
471  buffer (kHasNewLimits)
472 */
473 
475 
476  // first we need to create a copy of the histogram in case is not empty
477 
478  if (!fH0->IsEmpty() ) {
479  Bool_t mustCleanup = fH0->TestBit(kMustCleanup);
480  if (mustCleanup) fH0->ResetBit(kMustCleanup);
481  fHClone = (TH1*)fH0->IsA()->New();
482  fHClone->SetDirectory(0);
483  fH0->Copy(*fHClone);
484  if (mustCleanup) fH0->SetBit(kMustCleanup);
485  fH0->BufferEmpty(1); // To remove buffer.
486  fH0->Reset(); // BufferEmpty sets limits so we can't use it later.
487  fH0->SetEntries(0);
489 
490  }
491 
492  bool newLimitsX = (fNewAxisFlag & TH1::kXaxis);
493  bool newLimitsY = (fNewAxisFlag & TH1::kYaxis);
494  bool newLimitsZ = (fNewAxisFlag & TH1::kZaxis);
495  if (newLimitsX) {
496  fH0->fXaxis.SetRange(0,0);
497  if (fNewXAxis.GetXbins()->GetSize() != 0)
499  else
501  }
502  if (newLimitsY) {
503  fH0->fYaxis.SetRange(0,0);
504  if (fNewYAxis.GetXbins()->GetSize() != 0)
506  else
508  }
509  if (newLimitsZ) {
510  fH0->fZaxis.SetRange(0,0);
511  if (fNewZAxis.GetXbins()->GetSize() != 0)
513  else
515  }
516 
517  // we need to recompute fNcells and set the array size (as in TH1::SetBins)
518  fH0->fNcells = fH0->fXaxis.GetNbins()+2;
519  if (fH0->fDimension > 1) fH0->fNcells *= fH0->fYaxis.GetNbins()+2;
520  if (fH0->fDimension > 2) fH0->fNcells *= fH0->fZaxis.GetNbins()+2;
522  if (fH0->fSumw2.fN) fH0->fSumw2.Set(fH0->fNcells);
523  // set dummy Y and Z axis for lower dim histogras
524  if (fH0->fDimension < 3) fH0->fZaxis.Set(1,0,1);
525  if (fH0->fDimension < 2) fH0->fYaxis.Set(1,0,1);
526 
527  if (gDebug) {
528  if (newLimitsX) Info("DefineNewAxis","A new X axis has been defined Nbins=%d , [%f,%f]", fH0->fXaxis.GetNbins(),
529  fH0->fXaxis.GetXmin(), fH0->fXaxis.GetXmax() );
530  if (newLimitsY) Info("DefineNewAxis","A new Y axis has been defined Nbins=%d , [%f,%f]", fH0->fYaxis.GetNbins(),
531  fH0->fYaxis.GetXmin(), fH0->fYaxis.GetXmax() );
532  if (newLimitsZ) Info("DefineNewAxis","A new Z axis has been defined Nbins=%d , [%f,%f]", fH0->fZaxis.GetNbins(),
533  fH0->fZaxis.GetXmin(), fH0->fZaxis.GetXmax() );
534  }
535 
536  return;
537 
538 }
539 
540 void TH1Merger::CopyBuffer(TH1 *hsrc, TH1 *hdes)
541 {
542  // Check inputs
543  if (!hsrc || !hsrc->fBuffer || !hdes || !hdes->fBuffer) {
544  void *p1 = hsrc ? hsrc->fBuffer : 0;
545  void *p2 = hdes ? hdes->fBuffer : 0;
546  Warning("TH1Merger::CopyMerge", "invalid inputs: %p, %p, %p, %p -> do nothing", hsrc, hdes, p1, p2);
547  }
548 
549  // Entries from buffers have to be filled one by one
550  // because FillN doesn't resize histograms.
551  Int_t nbentries = (Int_t)hsrc->fBuffer[0];
552  if (hdes->fDimension == 1) {
553  for (Int_t i = 0; i < nbentries; i++)
554  hdes->Fill(hsrc->fBuffer[2 * i + 2], hsrc->fBuffer[2 * i + 1]);
555  }
556  if (hdes->fDimension == 2) {
557  auto h2 = dynamic_cast<TH2 *>(hdes);
558  R__ASSERT(h2);
559  for (Int_t i = 0; i < nbentries; i++)
560  h2->Fill(hsrc->fBuffer[3 * i + 2], hsrc->fBuffer[3 * i + 3], hsrc->fBuffer[3 * i + 1]);
561  }
562  if (hdes->fDimension == 3) {
563  auto h3 = dynamic_cast<TH3 *>(hdes);
564  R__ASSERT(h3);
565  for (Int_t i = 0; i < nbentries; i++)
566  h3->Fill(hsrc->fBuffer[4 * i + 2], hsrc->fBuffer[4 * i + 3], hsrc->fBuffer[4 * i + 4],
567  hsrc->fBuffer[4 * i + 1]);
568  }
569 }
570 
572 {
573 
574  TH1 *href = 0, *hist = 0;
575  TIter nextref(&fInputList);
577  href = fH0;
578  } else {
579  while ((hist = (TH1 *)nextref()) && !href) {
580  if (TH1Merger::AxesHaveLimits(hist))
581  href = hist;
582  }
583  }
584  Bool_t resetfH0 = kFALSE;
585  if (!href) {
586  // Merge all histograms to fH0 and do a final projection
587  href = fH0;
588  } else {
589  if (href != fH0) {
590  // Temporary add fH0 to the list for buffer merging
591  fInputList.Add(fH0);
592  resetfH0 = kTRUE;
593  }
594  }
595  TIter next(&fInputList);
596  while ((hist = (TH1 *)next())) {
597  if (!TH1Merger::AxesHaveLimits(hist) && hist->fBuffer) {
598  if (gDebug)
599  Info("AutoP2BufferMerge", "merging buffer of %s into %s", hist->GetName(), href->GetName());
600  CopyBuffer(hist, href);
601  fInputList.Remove(hist);
602  }
603  }
604  // Final projection
605  if (href->fBuffer)
606  href->BufferEmpty(1);
607  // Reset fH0, if already added, to avoid double counting
608  if (resetfH0)
609  fH0->Reset("ICES");
610  // Done, all histos have been processed
611  return kTRUE;
612 }
613 
615 {
616 
617  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
618  for (Int_t i = 0; i < TH1::kNstat; i++) {
619  totstats[i] = stats[i] = 0;
620  }
621 
622  TIter next(&fInputList);
623  TH1 *hist = 0;
624  // Calculate boundaries and bins
625  Double_t xmin = 0., xmax = 0.;
626  if (!(fH0->IsEmpty())) {
627  hist = fH0;
628  } else {
629  while ((hist = (TH1 *)next())) {
630  if (!hist->IsEmpty())
631  break;
632  }
633  }
634 
635  if (!hist) {
636  if (gDebug)
637  Info("TH1Merger::AutoP2Merge", "all histograms look empty!");
638  return kFALSE;
639  }
640 
641  // Start building the axes from the reference histogram
642  if (!AutoP2BuildAxes(hist)) {
643  Error("TH1Merger::AutoP2Merge", "cannot create axes from %s", hist->GetName());
644  return kFALSE;
645  }
646  TH1 *h = 0;
647  while ((h = (TH1 *)next())) {
648  if (!AutoP2BuildAxes(h)) {
649  Error("TH1Merger::AutoP2Merge", "cannot merge histogram %s: not merge compatible", h->GetName());
650  return kFALSE;
651  }
652  }
653  xmin = fNewXAxis.GetXmin();
654  xmax = fNewXAxis.GetXmax();
655  Int_t nbins = fNewXAxis.GetNbins();
656 
657  // Prepare stats
658  fH0->GetStats(totstats);
659  // Clone fH0 and add it to the list
660  if (!fH0->IsEmpty())
661  fInputList.Add(fH0->Clone());
662 
663  // reset fH0
664  fH0->Reset("ICES");
665  // Set the new boundaries
666  fH0->SetBins(nbins, xmin, xmax);
667 
668  next.Reset();
669  Double_t nentries = 0.;
670  while ((hist = (TH1 *)next())) {
671  // process only if the histogram has limits; otherwise it was processed before
672  // in the case of an existing buffer (see if statement just before)
673 
674  if (gDebug)
675  Info("TH1Merger::AutoP2Merge", "merging histogram %s into %s (entries: %f)", hist->GetName(), fH0->GetName(),
676  hist->GetEntries());
677 
678  // skip empty histograms
679  if (hist->IsEmpty())
680  continue;
681 
682  // import statistics
683  hist->GetStats(stats);
684  for (Int_t i = 0; i < TH1::kNstat; i++)
685  totstats[i] += stats[i];
686  nentries += hist->GetEntries();
687 
688  // Int_t nx = hist->GetXaxis()->GetNbins();
689  // loop on bins of the histogram and do the merge
690  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
691 
692  Double_t cu = hist->RetrieveBinContent(ibin);
693  Double_t e1sq = TMath::Abs(cu);
694  if (fH0->fSumw2.fN)
695  e1sq = hist->GetBinErrorSqUnchecked(ibin);
696 
697  Double_t xu = hist->GetBinCenter(ibin);
698  Int_t jbin = fH0->FindBin(xu);
699 
700  fH0->AddBinContent(jbin, cu);
701  if (fH0->fSumw2.fN)
702  fH0->fSumw2.fArray[jbin] += e1sq;
703  }
704  }
705  // copy merged stats
706  fH0->PutStats(totstats);
707  fH0->SetEntries(nentries);
708 
709  return kTRUE;
710 }
711 
713 {
714 
715  TIter next(&fInputList);
716  while (TH1* hist = (TH1*)next()) {
717  // support also case where some histogram have limits and some have the buffer
718  if ( !TH1Merger::AxesHaveLimits(hist) && hist->fBuffer ) {
719 
720  if (gDebug)
721  Info("TH1Merger::BufferMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
722  CopyBuffer(hist, fH0);
723  fInputList.Remove(hist);
724  }
725  }
726  // return true if the merge is completed
727  if (fInputList.GetSize() == 0) {
728  // all histo have been merged
729  return kTRUE;
730  }
731  // we need to reset the buffer in case of merging later on
732  // is this really needed ???
733  if (fH0->fBuffer) fH0->BufferEmpty(1);
734 
735  return kFALSE;
736 }
737 
739 
740 
741  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
742  for (Int_t i=0;i<TH1::kNstat;i++) {
743  totstats[i] = stats[i] = 0;
744  }
745  fH0->GetStats(totstats);
747 
748  TIter next(&fInputList);
749  while (TH1* hist=(TH1*)next()) {
750  // process only if the histogram has limits; otherwise it was processed before
751  // in the case of an existing buffer (see if statement just before)
752 
753  if (gDebug)
754  Info("TH1Merger::SameAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
755 
756  // skip empty histograms
757  if (hist->IsEmpty()) continue;
758 
759  // import statistics
760  hist->GetStats(stats);
761  for (Int_t i=0; i<TH1::kNstat; i++)
762  totstats[i] += stats[i];
763  nentries += hist->GetEntries();
764 
765  //Int_t nx = hist->GetXaxis()->GetNbins();
766  // loop on bins of the histogram and do the merge
767  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
768 
769  Double_t cu = hist->RetrieveBinContent(ibin);
770  Double_t e1sq = TMath::Abs(cu);
771  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
772 
773  fH0->AddBinContent(ibin,cu);
774  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ibin] += e1sq;
775 
776  }
777  }
778  //copy merged stats
779  fH0->PutStats(totstats);
780  fH0->SetEntries(nentries);
781 
782  return kTRUE;
783 }
784 
785 
786 /**
787  Merged histogram when axis can be different.
788  Histograms are merged looking at bin center positions
789 
790  */
792 
793  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
794  for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
795  fH0->GetStats(totstats);
797 
798  TIter next(&fInputList);
799  while (TH1* hist=(TH1*)next()) {
800 
801  if (gDebug)
802  Info("TH1Merger::DifferentAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
803 
804  // skip empty histograms
805  if (hist->IsEmpty()) continue;
806 
807  // import statistics
808  hist->GetStats(stats);
809  for (Int_t i=0;i<TH1::kNstat;i++)
810  totstats[i] += stats[i];
811  nentries += hist->GetEntries();
812 
813  // loop on bins of the histogram and do the merge
814  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
815 
816  Double_t cu = hist->RetrieveBinContent(ibin);
817  Double_t e1sq = TMath::Abs(cu);
818  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
819 
820  // if bin is empty we can skip it
821  if (cu == 0 && e1sq == 0) continue;
822 
823  Int_t binx,biny,binz;
824  hist->GetBinXYZ(ibin, binx, biny, binz);
825 
826  // case of underflow/overflows in the histogram being merged
827  if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
828  if (fH0->fXaxis.CanExtend() || ( hist->fXaxis.GetBinCenter(binx) > fH0->fXaxis.GetXmin() && hist->fXaxis.GetBinCenter(binx) < fH0->fXaxis.GetXmax()) ) {
829  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the X axis or have"
830  " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
831  return kFALSE;
832  }
833  }
834  if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
835  if (fH0->fYaxis.CanExtend() || ( hist->fYaxis.GetBinCenter(biny) > fH0->fYaxis.GetXmin() && hist->fYaxis.GetBinCenter(biny) < fH0->fYaxis.GetXmax()) ) {
836  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Y axis or have"
837  " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
838  return kFALSE;
839  }
840  }
841  if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
842  if (fH0->fZaxis.CanExtend() || ( hist->fZaxis.GetBinCenter(binz) > fH0->fZaxis.GetXmin() && hist->fZaxis.GetBinCenter(binz) < fH0->fZaxis.GetXmax()) ) {
843  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Z axis or have"
844  " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
845  return kFALSE;
846  }
847  }
848 
849  Int_t ix = 0;
850  Int_t iy = 0;
851  Int_t iz = 0;
852 
853  // we can extend eventually the axis if histogram is capable of doing it
854  // by using FindBin
855  ix = fH0->fXaxis.FindBin(hist->GetXaxis()->GetBinCenter(binx));
856  if (fH0->fDimension > 1)
857  iy = fH0->fYaxis.FindBin(hist->GetYaxis()->GetBinCenter(biny));
858  if (fH0->fDimension > 2)
859  iz = fH0->fZaxis.FindBin(hist->GetZaxis()->GetBinCenter(binz));
860 
861  Int_t ib = fH0->GetBin(ix,iy,iz);
862  if (ib < 0 || ib > fH0->fNcells) {
863  Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
864  fH0->GetName(), ib,fH0->fNcells);
865  }
866 
867  fH0->AddBinContent(ib,cu);
868  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ib] += e1sq;
869  }
870  }
871  //copy merged stats
872  fH0->PutStats(totstats);
873  fH0->SetEntries(nentries);
874 
875  return kTRUE;
876 }
877 
878 
879 /**
880  Merge histograms with labels
881 */
883 
884 
885  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
886  for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
887  fH0->GetStats(totstats);
889 
890  TIter next(&fInputList);
891  while (TH1* hist=(TH1*)next()) {
892 
893  if (gDebug)
894  Info("TH1Merger::LabelMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
895 
896  // skip empty histograms
897  if (hist->IsEmpty()) continue;
898 
899  // import statistics
900  hist->GetStats(stats);
901  for (Int_t i=0;i<TH1::kNstat;i++)
902  totstats[i] += stats[i];
903  nentries += hist->GetEntries();
904 
905  auto labelsX = hist->GetXaxis()->GetLabels();
906  auto labelsY = hist->GetYaxis()->GetLabels();
907  auto labelsZ = hist->GetZaxis()->GetLabels();
908  R__ASSERT(!( labelsX == nullptr && labelsY == nullptr && labelsZ == nullptr));
909 
910  // loop on bins of the histogram and do the merge
911  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
912 
913  Double_t cu = hist->RetrieveBinContent(ibin);
914  Double_t e1sq = cu;
915  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
916 
917  // if bin is empty we can skip it
918  if (cu == 0 && e1sq == 0) continue;
919 
920  Int_t binx,biny,binz;
921  hist->GetBinXYZ(ibin, binx, biny, binz);
922 
923  // here only in the case of bins with labels
924  const char * labelX = 0;
925  const char * labelY = 0;
926  const char * labelZ = 0;
927  labelX=hist->GetXaxis()->GetBinLabel(binx);
928  if (fH0->fDimension > 1) labelY = hist->GetYaxis()->GetBinLabel(biny);
929  if (fH0->fDimension > 2) labelZ = hist->GetYaxis()->GetBinLabel(binz);
930  // do we need to support case when there are bins with labels and bins without them ??
931  // this case should have been detected before when examining the histograms
932 
933 
934  Int_t ix = -1;
935  Int_t iy = (fH0->fDimension > 1) ? -1 : 0;
936  Int_t iz = (fH0->fDimension > 2) ? -1 : 0;
937 
938  // special case for underflow/overflows which have normally empty labels
939  if (binx == 0 && TString(labelX) == "" ) ix = 0;
940  if (binx == hist->fXaxis.GetNbins() +1 && TString(labelX) == "" ) ix = fH0->fXaxis.GetNbins() +1;
941  if (fH0->fDimension > 1 ) {
942  if (biny == 0 && TString(labelY) == "" ) iy = 0;
943  if (biny == hist->fYaxis.GetNbins() +1 && TString(labelY) == "" ) iy = fH0->fYaxis.GetNbins() +1;
944  }
945  if (fH0->fDimension > 2 ) {
946  if (binz == 0 && TString(labelZ) == "" ) iz = 0;
947  if (binz == hist->fZaxis.GetNbins() +1 && TString(labelZ) == "" ) iz = fH0->fZaxis.GetNbins() +1;
948  }
949 
950 
951 
952  // find corresponding case (in case bin is not overflow)
953  if (ix == -1) {
954  if (labelsX)
955  ix = fH0->fXaxis.FindBin(labelX);
956  else
957  ix = FindFixBinNumber(binx, hist->fXaxis, fH0->fXaxis);
958  }
959 
960  if (iy == -1 && fH0->fDimension> 1 ) { // check on dim should not be needed
961  if (labelsY)
962  iy= fH0->fYaxis.FindBin(labelY);
963  else
964  iy = FindFixBinNumber(biny, hist->fYaxis, fH0->fYaxis);
965  }
966  if (iz == -1 && fH0->fDimension> 2) {
967  if (labelsZ)
968  iz= fH0->fZaxis.FindBin(labelZ);
969  else
970  iz = FindFixBinNumber(binz, hist->fZaxis, fH0->fZaxis);
971  }
972 
973  if (gDebug)
974  Info("TH1Merge::LabelMerge","Merge bin [%d,%d,%d] with label [%s,%s,%s] into bin [%d,%d,%d]",
975  binx,biny,binz,labelX,labelY,labelZ,ix,iy,iz);
976 
977  Int_t ib = fH0->GetBin(ix,iy,iz);
978  if (ib < 0 || ib >= fH0->fNcells) {
979  Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
980  fH0->GetName(), ib,fH0->fNcells);
981  }
982 
983  fH0->AddBinContent(ib,cu);
984  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ib] += e1sq;
985  }
986  }
987  //copy merged stats
988  fH0->PutStats(totstats);
989  fH0->SetEntries(nentries);
990 
991  return kTRUE;
992 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Int_t FindBin(Double_t x, Double_t y=0, Double_t z=0)
Return Global bin number corresponding to x,y,z.
Definition: TH1.cxx:3565
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3244
TH1 * fHClone
histogram on which the list is merged
Definition: TH1Merger.h:92
float xmin
Definition: THbookFile.cxx:93
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition: TH1.cxx:8397
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:444
#define PRINTRANGE(a, b, bn)
Definition: TH1Merger.cxx:15
static Bool_t AxesHaveLimits(const TH1 *h)
Definition: TH1Merger.cxx:19
void DefineNewAxes()
Function to define new histogram axis when merging It is call only in case of merging with different ...
Definition: TH1Merger.cxx:474
void Fatal(const char *location, const char *msgfmt,...)
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition: TH1.cxx:8194
TAxis fNewYAxis
Definition: TH1Merger.h:95
void swap(TDirectoryEntry &e1, TDirectoryEntry &e2) noexcept
TAxis fYaxis
Y axis descriptor.
Definition: TH1.h:88
virtual void PutStats(Double_t *stats)
Replace current statistics with the values in array stats.
Definition: TH1.cxx:7202
const Double_t * GetArray() const
Definition: TArrayD.h:43
virtual void SetBins(Int_t nx, Double_t xmin, Double_t xmax)
Redefine x axis parameters.
Definition: TH1.cxx:8024
TH1 * h
Definition: legend2.C:5
static Bool_t SameLimitsAndNBins(const TAxis &axis1, const TAxis &axis2)
Same limits and bins.
Definition: TH1.cxx:5344
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4763
virtual Int_t GetEntries() const
Definition: TCollection.h:177
Bool_t LabelMerge()
Merge histograms with labels.
Definition: TH1Merger.cxx:882
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:97
#define R__ASSERT(e)
Definition: TError.h:96
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
static Int_t FindFixBinNumber(Int_t ibin, const TAxis &inAxis, const TAxis &outAxis)
Definition: TH1Merger.h:32
Basic string class.
Definition: TString.h:125
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TList fInputList
copy of fH0 - managed by this class
Definition: TH1Merger.h:93
TArrayD fSumw2
Array of sum of squares of weights.
Definition: TH1.h:101
static Bool_t RecomputeAxisLimits(TAxis &destAxis, const TAxis &anAxis)
Finds new limits for the axis for the Merge function.
Definition: TH1.cxx:5355
TAxis fZaxis
Z axis descriptor.
Definition: TH1.h:89
Bool_t CanExtend() const
Definition: TAxis.h:82
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
Bool_t AutoP2BufferMerge()
Definition: TH1Merger.cxx:571
void CopyBuffer(TH1 *hsrc, TH1 *hdes)
Definition: TH1Merger.cxx:540
void Reset()
Definition: TCollection.h:250
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void GetStats(Double_t *stats) const
fill the array stats from the contents of this histogram The array stats must be correctly dimensione...
Definition: TH1.cxx:7150
virtual Bool_t CanExtendAllAxes() const
Returns true if all axes are extendable.
Definition: TH1.cxx:6087
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:6545
TAxis fNewZAxis
Definition: TH1Merger.h:96
virtual Int_t GetDimension() const
Definition: TH1.h:277
Double_t GetXmin() const
Definition: TAxis.h:133
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Bool_t operator()()
Function performing the actual merge.
Definition: TH1Merger.cxx:27
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
Use Power(2)-based algorithm for autobinning.
Definition: TH1.h:169
THashList * GetLabels() const
Definition: TAxis.h:117
static double p2(double t, double a, double b, double c)
void Info(const char *location, const char *msgfmt,...)
Double_t * fArray
Definition: TArrayD.h:30
virtual void AddBinContent(Int_t bin)
Increment bin content by 1.
Definition: TH1.cxx:1200
void Error(const char *location, const char *msgfmt,...)
The 3-D histogram classes derived from the 1-D histogram classes.
Definition: TH3.h:31
Bool_t DifferentAxesMerge()
Merged histogram when axis can be different.
Definition: TH1Merger.cxx:791
UInt_t fNewAxisFlag
Definition: TH1Merger.h:97
Int_t fN
Definition: TArray.h:38
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis from bin first to last.
Definition: TAxis.cxx:903
TAxis fNewXAxis
Definition: TH1Merger.h:94
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:455
Service class for 2-Dim histogram classes.
Definition: TH2.h:30
Class to manage histogram axis.
Definition: TAxis.h:30
Int_t GetSize() const
Definition: TArray.h:47
void SetCanExtend(Bool_t canExtend)
Definition: TAxis.h:86
Bool_t AutoP2BuildAxes(TH1 *)
Determine final boundaries and number of bins for histograms created in power-of-2 autobin mode...
Definition: TH1Merger.cxx:77
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Copy(TObject &hnew) const
Copy this histogram structure to newth1.
Definition: TH1.cxx:2585
Bool_t SameAxesMerge()
Definition: TH1Merger.cxx:738
TAxis * GetYaxis()
Definition: TH1.h:316
static double p1(double t, double a, double b)
float xmax
Definition: THbookFile.cxx:93
void Warning(const char *location, const char *msgfmt,...)
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition: TH1.cxx:4665
REAL epsilon
Definition: triangle.c:617
virtual Double_t RetrieveBinContent(Int_t bin) const
Raw retrieval of bin content on internal data structure see convention for numbering bins in TH1::Get...
Definition: TH1.cxx:8695
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:279
virtual Int_t GetSumw2N() const
Definition: TH1.h:309
Bool_t CanBeAlphanumeric()
Definition: TAxis.h:83
Bool_t BufferMerge()
Definition: TH1Merger.cxx:712
double Double_t
Definition: RtypesCore.h:55
EMergerType ExamineHistograms()
Examine the list of histograms to find out which type of Merge we need to do Pass the input list cont...
Definition: TH1Merger.cxx:216
int type
Definition: TGX11.cxx:120
int nentries
Definition: THbookFile.cxx:89
The TH1 histogram class.
Definition: TH1.h:56
virtual Double_t GetEntries() const
Return the current number of entries.
Definition: TH1.cxx:4178
TAxis * GetZaxis()
Definition: TH1.h:317
virtual UInt_t SetCanExtend(UInt_t extendBitMask)
Make the histogram axes extendable / not extendable according to the bit mask returns the previous bi...
Definition: TH1.cxx:6100
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual Double_t GetBinErrorSqUnchecked(Int_t bin) const
Definition: TH1.h:435
virtual void SetBinsLength(Int_t=-1)
Definition: TH1.h:368
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition: TH1.cxx:8276
TObject * Clone(const char *newname=0) const
Make a complete copy of the underlying object.
Definition: TH1.cxx:2662
Int_t fDimension
!Histogram dimension (1, 2 or 3 dim)
Definition: TH1.h:107
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition: TH1.cxx:1346
virtual void SetEntries(Double_t n)
Definition: TH1.h:378
TAxis fXaxis
X axis descriptor.
Definition: TH1.h:87
Bool_t IsEmpty() const
Definition: TH1.h:138
void ResetBit(UInt_t f)
Definition: TObject.h:171
TH1 * fH0
Definition: TH1Merger.h:91
Int_t GetNbins() const
Definition: TAxis.h:121
virtual Int_t GetSize() const
Definition: TCollection.h:180
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition: TAxis.cxx:717
Double_t * fBuffer
[fBufferSize] entry buffer
Definition: TH1.h:105
const Bool_t kTRUE
Definition: RtypesCore.h:87
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:106
Double_t GetXmax() const
Definition: TAxis.h:134
Bool_t AutoP2Merge()
Definition: TH1Merger.cxx:614
const TArrayD * GetXbins() const
Definition: TAxis.h:130
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:315
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8319
Int_t fNcells
number of bins(1D), cells (2D) +U/Overflows
Definition: TH1.h:86