ROOT   Reference Guide
Searching...
No Matches
TProfile2D.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: Rene Brun 16/04/2000
3
4/*************************************************************************
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. * 9 * For the list of contributors see$ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TProfile2D.h"
13#include "TBuffer.h"
14#include "TMath.h"
15#include "THLimitsFinder.h"
16#include "TError.h"
17#include "TClass.h"
18#include "TProfileHelper.h"
19#include <iostream>
20
22
24
25/** \class TProfile2D
26 \ingroup Histograms
27 Profile2D histograms are used to display the mean
28 value of Z and its error for each cell in X,Y.
29 Profile2D histograms are in many cases an
30 elegant replacement of three-dimensional histograms : the inter-relation of three
31 measured quantities X, Y and Z can always be visualized by a three-dimensional
32 histogram or scatter-plot; its representation on the line-printer is not particularly
33 satisfactory, except for sparse data. If Z is an unknown (but single-valued)
34 approximate function of X,Y this function is displayed by a profile2D histogram with
35 much better precision than by a scatter-plot.
36
37 The following formulae show the cumulated contents (capital letters) and the values
38 displayed by the printing or plotting routines (small letters) of the elements for cell i, j.
39 \f[
40 \begin{align}
41 H(i,j) &= \sum w \cdot Z \\
42 E(i,j) &= \sum w \cdot Z^2 \\
43 W(i,j) &= \sum w \\
44 h(i,j) &= \frac{H(i,j)}{W(i,j)} \\
45 s(i,j) &= \sqrt{E(i,j)/W(i,j)- h(i,j)^2} \\
46 e(i,j) &= \frac{s(i,j)}{\sqrt{W(i,j)}}
47 \end{align}
48 \f]
49 The bin content is always the mean of the Z values, but errors change depending on options:
50 \f[
51 \begin{align}
52 \text{GetBinContent}(i,j) &= h(i,j) \\
53 \text{GetBinError}(i,j) &=
54 \begin{cases}
55 e(i,j) &\text{if option="" (default). Error of the mean of all z values.} \\
56 s(i,j) &\text{if option="s". Standard deviation of z values.} \\
57 \begin{cases} e(j) &\text{if } h(i,j) \ne 0 \\ 1/\sqrt{12 N} &\text{if } h(i,j)=0 \end{cases} &\text{if option="i". This is useful for storing integers such as ADC counts.} \\
58 1/\sqrt{W(i,j)} &\text{if option="g". Error of a weighted mean when combining measurements with variances of } w. \\
59 \end{cases}
60 \end{align}
61 \f]
62
63 In the special case where s(I,J) is zero (eg, case of 1 entry only in one cell)
64 the bin error e(I,J) is computed from the average of the s(I,J) for all cells
65 if the static function TProfile2D::Approximate has been called.
66 This simple/crude approximation was suggested in order to keep the cell
67 during a fit operation. But note that this approximation is not the default behaviour.
68
69 ### Creating and drawing a 2D profile
70 ~~~~{.cpp}
71 {
72 auto c1 = new TCanvas("c1","Profile histogram example",200,10,700,500);
73 auto hprof2d = new TProfile2D("hprof2d","Profile of pz versus px and py",40,-4,4,40,-4,4,0,20);
74 Float_t px, py, pz;
75 for ( Int_t i=0; i<25000; i++) {
76 gRandom->Rannor(px,py);
77 pz = px*px + py*py;
78 hprof2d->Fill(px,py,pz,1);
79 }
80 hprof2d->Draw();
81 }
82 ~~~~
83*/
84
85////////////////////////////////////////////////////////////////////////////////
86/// Default constructor for Profile2D histograms.
87
89{
90 fTsumwz = fTsumwz2 = 0;
92 BuildOptions(0,0,"");
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// Default destructor for Profile2D histograms.
97
99{
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Normal Constructor for Profile histograms.
104///
105/// The first eight parameters are similar to TH2D::TH2D.
106/// All values of z are accepted at filling time.
107/// To fill a profile2D histogram, one must use TProfile2D::Fill function.
108///
109/// Note that when filling the profile histogram the function Fill
110/// checks if the variable z is between fZmin and fZmax.
111/// If a minimum or maximum value is set for the Z scale before filling,
112/// then all values below zmin or above zmax will be discarded.
113/// Setting the minimum or maximum value for the Z scale before filling
114/// has the same effect as calling the special TProfile2D constructor below
115/// where zmin and zmax are specified.
116///
117/// H(I,J) is printed as the cell contents. The errors computed are s(I,J) if CHOPT='S'
118/// (spread option), or e(I,J) if CHOPT=' ' (error on mean).
119///
120/// See TProfile2D::BuildOptions for explanation of parameters
121///
122/// see other constructors below with all possible combinations of
123/// fix and variable bin size like in TH2D.
124
125TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,Double_t ylow,Double_t yup,Option_t *option)
126: TH2D(name,title,nx,xlow,xup,ny,ylow,yup)
127{
128 BuildOptions(0,0,option);
129 if (xlow >= xup || ylow >= yup) SetBuffer(fgBufferSize);
130}
131
132////////////////////////////////////////////////////////////////////////////////
133/// Create a 2-D Profile with variable bins in X and fix bins in Y.
134
135TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,Double_t ylow,Double_t yup,Option_t *option)
136: TH2D(name,title,nx,xbins,ny,ylow,yup)
137{
138 BuildOptions(0,0,option);
139}
140
141////////////////////////////////////////////////////////////////////////////////
142/// Create a 2-D Profile with fix bins in X and variable bins in Y.
143
144TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny,const Double_t *ybins,Option_t *option)
145: TH2D(name,title,nx,xlow,xup,ny,ybins)
146{
147 BuildOptions(0,0,option);
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Create a 2-D Profile with variable bins in X and variable bins in Y.
152
153TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,const Double_t *xbins,Int_t ny,const Double_t *ybins,Option_t *option)
154: TH2D(name,title,nx,xbins,ny,ybins)
155{
156 BuildOptions(0,0,option);
157}
158
159////////////////////////////////////////////////////////////////////////////////
160/// Constructor for Profile2D histograms with range in z.
161///
162/// The first eight parameters are similar to TH2D::TH2D.
163/// Only the values of Z between ZMIN and ZMAX will be considered at filling time.
164/// zmin and zmax will also be the maximum and minimum values
165/// on the z scale when drawing the profile2D.
166///
167/// See TProfile2D::BuildOptions for more explanations on errors
168
169TProfile2D::TProfile2D(const char *name,const char *title,Int_t nx,Double_t xlow,Double_t xup,Int_t ny, Double_t ylow,Double_t yup,Double_t zlow,Double_t zup,Option_t *option)
170: TH2D(name,title,nx,xlow,xup,ny,ylow,yup)
171{
172 BuildOptions(zlow,zup,option);
173 if (xlow >= xup || ylow >= yup) SetBuffer(fgBufferSize);
174}
175
176
177////////////////////////////////////////////////////////////////////////////////
178/// Set Profile2D histogram structure and options.
179///
180/// - zmin: minimum value allowed for z
181/// - zmax: maximum value allowed for z
182/// if (zmin = zmax = 0) there are no limits on the allowed z values (zmin = -inf, zmax = +inf)
183///
184/// - option: this is the option for the computation of the t error of the profile ( TProfile2D::GetBinError )
185/// possible values for the options are documented in TProfile2D::SetErrorOption
186///
187/// See TProfile::BuildOptions for a detailed description
188
190{
191
193
194 // create extra profile data structure (bin entries/ y^2 and sum of weight square)
196
197 fZmin = zmin;
198 fZmax = zmax;
200 fTsumwz = fTsumwz2 = 0;
201}
202
203////////////////////////////////////////////////////////////////////////////////
204/// Copy constructor.
205
207{
208 profile2d.TProfile2D::Copy(*this);
209}
210
212{
213 if (this != &profile2d)
214 profile2d.TProfile2D::Copy(*this);
215 return *this;
216}
217
218////////////////////////////////////////////////////////////////////////////////
219/// Performs the operation: this = this + c1*f1 .
220
222{
223 Error("Add","Function not implemented for TProfile2D");
224 return kFALSE;
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Performs the operation: this = this + c1*h1 .
229
231{
232 if (!h1) {
234 return kFALSE;
235 }
238 return kFALSE;
239 }
240
241 return TProfileHelper::Add(this, this, h1, 1, c1);
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Replace contents of this profile2D by the addition of h1 and h2.
246///
247/// this = c1*h1 + c2*h2
248
250{
251 if (!h1 || !h2) {
253 return kFALSE;
254 }
257 return kFALSE;
258 }
259 if (!h2->InheritsFrom(TProfile2D::Class())) {
261 return kFALSE;
262 }
263 return TProfileHelper::Add(this, h1, h2, c1, c2);
264}
265
266////////////////////////////////////////////////////////////////////////////////
267/// Static function, set the fgApproximate flag.
268///
269/// When the flag is true, the function GetBinError
270/// will approximate the bin error with the average profile error on all bins
271/// in the following situation only
272/// - the number of bins in the profile2D is less than 10404 (eg 100x100)
273/// - the bin number of entries is small ( <5)
274/// - the estimated bin error is extremely small compared to the bin content
275/// (see TProfile2D::GetBinError)
276
278{
279 fgApproximate = approx;
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// Fill histogram with all entries in the buffer.
284///
285/// - action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
286/// - action = 0 histogram is filled from the buffer
287/// - action = 1 histogram is filled and buffer is deleted
288/// The buffer is automatically deleted when the number of entries
289/// in the buffer is greater than the number of entries in the histogram
290
292{
293 // do we need to compute the bin size?
294 if (!fBuffer) return 0;
295 Int_t nbentries = (Int_t)fBuffer[0];
296 if (!nbentries) return 0;
297 Double_t *buffer = fBuffer;
298 if (nbentries < 0) {
299 if (action == 0) return 0;
300 nbentries = -nbentries;
301 fBuffer=nullptr;
302 Reset("ICES"); // reset without deleting the functions
303 fBuffer = buffer;
304 }
306 //find min, max of entries in buffer
307 Double_t xmin = fBuffer[2];
309 Double_t ymin = fBuffer[3];
311 for (Int_t i=1;i<nbentries;i++) {
312 Double_t x = fBuffer[4*i+2];
313 if (x < xmin) xmin = x;
314 if (x > xmax) xmax = x;
315 Double_t y = fBuffer[4*i+3];
316 if (y < ymin) ymin = y;
317 if (y > ymax) ymax = y;
318 }
319 if (fXaxis.GetXmax() <= fXaxis.GetXmin() || fYaxis.GetXmax() <= fYaxis.GetXmin()) {
321 } else {
322 fBuffer = nullptr;
323 Int_t keep = fBufferSize; fBufferSize = 0;
328 fBuffer = buffer;
329 fBufferSize = keep;
330 }
331 }
332
333 fBuffer = nullptr;
334 for (Int_t i=0;i<nbentries;i++) {
335 Fill(buffer[4*i+2],buffer[4*i+3],buffer[4*i+4],buffer[4*i+1]);
336 }
337 fBuffer = buffer;
338
339 if (action > 0) { delete [] fBuffer; fBuffer = nullptr; fBufferSize = 0;}
340 else {
341 if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
342 else fBuffer[0] = 0;
343 }
344 return nbentries;
345}
346
347////////////////////////////////////////////////////////////////////////////////
348/// Accumulate arguments in buffer.
349///
350/// When buffer is full, empty the buffer.
351///
352/// - fBuffer[0] = number of entries in buffer
353/// - fBuffer[1] = w of first entry
354/// - fBuffer[2] = x of first entry
355/// - fBuffer[3] = y of first entry
356/// - fBuffer[4] = z of first entry
357
359{
360 if (!fBuffer) return -3;
361 Int_t nbentries = (Int_t)fBuffer[0];
362 if (nbentries < 0) {
363 nbentries = -nbentries;
364 fBuffer[0] = nbentries;
365 if (fEntries > 0) {
366 Double_t *buffer = fBuffer; fBuffer=nullptr;
367 Reset("ICES"); // reset without deleting the functions
368 fBuffer = buffer;
369 }
370 }
371 if (4*nbentries+4 >= fBufferSize) {
372 BufferEmpty(1);
373 return Fill(x,y,z,w);
374 }
375 fBuffer[4*nbentries+1] = w;
376 fBuffer[4*nbentries+2] = x;
377 fBuffer[4*nbentries+3] = y;
378 fBuffer[4*nbentries+4] = z;
379 fBuffer[0] += 1;
380 return -2;
381}
382
383////////////////////////////////////////////////////////////////////////////////
384/// Copy a Profile2D histogram to a new profile2D histogram.
385
386void TProfile2D::Copy(TObject &obj) const
387{
388 try {
389 TProfile2D &pobj = dynamic_cast<TProfile2D &>(obj);
390
391 TH2D::Copy(pobj);
394 for (int bin=0;bin<fNcells;bin++) {
395 pobj.fArray[bin] = fArray[bin];
396 pobj.fSumw2.fArray[bin] = fSumw2.fArray[bin];
397 }
398 pobj.fZmin = fZmin;
399 pobj.fZmax = fZmax;
400 pobj.fScaling = fScaling;
401 pobj.fErrorMode = fErrorMode;
402 pobj.fTsumwz = fTsumwz;
403 pobj.fTsumwz2 = fTsumwz2;
404
405 } catch(...) {
406 Fatal("Copy","Cannot copy a TProfile2D in a %s",obj.IsA()->GetName());
407 }
408
409}
410
411////////////////////////////////////////////////////////////////////////////////
412/// Performs the operation: this = this/(c1*f1) .
413/// This function is not implemented
414
416{
417 Error("Divide","Function not implemented for TProfile2D");
418 return kFALSE;
419}
420
421////////////////////////////////////////////////////////////////////////////////
422/// Divide this profile2D by h1.
423///
424/// this = this/h1
425///
426///This function return kFALSE if the divide operation failed
427
429{
430
431 if (!h1) {
432 Error("Divide","Attempt to divide a non-existing profile2D");
433 return kFALSE;
434 }
436 Error("Divide","Attempt to divide a non-profile2D object");
437 return kFALSE;
438 }
439 TProfile2D *p1 = (TProfile2D*)h1;
440
441 // delete buffer if it is there since it will become invalid
442 if (fBuffer) BufferEmpty(1);
443
444 // Check profile compatibility
445 Int_t nx = GetNbinsX();
446 if (nx != p1->GetNbinsX()) {
447 Error("Divide","Attempt to divide profiles with different number of bins");
448 return kFALSE;
449 }
450 Int_t ny = GetNbinsY();
451 if (ny != p1->GetNbinsY()) {
452 Error("Divide","Attempt to divide profiles with different number of bins");
453 return kFALSE;
454 }
455
456 // Reset statistics
458
459 // Loop on bins (including underflows/overflows)
460 Int_t bin,binx,biny;
461 Double_t *cu1 = p1->GetW();
462 Double_t *er1 = p1->GetW2();
463 Double_t *en1 = p1->GetB();
464 Double_t c0,c1,w,z,x,y;
465 for (binx =0;binx<=nx+1;binx++) {
466 for (biny =0;biny<=ny+1;biny++) {
467 bin = biny*(fXaxis.GetNbins()+2) + binx;
468 c0 = fArray[bin];
469 c1 = cu1[bin];
470 if (c1) w = c0/c1;
471 else w = 0;
472 fArray[bin] = w;
473 z = TMath::Abs(w);
474 x = fXaxis.GetBinCenter(binx);
475 y = fYaxis.GetBinCenter(biny);
476 fEntries++;
477 fTsumw += z;
478 fTsumw2 += z*z;
479 fTsumwx += z*x;
480 fTsumwx2 += z*x*x;
481 fTsumwy += z*y;
482 fTsumwy2 += z*y*y;
483 fTsumwxy += z*x*y;
484 fTsumwz += z;
485 fTsumwz2 += z*z;
486 Double_t e0 = fSumw2.fArray[bin];
487 Double_t e1 = er1[bin];
488 Double_t c12= c1*c1;
489 if (!c1) fSumw2.fArray[bin] = 0;
490 else fSumw2.fArray[bin] = (e0*c1*c1 + e1*c0*c0)/(c12*c12);
491 if (!en1[bin]) fBinEntries.fArray[bin] = 0;
492 else fBinEntries.fArray[bin] /= en1[bin];
493 }
494 }
495 // maintaining the correct sum of weights square is not supported when dividing
496 // bin error resulting from division of profile needs to be checked
497 if (fBinSumw2.fN) {
498 Warning("Divide","Cannot preserve during the division of profiles the sum of bin weight square");
499 fBinSumw2 = TArrayD();
500 }
501 return kTRUE;
502}
503
504////////////////////////////////////////////////////////////////////////////////
505/// Replace contents of this profile2D by the division of h1 by h2.
506///
507/// this = c1*h1/(c2*h2)
508///
509/// This function return kFALSE if the divide operation failed
510
512{
513 TString opt = option;
514 opt.ToLower();
515 Bool_t binomial = kFALSE;
516 if (opt.Contains("b")) binomial = kTRUE;
517 if (!h1 || !h2) {
518 Error("Divide","Attempt to divide a non-existing profile2D");
519 return kFALSE;
520 }
522 Error("Divide","Attempt to divide a non-profile2D object");
523 return kFALSE;
524 }
525 TProfile2D *p1 = (TProfile2D*)h1;
526 if (!h2->InheritsFrom(TProfile2D::Class())) {
527 Error("Divide","Attempt to divide a non-profile2D object");
528 return kFALSE;
529 }
530 TProfile2D *p2 = (TProfile2D*)h2;
531
532 // delete buffer if it is there since it will become invalid
533 if (fBuffer) BufferEmpty(1);
534
535 // Check histogram compatibility
536 Int_t nx = GetNbinsX();
537 if (nx != p1->GetNbinsX() || nx != p2->GetNbinsX()) {
538 Error("Divide","Attempt to divide profiles with different number of bins");
539 return kFALSE;
540 }
541 Int_t ny = GetNbinsY();
542 if (ny != p1->GetNbinsY() || ny != p2->GetNbinsY()) {
543 Error("Divide","Attempt to divide profiles with different number of bins");
544 return kFALSE;
545 }
546 if (!c2) {
547 Error("Divide","Coefficient of dividing profile cannot be zero");
548 return kFALSE;
549 }
550
551 // Reset statistics
553
554 // Loop on bins (including underflows/overflows)
555 Int_t bin,binx,biny;
556 Double_t *cu1 = p1->GetW();
557 Double_t *cu2 = p2->GetW();
558 Double_t *er1 = p1->GetW2();
559 Double_t *er2 = p2->GetW2();
560 Double_t *en1 = p1->GetB();
561 Double_t *en2 = p2->GetB();
562 Double_t b1,b2,w,z,x,y,ac1,ac2;
563 ac1 = TMath::Abs(c1);
564 ac2 = TMath::Abs(c2);
565 for (binx =0;binx<=nx+1;binx++) {
566 for (biny =0;biny<=ny+1;biny++) {
567 bin = biny*(fXaxis.GetNbins()+2) + binx;
568 b1 = cu1[bin];
569 b2 = cu2[bin];
570 if (b2) w = c1*b1/(c2*b2);
571 else w = 0;
572 fArray[bin] = w;
573 z = TMath::Abs(w);
574 x = fXaxis.GetBinCenter(binx);
575 y = fYaxis.GetBinCenter(biny);
576 fEntries++;
577 fTsumw += z;
578 fTsumw2 += z*z;
579 fTsumwx += z*x;
580 fTsumwx2 += z*x*x;
581 fTsumwy += z*y;
582 fTsumwy2 += z*y*y;
583 fTsumwxy += z*x*y;
584 fTsumwz += z;
585 fTsumwz2 += z*z;
586 Double_t e1 = er1[bin];
587 Double_t e2 = er2[bin];
588 //Double_t b22= b2*b2*d2;
589 Double_t b22= b2*b2*TMath::Abs(c2);
590 if (!b2) fSumw2.fArray[bin] = 0;
591 else {
592 if (binomial) {
593 fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/(c2*b2));
594 } else {
595 fSumw2.fArray[bin] = ac1*ac2*(e1*b2*b2 + e2*b1*b1)/(b22*b22);
596 }
597 }
598 if (!en2[bin]) fBinEntries.fArray[bin] = 0;
599 else fBinEntries.fArray[bin] = en1[bin]/en2[bin];
600 }
601 }
602 return kTRUE;
603}
604
605////////////////////////////////////////////////////////////////////////////////
606/// Fill a Profile2D histogram (no weights).
607
609{
610 if (fBuffer) return BufferFill(x,y,z,1);
611
612 Int_t bin,binx,biny;
613
614 if (fZmin != fZmax) {
615 if (z <fZmin || z> fZmax || TMath::IsNaN(z) ) return -1;
616 }
617
618 fEntries++;
619 binx =fXaxis.FindBin(x);
620 biny =fYaxis.FindBin(y);
621 if (binx <0 || biny <0) return -1;
622 bin = GetBin(binx, biny);
623 fArray[bin] += z;
624 fSumw2.fArray[bin] += z*z;
625 fBinEntries.fArray[bin] += 1;
626 if (fBinSumw2.fN) fBinSumw2.fArray[bin] += 1;
627 if (binx == 0 || binx > fXaxis.GetNbins()) {
628 if (!GetStatOverflowsBehaviour()) return -1;
629 }
630 if (biny == 0 || biny > fYaxis.GetNbins()) {
631 if (!GetStatOverflowsBehaviour()) return -1;
632 }
633 ++fTsumw;
634 ++fTsumw2;
635 fTsumwx += x;
636 fTsumwx2 += x*x;
637 fTsumwy += y;
638 fTsumwy2 += y*y;
639 fTsumwxy += x*y;
640 fTsumwz += z;
641 fTsumwz2 += z*z;
642 return bin;
643}
644
645////////////////////////////////////////////////////////////////////////////////
646/// Fill a Profile2D histogram with weights.
647
649{
650 if (fBuffer) return BufferFill(x, y, z, w);
651
652 Int_t bin, binx, biny;
653
654 if (fZmin != fZmax) {
655 if (z < fZmin || z > fZmax || TMath::IsNaN(z)) return -1;
656 }
657
658 Double_t u = w;
659 fEntries++;
660 binx = fXaxis.FindBin(x);
661 biny = fYaxis.FindBin(y);
662 if (binx < 0 || biny < 0) return -1;
663 bin = biny * (fXaxis.GetNbins() + 2) + binx;
665 fSumw2.fArray[bin] += u * z * z;
666 if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW))
667 Sumw2(); // must be called before accumulating the entries
668 if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u * u;
669 fBinEntries.fArray[bin] += u;
670
671 if (binx == 0 || binx > fXaxis.GetNbins()) {
672 if (!GetStatOverflowsBehaviour()) return -1;
673 }
674 if (biny == 0 || biny > fYaxis.GetNbins()) {
675 if (!GetStatOverflowsBehaviour()) return -1;
676 }
677 fTsumw += u;
678 fTsumw2 += u * u;
679 fTsumwx += u * x;
680 fTsumwx2 += u * x * x;
681 fTsumwy += u * y;
682 fTsumwy2 += u * y * y;
683 fTsumwxy += u * x * y;
684 fTsumwz += u * z;
685 fTsumwz2 += u * z * z;
686 return bin;
687}
688////////////////////////////////////////////////////////////////////////////////
689/// Fill a Profile2D histogram (no weights).
690
692{
693 Int_t bin,binx,biny;
694
695 if (fZmin != fZmax) {
696 if (z <fZmin || z> fZmax || TMath::IsNaN(z)) return -1;
697 }
698
699 Double_t u = w;
700 fEntries++;
701 binx =fXaxis.FindBin(x);
702 biny =fYaxis.FindBin(namey);
703 if (binx <0 || biny <0) return -1;
704 bin = biny*(fXaxis.GetNbins()+2) + binx;
706 fSumw2.fArray[bin] += u * z * z;
707 if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW))
708 Sumw2(); // must be called before accumulating the entries
709 if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u * u;
710 fBinEntries.fArray[bin] += u;
711
712 if (binx == 0 || binx > fXaxis.GetNbins()) {
713 if (!GetStatOverflowsBehaviour()) return -1;
714 }
715 if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
716
718 Double_t y = (labelBitMask & TH1::kYaxis) ? 0 : fYaxis.GetBinCenter(biny);
719
720 fTsumw += u;
721 fTsumw2 += u * u;
722 fTsumwx += u * x;
723 fTsumwx2 += u * x * x;
724 fTsumwy += u * y;
725 fTsumwy2 += u * y * y;
726 fTsumwxy += u * x * y;
727 fTsumwz += u * z;
728 fTsumwz2 += u * z * z;
729
730 return bin;
731}
732
733////////////////////////////////////////////////////////////////////////////////
734/// Fill a Profile2D histogram (no weights).
735
736Int_t TProfile2D::Fill(const char *namex, const char *namey, Double_t z, Double_t w)
737{
738 Int_t bin,binx,biny;
739
740 if (fZmin != fZmax) {
741 if (z <fZmin || z> fZmax || TMath::IsNaN(z) ) return -1;
742 }
743
744 Double_t u = w;
745 fEntries++;
746 binx = fXaxis.FindBin(namex);
747 biny = fYaxis.FindBin(namey);
748 if (binx < 0 || biny < 0)
749 return -1;
750 bin = biny * (fXaxis.GetNbins() + 2) + binx;
752 fSumw2.fArray[bin] += u * z * z;
753 if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW))
754 Sumw2(); // must be called before accumulating the entries
755 if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u * u;
756 fBinEntries.fArray[bin] += u;
757
758 if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
759 if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
760
762 Double_t x = (labelBitMask & TH1::kXaxis) ? 0 : fXaxis.GetBinCenter(binx);
763 Double_t y = (labelBitMask & TH1::kYaxis) ? 0 : fYaxis.GetBinCenter(biny);
764
765 fTsumw += u;
766 fTsumw2 += u * u;
767 fTsumwx += u * x;
768 fTsumwx2 += u * x * x;
769 fTsumwy += u * y;
770 fTsumwy2 += u * y * y;
771 fTsumwxy += u * x * y;
772 fTsumwz += u * z;
773 fTsumwz2 += u * z * z;
774
775 return bin;
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Fill a Profile2D histogram (no weights).
780
782{
783 Int_t bin,binx,biny;
784
785 if (fZmin != fZmax) {
786 if (z <fZmin || z> fZmax || TMath::IsNaN(z)) return -1;
787 }
788
789 Double_t u = w;
790 fEntries++;
791 binx =fXaxis.FindBin(namex);
792 biny =fYaxis.FindBin(y);
793 if (binx <0 || biny <0) return -1;
794 bin = biny*(fXaxis.GetNbins()+2) + binx;
795
797 fSumw2.fArray[bin] += u * z * z;
798 if (!fBinSumw2.fN && u != 1.0 && !TestBit(TH1::kIsNotW))
799 Sumw2(); // must be called before accumulating the entries
800 if (fBinSumw2.fN) fBinSumw2.fArray[bin] += u * u;
801 fBinEntries.fArray[bin] += u;
802
803 if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
804 if (biny == 0 || biny > fYaxis.GetNbins()) {
805 if (!GetStatOverflowsBehaviour()) return -1;
806 }
807
809 Double_t x = (labelBitMask & TH1::kXaxis) ? 0 : fXaxis.GetBinCenter(binx);
810
811 fTsumw += u;
812 fTsumw2 += u * u;
813 fTsumwx += u * x;
814 fTsumwx2 += u * x * x;
815 fTsumwy += u * y;
816 fTsumwy2 += u * y * y;
817 fTsumwxy += u * x * y;
818 fTsumwz += u * z;
819 fTsumwz2 += u * z * z;
820
821 return bin;
822}
823
824
825
826////////////////////////////////////////////////////////////////////////////////
827/// Return bin content of a Profile2D histogram.
828
830{
831 if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
832
833 if (bin < 0 || bin >= fNcells) return 0;
834 if (fBinEntries.fArray[bin] == 0) return 0;
835 if (!fArray) return 0;
836 return fArray[bin]/fBinEntries.fArray[bin];
837}
838
839////////////////////////////////////////////////////////////////////////////////
840/// Return bin entries of a Profile2D histogram.
841
843{
844 if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
845
846 if (bin < 0 || bin >= fNcells) return 0;
847 return fBinEntries.fArray[bin];
848}
849
850////////////////////////////////////////////////////////////////////////////////
851/// Return bin effective entries for a weighted filled Profile histogram.
852/// In case of an unweighted profile, it is equivalent to the number of entries per bin
853/// The effective entries is defined as the square of the sum of the weights divided by the
854/// sum of the weights square.
855/// TProfile::Sumw2() must be called before filling the profile with weights.
856/// Only by calling this method the sum of the square of the weights per bin is stored.
857
859{
861}
862
863////////////////////////////////////////////////////////////////////////////////
864/// Return bin error of a Profile2D histogram.
865///
866/// ### Computing errors: A moving field
867///
868/// The computation of errors for a TProfile2D has evolved with the versions
869/// of ROOT. The difficulty is in computing errors for bins with low statistics.
870/// - prior to version 3.10, we had no special treatment of low statistic bins.
871/// As a result, these bins had huge errors. The reason is that the
872/// expression eprim2 is very close to 0 (rounding problems) or 0.
873/// - The algorithm is modified/protected for the case
874/// when a TProfile2D is projected (ProjectionX). The previous algorithm
875/// generated a N^2 problem when projecting a TProfile2D with a large number of
876/// bins (eg 100000).
877/// - in version 3.10/02, a new static function TProfile::Approximate
878/// is introduced to enable or disable (default) the approximation.
880
882{
883 return TProfileHelper::GetBinError((TProfile2D*)this, bin);
884}
885
886////////////////////////////////////////////////////////////////////////////////
887/// Return option to compute profile2D errors.
888
890{
891 if (fErrorMode == kERRORSPREAD) return "s";
892 if (fErrorMode == kERRORSPREADI) return "i";
893 if (fErrorMode == kERRORSPREADG) return "g";
894 return "";
895}
896
897////////////////////////////////////////////////////////////////////////////////
898/// Fill the array stats from the contents of this profile.
899/// The array stats must be correctly dimensioned in the calling program.
900///
901/// - stats[0] = sumw
902/// - stats[1] = sumw2
903/// - stats[2] = sumwx
904/// - stats[3] = sumwx2
905/// - stats[4] = sumwy
906/// - stats[5] = sumwy2
907/// - stats[6] = sumwxy
908/// - stats[7] = sumwz
909/// - stats[8] = sumwz2
910///
911/// If no axis-subrange is specified (via TAxis::SetRange), the array stats
912/// is simply a copy of the statistics quantities computed at filling time.
913/// If a sub-range is specified, the function recomputes these quantities
914/// from the bin contents in the current axis range.
915
917{
918 if (fBuffer) ((TProfile2D*)this)->BufferEmpty();
919
920 // check for labels axis . In that case corresponding statistics do not make sense and it is set to zero
921 Bool_t labelXaxis = ((const_cast<TAxis&>(fXaxis)).GetLabels() && fXaxis.CanExtend() );
922 Bool_t labelYaxis = ((const_cast<TAxis&>(fYaxis)).GetLabels() && fYaxis.CanExtend() );
923
924 // Loop on bins
925 if ( (fTsumw == 0 /* && fEntries > 0 */) || fXaxis.TestBit(TAxis::kAxisRange) || fYaxis.TestBit(TAxis::kAxisRange)) {
926 Int_t bin, binx, biny;
927 Double_t w, w2;
928 Double_t x,y;
929 for (bin=0;bin<9;bin++) stats[bin] = 0;
930 if (!fBinEntries.fArray) return;
931 Int_t firstBinX = fXaxis.GetFirst();
932 Int_t lastBinX = fXaxis.GetLast();
933 Int_t firstBinY = fYaxis.GetFirst();
934 Int_t lastBinY = fYaxis.GetLast();
935 // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
938 if (firstBinX == 1) firstBinX = 0;
939 if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
940 }
942 if (firstBinY == 1) firstBinY = 0;
943 if (lastBinY == fYaxis.GetNbins() ) lastBinY += 1;
944 }
945 }
946 for (biny = firstBinY; biny <= lastBinY; biny++) {
947 y = (!labelYaxis) ? fYaxis.GetBinCenter(biny) : 0;
948 for (binx = firstBinX; binx <= lastBinX; binx++) {
949 bin = GetBin(binx,biny);
950 w = fBinEntries.fArray[bin];
951 w2 = (fBinSumw2.fN ? fBinSumw2.fArray[bin] : w );
952 x = (!labelXaxis) ? fXaxis.GetBinCenter(binx) : 0;
953 stats[0] += w;
954 stats[1] += w2;
955 stats[2] += w*x;
956 stats[3] += w*x*x;
957 stats[4] += w*y;
958 stats[5] += w*y*y;
959 stats[6] += w*x*y;
960 stats[7] += fArray[bin];
961 stats[8] += fSumw2.fArray[bin];
962 }
963 }
964 } else {
965 stats[0] = fTsumw;
966 stats[1] = fTsumw2;
967 stats[2] = fTsumwx;
968 stats[3] = fTsumwx2;
969 stats[4] = fTsumwy;
970 stats[5] = fTsumwy2;
971 stats[6] = fTsumwxy;
972 stats[7] = fTsumwz;
973 stats[8] = fTsumwz2;
974 }
975}
976
977////////////////////////////////////////////////////////////////////////////////
978/// Reduce the number of bins for this axis to the number of bins having a label.
979
981{
983}
984
985////////////////////////////////////////////////////////////////////////////////
986/// Double the number of bins for axis.
987/// Refill histogram
988/// This function is called by TAxis::FindBin(const char *label)
989
991{
993}
994
995////////////////////////////////////////////////////////////////////////////////
996/// Set option(s) to draw axis with labels.
997///
998/// option might have the following values:
999///
1000/// - "a" sort by alphabetic order
1001/// - ">" sort by decreasing values
1002/// - "<" sort by increasing values
1003/// - "h" draw labels horizontal
1004/// - "v" draw labels vertical
1005/// - "u" draw labels up (end of label right adjusted)
1006/// - "d" draw labels down (start of label left adjusted)
1007
1009{
1010
1011 TAxis *axis = GetXaxis();
1012 if (ax[0] == 'y' || ax[0] == 'Y') axis = GetYaxis();
1013 THashList *labels = axis->GetLabels();
1014 if (!labels) {
1015 Warning("LabelsOption","Cannot sort. No labels");
1016 return;
1017 }
1018 TString opt = option;
1019 opt.ToLower();
1020 if (opt.Contains("h")) {
1025 }
1026 if (opt.Contains("v")) {
1031 }
1032 if (opt.Contains("u")) {
1033 axis->SetBit(TAxis::kLabelsUp);
1037 }
1038 if (opt.Contains("d")) {
1043 }
1044 Int_t sort = -1;
1045 if (opt.Contains("a")) sort = 0;
1046 if (opt.Contains(">")) sort = 1;
1047 if (opt.Contains("<")) sort = 2;
1048 if (sort < 0) return;
1049
1050 // support only cases where each bin has a labels (should be when axis is alphanumeric)
1051 Int_t n = labels->GetSize();
1052 if (n != axis->GetNbins()) {
1053 // check if labels are all consecutive and starts from the first bin
1054 // in that case the current code will work fine
1055 Int_t firstLabelBin = axis->GetNbins() + 1;
1056 Int_t lastLabelBin = -1;
1057 for (Int_t i = 0; i < n; ++i) {
1058 Int_t bin = labels->At(i)->GetUniqueID();
1059 if (bin < firstLabelBin)
1060 firstLabelBin = bin;
1061 if (bin > lastLabelBin)
1062 lastLabelBin = bin;
1063 }
1064 if (firstLabelBin != 1 || lastLabelBin - firstLabelBin + 1 != n) {
1065 Error("LabelsOption",
1066 "%s of TProfile2D %s contains bins without labels. Sorting will not work correctly - return",
1067 axis->GetName(), GetName());
1068 return;
1069 }
1070 // case where label bins are consecutive starting from first bin will work
1071 Warning(
1072 "LabelsOption",
1073 "axis %s of TProfile2D %s has extra following bins without labels. Sorting will work only for first label bins",
1074 axis->GetName(), GetName());
1075 }
1076
1077 std::vector<Int_t> a(n);
1078 Int_t i, j, k, ibin, bin;
1079 std::vector<Double_t> sumw(fNcells);
1080 std::vector<Double_t> errors(fNcells);
1081 std::vector<Double_t> ent(fNcells);
1082 std::vector<Double_t> binsw2;
1083 if (fBinSumw2.fN)
1084 binsw2.resize(fNcells);
1085
1086 // delete buffer if it is there since bins will be reordered.
1087 if (fBuffer)
1088 BufferEmpty(1);
1089
1090 // number of bins to loop
1091 Int_t nx = (axis == GetXaxis()) ? n + 1 : fXaxis.GetNbins() + 2;
1092 Int_t ny = (axis == GetYaxis()) ? n + 1 : fYaxis.GetNbins() + 2;
1093
1094 // make a labelold list but ordered with bins
1095 // (re-ordered original label list)
1096 std::vector<TObject *> labold(n);
1097 for (i = 0; i < n; i++)
1098 labold[i] = nullptr;
1099 TIter nextold(labels);
1100 TObject *obj;
1101 while ((obj = nextold())) {
1102 bin = obj->GetUniqueID();
1103 if (bin>=1 && bin<=n)
1104 labold[bin-1] = obj;
1105 }
1106 // order now labold according to bin content
1107
1108 labels->Clear();
1109
1110 std::vector<Double_t> pcont;
1111 std::vector<Double_t> econt;
1112 if (sort > 0) {
1113 pcont.resize(n);
1114 econt.resize(n);
1115 }
1116
1117 for (i = 0; i < nx; i++) {
1118 for (j = 0; j < ny; j++) {
1119 bin = GetBin(i, j);
1120 sumw[bin] = fArray[bin];
1121 errors[bin] = fSumw2.fArray[bin];
1122 ent[bin] = fBinEntries.fArray[bin];
1123 if (fBinSumw2.fN)
1124 binsw2[bin] = fBinSumw2.fArray[bin];
1125 if (axis == GetXaxis())
1126 k = i - 1;
1127 else
1128 k = j - 1;
1129 //---when sorting by values of bins
1130 if (sort > 0 && fBinEntries.fArray[bin] != 0 && k > 0 && k < n) {
1131 pcont[k] += fArray[bin];
1132 econt[k] += fBinEntries.fArray[bin];
1133 }
1134 }
1135 }
1136 // compute average of slize for ordering
1137 if (sort > 0) {
1138 for (k = 0; k < n; ++k) {
1139 a[k] = k;
1140 if (econt[k] > 0)
1141 pcont[k] /= econt[k];
1142 }
1143 if (sort == 1)
1144 TMath::Sort(n, pcont.data(), a.data(), kTRUE); // sort by decreasing values
1145 else
1146 TMath::Sort(n, pcont.data(), a.data(), kFALSE); // sort by increasing values
1147 } else {
1148 //---alphabetic sort
1149 // sort labels using vector of strings and TMath::Sort
1150 // I need to array because labels order in list is not necessary that of the bins
1151 std::vector<std::string> vecLabels(n);
1152 for (i = 0; i < n; i++) {
1153 vecLabels[i] = labold[i]->GetName();
1154 a[i] = i;
1155 }
1156 // sort in ascending order for strings
1157 TMath::Sort(n, vecLabels.data(), a.data(), kFALSE);
1158 }
1159
1160 // set the new labels
1161 for (i = 0; i < n; i++) {
1162 obj = labold[a[i]];
1164 // set the corresponding bin. NB bin starts from 1
1165 obj->SetUniqueID(i + 1);
1166 if (gDebug)
1167 std::cout << "bin " << i + 1 << " setting new labels for axis " << labold.at(a[i])->GetName() << " from "
1168 << a[i] << std::endl;
1169 }
1170 // set the new content
1171 for (i = 0; i < nx; i++) {
1172 for (j = 0; j < ny; j++) {
1173 bin = GetBin(i, j);
1174 if (axis == GetXaxis()) {
1175 if (i == 0) break; // skip underflow in x
1176 ibin = GetBin(a[i - 1] + 1, j);
1177 } else {
1178 if (j == 0) continue; // skip underflow in y
1179 ibin = GetBin(i, a[j-1] + 1);
1180 }
1181 fArray[bin] = sumw[ibin];
1182 fSumw2.fArray[bin] = errors[ibin];
1183 fBinEntries.fArray[bin] = ent[ibin];
1184 if (fBinSumw2.fN)
1185 fBinSumw2.fArray[bin] = binsw2[ibin];
1186 }
1187 }
1188 // need to set to zero the statistics if axis has been sorted
1189 // see for example TH3::PutStats for definition of s vector
1190 bool labelsAreSorted = kFALSE;
1191 for (i = 0; i < n; ++i) {
1192 if (a[i] != i) {
1193 labelsAreSorted = kTRUE;
1194 break;
1195 }
1196 }
1197 if (labelsAreSorted) {
1198 double s[TH1::kNstat];
1199 GetStats(s);
1200 if (axis == GetXaxis()) {
1201 s[2] = 0; // fTsumwx
1202 s[3] = 0; // fTsumwx2
1203 s[6] = 0; // fTsumwxy
1204 } else {
1205 s[4] = 0; // fTsumwy
1206 s[5] = 0; // fTsumwy2
1207 s[6] = 0; // fTsumwxy
1208 }
1209 PutStats(s);
1210 }
1211}
1212
1213////////////////////////////////////////////////////////////////////////////////
1214/// Merge all histograms in the collection in this histogram.
1215/// This function computes the min/max for the axes,
1216/// compute a new number of bins, if necessary,
1217/// add bin contents, errors and statistics.
1218/// If overflows are present and limits are different the function will fail.
1219/// The function returns the total number of entries in the result histogram
1220/// if the merge is successful, -1 otherwise.
1221///
1222/// IMPORTANT remark. The 2 axis x and y may have different number
1223/// of bins and different limits, BUT the largest bin width must be
1224/// a multiple of the smallest bin width and the upper limit must also
1225/// be a multiple of the bin width.
1226
1228{
1229 return TProfileHelper::Merge(this, li);
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Performs the operation: this = this*c1*f1
1234
1236{
1237 Error("Multiply","Function not implemented for TProfile2D");
1238 return kFALSE;
1239}
1240
1241////////////////////////////////////////////////////////////////////////////////
1242/// Multiply this profile2D by h1.
1243///
1244/// this = this*h1
1245
1247{
1248 Error("Multiply","Multiplication of profile2D histograms not implemented");
1249 return kFALSE;
1250}
1251
1252////////////////////////////////////////////////////////////////////////////////
1253/// Replace contents of this profile2D by multiplication of h1 by h2.
1254///
1255/// this = (c1*h1)*(c2*h2)
1256
1258{
1259 Error("Multiply","Multiplication of profile2D histograms not implemented");
1260 return kFALSE;
1261}
1262
1263////////////////////////////////////////////////////////////////////////////////
1264/// Project this profile2D into a 2-D histogram along X,Y.
1265///
1266/// The projection is always of the type TH2D.
1267///
1268/// - if option "E" is specified the errors of the projected histogram are computed and set
1269/// to be equal to the errors of the profile.
1270/// Option "E" is defined as the default one in the header file.
1271/// - if option "" is specified the histogram errors are simply the sqrt of its content
1272/// - if option "B" is specified, the content of bin of the returned histogram
1273/// will be equal to the GetBinEntries(bin) of the profile,
1274/// - if option "C=E" the bin contents of the projection are set to the
1275/// bin errors of the profile
1276/// - if option "W" is specified the bin content of the projected histogram is set to the
1277/// product of the bin content of the profile and the entries.
1278/// With this option the returned histogram will be equivalent to the one obtained by
1279/// filling directly a TH2D using the 3-rd value as a weight.
1280/// This option makes sense only for profile filled with all weights =1.
1281/// When the profile is weighted (filled with weights different than 1) the
1282/// bin error of the projected histogram (obtained using this option "W") cannot be
1283/// correctly computed from the information stored in the profile. In that case the
1284/// obtained histogram contains as bin error square the weighted sum of the square of the
1285/// profiled observable (TProfile2D::fSumw2[bin] )
1286
1288{
1289
1290 TString opt = option;
1291 opt.ToLower();
1292
1293 // Create the projection histogram
1294 // name of projected histogram is by default name of original histogram + _pxy
1295 TString pname(name);
1296 if (pname.IsNull() || pname == "_pxy")
1297 pname = TString(GetName() ) + TString("_pxy");
1298
1299
1300 Int_t nx = fXaxis.GetNbins();
1301 Int_t ny = fYaxis.GetNbins();
1302 const TArrayD *xbins = fXaxis.GetXbins();
1303 const TArrayD *ybins = fYaxis.GetXbins();
1304 TH2D * h1 = nullptr;
1305 if (xbins->fN == 0 && ybins->fN == 0) {
1306 h1 = new TH2D(pname,GetTitle(),nx,fXaxis.GetXmin(),fXaxis.GetXmax(),ny,fYaxis.GetXmin(),fYaxis.GetXmax());
1307 } else if (xbins->fN == 0) {
1308 h1 = new TH2D(pname,GetTitle(),nx,fXaxis.GetXmin(),fXaxis.GetXmax(),ny, ybins->GetArray() );
1309 } else if (ybins->fN == 0) {
1310 h1 = new TH2D(pname,GetTitle(),nx,xbins->GetArray(),ny,fYaxis.GetXmin(),fYaxis.GetXmax());
1311 } else {
1312 h1 = new TH2D(pname,GetTitle(),nx,xbins->GetArray(),ny,ybins->GetArray() );
1313 }
1314 Bool_t computeErrors = kFALSE;
1315 Bool_t cequalErrors = kFALSE;
1316 Bool_t binEntries = kFALSE;
1317 Bool_t binWeight = kFALSE;
1318 if (opt.Contains("b")) binEntries = kTRUE;
1319 if (opt.Contains("e")) computeErrors = kTRUE;
1320 if (opt.Contains("w")) binWeight = kTRUE;
1321 if (opt.Contains("c=e")) {cequalErrors = kTRUE; computeErrors=kFALSE;}
1322 if (computeErrors || binWeight || (binEntries && fBinSumw2.fN) ) h1->Sumw2();
1323
1324 // Fill the projected histogram
1325 Int_t bin,binx, biny;
1326 Double_t cont;
1327 for (binx =0;binx<=nx+1;binx++) {
1328 for (biny =0;biny<=ny+1;biny++) {
1329 bin = GetBin(binx,biny);
1330
1331 if (binEntries) cont = GetBinEntries(bin);
1332 else if (cequalErrors) cont = GetBinError(bin);
1333 else if (binWeight) cont = GetBinContent(bin) * GetBinEntries(bin);
1334 else cont = GetBinContent(bin); // default case
1335
1336 h1->SetBinContent(bin ,cont);
1337
1338 // if option E projected histogram errors are same as profile
1339 if (computeErrors ) h1->SetBinError(bin , GetBinError(bin) );
1340 // in case of option W bin error is deduced from bin sum of z**2 values of profile
1341 // this is correct only if the profile is unweighted
1342 if (binWeight) h1->GetSumw2()->fArray[bin] = fSumw2.fArray[bin];
1343 // in case of bin entries and profile is weighted, we need to set also the bin error
1344 if (binEntries && fBinSumw2.fN ) {
1345 R__ASSERT( h1->GetSumw2() );
1346 h1->GetSumw2()->fArray[bin] = fBinSumw2.fArray[bin];
1347 }
1348 }
1349 }
1351 return h1;
1352}
1353
1354////////////////////////////////////////////////////////////////////////////////
1355/// Project a 2-D histogram into a profile histogram along X.
1356///
1357/// The projection is made from the channels along the Y axis
1358/// ranging from firstybin to lastybin included.
1359/// The result is a 1D profile which contains the combination of all the considered bins along Y
1360/// By default, bins 1 to ny are included
1361/// When all bins are included, the number of entries in the projection
1362/// is set to the number of entries of the 2-D histogram, otherwise
1363/// the number of entries is incremented by 1 for all non empty cells.
1364///
1365/// The option can also be used to specify the projected profile error type.
1366/// Values which can be used are 's', 'i', or 'g'. See TProfile::BuildOptions for details
1367
1368TProfile *TProfile2D::ProfileX(const char *name, Int_t firstybin, Int_t lastybin, Option_t *option) const
1369{
1370 return DoProfile(true, name, firstybin, lastybin, option);
1371}
1372
1373////////////////////////////////////////////////////////////////////////////////
1374/// Project a 2-D histogram into a profile histogram along X
1375///
1376/// The projection is made from the channels along the X axis
1377/// ranging from firstybin to lastybin included.
1378/// The result is a 1D profile which contains the combination of all the considered bins along X
1379/// By default, bins 1 to ny are included
1380/// When all bins are included, the number of entries in the projection
1381/// is set to the number of entries of the 2-D histogram, otherwise
1382/// the number of entries is incremented by 1 for all non empty cells.
1383///
1384/// The option can also be used to specify the projected profile error type.
1385/// Values which can be used are 's', 'i', or 'g'. See TProfile::BuildOptions for details
1386
1387TProfile *TProfile2D::ProfileY(const char *name, Int_t firstxbin, Int_t lastxbin, Option_t *option) const
1388{
1389 return DoProfile(false, name, firstxbin, lastxbin, option);
1390}
1391
1392////////////////////////////////////////////////////////////////////////////////
1393/// Implementation of ProfileX or ProfileY for a TProfile2D.
1394///
1395/// Do correctly the combination of the bin averages when doing the projection
1396
1397TProfile * TProfile2D::DoProfile(bool onX, const char *name, Int_t firstbin, Int_t lastbin, Option_t *option) const {
1398 TString opt = option;
1399 opt.ToLower();
1400 bool originalRange = opt.Contains("o");
1401
1402 TString expectedName = ( onX ? "_pfx" : "_pfy" );
1403
1404 TString pname(name);
1405 if (pname.IsNull() || name == expectedName)
1406 pname = TString(GetName() ) + expectedName;
1407
1408 const TAxis& outAxis = ( onX ? fXaxis : fYaxis );
1409 const TArrayD *bins = outAxis.GetXbins();
1410 Int_t firstOutBin = outAxis.GetFirst();
1411 Int_t lastOutBin = outAxis.GetLast();
1412
1413 TProfile * p1 = nullptr;
1414 // case of fixed bins
1415 if (bins->fN == 0) {
1416 if (originalRange)
1417 p1 = new TProfile(pname,GetTitle(), outAxis.GetNbins(), outAxis.GetXmin(), outAxis.GetXmax(), opt );
1418 else
1419 p1 = new TProfile(pname,GetTitle(), lastOutBin-firstOutBin+1,
1420 outAxis.GetBinLowEdge(firstOutBin),outAxis.GetBinUpEdge(lastOutBin), opt);
1421 } else {
1422 // case of variable bins
1423 if (originalRange )
1424 p1 = new TProfile(pname,GetTitle(),outAxis.GetNbins(),bins->fArray,opt);
1425 else
1426 p1 = new TProfile(pname,GetTitle(),lastOutBin-firstOutBin+1,&bins->fArray[firstOutBin-1],opt);
1427
1428 }
1429
1430 if (fBinSumw2.fN) p1->Sumw2();
1431
1432 // make projection in a 2D first
1433 TH2D * h2dW = ProjectionXY("h2temp-W","W");
1434 TH2D * h2dN = ProjectionXY("h2temp-N","B");
1435
1436 h2dW->SetDirectory(nullptr); h2dN->SetDirectory(nullptr);
1437
1438
1439 TString opt1 = (originalRange) ? "o" : "";
1440 TH1D * h1W = (onX) ? h2dW->ProjectionX("h1temp-W",firstbin,lastbin,opt1) : h2dW->ProjectionY("h1temp-W",firstbin,lastbin,opt1);
1441 TH1D * h1N = (onX) ? h2dN->ProjectionX("h1temp-N",firstbin,lastbin,opt1) : h2dN->ProjectionY("h1temp-N",firstbin,lastbin,opt1);
1442 h1W->SetDirectory(nullptr); h1N->SetDirectory(nullptr);
1443
1444
1445 // fill the bin content
1446 R__ASSERT( h1W->fN == p1->fN );
1447 R__ASSERT( h1N->fN == p1->fN );
1448 R__ASSERT( h1W->GetSumw2()->fN != 0); // h1W should always be a weighted histogram since h2dW is
1449 for (int i = 0; i < p1->fN ; ++i) {
1450 p1->fArray[i] = h1W->GetBinContent(i); // array of profile is sum of all values
1451 p1->GetSumw2()->fArray[i] = h1W->GetSumw2()->fArray[i]; // array of content square of profile is weight square of the W projected histogram
1452 p1->SetBinEntries(i, h1N->GetBinContent(i) );
1453 if (fBinSumw2.fN) p1->GetBinSumw2()->fArray[i] = h1N->GetSumw2()->fArray[i]; // sum of weight squares are stored to compute errors in h1N histogram
1454 }
1455 // delete the created histograms
1456 delete h2dW;
1457 delete h2dN;
1458 delete h1W;
1459 delete h1N;
1460
1461 // Also we need to set the entries since they have not been correctly calculated during the projection
1462 // we can only set them to the effective entries
1463 p1->SetEntries( p1->GetEffectiveEntries() );
1464
1465 return p1;
1466}
1467
1468
1469////////////////////////////////////////////////////////////////////////////////
1470/// Replace current statistics with the values in array stats
1471
1473{
1474 fTsumw = stats[0];
1475 fTsumw2 = stats[1];
1476 fTsumwx = stats[2];
1477 fTsumwx2 = stats[3];
1478 fTsumwy = stats[4];
1479 fTsumwy2 = stats[5];
1480 fTsumwxy = stats[6];
1481 fTsumwz = stats[7];
1482 fTsumwz2 = stats[8];
1483}
1484
1485////////////////////////////////////////////////////////////////////////////////
1486/// Reset contents of a Profile2D histogram.
1487
1489{
1492 fBinSumw2.Reset();
1493 TString opt = option;
1494 opt.ToUpper();
1495 if (opt.Contains("ICE") && !opt.Contains("S")) return;
1496 fTsumwz = fTsumwz2 = 0;
1497}
1498
1499
1500////////////////////////////////////////////////////////////////////////////////
1501/// Profile histogram is resized along axis such that x is in the axis range.
1502///
1503/// The new axis limits are recomputed by doubling iteratively
1504/// the current axis range until the specified value x is within the limits.
1505/// The algorithm makes a copy of the histogram, then loops on all bins
1506/// of the old histogram to fill the extended histogram.
1507/// Takes into account errors (Sumw2) if any.
1508/// The axis must be extendable before invoking this function.
1509///
1510/// Ex: h->GetXaxis()->SetCanExtend(kTRUE)
1511
1513{
1514 TProfile2D* hold = TProfileHelper::ExtendAxis(this, x, axis);
1515 if ( hold ) {
1516 fTsumwz = hold->fTsumwz;
1517 fTsumwz2 = hold->fTsumwz2;
1518 delete hold;
1519 }
1520}
1521
1522////////////////////////////////////////////////////////////////////////////////
1523/// Rebin this histogram grouping nxgroup/nygroup bins along the xaxis/yaxis together.
1524///
1525/// if newname is not blank a new profile hnew is created.
1526/// else the current histogram is modified (default)
1527/// The parameter nxgroup/nygroup indicate how many bins along the xaxis/yaxis of this
1528/// have to be merged into one bin of hnew
1529/// If the original profile has errors stored (via Sumw2), the resulting
1530/// profile has new errors correctly calculated.
1531///
1532/// examples: if hpxpy is an existing TProfile2D profile with 40 x 40 bins
1533/// ~~~ {.cpp}
1534/// hpxpy->Rebin2D(); // merges two bins along the xaxis and yaxis in one
1535/// // Carefull: previous contents of hpxpy are lost
1536/// hpxpy->Rebin2D(3,5); // merges 3 bins along the xaxis and 5 bins along the yaxis in one
1537/// // Carefull: previous contents of hpxpy are lost
1538/// hpxpy->RebinX(5); //merges five bins along the xaxis in one in hpxpy
1539/// TProfile2D *hnew = hpxpy->RebinY(5,"hnew"); // creates a new profile hnew
1540/// // merging 5 bins of hpxpy along the yaxis in one bin
1541/// ~~~
1542///
1543/// NOTE : If nxgroup/nygroup is not an exact divider of the number of bins,
1544/// along the xaxis/yaxis the top limit(s) of the rebinned profile
1545/// is changed to the upper edge of the xbin=newxbins*nxgroup resp.
1546/// ybin=newybins*nygroup and the remaining bins are added to
1547/// the overflow bin.
1548/// Statistics will be recomputed from the new bin contents.
1549
1550TProfile2D * TProfile2D::Rebin2D(Int_t nxgroup ,Int_t nygroup,const char * newname ) {
1551 //something to do?
1552 if((nxgroup != 1) || (nygroup != 1)){
1553 Int_t nxbins = fXaxis.GetNbins();
1554 Int_t nybins = fYaxis.GetNbins();
1559 if ((nxgroup <= 0) || (nxgroup > nxbins)) {
1560 Error("Rebin", "Illegal value of nxgroup=%d",nxgroup);
1561 return nullptr;
1562 }
1563 if ((nygroup <= 0) || (nygroup > nybins)) {
1564 Error("Rebin", "Illegal value of nygroup=%d",nygroup);
1565 return nullptr;
1566 }
1567
1568 Int_t newxbins = nxbins/nxgroup;
1569 Int_t newybins = nybins/nygroup;
1570
1571 //warning if bins are added to the overflow bin
1572 if(newxbins*nxgroup != nxbins) {
1573 Warning("Rebin", "nxgroup=%d should be an exact divider of nxbins=%d",nxgroup,nxbins);
1574 }
1575 if(newybins*nygroup != nybins) {
1576 Warning("Rebin", "nygroup=%d should be an exact divider of nybins=%d",nygroup,nybins);
1577 }
1578
1579 //save old bin contents in new arrays
1580 Double_t *oldBins = new Double_t[(nxbins+2)*(nybins+2)];
1581 Double_t *oldCount = new Double_t[(nxbins+2)*(nybins+2)];
1582 Double_t *oldErrors = new Double_t[(nxbins+2)*(nybins+2)];
1583 Double_t *oldBinw2 = (fBinSumw2.fN ? new Double_t[(nxbins+2)*(nybins+2)] : nullptr );
1584 Double_t *cu1 = GetW();
1585 Double_t *er1 = GetW2();
1586 Double_t *en1 = GetB();
1587 Double_t *ew1 = GetB2();
1588 for(Int_t ibin=0; ibin < (nxbins+2)*(nybins+2); ibin++){
1589 oldBins[ibin] = cu1[ibin];
1590 oldCount[ibin] = en1[ibin];
1591 oldErrors[ibin] = er1[ibin];
1592 if (ew1 && fBinSumw2.fN) oldBinw2[ibin] = ew1[ibin];
1593 }
1594
1595 // create a clone of the old profile if newname is specified
1596 TProfile2D *hnew = this;
1597 if(newname && strlen(newname) > 0) {
1598 hnew = (TProfile2D*)Clone(newname);
1599 }
1600
1601 // in case of nxgroup/nygroup not an exact divider of nxbins/nybins,
1602 // top limit is changed (see NOTE in method comment)
1603 if(newxbins*nxgroup != nxbins) {
1604 xmax = fXaxis.GetBinUpEdge(newxbins*nxgroup);
1605 hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
1606 }
1607 if(newybins*nygroup != nybins) {
1608 ymax = fYaxis.GetBinUpEdge(newybins*nygroup);
1609 hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
1610 }
1611
1612 //rebin the axis
1613 if((fXaxis.GetXbins()->GetSize() > 0) || (fYaxis.GetXbins()->GetSize() > 0)){
1614 Double_t* xbins = new Double_t[newxbins+1];
1615 Double_t* ybins = new Double_t[newybins+1];
1616 for(Int_t i=0; i < newxbins+1; i++)
1617 xbins[i] = fXaxis.GetBinLowEdge(1+i*nxgroup);
1618 for(Int_t j=0; j < newybins+1; j++)
1619 ybins[j] = fYaxis.GetBinLowEdge(1+j*nygroup);
1620 hnew->SetBins(newxbins,xbins,newybins,ybins);
1621 delete [] xbins;
1622 delete [] ybins;
1623 }
1624 //fixed bin size
1625 else{
1626 hnew->SetBins(newxbins,xmin,xmax,newybins,ymin,ymax);
1627 }
1628
1629 //merge bins
1630 Double_t *cu2 = hnew->GetW();
1631 Double_t *er2 = hnew->GetW2();
1632 Double_t *en2 = hnew->GetB();
1633 Double_t *ew2 = hnew->GetB2();
1634 Double_t binContent, binCount, binError, binSumw2;
1635 //connection between x and y bin number and linear global bin number:
1636 //global bin = xbin + (nxbins+2) * ybin
1637 Int_t oldxbin = 1;
1638 Int_t oldybin = 1;
1639 //global bin number
1640 Int_t bin;
1641 for(Int_t xbin = 1; xbin <= newxbins; xbin++){
1642 oldybin = 1;
1643 for(Int_t ybin = 1; ybin <= newybins; ybin++){
1644 binContent = 0;
1645 binCount = 0;
1646 binError = 0;
1647 binSumw2 = 0;
1648 for(Int_t i=0; i < nxgroup; i++){
1649 if(oldxbin + i > nxbins) break;
1650 for(Int_t j=0; j < nygroup; j++){
1651 if(oldybin + j > nybins) break;
1652 bin = oldxbin + i + (nxbins+2)*(oldybin+j);
1653 binContent += oldBins[bin];
1654 binCount += oldCount[bin];
1655 binError += oldErrors[bin];
1656 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1657 }
1658 }
1659 bin = xbin + (newxbins + 2)*ybin;
1660 cu2[bin] = binContent;
1661 er2[bin] = binError;
1662 en2[bin] = binCount;
1663 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1664 oldybin += nygroup;
1665 }
1666 oldxbin += nxgroup;
1667 }
1668
1669 //copy the underflow bin in x and y (0,0)
1670 cu2[0] = oldBins[0];
1671 er2[0] = oldErrors[0];
1672 en2[0] = oldCount[0];
1673 if(fBinSumw2.fN) ew2[0] = oldBinw2[0];
1674 //calculate overflow bin in x and y (newxbins+1,newybins+1)
1675 //therefore the oldxbin and oldybin from above are needed!
1676 binContent = 0;
1677 binCount = 0;
1678 binError = 0;
1679 binSumw2 = 0;
1680 for(Int_t i=oldxbin; i <= nxbins+1; i++){
1681 for(Int_t j=oldybin; j <= nybins+1; j++){
1682 //global bin number
1683 bin = i + (nxbins+2)*j;
1684 binContent += oldBins[bin];
1685 binCount += oldCount[bin];
1686 binError += oldErrors[bin];
1687 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1688 }
1689 }
1690 bin = (newxbins+2)*(newybins+2)-1;
1691 cu2[bin] = binContent;
1692 er2[bin] = binError;
1693 en2[bin] = binCount;
1694 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1695 //calculate overflow bin in x and underflow bin in y (newxbins+1,0)
1696 binContent = 0;
1697 binCount = 0;
1698 binError = 0;
1699 binSumw2 = 0;
1700 for(Int_t i=oldxbin; i <= nxbins+1; i++){
1701 bin = i;
1702 binContent += oldBins[bin];
1703 binCount += oldCount[bin];
1704 binError += oldErrors[bin];
1705 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1706 }
1707 bin = newxbins + 1;
1708 cu2[bin] = binContent;
1709 er2[bin] = binError;
1710 en2[bin] = binCount;
1711 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1712 //calculate underflow bin in x and overflow bin in y (0,newybins+1)
1713 binContent = 0;
1714 binCount = 0;
1715 binError = 0;
1716 binSumw2 = 0;
1717 for(Int_t i=oldybin; i <= nybins+1; i++){
1718 bin = i*(nxbins + 2);
1719 binContent += oldBins[bin];
1720 binCount += oldCount[bin];
1721 binError += oldErrors[bin];
1722 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1723 }
1724 bin = (newxbins + 2)*(newybins + 1);
1725 cu2[bin] = binContent;
1726 er2[bin] = binError;
1727 en2[bin] = binCount;
1728 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1729 //calculate under/overflow contents in y for the new x bins
1730 Double_t binContentuf, binCountuf, binErroruf, binSumw2uf;
1731 Double_t binContentof, binCountof, binErrorof, binSumw2of;
1732 Int_t ufbin, ofbin;
1733 Int_t oldxbin2 = 1;
1734 for(Int_t xbin = 1; xbin <= newxbins; xbin++){
1735 binContentuf = 0;
1736 binCountuf = 0;
1737 binErroruf = 0;
1738 binSumw2uf = 0;
1739 binContentof = 0;
1740 binCountof = 0;
1741 binErrorof = 0;
1742 binSumw2of = 0;
1743 for(Int_t i = 0; i < nxgroup; i++){
1744 //index of under/overflow bin for y in old binning
1745 ufbin = (oldxbin2 + i);
1746 binContentuf += oldBins[ufbin];
1747 binCountuf += oldCount[ufbin];
1748 binErroruf += oldErrors[ufbin];
1749 if(fBinSumw2.fN) binSumw2uf += oldBinw2[ufbin];
1750 for(Int_t j = oldybin; j <= nybins+1; j++)
1751 {
1752 ofbin = ufbin + j*(nxbins + 2);
1753 binContentof += oldBins[ofbin];
1754 binCountof += oldCount[ofbin];
1755 binErrorof += oldErrors[ofbin];
1756 if(fBinSumw2.fN) binSumw2of += oldBinw2[ofbin];
1757 }
1758 }
1759 //index of under/overflow bin for y in new binning
1760 ufbin = xbin;
1761 ofbin = ufbin + (newybins + 1)*(newxbins + 2);
1762 cu2[ufbin] = binContentuf;
1763 er2[ufbin] = binErroruf;
1764 en2[ufbin] = binCountuf;
1765 if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
1766 cu2[ofbin] = binContentof;
1767 er2[ofbin] = binErrorof;
1768 en2[ofbin] = binCountof;
1769 if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
1770
1771 oldxbin2 += nxgroup;
1772 }
1773 //calculate under/overflow contents in x for the new y bins
1774 Int_t oldybin2 = 1;
1775 for(Int_t ybin = 1; ybin <= newybins; ybin++){
1776 binContentuf = 0;
1777 binCountuf = 0;
1778 binErroruf = 0;
1779 binSumw2uf = 0;
1780 binContentof = 0;
1781 binCountof = 0;
1782 binErrorof = 0;
1783 binSumw2of = 0;
1784 for(Int_t i = 0; i < nygroup; i++){
1785 //index of under/overflow bin for x in old binning
1786 ufbin = (oldybin2 + i)*(nxbins+2);
1787 binContentuf += oldBins[ufbin];
1788 binCountuf += oldCount[ufbin];
1789 binErroruf += oldErrors[ufbin];
1790 if(fBinSumw2.fN) binSumw2uf += oldBinw2[ufbin];
1791 for(Int_t j = oldxbin; j <= nxbins+1; j++)
1792 {
1793 ofbin = j + ufbin;
1794 binContentof += oldBins[ofbin];
1795 binCountof += oldCount[ofbin];
1796 binErrorof += oldErrors[ofbin];
1797 if(fBinSumw2.fN) binSumw2of += oldBinw2[ofbin];
1798 }
1799 }
1800 //index of under/overflow bin for x in new binning
1801 ufbin = ybin * (newxbins + 2);
1802 ofbin = newxbins + 1 + ufbin;
1803 cu2[ufbin] = binContentuf;
1804 er2[ufbin] = binErroruf;
1805 en2[ufbin] = binCountuf;
1806 if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
1807 cu2[ofbin] = binContentof;
1808 er2[ofbin] = binErrorof;
1809 en2[ofbin] = binCountof;
1810 if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
1811
1812 oldybin2 += nygroup;
1813 }
1814
1815 delete [] oldBins;
1816 delete [] oldCount;
1817 delete [] oldErrors;
1818 if (oldBinw2) delete [] oldBinw2;
1819
1820 return hnew;
1821 }
1822 //nxgroup == nygroup == 1
1823 else{
1824 if(newname && (strlen(newname) > 0))
1825 return (TProfile2D*)Clone(newname);
1826 else
1827 return this;
1828 }
1829}
1830
1831////////////////////////////////////////////////////////////////////////////////
1832/// Rebin only the X axis.
1833/// see Rebin2D
1834
1835TProfile2D * TProfile2D::RebinX(Int_t ngroup,const char * newname ) {
1836 return Rebin2D(ngroup,1,newname);
1837}
1838
1839////////////////////////////////////////////////////////////////////////////////
1840/// Rebin only the Y axis.
1841/// see Rebin2D
1842
1843TProfile2D * TProfile2D::RebinY(Int_t ngroup,const char * newname ) {
1844 return Rebin2D(1,ngroup,newname);
1845}
1846
1847////////////////////////////////////////////////////////////////////////////////
1848/// Save primitive as a C++ statement(s) on output stream out.
1849///
1850/// Note the following restrictions in the code generated:
1851/// - variable bin size not implemented
1852/// - SetErrorOption not implemented
1853
1854void TProfile2D::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1855{
1856 char quote = '"';
1857 out <<" "<<std::endl;
1858 out <<" "<<ClassName()<<" *";
1859
1860 out << GetName() << " = new " << ClassName() << "(" << quote
1861 << GetName() << quote << "," << quote<< GetTitle() << quote
1862 << "," << GetXaxis()->GetNbins();
1863 out << "," << GetXaxis()->GetXmin()
1864 << "," << GetXaxis()->GetXmax();
1865 out << "," << GetYaxis()->GetNbins();
1866 out << "," << GetYaxis()->GetXmin()
1867 << "," << GetYaxis()->GetXmax();
1868 out << "," << fZmin
1869 << "," << fZmax;
1870 out << ");" << std::endl;
1871
1872
1873 // save bin entries
1874 Int_t bin;
1875 for (bin=0;bin<fNcells;bin++) {
1876 Double_t bi = GetBinEntries(bin);
1877 if (bi) {
1878 out<<" "<<GetName()<<"->SetBinEntries("<<bin<<","<<bi<<");"<<std::endl;
1879 }
1880 }
1881 //save bin contents
1882 for (bin=0;bin<fNcells;bin++) {
1883 Double_t bc = fArray[bin];
1884 if (bc) {
1885 out<<" "<<GetName()<<"->SetBinContent("<<bin<<","<<bc<<");"<<std::endl;
1886 }
1887 }
1888 // save bin errors
1889 if (fSumw2.fN) {
1890 for (bin=0;bin<fNcells;bin++) {
1891 Double_t be = TMath::Sqrt(fSumw2.fArray[bin]);
1892 if (be) {
1893 out<<" "<<GetName()<<"->SetBinError("<<bin<<","<<be<<");"<<std::endl;
1894 }
1895 }
1896 }
1897
1899}
1900
1901////////////////////////////////////////////////////////////////////////////////
1902/// Multiply this profile2D by a constant c1.
1903///
1904/// `this = c1*this
1905///
1906/// This function uses the services of TProfile2D::Add
1907
1909{
1911}
1912
1913////////////////////////////////////////////////////////////////////////////////
1914/// Set the number of entries in bin.
1915
1917{
1918 TProfileHelper::SetBinEntries(this, bin, w);
1919}
1920
1921////////////////////////////////////////////////////////////////////////////////
1922/// Redefine x and y axis parameters.
1923
1925{
1926 TH1::SetBins(nx,xmin, xmax,ny, ymin,ymax);
1929}
1930
1931////////////////////////////////////////////////////////////////////////////////
1932/// Redefine x and y axis parameters for variable bin sizes.
1933
1934void TProfile2D::SetBins(Int_t nx, const Double_t *xbins, Int_t ny, const Double_t *ybins)
1935{
1936 TH1::SetBins(nx,xbins,ny,ybins);
1939}
1940
1941////////////////////////////////////////////////////////////////////////////////
1942/// Set total number of bins including under/overflow.
1943/// Reallocate bin contents array
1944
1946{
1949}
1950
1951////////////////////////////////////////////////////////////////////////////////
1952/// Set the buffer size in units of 8 bytes (double).
1953
1955{
1956 if (fBuffer) {
1957 BufferEmpty();
1958 delete [] fBuffer;
1959 fBuffer = nullptr;
1960 }
1961 if (buffersize <= 0) {
1962 fBufferSize = 0;
1963 return;
1964 }
1965 if (buffersize < 100) buffersize = 100;
1966 fBufferSize = 1 + 4*buffersize;
1968 memset(fBuffer,0,sizeof(Double_t)*fBufferSize);
1969}
1970
1971////////////////////////////////////////////////////////////////////////////////
1972/// Set option to compute profile2D errors.
1973///
1974/// The computation of the bin errors is based on the parameter option:
1975/// - ' ' (Default) The bin errors are the standard error on the mean of the bin profiled values (Z),
1976/// i.e. the standard error of the bin contents.
1977/// Note that if TProfile::Approximate() is called, an approximation is used when
1978/// the spread in Z is 0 and the number of bin entries is > 0
1979/// - 's' The bin errors are the standard deviations of the Z bin values
1980/// Note that if TProfile::Approximate() is called, an approximation is used when
1981/// the spread in Z is 0 and the number of bin entries is > 0
1982/// - 'i' Errors are as in default case (standard errors of the bin contents)
1983/// The only difference is for the case when the spread in Z is zero.
1984/// In this case for N > 0 the error is 1./SQRT(12.*N)
1985/// - 'g' Errors are 1./SQRT(W) for W not equal to 0 and 0 for W = 0.
1986/// W is the sum in the bin of the weights of the profile.
1987/// This option is for combining measurements z +/- dz,
1988/// and the profile is filled with values y and weights z = 1/dz**2
1989///
1990/// See TProfile::BuildOptions for a detailed explanation of all options
1991
1993{
1995}
1996
1997////////////////////////////////////////////////////////////////////////////////
1998/// Stream an object of class TProfile2D.
1999
2001{
2003 UInt_t R__s, R__c;
2004 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2005 if (R__v > 2) {
2006 R__b.ReadClassBuffer(TProfile2D::Class(), this, R__v, R__s, R__c);
2007 return;
2008 }
2009 //====process old versions before automatic schema evolution
2010 TH2D::Streamer(R__b);
2011 fBinEntries.Streamer(R__b);
2012 Int_t errorMode;
2013 R__b >> errorMode;
2014 fErrorMode = (EErrorType)errorMode;
2015 if (R__v < 2) {
2016 Float_t zmin,zmax;
2017 R__b >> zmin; fZmin = zmin;
2018 R__b >> zmax; fZmax = zmax;
2019 } else {
2020 R__b >> fZmin;
2021 R__b >> fZmax;
2022 }
2023 R__b.CheckByteCount(R__s, R__c, TProfile2D::IsA());
2024 //====end of old versions
2025
2026 } else {
2028 }
2029}
2030
2031////////////////////////////////////////////////////////////////////////////////
2032/// Create/Delete structure to store sum of squares of weights per bin.
2033///
2034/// This is needed to compute the correct statistical quantities
2035/// of a profile filled with weights
2036///
2037/// This function is automatically called when the histogram is created
2038/// if the static function TH1::SetDefaultSumw2 has been called before.
2039/// If flag is false the structure is deleted
2040
2042{
2043 TProfileHelper::Sumw2(this, flag);
2044}
#define a(i)
Definition RSha256.hxx:99
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
float Float_t
Definition RtypesCore.h:57
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:244
Option_t Option_t option
char name[80]
Definition TGX11.cxx:110
float xmin
float ymin
float xmax
float ymax
EErrorType
Definition TProfile.h:28
Definition TProfile.h:28
Definition TProfile.h:28
Definition TProfile.h:28
Int_t gDebug
Definition TROOT.cxx:597
Array of doubles (64 bits per element).
Definition TArrayD.h:27
Double_t * fArray
Definition TArrayD.h:30
void Streamer(TBuffer &) override
Stream a TArrayD object.
Definition TArrayD.cxx:149
void Copy(TArrayD &array) const
Definition TArrayD.h:42
void Set(Int_t n) override
Set size of this array to n doubles.
Definition TArrayD.cxx:106
TArrayD()
Default TArrayD ctor.
Definition TArrayD.cxx:26
const Double_t * GetArray() const
Definition TArrayD.h:43
void Reset()
Definition TArrayD.h:47
Int_t fN
Definition TArray.h:38
Int_t GetSize() const
Definition TArray.h:47
Class to manage histogram axis.
Definition TAxis.h:31
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
Bool_t CanExtend() const
Definition TAxis.h:86
const TArrayD * GetXbins() const
Definition TAxis.h:136
Double_t GetXmax() const
Definition TAxis.h:140
@ kLabelsUp
Definition TAxis.h:74
@ kLabelsDown
Definition TAxis.h:73
@ kLabelsHori
Definition TAxis.h:71
@ kAxisRange
Definition TAxis.h:65
@ kLabelsVert
Definition TAxis.h:72
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:518
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:469
Double_t GetXmin() const
Definition TAxis.h:139
Int_t GetNbins() const
Definition TAxis.h:125
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:458
THashList * GetLabels() const
Definition TAxis.h:121
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Collection abstract base class.
Definition TCollection.h:65
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
1-Dim function class
Definition TF1.h:233
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:670
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
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:8928
Double_t * fBuffer
[fBufferSize] entry buffer
Definition TH1.h:108
virtual Double_t GetEffectiveEntries() const
Number of effective entries of the histogram.
Definition TH1.cxx:4448
@ kXaxis
Definition TH1.h:73
@ kYaxis
Definition TH1.h:74
Int_t fNcells
Number of bins(1D), cells (2D) +U/Overflows.
Definition TH1.h:89
Double_t fTsumw
Total Sum of weights.
Definition TH1.h:96
Double_t fTsumw2
Total Sum of squares of weights.
Definition TH1.h:97
Double_t fTsumwx2
Total Sum of weight*X*X.
Definition TH1.h:99
virtual Int_t GetNbinsY() const
Definition TH1.h:298
@ kIsNotW
Histogram is forced to be not weighted even when the histogram is filled with weighted.
Definition TH1.h:172
virtual Bool_t CanExtendAllAxes() const
Returns true if all axes are extendable.
Definition TH1.cxx:6627
TAxis * GetXaxis()
Definition TH1.h:324
virtual Int_t GetNbinsX() const
Definition TH1.h:297
Int_t fBufferSize
fBuffer size
Definition TH1.h:107
virtual void SetBinError(Int_t bin, Double_t error)
Set the bin Error Note that this resets the bin eror option to be of Normal Type and for the non-empt...
Definition TH1.cxx:9197
static Int_t fgBufferSize
! Default buffer size for automatic histograms
Definition TH1.h:115
TAxis * GetYaxis()
Definition TH1.h:325
virtual void SavePrimitiveHelp(std::ostream &out, const char *hname, Option_t *option="")
Helper function for the SavePrimitive functions from TH1 or classes derived from TH1,...
Definition TH1.cxx:7370
UInt_t GetAxisLabelStatus() const
Internal function used in TH1::Fill to see which axis is full alphanumeric, i.e.
Definition TH1.cxx:6666
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9213
@ kNstat
Size of statistics data (up to TProfile3D)
Definition TH1.h:184
Double_t fEntries
Number of entries.
Definition TH1.h:95
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5052
virtual TArrayD * GetSumw2()
Definition TH1.h:313
TAxis fXaxis
X axis descriptor.
Definition TH1.h:90
TArrayD fSumw2
Array of sum of squares of weights.
Definition TH1.h:104
Bool_t GetStatOverflowsBehaviour() const
Definition TH1.h:152
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2752
TAxis fYaxis
Y axis descriptor.
Definition TH1.h:91
virtual void SetBins(Int_t nx, Double_t xmin, Double_t xmax)
Redefine x axis parameters.
Definition TH1.cxx:8758
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:9011
virtual void SetEntries(Double_t n)
Definition TH1.h:391
Double_t fTsumwx
Total Sum of weight*X.
Definition TH1.h:98
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:357
void Streamer(TBuffer &) override
Stream an object of class TH2D.
Definition TH2.cxx:4270
void SetBinsLength(Int_t n=-1) override
Set total number of bins including under/overflow Reallocate bin contents array.
Definition TH2.cxx:4259
void Copy(TObject &hnew) const override
Copy.
Definition TH2.cxx:4239
TH2D()
Constructor.
Definition TH2.cxx:4122
Increment bin content by 1.
Definition TH2.h:377
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y.
Definition TH2.cxx:2476
Double_t fTsumwxy
Total Sum of weight*X*Y.
Definition TH2.h:36
Double_t fTsumwy2
Total Sum of weight*Y*Y.
Definition TH2.h:35
Int_t GetBin(Int_t binx, Int_t biny, Int_t binz=0) const override
Return Global bin number corresponding to binx,y,z.
Definition TH2.cxx:1086
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X.
Definition TH2.cxx:2436
Double_t fTsumwy
Total Sum of weight*Y.
Definition TH2.h:34
static THLimitsFinder * GetLimitsFinder()
Return pointer to the current finder.
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax)
Compute the best axis limits for the X axis.
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.h:83
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
Mother of all ROOT objects.
Definition TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:456
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:524
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:791
virtual TClass * IsA() const
Definition TObject.h:243
void ResetBit(UInt_t f)
Definition TObject.h:198
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
Long64_t Merge(TCollection *list) override
Merge all histograms in the collection in this histogram.
void PutStats(Double_t *stats) override
Replace current statistics with the values in array stats.
Int_t BufferFill(Double_t, Double_t) override
accumulate arguments in buffer.
Definition TProfile2D.h:44
Double_t fTsumwz
Total Sum of weight*Z.
Definition TProfile2D.h:39
Int_t Fill(const Double_t *v)
Definition TProfile2D.h:51
TClass * IsA() const override
Definition TProfile2D.h:153
TH2D * ProjectionXY(const char *name="_pxy", Option_t *option="e") const
Project this profile2D into a 2-D histogram along X,Y.
Bool_t Multiply(TF1 *h1, Double_t c1=1) override
Performs the operation: this = this*c1*f1.
void LabelsDeflate(Option_t *axis="X") override
Reduce the number of bins for this axis to the number of bins having a label.
Double_t GetBinError(Int_t bin) const override
Return bin error of a Profile2D histogram.
static void Approximate(Bool_t approx=kTRUE)
Static function, set the fgApproximate flag.
EErrorType fErrorMode
Option to compute errors.
Definition TProfile2D.h:35
Double_t fZmin
Lower limit in Z (if set)
Definition TProfile2D.h:36
TProfile2D * RebinX(Int_t ngroup=2, const char *newname="") override
Rebin only the X axis.
Double_t * GetW2()
Definition TProfile2D.h:66
Bool_t fScaling
! True when TProfile2D::Scale is called
Definition TProfile2D.h:38
virtual Double_t GetBinEffectiveEntries(Int_t bin)
Return bin effective entries for a weighted filled Profile histogram.
Option_t * GetErrorOption() const
Return option to compute profile2D errors.
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
TArrayD fBinSumw2
Array of sum of squares of weights per bin.
Definition TProfile2D.h:41
Double_t * GetB2()
Definition TProfile2D.h:64
static TClass * Class()
void ExtendAxis(Double_t x, TAxis *axis) override
Profile histogram is resized along axis such that x is in the axis range.
TProfile * ProfileY(const char *name="_pfy", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a profile histogram along X.
TProfile2D * RebinY(Int_t ngroup=2, const char *newname="") override
Rebin only the Y axis.
Double_t * GetW()
Definition TProfile2D.h:65
void Scale(Double_t c1=1, Option_t *option="") override
Multiply this profile2D by a constant c1.
virtual void SetBinEntries(Int_t bin, Double_t w)
Set the number of entries in bin.
void Copy(TObject &hnew) const override
Copy a Profile2D histogram to a new profile2D histogram.
TProfile * DoProfile(bool onX, const char *name, Int_t firstbin, Int_t lastbin, Option_t *option) const override
Implementation of ProfileX or ProfileY for a TProfile2D.
TProfile * ProfileX(const char *name="_pfx", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a profile histogram along X.
void LabelsOption(Option_t *option="h", Option_t *axis="X") override
Set option(s) to draw axis with labels.
TProfile2D()
Default constructor for Profile2D histograms.
void Sumw2(Bool_t flag=kTRUE) override
Create/Delete structure to store sum of squares of weights per bin.
TArrayD fBinEntries
Number of entries per bin.
Definition TProfile2D.h:34
void SetBins(const Int_t *nbins, const Double_t *range)
Definition TProfile2D.h:49
~TProfile2D() override
Default destructor for Profile2D histograms.
void Streamer(TBuffer &) override
Stream an object of class TProfile2D.
static Bool_t fgApproximate
Bin error approximation option.
Definition TProfile2D.h:42
Bool_t Divide(TF1 *h1, Double_t c1=1) override
Performs the operation: this = this/(c1*f1) .
TProfile2D * Rebin2D(Int_t nxgroup=2, Int_t nygroup=2, const char *newname="") override
Rebin this histogram grouping nxgroup/nygroup bins along the xaxis/yaxis together.
Int_t BufferEmpty(Int_t action=0) override
Fill histogram with all entries in the buffer.
void LabelsInflate(Option_t *axis="X") override
Double the number of bins for axis.
void GetStats(Double_t *stats) const override
Fill the array stats from the contents of this profile.
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Double_t fZmax
Upper limit in Z (if set)
Definition TProfile2D.h:37
void SetBinsLength(Int_t n=-1) override
Set total number of bins including under/overflow.
void BuildOptions(Double_t zmin, Double_t zmax, Option_t *option)
Set Profile2D histogram structure and options.
Bool_t Add(TF1 *h1, Double_t c1=1, Option_t *option="") override
Performs the operation: this = this + c1*f1 .
TProfile2D & operator=(const TProfile2D &profile)
void SetBuffer(Int_t buffersize, Option_t *option="") override
Set the buffer size in units of 8 bytes (double).
Double_t fTsumwz2
Total Sum of weight*Z*Z.
Definition TProfile2D.h:40
Double_t * GetB()
Definition TProfile2D.h:63
virtual void SetErrorOption(Option_t *option="")
Set option to compute profile2D errors.
Double_t GetBinContent(Int_t bin) const override
Return bin content of a Profile2D histogram.
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 *)
Profile Histogram.
Definition TProfile.h:32
virtual TArrayD * GetBinSumw2()
Definition TProfile.h:111
virtual void SetBinEntries(Int_t bin, Double_t w)
Set the number of entries in bin.
void Sumw2(Bool_t flag=kTRUE) override
Create/delete structure to store sum of squares of weights per bin.
Basic string class.
Definition TString.h:139
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
void ToUpper()
Change string to upper case.
Definition TString.cxx:1195
Bool_t IsNull() const
Definition TString.h:414
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TH1F * h1
Definition legend1.C:5
return c2
Definition legend2.C:14
Bool_t IsNaN(Double_t x)
Definition TMath.h:892
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:662
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Sort the n elements of the array a of generic templated type Element.
Definition TMathBase.h:431
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123