Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
43 return LabelMerge(true);
44
45 if (type == kAllNoLimits)
46 return BufferMerge();
47
49 return AutoP2Merge();
50
51 // this is the mixed case - more complicated
52 if (type == kHasNewLimits) {
53 // we need to define some new axes
55 // we might need to merge some histogram using the buffer
57 // if ret is true the merge is completed and we can exit
58 if (ret) return kTRUE;
59 // in the other cases then we merge using FindBin
60 return DifferentAxesMerge();
61 }
62 Error("TH1Merger","Unknown type of Merge for histogram %s",fH0->GetName());
63 return kFALSE;
64}
65
66/////////////////////////////////////////////////////////////////////////////////////////
67/// Determine final boundaries and number of bins for histograms created in power-of-2
68/// autobin mode.
69///
70/// Return kTRUE if compatible, updating fNewXaxis accordingly; return kFALSE if something
71/// wrong.
72///
73/// The histograms are not merge-compatible if
74///
75/// 1. have different variable-size bins
76/// 2. larger bin size is not an integer multiple of the smaller one
77/// 3. the final estimated range is smalle then the bin size
78///
79
81{
82 // They must be both defined
83 if (!h) {
84 Error("AutoP2BuildAxes", "undefined histogram: %p", h);
85 return kFALSE;
86 }
87
88 // They must be created in power-of-2 autobin mode
89 if (!h->TestBit(TH1::kAutoBinPTwo)) {
90 Error("AutoP2BuildAxes", "not in autobin-power-of-2 mode!");
91 return kFALSE;
92 }
93
94 // Point to axes
95 TAxis *a0 = &fNewXAxis, *a1 = h->GetXaxis();
96
97 // This is for future merging of detached ranges (only possible if no over/underflows)
98 Bool_t canextend = (h->GetBinContent(0) > 0 || h->GetBinContent(a1->GetNbins() + 1) > 0) ? kFALSE : kTRUE;
99
100 // The first time we just copy the boundaries and bins
101 if (a0->GetFirst() == a0->GetLast()) {
102 a0->Set(a1->GetNbins(), a1->GetXmin(), a1->GetXmax());
103 // This is for future merging of detached ranges (only possible if no over/underflows)
104 a0->SetCanExtend(canextend);
105 return kTRUE;
106 }
107
108 // Bin sizes must be in integer ratio
109 Double_t bwmax = (a0->GetXmax() - a0->GetXmin()) / a0->GetNbins();
110 Double_t bwmin = (a1->GetXmax() - a1->GetXmin()) / a1->GetNbins();
111 Bool_t b0 = kTRUE;
112 if (bwmin > bwmax) {
113 std::swap(bwmax, bwmin);
114 b0 = kFALSE;
115 }
116 if (!(bwmin > 0.)) {
117 PRINTRANGE(a0, a1, h->GetName());
118 Error("AutoP2BuildAxes", "minimal bin width negative or null: %f", bwmin);
119 return kFALSE;
120 }
121
122 Double_t rt;
123 Double_t re = std::modf(bwmax / bwmin, &rt);
124 if (re > std::numeric_limits<Double_t>::epsilon()) {
125 PRINTRANGE(a0, a1, h->GetName());
126 Error("AutoP2BuildAxes", "bin widths not in integer ratio: %f", re);
127 return kFALSE;
128 }
129
130 // Range of the merged histogram, taking into account overlaps
133 if (a0->GetXmin() < a1->GetXmin()) {
134 if (a0->GetXmax() < a1->GetXmin()) {
135 if (!a0->CanExtend() || !canextend) {
136 PRINTRANGE(a0, a1, h->GetName());
137 Error("AutoP2BuildAxes", "ranges are disconnected and under/overflows: cannot merge");
138 return kFALSE;
139 }
140 xmax = a1->GetXmax();
141 xmin = a0->GetXmin();
142 domax = b0 ? kTRUE : kFALSE;
143 } else {
144 if (a0->GetXmax() >= a1->GetXmax()) {
145 xmax = a1->GetXmax();
146 xmin = a1->GetXmin();
147 domax = !b0 ? kTRUE : kFALSE;
148 } else {
149 xmax = a0->GetXmax();
150 xmin = a1->GetXmin();
151 domax = !b0 ? kTRUE : kFALSE;
152 }
153 }
154 } else {
155 if (a1->GetXmax() < a0->GetXmin()) {
156 if (!a0->CanExtend() || !canextend) {
157 PRINTRANGE(a0, a1, h->GetName());
158 Error("AutoP2BuildAxes", "ranges are disconnected and under/overflows: cannot merge");
159 return kFALSE;
160 }
161 xmax = a0->GetXmax();
162 xmin = a1->GetXmin();
163 domax = !b0 ? kTRUE : kFALSE;
164 } else {
165 if (a1->GetXmax() >= a0->GetXmax()) {
166 xmax = a0->GetXmax();
167 xmin = a0->GetXmin();
168 domax = b0 ? kTRUE : kFALSE;
169 } else {
170 xmax = a1->GetXmax();
171 xmin = a0->GetXmin();
172 domax = b0 ? kTRUE : kFALSE;
173 }
174 }
175 }
177
178 re = std::modf(range / bwmax, &rt);
179 if (rt < 1.) {
180 PRINTRANGE(a0, a1, h->GetName());
181 Error("MergeCompatibleHistograms", "range smaller than bin width: %f %f %f", range, bwmax, rt);
182 return kFALSE;
183 }
184 if (re > std::numeric_limits<Double_t>::epsilon()) {
185 if (domax) {
186 xmax -= bwmax * re;
187 } else {
188 xmin += bwmax * re;
189 }
190 }
191 // Number of bins
192 Int_t nb = (Int_t)rt;
193
194 // Set the result
195 a0->Set(nb, xmin, xmax);
196
197 // This is for future merging of detached ranges (only possible if no over/underflows)
198 if (!a0->CanExtend())
199 a0->SetCanExtend(canextend);
200
201 // Done
202 return kTRUE;
203}
204
205/**
206 Examine the list of histograms to find out which type of Merge we need to do
207 Pass the input list containing the histogram to merge and h0 which is the initial histogram
208 on which all the histogram of the list will be merged
209 This are the possible cases:
210 - 1. All histogram have the same axis (allSameLimits = true)
211 - 2. Histogram have different axis but compatible (allSameLimits = false) and sameLimitsX,Y,Z specifies which axis
212 has different limits
213 - 3. Histogram do not have limits (so the Buffer is used) allHaveLimits = false
214 - 3b. One histogram has limits the other not : allHaveLimits = false AND initialLimitsFound = true
215 - 4. Histogram Have labels = allHaveLabels = true
216
217
218*/
220
221
222
224 Bool_t allHaveLabels = kTRUE; // assume all histo have labels and check later
225 UInt_t labelAxisType = TH1::kNoAxis; // type of axes that have label
233
235
236 // TAxis newXAxis;
237 // TAxis newYAxis;
238 // TAxis newZAxis;
239
240 TIter next(&fInputList);
241 TH1 * h = fH0; // start with fH0
242
243 int dimension = fH0->GetDimension();
244
246
247 // if the option alphanumeric merge is set
248 // we assume we do not have labels
250
251 // start looping on the histograms
252
253 do {
254
255 // check first histogram compatibility
256 if (h != fH0) {
257 if (h->GetDimension() != dimension) {
258 Error("Merge", "Cannot merge histogram - dimensions are different\n "
259 "%s has dim=%d and %s has dim=%d",fH0->GetName(),dimension,h->GetName(),h->GetDimension());
260 return kNotCompatible;
261 }
262 }
263
264 // check if one of the histogram is weighted
265 haveWeights |= h->GetSumw2N() != 0;
266
267 // do not skip anymore empty histograms
268 // since are used to set the limits
272
273 if (isAutoP2 && !h->TestBit(TH1::kAutoBinPTwo)) {
274 Error("Merge", "Cannot merge histogram - some are in autobin-power-of-2 mode, but not %s!", h->GetName());
275 return kNotCompatible;
276 }
277 if (!isAutoP2 && h->TestBit(TH1::kAutoBinPTwo)) {
278 Error("Merge", "Cannot merge histogram - %s is in autobin-power-of-2 mode, but not the previous ones",
279 h->GetName());
280 return kNotCompatible;
281 }
282
283 if (hasLimits) {
284 h->BufferEmpty();
285
286// // this is done in case the first histograms are empty and
287// // the histogram have different limits
288// #ifdef LATER
289// if (firstHistWithLimits ) {
290// // set axis limits in the case the first histogram did not have limits
291// if (h != this && !SameLimitsAndNBins( fXaxis, *h->GetXaxis()) ) {
292// if (h->GetXaxis()->GetXbins()->GetSize() != 0) fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
293// else fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
294// }
295// firstHistWithLimits = kFALSE;
296// }
297// #endif
298
299 // this is executed the first time an histogram with limits is found
300 // to set some initial values on the new axis
301 if (!initialLimitsFound) {
303 if (h->GetXaxis()->GetXbins()->GetSize() != 0)
304 fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
305 else
306 fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
307 if (dimension > 1) {
308 if (h->GetYaxis()->GetXbins()->GetSize() != 0)
309 fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXbins()->GetArray());
310 else
311 fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
312 }
313 if (dimension > 2) {
314 if (h->GetZaxis()->GetXbins()->GetSize() != 0)
315 fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXbins()->GetArray());
316 else
317 fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(), h->GetZaxis()->GetXmax());
318
319 }
320 }
321 else {
322 // check first if histograms have same bins in X
323 if (!TH1::SameLimitsAndNBins(fNewXAxis, *(h->GetXaxis())) ) {
325 // recompute the limits in this case the optimal limits
326 // The condition to works is that the histogram have same bin with
327 // and one common bin edge
328 if (!TH1::RecomputeAxisLimits(fNewXAxis, *(h->GetXaxis()))) {
329 Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
330 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
332 h->GetName(),h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
333 h->GetXaxis()->GetXmax());
334 return kNotCompatible;
335 }
336 }
337 // check first if histograms have same bins in Y
338 if (dimension > 1 && !TH1::SameLimitsAndNBins(fNewYAxis, *(h->GetYaxis()))) {
340 // recompute in this case the optimal limits
341 // The condition to works is that the histogram have same bin with
342 // and one common bin edge
343 if (!TH1::RecomputeAxisLimits(fNewYAxis, *(h->GetYaxis()))) {
344 Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
345 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
347 h->GetName(), h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
348 h->GetYaxis()->GetXmax());
349 return kNotCompatible;
350 }
351 }
352 if(dimension > 2 && !fH0->SameLimitsAndNBins(fNewZAxis, *(h->GetZaxis()))) {
354 if (!TH1::RecomputeAxisLimits(fNewZAxis, *(h->GetZaxis()))) {
355 Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
356 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
358 h->GetName(),h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
359 h->GetZaxis()->GetXmax());
360 return kNotCompatible;
361 }
362 }
364
365
366 }
367 }
368 Bool_t histoIsEmpty = h->IsEmpty();
369 // std::cout << "considering histo " << h->GetName() << " labels - " << allHaveLabels << " is empty "
370 // << histoIsEmpty << std::endl;
371
372 // if histogram is empty it does not matter if it has label or not
373 if (allHaveLabels && !histoIsEmpty) {
374 THashList* hlabelsX = h->GetXaxis()->GetLabels();
375 THashList* hlabelsY = (dimension > 1) ? h->GetYaxis()->GetLabels() : nullptr;
376 THashList* hlabelsZ = (dimension > 2) ? h->GetZaxis()->GetLabels() : nullptr;
377 Bool_t haveOneLabelX = hlabelsX != nullptr;
378 Bool_t haveOneLabelY = hlabelsY != nullptr;
379 Bool_t haveOneLabelZ = hlabelsZ != nullptr;
381 // do here to print message only one time
383 Warning("Merge","Not all histograms have labels. I will ignore labels,"
384 " falling back to bin numbering mode.");
385 }
386
388
389 if (haveOneLabel) {
391 UInt_t type = 0;
396 // check if all histogram have consistent label axis
397 // this means that there is at least one axis where boith histogram have labels
400 if (!consistentLabels)
401 Warning("TH1Merger::ExamineHistogram","Histogram %s has inconsistent labels: %d is not consistent with %d",
402 h->GetName(), (int) type, (int) labelAxisType );
404 Info("TH1Merger::ExamineHistogram","Histogram %s has consistent labels",h->GetName() );
405 }
406
407 // Check compatibility of axis that have labels with axis that can be extended
410 if (dimension > 1 && fH0->GetYaxis()->CanExtend()) extendAxisType |= TH1::kYaxis;
411 if (dimension > 2 && fH0->GetZaxis()->CanExtend()) extendAxisType |= TH1::kZaxis;
412 // it is sufficient to have a consistent label axis that can be extended
414 // If histograms have labels but corresponding axes cannot be extended use bin center mode
416 // special case for this histogram when is empty
417 // and axis cannot be extended (because it is the default)
418 if ( fH0->IsEmpty() ) {
419 if (gDebug)
420 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());
422 }
423 else { // histogram is not empty
424 if (gDebug)
425 Info("TH1Merger::ExamineHistogram","Histogram %s to be merged has labels but corresponding axis cannot be extended - using bin numeric mode to merge. Call TH1::SetCanExtend(TH1::kAllAxes) if want to merge using label mode",fH0->GetName());
427 }
428 }
429 // we don't need to check anymore for the case of non empty histograms containing labels.
430 // If we have some labels set and the axis is not extendable the LabelsMerge function handles
431 // that case correctly and falls back to a numeric merge
432
433 }
434 if (gDebug)
435 Info("TH1Merger::ExamineHistogram","Examine histogram %s - labels %d - same limits %d - axis found %d",h->GetName(),allHaveLabels,allSameLimits,initialLimitsFound );
436
437 } while ( ( h = dynamic_cast<TH1*> ( next() ) ) != nullptr );
438
439 if (!h && (*next) ) {
440 Error("Merge","Attempt to merge object of class: %s to a %s",
441 (*next)->ClassName(),fH0->ClassName());
442 return kNotCompatible;
443 }
444
445 // in case of weighted histogram set Sumw2() on fH0 is is not weighted
446 if (haveWeights && fH0->GetSumw2N() == 0)
447 fH0->Sumw2();
448
449 // AutoP2
450 if (isAutoP2) {
451 if (allHaveLimits)
452 return kAutoP2HaveLimits;
453 return kAutoP2NeedLimits;
454 }
455
456 // return the type of merge
458 if (allSameLimits) return kAllSameAxes;
459 if (!initialLimitsFound) {
461 // case where no limits are found and the buffer is used
462 return kAllNoLimits;
463 }
464 // remaining case should be the mixed one. Some histogram have limits some not
465 fNewAxisFlag = 0;
469
470 // we need to set the flag also in case this histogram has no limits
471 // we need to set explicitly the flag to re-define a new axis
473 if (dimension > 1 && fH0->GetYaxis()->GetXmin() >= fH0->GetYaxis()->GetXmax()) fNewAxisFlag |= TH1::kYaxis;
474 if (dimension > 2 && fH0->GetZaxis()->GetXmin() >= fH0->GetZaxis()->GetXmax()) fNewAxisFlag |= TH1::kZaxis;
475
477
478 return kHasNewLimits;
479
480}
481
482/**
483 Function to define new histogram axis when merging
484 It is call only in case of merging with different axis or with the
485 buffer (kHasNewLimits)
486*/
487
489
490 // first we need to create a copy of the histogram in case is not empty
491
492 if (!fH0->IsEmpty() ) {
495 fHClone = (TH1*)fH0->IsA()->New();
496 fHClone->SetDirectory(nullptr);
497 fH0->Copy(*fHClone);
499 fH0->BufferEmpty(1); // To remove buffer.
500 fH0->Reset(); // BufferEmpty sets limits so we can't use it later.
501 fH0->SetEntries(0);
503
504 }
505
509 if (newLimitsX) {
510 fH0->fXaxis.SetRange(0,0);
511 if (fNewXAxis.GetXbins()->GetSize() != 0)
513 else
515 }
516 if (newLimitsY) {
517 fH0->fYaxis.SetRange(0,0);
518 if (fNewYAxis.GetXbins()->GetSize() != 0)
520 else
522 }
523 if (newLimitsZ) {
524 fH0->fZaxis.SetRange(0,0);
525 if (fNewZAxis.GetXbins()->GetSize() != 0)
527 else
529 }
530
531 // we need to recompute fNcells and set the array size (as in TH1::SetBins)
532 fH0->fNcells = fH0->fXaxis.GetNbins()+2;
533 if (fH0->fDimension > 1) fH0->fNcells *= fH0->fYaxis.GetNbins()+2;
534 if (fH0->fDimension > 2) fH0->fNcells *= fH0->fZaxis.GetNbins()+2;
536 if (fH0->fSumw2.fN) fH0->fSumw2.Set(fH0->fNcells);
537 // set dummy Y and Z axis for lower dim histogras
538 if (fH0->fDimension < 3) fH0->fZaxis.Set(1,0,1);
539 if (fH0->fDimension < 2) fH0->fYaxis.Set(1,0,1);
540
541 if (gDebug) {
542 if (newLimitsX) Info("DefineNewAxis","A new X axis has been defined Nbins=%d , [%f,%f]", fH0->fXaxis.GetNbins(),
544 if (newLimitsY) Info("DefineNewAxis","A new Y axis has been defined Nbins=%d , [%f,%f]", fH0->fYaxis.GetNbins(),
546 if (newLimitsZ) Info("DefineNewAxis","A new Z axis has been defined Nbins=%d , [%f,%f]", fH0->fZaxis.GetNbins(),
548 }
549
550 return;
551
552}
553
555{
556 // Check inputs
557 //if (!hsrc || !hsrc->fBuffer || !hdes || !hdes->fBuffer) {
558 if (!hsrc || !hsrc->fBuffer || !hdes ) {
559 void *p1 = hsrc ? hsrc->fBuffer : nullptr;
560 //void *p2 = hdes ? hdes->fBuffer : 0;
561 //Warning("TH1Merger::CopyMerge", "invalid inputs: %p, %p, %p, %p -> do nothing", hsrc, hdes, p1, p2);
562 Warning("TH1Merger::CopyMerge", "invalid inputs: %p, %p, %p, -> do nothing", hsrc, hdes, p1);
563 return;
564 }
565
566 // Entries from buffers have to be filled one by one
567 // because FillN doesn't resize histograms.
568 Int_t nbentries = (Int_t)hsrc->fBuffer[0];
569 if (hdes->fDimension == 1) {
570 for (Int_t i = 0; i < nbentries; i++)
571 hdes->Fill(hsrc->fBuffer[2 * i + 2], hsrc->fBuffer[2 * i + 1]);
572 }
573 if (hdes->fDimension == 2) {
574 auto h2 = dynamic_cast<TH2 *>(hdes);
575 R__ASSERT(h2);
576 for (Int_t i = 0; i < nbentries; i++)
577 h2->Fill(hsrc->fBuffer[3 * i + 2], hsrc->fBuffer[3 * i + 3], hsrc->fBuffer[3 * i + 1]);
578 }
579 if (hdes->fDimension == 3) {
580 auto h3 = dynamic_cast<TH3 *>(hdes);
581 R__ASSERT(h3);
582 for (Int_t i = 0; i < nbentries; i++)
583 h3->Fill(hsrc->fBuffer[4 * i + 2], hsrc->fBuffer[4 * i + 3], hsrc->fBuffer[4 * i + 4],
584 hsrc->fBuffer[4 * i + 1]);
585 }
586}
587
589{
590
591 TH1 *href = nullptr, *hist = nullptr;
594 href = fH0;
595 } else {
596 while ((hist = (TH1 *)nextref()) && !href) {
598 href = hist;
599 }
600 }
602 if (!href) {
603 // Merge all histograms to fH0 and do a final projection
604 href = fH0;
605 } else {
606 if (href != fH0) {
607 // Temporary add fH0 to the list for buffer merging
609 resetfH0 = kTRUE;
610 }
611 }
612 TIter next(&fInputList);
613 while ((hist = (TH1 *)next())) {
614 if (!TH1Merger::AxesHaveLimits(hist) && hist->fBuffer) {
615 if (gDebug)
616 Info("AutoP2BufferMerge", "merging buffer of %s into %s", hist->GetName(), href->GetName());
617 CopyBuffer(hist, href);
618 fInputList.Remove(hist);
619 }
620 }
621 // Final projection
622 if (href->fBuffer)
623 href->BufferEmpty(1);
624 // Reset fH0, if already added, to avoid double counting
625 if (resetfH0)
626 fH0->Reset("ICES");
627 // Done, all histos have been processed
628 return kTRUE;
629}
630
632{
633
635 for (Int_t i = 0; i < TH1::kNstat; i++) {
636 totstats[i] = stats[i] = 0;
637 }
638
639 TIter next(&fInputList);
640 TH1 *hist = nullptr;
641 // Calculate boundaries and bins
642 Double_t xmin = 0., xmax = 0.;
643 if (!(fH0->IsEmpty())) {
644 hist = fH0;
645 } else {
646 while ((hist = (TH1 *)next())) {
647 if (!hist->IsEmpty())
648 break;
649 }
650 }
651
652 if (!hist) {
653 if (gDebug)
654 Info("TH1Merger::AutoP2Merge", "all histograms look empty!");
655 return kFALSE;
656 }
657
658 // Start building the axes from the reference histogram
659 if (!AutoP2BuildAxes(hist)) {
660 Error("TH1Merger::AutoP2Merge", "cannot create axes from %s", hist->GetName());
661 return kFALSE;
662 }
663 TH1 *h = nullptr;
664 while ((h = (TH1 *)next())) {
665 if (!AutoP2BuildAxes(h)) {
666 Error("TH1Merger::AutoP2Merge", "cannot merge histogram %s: not merge compatible", h->GetName());
667 return kFALSE;
668 }
669 }
672 Int_t nbins = fNewXAxis.GetNbins();
673
674 // Prepare stats
676 // Clone fH0 and add it to the list
677 if (!fH0->IsEmpty())
679
680 // reset fH0
681 fH0->Reset("ICES");
682 // Set the new boundaries
683 fH0->SetBins(nbins, xmin, xmax);
684
685 next.Reset();
686 Double_t nentries = 0.;
687 while ((hist = (TH1 *)next())) {
688 // process only if the histogram has limits; otherwise it was processed before
689 // in the case of an existing buffer (see if statement just before)
690
691 if (gDebug)
692 Info("TH1Merger::AutoP2Merge", "merging histogram %s into %s (entries: %f)", hist->GetName(), fH0->GetName(),
693 hist->GetEntries());
694
695 // skip empty histograms
696 if (hist->IsEmpty())
697 continue;
698
699 // import statistics
700 hist->GetStats(stats);
701 for (Int_t i = 0; i < TH1::kNstat; i++)
702 totstats[i] += stats[i];
703 nentries += hist->GetEntries();
704
705 // Int_t nx = hist->GetXaxis()->GetNbins();
706 // loop on bins of the histogram and do the merge
707 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
708
711 if (fH0->fSumw2.fN)
713
714 Double_t xu = hist->GetBinCenter(ibin);
715 Int_t jbin = fH0->FindBin(xu);
716
718 if (fH0->fSumw2.fN)
720 }
721 }
722 // copy merged stats
725
726 return kTRUE;
727}
728
730{
731
732 TIter next(&fInputList);
733 while (TH1* hist = (TH1*)next()) {
734 // support also case where some histogram have limits and some have the buffer
735 if ( !TH1Merger::AxesHaveLimits(hist) && hist->fBuffer ) {
736
737 if (gDebug)
738 Info("TH1Merger::BufferMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
739 CopyBuffer(hist, fH0);
740 fInputList.Remove(hist);
741 }
742 }
743 // return true if the merge is completed
744 if (fInputList.GetSize() == 0) {
745 // all histo have been merged
746 return kTRUE;
747 }
748 // we need to reset the buffer in case of merging later on
749 // is this really needed ???
750 if (fH0->fBuffer) fH0->BufferEmpty(1);
751
752 return kFALSE;
753}
754
756
757
759 for (Int_t i=0;i<TH1::kNstat;i++) {
760 totstats[i] = stats[i] = 0;
761 }
764
765 TIter next(&fInputList);
766 while (TH1* hist=(TH1*)next()) {
767 // process only if the histogram has limits; otherwise it was processed before
768 // in the case of an existing buffer (see if statement just before)
769
770 if (gDebug)
771 Info("TH1Merger::SameAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
772
773 // skip empty histograms
774 if (hist->IsEmpty()) continue;
775
776 // import statistics
777 hist->GetStats(stats);
778 for (Int_t i=0; i<TH1::kNstat; i++)
779 totstats[i] += stats[i];
780 nentries += hist->GetEntries();
781
782 //Int_t nx = hist->GetXaxis()->GetNbins();
783 // loop on bins of the histogram and do the merge
784 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
785 MergeBin(hist, ibin, ibin);
786 }
787 }
788 //copy merged stats
791
792 return kTRUE;
793}
794
795
796/**
797 Merged histogram when axis can be different.
798 Histograms are merged looking at bin center positions
799
800 */
802
804 for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
808
809 TIter next(&fInputList);
810 while (TH1* hist=(TH1*)next()) {
811
812 if (gDebug)
813 Info("TH1Merger::DifferentAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
814
815 // skip empty histograms
816 if (hist->IsEmpty()) continue;
817
818 // import statistics
819 hist->GetStats(stats);
820 for (Int_t i=0;i<TH1::kNstat;i++)
821 totstats[i] += stats[i];
822 nentries += hist->GetEntries();
823
824 // loop on bins of the histogram and do the merge
825 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
826
827 // if bin is empty we can skip it
829 continue;
830
832 hist->GetBinXYZ(ibin, binx, biny, binz);
833
834 // case of underflow/overflows in the histogram being merged
835 if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
836 if (fH0->fXaxis.CanExtend() || ( hist->fXaxis.GetBinCenter(binx) > fH0->fXaxis.GetXmin() && hist->fXaxis.GetBinCenter(binx) < fH0->fXaxis.GetXmax()) ) {
837 Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the X axis or have"
838 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
839 return kFALSE;
840 }
841 }
842 if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
843 if (fH0->fYaxis.CanExtend() || ( hist->fYaxis.GetBinCenter(biny) > fH0->fYaxis.GetXmin() && hist->fYaxis.GetBinCenter(biny) < fH0->fYaxis.GetXmax()) ) {
844 Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Y axis or have"
845 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
846 return kFALSE;
847 }
848 }
849 if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
850 if (fH0->fZaxis.CanExtend() || ( hist->fZaxis.GetBinCenter(binz) > fH0->fZaxis.GetXmin() && hist->fZaxis.GetBinCenter(binz) < fH0->fZaxis.GetXmax()) ) {
851 Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Z axis or have"
852 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
853 return kFALSE;
854 }
855 }
856
857 Int_t ix = 0;
858 Int_t iy = 0;
859 Int_t iz = 0;
860
861 // we can extend eventually the axis if histogram is capable of doing it
862 // by using FindBin
863 ix = fH0->fXaxis.FindBin(hist->GetXaxis()->GetBinCenter(binx));
864 if (fH0->fDimension > 1)
865 iy = fH0->fYaxis.FindBin(hist->GetYaxis()->GetBinCenter(biny));
866 if (fH0->fDimension > 2)
867 iz = fH0->fZaxis.FindBin(hist->GetZaxis()->GetBinCenter(binz));
868
869 Int_t ib = fH0->GetBin(ix,iy,iz);
871 Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
872 fH0->GetName(), ib,fH0->fNcells);
873 }
874
875 if (!fIsProfileMerge) {
876 MergeBin(hist, ibin, ib);
877 } else {
878 if (fIsProfile1D)
879 MergeProfileBin(static_cast<const TProfile *> (hist), ibin, ib);
880 else if (fIsProfile2D)
881 MergeProfileBin(static_cast<const TProfile2D *> (hist), ibin, ib);
882 else if (fIsProfile3D)
883 MergeProfileBin(static_cast<const TProfile3D *> (hist), ibin, ib);
884 }
885 }
886 }
887 //copy merged stats
890
891 return kTRUE;
892}
893
894/**
895 Find a duplicate labels in an axis label list
896*/
898
899 if (!labels) return kFALSE;
900
901 for (const auto * obj: *labels) {
902 auto objList = labels->GetListForObject(obj);
903 //objList->ls();
904 if (objList->GetSize() > 1 ) {
905 // check here if in the list we have duplicates
906 std::unordered_set<std::string> s;
907 for ( const auto * o: *objList) {
908 auto ret = s.insert(std::string(o->GetName() ));
909 if (!ret.second) return kTRUE;
910 }
911 }
912 }
913 return kFALSE;
914}
915
916/**
917 Check if histogram has duplicate labels
918 Return an integer with bit set correponding
919 on the axis that has duplicate labels
920 e.g. duplicate labels on x axis : return 1
921 duplicate labels on x and z axis : return 5
922
923*/
925
926 R__ASSERT(hist != nullptr);
927
928 auto labelsX = hist->GetXaxis()->GetLabels();
929 auto labelsY = hist->GetYaxis()->GetLabels();
930 auto labelsZ = hist->GetZaxis()->GetLabels();
931
932 Int_t res = 0;
934 Warning("TH1Merger::CheckForDuplicateLabels","Histogram %s has duplicate labels in the x axis. "
935 "Bin contents will be merged in a single bin",hist->GetName());
936 res |= 1;
937 }
939 Warning("TH1Merger::CheckForDuplicateLabels","Histogram %s has duplicate labels in the y axis. "
940 "Bin contents will be merged in a single bin",hist->GetName());
941 res |= 2;
942 }
944 Warning("TH1Merger::CheckForDuplicateLabels","Histogram %s has duplicate labels in the z axis. "
945 "Bin contents will be merged in a single bin",hist->GetName());
946 res |= 4;
947 }
948 return res;
949}
950
951/**
952 Merge histograms with labels and if newLimits is set support the case that one of the axis
953 can set new limits, if the axes are compatible
954*/
956
958
960 for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
963
964 // check for duplicate labels
966
967 TIter next(&fInputList);
968 while (TH1* hist=(TH1*)next()) {
969
970 if (gDebug)
971 Info("TH1Merger::LabelMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
972
973 // skip empty histograms
974 if (hist->IsEmpty()) continue;
975
976 // import statistics
977 hist->GetStats(stats);
978 for (Int_t i=0;i<TH1::kNstat;i++)
979 totstats[i] += stats[i];
980 nentries += hist->GetEntries();
981
982 auto labelsX = hist->GetXaxis()->GetLabels();
983 auto labelsY = hist->GetYaxis()->GetLabels();
984 auto labelsZ = hist->GetZaxis()->GetLabels();
985 R__ASSERT(!( labelsX == nullptr && labelsY == nullptr && labelsZ == nullptr));
986
987 Bool_t mergeLabelsX = labelsX && fH0->fXaxis.CanExtend() && hist->fXaxis.CanExtend();
988 Bool_t mergeLabelsY = labelsY && fH0->fYaxis.CanExtend() && hist->fYaxis.CanExtend();
989 Bool_t mergeLabelsZ = labelsZ && fH0->fZaxis.CanExtend() && hist->fZaxis.CanExtend();
990
991 if (gDebug) {
992 if (mergeLabelsX)
993 Info("TH1Merger::LabelMerge","Merging X axis in label mode");
994 else
995 Info("TH1Merger::LabelMerge","Merging X axis in numeric mode");
996 if (mergeLabelsY)
997 Info("TH1Merger::LabelMerge","Merging Y axis in label mode");
998 else if (hist->GetDimension() > 1)
999 Info("TH1Merger::LabelMerge","Merging Y axis in numeric mode");
1000 if (mergeLabelsZ)
1001 Info("TH1Merger::LabelMerge","Merging Z axis in label mode" );
1002 else if (hist->GetDimension() > 2)
1003 Info("TH1Merger::LabelMerge","Merging Z axis in numeric mode");
1004 }
1005
1006 // check if histogram has duplicate labels
1007 if (!fNoCheck && hist->GetEntries() > 0) CheckForDuplicateLabels(hist);
1008
1009 // loop on bins of the histogram and do the merge
1010 if (gDebug) {
1011 // print bins original histogram
1012 std::cout << "Bins of original histograms\n";
1013 for (int ix = 1; ix <= fH0->GetXaxis()->GetNbins(); ++ix) {
1014 for (int iy = 1; iy <= fH0->GetYaxis()->GetNbins(); ++iy) {
1015 for (int iz = 1; iz <= fH0->GetZaxis()->GetNbins(); ++iz) {
1016 int i = fH0->GetBin(ix,iy,iz);
1017 std::cout << "bin" << ix << "," << iy << "," << iz
1018 << " : " << fH0->RetrieveBinContent(i) /* << " , " << fH0->fBinEntries.fArray[i] */ << std::endl;
1019 }
1020 }
1021 }
1022 }
1023 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
1024
1025 // if bin is empty we can skip it
1026 if (IsBinEmpty(hist,ibin)) continue;
1027
1029 hist->GetBinXYZ(ibin, binx, biny, binz);
1030
1031 // here only in the case of bins with labels
1032 const char * labelX = hist->GetXaxis()->GetBinLabel(binx);
1033 const char * labelY = (fH0->fDimension > 1) ? hist->GetYaxis()->GetBinLabel(biny) : nullptr;
1034 const char * labelZ = (fH0->fDimension > 2) ? hist->GetYaxis()->GetBinLabel(binz) : nullptr;
1035
1036 // do we need to support case when there are bins with labels and bins without them ??
1037 // this case should have been detected before when examining the histograms
1038
1039 Int_t ix = -1;
1040 Int_t iy = (fH0->fDimension > 1) ? -1 : 0;
1041 Int_t iz = (fH0->fDimension > 2) ? -1 : 0;
1042
1043
1044 // special case for underflow/overflows which have normally empty labels
1045 // if (binx == 0 && TString(labelX) == "" ) ix = 0;
1046 // if (binx == hist->fXaxis.GetNbins() +1 && TString(labelX) == "" ) ix = fH0->fXaxis.GetNbins() +1;
1047
1048 // deal with the case of underflow/overflows in the histogram being merged
1049 // normally underflow/overflow have empty labels
1050 if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
1051 if (TString(labelX) == "" )
1052 ix = (binx <= 0) ? 0 : fH0->fXaxis.GetNbins() +1;
1053 if (newLimits && !mergeLabelsX) {
1054 if (fH0->fXaxis.CanExtend() || ( hist->fXaxis.GetBinCenter(binx) > fH0->fXaxis.GetXmin() && hist->fXaxis.GetBinCenter(binx) < fH0->fXaxis.GetXmax()) ) {
1055 Error("TH1Merger::LabelMerge", "Cannot merge histograms - the histograms %s can extend the X axis or have"
1056 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
1057 return kFALSE;
1058 }
1059 }
1060 }
1061 if (fH0->fDimension > 1 ) {
1062 if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
1063 if (TString(labelY) == "" )
1064 iy = (biny <= 0) ? 0 : fH0->fYaxis.GetNbins() +1;
1065 if (newLimits && !mergeLabelsY) {
1066 if (fH0->fYaxis.CanExtend() || ( hist->fYaxis.GetBinCenter(biny) > fH0->fYaxis.GetXmin() && hist->fYaxis.GetBinCenter(biny) < fH0->fYaxis.GetXmax()) ) {
1067 Error("TH1Merger::LabelMerge", "Cannot merge histograms - the histograms %s can extend the Y axis or have"
1068 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
1069 return kFALSE;
1070 }
1071 }
1072 }
1073 }
1074 if (fH0->fDimension > 2 ) {
1075 if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
1076 if (TString(labelZ) == "" )
1077 iz = (binz <= 0) ? 0 : fH0->fZaxis.GetNbins() +1;
1078 if (newLimits && !mergeLabelsZ) {
1079 if (fH0->fZaxis.CanExtend() || ( hist->fZaxis.GetBinCenter(binz) > fH0->fZaxis.GetXmin() && hist->fZaxis.GetBinCenter(binz) < fH0->fZaxis.GetXmax()) ) {
1080 Error("TH1Merger::LabelMerge", "Cannot merge histograms - the histograms %s can extend the Z axis or have"
1081 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
1082 return kFALSE;
1083 }
1084 }
1085 }
1086 }
1087
1088 // find corresponding case (in case bin is not overflow)
1089 // and see if for that axis we need to merge using labels or bin numbers
1090 if (ix == -1) {
1091 if (mergeLabelsX) {
1092 ix = fH0->fXaxis.FindBin(labelX);
1093 }
1094 else
1095 // use find bin in case axis can be extended
1096 ix = FindFixBinNumber(binx, hist->fXaxis, fH0->fXaxis);
1097 }
1098
1099 if (iy == -1 && fH0->fDimension> 1 ) { // check on dim should not be needed
1100 if (mergeLabelsY)
1101 iy= fH0->fYaxis.FindBin(labelY);
1102 else
1103 iy = FindFixBinNumber(biny, hist->fYaxis, fH0->fYaxis);
1104 }
1105 if (iz == -1 && fH0->fDimension> 2) {
1106 if (mergeLabelsZ)
1107 iz= fH0->fZaxis.FindBin(labelZ);
1108 else
1109 iz = FindFixBinNumber(binz, hist->fZaxis, fH0->fZaxis);
1110 }
1111
1112 if (gDebug)
1113 Info("TH1Merge::LabelMerge","Merge bin [%d,%d,%d] with label [%s,%s,%s] into bin [%d,%d,%d]",
1114 binx,biny,binz,labelX,labelY,labelZ,ix,iy,iz);
1115
1116
1117 Int_t ib = fH0->GetBin(ix,iy,iz);
1118 if (ib < 0 || ib >= fH0->fNcells) {
1119 Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
1120 fH0->GetName(), ib,fH0->fNcells);
1121 }
1122
1123 MergeBin(hist, ibin, ib);
1124 }
1125 }
1126 //copy merged stats
1129
1130 return kTRUE;
1131}
1132
1133/// helper function for merging
1134/// \param profileDim 0 if it's a regular TH1 merge (default), 1 for TProfile, 2 for TProfile2D and 3 for TProfile3D
1135
1138 Double_t e1sq = (hist->fSumw2.fN) ? hist->GetBinErrorSqUnchecked(ibin) : cu;
1139 bool profileCheck = (profileDim == 0);
1140 // For TProfiles we need also to check that entries is 0 even if content and errors are 0
1141 if (profileDim == 1) {
1142 auto prof = static_cast<const TProfile *>(hist);
1143 profileCheck = prof->fBinEntries.fArray[ibin] == 0;
1144 } else if (profileDim == 2) {
1145 auto prof = static_cast<const TProfile2D *>(hist);
1146 profileCheck = prof->fBinEntries.fArray[ibin] == 0;
1147 } else if (profileDim == 3) {
1148 auto prof = static_cast<const TProfile3D *>(hist);
1149 profileCheck = prof->fBinEntries.fArray[ibin] == 0;
1150 }
1151 return cu == 0 && e1sq == 0 && profileCheck;
1152}
1153
1154// merge input bin (ibin) of histograms hist ibin into current bin cbin of this histogram
1156{
1157 if (!fIsProfileMerge) {
1160 if (fH0->fSumw2.fN) {
1161 Double_t e1sq = (hist->fSumw2.fN) ? hist->GetBinErrorSqUnchecked(ibin) : cu;
1162 fH0->fSumw2.fArray[cbin] += e1sq;
1163 }
1164 } else {
1165 if (fIsProfile1D)
1166 MergeProfileBin(static_cast<const TProfile *> (hist), ibin, cbin);
1167 else if (fIsProfile2D)
1168 MergeProfileBin(static_cast<const TProfile2D *> (hist), ibin, cbin);
1169 else if (fIsProfile3D)
1170 MergeProfileBin(static_cast<const TProfile3D *> (hist), ibin, cbin);
1171 }
1172 return;
1173}
1174
1175// merge profile input bin (ibin) of histograms hist ibin into current bin cbin of this histogram
1176template<class TProfileType>
1178{
1179 TProfileType *p = static_cast<TProfileType *>(fH0);
1180 p->fArray[pbin] += h->fArray[hbin];
1181 p->fSumw2.fArray[pbin] += h->fSumw2.fArray[hbin];
1182 p->fBinEntries.fArray[pbin] += h->fBinEntries.fArray[hbin];
1183 if (p->fBinSumw2.fN) {
1184 if (h->fBinSumw2.fN)
1185 p->fBinSumw2.fArray[pbin] += h->fBinSumw2.fArray[hbin];
1186 else
1187 p->fBinSumw2.fArray[pbin] += h->fArray[hbin];
1188 }
1189 if (gDebug)
1190 Info("TH1Merge::MergeProfileBin", "Merge bin %d of profile %s with content %f in bin %d - result is %f", hbin,
1191 h->GetName(), h->fArray[hbin], pbin, p->fArray[pbin]);
1192}
#define h(i)
Definition RSha256.hxx:106
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:244
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
#define PRINTRANGE(a, b, bn)
Definition TH1Merger.cxx:15
float xmin
int nentries
float xmax
@ kMustCleanup
Definition TObject.h:374
Int_t gDebug
Definition TROOT.cxx:622
Double_t * fArray
Definition TArrayD.h:30
void Set(Int_t n) override
Set size of this array to n doubles.
Definition TArrayD.cxx:106
Int_t fN
Definition TArray.h:38
Class to manage histogram axis.
Definition TAxis.h:32
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:296
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition TAxis.cxx:784
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1046
THashList * GetLabels() const
Definition TAxis.h:123
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5118
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Bool_t AutoP2BufferMerge()
static Bool_t AxesHaveLimits(const TH1 *h)
Definition TH1Merger.cxx:19
Bool_t AutoP2Merge()
static Int_t CheckForDuplicateLabels(const TH1 *hist)
Check if histogram has duplicate labels Return an integer with bit set correponding on the axis that ...
Bool_t AutoP2BuildAxes(TH1 *)
Determine final boundaries and number of bins for histograms created in power-of-2 autobin mode.
Definition TH1Merger.cxx:80
Bool_t fIsProfileMerge
Definition TH1Merger.h:135
Bool_t DifferentAxesMerge()
Merged histogram when axis can be different.
Bool_t SameAxesMerge()
TList fInputList
copy of fH0 - managed by this class
Definition TH1Merger.h:141
Bool_t fNoLabelMerge
Definition TH1Merger.h:133
static Int_t FindFixBinNumber(Int_t ibin, const TAxis &inAxis, const TAxis &outAxis)
Definition TH1Merger.h:36
TH1 * fH0
Definition TH1Merger.h:139
Bool_t fIsProfile3D
Definition TH1Merger.h:138
TAxis fNewZAxis
Definition TH1Merger.h:144
Bool_t fIsProfile1D
Definition TH1Merger.h:136
void CopyBuffer(TH1 *hsrc, TH1 *hdes)
Bool_t LabelMerge(bool newLimits=false)
Merge histograms with labels and if newLimits is set support the case that one of the axis can set ne...
Bool_t BufferMerge()
EMergerType ExamineHistograms()
Examine the list of histograms to find out which type of Merge we need to do Pass the input list cont...
static Bool_t HasDuplicateLabels(const THashList *labels)
Find a duplicate labels in an axis label list.
void MergeBin(const TH1 *hist, Int_t inbin, Int_t outbin)
Bool_t operator()()
Function performing the actual merge.
Definition TH1Merger.cxx:27
Bool_t fIsProfile2D
Definition TH1Merger.h:137
@ kAllNoLimits
Definition TH1Merger.h:26
@ kLabelAndNewLimits
Definition TH1Merger.h:29
@ kNotCompatible
Definition TH1Merger.h:24
@ kAutoP2NeedLimits
Definition TH1Merger.h:31
@ kHasNewLimits
Definition TH1Merger.h:27
@ kAutoP2HaveLimits
Definition TH1Merger.h:30
@ kAllSameAxes
Definition TH1Merger.h:25
void DefineNewAxes()
Function to define new histogram axis when merging It is call only in case of merging with different ...
static Bool_t IsBinEmpty(const TH1 *hist, Int_t bin, Int_t profileDim=0)
helper function for merging
Bool_t fNoCheck
Definition TH1Merger.h:134
TH1 * fHClone
histogram on which the list is merged
Definition TH1Merger.h:140
UInt_t fNewAxisFlag
Definition TH1Merger.h:145
TAxis fNewXAxis
Definition TH1Merger.h:142
void MergeProfileBin(const TProfileType *p, Int_t ibin, Int_t outbin)
TAxis fNewYAxis
Definition TH1Merger.h:143
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:108
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:8966
Double_t * fBuffer
[fBufferSize] entry buffer
Definition TH1.h:168
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition TH1.cxx:9170
TAxis * GetZaxis()
Definition TH1.h:575
@ kXaxis
Definition TH1.h:122
@ kNoAxis
NOTE: Must always be 0 !!!
Definition TH1.h:121
@ kZaxis
Definition TH1.h:124
@ kYaxis
Definition TH1.h:123
Int_t fNcells
Number of bins(1D), cells (2D) +U/Overflows.
Definition TH1.h:149
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:7857
void Copy(TObject &hnew) const override
Copy this histogram structure to newth1.
Definition TH1.cxx:2643
virtual Int_t GetDimension() const
Definition TH1.h:529
@ kAutoBinPTwo
different than 1.
Definition TH1.h:414
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7139
TAxis * GetXaxis()
Definition TH1.h:573
static Bool_t RecomputeAxisLimits(TAxis &destAxis, const TAxis &anAxis)
Finds new limits for the axis for the Merge function.
Definition TH1.cxx:5911
virtual void PutStats(Double_t *stats)
Replace current statistics with the values in array stats.
Definition TH1.cxx:7908
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:4964
static Bool_t SameLimitsAndNBins(const TAxis &axis1, const TAxis &axis2)
Same limits and bins.
Definition TH1.cxx:5901
Int_t fDimension
! Histogram dimension (1, 2 or 3 dim)
Definition TH1.h:170
virtual void SetBinsLength(Int_t=-1)
Definition TH1.h:630
TAxis * GetYaxis()
Definition TH1.h:574
virtual Double_t GetBinErrorSqUnchecked(Int_t bin) const
Definition TH1.h:707
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4401
virtual Double_t RetrieveBinContent(Int_t bin) const =0
Raw retrieval of bin content on internal data structure see convention for numbering bins in TH1::Get...
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:6685
Bool_t IsEmpty() const
Check if a histogram is empty (this is a protected method used mainly by TH1Merger )
Definition TH1.cxx:5167
@ kNstat
Size of statistics data (up to TProfile3D)
Definition TH1.h:424
TAxis fZaxis
Z axis descriptor.
Definition TH1.h:152
TClass * IsA() const override
Definition TH1.h:695
TAxis fXaxis
X axis descriptor.
Definition TH1.h:150
TArrayD fSumw2
Array of sum of squares of weights.
Definition TH1.h:164
virtual Int_t GetSumw2N() const
Definition TH1.h:564
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:3650
virtual void AddBinContent(Int_t bin)=0
Increment bin content by 1.
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2724
TAxis fYaxis
Y axis descriptor.
Definition TH1.h:151
virtual void SetBins(Int_t nx, Double_t xmin, Double_t xmax)
Redefine x axis parameters.
Definition TH1.cxx:8796
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:9049
virtual void SetEntries(Double_t n)
Definition TH1.h:641
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1384
Service class for 2-D histogram classes.
Definition TH2.h:30
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:40
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
const TList * GetListForObject(const char *name) const
Return the THashTable's list (bucket) in which obj can be found based on its hash; see THashTable::Ge...
void Reset()
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:98
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
void ResetBit(UInt_t f)
Definition TObject.h:204
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
Profile3D histograms are used to display the mean value of T and its RMS for each cell in X,...
Definition TProfile3D.h:27
Profile Histogram.
Definition TProfile.h:32
Basic string class.
Definition TString.h:139
std::ostream & Info()
Definition hadd.cxx:177
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123