Logo ROOT   6.10/09
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 
13 
15  Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
16  if (h->GetDimension() > 1) hasLimits &= h->GetYaxis()->GetXmin() < h->GetYaxis()->GetXmax();
17  if (h->GetDimension() > 2) hasLimits &= h->GetZaxis()->GetXmin() < h->GetZaxis()->GetXmax();
18  return hasLimits;
19 }
20 
21 /// Function performing the actual merge
23 
24 
26 
27  if (gDebug) Info("Merge","Histogram Merge type is %d and new axis flag is %d",(int) type,(int) fNewAxisFlag);
28 
29  if (type == kNotCompatible) return kFALSE;
30 
31  if (type == kAllSameAxes)
32  return SameAxesMerge();
33 
34  if (type == kAllLabel)
35  return LabelMerge();
36 
37  if (type == kAllNoLimits)
38  return BufferMerge();
39 
40  // this is the mixed case - more complicated
41  if (type == kHasNewLimits) {
42  // we need to define some new axes
43  DefineNewAxes();
44  // we might need to merge some histogram using the buffer
45  Bool_t ret = BufferMerge();
46  // if ret is true the merge is completed and we can exit
47  if (ret) return kTRUE;
48  // in the other cases then we merge using FindBin
49  return DifferentAxesMerge();
50  }
51  Error("TH1Merger","Unknown type of Merge for histogram %s",fH0->GetName());
52  return kFALSE;
53 }
54 
55 /**
56  Examine the list of histograms to find out which type of Merge we need to do
57  Pass the input list containing the histogram to merge and h0 which is the initial histogram
58  on which all the histogram of the list will be merged
59  This are the possible cases:
60  - 1. All histogram have the same axis (allSameLimits = true)
61  - 2. Histogram have different axis but compatible (allSameLimits = false) and sameLimitsX,Y,Z specifies which axis
62  has different limits
63  - 3. Histogram do not have limits (so the Buffer is used) allHaveLimits = false
64  - 3b. One histogram has limits the other not : allHaveLimits = false AND initialLimitsFound = true
65  - 4. Histogram Have labels = allHaveLabels = true
66 
67 
68 */
70 
71 
72 
73  Bool_t initialLimitsFound = kFALSE;
74  Bool_t allHaveLabels = kTRUE; // assume all histo have labels and check later
75  Bool_t allHaveLimits = kTRUE;
76  Bool_t allSameLimits = kTRUE;
77  Bool_t sameLimitsX = kTRUE;
78  Bool_t sameLimitsY = kTRUE;
79  Bool_t sameLimitsZ = kTRUE;
80  Bool_t foundLabelHist = kFALSE;
81 
82  // TAxis newXAxis;
83  // TAxis newYAxis;
84  // TAxis newZAxis;
85 
86  TIter next(&fInputList);
87  TH1 * h = fH0; // start with fH0
88 
89  int dimension = fH0->GetDimension();
90 
91  // start looping on the histograms
92 
93  do {
94 
95  // check first histogram compatibility
96  if (h != fH0) {
97  if (h->GetDimension() != dimension) {
98  Error("Merge", "Cannot merge histogram - dimensions are different\n "
99  "%s has dim=%d and %s has dim=%d",fH0->GetName(),dimension,h->GetName(),h->GetDimension());
100  return kNotCompatible;
101  }
102  }
103 
104 
105  // do not skip anymore empty histograms
106  // since are used to set the limits
107  Bool_t hasLimits = TH1Merger::AxesHaveLimits(h);
108  allHaveLimits = allHaveLimits && hasLimits;
109  allSameLimits &= allHaveLimits;
110 
111 
112  if (hasLimits) {
113  h->BufferEmpty();
114 
115 // // this is done in case the first histograms are empty and
116 // // the histogram have different limits
117 // #ifdef LATER
118 // if (firstHistWithLimits ) {
119 // // set axis limits in the case the first histogram did not have limits
120 // if (h != this && !SameLimitsAndNBins( fXaxis, *h->GetXaxis()) ) {
121 // if (h->GetXaxis()->GetXbins()->GetSize() != 0) fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
122 // else fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
123 // }
124 // firstHistWithLimits = kFALSE;
125 // }
126 // #endif
127 
128  // this is executed the first time an histogram with limits is found
129  // to set some initial values on the new axis
130  if (!initialLimitsFound) {
131  initialLimitsFound = kTRUE;
132  if (h->GetXaxis()->GetXbins()->GetSize() != 0)
133  fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
134  else
135  fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
136  if (dimension > 1) {
137  if (h->GetYaxis()->GetXbins()->GetSize() != 0)
138  fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXbins()->GetArray());
139  else
140  fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
141  }
142  if (dimension > 2) {
143  if (h->GetZaxis()->GetXbins()->GetSize() != 0)
144  fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXbins()->GetArray());
145  else
146  fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(), h->GetZaxis()->GetXmax());
147 
148  }
149  }
150  else {
151  // check first if histograms have same bins in X
152  if (!TH1::SameLimitsAndNBins(fNewXAxis, *(h->GetXaxis())) ) {
153  sameLimitsX = kFALSE;
154  // recompute the limits in this case the optimal limits
155  // The condition to works is that the histogram have same bin with
156  // and one common bin edge
158  Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
159  "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
161  h->GetName(),h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
162  h->GetXaxis()->GetXmax());
163  return kNotCompatible;
164  }
165  }
166  // check first if histograms have same bins in Y
167  if (dimension > 1 && !TH1::SameLimitsAndNBins(fNewYAxis, *(h->GetYaxis()))) {
168  sameLimitsY = kFALSE;
169  // recompute in this case the optimal limits
170  // The condition to works is that the histogram have same bin with
171  // and one common bin edge
173  Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
174  "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
176  h->GetName(), h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
177  h->GetYaxis()->GetXmax());
178  return kNotCompatible;
179  }
180  }
181  if(dimension > 2 && !fH0->SameLimitsAndNBins(fNewZAxis, *(h->GetZaxis()))) {
182  sameLimitsZ = kFALSE;
184  Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
185  "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
187  h->GetName(),h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
188  h->GetZaxis()->GetXmax());
189  return kNotCompatible;
190  }
191  }
192  allSameLimits = sameLimitsX && sameLimitsY && sameLimitsZ;
193 
194 
195  }
196  }
197  Bool_t histoIsEmpty = h->IsEmpty();
198  // std::cout << "considering histo " << h->GetName() << " labels - " << allHaveLabels << " is empty "
199  // << histoIsEmpty << std::endl;
200 
201  // if histogram is empty it does not matter if it has label or not
202  if (allHaveLabels && !histoIsEmpty) {
203  THashList* hlabels=h->GetXaxis()->GetLabels();
204  Bool_t haveOneLabel = (hlabels != nullptr);
205  // do here to print message only one time
206  if (foundLabelHist && allHaveLabels && !haveOneLabel) {
207  Warning("Merge","Not all histograms have labels. I will ignore labels,"
208  " falling back to bin numbering mode.");
209  }
210 
211  allHaveLabels &= (haveOneLabel);
212  // for the error message
213  if (haveOneLabel) foundLabelHist = kTRUE;
214 
215  if (foundLabelHist && gDebug)
216  Info("TH1Merger::ExamineHistogram","Histogram %s has labels",h->GetName() );
217 
218  // If histograms have labels but CanExtendAllAxes() is false
219  // use bin center mode
220  if (allHaveLabels && !fH0->CanExtendAllAxes()) {
221  // special case for this histogram when is empty
222  // and axis cannot be extended (because it is the default)
223  if ( fH0->IsEmpty() ) {
224  if (gDebug)
225  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());
226  UInt_t bitMaskX = fH0->GetXaxis()->CanBeAlphanumeric() & TH1::kXaxis;
227  UInt_t bitMaskY = (fH0->GetYaxis()->CanBeAlphanumeric() << 1 ) & TH1::kYaxis;
228  UInt_t bitMaskZ = (fH0->GetZaxis()->CanBeAlphanumeric() << 2 ) & TH1::kZaxis;
229  fH0->SetCanExtend(bitMaskX | bitMaskY | bitMaskZ );
230  }
231  if (!fH0->CanExtendAllAxes()) {
232  if (gDebug)
233  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());
234  allHaveLabels = kFALSE;
235  }
236  }
237  // I could add a check if histogram contains bins without a label
238  // and with non-zero bin content
239  // Do we want to support this ???
240  // only in case the !h->CanExtendAllAxes()
241  if (allHaveLabels && !h->CanExtendAllAxes()) {
242  // count number of bins with non-null content
243  Int_t non_zero_bins = 0;
244  Int_t nbins = h->GetXaxis()->GetNbins();
245  if (nbins > hlabels->GetEntries() ) {
246  for (Int_t i = 1; i <= nbins; i++) {
247  if (h->RetrieveBinContent(i) != 0 || (fH0->fSumw2.fN && h->GetBinError(i) != 0) ) {
248  non_zero_bins++;
249  }
250  }
251  if (non_zero_bins > hlabels->GetEntries() ) {
252  Warning("TH1Merger::ExamineHistograms","Histogram %s contains non-empty bins without labels - falling back to bin numbering mode",h->GetName() );
253  allHaveLabels = kFALSE;
254  }
255  }
256  }
257  }
258  if (gDebug)
259  Info("TH1Merger::ExamineHistogram","Examine histogram %s - labels %d - same limits %d - axis found %d",h->GetName(),allHaveLabels,allSameLimits,initialLimitsFound );
260 
261  } while ( ( h = dynamic_cast<TH1*> ( next() ) ) != NULL );
262 
263  if (!h && (*next) ) {
264  Error("Merge","Attempt to merge object of class: %s to a %s",
265  (*next)->ClassName(),fH0->ClassName());
266  return kNotCompatible;
267  }
268 
269  // return the type of merge
270  if (allHaveLabels) return kAllLabel;
271  if (allSameLimits) return kAllSameAxes;
272  if (!initialLimitsFound) {
273  R__ASSERT(!allHaveLimits);
274  // case where no limits are found and the buffer is used
275  return kAllNoLimits;
276  }
277  // remaining case should be the mixed one. Some histogram have limits some not
278  fNewAxisFlag = 0;
279  if (!sameLimitsX) fNewAxisFlag |= TH1::kXaxis;
280  if (!sameLimitsY) fNewAxisFlag |= TH1::kYaxis;
281  if (!sameLimitsZ) fNewAxisFlag |= TH1::kZaxis;
282 
283  // we need to set the flag also in case this histogram has no limits
284  // we need to set explicitly the flag to re-define a new axis
286  if (dimension > 1 && fH0->GetYaxis()->GetXmin() >= fH0->GetYaxis()->GetXmax()) fNewAxisFlag |= TH1::kYaxis;
287  if (dimension > 2 && fH0->GetZaxis()->GetXmin() >= fH0->GetZaxis()->GetXmax()) fNewAxisFlag |= TH1::kZaxis;
288 
289 
290  return kHasNewLimits;
291 
292 }
293 
294 /**
295  Function to define new histogram axis when merging
296  It is call only in case of merging with different axis or with the
297  buffer (kHasNewLimits)
298 */
299 
301 
302  // first we need to create a copy of the histogram in case is not empty
303 
304  if (!fH0->IsEmpty() ) {
305  Bool_t mustCleanup = fH0->TestBit(kMustCleanup);
306  if (mustCleanup) fH0->ResetBit(kMustCleanup);
307  fHClone = (TH1*)fH0->IsA()->New();
308  fHClone->SetDirectory(0);
309  fH0->Copy(*fHClone);
310  if (mustCleanup) fH0->SetBit(kMustCleanup);
311  fH0->BufferEmpty(1); // To remove buffer.
312  fH0->Reset(); // BufferEmpty sets limits so we can't use it later.
313  fH0->SetEntries(0);
315 
316  }
317 
318  bool newLimitsX = (fNewAxisFlag & TH1::kXaxis);
319  bool newLimitsY = (fNewAxisFlag & TH1::kYaxis);
320  bool newLimitsZ = (fNewAxisFlag & TH1::kZaxis);
321  if (newLimitsX) {
322  fH0->fXaxis.SetRange(0,0);
323  if (fNewXAxis.GetXbins()->GetSize() != 0)
325  else
327  }
328  if (newLimitsY) {
329  fH0->fYaxis.SetRange(0,0);
330  if (fNewYAxis.GetXbins()->GetSize() != 0)
332  else
334  }
335  if (newLimitsZ) {
336  fH0->fZaxis.SetRange(0,0);
337  if (fNewZAxis.GetXbins()->GetSize() != 0)
339  else
341  }
342 
343  // we need to recompute fNcells and set the array size (as in TH1::SetBins)
344  fH0->fNcells = fH0->fXaxis.GetNbins()+2;
345  if (fH0->fDimension > 1) fH0->fNcells *= fH0->fYaxis.GetNbins()+2;
346  if (fH0->fDimension > 2) fH0->fNcells *= fH0->fZaxis.GetNbins()+2;
348  if (fH0->fSumw2.fN) fH0->fSumw2.Set(fH0->fNcells);
349  // set dummy Y and Z axis for lower dim histogras
350  if (fH0->fDimension < 3) fH0->fZaxis.Set(1,0,1);
351  if (fH0->fDimension < 2) fH0->fYaxis.Set(1,0,1);
352 
353  if (gDebug) {
354  if (newLimitsX) Info("DefineNewAxis","A new X axis has been defined Nbins=%d , [%f,%f]", fH0->fXaxis.GetNbins(),
355  fH0->fXaxis.GetXmin(), fH0->fXaxis.GetXmax() );
356  if (newLimitsY) Info("DefineNewAxis","A new Y axis has been defined Nbins=%d , [%f,%f]", fH0->fYaxis.GetNbins(),
357  fH0->fYaxis.GetXmin(), fH0->fYaxis.GetXmax() );
358  if (newLimitsZ) Info("DefineNewAxis","A new Z axis has been defined Nbins=%d , [%f,%f]", fH0->fZaxis.GetNbins(),
359  fH0->fZaxis.GetXmin(), fH0->fZaxis.GetXmax() );
360  }
361 
362  return;
363 
364 }
365 
367 
368  TIter next(&fInputList);
369  while (TH1* hist = (TH1*)next()) {
370  // support also case where some histogram have limits and some have the buffer
371  if ( !TH1Merger::AxesHaveLimits(hist) && hist->fBuffer ) {
372 
373  if (gDebug)
374  Info("TH1Merger::BufferMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
375 
376 
377  // case of no limits
378  // Entries from buffers have to be filled one by one
379  // because FillN doesn't resize histograms.
380  Int_t nbentries = (Int_t)hist->fBuffer[0];
381  if (fH0->fDimension == 1) {
382  for (Int_t i = 0; i < nbentries; i++)
383  fH0->Fill(hist->fBuffer[2*i + 2], hist->fBuffer[2*i + 1]);
384  }
385  if (fH0->fDimension == 2) {
386  auto h2 = dynamic_cast<TH2*>(fH0);
387  R__ASSERT(h2);
388  for (Int_t i = 0; i < nbentries; i++)
389  h2->Fill(hist->fBuffer[3*i + 2], hist->fBuffer[3*i + 3],hist->fBuffer[3*i + 1] );
390  }
391  if (fH0->fDimension == 3) {
392  auto h3 = dynamic_cast<TH3*>(fH0);
393  R__ASSERT(h3);
394  for (Int_t i = 0; i < nbentries; i++)
395  h3->Fill(hist->fBuffer[4*i + 2], hist->fBuffer[4*i + 3],hist->fBuffer[4*i + 4], hist->fBuffer[4*i + 1] );
396  }
397  fInputList.Remove(hist);
398  }
399  }
400  // return true if the merge is completed
401  if (fInputList.GetSize() == 0) {
402  // all histo have been merged
403  return kTRUE;
404  }
405  // we need to reset the buffer in case of merging later on
406  // is this really needed ???
407  if (fH0->fBuffer) fH0->BufferEmpty(1);
408 
409  return kFALSE;
410 }
411 
413 
414 
415  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
416  for (Int_t i=0;i<TH1::kNstat;i++) {
417  totstats[i] = stats[i] = 0;
418  }
419  fH0->GetStats(totstats);
421 
422  TIter next(&fInputList);
423  while (TH1* hist=(TH1*)next()) {
424  // process only if the histogram has limits; otherwise it was processed before
425  // in the case of an existing buffer (see if statement just before)
426 
427  if (gDebug)
428  Info("TH1Merger::SameAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
429 
430  // skip empty histograms
431  if (hist->IsEmpty()) continue;
432 
433  // import statistics
434  hist->GetStats(stats);
435  for (Int_t i=0; i<TH1::kNstat; i++)
436  totstats[i] += stats[i];
437  nentries += hist->GetEntries();
438 
439  //Int_t nx = hist->GetXaxis()->GetNbins();
440  // loop on bins of the histogram and do the merge
441  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
442 
443  Double_t cu = hist->RetrieveBinContent(ibin);
444  Double_t e1sq = TMath::Abs(cu);
445  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
446 
447  fH0->AddBinContent(ibin,cu);
448  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ibin] += e1sq;
449 
450  }
451  }
452  //copy merged stats
453  fH0->PutStats(totstats);
454  fH0->SetEntries(nentries);
455 
456  return kTRUE;
457 }
458 
459 
460 /**
461  Merged histogram when axis can be different.
462  Histograms are merged looking at bin center positions
463 
464  */
466 
467  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
468  for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
469  fH0->GetStats(totstats);
471 
472  TIter next(&fInputList);
473  while (TH1* hist=(TH1*)next()) {
474 
475  if (gDebug)
476  Info("TH1Merger::DifferentAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
477 
478  // skip empty histograms
479  if (hist->IsEmpty()) continue;
480 
481  // import statistics
482  hist->GetStats(stats);
483  for (Int_t i=0;i<TH1::kNstat;i++)
484  totstats[i] += stats[i];
485  nentries += hist->GetEntries();
486 
487  // loop on bins of the histogram and do the merge
488  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
489 
490  Double_t cu = hist->RetrieveBinContent(ibin);
491  Double_t e1sq = TMath::Abs(cu);
492  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
493 
494  // if bin is empty we can skip it
495  if (cu == 0 && e1sq == 0) continue;
496 
497  Int_t binx,biny,binz;
498  hist->GetBinXYZ(ibin, binx, biny, binz);
499 
500  // case of underflow/overflows in the histogram being merged
501  if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
502  if (fH0->fXaxis.CanExtend() || ( hist->fXaxis.GetBinCenter(binx) > fH0->fXaxis.GetXmin() && hist->fXaxis.GetBinCenter(binx) < fH0->fXaxis.GetXmax()) ) {
503  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the X axis or have"
504  " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
505  return kFALSE;
506  }
507  }
508  if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
509  if (fH0->fYaxis.CanExtend() || ( hist->fYaxis.GetBinCenter(biny) > fH0->fYaxis.GetXmin() && hist->fYaxis.GetBinCenter(biny) < fH0->fYaxis.GetXmax()) ) {
510  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Y axis or have"
511  " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
512  return kFALSE;
513  }
514  }
515  if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
516  if (fH0->fZaxis.CanExtend() || ( hist->fZaxis.GetBinCenter(binz) > fH0->fZaxis.GetXmin() && hist->fZaxis.GetBinCenter(binz) < fH0->fZaxis.GetXmax()) ) {
517  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Z axis or have"
518  " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
519  return kFALSE;
520  }
521  }
522 
523  Int_t ix = 0;
524  Int_t iy = 0;
525  Int_t iz = 0;
526 
527  // we can extend eventually the axis if histogram is capable of doing it
528  // by using FindBin
529  ix = fH0->fXaxis.FindBin(hist->GetXaxis()->GetBinCenter(binx));
530  if (fH0->fDimension > 1)
531  iy = fH0->fYaxis.FindBin(hist->GetYaxis()->GetBinCenter(biny));
532  if (fH0->fDimension > 2)
533  iz = fH0->fZaxis.FindBin(hist->GetZaxis()->GetBinCenter(binz));
534 
535  Int_t ib = fH0->GetBin(ix,iy,iz);
536  if (ib < 0 || ib > fH0->fNcells) {
537  Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
538  fH0->GetName(), ib,fH0->fNcells);
539  }
540 
541  fH0->AddBinContent(ib,cu);
542  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ib] += e1sq;
543  }
544  }
545  //copy merged stats
546  fH0->PutStats(totstats);
547  fH0->SetEntries(nentries);
548 
549  return kTRUE;
550 }
551 
552 
553 /**
554  Merge histograms with labels
555 */
557 
558 
559  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
560  for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
561  fH0->GetStats(totstats);
563 
564  TIter next(&fInputList);
565  while (TH1* hist=(TH1*)next()) {
566 
567  if (gDebug)
568  Info("TH1Merger::LabelMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
569 
570  // skip empty histograms
571  if (hist->IsEmpty()) continue;
572 
573  // import statistics
574  hist->GetStats(stats);
575  for (Int_t i=0;i<TH1::kNstat;i++)
576  totstats[i] += stats[i];
577  nentries += hist->GetEntries();
578 
579  auto labelsX = hist->GetXaxis()->GetLabels();
580  auto labelsY = hist->GetYaxis()->GetLabels();
581  auto labelsZ = hist->GetZaxis()->GetLabels();
582  R__ASSERT(!( labelsX == nullptr && labelsY == nullptr && labelsZ == nullptr));
583 
584  // loop on bins of the histogram and do the merge
585  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
586 
587  Double_t cu = hist->RetrieveBinContent(ibin);
588  Double_t e1sq = cu;
589  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
590 
591  // if bin is empty we can skip it
592  if (cu == 0 && e1sq == 0) continue;
593 
594  Int_t binx,biny,binz;
595  hist->GetBinXYZ(ibin, binx, biny, binz);
596 
597  // here only in the case of bins with labels
598  const char * labelX = 0;
599  const char * labelY = 0;
600  const char * labelZ = 0;
601  labelX=hist->GetXaxis()->GetBinLabel(binx);
602  if (fH0->fDimension > 1) labelY = hist->GetYaxis()->GetBinLabel(biny);
603  if (fH0->fDimension > 2) labelZ = hist->GetYaxis()->GetBinLabel(binz);
604  // do we need to support case when there are bins with labels and bins without them ??
605  // this case should have been detected before when examining the histograms
606 
607 
608  Int_t ix = -1;
609  Int_t iy = (fH0->fDimension > 1) ? -1 : 0;
610  Int_t iz = (fH0->fDimension > 2) ? -1 : 0;
611 
612  // special case for underflow/overflows which have normally empty labels
613  if (binx == 0 && TString(labelX) == "" ) ix = 0;
614  if (binx == hist->fXaxis.GetNbins() +1 && TString(labelX) == "" ) ix = fH0->fXaxis.GetNbins() +1;
615  if (fH0->fDimension > 1 ) {
616  if (biny == 0 && TString(labelY) == "" ) iy = 0;
617  if (biny == hist->fYaxis.GetNbins() +1 && TString(labelY) == "" ) iy = fH0->fYaxis.GetNbins() +1;
618  }
619  if (fH0->fDimension > 2 ) {
620  if (binz == 0 && TString(labelZ) == "" ) iz = 0;
621  if (binz == hist->fZaxis.GetNbins() +1 && TString(labelZ) == "" ) iz = fH0->fZaxis.GetNbins() +1;
622  }
623 
624 
625 
626  // find corresponding case (in case bin is not overflow)
627  if (ix == -1) {
628  if (labelsX)
629  ix = fH0->fXaxis.FindBin(labelX);
630  else
631  ix = FindFixBinNumber(binx, hist->fXaxis, fH0->fXaxis);
632  }
633 
634  if (iy == -1 && fH0->fDimension> 1 ) { // check on dim should not be needed
635  if (labelsY)
636  iy= fH0->fYaxis.FindBin(labelY);
637  else
638  iy = FindFixBinNumber(biny, hist->fYaxis, fH0->fYaxis);
639  }
640  if (iz == -1 && fH0->fDimension> 2) {
641  if (labelsZ)
642  iz= fH0->fZaxis.FindBin(labelZ);
643  else
644  iz = FindFixBinNumber(binz, hist->fZaxis, fH0->fZaxis);
645  }
646 
647  if (gDebug)
648  Info("TH1Merge::LabelMerge","Merge bin [%d,%d,%d] with label [%s,%s,%s] into bin [%d,%d,%d]",
649  binx,biny,binz,labelX,labelY,labelZ,ix,iy,iz);
650 
651  Int_t ib = fH0->GetBin(ix,iy,iz);
652  if (ib < 0 || ib >= fH0->fNcells) {
653  Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
654  fH0->GetName(), ib,fH0->fNcells);
655  }
656 
657  fH0->AddBinContent(ib,cu);
658  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ib] += e1sq;
659  }
660  }
661  //copy merged stats
662  fH0->PutStats(totstats);
663  fH0->SetEntries(nentries);
664 
665  return kTRUE;
666 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3126
TH1 * fHClone
histogram on which the list is merged
Definition: TH1Merger.h:84
static Bool_t AxesHaveLimits(const TH1 *h)
Definition: TH1Merger.cxx:14
void DefineNewAxes()
Function to define new histogram axis when merging It is call only in case of merging with different ...
Definition: TH1Merger.cxx:300
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:8053
TAxis fNewYAxis
Definition: TH1Merger.h:87
TAxis fYaxis
Y axis descriptor.
Definition: TH1.h:81
virtual void PutStats(Double_t *stats)
Replace current statistics with the values in array stats.
Definition: TH1.cxx:7073
const Double_t * GetArray() const
Definition: TArrayD.h:43
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
TH1 * h
Definition: legend2.C:5
static Bool_t SameLimitsAndNBins(const TAxis &axis1, const TAxis &axis2)
Same limits and bins.
Definition: TH1.cxx:5220
virtual Int_t GetEntries() const
Definition: TCollection.h:86
Bool_t LabelMerge()
Merge histograms with labels.
Definition: TH1Merger.cxx:556
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
static Int_t FindFixBinNumber(Int_t ibin, const TAxis &inAxis, const TAxis &outAxis)
Definition: TH1Merger.h:31
Basic string class.
Definition: TString.h:129
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:85
int nbins[3]
TArrayD fSumw2
Array of sum of squares of weights.
Definition: TH1.h:94
#define NULL
Definition: RtypesCore.h:88
static Bool_t RecomputeAxisLimits(TAxis &destAxis, const TAxis &anAxis)
Finds new limits for the axis for the Merge function.
Definition: TH1.cxx:5231
TAxis fZaxis
Z axis descriptor.
Definition: TH1.h:82
Bool_t CanExtend() const
Definition: TAxis.h:82
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:687
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:7021
virtual Bool_t CanExtendAllAxes() const
Returns true if all axes are extendable.
Definition: TH1.cxx:5961
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:6419
TAxis fNewZAxis
Definition: TH1Merger.h:88
virtual Int_t GetDimension() const
Definition: TH1.h:263
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:135
Bool_t operator()()
Function performing the actual merge.
Definition: TH1Merger.cxx:22
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
THashList * GetLabels() const
Definition: TAxis.h:117
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:1193
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:465
UInt_t fNewAxisFlag
Definition: TH1Merger.h:89
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:889
TAxis fNewXAxis
Definition: TH1Merger.h:86
Service class for 2-Dim histogram classes.
Definition: TH2.h:30
Int_t GetSize() const
Definition: TArray.h:47
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:679
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Copy(TObject &hnew) const
Copy this histogram structure to newth1.
Definition: TH1.cxx:2468
Bool_t SameAxesMerge()
Definition: TH1Merger.cxx:412
TAxis * GetYaxis()
Definition: TH1.h:301
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:4541
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:8543
const Bool_t kFALSE
Definition: RtypesCore.h:92
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:279
Bool_t CanBeAlphanumeric()
Definition: TAxis.h:83
Bool_t BufferMerge()
Definition: TH1Merger.cxx:366
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:69
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:4054
TAxis * GetZaxis()
Definition: TH1.h:302
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:5974
virtual void SetBinsLength(Int_t=-1)
Definition: TH1.h:353
Int_t fDimension
!Histogram dimension (1, 2 or 3 dim)
Definition: TH1.h:100
R__EXTERN Int_t gDebug
Definition: Rtypes.h:83
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition: TH1.cxx:1236
virtual void SetEntries(Double_t n)
Definition: TH1.h:363
TAxis fXaxis
X axis descriptor.
Definition: TH1.h:80
Bool_t IsEmpty() const
Definition: TH1.h:130
void ResetBit(UInt_t f)
Definition: TObject.h:158
TH1 * fH0
Definition: TH1Merger.h:83
Int_t GetNbins() const
Definition: TAxis.h:121
virtual Int_t GetSize() const
Definition: TCollection.h:89
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:98
const Bool_t kTRUE
Definition: RtypesCore.h:91
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:105
Double_t GetXmax() const
Definition: TAxis.h:134
const TArrayD * GetXbins() const
Definition: TAxis.h:130
TAxis * GetXaxis()
Definition: TH1.h:300
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8175
Int_t fNcells
number of bins(1D), cells (2D) +U/Overflows
Definition: TH1.h:79