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