Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TProfileHelper.h
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: David Gonzalez Maline 18/01/2008
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#ifndef ROOT_TProfileHelper
13#define ROOT_TProfileHelper
14
15
16//////////////////////////////////////////////////////////////////////////
17// //
18// TProfileHelper //
19// //
20// Profile helper class. //
21// //
22//////////////////////////////////////////////////////////////////////////
23
24#include "TH1.h"
25#include "TError.h"
26#include "THashList.h"
27#include "TMath.h"
28#include "TH1Merger.h"
29
31
32public:
33 template <typename T>
34 static Bool_t Add(T* p, const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2=1);
35
36 template <typename T>
37 static void BuildArray(T* p);
38
39 template <typename T>
40 static Double_t GetBinEffectiveEntries(T* p, Int_t bin);
41
42 template <typename T>
43 static Long64_t Merge(T* p, TCollection *list);
44
45 template <typename T>
46 static T* ExtendAxis(T* p, Double_t x, TAxis *axis);
47
48 template <typename T>
49 static void Scale(T* p, Double_t c1, Option_t * option);
50
51 template <typename T>
52 static void Sumw2(T* p, Bool_t flag );
53
54 template <typename T>
55 static void LabelsDeflate(T* p, Option_t *);
56
57 template <typename T>
58 static void LabelsInflate(T* p, Option_t *);
59
60 template <typename T>
61 static Double_t GetBinError(T* p, Int_t bin);
62
63 template <typename T>
64 static void SetBinEntries(T* p, Int_t bin, Double_t w);
65
66 template <typename T>
67 static void SetErrorOption(T* p, Option_t * opt);
68};
69
70template <typename T>
72{
73 // Performs the operation: this = c1*h1 + c2*h2
74
75 T *p1 = (T*)h1;
76 T *p2 = (T*)h2;
77
78 // delete buffer if it is there since it will become invalid
79 if (p->fBuffer) p->BufferEmpty(1);
80
81// Check profile compatibility
82 Int_t nx = p->GetNbinsX();
83 Int_t ny = p->GetNbinsY();
84 Int_t nz = p->GetNbinsZ();
85
86 if ( nx != p1->GetNbinsX() || nx != p2->GetNbinsX() ||
87 ny != p1->GetNbinsY() || ny != p2->GetNbinsY() ||
88 nz != p1->GetNbinsZ() || nz != p2->GetNbinsZ() ) {
89 Error("TProfileHelper::Add","Attempt to add profiles with different number of bins");
90 return kFALSE;
91 }
92
93// Add statistics
96 p->fEntries = ac1*p1->GetEntries() + ac2*p2->GetEntries();
98 Int_t i;
99 for (i=0;i<TH1::kNstat;i++) {s0[i] = s1[i] = s2[i] = 0;}
100 p->GetStats(s0);
101 p1->GetStats(s1);
102 p2->GetStats(s2);
103 for (i=0;i<TH1::kNstat;i++) {
104 if (i == 1) s0[i] = c1*c1*s1[i] + c2*c2*s2[i];
105 else s0[i] = ac1*s1[i] + ac2*s2[i];
106 }
107 p->PutStats(s0);
108
109 // create sumw2 per bin if not set
110 if (p->fBinSumw2.fN == 0 && (p1->fBinSumw2.fN != 0 || p2->fBinSumw2.fN != 0)) p->Sumw2();
111 // create sumw2 also for the case where coefficients are not equal to 1
112 if (p->fSumw2.fN == 0 && (c1 != 1.0 || c2 != 1.0)) p->Sumw2();
113
114 // Make the loop over the bins to calculate the Addition
115 Double_t *cu1 = p1->GetW(); Double_t *cu2 = p2->GetW();
116 Double_t *er1 = p1->GetW2(); Double_t *er2 = p2->GetW2();
117 Double_t *en1 = p1->GetB(); Double_t *en2 = p2->GetB();
118 Double_t *ew1 = p1->GetB2(); Double_t *ew2 = p2->GetB2();
119 // if p1 has not the sum of weight squared/bin stored use just the sum of weights
120 if (ew1 == nullptr) ew1 = en1;
121 if (ew2 == nullptr) ew2 = en2;
122 for (Int_t bin = 0; bin < p->fN; bin++) {
123 p->fArray[bin] = c1*cu1[bin] + c2*cu2[bin];
124 p->fSumw2.fArray[bin] = ac1*er1[bin] + ac2*er2[bin];
125 p->fBinEntries.fArray[bin] = ac1*en1[bin] + ac2*en2[bin];
126 if (p->fBinSumw2.fN ) p->fBinSumw2.fArray[bin] = ac1*ac1*ew1[bin] + ac2*ac2*ew2[bin];
127 }
128 return kTRUE;
129}
130
131template <typename T>
133 // Build the extra profile data structure in addition to the histograms
134 // this are: array of bin entries: fBinEntries
135 // array of sum of profiled observable value - squared
136 // stored in TH1::fSumw2
137 // array of some of weight squared (optional) in TProfile::fBinSumw2
138 p->fBinEntries.Set(p->fNcells);
139 p->fSumw2.Set(p->fNcells);
140 if (TH1::GetDefaultSumw2() || p->fBinSumw2.fN > 0 ) p->fBinSumw2.Set(p->fNcells);
141}
142
143
144template <typename T>
146{
147// Return bin effective entries for a weighted filled Profile histogram.
148// In case of an unweighted profile, it is equivalent to the number of entries per bin
149// The effective entries is defined as the square of the sum of the weights divided by the
150// sum of the weights square.
151// TProfile::Sumw2() must be called before filling the profile with weights.
152// Only by calling this method the sum of the square of the weights per bin is stored.
153//
154
155 if (p->fBuffer) p->BufferEmpty();
156
157 if (bin < 0 || bin >= p->fNcells) return 0;
158 double sumOfWeights = p->fBinEntries.fArray[bin];
159 if ( p->fBinSumw2.fN == 0 || p->fBinSumw2.fN != p->fNcells) {
160 // this can happen when reading an old file
161 p->fBinSumw2.Set(0);
162 return sumOfWeights;
163 }
164 double sumOfWeightsSquare = p->fBinSumw2.fArray[bin];
166}
167
168template <typename T>
170 //Merge all histograms in the collection in this histogram.
171 //This function computes the min/max for the axes,
172 //compute a new number of bins, if necessary,
173 //add bin contents, errors and statistics.
174 //If overflows are present and limits are different the function will fail.
175 //The function returns the total number of entries in the result histogram
176 //if the merge is successful, -1 otherwise.
177 //
178 //IMPORTANT remark. The 2 axis x and y may have different number
179 //of bins and different limits, BUT the largest bin width must be
180 //a multiple of the smallest bin width and the upper limit must also
181 //be a multiple of the bin width.
182
183 if (!li) return 0;
184 if (li->IsEmpty()) return (Int_t) p->GetEntries();
185
187 inlist.AddAll(li);
188
189 // use TH1Merger class
190 TH1Merger merger(*p, *li, "");
191 Bool_t ret = merger();
192
193 return (ret) ? p->GetEntries() : -1;
194
195#ifdef OLD_PROFILE_MERGE
196
203// Bool_t firstNonEmptyHist = kTRUE;
204
205 TIter next(&inlist);
206 T* h = p;
207
208 do {
209
210 // skip empty histograms
211 // if (h->fTsumw == 0 && h->GetEntries() == 0) continue;
212
213 Bool_t hasLimits = h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax();
215
216 if (hasLimits) {
217 h->BufferEmpty();
218
219#ifdef LATER
220 // this is done in case the first histograms are empty and
221 // the histogram have different limits
222 if (firstNonEmptyHist ) {
223 // set axis limits in the case the first histogram was empty
224 if (h != p ) {
225 if (!p->SameLimitsAndNBins(p->fXaxis, *(h->GetXaxis())) )
226 p->fXaxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax());
227 if (!p->SameLimitsAndNBins(p->fYaxis, *(h->GetYaxis())) )
228 p->fYaxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
229 if (!p->SameLimitsAndNBins(p->fZaxis, *(h->GetZaxis())) )
230 p->fZaxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),h->GetZaxis()->GetXmax());
231 }
233 }
234#endif
235
236 // this is executed the first time an histogram with limits is found
237 // to set some initial values on the new axis
238 if (!initialLimitsFound) {
240 newXAxis.Set(h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
241 h->GetXaxis()->GetXmax());
242 if ( p->GetDimension() >= 2 )
243 newYAxis.Set(h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
244 h->GetYaxis()->GetXmax());
245 if ( p->GetDimension() >= 3 )
246 newZAxis.Set(h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
247 h->GetZaxis()->GetXmax());
248 }
249 else {
250 // check first if histograms have same bins
251 if (!p->SameLimitsAndNBins(newXAxis, *(h->GetXaxis())) ||
252 !p->SameLimitsAndNBins(newYAxis, *(h->GetYaxis())) ||
253 !p->SameLimitsAndNBins(newZAxis, *(h->GetZaxis())) ) {
254
256 // recompute in this case the optimal limits
257 // The condition to works is that the histogram have same bin with
258 // and one common bin edge
259
260 if (!p->RecomputeAxisLimits(newXAxis, *(h->GetXaxis()))) {
261 Error("TProfileHelper::Merge", "Cannot merge profiles %d dim - limits are inconsistent:\n "
262 "first: (%d, %f, %f), second: (%d, %f, %f)",p->GetDimension(),
263 newXAxis.GetNbins(), newXAxis.GetXmin(), newXAxis.GetXmax(),
264 h->GetXaxis()->GetNbins(), h->GetXaxis()->GetXmin(),
265 h->GetXaxis()->GetXmax());
266 return -1;
267 }
268 if (p->GetDimension() >= 2 && !p->RecomputeAxisLimits(newYAxis, *(h->GetYaxis()))) {
269 Error("TProfileHelper::Merge", "Cannot merge profiles %d dim - limits are inconsistent:\n "
270 "first: (%d, %f, %f), second: (%d, %f, %f)",p->GetDimension(),
271 newYAxis.GetNbins(), newYAxis.GetXmin(), newYAxis.GetXmax(),
272 h->GetYaxis()->GetNbins(), h->GetYaxis()->GetXmin(),
273 h->GetYaxis()->GetXmax());
274 return -1;
275 }
276 if (p->GetDimension() >= 3 && !p->RecomputeAxisLimits(newZAxis, *(h->GetZaxis()))) {
277 Error("TProfileHelper::Merge", "Cannot merge profiles %d dim - limits are inconsistent:\n "
278 "first: (%d, %f, %f), second: (%d, %f, %f)",p->GetDimension(),
279 newZAxis.GetNbins(), newZAxis.GetXmin(), newZAxis.GetXmax(),
280 h->GetZaxis()->GetNbins(), h->GetZaxis()->GetXmin(),
281 h->GetZaxis()->GetXmax());
282 return -1;
283 }
284 }
285 }
286 }
287 } while ( ( h = dynamic_cast<T*> ( next() ) ) != nullptr );
288 if (!h && (*next) ) {
289 Error("TProfileHelper::Merge","Attempt to merge object of class: %s to a %s",
290 (*next)->ClassName(),p->ClassName());
291 return -1;
292 }
293
294 next.Reset();
295
296 // In the case of histogram with different limits
297 // newX(Y)Axis will now have the new found limits
298 // but one needs first to clone this histogram to perform the merge
299 // The clone is not needed when all histograms have the same limits
300 T * hclone = 0;
301 if (!allSameLimits) {
302 // We don't want to add the clone to gDirectory,
303 // so remove our kMustCleanup bit temporarily
304 Bool_t mustCleanup = p->TestBit(kMustCleanup);
305 if (mustCleanup) p->ResetBit(kMustCleanup);
306 hclone = (T*)p->IsA()->New();
308 hclone->SetDirectory(0);
309 p->Copy(*hclone);
310 if (mustCleanup) p->SetBit(kMustCleanup);
311 p->BufferEmpty(1); // To remove buffer.
312 p->Reset(); // BufferEmpty sets limits so we can't use it later.
313 p->SetEntries(0);
314 inlist.AddFirst(hclone);
315 }
316
318 Int_t b[] = { newXAxis.GetNbins(), newYAxis.GetNbins(), newZAxis.GetNbins() };
319 Double_t v[] = { newXAxis.GetXmin(), newXAxis.GetXmax(),
320 newYAxis.GetXmin(), newYAxis.GetXmax(),
321 newZAxis.GetXmin(), newZAxis.GetXmax() };
322 p->SetBins(b, v);
323 }
324
325 if (!allHaveLimits) {
326 // fill this histogram with all the data from buffers of histograms without limits
327 while ( (h = dynamic_cast<T*> (next()) ) ) {
328 if (h->GetXaxis()->GetXmin() >= h->GetXaxis()->GetXmax() && h->fBuffer) {
329 // no limits
330 Int_t nbentries = (Int_t)h->fBuffer[0];
331 Double_t v[5];
332 for (Int_t i = 0; i < nbentries; i++)
333 if ( p->GetDimension() == 3 ) {
334 v[0] = h->fBuffer[5*i + 2];
335 v[1] = h->fBuffer[5*i + 3];
336 v[2] = h->fBuffer[5*i + 4];
337 v[3] = h->fBuffer[5*i + 5];
338 v[4] = h->fBuffer[5*i + 1];
339 p->Fill(v);
340 } else if ( p->GetDimension() == 2 ) {
341 v[0] = h->fBuffer[4*i + 2];
342 v[1] = h->fBuffer[4*i + 3];
343 v[2] = h->fBuffer[4*i + 4];
344 v[3] = h->fBuffer[4*i + 1];
345 v[4] = 0;
346 p->Fill(v);
347 }
348 else if ( p->GetDimension() == 1 ) {
349 v[0] = h->fBuffer[3*i + 2];
350 v[1] = h->fBuffer[3*i + 3];
351 v[2] = h->fBuffer[3*i + 1];
352 v[3] = v[4] = 0;
353 p->Fill(v);
354 }
355 }
356 }
357 if (!initialLimitsFound) {
358 if (hclone) {
359 inlist.Remove(hclone);
360 delete hclone;
361 }
362 return (Int_t) p->GetEntries(); // all histograms have been processed
363 }
364 next.Reset();
365 }
366
367 //merge bin contents and errors
369 for (Int_t i=0;i<TH1::kNstat;i++) {totstats[i] = stats[i] = 0;}
370 p->GetStats(totstats);
371 Double_t nentries = p->GetEntries();
372 Bool_t canExtend = p->CanExtendAllAxes();
373 p->SetCanExtend(TH1::kNoAxis); // reset, otherwise setting the under/overflow will extend the axis
374
375 while ( (h=static_cast<T*>(next())) ) {
376 // process only if the histogram has limits; otherwise it was processed before
377
378 if (h->GetXaxis()->GetXmin() < h->GetXaxis()->GetXmax()) {
379 // import statistics
380 h->GetStats(stats);
381 for (Int_t i = 0; i < TH1::kNstat; i++)
382 totstats[i] += stats[i];
383 nentries += h->GetEntries();
384
385 for ( Int_t hbin = 0; hbin < h->fN; ++hbin ) {
386 Int_t pbin = hbin;
387 if (!allSameLimits) {
388 // histogram have different limits:
389 // find global bin number in p given the x,y,z axis bin numbers in h
390 // in case of non equal axes
391 // we can use FindBin on p axes because SetCanExtend(TH1::kNoAxis) has been called
392 if ( h->GetW()[hbin] != 0 && (h->IsBinUnderflow(hbin) || h->IsBinOverflow(hbin)) ) {
393 // reject cases where underflow/overflow are there and bin content is not zero
394 Error("TProfileHelper::Merge", "Cannot merge profiles - they have"
395 " different limits and underflows/overflows are present."
396 " The initial profile is now broken!");
397 return -1;
398 }
400 h->GetBinXYZ(hbin, hbinx, hbiny, hbinz);
401
402 pbin = p->GetBin( p->fXaxis.FindBin( h->GetXaxis()->GetBinCenter(hbinx) ),
403 p->fYaxis.FindBin( h->GetYaxis()->GetBinCenter(hbiny) ),
404 p->fZaxis.FindBin( h->GetZaxis()->GetBinCenter(hbinz) ) );
405 }
406
407
408 p->fArray[pbin] += h->GetW()[hbin];
409 p->fSumw2.fArray[pbin] += h->GetW2()[hbin];
410 p->fBinEntries.fArray[pbin] += h->GetB()[hbin];
411 if (p->fBinSumw2.fN) {
412 if ( h->GetB2() ) p->fBinSumw2.fArray[pbin] += h->GetB2()[hbin];
413 else p->fBinSumw2.fArray[pbin] += h->GetB()[hbin];
414 }
415 }
416 }
417 }
418 if (canExtend) p->SetCanExtend(TH1::kAllAxes);
419
420 //copy merged stats
421 p->PutStats(totstats);
422 p->SetEntries(nentries);
423 if (hclone) {
424 inlist.Remove(hclone);
425 delete hclone;
426 }
427 return (Long64_t)nentries;
428#endif
429}
430
431template <typename T>
433{
434// Profile histogram is resized along axis such that x is in the axis range.
435// The new axis limits are recomputed by doubling iteratively
436// the current axis range until the specified value x is within the limits.
437// The algorithm makes a copy of the histogram, then loops on all bins
438// of the old histogram to fill the extended histogram.
439// Takes into account errors (Sumw2) if any.
440// The axis must be extendable before invoking this function.
441// Ex: h->GetXaxis()->SetCanExtend(kTRUE)
442
443
444 if (!axis->CanExtend()) return 0;
445 if (axis->GetXmin() >= axis->GetXmax()) return 0;
446 if (axis->GetNbins() <= 0) return 0;
447 if (TMath::IsNaN(x)) { // x may be a NaN
448 return 0;
449 }
450
452 if (!p->FindNewAxisLimits(axis, x, xmin, xmax))
453 return 0;
454
455 //save a copy of this histogram
456 T* hold = (T*)p->IsA()->New();
458 hold->SetDirectory(0);
459 p->Copy(*hold);
460 //set new axis limits but keep same number of bins
461 axis->SetLimits(xmin,xmax);
462 if (p->fBinSumw2.fN) hold->Sumw2();
463
464 // total bins (including underflow /overflow)
465 Int_t nx = p->fXaxis.GetNbins() + 2;
466 Int_t ny = (p->GetDimension() > 1) ? p->fYaxis.GetNbins() + 2 : 1;
467 Int_t nz = (p->GetDimension() > 2) ? p->fZaxis.GetNbins() + 2 : 1;
468
469 Int_t iaxis = 0;
470 if (axis == p->GetXaxis()) iaxis = 1;
471 if (axis == p->GetYaxis()) iaxis = 2;
472 if (axis == p->GetZaxis()) iaxis = 3;
474
475 //now loop on all bins and refill
476 p->Reset("ICE"); //reset only Integral, contents and Errors
477
478 // need to consider also underflow/overflow in the non-extending axes
480 Int_t ix, iy, iz, binx, biny, binz;
481 for (binz=0;binz< nz;binz++) {
482 zc = hold->GetZaxis()->GetBinCenter(binz);
483 iz = p->fZaxis.FindFixBin(zc);
484 for (biny=0;biny<ny;biny++) {
485 yc = hold->GetYaxis()->GetBinCenter(biny);
486 iy = p->fYaxis.FindFixBin(yc);
487 for (binx=0;binx<nx;binx++) {
488 xc = hold->GetXaxis()->GetBinCenter(binx);
489 ix = p->fXaxis.FindFixBin(xc);
490 Int_t sourceBin = hold->GetBin(binx,biny,binz);
491 // skip empty bins
492 if (hold->fBinEntries.fArray[sourceBin] == 0) continue;
493 if (hold->IsBinUnderflow(sourceBin, iaxis) || hold->IsBinOverflow(sourceBin, iaxis)) {
494 if (firstw) {
495 Warning("ExtendAxis",
496 "Histogram %s has underflow or overflow in the %s that is extendable"
497 " their content will be lost",p->GetName(),axis->GetName());
498 firstw = kFALSE;
499 }
500 continue;
501 }
502 Int_t destinationBin = p->GetBin(ix,iy,iz);
503 p->AddBinContent(destinationBin, hold->fArray[sourceBin]);
504 p->fBinEntries.fArray[destinationBin] += hold->fBinEntries.fArray[sourceBin];
505 p->fSumw2.fArray[destinationBin] += hold->fSumw2.fArray[sourceBin];
506 if (p->fBinSumw2.fN) p->fBinSumw2.fArray[destinationBin] += hold->fBinSumw2.fArray[sourceBin];
507 }
508 }
509 }
510 return hold;
511}
512
513template <typename T>
515{
517
518 // Make the loop over the bins to calculate the Addition
519 Int_t bin;
520 Double_t *cu1 = p->GetW();
521 Double_t *er1 = p->GetW2();
522 Double_t *en1 = p->GetB();
523 for (bin=0;bin<p->fN;bin++) {
524 p->fArray[bin] = c1*cu1[bin];
525 p->fSumw2.fArray[bin] = ac1*ac1*er1[bin];
526 p->fBinEntries.fArray[bin] = en1[bin];
527 }
528}
529
530template <typename T>
532{
533 // Create/Delete structure to store sum of squares of weights per bin *-*-*-*-*-*-*-*
534 // This is needed to compute the correct statistical quantities
535 // of a profile filled with weights
536 //
537 //
538 // This function is automatically called when the histogram is created
539 // if the static function TH1::SetDefaultSumw2 has been called before.
540
541 if (!flag) {
542 // clear array if existing or do nothing
543 if (p->fBinSumw2.fN > 0 ) p->fBinSumw2.Set(0);
544 return;
545 }
546
547 if ( p->fBinSumw2.fN == p->fNcells) {
548 if (!p->fgDefaultSumw2)
549 Warning("Sumw2","Sum of squares of profile bin weights structure already created");
550 return;
551 }
552
553 p->fBinSumw2.Set(p->fNcells);
554
555 // by default fill with the sum of weights which are stored in fBinEntries
556 for (Int_t bin=0; bin<p->fNcells; bin++) {
557 p->fBinSumw2.fArray[bin] = p->fBinEntries.fArray[bin];
558 }
559}
560
561template <typename T>
563{
564 // Reduce the number of bins for this axis to the number of bins having a label.
565 // Works only for the given axis passed in the option
566 // The method will remove only the extra bins existing after the last "labeled" bin.
567 // Note that if there are "un-labeled" bins present between "labeled" bins they will not be removed
568
569
570 TAxis *axis = p->GetXaxis();
571 if (ax[0] == 'y' || ax[0] == 'Y') axis = p->GetYaxis();
572 if (ax[0] == 'z' || ax[0] == 'Z') axis = p->GetZaxis();
573 if (!axis) {
574 Error("TProfileHelper::LabelsDeflate","Invalid axis option %s",ax);
575 return;
576 }
577 if (!axis->GetLabels()) return;
578
579 // find bin with last labels
580 // bin number is object ID in list of labels
581 // therefore max bin number is number of bins of the deflated histograms
582 TIter next(axis->GetLabels());
583 TObject *obj;
584 Int_t nbins = 0;
585 while ((obj = next())) {
586 Int_t ibin = obj->GetUniqueID();
587 if (ibin > nbins) nbins = ibin;
588 }
589 if (nbins < 1) nbins = 1;
590
591 // do nothing in case it was the last bin
592 if (nbins==axis->GetNbins()) return;
593
594 T *hold = (T*)p->IsA()->New();
595 hold->SetDirectory(0);
596 p->Copy(*hold);
597
598
599 Double_t xmin = axis->GetXmin();
600 Double_t xmax = axis->GetBinUpEdge(nbins);
601 axis->SetRange(0,0);
602 // set the new bins and range
603 axis->Set(nbins,xmin,xmax);
604 p->SetBinsLength(-1); // reset the number of cells
605 p->fBinEntries.Set(p->fN);
606 p->fSumw2.Set(p->fN);
607 if (p->fBinSumw2.fN) p->fBinSumw2.Set(p->fN);
608
609 // reset the content
610 p->Reset("ICE");
611
612 //now loop on all bins and refill
613 Int_t bin,binx,biny,binz;
614 for (bin =0; bin < hold->fN; ++bin)
615 {
616 hold->GetBinXYZ(bin, binx, biny, binz);
617 Int_t ibin = p->GetBin(binx, biny, binz);
618 p->fArray[ibin] += hold->fArray[bin];
619 p->fBinEntries.fArray[ibin] += hold->fBinEntries.fArray[bin];
620 p->fSumw2.fArray[ibin] += hold->fSumw2.fArray[bin];
621 if (p->fBinSumw2.fN) p->fBinSumw2.fArray[ibin] += hold->fBinSumw2.fArray[bin];
622 }
623
624 delete hold;
625}
626
627template <typename T>
629{
630// Double the number of bins for axis.
631// Refill histogram
632// This function is called by TAxis::FindBin(const char *label)
633// Works only for the given axis
634
635 if (gDebug) Info("LabelsInflate","Inflate label for axis %s of profile %s",ax,p->GetName());
636
637 Int_t iaxis = p->AxisChoice(ax);
638 TAxis *axis = nullptr;
639 if (iaxis == 1) axis = p->GetXaxis();
640 if (iaxis == 2) axis = p->GetYaxis();
641 if (iaxis == 3) axis = p->GetZaxis();
642 if (!axis) return;
643 // TAxis *axis = p->GetXaxis();
644 // if (ax[0] == 'y' || ax[0] == 'Y') axis = p->GetYaxis();
645
646 T *hold = (T*)p->IsA()->New();
647 hold->SetDirectory(0);
648 p->Copy(*hold);
649
650
651// Int_t nbxold = p->fXaxis.GetNbins();
652// Int_t nbyold = p->fYaxis.GetNbins();
653 Int_t nbins = axis->GetNbins();
654 Double_t xmin = axis->GetXmin();
655 Double_t xmax = axis->GetXmax();
656 xmax = xmin + 2*(xmax-xmin);
657 axis->SetRange(0,0);
658 // double the number of bins
659 nbins *= 2;
660 axis->Set(nbins,xmin,xmax);
661 // reset the array of content according to the axis
662 p->SetBinsLength(-1);
663 Int_t ncells = p->fN;
664 p->fBinEntries.Set(ncells);
665 p->fSumw2.Set(ncells);
666 if (p->fBinSumw2.fN) p->fBinSumw2.Set(ncells);
667
668 p->Reset("ICE"); // reset content and error
669
670 //now loop on all old bins and refill excluding underflow/overflow in
671 // the axis that has the bin doubled
672 Int_t binx, biny, binz = 0;
673 for (Int_t ibin =0; ibin < hold->fNcells; ibin++) {
674 // get the binx,y,z values . The x-y-z (axis) bin values will stay the same between new-old after the expanding
675 hold->GetBinXYZ(ibin,binx,biny,binz);
676 Int_t bin = p->GetBin(binx,biny,binz);
677
678 // underflow and overflow will be cleaned up because their meaning has been altered
679 if (hold->IsBinUnderflow(ibin,iaxis) || hold->IsBinOverflow(ibin,iaxis)) {
680 if (gDebug && hold->fBinEntries.fArray[ibin] > 0) Info("LabelsInflate","Content for underflow/overflow of bin (%d,%d,%d) will be lost",binx,biny,binz);
681 continue;
682 }
683 else {
684 p->fArray[bin] = hold->fArray[ibin];
685 p->fBinEntries.fArray[bin] = hold->fBinEntries.fArray[ibin];
686 p->fSumw2.fArray[bin] = hold->fSumw2.fArray[ibin];
687 if (p->fBinSumw2.fN) p->fBinSumw2.fArray[bin] = hold->fBinSumw2.fArray[ibin];
688 if (gDebug) Info("LabelsInflate","Copy Content from bin (%d,%d,%d) from %d in %d (%f,%f)",binx,biny,binz, ibin, bin, hold->fArray[ibin],hold->fBinEntries.fArray[ibin] );
689 }
690 }
691 delete hold;
692}
693
694template <typename T>
696 // set the profile option
697 TString opt = option;
698 opt.ToLower();
699 p->fErrorMode = kERRORMEAN;
700 if (opt.Contains("s")) p->fErrorMode = kERRORSPREAD;
701 if (opt.Contains("i")) p->fErrorMode = kERRORSPREADI;
702 if (opt.Contains("g")) p->fErrorMode = kERRORSPREADG;
703}
704
705template <typename T>
707{
708 // compute bin error of profile histograms
709
710 if (p->fBuffer) p->BufferEmpty();
711
712 if (bin < 0 || bin >= p->fNcells) return 0;
713 Double_t cont = p->fArray[bin]; // sum of bin w *y
714 Double_t sum = p->fBinEntries.fArray[bin]; // sum of bin weights
715 Double_t err2 = p->fSumw2.fArray[bin]; // sum of bin w * y^2
716 Double_t neff = p->GetBinEffectiveEntries(bin); // (sum of w)^2 / (sum of w^2)
717 if (sum == 0) return 0; // for empty bins
718 // case the values y are gaussian distributed y +/- sigma and w = 1/sigma^2
719 if (p->fErrorMode == kERRORSPREADG) {
720 return 1./TMath::Sqrt(sum);
721 }
722 // compute variance in y (eprim2) and standard deviation in y (eprim)
726
727 if (p->fErrorMode == kERRORSPREADI) {
728 if (eprim != 0) return eprim/TMath::Sqrt(neff);
729 // in case content y is an integer (so each my has an error +/- 1/sqrt(12)
730 // when the std(y) is zero
731 return 1/TMath::Sqrt(12*neff);
732 }
733
734 // if approximate compute the sums (of w, wy and wy2) using all the bins
735 // when the variance in y is zero
736 Double_t test = 1;
737 if (err2 != 0 && neff < 5) test = eprim2*sum/err2;
738 //Int_t cellLimit = (p->GetDimension() == 3)?1000404:10404;
739 if (p->fgApproximate && (test < 1.e-4 || eprim2 <= 0)) {
740 Double_t stats[TH1::kNstat] = {0};
741 p->GetStats(stats);
742 Double_t ssum = stats[0];
743 // for 1D profile
744 int index = 4; // index in the stats array for 1D
745 if (p->GetDimension() == 2) index = 7; // for 2D
746 if (p->GetDimension() == 3) index = 11; // for 3D
747 Double_t scont = stats[index];
748 Double_t serr2 = stats[index+1];
749
750 // compute mean and variance in y
751 Double_t scontsum = scont/ssum; // global mean
752 Double_t seprim2 = TMath::Abs(serr2/ssum - scontsum*scontsum); // global variance
753 eprim = 2*TMath::Sqrt(seprim2); // global std (why factor of 2 ??)
754 sum = ssum;
755 }
756 sum = TMath::Abs(sum);
757
758 // case option "S" return standard deviation in y
759 if (p->fErrorMode == kERRORSPREAD) return eprim;
760
761 // default case : fErrorMode = kERRORMEAN
762 // return standard error on the mean of y
763 //if (neff == 0) std::cerr << "NEFF = 0 for bin " << bin << " " << eprim << " " << neff << " " << std::endl;
764 return eprim/TMath::Sqrt(neff);
765
766}
767
768
769template <typename T>
771// Set the number of entries in bin for the profile
772// In case the profile stores the sum of weight squares - set the sum of weight square to the number entries
773// (i.e. assume the entries have been filled all with a weight == 1 )
774
775 if (bin < 0 || bin >= p->fNcells) return;
776 p->fBinEntries.fArray[bin] = w;
777 if (p->fBinSumw2.fN) p->fBinSumw2.fArray[bin] = w;
778
779}
780
781#endif
#define b(i)
Definition RSha256.hxx:100
#define s0(x)
Definition RSha256.hxx:90
#define s1(x)
Definition RSha256.hxx:91
#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
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
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
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
float xmin
int nentries
float xmax
@ kMustCleanup
Definition TObject.h:373
@ kERRORSPREAD
Definition TProfile.h:28
@ kERRORSPREADG
Definition TProfile.h:28
@ kERRORSPREADI
Definition TProfile.h:28
@ kERRORMEAN
Definition TProfile.h:28
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
Class to manage histogram axis.
Definition TAxis.h:32
Bool_t CanExtend() const
Definition TAxis.h:88
Double_t GetXmax() const
Definition TAxis.h:142
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition TAxis.cxx:790
virtual void SetLimits(Double_t xmin, Double_t xmax)
Definition TAxis.h:166
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:1061
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
THashList * GetLabels() const
Definition TAxis.h:123
Collection abstract base class.
Definition TCollection.h:65
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
@ kAllAxes
Definition TH1.h:126
@ kNoAxis
NOTE: Must always be 0 !!!
Definition TH1.h:122
static Bool_t GetDefaultSumw2()
Return kTRUE if TH1::Sumw2 must be called when creating new histograms.
Definition TH1.cxx:4450
@ kNstat
Size of statistics data (up to TProfile3D)
Definition TH1.h:422
void Reset()
A doubly linked list.
Definition TList.h:38
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:42
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:476
static void LabelsInflate(T *p, Option_t *)
static Double_t GetBinError(T *p, Int_t bin)
static T * ExtendAxis(T *p, Double_t x, TAxis *axis)
static void Sumw2(T *p, Bool_t flag)
static void SetBinEntries(T *p, Int_t bin, Double_t w)
static void Scale(T *p, Double_t c1, Option_t *option)
static void SetErrorOption(T *p, Option_t *opt)
static Long64_t Merge(T *p, TCollection *list)
static void BuildArray(T *p)
static Bool_t Add(T *p, const TH1 *h1, const TH1 *h2, Double_t c1, Double_t c2=1)
static Double_t GetBinEffectiveEntries(T *p, Int_t bin)
static void LabelsDeflate(T *p, Option_t *)
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
return c2
Definition legend2.C:14
Bool_t IsNaN(Double_t x)
Definition TMath.h:903
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2338