Logo ROOT  
Reference Guide
 
Loading...
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/*************************************************************************
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#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) {
233 Error("Add","Attempt to add a non-existing profile");
234 return kFALSE;
235 }
237 Error("Add","Attempt to add a non-profile2D object");
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) {
252 Error("Add","Attempt to add a non-existing profile");
253 return kFALSE;
254 }
256 Error("Add","Attempt to add a non-profile2D object");
257 return kFALSE;
258 }
259 if (!h2->InheritsFrom(TProfile2D::Class())) {
260 Error("Add","Attempt to add a non-profile2D object");
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;
664 AddBinContent(bin, u * z);
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;
705 AddBinContent(bin, u * z);
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
717 UInt_t labelBitMask = GetAxisLabelStatus();
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;
751 AddBinContent(bin, u * z);
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
761 UInt_t labelBitMask = GetAxisLabelStatus();
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
796 AddBinContent(bin, u * z);
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
808 UInt_t labelBitMask = GetAxisLabelStatus();
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.
879/// (see also comments in TProfile::GetBinError)
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]];
1163 labels->Add(obj);
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 fXaxis.Copy(*h1->GetXaxis());
1315 fYaxis.Copy(*h1->GetYaxis());
1316 Bool_t computeErrors = kFALSE;
1317 Bool_t cequalErrors = kFALSE;
1318 Bool_t binEntries = kFALSE;
1319 Bool_t binWeight = kFALSE;
1320 if (opt.Contains("b")) binEntries = kTRUE;
1321 if (opt.Contains("e")) computeErrors = kTRUE;
1322 if (opt.Contains("w")) binWeight = kTRUE;
1323 if (opt.Contains("c=e")) {cequalErrors = kTRUE; computeErrors=kFALSE;}
1324 if (computeErrors || binWeight || (binEntries && fBinSumw2.fN) ) h1->Sumw2();
1325
1326 // Fill the projected histogram
1327 Int_t bin,binx, biny;
1328 Double_t cont;
1329 for (binx =0;binx<=nx+1;binx++) {
1330 for (biny =0;biny<=ny+1;biny++) {
1331 bin = GetBin(binx,biny);
1332
1333 if (binEntries) cont = GetBinEntries(bin);
1334 else if (cequalErrors) cont = GetBinError(bin);
1335 else if (binWeight) cont = GetBinContent(bin) * GetBinEntries(bin);
1336 else cont = GetBinContent(bin); // default case
1337
1338 h1->SetBinContent(bin ,cont);
1339
1340 // if option E projected histogram errors are same as profile
1341 if (computeErrors ) h1->SetBinError(bin , GetBinError(bin) );
1342 // in case of option W bin error is deduced from bin sum of z**2 values of profile
1343 // this is correct only if the profile is unweighted
1344 if (binWeight) h1->GetSumw2()->fArray[bin] = fSumw2.fArray[bin];
1345 // in case of bin entries and profile is weighted, we need to set also the bin error
1346 if (binEntries && fBinSumw2.fN ) {
1347 R__ASSERT( h1->GetSumw2() );
1348 h1->GetSumw2()->fArray[bin] = fBinSumw2.fArray[bin];
1349 }
1350 }
1351 }
1353 return h1;
1354}
1355
1356////////////////////////////////////////////////////////////////////////////////
1357/// Project a 2-D histogram into a profile histogram along X.
1358///
1359/// The projection is made from the channels along the Y axis
1360/// ranging from firstybin to lastybin included.
1361/// The result is a 1D profile which contains the combination of all the considered bins along Y
1362/// By default, bins 1 to ny are included
1363/// When all bins are included, the number of entries in the projection
1364/// is set to the number of entries of the 2-D histogram, otherwise
1365/// the number of entries is incremented by 1 for all non empty cells.
1366///
1367/// The option can also be used to specify the projected profile error type.
1368/// Values which can be used are 's', 'i', or 'g'. See TProfile::BuildOptions for details
1369
1370TProfile *TProfile2D::ProfileX(const char *name, Int_t firstybin, Int_t lastybin, Option_t *option) const
1371{
1372 return DoProfile(true, name, firstybin, lastybin, option);
1373}
1374
1375////////////////////////////////////////////////////////////////////////////////
1376/// Project a 2-D histogram into a profile histogram along X
1377///
1378/// The projection is made from the channels along the X axis
1379/// ranging from firstybin to lastybin included.
1380/// The result is a 1D profile which contains the combination of all the considered bins along X
1381/// By default, bins 1 to ny are included
1382/// When all bins are included, the number of entries in the projection
1383/// is set to the number of entries of the 2-D histogram, otherwise
1384/// the number of entries is incremented by 1 for all non empty cells.
1385///
1386/// The option can also be used to specify the projected profile error type.
1387/// Values which can be used are 's', 'i', or 'g'. See TProfile::BuildOptions for details
1388
1389TProfile *TProfile2D::ProfileY(const char *name, Int_t firstxbin, Int_t lastxbin, Option_t *option) const
1390{
1391 return DoProfile(false, name, firstxbin, lastxbin, option);
1392}
1393
1394////////////////////////////////////////////////////////////////////////////////
1395/// Implementation of ProfileX or ProfileY for a TProfile2D.
1396///
1397/// Do correctly the combination of the bin averages when doing the projection
1398
1399TProfile * TProfile2D::DoProfile(bool onX, const char *name, Int_t firstbin, Int_t lastbin, Option_t *option) const {
1400 TString opt = option;
1401 opt.ToLower();
1402 bool originalRange = opt.Contains("o");
1403
1404 TString expectedName = ( onX ? "_pfx" : "_pfy" );
1405
1406 TString pname(name);
1407 if (pname.IsNull() || name == expectedName)
1408 pname = TString(GetName() ) + expectedName;
1409
1410 const TAxis& outAxis = ( onX ? fXaxis : fYaxis );
1411 const TArrayD *bins = outAxis.GetXbins();
1412 Int_t firstOutBin = outAxis.GetFirst();
1413 Int_t lastOutBin = outAxis.GetLast();
1414
1415 TProfile * p1 = nullptr;
1416 // case of fixed bins
1417 if (bins->fN == 0) {
1418 if (originalRange)
1419 p1 = new TProfile(pname,GetTitle(), outAxis.GetNbins(), outAxis.GetXmin(), outAxis.GetXmax(), opt );
1420 else
1421 p1 = new TProfile(pname,GetTitle(), lastOutBin-firstOutBin+1,
1422 outAxis.GetBinLowEdge(firstOutBin),outAxis.GetBinUpEdge(lastOutBin), opt);
1423 } else {
1424 // case of variable bins
1425 if (originalRange )
1426 p1 = new TProfile(pname,GetTitle(),outAxis.GetNbins(),bins->fArray,opt);
1427 else
1428 p1 = new TProfile(pname,GetTitle(),lastOutBin-firstOutBin+1,&bins->fArray[firstOutBin-1],opt);
1429
1430 }
1431
1432 if (fBinSumw2.fN) p1->Sumw2();
1433
1434 // make projection in a 2D first
1435 TH2D * h2dW = ProjectionXY("h2temp-W","W");
1436 TH2D * h2dN = ProjectionXY("h2temp-N","B");
1437
1438 h2dW->SetDirectory(nullptr); h2dN->SetDirectory(nullptr);
1439
1440
1441 TString opt1 = (originalRange) ? "o" : "";
1442 TH1D * h1W = (onX) ? h2dW->ProjectionX("h1temp-W",firstbin,lastbin,opt1) : h2dW->ProjectionY("h1temp-W",firstbin,lastbin,opt1);
1443 TH1D * h1N = (onX) ? h2dN->ProjectionX("h1temp-N",firstbin,lastbin,opt1) : h2dN->ProjectionY("h1temp-N",firstbin,lastbin,opt1);
1444 h1W->SetDirectory(nullptr); h1N->SetDirectory(nullptr);
1445
1446
1447 // fill the bin content
1448 R__ASSERT( h1W->fN == p1->fN );
1449 R__ASSERT( h1N->fN == p1->fN );
1450 R__ASSERT( h1W->GetSumw2()->fN != 0); // h1W should always be a weighted histogram since h2dW is
1451 for (int i = 0; i < p1->fN ; ++i) {
1452 p1->fArray[i] = h1W->GetBinContent(i); // array of profile is sum of all values
1453 p1->GetSumw2()->fArray[i] = h1W->GetSumw2()->fArray[i]; // array of content square of profile is weight square of the W projected histogram
1454 p1->SetBinEntries(i, h1N->GetBinContent(i) );
1455 if (fBinSumw2.fN) p1->GetBinSumw2()->fArray[i] = h1N->GetSumw2()->fArray[i]; // sum of weight squares are stored to compute errors in h1N histogram
1456 }
1457 // delete the created histograms
1458 delete h2dW;
1459 delete h2dN;
1460 delete h1W;
1461 delete h1N;
1462
1463 // Also we need to set the entries since they have not been correctly calculated during the projection
1464 // we can only set them to the effective entries
1465 p1->SetEntries( p1->GetEffectiveEntries() );
1466
1467 return p1;
1468}
1469
1470
1471////////////////////////////////////////////////////////////////////////////////
1472/// Replace current statistics with the values in array stats
1473
1475{
1476 fTsumw = stats[0];
1477 fTsumw2 = stats[1];
1478 fTsumwx = stats[2];
1479 fTsumwx2 = stats[3];
1480 fTsumwy = stats[4];
1481 fTsumwy2 = stats[5];
1482 fTsumwxy = stats[6];
1483 fTsumwz = stats[7];
1484 fTsumwz2 = stats[8];
1485}
1486
1487////////////////////////////////////////////////////////////////////////////////
1488/// Reset contents of a Profile2D histogram.
1489
1491{
1494 fBinSumw2.Reset();
1495 TString opt = option;
1496 opt.ToUpper();
1497 if (opt.Contains("ICE") && !opt.Contains("S")) return;
1498 fTsumwz = fTsumwz2 = 0;
1499}
1500
1501
1502////////////////////////////////////////////////////////////////////////////////
1503/// Profile histogram is resized along axis such that x is in the axis range.
1504///
1505/// The new axis limits are recomputed by doubling iteratively
1506/// the current axis range until the specified value x is within the limits.
1507/// The algorithm makes a copy of the histogram, then loops on all bins
1508/// of the old histogram to fill the extended histogram.
1509/// Takes into account errors (Sumw2) if any.
1510/// The axis must be extendable before invoking this function.
1511///
1512/// Ex: `h->GetXaxis()->SetCanExtend(kTRUE)`
1513
1515{
1516 TProfile2D* hold = TProfileHelper::ExtendAxis(this, x, axis);
1517 if ( hold ) {
1518 fTsumwz = hold->fTsumwz;
1519 fTsumwz2 = hold->fTsumwz2;
1520 delete hold;
1521 }
1522}
1523
1524////////////////////////////////////////////////////////////////////////////////
1525/// Rebin this histogram grouping nxgroup/nygroup bins along the xaxis/yaxis together.
1526///
1527/// if newname is not blank a new profile hnew is created.
1528/// else the current histogram is modified (default)
1529/// The parameter nxgroup/nygroup indicate how many bins along the xaxis/yaxis of this
1530/// have to be merged into one bin of hnew
1531/// If the original profile has errors stored (via Sumw2), the resulting
1532/// profile has new errors correctly calculated.
1533///
1534/// examples: if hpxpy is an existing TProfile2D profile with 40 x 40 bins
1535/// ~~~ {.cpp}
1536/// hpxpy->Rebin2D(); // merges two bins along the xaxis and yaxis in one
1537/// // Carefull: previous contents of hpxpy are lost
1538/// hpxpy->Rebin2D(3,5); // merges 3 bins along the xaxis and 5 bins along the yaxis in one
1539/// // Carefull: previous contents of hpxpy are lost
1540/// hpxpy->RebinX(5); //merges five bins along the xaxis in one in hpxpy
1541/// TProfile2D *hnew = hpxpy->RebinY(5,"hnew"); // creates a new profile hnew
1542/// // merging 5 bins of hpxpy along the yaxis in one bin
1543/// ~~~
1544///
1545/// NOTE : If nxgroup/nygroup is not an exact divider of the number of bins,
1546/// along the xaxis/yaxis the top limit(s) of the rebinned profile
1547/// is changed to the upper edge of the xbin=newxbins*nxgroup resp.
1548/// ybin=newybins*nygroup and the remaining bins are added to
1549/// the overflow bin.
1550/// Statistics will be recomputed from the new bin contents.
1551
1552TProfile2D * TProfile2D::Rebin2D(Int_t nxgroup ,Int_t nygroup,const char * newname ) {
1553 //something to do?
1554 if((nxgroup != 1) || (nygroup != 1)){
1555 Int_t nxbins = fXaxis.GetNbins();
1556 Int_t nybins = fYaxis.GetNbins();
1561 if ((nxgroup <= 0) || (nxgroup > nxbins)) {
1562 Error("Rebin", "Illegal value of nxgroup=%d",nxgroup);
1563 return nullptr;
1564 }
1565 if ((nygroup <= 0) || (nygroup > nybins)) {
1566 Error("Rebin", "Illegal value of nygroup=%d",nygroup);
1567 return nullptr;
1568 }
1569
1570 Int_t newxbins = nxbins/nxgroup;
1571 Int_t newybins = nybins/nygroup;
1572
1573 //warning if bins are added to the overflow bin
1574 if(newxbins*nxgroup != nxbins) {
1575 Warning("Rebin", "nxgroup=%d should be an exact divider of nxbins=%d",nxgroup,nxbins);
1576 }
1577 if(newybins*nygroup != nybins) {
1578 Warning("Rebin", "nygroup=%d should be an exact divider of nybins=%d",nygroup,nybins);
1579 }
1580
1581 //save old bin contents in new arrays
1582 Double_t *oldBins = new Double_t[(nxbins+2)*(nybins+2)];
1583 Double_t *oldCount = new Double_t[(nxbins+2)*(nybins+2)];
1584 Double_t *oldErrors = new Double_t[(nxbins+2)*(nybins+2)];
1585 Double_t *oldBinw2 = (fBinSumw2.fN ? new Double_t[(nxbins+2)*(nybins+2)] : nullptr );
1586 Double_t *cu1 = GetW();
1587 Double_t *er1 = GetW2();
1588 Double_t *en1 = GetB();
1589 Double_t *ew1 = GetB2();
1590 for(Int_t ibin=0; ibin < (nxbins+2)*(nybins+2); ibin++){
1591 oldBins[ibin] = cu1[ibin];
1592 oldCount[ibin] = en1[ibin];
1593 oldErrors[ibin] = er1[ibin];
1594 if (ew1 && fBinSumw2.fN) oldBinw2[ibin] = ew1[ibin];
1595 }
1596
1597 // create a clone of the old profile if newname is specified
1598 TProfile2D *hnew = this;
1599 if(newname && strlen(newname) > 0) {
1600 hnew = (TProfile2D*)Clone(newname);
1601 }
1602
1603 // in case of nxgroup/nygroup not an exact divider of nxbins/nybins,
1604 // top limit is changed (see NOTE in method comment)
1605 if(newxbins*nxgroup != nxbins) {
1606 xmax = fXaxis.GetBinUpEdge(newxbins*nxgroup);
1607 hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
1608 }
1609 if(newybins*nygroup != nybins) {
1610 ymax = fYaxis.GetBinUpEdge(newybins*nygroup);
1611 hnew->fTsumw = 0; //stats must be reset because top bins will be moved to overflow bin
1612 }
1613
1614 //rebin the axis
1615 if((fXaxis.GetXbins()->GetSize() > 0) || (fYaxis.GetXbins()->GetSize() > 0)){
1616 Double_t* xbins = new Double_t[newxbins+1];
1617 Double_t* ybins = new Double_t[newybins+1];
1618 for(Int_t i=0; i < newxbins+1; i++)
1619 xbins[i] = fXaxis.GetBinLowEdge(1+i*nxgroup);
1620 for(Int_t j=0; j < newybins+1; j++)
1621 ybins[j] = fYaxis.GetBinLowEdge(1+j*nygroup);
1622 hnew->SetBins(newxbins,xbins,newybins,ybins);
1623 delete [] xbins;
1624 delete [] ybins;
1625 }
1626 //fixed bin size
1627 else{
1628 hnew->SetBins(newxbins,xmin,xmax,newybins,ymin,ymax);
1629 }
1630
1631 //merge bins
1632 Double_t *cu2 = hnew->GetW();
1633 Double_t *er2 = hnew->GetW2();
1634 Double_t *en2 = hnew->GetB();
1635 Double_t *ew2 = hnew->GetB2();
1636 Double_t binContent, binCount, binError, binSumw2;
1637 //connection between x and y bin number and linear global bin number:
1638 //global bin = xbin + (nxbins+2) * ybin
1639 Int_t oldxbin = 1;
1640 Int_t oldybin = 1;
1641 //global bin number
1642 Int_t bin;
1643 for(Int_t xbin = 1; xbin <= newxbins; xbin++){
1644 oldybin = 1;
1645 for(Int_t ybin = 1; ybin <= newybins; ybin++){
1646 binContent = 0;
1647 binCount = 0;
1648 binError = 0;
1649 binSumw2 = 0;
1650 for(Int_t i=0; i < nxgroup; i++){
1651 if(oldxbin + i > nxbins) break;
1652 for(Int_t j=0; j < nygroup; j++){
1653 if(oldybin + j > nybins) break;
1654 bin = oldxbin + i + (nxbins+2)*(oldybin+j);
1655 binContent += oldBins[bin];
1656 binCount += oldCount[bin];
1657 binError += oldErrors[bin];
1658 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1659 }
1660 }
1661 bin = xbin + (newxbins + 2)*ybin;
1662 cu2[bin] = binContent;
1663 er2[bin] = binError;
1664 en2[bin] = binCount;
1665 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1666 oldybin += nygroup;
1667 }
1668 oldxbin += nxgroup;
1669 }
1670
1671 //copy the underflow bin in x and y (0,0)
1672 cu2[0] = oldBins[0];
1673 er2[0] = oldErrors[0];
1674 en2[0] = oldCount[0];
1675 if(fBinSumw2.fN) ew2[0] = oldBinw2[0];
1676 //calculate overflow bin in x and y (newxbins+1,newybins+1)
1677 //therefore the oldxbin and oldybin from above are needed!
1678 binContent = 0;
1679 binCount = 0;
1680 binError = 0;
1681 binSumw2 = 0;
1682 for(Int_t i=oldxbin; i <= nxbins+1; i++){
1683 for(Int_t j=oldybin; j <= nybins+1; j++){
1684 //global bin number
1685 bin = i + (nxbins+2)*j;
1686 binContent += oldBins[bin];
1687 binCount += oldCount[bin];
1688 binError += oldErrors[bin];
1689 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1690 }
1691 }
1692 bin = (newxbins+2)*(newybins+2)-1;
1693 cu2[bin] = binContent;
1694 er2[bin] = binError;
1695 en2[bin] = binCount;
1696 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1697 //calculate overflow bin in x and underflow bin in y (newxbins+1,0)
1698 binContent = 0;
1699 binCount = 0;
1700 binError = 0;
1701 binSumw2 = 0;
1702 for(Int_t i=oldxbin; i <= nxbins+1; i++){
1703 bin = i;
1704 binContent += oldBins[bin];
1705 binCount += oldCount[bin];
1706 binError += oldErrors[bin];
1707 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1708 }
1709 bin = newxbins + 1;
1710 cu2[bin] = binContent;
1711 er2[bin] = binError;
1712 en2[bin] = binCount;
1713 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1714 //calculate underflow bin in x and overflow bin in y (0,newybins+1)
1715 binContent = 0;
1716 binCount = 0;
1717 binError = 0;
1718 binSumw2 = 0;
1719 for(Int_t i=oldybin; i <= nybins+1; i++){
1720 bin = i*(nxbins + 2);
1721 binContent += oldBins[bin];
1722 binCount += oldCount[bin];
1723 binError += oldErrors[bin];
1724 if(fBinSumw2.fN) binSumw2 += oldBinw2[bin];
1725 }
1726 bin = (newxbins + 2)*(newybins + 1);
1727 cu2[bin] = binContent;
1728 er2[bin] = binError;
1729 en2[bin] = binCount;
1730 if(fBinSumw2.fN) ew2[bin] = binSumw2;
1731 //calculate under/overflow contents in y for the new x bins
1732 Double_t binContentuf, binCountuf, binErroruf, binSumw2uf;
1733 Double_t binContentof, binCountof, binErrorof, binSumw2of;
1734 Int_t ufbin, ofbin;
1735 Int_t oldxbin2 = 1;
1736 for(Int_t xbin = 1; xbin <= newxbins; xbin++){
1737 binContentuf = 0;
1738 binCountuf = 0;
1739 binErroruf = 0;
1740 binSumw2uf = 0;
1741 binContentof = 0;
1742 binCountof = 0;
1743 binErrorof = 0;
1744 binSumw2of = 0;
1745 for(Int_t i = 0; i < nxgroup; i++){
1746 //index of under/overflow bin for y in old binning
1747 ufbin = (oldxbin2 + i);
1748 binContentuf += oldBins[ufbin];
1749 binCountuf += oldCount[ufbin];
1750 binErroruf += oldErrors[ufbin];
1751 if(fBinSumw2.fN) binSumw2uf += oldBinw2[ufbin];
1752 for(Int_t j = oldybin; j <= nybins+1; j++)
1753 {
1754 ofbin = ufbin + j*(nxbins + 2);
1755 binContentof += oldBins[ofbin];
1756 binCountof += oldCount[ofbin];
1757 binErrorof += oldErrors[ofbin];
1758 if(fBinSumw2.fN) binSumw2of += oldBinw2[ofbin];
1759 }
1760 }
1761 //index of under/overflow bin for y in new binning
1762 ufbin = xbin;
1763 ofbin = ufbin + (newybins + 1)*(newxbins + 2);
1764 cu2[ufbin] = binContentuf;
1765 er2[ufbin] = binErroruf;
1766 en2[ufbin] = binCountuf;
1767 if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
1768 cu2[ofbin] = binContentof;
1769 er2[ofbin] = binErrorof;
1770 en2[ofbin] = binCountof;
1771 if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
1772
1773 oldxbin2 += nxgroup;
1774 }
1775 //calculate under/overflow contents in x for the new y bins
1776 Int_t oldybin2 = 1;
1777 for(Int_t ybin = 1; ybin <= newybins; ybin++){
1778 binContentuf = 0;
1779 binCountuf = 0;
1780 binErroruf = 0;
1781 binSumw2uf = 0;
1782 binContentof = 0;
1783 binCountof = 0;
1784 binErrorof = 0;
1785 binSumw2of = 0;
1786 for(Int_t i = 0; i < nygroup; i++){
1787 //index of under/overflow bin for x in old binning
1788 ufbin = (oldybin2 + i)*(nxbins+2);
1789 binContentuf += oldBins[ufbin];
1790 binCountuf += oldCount[ufbin];
1791 binErroruf += oldErrors[ufbin];
1792 if(fBinSumw2.fN) binSumw2uf += oldBinw2[ufbin];
1793 for(Int_t j = oldxbin; j <= nxbins+1; j++)
1794 {
1795 ofbin = j + ufbin;
1796 binContentof += oldBins[ofbin];
1797 binCountof += oldCount[ofbin];
1798 binErrorof += oldErrors[ofbin];
1799 if(fBinSumw2.fN) binSumw2of += oldBinw2[ofbin];
1800 }
1801 }
1802 //index of under/overflow bin for x in new binning
1803 ufbin = ybin * (newxbins + 2);
1804 ofbin = newxbins + 1 + ufbin;
1805 cu2[ufbin] = binContentuf;
1806 er2[ufbin] = binErroruf;
1807 en2[ufbin] = binCountuf;
1808 if(fBinSumw2.fN) ew2[ufbin] = binSumw2uf;
1809 cu2[ofbin] = binContentof;
1810 er2[ofbin] = binErrorof;
1811 en2[ofbin] = binCountof;
1812 if(fBinSumw2.fN) ew2[ofbin] = binSumw2of;
1813
1814 oldybin2 += nygroup;
1815 }
1816
1817 delete [] oldBins;
1818 delete [] oldCount;
1819 delete [] oldErrors;
1820 if (oldBinw2) delete [] oldBinw2;
1821
1822 return hnew;
1823 }
1824 //nxgroup == nygroup == 1
1825 else{
1826 if(newname && (strlen(newname) > 0))
1827 return (TProfile2D*)Clone(newname);
1828 else
1829 return this;
1830 }
1831}
1832
1833////////////////////////////////////////////////////////////////////////////////
1834/// Rebin only the X axis.
1835/// see Rebin2D
1836
1837TProfile2D * TProfile2D::RebinX(Int_t ngroup,const char * newname ) {
1838 return Rebin2D(ngroup,1,newname);
1839}
1840
1841////////////////////////////////////////////////////////////////////////////////
1842/// Rebin only the Y axis.
1843/// see Rebin2D
1844
1845TProfile2D * TProfile2D::RebinY(Int_t ngroup,const char * newname ) {
1846 return Rebin2D(1,ngroup,newname);
1847}
1848
1849////////////////////////////////////////////////////////////////////////////////
1850/// Save primitive as a C++ statement(s) on output stream out.
1851///
1852/// Note the following restrictions in the code generated:
1853/// - variable bin size not implemented
1854/// - SetErrorOption not implemented
1855
1856void TProfile2D::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1857{
1858 char quote = '"';
1859 out <<" "<<std::endl;
1860 out <<" "<<ClassName()<<" *";
1861
1862 out << GetName() << " = new " << ClassName() << "(" << quote
1863 << GetName() << quote << "," << quote<< GetTitle() << quote
1864 << "," << GetXaxis()->GetNbins();
1865 out << "," << GetXaxis()->GetXmin()
1866 << "," << GetXaxis()->GetXmax();
1867 out << "," << GetYaxis()->GetNbins();
1868 out << "," << GetYaxis()->GetXmin()
1869 << "," << GetYaxis()->GetXmax();
1870 out << "," << fZmin
1871 << "," << fZmax;
1872 out << ");" << std::endl;
1873
1874
1875 // save bin entries
1876 Int_t bin;
1877 for (bin=0;bin<fNcells;bin++) {
1878 Double_t bi = GetBinEntries(bin);
1879 if (bi) {
1880 out<<" "<<GetName()<<"->SetBinEntries("<<bin<<","<<bi<<");"<<std::endl;
1881 }
1882 }
1883 //save bin contents
1884 for (bin=0;bin<fNcells;bin++) {
1885 Double_t bc = fArray[bin];
1886 if (bc) {
1887 out<<" "<<GetName()<<"->SetBinContent("<<bin<<","<<bc<<");"<<std::endl;
1888 }
1889 }
1890 // save bin errors
1891 if (fSumw2.fN) {
1892 for (bin=0;bin<fNcells;bin++) {
1893 Double_t be = TMath::Sqrt(fSumw2.fArray[bin]);
1894 if (be) {
1895 out<<" "<<GetName()<<"->SetBinError("<<bin<<","<<be<<");"<<std::endl;
1896 }
1897 }
1898 }
1899
1901}
1902
1903////////////////////////////////////////////////////////////////////////////////
1904/// Multiply this profile2D by a constant c1.
1905///
1906/// `this = c1*this
1907///
1908/// This function uses the services of TProfile2D::Add
1909
1911{
1913}
1914
1915////////////////////////////////////////////////////////////////////////////////
1916/// Set the number of entries in bin.
1917
1919{
1920 TProfileHelper::SetBinEntries(this, bin, w);
1921}
1922
1923////////////////////////////////////////////////////////////////////////////////
1924/// Redefine x and y axis parameters.
1925
1927{
1928 TH1::SetBins(nx,xmin, xmax,ny, ymin,ymax);
1931}
1932
1933////////////////////////////////////////////////////////////////////////////////
1934/// Redefine x and y axis parameters for variable bin sizes.
1935
1936void TProfile2D::SetBins(Int_t nx, const Double_t *xbins, Int_t ny, const Double_t *ybins)
1937{
1938 TH1::SetBins(nx,xbins,ny,ybins);
1941}
1942
1943////////////////////////////////////////////////////////////////////////////////
1944/// Set total number of bins including under/overflow.
1945/// Reallocate bin contents array
1946
1948{
1951}
1952
1953////////////////////////////////////////////////////////////////////////////////
1954/// Set the buffer size in units of 8 bytes (double).
1955
1957{
1958 if (fBuffer) {
1959 BufferEmpty();
1960 delete [] fBuffer;
1961 fBuffer = nullptr;
1962 }
1963 if (buffersize <= 0) {
1964 fBufferSize = 0;
1965 return;
1966 }
1967 if (buffersize < 100) buffersize = 100;
1968 fBufferSize = 1 + 4*buffersize;
1970 memset(fBuffer,0,sizeof(Double_t)*fBufferSize);
1971}
1972
1973////////////////////////////////////////////////////////////////////////////////
1974/// Set option to compute profile2D errors.
1975///
1976/// The computation of the bin errors is based on the parameter option:
1977/// - ' ' (Default) The bin errors are the standard error on the mean of the bin profiled values (Z),
1978/// i.e. the standard error of the bin contents.
1979/// Note that if TProfile::Approximate() is called, an approximation is used when
1980/// the spread in Z is 0 and the number of bin entries is > 0
1981/// - 's' The bin errors are the standard deviations of the Z bin values
1982/// Note that if TProfile::Approximate() is called, an approximation is used when
1983/// the spread in Z is 0 and the number of bin entries is > 0
1984/// - 'i' Errors are as in default case (standard errors of the bin contents)
1985/// The only difference is for the case when the spread in Z is zero.
1986/// In this case for N > 0 the error is 1./SQRT(12.*N)
1987/// - 'g' Errors are 1./SQRT(W) for W not equal to 0 and 0 for W = 0.
1988/// W is the sum in the bin of the weights of the profile.
1989/// This option is for combining measurements z +/- dz,
1990/// and the profile is filled with values y and weights z = 1/dz**2
1991///
1992/// See TProfile::BuildOptions for a detailed explanation of all options
1993
1995{
1997}
1998
1999////////////////////////////////////////////////////////////////////////////////
2000/// Stream an object of class TProfile2D.
2001
2003{
2004 if (R__b.IsReading()) {
2005 UInt_t R__s, R__c;
2006 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2007 if (R__v > 2) {
2008 R__b.ReadClassBuffer(TProfile2D::Class(), this, R__v, R__s, R__c);
2009 return;
2010 }
2011 //====process old versions before automatic schema evolution
2012 TH2D::Streamer(R__b);
2013 fBinEntries.Streamer(R__b);
2014 Int_t errorMode;
2015 R__b >> errorMode;
2016 fErrorMode = (EErrorType)errorMode;
2017 if (R__v < 2) {
2018 Float_t zmin,zmax;
2019 R__b >> zmin; fZmin = zmin;
2020 R__b >> zmax; fZmax = zmax;
2021 } else {
2022 R__b >> fZmin;
2023 R__b >> fZmax;
2024 }
2025 R__b.CheckByteCount(R__s, R__c, TProfile2D::IsA());
2026 //====end of old versions
2027
2028 } else {
2030 }
2031}
2032
2033////////////////////////////////////////////////////////////////////////////////
2034/// Create/Delete structure to store sum of squares of weights per bin.
2035///
2036/// This is needed to compute the correct statistical quantities
2037/// of a profile filled with weights
2038///
2039/// This function is automatically called when the histogram is created
2040/// if the static function TH1::SetDefaultSumw2 has been called before.
2041/// If flag is false the structure is deleted
2042
2044{
2045 TProfileHelper::Sumw2(this, flag);
2046}
#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:94
long long Long64_t
Definition RtypesCore.h:69
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:382
#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
@ kERRORSPREAD
Definition TProfile.h:28
@ kERRORSPREADG
Definition TProfile.h:28
@ kERRORSPREADI
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
void Copy(TObject &axis) const override
Copy axis structure to another axis.
Definition TAxis.cxx:216
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
Bool_t IsReading() const
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:8958
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:6657
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:9227
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:7400
UInt_t GetAxisLabelStatus() const
Internal function used in TH1::Fill to see which axis is full alphanumeric, i.e.
Definition TH1.cxx:6696
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:9243
@ 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:5082
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:8788
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:9041
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:4268
void SetBinsLength(Int_t n=-1) override
Set total number of bins including under/overflow Reallocate bin contents array.
Definition TH2.cxx:4257
void Copy(TObject &hnew) const override
Copy.
Definition TH2.cxx:4237
TH2D()
Constructor.
Definition TH2.cxx:4120
void AddBinContent(Int_t bin) override
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.
void Add(TObject *obj) override
Definition TList.h:81
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:474
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:798
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:542
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:809
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