Logo ROOT   6.07/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 otehr case then we merge using FindBin
49  return DifferentAxesMerge();
50  }
51  Error("TH1Merger","Unknown type");
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: (%d, %f, %f), second: (%d, %f, %f)",
161  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: (%d, %f, %f), second: (%d, %f, %f)",
176  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: (%d, %f, %f), second: (%d, %f, %f)",
187  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  if (histoIsEmpty) continue;
204  THashList* hlabels=h->GetXaxis()->GetLabels();
205  Bool_t haveOneLabel = (hlabels != nullptr);
206  // do here to print message only one time
207  if (foundLabelHist && allHaveLabels && !haveOneLabel) {
208  Warning("Merge","Not all histograms have labels. I will ignore labels,"
209  " falling back to bin numbering mode.");
210  }
211 
212  allHaveLabels &= (haveOneLabel);
213  // for the error message
214  if (haveOneLabel) foundLabelHist = kTRUE;
215 
216  if (foundLabelHist && gDebug)
217  Info("TH1Merger::ExamineHistogram","Histogram %s has labels",h->GetName() );
218 
219  // If histograms have labels but CanExtendAllAxes() is false
220  // use bin center mode
221  if (allHaveLabels && !fH0->CanExtendAllAxes()) {
222  // special case for this histogram when is empty
223  // and axis cannot be extended (because it is the default)
224  if ( fH0->IsEmpty() ) {
225  if (gDebug)
226  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());
227  UInt_t bitMaskX = fH0->GetXaxis()->CanBeAlphanumeric() & TH1::kXaxis;
228  UInt_t bitMaskY = (fH0->GetYaxis()->CanBeAlphanumeric() << 1 ) & TH1::kYaxis;
229  UInt_t bitMaskZ = (fH0->GetZaxis()->CanBeAlphanumeric() << 2 ) & TH1::kZaxis;
230  fH0->SetCanExtend(bitMaskX | bitMaskY | bitMaskZ );
231  }
232  if (!fH0->CanExtendAllAxes()) {
233  if (gDebug)
234  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());
235  allHaveLabels = kFALSE;
236  }
237  }
238  // I could add a check if histogram contains bins without a label
239  // and with non-zero bin content
240  // Do we want to support this ???
241  // only in case the !h->CanExtendAllAxes()
242  if (allHaveLabels && !h->CanExtendAllAxes()) {
243  // count number of bins with non-null content
244  Int_t non_zero_bins = 0;
245  Int_t nbins = h->GetXaxis()->GetNbins();
246  if (nbins > hlabels->GetEntries() ) {
247  for (Int_t i = 1; i <= nbins; i++) {
248  if (h->RetrieveBinContent(i) != 0 || (fH0->fSumw2.fN && h->GetBinError(i) != 0) ) {
249  non_zero_bins++;
250  }
251  }
252  if (non_zero_bins > hlabels->GetEntries() ) {
253  Warning("TH1Merger::ExamineHistograms","Histogram %s contains non-empty bins without labels - falling back to bin numbering mode",h->GetName() );
254  allHaveLabels = kFALSE;
255  }
256  }
257  }
258  }
259  if (gDebug)
260  Info("TH1Merger::ExamineHistogram","Examine histogram %s - labels %d - same limits %d - axis found %d",h->GetName(),allHaveLabels,allSameLimits,initialLimitsFound );
261 
262  } while ( ( h = dynamic_cast<TH1*> ( next() ) ) != NULL );
263 
264  if (!h && (*next) ) {
265  Error("Merge","Attempt to merge object of class: %s to a %s",
266  (*next)->ClassName(),fH0->ClassName());
267  return kNotCompatible;
268  }
269 
270  // return the type of merge
271  if (allHaveLabels) return kAllLabel;
272  if (allSameLimits) return kAllSameAxes;
273  if (!initialLimitsFound) {
274  R__ASSERT(!allHaveLimits);
275  // case where no limits are found and the buffer is used
276  return kAllNoLimits;
277  }
278  // remaining case should be the mixed one. Some histogram have limits some not
279  fNewAxisFlag = 0;
280  if (!sameLimitsX) fNewAxisFlag |= TH1::kXaxis;
281  if (!sameLimitsY) fNewAxisFlag |= TH1::kYaxis;
282  if (!sameLimitsZ) fNewAxisFlag |= TH1::kZaxis;
283 
284  // we need to set the flag also in case this histogram has no limits
285  // we need to set explicitly the flag to re-define a new axis
287  if (dimension > 1 && fH0->GetYaxis()->GetXmin() >= fH0->GetYaxis()->GetXmax()) fNewAxisFlag |= TH1::kYaxis;
288  if (dimension > 2 && fH0->GetZaxis()->GetXmin() >= fH0->GetZaxis()->GetXmax()) fNewAxisFlag |= TH1::kZaxis;
289 
290 
291  return kHasNewLimits;
292 
293 }
294 
295 /**
296  Function to define new histogram axis when merging
297  It is call only in case of merging with different axis or with the
298  buffer (kHasNewLimits)
299 */
300 
302 
303  // first we need to create a copy of the histogram in case is not empty
304 
305  if (!fH0->IsEmpty() ) {
306  Bool_t mustCleanup = fH0->TestBit(kMustCleanup);
307  if (mustCleanup) fH0->ResetBit(kMustCleanup);
308  fHClone = (TH1*)fH0->IsA()->New();
309  fHClone->SetDirectory(0);
310  fH0->Copy(*fHClone);
311  if (mustCleanup) fH0->SetBit(kMustCleanup);
312  fH0->BufferEmpty(1); // To remove buffer.
313  fH0->Reset(); // BufferEmpty sets limits so we can't use it later.
314  fH0->SetEntries(0);
316 
317  }
318 
319  bool newLimitsX = (fNewAxisFlag & TH1::kXaxis);
320  bool newLimitsY = (fNewAxisFlag & TH1::kYaxis);
321  bool newLimitsZ = (fNewAxisFlag & TH1::kZaxis);
322  if (newLimitsX) {
323  fH0->fXaxis.SetRange(0,0);
324  if (fNewXAxis.GetXbins()->GetSize() != 0)
326  else
328  }
329  if (newLimitsY) {
330  fH0->fYaxis.SetRange(0,0);
331  if (fNewYAxis.GetXbins()->GetSize() != 0)
333  else
335  }
336  if (newLimitsZ) {
337  fH0->fZaxis.SetRange(0,0);
338  if (fNewZAxis.GetXbins()->GetSize() != 0)
340  else
342  }
343 
344  // we need to recompute fNcells and set the array size (as in TH1::SetBins)
345  fH0->fNcells = fH0->fXaxis.GetNbins()+2;
346  if (fH0->fDimension > 1) fH0->fNcells *= fH0->fYaxis.GetNbins()+2;
347  if (fH0->fDimension > 2) fH0->fNcells *= fH0->fZaxis.GetNbins()+2;
349  if (fH0->fSumw2.fN) fH0->fSumw2.Set(fH0->fNcells);
350  // set dummy Y and Z axis for lower dim histogras
351  if (fH0->fDimension < 3) fH0->fZaxis.Set(1,0,1);
352  if (fH0->fDimension < 2) fH0->fYaxis.Set(1,0,1);
353 
354  if (gDebug) {
355  if (newLimitsX) Info("DefineNewAxis","A new X axis has been defined Nbins=%d , [%f,%f]", fH0->fXaxis.GetNbins(),
356  fH0->fXaxis.GetXmin(), fH0->fXaxis.GetXmax() );
357  if (newLimitsY) Info("DefineNewAxis","A new Y axis has been defined Nbins=%d , [%f,%f]", fH0->fYaxis.GetNbins(),
358  fH0->fYaxis.GetXmin(), fH0->fYaxis.GetXmax() );
359  if (newLimitsZ) Info("DefineNewAxis","A new Z axis has been defined Nbins=%d , [%f,%f]", fH0->fZaxis.GetNbins(),
360  fH0->fZaxis.GetXmin(), fH0->fZaxis.GetXmax() );
361  }
362 
363  return;
364 
365 }
366 
368 
369  TIter next(&fInputList);
370  while (TH1* hist = (TH1*)next()) {
371  // support also case where some histogram have limits and some have the buffer
372  if ( !TH1Merger::AxesHaveLimits(hist) && hist->fBuffer ) {
373 
374  if (gDebug)
375  Info("TH1Merger::BufferMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
376 
377 
378  // case of no limits
379  // Entries from buffers have to be filled one by one
380  // because FillN doesn't resize histograms.
381  Int_t nbentries = (Int_t)hist->fBuffer[0];
382  if (fH0->fDimension == 1) {
383  for (Int_t i = 0; i < nbentries; i++)
384  fH0->Fill(hist->fBuffer[2*i + 2], hist->fBuffer[2*i + 1]);
385  }
386  if (fH0->fDimension == 2) {
387  auto h2 = dynamic_cast<TH2*>(fH0);
388  R__ASSERT(h2);
389  for (Int_t i = 0; i < nbentries; i++)
390  h2->Fill(hist->fBuffer[3*i + 2], hist->fBuffer[3*i + 3],hist->fBuffer[3*i + 1] );
391  }
392  if (fH0->fDimension == 3) {
393  auto h3 = dynamic_cast<TH3*>(fH0);
394  R__ASSERT(h3);
395  for (Int_t i = 0; i < nbentries; i++)
396  h3->Fill(hist->fBuffer[4*i + 2], hist->fBuffer[4*i + 3],hist->fBuffer[4*i + 4], hist->fBuffer[4*i + 1] );
397  }
398  fInputList.Remove(hist);
399  }
400  }
401  // return true if the merge is completed
402  if (fInputList.GetSize() == 0) {
403  // all histo have been merged
404  return kTRUE;
405  }
406  // we need to reset the buffer in case of merging later on
407  // is this really needed ???
408  if (fH0->fBuffer) fH0->BufferEmpty(1);
409 
410  return kFALSE;
411 }
412 
414 
415 
416  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
417  for (Int_t i=0;i<TH1::kNstat;i++) {
418  totstats[i] = stats[i] = 0;
419  }
420  fH0->GetStats(totstats);
422 
423  TIter next(&fInputList);
424  while (TH1* hist=(TH1*)next()) {
425  // process only if the histogram has limits; otherwise it was processed before
426  // in the case of an existing buffer (see if statement just before)
427 
428  if (gDebug)
429  Info("TH1Merger::SameAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
430 
431  // skip empty histograms
432  if (hist->IsEmpty()) continue;
433 
434  // import statistics
435  hist->GetStats(stats);
436  for (Int_t i=0; i<TH1::kNstat; i++)
437  totstats[i] += stats[i];
438  nentries += hist->GetEntries();
439 
440  //Int_t nx = hist->GetXaxis()->GetNbins();
441  // loop on bins of the histogram and do the merge
442  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
443 
444  Double_t cu = hist->RetrieveBinContent(ibin);
445  Double_t e1sq = TMath::Abs(cu);
446  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
447 
448  fH0->AddBinContent(ibin,cu);
449  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ibin] += e1sq;
450 
451  }
452  }
453  //copy merged stats
454  fH0->PutStats(totstats);
455  fH0->SetEntries(nentries);
456 
457  return kTRUE;
458 }
459 
460 
461 /**
462  Merged histogram when axis can be different.
463  Histograms are merged looking at bin center positions
464 
465  */
467 
468  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
469  for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
470  fH0->GetStats(totstats);
472 
473  TIter next(&fInputList);
474  while (TH1* hist=(TH1*)next()) {
475 
476  if (gDebug)
477  Info("TH1Merger::DifferentAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
478 
479  // skip empty histograms
480  if (hist->IsEmpty()) continue;
481 
482  // import statistics
483  hist->GetStats(stats);
484  for (Int_t i=0;i<TH1::kNstat;i++)
485  totstats[i] += stats[i];
486  nentries += hist->GetEntries();
487 
488  // loop on bins of the histogram and do the merge
489  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
490 
491  Double_t cu = hist->RetrieveBinContent(ibin);
492  Double_t e1sq = TMath::Abs(cu);
493  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
494 
495  // if bin is empty we can skip it
496  if (cu == 0 && e1sq == 0) continue;
497 
498  if (hist->IsBinUnderflow(ibin) || hist->IsBinOverflow(ibin) ) {
499  Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms have"
500  " different limits and underflows/overflows are present."
501  " The initial histogram is now broken!");
502  return kFALSE;
503  }
504 
505  Int_t binx,biny,binz;
506  hist->GetBinXYZ(ibin, binx, biny, binz);
507 
508 
509 
510  Int_t ix = 0;
511  Int_t iy = 0;
512  Int_t iz = 0;
513 
514  // we can extend eventually the axis if histogram is capable of doing it
515  // by using FindBIn
516  ix = fH0->fXaxis.FindBin(hist->GetXaxis()->GetBinCenter(binx));
517  if (fH0->fDimension > 1)
518  iy = fH0->fYaxis.FindBin(hist->GetYaxis()->GetBinCenter(biny));
519  if (fH0->fDimension > 2)
520  iz = fH0->fZaxis.FindBin(hist->GetZaxis()->GetBinCenter(binz));
521 
522  Int_t ib = fH0->GetBin(ix,iy,iz);
523  if (ib < 0 || ib > fH0->fNcells) {
524  Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
525  fH0->GetName(), ib,fH0->fNcells);
526  }
527 
528  fH0->AddBinContent(ib,cu);
529  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ib] += e1sq;
530  }
531  }
532  //copy merged stats
533  fH0->PutStats(totstats);
534  fH0->SetEntries(nentries);
535 
536  return kTRUE;
537 }
538 
539 
540 /**
541  Merge histograms with labels
542 */
544 
545 
546  Double_t stats[TH1::kNstat], totstats[TH1::kNstat];
547  for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
548  fH0->GetStats(totstats);
550 
551  TIter next(&fInputList);
552  while (TH1* hist=(TH1*)next()) {
553 
554  if (gDebug)
555  Info("TH1Merger::LabelMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
556 
557  // skip empty histograms
558  if (hist->IsEmpty()) continue;
559 
560  // import statistics
561  hist->GetStats(stats);
562  for (Int_t i=0;i<TH1::kNstat;i++)
563  totstats[i] += stats[i];
564  nentries += hist->GetEntries();
565 
566  auto labelsX = hist->GetXaxis()->GetLabels();
567  auto labelsY = hist->GetYaxis()->GetLabels();
568  auto labelsZ = hist->GetZaxis()->GetLabels();
569  R__ASSERT(!( labelsX == nullptr && labelsY == nullptr && labelsZ == nullptr));
570 
571  // loop on bins of the histogram and do the merge
572  for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
573 
574  Double_t cu = hist->RetrieveBinContent(ibin);
575  Double_t e1sq = cu;
576  if (fH0->fSumw2.fN) e1sq= hist->GetBinErrorSqUnchecked(ibin);
577 
578  // if bin is empty we can skip it
579  if (cu == 0 && e1sq == 0) continue;
580 
581  Int_t binx,biny,binz;
582  hist->GetBinXYZ(ibin, binx, biny, binz);
583 
584  // here only in the case of bins with labels
585  const char * labelX = 0;
586  const char * labelY = 0;
587  const char * labelZ = 0;
588  labelX=hist->GetXaxis()->GetBinLabel(binx);
589  if (fH0->fDimension > 1) labelY = hist->GetYaxis()->GetBinLabel(biny);
590  if (fH0->fDimension > 2) labelZ = hist->GetYaxis()->GetBinLabel(binz);
591  // do we need to support case when there are bins with labels and bins without them ??
592  // this case should have been detected before when examining the histograms
593 
594 
595  Int_t ix = -1;
596  Int_t iy = (fH0->fDimension > 1) ? -1 : 0;
597  Int_t iz = (fH0->fDimension > 2) ? -1 : 0;
598 
599  // special case for underflow/overflows which have normally empty labels
600  if (binx == 0 && TString(labelX) == "" ) ix = 0;
601  if (binx == hist->fXaxis.GetNbins() +1 && TString(labelX) == "" ) ix = fH0->fXaxis.GetNbins() +1;
602  if (fH0->fDimension > 1 ) {
603  if (biny == 0 && TString(labelY) == "" ) iy = 0;
604  if (biny == hist->fYaxis.GetNbins() +1 && TString(labelY) == "" ) iy = fH0->fYaxis.GetNbins() +1;
605  }
606  if (fH0->fDimension > 2 ) {
607  if (binz == 0 && TString(labelZ) == "" ) iz = 0;
608  if (binz == hist->fZaxis.GetNbins() +1 && TString(labelZ) == "" ) iz = fH0->fZaxis.GetNbins() +1;
609  }
610 
611 
612 
613  // find corresponding case (in case bin is not overflow)
614  if (ix == -1) {
615  if (labelsX)
616  ix = fH0->fXaxis.FindBin(labelX);
617  else
618  ix = FindFixBinNumber(binx, hist->fXaxis, fH0->fXaxis);
619  }
620 
621  if (iy == -1 && fH0->fDimension> 1 ) { // check on dim should not be needed
622  if (labelsY)
623  iy= fH0->fYaxis.FindBin(labelY);
624  else
625  iy = FindFixBinNumber(biny, hist->fYaxis, fH0->fYaxis);
626  }
627  if (iz == -1 && fH0->fDimension> 2) {
628  if (labelsZ)
629  iz= fH0->fZaxis.FindBin(labelZ);
630  else
631  iz = FindFixBinNumber(binz, hist->fZaxis, fH0->fZaxis);
632  }
633 
634  if (gDebug)
635  Info("TH1Merge::LabelMerge","Merge bin [%d,%d,%d] with label [%s,%s,%s] into bin [%d,%d,%d]",
636  binx,biny,binz,labelX,labelY,labelZ,ix,iy,iz);
637 
638  Int_t ib = fH0->GetBin(ix,iy,iz);
639  if (ib < 0 || ib >= fH0->fNcells) {
640  Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
641  fH0->GetName(), ib,fH0->fNcells);
642  }
643 
644  fH0->AddBinContent(ib,cu);
645  if (fH0->fSumw2.fN) fH0->fSumw2.fArray[ib] += e1sq;
646  }
647  }
648  //copy merged stats
649  fH0->PutStats(totstats);
650  fH0->SetEntries(nentries);
651 
652  return kTRUE;
653 }
virtual Int_t GetEntries() const
Definition: TCollection.h:92
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3127
TH1 * fHClone
histogram on which the list is merged
Definition: TH1Merger.h:70
Bool_t IsEmpty() const
Definition: TH1.h:154
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:301
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:8008
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:6975
TAxis fNewYAxis
Definition: TH1Merger.h:73
TAxis fYaxis
Y axis descriptor.
Definition: TH1.h:105
virtual void PutStats(Double_t *stats)
Replace current statistics with the values in array stats.
Definition: TH1.cxx:7027
virtual Int_t GetDimension() const
Definition: TH1.h:287
TH1 * h
Definition: legend2.C:5
static Bool_t SameLimitsAndNBins(const TAxis &axis1, const TAxis &axis2)
Same limits and bins.
Definition: TH1.cxx:5193
Bool_t LabelMerge()
Merge histograms with labels.
Definition: TH1Merger.cxx:543
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:93
#define R__ASSERT(e)
Definition: TError.h:98
static Int_t FindFixBinNumber(Int_t ibin, const TAxis &inAxis, const TAxis &outAxis)
Definition: TH1Merger.h:21
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TList fInputList
copy of fH0 - managed bby this class
Definition: TH1Merger.h:71
const Bool_t kFALSE
Definition: Rtypes.h:92
int nbins[3]
TArrayD fSumw2
Array of sum of squares of weights.
Definition: TH1.h:118
static Bool_t RecomputeAxisLimits(TAxis &destAxis, const TAxis &anAxis)
Finds new limits for the axis for the Merge function.
Definition: TH1.cxx:5204
TAxis fZaxis
Z axis descriptor.
Definition: TH1.h:106
virtual Double_t GetEntries() const
Return the current number of entries.
Definition: TH1.cxx:4055
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:6375
TAxis fNewZAxis
Definition: TH1Merger.h:74
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:36
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:4542
void Info(const char *location, const char *msgfmt,...)
Double_t * fArray
Definition: TArrayD.h:32
virtual void AddBinContent(Int_t bin)
Increment bin content by 1.
Definition: TH1.cxx:1195
Double_t GetXmin() const
Definition: TAxis.h:139
void Error(const char *location, const char *msgfmt,...)
The 3-D histogram classes derived from the 1-D histogram classes.
Definition: TH3.h:35
Bool_t DifferentAxesMerge()
Merged histogram when axis can be different.
Definition: TH1Merger.cxx:466
UInt_t fNewAxisFlag
Definition: TH1Merger.h:75
Int_t fN
Definition: TArray.h:40
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:887
TAxis fNewXAxis
Definition: TH1Merger.h:72
Service class for 2-Dim histogram classes.
Definition: TH2.h:36
Int_t GetNbins() const
Definition: TAxis.h:127
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:188
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:675
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Bool_t SameAxesMerge()
Definition: TH1Merger.cxx:413
TAxis * GetYaxis()
Definition: TH1.h:325
void Warning(const char *location, const char *msgfmt,...)
const Double_t * GetArray() const
Definition: TArrayD.h:45
Int_t GetSize() const
Definition: TArray.h:49
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:279
Bool_t CanBeAlphanumeric()
Definition: TAxis.h:89
Bool_t BufferMerge()
Definition: TH1Merger.cxx:367
virtual Int_t GetSize() const
Definition: TCollection.h:95
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
Double_t GetXmax() const
Definition: TAxis.h:140
int nentries
Definition: THbookFile.cxx:89
The TH1 histogram class.
Definition: TH1.h:80
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:8498
TAxis * GetZaxis()
Definition: TH1.h:326
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:5930
THashList * GetLabels() const
Definition: TAxis.h:123
virtual void Copy(TObject &hnew) const
Copy this histogram structure to newth1.
Definition: TH1.cxx:2470
virtual void SetBinsLength(Int_t=-1)
Definition: TH1.h:377
virtual Bool_t CanExtendAllAxes() const
Returns true if all axes are extendable.
Definition: TH1.cxx:5917
#define NULL
Definition: Rtypes.h:82
Int_t fDimension
!Histogram dimension (1, 2 or 3 dim)
Definition: TH1.h:124
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition: TH1.cxx:1238
virtual void SetEntries(Double_t n)
Definition: TH1.h:387
TAxis fXaxis
X axis descriptor.
Definition: TH1.h:104
const TArrayD * GetXbins() const
Definition: TAxis.h:136
void ResetBit(UInt_t f)
Definition: TObject.h:158
TH1 * fH0
Definition: TH1Merger.h:69
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition: TAxis.cxx:716
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8130
const Bool_t kTRUE
Definition: Rtypes.h:91
Double_t * fBuffer
[fBufferSize] entry buffer
Definition: TH1.h:122
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:105
TAxis * GetXaxis()
Definition: TH1.h:324
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443
Int_t fNcells
number of bins(1D), cells (2D) +U/Overflows
Definition: TH1.h:103