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