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#include <cmath>
15
16#define PRINTRANGE(a, b, bn) \
17 Printf(" base: %f %f %d, %s: %f %f %d", a->GetXmin(), a->GetXmax(), a->GetNbins(), bn, b->GetXmin(), b->GetXmax(), \
18 b->GetNbins());
19
21 Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
22 if (h->GetDimension() > 1) hasLimits &= h->GetYaxis()->GetXmin() < h->GetYaxis()->GetXmax();
23 if (h->GetDimension() > 2) hasLimits &= h->GetZaxis()->GetXmin() < h->GetZaxis()->GetXmax();
24 return hasLimits;
25}
26
27/// Function performing the actual merge
29
30
32
33 if (gDebug) Info("Merge","Histogram Merge type is %d and new axis flag is %d",(int) type,(int) fNewAxisFlag);
34
35 if (type == kNotCompatible) return kFALSE;
36
37 if (type == kAllSameAxes)
38 return SameAxesMerge();
39
40 if (type == kAllLabel)
41 return LabelMerge();
42
44 return LabelMerge(true);
45
46 if (type == kAllNoLimits)
47 return BufferMerge();
48
50 return AutoP2Merge();
51
52 // this is the mixed case - more complicated
53 if (type == kHasNewLimits) {
54 // we need to define some new axes
56 // we might need to merge some histogram using the buffer
58 // if ret is true the merge is completed and we can exit
59 if (ret) return kTRUE;
60 // in the other cases then we merge using FindBin
61 return DifferentAxesMerge();
62 }
63 Error("TH1Merger","Unknown type of Merge for histogram %s",fH0->GetName());
64 return kFALSE;
65}
66
67/////////////////////////////////////////////////////////////////////////////////////////
68/// Determine final boundaries and number of bins for histograms created in power-of-2
69/// autobin mode.
70///
71/// Return kTRUE if compatible, updating fNewXaxis accordingly; return kFALSE if something
72/// wrong.
73///
74/// The histograms are not merge-compatible if
75///
76/// 1. have different variable-size bins
77/// 2. larger bin size is not an integer multiple of the smaller one
78/// 3. the final estimated range is smalle then the bin size
79///
80
82{
83 // They must be both defined
84 if (!h) {
85 Error("AutoP2BuildAxes", "undefined histogram: %p", h);
86 return kFALSE;
87 }
88
89 // They must be created in power-of-2 autobin mode
90 if (!h->TestBit(TH1::kAutoBinPTwo)) {
91 Error("AutoP2BuildAxes", "not in autobin-power-of-2 mode!");
92 return kFALSE;
93 }
94
95 // Point to axes
96 TAxis *a0 = &fNewXAxis, *a1 = h->GetXaxis();
97
98 // This is for future merging of detached ranges (only possible if no over/underflows)
99 Bool_t canextend = (h->GetBinContent(0) > 0 || h->GetBinContent(a1->GetNbins() + 1) > 0) ? kFALSE : kTRUE;
100
101 // The first time we just copy the boundaries and bins
102 if (a0->GetFirst() == a0->GetLast()) {
103 a0->Set(a1->GetNbins(), a1->GetXmin(), a1->GetXmax());
104 // This is for future merging of detached ranges (only possible if no over/underflows)
105 a0->SetCanExtend(canextend);
106 return kTRUE;
107 }
108
109 // Bin sizes must be in integer ratio
110 Double_t bwmax = (a0->GetXmax() - a0->GetXmin()) / a0->GetNbins();
111 Double_t bwmin = (a1->GetXmax() - a1->GetXmin()) / a1->GetNbins();
112 Bool_t b0 = kTRUE;
113 if (bwmin > bwmax) {
114 std::swap(bwmax, bwmin);
115 b0 = kFALSE;
116 }
117 if (!(bwmin > 0.)) {
118 PRINTRANGE(a0, a1, h->GetName());
119 Error("AutoP2BuildAxes", "minimal bin width negative or null: %f", bwmin);
120 return kFALSE;
121 }
122
123 Double_t rt;
124 Double_t re = std::modf(bwmax / bwmin, &rt);
125 if (re > std::numeric_limits<Double_t>::epsilon()) {
126 PRINTRANGE(a0, a1, h->GetName());
127 Error("AutoP2BuildAxes", "bin widths not in integer ratio: %f", re);
128 return kFALSE;
129 }
130
131 // Range of the merged histogram, taking into account overlaps
134 if (a0->GetXmin() < a1->GetXmin()) {
135 if (a0->GetXmax() < a1->GetXmin()) {
136 if (!a0->CanExtend() || !canextend) {
137 PRINTRANGE(a0, a1, h->GetName());
138 Error("AutoP2BuildAxes", "ranges are disconnected and under/overflows: cannot merge");
139 return kFALSE;
140 }
141 xmax = a1->GetXmax();
142 xmin = a0->GetXmin();
143 domax = b0 ? kTRUE : kFALSE;
144 } else {
145 if (a0->GetXmax() >= a1->GetXmax()) {
146 xmax = a1->GetXmax();
147 xmin = a1->GetXmin();
148 domax = !b0 ? kTRUE : kFALSE;
149 } else {
150 xmax = a0->GetXmax();
151 xmin = a1->GetXmin();
152 domax = !b0 ? kTRUE : kFALSE;
153 }
154 }
155 } else {
156 if (a1->GetXmax() < a0->GetXmin()) {
157 if (!a0->CanExtend() || !canextend) {
158 PRINTRANGE(a0, a1, h->GetName());
159 Error("AutoP2BuildAxes", "ranges are disconnected and under/overflows: cannot merge");
160 return kFALSE;
161 }
162 xmax = a0->GetXmax();
163 xmin = a1->GetXmin();
164 domax = !b0 ? kTRUE : kFALSE;
165 } else {
166 if (a1->GetXmax() >= a0->GetXmax()) {
167 xmax = a0->GetXmax();
168 xmin = a0->GetXmin();
169 domax = b0 ? kTRUE : kFALSE;
170 } else {
171 xmax = a1->GetXmax();
172 xmin = a0->GetXmin();
173 domax = b0 ? kTRUE : kFALSE;
174 }
175 }
176 }
178
179 re = std::modf(range / bwmax, &rt);
180 if (rt < 1.) {
181 PRINTRANGE(a0, a1, h->GetName());
182 Error("MergeCompatibleHistograms", "range smaller than bin width: %f %f %f", range, bwmax, rt);
183 return kFALSE;
184 }
185 if (re > std::numeric_limits<Double_t>::epsilon()) {
186 if (domax) {
187 xmax -= bwmax * re;
188 } else {
189 xmin += bwmax * re;
190 }
191 }
192 // Number of bins
193 Int_t nb = (Int_t)rt;
194
195 // Set the result
196 a0->Set(nb, xmin, xmax);
197
198 // This is for future merging of detached ranges (only possible if no over/underflows)
199 if (!a0->CanExtend())
200 a0->SetCanExtend(canextend);
201
202 // Done
203 return kTRUE;
204}
205
206/**
207 Examine the list of histograms to find out which type of Merge we need to do
208 Pass the input list containing the histogram to merge and h0 which is the initial histogram
209 on which all the histogram of the list will be merged
210 This are the possible cases:
211 - 1. All histogram have the same axis (allSameLimits = true)
212 - 2. Histogram have different axis but compatible (allSameLimits = false) and sameLimitsX,Y,Z specifies which axis
213 has different limits
214 - 3. Histogram do not have limits (so the Buffer is used) allHaveLimits = false
215 - 3b. One histogram has limits the other not : allHaveLimits = false AND initialLimitsFound = true
216 - 4. Histogram Have labels = allHaveLabels = true
217
218
219*/
221
222
223
225 Bool_t allHaveLabels = kTRUE; // assume all histo have labels and check later
226 UInt_t labelAxisType = TH1::kNoAxis; // type of axes that have label
234
236
237 // TAxis newXAxis;
238 // TAxis newYAxis;
239 // TAxis newZAxis;
240
241 TIter next(&fInputList);
242 TH1 * h = fH0; // start with fH0
243
244 int dimension = fH0->GetDimension();
245
247
248 // if the option alphanumeric merge is set
249 // we assume we do not have labels
251
252 // start looping on the histograms
253
254 do {
255
256 // check first histogram compatibility
257 if (h != fH0) {
258 if (h->GetDimension() != dimension) {
259 Error("Merge", "Cannot merge histogram - dimensions are different\n "
260 "%s has dim=%d and %s has dim=%d",fH0->GetName(),dimension,h->GetName(),h->GetDimension());
261 return kNotCompatible;
262 }
263 }
264
265 // check if one of the histogram is weighted
266 haveWeights |= h->GetSumw2N() != 0;
267
268 // do not skip anymore empty histograms
269 // since are used to set the limits
273
274 if (isAutoP2 && !h->TestBit(TH1::kAutoBinPTwo)) {
275 Error("Merge", "Cannot merge histogram - some are in autobin-power-of-2 mode, but not %s!", h->GetName());
276 return kNotCompatible;
277 }
278 if (!isAutoP2 && h->TestBit(TH1::kAutoBinPTwo)) {
279 Error("Merge", "Cannot merge histogram - %s is in autobin-power-of-2 mode, but not the previous ones",
280 h->GetName());
281 return kNotCompatible;
282 }
283
284 if (hasLimits) {
285 h->BufferEmpty();
286
287// // this is done in case the first histograms are empty and
288// // the histogram have different limits
289// #ifdef LATER
290// if (firstHistWithLimits ) {
291// // set axis limits in the case the first histogram did not have limits
292// if (h != this && !SameLimitsAndNBins( fXaxis, *h->GetXaxis()) ) {
293// if (h->GetXaxis()->GetXbins()->GetSize() != 0) fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
294// else fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
295// }
296// firstHistWithLimits = kFALSE;
297// }
298// #endif
299
300 // this is executed the first time an histogram with limits is found
301 // to set some initial values on the new axis
302 if (!initialLimitsFound) {
304 if (h->GetXaxis()->GetXbins()->GetSize() != 0)
305 fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXbins()->GetArray());
306 else
307 fNewXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
308 if (dimension > 1) {
309 if (h->GetYaxis()->GetXbins()->GetSize() != 0)
310 fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXbins()->GetArray());
311 else
312 fNewYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(), h->GetYaxis()->GetXmax());
313 }
314 if (dimension > 2) {
315 if (h->GetZaxis()->GetXbins()->GetSize() != 0)
316 fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXbins()->GetArray());
317 else
318 fNewZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(), h->GetZaxis()->GetXmax());
319
320 }
321 }
322 else {
323 // check first if histograms have same bins in X
324 if (!TH1::SameLimitsAndNBins(fNewXAxis, *(h->GetXaxis())) ) {
326 // recompute the limits in this case the optimal limits
327 // The condition to works is that the histogram have same bin with
328 // and one common bin edge
329 if (!TH1::RecomputeAxisLimits(fNewXAxis, *(h->GetXaxis()))) {
330 Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
331 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
333 h->GetName(),h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
334 h->GetXaxis()->GetXmax());
335 return kNotCompatible;
336 }
337 }
338 // check first if histograms have same bins in Y
339 if (dimension > 1 && !TH1::SameLimitsAndNBins(fNewYAxis, *(h->GetYaxis()))) {
341 // recompute in this case the optimal limits
342 // The condition to works is that the histogram have same bin with
343 // and one common bin edge
344 if (!TH1::RecomputeAxisLimits(fNewYAxis, *(h->GetYaxis()))) {
345 Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
346 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
348 h->GetName(), h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
349 h->GetYaxis()->GetXmax());
350 return kNotCompatible;
351 }
352 }
353 if(dimension > 2 && !fH0->SameLimitsAndNBins(fNewZAxis, *(h->GetZaxis()))) {
355 if (!TH1::RecomputeAxisLimits(fNewZAxis, *(h->GetZaxis()))) {
356 Error("Merge", "Cannot merge histograms - limits are inconsistent:\n "
357 "first: %s (%d, %f, %f), second: %s (%d, %f, %f)", fH0->GetName(),
359 h->GetName(),h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
360 h->GetZaxis()->GetXmax());
361 return kNotCompatible;
362 }
363 }
365
366
367 }
368 }
369 Bool_t histoIsEmpty = h->IsEmpty();
370 // std::cout << "considering histo " << h->GetName() << " labels - " << allHaveLabels << " is empty "
371 // << histoIsEmpty << std::endl;
372
373 // if histogram is empty it does not matter if it has label or not
374 if (allHaveLabels && !histoIsEmpty) {
375 THashList* hlabelsX = h->GetXaxis()->GetLabels();
376 THashList* hlabelsY = (dimension > 1) ? h->GetYaxis()->GetLabels() : nullptr;
377 THashList* hlabelsZ = (dimension > 2) ? h->GetZaxis()->GetLabels() : nullptr;
378 Bool_t haveOneLabelX = hlabelsX != nullptr;
379 Bool_t haveOneLabelY = hlabelsY != nullptr;
380 Bool_t haveOneLabelZ = hlabelsZ != nullptr;
382 // do here to print message only one time
384 Warning("Merge","Not all histograms have labels. I will ignore labels,"
385 " falling back to bin numbering mode.");
386 }
387
389
390 if (haveOneLabel) {
392 UInt_t type = 0;
397 // check if all histogram have consistent label axis
398 // this means that there is at least one axis where boith histogram have labels
401 if (!consistentLabels)
402 Warning("TH1Merger::ExamineHistogram","Histogram %s has inconsistent labels: %d is not consistent with %d",
403 h->GetName(), (int) type, (int) labelAxisType );
405 Info("TH1Merger::ExamineHistogram","Histogram %s has consistent labels",h->GetName() );
406 }
407
408 // Check compatibility of axis that have labels with axis that can be extended
411 if (dimension > 1 && fH0->GetYaxis()->CanExtend()) extendAxisType |= TH1::kYaxis;
412 if (dimension > 2 && fH0->GetZaxis()->CanExtend()) extendAxisType |= TH1::kZaxis;
413 // it is sufficient to have a consistent label axis that can be extended
415 // If histograms have labels but corresponding axes cannot be extended use bin center mode
417 // special case for this histogram when is empty
418 // and axis cannot be extended (because it is the default)
419 if ( fH0->IsEmpty() ) {
420 if (gDebug)
421 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());
423 }
424 else { // histogram is not empty
425 if (gDebug)
426 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());
428 }
429 }
430 // we don't need to check anymore for the case of non empty histograms containing labels.
431 // If we have some labels set and the axis is not extendable the LabelsMerge function handles
432 // that case correctly and falls back to a numeric merge
433
434 }
435 if (gDebug)
436 Info("TH1Merger::ExamineHistogram","Examine histogram %s - labels %d - same limits %d - axis found %d",h->GetName(),allHaveLabels,allSameLimits,initialLimitsFound );
437
438 } while ( ( h = dynamic_cast<TH1*> ( next() ) ) != nullptr );
439
440 if (!h && (*next) ) {
441 Error("Merge","Attempt to merge object of class: %s to a %s",
442 (*next)->ClassName(),fH0->ClassName());
443 return kNotCompatible;
444 }
445
446 // in case of weighted histogram set Sumw2() on fH0 is is not weighted
447 if (haveWeights && fH0->GetSumw2N() == 0)
448 fH0->Sumw2();
449
450 // AutoP2
451 if (isAutoP2) {
452 if (allHaveLimits)
453 return kAutoP2HaveLimits;
454 return kAutoP2NeedLimits;
455 }
456
457 // return the type of merge
459 if (allSameLimits) return kAllSameAxes;
460 if (!initialLimitsFound) {
462 // case where no limits are found and the buffer is used
463 return kAllNoLimits;
464 }
465 // remaining case should be the mixed one. Some histogram have limits some not
466 fNewAxisFlag = 0;
470
471 // we need to set the flag also in case this histogram has no limits
472 // we need to set explicitly the flag to re-define a new axis
474 if (dimension > 1 && fH0->GetYaxis()->GetXmin() >= fH0->GetYaxis()->GetXmax()) fNewAxisFlag |= TH1::kYaxis;
475 if (dimension > 2 && fH0->GetZaxis()->GetXmin() >= fH0->GetZaxis()->GetXmax()) fNewAxisFlag |= TH1::kZaxis;
476
478
479 return kHasNewLimits;
480
481}
482
483/**
484 Function to define new histogram axis when merging
485 It is call only in case of merging with different axis or with the
486 buffer (kHasNewLimits)
487*/
488
490
491 // first we need to create a copy of the histogram in case is not empty
492
493 if (!fH0->IsEmpty() ) {
496 fHClone = (TH1*)fH0->IsA()->New();
497 fHClone->SetDirectory(nullptr);
498 fH0->Copy(*fHClone);
500 fH0->BufferEmpty(1); // To remove buffer.
501 fH0->Reset(); // BufferEmpty sets limits so we can't use it later.
502 fH0->SetEntries(0);
504
505 }
506
510 if (newLimitsX) {
511 fH0->fXaxis.SetRange(0,0);
512 if (fNewXAxis.GetXbins()->GetSize() != 0)
514 else
516 }
517 if (newLimitsY) {
518 fH0->fYaxis.SetRange(0,0);
519 if (fNewYAxis.GetXbins()->GetSize() != 0)
521 else
523 }
524 if (newLimitsZ) {
525 fH0->fZaxis.SetRange(0,0);
526 if (fNewZAxis.GetXbins()->GetSize() != 0)
528 else
530 }
531
532 // we need to recompute fNcells and set the array size (as in TH1::SetBins)
533 fH0->fNcells = fH0->fXaxis.GetNbins()+2;
534 if (fH0->fDimension > 1) fH0->fNcells *= fH0->fYaxis.GetNbins()+2;
535 if (fH0->fDimension > 2) fH0->fNcells *= fH0->fZaxis.GetNbins()+2;
537 if (fH0->fSumw2.fN) fH0->fSumw2.Set(fH0->fNcells);
538 // set dummy Y and Z axis for lower dim histogras
539 if (fH0->fDimension < 3) fH0->fZaxis.Set(1,0,1);
540 if (fH0->fDimension < 2) fH0->fYaxis.Set(1,0,1);
541
542 if (gDebug) {
543 if (newLimitsX) Info("DefineNewAxis","A new X axis has been defined Nbins=%d , [%f,%f]", fH0->fXaxis.GetNbins(),
545 if (newLimitsY) Info("DefineNewAxis","A new Y axis has been defined Nbins=%d , [%f,%f]", fH0->fYaxis.GetNbins(),
547 if (newLimitsZ) Info("DefineNewAxis","A new Z axis has been defined Nbins=%d , [%f,%f]", fH0->fZaxis.GetNbins(),
549 }
550
551 return;
552
553}
554
556{
557 // Check inputs
558 //if (!hsrc || !hsrc->fBuffer || !hdes || !hdes->fBuffer) {
559 if (!hsrc || !hsrc->fBuffer || !hdes ) {
560 void *p1 = hsrc ? hsrc->fBuffer : nullptr;
561 //void *p2 = hdes ? hdes->fBuffer : 0;
562 //Warning("TH1Merger::CopyMerge", "invalid inputs: %p, %p, %p, %p -> do nothing", hsrc, hdes, p1, p2);
563 Warning("TH1Merger::CopyMerge", "invalid inputs: %p, %p, %p, -> do nothing", hsrc, hdes, p1);
564 return;
565 }
566
567 // Entries from buffers have to be filled one by one
568 // because FillN doesn't resize histograms.
569 Int_t nbentries = (Int_t)hsrc->fBuffer[0];
570 if (hdes->fDimension == 1) {
571 for (Int_t i = 0; i < nbentries; i++)
572 hdes->Fill(hsrc->fBuffer[2 * i + 2], hsrc->fBuffer[2 * i + 1]);
573 }
574 if (hdes->fDimension == 2) {
575 auto h2 = dynamic_cast<TH2 *>(hdes);
576 R__ASSERT(h2);
577 for (Int_t i = 0; i < nbentries; i++)
578 h2->Fill(hsrc->fBuffer[3 * i + 2], hsrc->fBuffer[3 * i + 3], hsrc->fBuffer[3 * i + 1]);
579 }
580 if (hdes->fDimension == 3) {
581 auto h3 = dynamic_cast<TH3 *>(hdes);
582 R__ASSERT(h3);
583 for (Int_t i = 0; i < nbentries; i++)
584 h3->Fill(hsrc->fBuffer[4 * i + 2], hsrc->fBuffer[4 * i + 3], hsrc->fBuffer[4 * i + 4],
585 hsrc->fBuffer[4 * i + 1]);
586 }
587}
588
590{
591
592 TH1 *href = nullptr, *hist = nullptr;
595 href = fH0;
596 } else {
597 while ((hist = (TH1 *)nextref()) && !href) {
599 href = hist;
600 }
601 }
603 if (!href) {
604 // Merge all histograms to fH0 and do a final projection
605 href = fH0;
606 } else {
607 if (href != fH0) {
608 // Temporary add fH0 to the list for buffer merging
610 resetfH0 = kTRUE;
611 }
612 }
613 TIter next(&fInputList);
614 while ((hist = (TH1 *)next())) {
615 if (!TH1Merger::AxesHaveLimits(hist) && hist->fBuffer) {
616 if (gDebug)
617 Info("AutoP2BufferMerge", "merging buffer of %s into %s", hist->GetName(), href->GetName());
618 CopyBuffer(hist, href);
619 fInputList.Remove(hist);
620 }
621 }
622 // Final projection
623 if (href->fBuffer)
624 href->BufferEmpty(1);
625 // Reset fH0, if already added, to avoid double counting
626 if (resetfH0)
627 fH0->Reset("ICES");
628 // Done, all histos have been processed
629 return kTRUE;
630}
631
633{
634
636 for (Int_t i = 0; i < TH1::kNstat; i++) {
637 totstats[i] = stats[i] = 0;
638 }
639
640 TIter next(&fInputList);
641 TH1 *hist = nullptr;
642 // Calculate boundaries and bins
643 Double_t xmin = 0., xmax = 0.;
644 if (!(fH0->IsEmpty())) {
645 hist = fH0;
646 } else {
647 while ((hist = (TH1 *)next())) {
648 if (!hist->IsEmpty())
649 break;
650 }
651 }
652
653 if (!hist) {
654 if (gDebug)
655 Info("TH1Merger::AutoP2Merge", "all histograms look empty!");
656 return kFALSE;
657 }
658
659 // Start building the axes from the reference histogram
660 if (!AutoP2BuildAxes(hist)) {
661 Error("TH1Merger::AutoP2Merge", "cannot create axes from %s", hist->GetName());
662 return kFALSE;
663 }
664 TH1 *h = nullptr;
665 while ((h = (TH1 *)next())) {
666 if (!AutoP2BuildAxes(h)) {
667 Error("TH1Merger::AutoP2Merge", "cannot merge histogram %s: not merge compatible", h->GetName());
668 return kFALSE;
669 }
670 }
673 Int_t nbins = fNewXAxis.GetNbins();
674
675 // Prepare stats
677 // Clone fH0 and add it to the list
678 if (!fH0->IsEmpty())
680
681 // reset fH0
682 fH0->Reset("ICES");
683 // Set the new boundaries
684 fH0->SetBins(nbins, xmin, xmax);
685
686 next.Reset();
687 Double_t nentries = 0.;
688 while ((hist = (TH1 *)next())) {
689 // process only if the histogram has limits; otherwise it was processed before
690 // in the case of an existing buffer (see if statement just before)
691
692 if (gDebug)
693 Info("TH1Merger::AutoP2Merge", "merging histogram %s into %s (entries: %f)", hist->GetName(), fH0->GetName(),
694 hist->GetEntries());
695
696 // skip empty histograms
697 if (hist->IsEmpty())
698 continue;
699
700 // import statistics
701 hist->GetStats(stats);
702 for (Int_t i = 0; i < TH1::kNstat; i++)
703 totstats[i] += stats[i];
704 nentries += hist->GetEntries();
705
706 // Int_t nx = hist->GetXaxis()->GetNbins();
707 // loop on bins of the histogram and do the merge
708 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
709
711 Double_t e1sq = std::abs(cu);
712 if (fH0->fSumw2.fN)
714
715 Double_t xu = hist->GetBinCenter(ibin);
716 Int_t jbin = fH0->FindBin(xu);
717
719 if (fH0->fSumw2.fN)
721 }
722 }
723 // copy merged stats
726
727 return kTRUE;
728}
729
731{
732
733 TIter next(&fInputList);
734 while (TH1* hist = (TH1*)next()) {
735 // support also case where some histogram have limits and some have the buffer
736 if ( !TH1Merger::AxesHaveLimits(hist) && hist->fBuffer ) {
737
738 if (gDebug)
739 Info("TH1Merger::BufferMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
740 CopyBuffer(hist, fH0);
741 fInputList.Remove(hist);
742 }
743 }
744 // return true if the merge is completed
745 if (fInputList.GetSize() == 0) {
746 // all histo have been merged
747 return kTRUE;
748 }
749 // we need to reset the buffer in case of merging later on
750 // is this really needed ???
751 if (fH0->fBuffer) fH0->BufferEmpty(1);
752
753 return kFALSE;
754}
755
757
758
760 for (Int_t i=0;i<TH1::kNstat;i++) {
761 totstats[i] = stats[i] = 0;
762 }
765
766 TIter next(&fInputList);
767 while (TH1* hist=(TH1*)next()) {
768 // process only if the histogram has limits; otherwise it was processed before
769 // in the case of an existing buffer (see if statement just before)
770
771 if (gDebug)
772 Info("TH1Merger::SameAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
773
774 // skip empty histograms
775 if (hist->IsEmpty()) continue;
776
777 // import statistics
778 hist->GetStats(stats);
779 for (Int_t i=0; i<TH1::kNstat; i++)
780 totstats[i] += stats[i];
781 nentries += hist->GetEntries();
782
783 //Int_t nx = hist->GetXaxis()->GetNbins();
784 // loop on bins of the histogram and do the merge
785 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
786 MergeBin(hist, ibin, ibin);
787 }
788 }
789 //copy merged stats
792
793 return kTRUE;
794}
795
796
797/**
798 Merged histogram when axis can be different.
799 Histograms are merged looking at bin center positions
800
801 */
803
805 for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
809
810 TIter next(&fInputList);
811 while (TH1* hist=(TH1*)next()) {
812
813 if (gDebug)
814 Info("TH1Merger::DifferentAxesMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
815
816 // skip empty histograms
817 if (hist->IsEmpty()) continue;
818
819 // import statistics
820 hist->GetStats(stats);
821 for (Int_t i=0;i<TH1::kNstat;i++)
822 totstats[i] += stats[i];
823 nentries += hist->GetEntries();
824
825 // loop on bins of the histogram and do the merge
826 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
827
828 // if bin is empty we can skip it
830 continue;
831
833 hist->GetBinXYZ(ibin, binx, biny, binz);
834
835 // case of underflow/overflows in the histogram being merged
836 if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
837 if (fH0->fXaxis.CanExtend() || ( hist->fXaxis.GetBinCenter(binx) > fH0->fXaxis.GetXmin() && hist->fXaxis.GetBinCenter(binx) < fH0->fXaxis.GetXmax()) ) {
838 Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the X axis or have"
839 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
840 return kFALSE;
841 }
842 }
843 if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
844 if (fH0->fYaxis.CanExtend() || ( hist->fYaxis.GetBinCenter(biny) > fH0->fYaxis.GetXmin() && hist->fYaxis.GetBinCenter(biny) < fH0->fYaxis.GetXmax()) ) {
845 Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Y axis or have"
846 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
847 return kFALSE;
848 }
849 }
850 if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
851 if (fH0->fZaxis.CanExtend() || ( hist->fZaxis.GetBinCenter(binz) > fH0->fZaxis.GetXmin() && hist->fZaxis.GetBinCenter(binz) < fH0->fZaxis.GetXmax()) ) {
852 Error("TH1Merger::DifferentAxesMerge", "Cannot merge histograms - the histograms %s can extend the Z axis or have"
853 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
854 return kFALSE;
855 }
856 }
857
858 Int_t ix = 0;
859 Int_t iy = 0;
860 Int_t iz = 0;
861
862 // we can extend eventually the axis if histogram is capable of doing it
863 // by using FindBin
864 ix = fH0->fXaxis.FindBin(hist->GetXaxis()->GetBinCenter(binx));
865 if (fH0->fDimension > 1)
866 iy = fH0->fYaxis.FindBin(hist->GetYaxis()->GetBinCenter(biny));
867 if (fH0->fDimension > 2)
868 iz = fH0->fZaxis.FindBin(hist->GetZaxis()->GetBinCenter(binz));
869
870 Int_t ib = fH0->GetBin(ix,iy,iz);
872 Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
873 fH0->GetName(), ib,fH0->fNcells);
874 }
875
876 if (!fIsProfileMerge) {
877 MergeBin(hist, ibin, ib);
878 } else {
879 if (fIsProfile1D)
880 MergeProfileBin(static_cast<const TProfile *> (hist), ibin, ib);
881 else if (fIsProfile2D)
882 MergeProfileBin(static_cast<const TProfile2D *> (hist), ibin, ib);
883 else if (fIsProfile3D)
884 MergeProfileBin(static_cast<const TProfile3D *> (hist), ibin, ib);
885 }
886 }
887 }
888 //copy merged stats
891
892 return kTRUE;
893}
894
895/**
896 Find a duplicate labels in an axis label list
897*/
899
900 if (!labels) return kFALSE;
901
902 for (const auto * obj: *labels) {
903 auto objList = labels->GetListForObject(obj);
904 //objList->ls();
905 if (objList->GetSize() > 1 ) {
906 // check here if in the list we have duplicates
907 std::unordered_set<std::string> s;
908 for ( const auto * o: *objList) {
909 auto ret = s.insert(std::string(o->GetName() ));
910 if (!ret.second) return kTRUE;
911 }
912 }
913 }
914 return kFALSE;
915}
916
917/**
918 Check if histogram has duplicate labels
919 Return an integer with bit set correponding
920 on the axis that has duplicate labels
921 e.g. duplicate labels on x axis : return 1
922 duplicate labels on x and z axis : return 5
923
924*/
926
927 R__ASSERT(hist != nullptr);
928
929 auto labelsX = hist->GetXaxis()->GetLabels();
930 auto labelsY = hist->GetYaxis()->GetLabels();
931 auto labelsZ = hist->GetZaxis()->GetLabels();
932
933 Int_t res = 0;
935 Warning("TH1Merger::CheckForDuplicateLabels","Histogram %s has duplicate labels in the x axis. "
936 "Bin contents will be merged in a single bin",hist->GetName());
937 res |= 1;
938 }
940 Warning("TH1Merger::CheckForDuplicateLabels","Histogram %s has duplicate labels in the y axis. "
941 "Bin contents will be merged in a single bin",hist->GetName());
942 res |= 2;
943 }
945 Warning("TH1Merger::CheckForDuplicateLabels","Histogram %s has duplicate labels in the z axis. "
946 "Bin contents will be merged in a single bin",hist->GetName());
947 res |= 4;
948 }
949 return res;
950}
951
952/**
953 Merge histograms with labels and if newLimits is set support the case that one of the axis
954 can set new limits, if the axes are compatible
955*/
957
959
961 for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
964
965 // check for duplicate labels
967
968 TIter next(&fInputList);
969 while (TH1* hist=(TH1*)next()) {
970
971 if (gDebug)
972 Info("TH1Merger::LabelMerge","Merging histogram %s into %s",hist->GetName(), fH0->GetName() );
973
974 // skip empty histograms
975 if (hist->IsEmpty()) continue;
976
977 // import statistics
978 hist->GetStats(stats);
979 for (Int_t i=0;i<TH1::kNstat;i++)
980 totstats[i] += stats[i];
981 nentries += hist->GetEntries();
982
983 auto labelsX = hist->GetXaxis()->GetLabels();
984 auto labelsY = hist->GetYaxis()->GetLabels();
985 auto labelsZ = hist->GetZaxis()->GetLabels();
986 R__ASSERT(!( labelsX == nullptr && labelsY == nullptr && labelsZ == nullptr));
987
988 Bool_t mergeLabelsX = labelsX && fH0->fXaxis.CanExtend() && hist->fXaxis.CanExtend();
989 Bool_t mergeLabelsY = labelsY && fH0->fYaxis.CanExtend() && hist->fYaxis.CanExtend();
990 Bool_t mergeLabelsZ = labelsZ && fH0->fZaxis.CanExtend() && hist->fZaxis.CanExtend();
991
992 if (gDebug) {
993 if (mergeLabelsX)
994 Info("TH1Merger::LabelMerge","Merging X axis in label mode");
995 else
996 Info("TH1Merger::LabelMerge","Merging X axis in numeric mode");
997 if (mergeLabelsY)
998 Info("TH1Merger::LabelMerge","Merging Y axis in label mode");
999 else if (hist->GetDimension() > 1)
1000 Info("TH1Merger::LabelMerge","Merging Y axis in numeric mode");
1001 if (mergeLabelsZ)
1002 Info("TH1Merger::LabelMerge","Merging Z axis in label mode" );
1003 else if (hist->GetDimension() > 2)
1004 Info("TH1Merger::LabelMerge","Merging Z axis in numeric mode");
1005 }
1006
1007 // check if histogram has duplicate labels
1008 if (!fNoCheck && hist->GetEntries() > 0) CheckForDuplicateLabels(hist);
1009
1010 // loop on bins of the histogram and do the merge
1011 if (gDebug) {
1012 // print bins original histogram
1013 std::cout << "Bins of original histograms\n";
1014 for (int ix = 1; ix <= fH0->GetXaxis()->GetNbins(); ++ix) {
1015 for (int iy = 1; iy <= fH0->GetYaxis()->GetNbins(); ++iy) {
1016 for (int iz = 1; iz <= fH0->GetZaxis()->GetNbins(); ++iz) {
1017 int i = fH0->GetBin(ix,iy,iz);
1018 std::cout << "bin" << ix << "," << iy << "," << iz
1019 << " : " << fH0->RetrieveBinContent(i) /* << " , " << fH0->fBinEntries.fArray[i] */ << std::endl;
1020 }
1021 }
1022 }
1023 }
1024 for (Int_t ibin = 0; ibin < hist->fNcells; ibin++) {
1025
1026 // if bin is empty we can skip it
1027 if (IsBinEmpty(hist,ibin)) continue;
1028
1030 hist->GetBinXYZ(ibin, binx, biny, binz);
1031
1032 // here only in the case of bins with labels
1033 const char * labelX = hist->GetXaxis()->GetBinLabel(binx);
1034 const char * labelY = (fH0->fDimension > 1) ? hist->GetYaxis()->GetBinLabel(biny) : nullptr;
1035 const char * labelZ = (fH0->fDimension > 2) ? hist->GetYaxis()->GetBinLabel(binz) : nullptr;
1036
1037 // do we need to support case when there are bins with labels and bins without them ??
1038 // this case should have been detected before when examining the histograms
1039
1040 Int_t ix = -1;
1041 Int_t iy = (fH0->fDimension > 1) ? -1 : 0;
1042 Int_t iz = (fH0->fDimension > 2) ? -1 : 0;
1043
1044
1045 // special case for underflow/overflows which have normally empty labels
1046 // if (binx == 0 && TString(labelX) == "" ) ix = 0;
1047 // if (binx == hist->fXaxis.GetNbins() +1 && TString(labelX) == "" ) ix = fH0->fXaxis.GetNbins() +1;
1048
1049 // deal with the case of underflow/overflows in the histogram being merged
1050 // normally underflow/overflow have empty labels
1051 if (binx <= 0 || binx >= hist->GetNbinsX() + 1) {
1052 if (TString(labelX) == "" )
1053 ix = (binx <= 0) ? 0 : fH0->fXaxis.GetNbins() +1;
1054 if (newLimits && !mergeLabelsX) {
1055 if (fH0->fXaxis.CanExtend() || ( hist->fXaxis.GetBinCenter(binx) > fH0->fXaxis.GetXmin() && hist->fXaxis.GetBinCenter(binx) < fH0->fXaxis.GetXmax()) ) {
1056 Error("TH1Merger::LabelMerge", "Cannot merge histograms - the histograms %s can extend the X axis or have"
1057 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
1058 return kFALSE;
1059 }
1060 }
1061 }
1062 if (fH0->fDimension > 1 ) {
1063 if (biny <= 0 || biny >= hist->GetNbinsY() + 1) {
1064 if (TString(labelY) == "" )
1065 iy = (biny <= 0) ? 0 : fH0->fYaxis.GetNbins() +1;
1066 if (newLimits && !mergeLabelsY) {
1067 if (fH0->fYaxis.CanExtend() || ( hist->fYaxis.GetBinCenter(biny) > fH0->fYaxis.GetXmin() && hist->fYaxis.GetBinCenter(biny) < fH0->fYaxis.GetXmax()) ) {
1068 Error("TH1Merger::LabelMerge", "Cannot merge histograms - the histograms %s can extend the Y axis or have"
1069 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
1070 return kFALSE;
1071 }
1072 }
1073 }
1074 }
1075 if (fH0->fDimension > 2 ) {
1076 if (binz <= 0 || binz >= hist->GetNbinsZ() + 1) {
1077 if (TString(labelZ) == "" )
1078 iz = (binz <= 0) ? 0 : fH0->fZaxis.GetNbins() +1;
1079 if (newLimits && !mergeLabelsZ) {
1080 if (fH0->fZaxis.CanExtend() || ( hist->fZaxis.GetBinCenter(binz) > fH0->fZaxis.GetXmin() && hist->fZaxis.GetBinCenter(binz) < fH0->fZaxis.GetXmax()) ) {
1081 Error("TH1Merger::LabelMerge", "Cannot merge histograms - the histograms %s can extend the Z axis or have"
1082 " different limits and underflows/overflows are present in the histogram %s.",fH0->GetName(),hist->GetName());
1083 return kFALSE;
1084 }
1085 }
1086 }
1087 }
1088
1089 // find corresponding case (in case bin is not overflow)
1090 // and see if for that axis we need to merge using labels or bin numbers
1091 if (ix == -1) {
1092 if (mergeLabelsX) {
1093 ix = fH0->fXaxis.FindBin(labelX);
1094 }
1095 else
1096 // use find bin in case axis can be extended
1097 ix = FindFixBinNumber(binx, hist->fXaxis, fH0->fXaxis);
1098 }
1099
1100 if (iy == -1 && fH0->fDimension> 1 ) { // check on dim should not be needed
1101 if (mergeLabelsY)
1102 iy= fH0->fYaxis.FindBin(labelY);
1103 else
1104 iy = FindFixBinNumber(biny, hist->fYaxis, fH0->fYaxis);
1105 }
1106 if (iz == -1 && fH0->fDimension> 2) {
1107 if (mergeLabelsZ)
1108 iz= fH0->fZaxis.FindBin(labelZ);
1109 else
1110 iz = FindFixBinNumber(binz, hist->fZaxis, fH0->fZaxis);
1111 }
1112
1113 if (gDebug)
1114 Info("TH1Merge::LabelMerge","Merge bin [%d,%d,%d] with label [%s,%s,%s] into bin [%d,%d,%d]",
1115 binx,biny,binz,labelX,labelY,labelZ,ix,iy,iz);
1116
1117
1118 Int_t ib = fH0->GetBin(ix,iy,iz);
1119 if (ib < 0 || ib >= fH0->fNcells) {
1120 Fatal("TH1Merger::LabelMerge","Fatal error merging histogram %s - bin number is %d and array size is %d",
1121 fH0->GetName(), ib,fH0->fNcells);
1122 }
1123
1124 MergeBin(hist, ibin, ib);
1125 }
1126 }
1127 //copy merged stats
1130
1131 return kTRUE;
1132}
1133
1134/// helper function for merging
1135/// \param profileDim 0 if it's a regular TH1 merge (default), 1 for TProfile, 2 for TProfile2D and 3 for TProfile3D
1136
1139 Double_t e1sq = (hist->fSumw2.fN) ? hist->GetBinErrorSqUnchecked(ibin) : cu;
1140 bool profileCheck = (profileDim == 0);
1141 // For TProfiles we need also to check that entries is 0 even if content and errors are 0
1142 if (profileDim == 1) {
1143 auto prof = static_cast<const TProfile *>(hist);
1144 profileCheck = prof->fBinEntries.fArray[ibin] == 0;
1145 } else if (profileDim == 2) {
1146 auto prof = static_cast<const TProfile2D *>(hist);
1147 profileCheck = prof->fBinEntries.fArray[ibin] == 0;
1148 } else if (profileDim == 3) {
1149 auto prof = static_cast<const TProfile3D *>(hist);
1150 profileCheck = prof->fBinEntries.fArray[ibin] == 0;
1151 }
1152 return cu == 0 && e1sq == 0 && profileCheck;
1153}
1154
1155// merge input bin (ibin) of histograms hist ibin into current bin cbin of this histogram
1157{
1158 if (!fIsProfileMerge) {
1161 if (fH0->fSumw2.fN) {
1162 Double_t e1sq = (hist->fSumw2.fN) ? hist->GetBinErrorSqUnchecked(ibin) : cu;
1163 fH0->fSumw2.fArray[cbin] += e1sq;
1164 }
1165 } else {
1166 if (fIsProfile1D)
1167 MergeProfileBin(static_cast<const TProfile *> (hist), ibin, cbin);
1168 else if (fIsProfile2D)
1169 MergeProfileBin(static_cast<const TProfile2D *> (hist), ibin, cbin);
1170 else if (fIsProfile3D)
1171 MergeProfileBin(static_cast<const TProfile3D *> (hist), ibin, cbin);
1172 }
1173 return;
1174}
1175
1176// merge profile input bin (ibin) of histograms hist ibin into current bin cbin of this histogram
1177template<class TProfileType>
1179{
1180 TProfileType *p = static_cast<TProfileType *>(fH0);
1181 p->fArray[pbin] += h->fArray[hbin];
1182 p->fSumw2.fArray[pbin] += h->fSumw2.fArray[hbin];
1183 p->fBinEntries.fArray[pbin] += h->fBinEntries.fArray[hbin];
1184 if (p->fBinSumw2.fN) {
1185 if (h->fBinSumw2.fN)
1186 p->fBinSumw2.fArray[pbin] += h->fBinSumw2.fArray[hbin];
1187 else
1188 p->fBinSumw2.fArray[pbin] += h->fArray[hbin];
1189 }
1190 if (gDebug)
1191 Info("TH1Merge::MergeProfileBin", "Merge bin %d of profile %s with content %f in bin %d - result is %f", hbin,
1192 h->GetName(), h->fArray[hbin], pbin, p->fArray[pbin]);
1193}
#define h(i)
Definition RSha256.hxx:106
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
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 Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
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:267
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:16
float xmin
int nentries
float xmax
@ kMustCleanup
Definition TObject.h:371
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
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:293
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:5018
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:20
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:81
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:28
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:109
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:169
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition TH1.cxx:9167
TAxis * GetZaxis()
Definition TH1.h:574
@ kXaxis
Definition TH1.h:123
@ kNoAxis
NOTE: Must always be 0 !!!
Definition TH1.h:122
@ kZaxis
Definition TH1.h:125
@ kYaxis
Definition TH1.h:124
Int_t fNcells
Number of bins(1D), cells (2D) +U/Overflows.
Definition TH1.h:150
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:528
@ kAutoBinPTwo
different than 1.
Definition TH1.h:413
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7139
TAxis * GetXaxis()
Definition TH1.h:572
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:171
virtual void SetBinsLength(Int_t=-1)
Definition TH1.h:629
TAxis * GetYaxis()
Definition TH1.h:573
virtual Double_t GetBinErrorSqUnchecked(Int_t bin) const
Definition TH1.h:706
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:423
TAxis fZaxis
Z axis descriptor.
Definition TH1.h:153
TClass * IsA() const override
Definition TH1.h:694
TAxis fXaxis
X axis descriptor.
Definition TH1.h:151
TArrayD fSumw2
Array of sum of squares of weights.
Definition TH1.h:165
virtual Int_t GetSumw2N() const
Definition TH1.h:563
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:152
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:640
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:202
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:227
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:865
void ResetBit(UInt_t f)
Definition TObject.h:201
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:138