Logo ROOT  
Reference Guide
TH3.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: Rene Brun 27/10/95
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 "TROOT.h"
13#include "TBuffer.h"
14#include "TClass.h"
15#include "THashList.h"
16#include "TH3.h"
17#include "TProfile2D.h"
18#include "TH2.h"
19#include "TF3.h"
20#include "TVirtualPad.h"
21#include "TVirtualHistPainter.h"
22#include "THLimitsFinder.h"
23#include "TRandom.h"
24#include "TError.h"
25#include "TMath.h"
26#include "TObjString.h"
27
29
30/** \addtogroup Hist
31@{
32\class TH3C
33\brief 3-D histogram with a byte per channel (see TH1 documentation)
34\class TH3S
35\brief 3-D histogram with a short per channel (see TH1 documentation)
36\class TH3I
37\brief 3-D histogram with an int per channel (see TH1 documentation)}
38\class TH3F
39\brief 3-D histogram with a float per channel (see TH1 documentation)}
40\class TH3D
41\brief 3-D histogram with a double per channel (see TH1 documentation)}
42@}
43*/
44
45/** \class TH3
46 \ingroup Hist
47The 3-D histogram classes derived from the 1-D histogram classes.
48All operations are supported (fill, fit).
49Drawing is currently restricted to one single option.
50A cloud of points is drawn. The number of points is proportional to
51cell content.
52
53- TH3C a 3-D histogram with one byte per cell (char)
54- TH3S a 3-D histogram with two bytes per cell (short integer)
55- TH3I a 3-D histogram with four bytes per cell (32 bits integer)
56- TH3F a 3-D histogram with four bytes per cell (float)
57- TH3D a 3-D histogram with eight bytes per cell (double)
58*/
59
60
61////////////////////////////////////////////////////////////////////////////////
62/// Default constructor.
63
65{
66 fDimension = 3;
69}
70
71
72////////////////////////////////////////////////////////////////////////////////
73/// Normal constructor for fix bin size 3-D histograms.
74
75TH3::TH3(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
76 ,Int_t nbinsy,Double_t ylow,Double_t yup
77 ,Int_t nbinsz,Double_t zlow,Double_t zup)
78 :TH1(name,title,nbinsx,xlow,xup),
79 TAtt3D()
81 fDimension = 3;
82 if (nbinsy <= 0) {
83 Warning("TH3","nbinsy is <=0 - set to nbinsy = 1");
84 nbinsy = 1;
85 }
86 if (nbinsz <= 0) {
87 Warning("TH3","nbinsz is <=0 - set to nbinsz = 1");
88 nbinsz = 1;
89 }
90 fYaxis.Set(nbinsy,ylow,yup);
91 fZaxis.Set(nbinsz,zlow,zup);
92 fNcells = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
93 fTsumwy = fTsumwy2 = fTsumwxy = 0;
94 fTsumwz = fTsumwz2 = fTsumwxz = fTsumwyz = 0;
95}
96
97
98////////////////////////////////////////////////////////////////////////////////
99/// Normal constructor for variable bin size 3-D histograms.
100
101TH3::TH3(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
102 ,Int_t nbinsy,const Float_t *ybins
103 ,Int_t nbinsz,const Float_t *zbins)
104 :TH1(name,title,nbinsx,xbins),
105 TAtt3D()
106{
107 fDimension = 3;
108 if (nbinsy <= 0) {Warning("TH3","nbinsy is <=0 - set to nbinsy = 1"); nbinsy = 1; }
109 if (nbinsz <= 0) nbinsz = 1;
110 if (ybins) fYaxis.Set(nbinsy,ybins);
111 else fYaxis.Set(nbinsy,0,1);
112 if (zbins) fZaxis.Set(nbinsz,zbins);
113 else fZaxis.Set(nbinsz,0,1);
114 fNcells = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
115 fTsumwy = fTsumwy2 = fTsumwxy = 0;
117}
118
119
120////////////////////////////////////////////////////////////////////////////////
121/// Normal constructor for variable bin size 3-D histograms.
122
123TH3::TH3(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
124 ,Int_t nbinsy,const Double_t *ybins
125 ,Int_t nbinsz,const Double_t *zbins)
126 :TH1(name,title,nbinsx,xbins),
127 TAtt3D()
128{
129 fDimension = 3;
130 if (nbinsy <= 0) {Warning("TH3","nbinsy is <=0 - set to nbinsy = 1"); nbinsy = 1; }
131 if (nbinsz <= 0) nbinsz = 1;
132 if (ybins) fYaxis.Set(nbinsy,ybins);
133 else fYaxis.Set(nbinsy,0,1);
134 if (zbins) fZaxis.Set(nbinsz,zbins);
135 else fZaxis.Set(nbinsz,0,1);
136 fNcells = (nbinsx+2)*(nbinsy+2)*(nbinsz+2);
137 fTsumwy = fTsumwy2 = fTsumwxy = 0;
139}
140
141
142////////////////////////////////////////////////////////////////////////////////
143/// Copy constructor.
144/// The list of functions is not copied. (Use Clone if needed)
145
146TH3::TH3(const TH3 &h) : TH1(), TAtt3D()
147{
148 ((TH3&)h).Copy(*this);
149}
150
151
152////////////////////////////////////////////////////////////////////////////////
153/// Destructor.
154
156{
157}
158
159
160////////////////////////////////////////////////////////////////////////////////
161/// Copy.
162
163void TH3::Copy(TObject &obj) const
164{
165 TH1::Copy(obj);
166 ((TH3&)obj).fTsumwy = fTsumwy;
167 ((TH3&)obj).fTsumwy2 = fTsumwy2;
168 ((TH3&)obj).fTsumwxy = fTsumwxy;
169 ((TH3&)obj).fTsumwz = fTsumwz;
170 ((TH3&)obj).fTsumwz2 = fTsumwz2;
171 ((TH3&)obj).fTsumwxz = fTsumwxz;
172 ((TH3&)obj).fTsumwyz = fTsumwyz;
173}
174
175
176////////////////////////////////////////////////////////////////////////////////
177/// Fill histogram with all entries in the buffer.
178/// action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
179/// action = 0 histogram is filled from the buffer
180/// action = 1 histogram is filled and buffer is deleted
181/// The buffer is automatically deleted when the number of entries
182/// in the buffer is greater than the number of entries in the histogram
183
185{
186 // do we need to compute the bin size?
187 if (!fBuffer) return 0;
188 Int_t nbentries = (Int_t)fBuffer[0];
189 if (!nbentries) return 0;
190 Double_t *buffer = fBuffer;
191 if (nbentries < 0) {
192 if (action == 0) return 0;
193 nbentries = -nbentries;
194 fBuffer=0;
195 Reset("ICES");
196 fBuffer = buffer;
197 }
198 if (CanExtendAllAxes() || fXaxis.GetXmax() <= fXaxis.GetXmin() ||
199 fYaxis.GetXmax() <= fYaxis.GetXmin() ||
200 fZaxis.GetXmax() <= fZaxis.GetXmin()) {
201 //find min, max of entries in buffer
202 Double_t xmin = fBuffer[2];
204 Double_t ymin = fBuffer[3];
206 Double_t zmin = fBuffer[4];
207 Double_t zmax = zmin;
208 for (Int_t i=1;i<nbentries;i++) {
209 Double_t x = fBuffer[4*i+2];
210 if (x < xmin) xmin = x;
211 if (x > xmax) xmax = x;
212 Double_t y = fBuffer[4*i+3];
213 if (y < ymin) ymin = y;
214 if (y > ymax) ymax = y;
215 Double_t z = fBuffer[4*i+4];
216 if (z < zmin) zmin = z;
217 if (z > zmax) zmax = z;
218 }
221 } else {
222 fBuffer = 0;
223 Int_t keep = fBufferSize; fBufferSize = 0;
228 if (zmin < fZaxis.GetXmin()) ExtendAxis(zmin,&fZaxis);
229 if (zmax >= fZaxis.GetXmax()) ExtendAxis(zmax,&fZaxis);
230 fBuffer = buffer;
231 fBufferSize = keep;
232 }
233 }
234 fBuffer = 0;
235
236 for (Int_t i=0;i<nbentries;i++) {
237 Fill(buffer[4*i+2],buffer[4*i+3],buffer[4*i+4],buffer[4*i+1]);
238 }
239 fBuffer = buffer;
240
241 if (action > 0) { delete [] fBuffer; fBuffer = 0; fBufferSize = 0;}
242 else {
243 if (nbentries == (Int_t)fEntries) fBuffer[0] = -nbentries;
244 else fBuffer[0] = 0;
245 }
246 return nbentries;
247}
248
249
250////////////////////////////////////////////////////////////////////////////////
251/// accumulate arguments in buffer. When buffer is full, empty the buffer
252/// fBuffer[0] = number of entries in buffer
253/// fBuffer[1] = w of first entry
254/// fBuffer[2] = x of first entry
255/// fBuffer[3] = y of first entry
256/// fBuffer[4] = z of first entry
257
259{
260 if (!fBuffer) return -3;
261 Int_t nbentries = (Int_t)fBuffer[0];
262 if (nbentries < 0) {
263 nbentries = -nbentries;
264 fBuffer[0] = nbentries;
265 if (fEntries > 0) {
266 Double_t *buffer = fBuffer; fBuffer=0;
267 Reset("ICES");
268 fBuffer = buffer;
269 }
270 }
271 if (4*nbentries+4 >= fBufferSize) {
272 BufferEmpty(1);
273 return Fill(x,y,z,w);
274 }
275 fBuffer[4*nbentries+1] = w;
276 fBuffer[4*nbentries+2] = x;
277 fBuffer[4*nbentries+3] = y;
278 fBuffer[4*nbentries+4] = z;
279 fBuffer[0] += 1;
280 return -3;
281}
282
283
284////////////////////////////////////////////////////////////////////////////////
285/// Invalid Fill method
286
288{
289 Error("Fill", "Invalid signature - do nothing");
290 return -1;
291}
292
293
294////////////////////////////////////////////////////////////////////////////////
295/// Increment cell defined by x,y,z by 1 .
296///
297/// The function returns the corresponding global bin number which has its content
298/// incremented by 1
299
301{
302 if (fBuffer) return BufferFill(x,y,z,1);
303
304 Int_t binx, biny, binz, bin;
305 fEntries++;
306 binx = fXaxis.FindBin(x);
307 biny = fYaxis.FindBin(y);
308 binz = fZaxis.FindBin(z);
309 if (binx <0 || biny <0 || binz<0) return -1;
310 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
311 if (fSumw2.fN) ++fSumw2.fArray[bin];
312 AddBinContent(bin);
313 if (binx == 0 || binx > fXaxis.GetNbins()) {
314 if (!GetStatOverflowsBehaviour()) return -1;
315 }
316
317 if (biny == 0 || biny > fYaxis.GetNbins()) {
318 if (!GetStatOverflowsBehaviour()) return -1;
319 }
320 if (binz == 0 || binz > fZaxis.GetNbins()) {
321 if (!GetStatOverflowsBehaviour()) return -1;
322 }
323 ++fTsumw;
324 ++fTsumw2;
325 fTsumwx += x;
326 fTsumwx2 += x*x;
327 fTsumwy += y;
328 fTsumwy2 += y*y;
329 fTsumwxy += x*y;
330 fTsumwz += z;
331 fTsumwz2 += z*z;
332 fTsumwxz += x*z;
333 fTsumwyz += y*z;
334 return bin;
335}
336
337
338////////////////////////////////////////////////////////////////////////////////
339/// Increment cell defined by x,y,z by a weight w.
340///
341/// If the weight is not equal to 1, the storage of the sum of squares of
342/// weights is automatically triggered and the sum of the squares of weights is incremented
343/// by w^2 in the cell corresponding to x,y,z.
344///
345/// The function returns the corresponding global bin number which has its content
346/// incremented by w
347
349{
350 if (fBuffer) return BufferFill(x,y,z,w);
351
352 Int_t binx, biny, binz, bin;
353 fEntries++;
354 binx = fXaxis.FindBin(x);
355 biny = fYaxis.FindBin(y);
356 binz = fZaxis.FindBin(z);
357 if (binx <0 || biny <0 || binz<0) return -1;
358 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
359 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
360 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
361 AddBinContent(bin,w);
362 if (binx == 0 || binx > fXaxis.GetNbins()) {
363 if (!GetStatOverflowsBehaviour()) return -1;
364 }
365 if (biny == 0 || biny > fYaxis.GetNbins()) {
366 if (!GetStatOverflowsBehaviour()) return -1;
367 }
368 if (binz == 0 || binz > fZaxis.GetNbins()) {
369 if (!GetStatOverflowsBehaviour()) return -1;
370 }
371 fTsumw += w;
372 fTsumw2 += w*w;
373 fTsumwx += w*x;
374 fTsumwx2 += w*x*x;
375 fTsumwy += w*y;
376 fTsumwy2 += w*y*y;
377 fTsumwxy += w*x*y;
378 fTsumwz += w*z;
379 fTsumwz2 += w*z*z;
380 fTsumwxz += w*x*z;
381 fTsumwyz += w*y*z;
382 return bin;
383}
384
385
386////////////////////////////////////////////////////////////////////////////////
387/// Increment cell defined by namex,namey,namez by a weight w
388///
389/// If the weight is not equal to 1, the storage of the sum of squares of
390/// weights is automatically triggered and the sum of the squares of weights is incremented
391/// by w^2 in the corresponding cell.
392/// The function returns the corresponding global bin number which has its content
393/// incremented by w
394
395Int_t TH3::Fill(const char *namex, const char *namey, const char *namez, Double_t w)
396{
397 Int_t binx, biny, binz, bin;
398 fEntries++;
399 binx = fXaxis.FindBin(namex);
400 biny = fYaxis.FindBin(namey);
401 binz = fZaxis.FindBin(namez);
402 if (binx <0 || biny <0 || binz<0) return -1;
403 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
404 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
405 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
406 AddBinContent(bin,w);
407 if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
408 if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
409 if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
412 Double_t z = fZaxis.GetBinCenter(binz);
413 Double_t v = w;
414 fTsumw += v;
415 fTsumw2 += v*v;
416 fTsumwx += v*x;
417 fTsumwx2 += v*x*x;
418 fTsumwy += v*y;
419 fTsumwy2 += v*y*y;
420 fTsumwxy += v*x*y;
421 fTsumwz += v*z;
422 fTsumwz2 += v*z*z;
423 fTsumwxz += v*x*z;
424 fTsumwyz += v*y*z;
425 return bin;
426}
427
428
429////////////////////////////////////////////////////////////////////////////////
430/// Increment cell defined by namex,y,namez by a weight w
431///
432/// If the weight is not equal to 1, the storage of the sum of squares of
433/// weights is automatically triggered and the sum of the squares of weights is incremented
434/// by w^2 in the corresponding cell.
435/// The function returns the corresponding global bin number which has its content
436/// incremented by w
437
438Int_t TH3::Fill(const char *namex, Double_t y, const char *namez, Double_t w)
439{
440 Int_t binx, biny, binz, bin;
441 fEntries++;
442 binx = fXaxis.FindBin(namex);
443 biny = fYaxis.FindBin(y);
444 binz = fZaxis.FindBin(namez);
445 if (binx <0 || biny <0 || binz<0) return -1;
446 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
447 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
448 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
449 AddBinContent(bin,w);
450 if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
451 if (biny == 0 || biny > fYaxis.GetNbins()) {
452 if (!GetStatOverflowsBehaviour()) return -1;
453 }
454 if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
456 Double_t z = fZaxis.GetBinCenter(binz);
457 Double_t v = w;
458 fTsumw += v;
459 fTsumw2 += v*v;
460 fTsumwx += v*x;
461 fTsumwx2 += v*x*x;
462 fTsumwy += v*y;
463 fTsumwy2 += v*y*y;
464 fTsumwxy += v*x*y;
465 fTsumwz += v*z;
466 fTsumwz2 += v*z*z;
467 fTsumwxz += v*x*z;
468 fTsumwyz += v*y*z;
469 return bin;
470}
471
472
473////////////////////////////////////////////////////////////////////////////////
474/// Increment cell defined by namex,namey,z by a weight w
475///
476/// If the weight is not equal to 1, the storage of the sum of squares of
477/// weights is automatically triggered and the sum of the squares of weights is incremented
478/// by w^2 in the corresponding cell.
479/// The function returns the corresponding global bin number which has its content
480/// incremented by w
481
482Int_t TH3::Fill(const char *namex, const char *namey, Double_t z, Double_t w)
483{
484 Int_t binx, biny, binz, bin;
485 fEntries++;
486 binx = fXaxis.FindBin(namex);
487 biny = fYaxis.FindBin(namey);
488 binz = fZaxis.FindBin(z);
489 if (binx <0 || biny <0 || binz<0) return -1;
490 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
491 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
492 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
493 AddBinContent(bin,w);
494 if (binx == 0 || binx > fXaxis.GetNbins()) return -1;
495 if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
496 if (binz == 0 || binz > fZaxis.GetNbins()) {
497 if (!GetStatOverflowsBehaviour()) return -1;
498 }
501 Double_t v = w;
502 fTsumw += v;
503 fTsumw2 += v*v;
504 fTsumwx += v*x;
505 fTsumwx2 += v*x*x;
506 fTsumwy += v*y;
507 fTsumwy2 += v*y*y;
508 fTsumwxy += v*x*y;
509 fTsumwz += v*z;
510 fTsumwz2 += v*z*z;
511 fTsumwxz += v*x*z;
512 fTsumwyz += v*y*z;
513 return bin;
514}
515
516
517////////////////////////////////////////////////////////////////////////////////
518/// Increment cell defined by x,namey,namez by a weight w
519///
520/// If the weight is not equal to 1, the storage of the sum of squares of
521/// weights is automatically triggered and the sum of the squares of weights is incremented
522/// by w^2 in the corresponding cell.
523/// The function returns the corresponding global bin number which has its content
524/// incremented by w
525
526Int_t TH3::Fill(Double_t x, const char *namey, const char *namez, Double_t w)
527{
528 Int_t binx, biny, binz, bin;
529 fEntries++;
530 binx = fXaxis.FindBin(x);
531 biny = fYaxis.FindBin(namey);
532 binz = fZaxis.FindBin(namez);
533 if (binx <0 || biny <0 || binz<0) return -1;
534 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
535 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
536 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
537 AddBinContent(bin,w);
538 if (binx == 0 || binx > fXaxis.GetNbins()) {
539 if (!GetStatOverflowsBehaviour()) return -1;
540 }
541 if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
542 if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
544 Double_t z = fZaxis.GetBinCenter(binz);
545 Double_t v = w;
546 fTsumw += v;
547 fTsumw2 += v*v;
548 fTsumwx += v*x;
549 fTsumwx2 += v*x*x;
550 fTsumwy += v*y;
551 fTsumwy2 += v*y*y;
552 fTsumwxy += v*x*y;
553 fTsumwz += v*z;
554 fTsumwz2 += v*z*z;
555 fTsumwxz += v*x*z;
556 fTsumwyz += v*y*z;
557 return bin;
558}
559
560
561////////////////////////////////////////////////////////////////////////////////
562/// Increment cell defined by x,namey,z by a weight w
563///
564/// If the weight is not equal to 1, the storage of the sum of squares of
565/// weights is automatically triggered and the sum of the squares of weights is incremented
566/// by w^2 in the corresponding cell.
567/// The function returns the corresponding global bin number which has its content
568/// incremented by w
569
570Int_t TH3::Fill(Double_t x, const char *namey, Double_t z, Double_t w)
571{
572 Int_t binx, biny, binz, bin;
573 fEntries++;
574 binx = fXaxis.FindBin(x);
575 biny = fYaxis.FindBin(namey);
576 binz = fZaxis.FindBin(z);
577 if (binx <0 || biny <0 || binz<0) return -1;
578 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
579 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
580 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
581 AddBinContent(bin,w);
582 if (binx == 0 || binx > fXaxis.GetNbins()) {
583 if (!GetStatOverflowsBehaviour()) return -1;
584 }
585 if (biny == 0 || biny > fYaxis.GetNbins()) return -1;
586 if (binz == 0 || binz > fZaxis.GetNbins()) {
587 if (!GetStatOverflowsBehaviour()) return -1;
588 }
590 Double_t v = w;
591 fTsumw += v;
592 fTsumw2 += v*v;
593 fTsumwx += v*x;
594 fTsumwx2 += v*x*x;
595 fTsumwy += v*y;
596 fTsumwy2 += v*y*y;
597 fTsumwxy += v*x*y;
598 fTsumwz += v*z;
599 fTsumwz2 += v*z*z;
600 fTsumwxz += v*x*z;
601 fTsumwyz += v*y*z;
602 return bin;
603}
604
605
606////////////////////////////////////////////////////////////////////////////////
607/// Increment cell defined by x,y,namez by a weight w
608///
609/// If the weight is not equal to 1, the storage of the sum of squares of
610/// weights is automatically triggered and the sum of the squares of weights is incremented
611/// by w^2 in the corresponding cell.
612/// The function returns the corresponding global bin number which has its content
613/// incremented by w
614
615Int_t TH3::Fill(Double_t x, Double_t y, const char *namez, Double_t w)
616{
617 Int_t binx, biny, binz, bin;
618 fEntries++;
619 binx = fXaxis.FindBin(x);
620 biny = fYaxis.FindBin(y);
621 binz = fZaxis.FindBin(namez);
622 if (binx <0 || biny <0 || binz<0) return -1;
623 bin = binx + (fXaxis.GetNbins()+2)*(biny + (fYaxis.GetNbins()+2)*binz);
624 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2(); // must be called before AddBinContent
625 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
626 AddBinContent(bin,w);
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 if (binz == 0 || binz > fZaxis.GetNbins()) return -1;
634 Double_t z = fZaxis.GetBinCenter(binz);
635 Double_t v = w;
636 fTsumw += v;
637 fTsumw2 += v*v;
638 fTsumwx += v*x;
639 fTsumwx2 += v*x*x;
640 fTsumwy += v*y;
641 fTsumwy2 += v*y*y;
642 fTsumwxy += v*x*y;
643 fTsumwz += v*z;
644 fTsumwz2 += v*z*z;
645 fTsumwxz += v*x*z;
646 fTsumwyz += v*y*z;
647 return bin;
648}
649
650
651////////////////////////////////////////////////////////////////////////////////
652/// Fill histogram following distribution in function fname.
653///
654/// The distribution contained in the function fname (TF1) is integrated
655/// over the channel contents.
656/// It is normalized to 1.
657/// Getting one random number implies:
658/// - Generating a random number between 0 and 1 (say r1)
659/// - Look in which bin in the normalized integral r1 corresponds to
660/// - Fill histogram channel
661/// ntimes random numbers are generated
662///
663/// N.B. By dfault this methods approximates the integral of the function in each bin with the
664/// function value at the center of the bin, mutiplied by the bin width
665///
666///
667/// One can also call TF1::GetRandom to get a random variate from a function.
668
669void TH3::FillRandom(const char *fname, Int_t ntimes)
670{
671 Int_t bin, binx, biny, binz, ibin, loop;
672 Double_t r1, x, y,z, xv[3];
673 // Search for fname in the list of ROOT defined functions
674 TObject *fobj = gROOT->GetFunction(fname);
675 if (!fobj) { Error("FillRandom", "Unknown function: %s",fname); return; }
676 TF3 *f1 = dynamic_cast<TF3*>( fobj );
677 if (!f1) { Error("FillRandom", "Function: %s is not a TF3, is a %s",fname,fobj->IsA()->GetName()); return; }
678
679 TAxis & xAxis = fXaxis;
680 TAxis & yAxis = fYaxis;
681 TAxis & zAxis = fZaxis;
682
683 // in case axes of histogram are not defined use the function axis
685 Double_t xmin,xmax,ymin,ymax,zmin,zmax;
686 f1->GetRange(xmin,ymin,zmin,xmax,ymax,zmax);
687 Info("FillRandom","Using function axis and range ([%g,%g],[%g,%g],[%g,%g])",xmin, xmax,ymin,ymax,zmin,zmax);
688 xAxis = *(f1->GetHistogram()->GetXaxis());
689 yAxis = *(f1->GetHistogram()->GetYaxis());
690 zAxis = *(f1->GetHistogram()->GetZaxis());
691 }
692
693 // Allocate temporary space to store the integral and compute integral
694 Int_t nbinsx = xAxis.GetNbins();
695 Int_t nbinsy = yAxis.GetNbins();
696 Int_t nbinsz = zAxis.GetNbins();
697 Int_t nxy = nbinsx*nbinsy;
698 Int_t nbins = nbinsx*nbinsy*nbinsz;
699
700 Double_t *integral = new Double_t[nbins+1];
701 ibin = 0;
702 integral[ibin] = 0;
703 // approximate integral with function value at bin center
704 for (binz=1;binz<=nbinsz;binz++) {
705 xv[2] = zAxis.GetBinCenter(binz);
706 for (biny=1;biny<=nbinsy;biny++) {
707 xv[1] = yAxis.GetBinCenter(biny);
708 for (binx=1;binx<=nbinsx;binx++) {
709 xv[0] = xAxis.GetBinCenter(binx);
710 ibin++;
711 Double_t fint = f1->EvalPar(xv, nullptr);
712 // uncomment this line to have the integral computation in a bin
713 // Double_t fint = f1->Integral(xAxis.GetBinLowEdge(binx), xAxis.GetBinUpEdge(binx),
714 // yAxis.GetBinLowEdge(biny), yAxis.GetBinUpEdge(biny),
715 // zAxis.GetBinLowEdge(binz), zAxis.GetBinUpEdge(binz));
716 integral[ibin] = integral[ibin-1] + fint;
717 }
718 }
719 }
720
721 // Normalize integral to 1
722 if (integral[nbins] == 0 ) {
723 delete [] integral;
724 Error("FillRandom", "Integral = zero"); return;
725 }
726 for (bin=1;bin<=nbins;bin++) integral[bin] /= integral[nbins];
727
728 // Start main loop ntimes
729 if (fDimension < 2) nbinsy = -1;
730 if (fDimension < 3) nbinsz = -1;
731 for (loop=0;loop<ntimes;loop++) {
732 r1 = gRandom->Rndm();
733 ibin = TMath::BinarySearch(nbins,&integral[0],r1);
734 binz = ibin/nxy;
735 biny = (ibin - nxy*binz)/nbinsx;
736 binx = 1 + ibin - nbinsx*(biny + nbinsy*binz);
737 if (nbinsz) binz++;
738 if (nbinsy) biny++;
739 x = xAxis.GetBinCenter(binx);
740 y = yAxis.GetBinCenter(biny);
741 z = zAxis.GetBinCenter(binz);
742 Fill(x,y,z, 1.);
743 }
744 delete [] integral;
745}
746
747
748////////////////////////////////////////////////////////////////////////////////
749/// Fill histogram following distribution in histogram h.
750///
751/// The distribution contained in the histogram h (TH3) is integrated
752/// over the channel contents.
753/// It is normalized to 1.
754/// Getting one random number implies:
755/// - Generating a random number between 0 and 1 (say r1)
756/// - Look in which bin in the normalized integral r1 corresponds to
757/// - Fill histogram channel
758/// ntimes random numbers are generated
759
761{
762 if (!h) { Error("FillRandom", "Null histogram"); return; }
763 if (fDimension != h->GetDimension()) {
764 Error("FillRandom", "Histograms with different dimensions"); return;
765 }
766
767 if (h->ComputeIntegral() == 0) return;
768
769 TH3 *h3 = (TH3*)h;
770 Int_t loop;
771 Double_t x,y,z;
772 for (loop=0;loop<ntimes;loop++) {
773 h3->GetRandom3(x,y,z);
774 Fill(x,y,z);
775 }
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Project slices along Z in case of a 3-D histogram, then fit each slice
780/// with function f1 and make a 2-d histogram for each fit parameter
781/// Only cells in the bin range [binminx,binmaxx] and [binminy,binmaxy] are considered.
782/// if f1=0, a gaussian is assumed
783/// Before invoking this function, one can set a subrange to be fitted along Z
784/// via f1->SetRange(zmin,zmax)
785/// The argument option (default="QNR") can be used to change the fit options.
786/// "Q" means Quiet mode
787/// "N" means do not show the result of the fit
788/// "R" means fit the function in the specified function range
789///
790/// Note that the generated histograms are added to the list of objects
791/// in the current directory. It is the user's responsibility to delete
792/// these histograms.
793///
794/// Example: Assume a 3-d histogram h3
795/// Root > h3->FitSlicesZ(); produces 4 TH2D histograms
796/// with h3_0 containing parameter 0(Constant) for a Gaus fit
797/// of each cell in X,Y projected along Z
798/// with h3_1 containing parameter 1(Mean) for a gaus fit
799/// with h3_2 containing parameter 2(StdDev) for a gaus fit
800/// with h3_chi2 containing the chisquare/number of degrees of freedom for a gaus fit
801///
802/// Root > h3->Fit(0,15,22,0,0,10);
803/// same as above, but only for bins 15 to 22 along X
804/// and only for cells in X,Y for which the corresponding projection
805/// along Z has more than cut bins filled.
806///
807/// NOTE: To access the generated histograms in the current directory, do eg:
808/// TH2D *h3_1 = (TH2D*)gDirectory->Get("h3_1");
809
810void TH3::FitSlicesZ(TF1 *f1, Int_t binminx, Int_t binmaxx, Int_t binminy, Int_t binmaxy, Int_t cut, Option_t *option)
811{
812 //Int_t nbinsz = fZaxis.GetNbins();
813
814 // get correct first and last bins for outer axes used in the loop doing the slices
815 // when using default values (0,-1) check if an axis range is set in outer axis
816 // do same as in DoProjection for inner axis
817 auto computeFirstAndLastBin = [](const TAxis & outerAxis, Int_t &firstbin, Int_t &lastbin) {
818 Int_t nbins = outerAxis.GetNbins();
819 if ( lastbin < firstbin && outerAxis.TestBit(TAxis::kAxisRange) ) {
820 firstbin = outerAxis.GetFirst();
821 lastbin = outerAxis.GetLast();
822 // For special case of TAxis::SetRange, when first == 1 and last
823 // = N and the range bit has been set, the TAxis will return 0
824 // for both.
825 if (firstbin == 0 && lastbin == 0) {
826 firstbin = 1;
827 lastbin = nbins;
828 }
829 }
830 if (firstbin < 0) firstbin = 0;
831 if (lastbin < 0 || lastbin > nbins + 1) lastbin = nbins + 1;
832 if (lastbin < firstbin) {firstbin = 0; lastbin = nbins + 1;}
833 };
834
835 computeFirstAndLastBin(fXaxis, binminx, binmaxx);
836 computeFirstAndLastBin(fYaxis, binminy, binmaxy);
837
838 // limits for the axis of the fit results histograms are different
839 auto computeAxisLimits = [](const TAxis & outerAxis, Int_t firstbin, Int_t lastbin,
840 Int_t &nBins, Double_t &xMin, Double_t & xMax) {
841 Int_t firstOutBin = std::max(firstbin,1);
842 Int_t lastOutBin = std::min(lastbin,outerAxis.GetNbins() ) ;
843 nBins = lastOutBin-firstOutBin+1;
844 xMin = outerAxis.GetBinLowEdge(firstOutBin);
845 xMax = outerAxis.GetBinUpEdge(lastOutBin);
846 // return first bin that is used in case of variable bin size axis
847 return firstOutBin;
848 };
849 Int_t nbinsX = 0;
850 Double_t xMin, xMax = 0;
851 Int_t firstBinXaxis = computeAxisLimits(fXaxis, binminx, binmaxx, nbinsX, xMin, xMax);
852 Int_t nbinsY = 0;
853 Double_t yMin, yMax = 0;
854 Int_t firstBinYaxis = computeAxisLimits(fYaxis, binminy, binmaxy, nbinsY, yMin, yMax);
855
856 //default is to fit with a gaussian
857 if (f1 == 0) {
858 f1 = (TF1*)gROOT->GetFunction("gaus");
859 if (f1 == 0) f1 = new TF1("gaus","gaus",fZaxis.GetXmin(),fZaxis.GetXmax());
861 }
862 const char *fname = f1->GetName();
863 Int_t npar = f1->GetNpar();
864 Double_t *parsave = new Double_t[npar];
865 f1->GetParameters(parsave);
866
867 //Create one 2-d histogram for each function parameter
868 Int_t ipar;
870 TString title;
871 std::vector<TH1*> hlist(npar+1); // include also chi2 histogram
872 const TArrayD *xbins = fXaxis.GetXbins();
873 const TArrayD *ybins = fYaxis.GetXbins();
874 for (ipar=0;ipar<= npar;ipar++) {
875 if (ipar < npar) {
876 // fitted parameter histograms
877 name = TString::Format("%s_%d",GetName(),ipar);
878 title = TString::Format("Fitted value of par[%d]=%s",ipar,f1->GetParName(ipar));
879 } else {
880 // chi2 histograms
881 name = TString::Format("%s_chi2",GetName());
882 title = "chisquare";
883 }
884 if (xbins->fN == 0 && ybins->fN == 0) {
885 hlist[ipar] = new TH2D(name, title,
886 nbinsX, xMin, xMax,
887 nbinsY, yMin, yMax);
888 } else if (xbins->fN > 0 && ybins->fN > 0 ) {
889 hlist[ipar] = new TH2D(name, title,
890 nbinsX, &xbins->fArray[firstBinXaxis],
891 nbinsY, &ybins->fArray[firstBinYaxis]);
892 }
893 // mixed case do not exist for TH3
894 R__ASSERT(hlist[ipar]);
895
896 hlist[ipar]->GetXaxis()->SetTitle(fXaxis.GetTitle());
897 hlist[ipar]->GetYaxis()->SetTitle(fYaxis.GetTitle());
898 }
899 TH1 * hchi2 = hlist.back();
900
901 //Loop on all cells in X,Y generate a projection along Z
902 TH1D *hpz = nullptr;
903 TString opt(option);
904 // add option "N" when fitting the 2D histograms
905 opt += " N ";
906
907 for (Int_t biny=binminy; biny<=binmaxy; biny++) {
908 for (Int_t binx=binminx; binx<=binmaxx; binx++) {
909 // use TH3::ProjectionZ
910 hpz = ProjectionZ("R_temp",binx,binx,biny,biny);
911
913 if ( nentries <= 0 || nentries < cut) {
914 if (!opt.Contains("Q"))
915 Info("FitSlicesZ","Slice (%d,%d) skipped, the number of entries is zero or smaller than the given cut value, n=%f",binx,biny,nentries);
916 continue;
917 }
918 f1->SetParameters(parsave);
919 Int_t bin = hlist[0]->FindBin( fXaxis.GetBinCenter(binx), fYaxis.GetBinCenter(biny) );
920 if (!opt.Contains("Q")) {
921 int ibx,iby,ibz = 0;
922 hlist[0]->GetBinXYZ(bin,ibx,iby,ibz);
923 Info("DoFitSlices","Slice fit [(%f,%f),(%f,%f)]",hlist[0]->GetXaxis()->GetBinLowEdge(ibx), hlist[0]->GetXaxis()->GetBinUpEdge(ibx),
924 hlist[0]->GetYaxis()->GetBinLowEdge(iby), hlist[0]->GetYaxis()->GetBinUpEdge(iby));
925 }
926 hpz->Fit(fname,opt.Data());
927 Int_t npfits = f1->GetNumberFitPoints();
928 if (npfits > npar && npfits >= cut) {
929 for (ipar=0;ipar<npar;ipar++) {
930 hlist[ipar]->SetBinContent(bin,f1->GetParameter(ipar));
931 hlist[ipar]->SetBinError(bin,f1->GetParError(ipar));
932 }
933 hchi2->SetBinContent(bin,f1->GetChisquare()/(npfits-npar));
934 }
935 else {
936 if (!opt.Contains("Q"))
937 Info("FitSlicesZ","Fitted slice (%d,%d) skipped, the number of fitted points is too small, n=%d",binx,biny,npfits);
938 }
939 }
940 }
941 delete [] parsave;
942 delete hpz;
943}
944
945
946////////////////////////////////////////////////////////////////////////////////
947/// See comments in TH1::GetBin
948
949Int_t TH3::GetBin(Int_t binx, Int_t biny, Int_t binz) const
950{
951 Int_t ofy = fYaxis.GetNbins() + 1; // code duplication unavoidable because TH3 does not inherit from TH2
952 if (biny < 0) biny = 0;
953 if (biny > ofy) biny = ofy;
954
955 Int_t ofz = fZaxis.GetNbins() + 1; // overflow bin
956 if (binz < 0) binz = 0;
957 if (binz > ofz) binz = ofz;
958
959 return TH1::GetBin(binx) + (fXaxis.GetNbins() + 2) * (biny + (fYaxis.GetNbins() + 2) * binz);
960}
961
962
963////////////////////////////////////////////////////////////////////////////////
964/// Compute first cell (binx,biny,binz) in the range [firstx,lastx](firsty,lasty][firstz,lastz] for which
965/// diff = abs(cell_content-c) <= maxdiff
966/// In case several cells in the specified range with diff=0 are found
967/// the first cell found is returned in binx,biny,binz.
968/// In case several cells in the specified range satisfy diff <=maxdiff
969/// the cell with the smallest difference is returned in binx,biny,binz.
970/// In all cases the function returns the smallest difference.
971///
972/// NOTE1: if firstx <= 0, firstx is set to bin 1
973/// if (lastx < firstx then firstx is set to the number of bins in X
974/// ie if firstx=0 and lastx=0 (default) the search is on all bins in X.
975/// if firsty <= 0, firsty is set to bin 1
976/// if (lasty < firsty then firsty is set to the number of bins in Y
977/// ie if firsty=0 and lasty=0 (default) the search is on all bins in Y.
978/// if firstz <= 0, firstz is set to bin 1
979/// if (lastz < firstz then firstz is set to the number of bins in Z
980/// ie if firstz=0 and lastz=0 (default) the search is on all bins in Z.
981/// NOTE2: if maxdiff=0 (default), the first cell with content=c is returned.
982
984 Int_t firstx, Int_t lastx,
985 Int_t firsty, Int_t lasty,
986 Int_t firstz, Int_t lastz,
987 Double_t maxdiff) const
988{
989 if (fDimension != 3) {
990 binx = 0;
991 biny = 0;
992 binz = 0;
993 Error("GetBinWithContent3","function is only valid for 3-D histograms");
994 return 0;
995 }
996 if (firstx <= 0) firstx = 1;
997 if (lastx < firstx) lastx = fXaxis.GetNbins();
998 if (firsty <= 0) firsty = 1;
999 if (lasty < firsty) lasty = fYaxis.GetNbins();
1000 if (firstz <= 0) firstz = 1;
1001 if (lastz < firstz) lastz = fZaxis.GetNbins();
1002 Int_t binminx = 0, binminy=0, binminz=0;
1003 Double_t diff, curmax = 1.e240;
1004 for (Int_t k=firstz;k<=lastz;k++) {
1005 for (Int_t j=firsty;j<=lasty;j++) {
1006 for (Int_t i=firstx;i<=lastx;i++) {
1007 diff = TMath::Abs(GetBinContent(i,j,k)-c);
1008 if (diff <= 0) {binx = i; biny=j; binz=k; return diff;}
1009 if (diff < curmax && diff <= maxdiff) {curmax = diff, binminx=i; binminy=j;binminz=k;}
1010 }
1011 }
1012 }
1013 binx = binminx;
1014 biny = binminy;
1015 binz = binminz;
1016 return curmax;
1017}
1018
1019
1020////////////////////////////////////////////////////////////////////////////////
1021/// Return correlation factor between axis1 and axis2.
1022
1024{
1025 if (axis1 < 1 || axis2 < 1 || axis1 > 3 || axis2 > 3) {
1026 Error("GetCorrelationFactor","Wrong parameters");
1027 return 0;
1028 }
1029 if (axis1 == axis2) return 1;
1030 Double_t stddev1 = GetStdDev(axis1);
1031 if (stddev1 == 0) return 0;
1032 Double_t stddev2 = GetStdDev(axis2);
1033 if (stddev2 == 0) return 0;
1034 return GetCovariance(axis1,axis2)/stddev1/stddev2;
1035}
1036
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Return covariance between axis1 and axis2.
1040
1042{
1043 if (axis1 < 1 || axis2 < 1 || axis1 > 3 || axis2 > 3) {
1044 Error("GetCovariance","Wrong parameters");
1045 return 0;
1046 }
1047 Double_t stats[kNstat];
1048 GetStats(stats);
1049 Double_t sumw = stats[0];
1050 Double_t sumw2 = stats[1];
1051 Double_t sumwx = stats[2];
1052 Double_t sumwx2 = stats[3];
1053 Double_t sumwy = stats[4];
1054 Double_t sumwy2 = stats[5];
1055 Double_t sumwxy = stats[6];
1056 Double_t sumwz = stats[7];
1057 Double_t sumwz2 = stats[8];
1058 Double_t sumwxz = stats[9];
1059 Double_t sumwyz = stats[10];
1060
1061 if (sumw == 0) return 0;
1062 if (axis1 == 1 && axis2 == 1) {
1063 return TMath::Abs(sumwx2/sumw - sumwx*sumwx/sumw2);
1064 }
1065 if (axis1 == 2 && axis2 == 2) {
1066 return TMath::Abs(sumwy2/sumw - sumwy*sumwy/sumw2);
1067 }
1068 if (axis1 == 3 && axis2 == 3) {
1069 return TMath::Abs(sumwz2/sumw - sumwz*sumwz/sumw2);
1070 }
1071 if ((axis1 == 1 && axis2 == 2) || (axis1 == 2 && axis2 == 1)) {
1072 return sumwxy/sumw - sumwx/sumw*sumwy/sumw;
1073 }
1074 if ((axis1 == 1 && axis2 == 3) || (axis1 == 3 && axis2 == 1)) {
1075 return sumwxz/sumw - sumwx/sumw*sumwz/sumw;
1076 }
1077 if ((axis1 == 2 && axis2 == 3) || (axis1 == 3 && axis2 == 2)) {
1078 return sumwyz/sumw - sumwy/sumw*sumwz/sumw;
1079 }
1080 return 0;
1081}
1082
1083
1084////////////////////////////////////////////////////////////////////////////////
1085/// Return 3 random numbers along axis x , y and z distributed according
1086/// the cell-contents of a 3-dim histogram
1087
1089{
1090 Int_t nbinsx = GetNbinsX();
1091 Int_t nbinsy = GetNbinsY();
1092 Int_t nbinsz = GetNbinsZ();
1093 Int_t nxy = nbinsx*nbinsy;
1094 Int_t nbins = nxy*nbinsz;
1095 Double_t integral;
1096 // compute integral checking that all bins have positive content (see ROOT-5894)
1097 if (fIntegral) {
1098 if (fIntegral[nbins+1] != fEntries) integral = ComputeIntegral(true);
1099 else integral = fIntegral[nbins];
1100 } else {
1101 integral = ComputeIntegral(true);
1102 }
1103 if (integral == 0 ) { x = 0; y = 0; z = 0; return;}
1104 // case histogram has negative bins
1105 if (integral == TMath::QuietNaN() ) { x = TMath::QuietNaN(); y = TMath::QuietNaN(); z = TMath::QuietNaN(); return;}
1106
1107 Double_t r1 = gRandom->Rndm();
1108 Int_t ibin = TMath::BinarySearch(nbins,fIntegral,(Double_t) r1);
1109 Int_t binz = ibin/nxy;
1110 Int_t biny = (ibin - nxy*binz)/nbinsx;
1111 Int_t binx = ibin - nbinsx*(biny + nbinsy*binz);
1112 x = fXaxis.GetBinLowEdge(binx+1);
1113 if (r1 > fIntegral[ibin]) x +=
1114 fXaxis.GetBinWidth(binx+1)*(r1-fIntegral[ibin])/(fIntegral[ibin+1] - fIntegral[ibin]);
1115 y = fYaxis.GetBinLowEdge(biny+1) + fYaxis.GetBinWidth(biny+1)*gRandom->Rndm();
1116 z = fZaxis.GetBinLowEdge(binz+1) + fZaxis.GetBinWidth(binz+1)*gRandom->Rndm();
1117}
1118
1119
1120////////////////////////////////////////////////////////////////////////////////
1121/// Fill the array stats from the contents of this histogram
1122/// The array stats must be correctly dimensioned in the calling program.
1123/// stats[0] = sumw
1124/// stats[1] = sumw2
1125/// stats[2] = sumwx
1126/// stats[3] = sumwx2
1127/// stats[4] = sumwy
1128/// stats[5] = sumwy2
1129/// stats[6] = sumwxy
1130/// stats[7] = sumwz
1131/// stats[8] = sumwz2
1132/// stats[9] = sumwxz
1133/// stats[10]= sumwyz
1134
1135void TH3::GetStats(Double_t *stats) const
1136{
1137 if (fBuffer) ((TH3*)this)->BufferEmpty();
1138
1139 Int_t bin, binx, biny, binz;
1140 Double_t w,err;
1141 Double_t x,y,z;
1143 for (bin=0;bin<11;bin++) stats[bin] = 0;
1144
1145 Int_t firstBinX = fXaxis.GetFirst();
1146 Int_t lastBinX = fXaxis.GetLast();
1147 Int_t firstBinY = fYaxis.GetFirst();
1148 Int_t lastBinY = fYaxis.GetLast();
1149 Int_t firstBinZ = fZaxis.GetFirst();
1150 Int_t lastBinZ = fZaxis.GetLast();
1151 // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
1154 if (firstBinX == 1) firstBinX = 0;
1155 if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
1156 }
1158 if (firstBinY == 1) firstBinY = 0;
1159 if (lastBinY == fYaxis.GetNbins() ) lastBinY += 1;
1160 }
1162 if (firstBinZ == 1) firstBinZ = 0;
1163 if (lastBinZ == fZaxis.GetNbins() ) lastBinZ += 1;
1164 }
1165 }
1166 for (binz = firstBinZ; binz <= lastBinZ; binz++) {
1167 z = fZaxis.GetBinCenter(binz);
1168 for (biny = firstBinY; biny <= lastBinY; biny++) {
1169 y = fYaxis.GetBinCenter(biny);
1170 for (binx = firstBinX; binx <= lastBinX; binx++) {
1171 bin = GetBin(binx,biny,binz);
1172 x = fXaxis.GetBinCenter(binx);
1173 //w = TMath::Abs(GetBinContent(bin));
1174 w = RetrieveBinContent(bin);
1175 err = TMath::Abs(GetBinError(bin));
1176 stats[0] += w;
1177 stats[1] += err*err;
1178 stats[2] += w*x;
1179 stats[3] += w*x*x;
1180 stats[4] += w*y;
1181 stats[5] += w*y*y;
1182 stats[6] += w*x*y;
1183 stats[7] += w*z;
1184 stats[8] += w*z*z;
1185 stats[9] += w*x*z;
1186 stats[10]+= w*y*z;
1187 }
1188 }
1189 }
1190 } else {
1191 stats[0] = fTsumw;
1192 stats[1] = fTsumw2;
1193 stats[2] = fTsumwx;
1194 stats[3] = fTsumwx2;
1195 stats[4] = fTsumwy;
1196 stats[5] = fTsumwy2;
1197 stats[6] = fTsumwxy;
1198 stats[7] = fTsumwz;
1199 stats[8] = fTsumwz2;
1200 stats[9] = fTsumwxz;
1201 stats[10]= fTsumwyz;
1202 }
1203}
1204
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Return integral of bin contents. Only bins in the bins range are considered.
1208/// By default the integral is computed as the sum of bin contents in the range.
1209/// if option "width" is specified, the integral is the sum of
1210/// the bin contents multiplied by the bin width in x, y and in z.
1211
1213{
1216 fZaxis.GetFirst(),fZaxis.GetLast(),option);
1217}
1218
1219
1220////////////////////////////////////////////////////////////////////////////////
1221/// Return integral of bin contents in range [binx1,binx2],[biny1,biny2],[binz1,binz2]
1222/// for a 3-D histogram
1223/// By default the integral is computed as the sum of bin contents in the range.
1224/// if option "width" is specified, the integral is the sum of
1225/// the bin contents multiplied by the bin width in x, y and in z.
1226
1227Double_t TH3::Integral(Int_t binx1, Int_t binx2, Int_t biny1, Int_t biny2,
1228 Int_t binz1, Int_t binz2, Option_t *option) const
1229{
1230 Double_t err = 0;
1231 return DoIntegral(binx1,binx2,biny1,biny2,binz1,binz2,err,option);
1232}
1233
1234
1235////////////////////////////////////////////////////////////////////////////////
1236/// Return integral of bin contents in range [binx1,binx2],[biny1,biny2],[binz1,binz2]
1237/// for a 3-D histogram. Calculates also the integral error using error propagation
1238/// from the bin errors assuming that all the bins are uncorrelated.
1239/// By default the integral is computed as the sum of bin contents in the range.
1240/// if option "width" is specified, the integral is the sum of
1241/// the bin contents multiplied by the bin width in x, y and in z.
1242
1244 Int_t binz1, Int_t binz2,
1245 Double_t & error, Option_t *option) const
1246{
1247 return DoIntegral(binx1,binx2,biny1,biny2,binz1,binz2,error,option,kTRUE);
1248}
1249
1250////////////////////////////////////////////////////////////////////////////////
1251///Not yet implemented
1252
1254{
1255 Error("Interpolate","This function must be called with 3 arguments for a TH3");
1256 return 0;
1257}
1258
1259
1260////////////////////////////////////////////////////////////////////////////////
1261///Not yet implemented
1262
1264{
1265 Error("Interpolate","This function must be called with 3 arguments for a TH3");
1266 return 0;
1267}
1268
1269
1270////////////////////////////////////////////////////////////////////////////////
1271/// Given a point P(x,y,z), Interpolate approximates the value via trilinear interpolation
1272/// based on the 8 nearest bin center points (corner of the cube surrounding the points)
1273/// The Algorithm is described in http://en.wikipedia.org/wiki/Trilinear_interpolation
1274/// The given values (x,y,z) must be between first bin center and last bin center for each coordinate:
1275///
1276/// fXAxis.GetBinCenter(1) < x < fXaxis.GetBinCenter(nbinX) AND
1277/// fYAxis.GetBinCenter(1) < y < fYaxis.GetBinCenter(nbinY) AND
1278/// fZAxis.GetBinCenter(1) < z < fZaxis.GetBinCenter(nbinZ)
1279
1281{
1282 Int_t ubx = fXaxis.FindFixBin(x);
1283 if ( x < fXaxis.GetBinCenter(ubx) ) ubx -= 1;
1284 Int_t obx = ubx + 1;
1285
1286 Int_t uby = fYaxis.FindFixBin(y);
1287 if ( y < fYaxis.GetBinCenter(uby) ) uby -= 1;
1288 Int_t oby = uby + 1;
1289
1290 Int_t ubz = fZaxis.FindFixBin(z);
1291 if ( z < fZaxis.GetBinCenter(ubz) ) ubz -= 1;
1292 Int_t obz = ubz + 1;
1293
1294
1295// if ( IsBinUnderflow(GetBin(ubx, uby, ubz)) ||
1296// IsBinOverflow (GetBin(obx, oby, obz)) ) {
1297 if (ubx <=0 || uby <=0 || ubz <= 0 ||
1298 obx > fXaxis.GetNbins() || oby > fYaxis.GetNbins() || obz > fZaxis.GetNbins() ) {
1299 Error("Interpolate","Cannot interpolate outside histogram domain.");
1300 return 0;
1301 }
1302
1306
1307 Double_t xd = (x - fXaxis.GetBinCenter(ubx)) / xw;
1308 Double_t yd = (y - fYaxis.GetBinCenter(uby)) / yw;
1309 Double_t zd = (z - fZaxis.GetBinCenter(ubz)) / zw;
1310
1311
1312 Double_t v[] = { GetBinContent( ubx, uby, ubz ), GetBinContent( ubx, uby, obz ),
1313 GetBinContent( ubx, oby, ubz ), GetBinContent( ubx, oby, obz ),
1314 GetBinContent( obx, uby, ubz ), GetBinContent( obx, uby, obz ),
1315 GetBinContent( obx, oby, ubz ), GetBinContent( obx, oby, obz ) };
1316
1317
1318 Double_t i1 = v[0] * (1 - zd) + v[1] * zd;
1319 Double_t i2 = v[2] * (1 - zd) + v[3] * zd;
1320 Double_t j1 = v[4] * (1 - zd) + v[5] * zd;
1321 Double_t j2 = v[6] * (1 - zd) + v[7] * zd;
1322
1323
1324 Double_t w1 = i1 * (1 - yd) + i2 * yd;
1325 Double_t w2 = j1 * (1 - yd) + j2 * yd;
1326
1327
1328 Double_t result = w1 * (1 - xd) + w2 * xd;
1329
1330 return result;
1331}
1332
1333
1334////////////////////////////////////////////////////////////////////////////////
1335/// Statistical test of compatibility in shape between
1336/// THIS histogram and h2, using Kolmogorov test.
1337/// Default: Ignore under- and overflow bins in comparison
1338///
1339/// option is a character string to specify options
1340/// "U" include Underflows in test
1341/// "O" include Overflows
1342/// "N" include comparison of normalizations
1343/// "D" Put out a line of "Debug" printout
1344/// "M" Return the Maximum Kolmogorov distance instead of prob
1345///
1346/// The returned function value is the probability of test
1347/// (much less than one means NOT compatible)
1348///
1349/// The KS test uses the distance between the pseudo-CDF's obtained
1350/// from the histogram. Since in more than 1D the order for generating the pseudo-CDF is
1351/// arbitrary, we use the pseudo-CDF's obtained from all the possible 6 combinations of the 3 axis.
1352/// The average of all the maximum distances obtained is used in the tests.
1353
1354Double_t TH3::KolmogorovTest(const TH1 *h2, Option_t *option) const
1355{
1356 TString opt = option;
1357 opt.ToUpper();
1358
1359 Double_t prb = 0;
1360 TH1 *h1 = (TH1*)this;
1361 if (h2 == 0) return 0;
1362 const TAxis *xaxis1 = h1->GetXaxis();
1363 const TAxis *xaxis2 = h2->GetXaxis();
1364 const TAxis *yaxis1 = h1->GetYaxis();
1365 const TAxis *yaxis2 = h2->GetYaxis();
1366 const TAxis *zaxis1 = h1->GetZaxis();
1367 const TAxis *zaxis2 = h2->GetZaxis();
1368 Int_t ncx1 = xaxis1->GetNbins();
1369 Int_t ncx2 = xaxis2->GetNbins();
1370 Int_t ncy1 = yaxis1->GetNbins();
1371 Int_t ncy2 = yaxis2->GetNbins();
1372 Int_t ncz1 = zaxis1->GetNbins();
1373 Int_t ncz2 = zaxis2->GetNbins();
1374
1375 // Check consistency of dimensions
1376 if (h1->GetDimension() != 3 || h2->GetDimension() != 3) {
1377 Error("KolmogorovTest","Histograms must be 3-D\n");
1378 return 0;
1379 }
1380
1381 // Check consistency in number of channels
1382 if (ncx1 != ncx2) {
1383 Error("KolmogorovTest","Number of channels in X is different, %d and %d\n",ncx1,ncx2);
1384 return 0;
1385 }
1386 if (ncy1 != ncy2) {
1387 Error("KolmogorovTest","Number of channels in Y is different, %d and %d\n",ncy1,ncy2);
1388 return 0;
1389 }
1390 if (ncz1 != ncz2) {
1391 Error("KolmogorovTest","Number of channels in Z is different, %d and %d\n",ncz1,ncz2);
1392 return 0;
1393 }
1394
1395 // Check consistency in channel edges
1396 Bool_t afunc1 = kFALSE;
1397 Bool_t afunc2 = kFALSE;
1398 Double_t difprec = 1e-5;
1399 Double_t diff1 = TMath::Abs(xaxis1->GetXmin() - xaxis2->GetXmin());
1400 Double_t diff2 = TMath::Abs(xaxis1->GetXmax() - xaxis2->GetXmax());
1401 if (diff1 > difprec || diff2 > difprec) {
1402 Error("KolmogorovTest","histograms with different binning along X");
1403 return 0;
1404 }
1405 diff1 = TMath::Abs(yaxis1->GetXmin() - yaxis2->GetXmin());
1406 diff2 = TMath::Abs(yaxis1->GetXmax() - yaxis2->GetXmax());
1407 if (diff1 > difprec || diff2 > difprec) {
1408 Error("KolmogorovTest","histograms with different binning along Y");
1409 return 0;
1410 }
1411 diff1 = TMath::Abs(zaxis1->GetXmin() - zaxis2->GetXmin());
1412 diff2 = TMath::Abs(zaxis1->GetXmax() - zaxis2->GetXmax());
1413 if (diff1 > difprec || diff2 > difprec) {
1414 Error("KolmogorovTest","histograms with different binning along Z");
1415 return 0;
1416 }
1417
1418 // Should we include Uflows, Oflows?
1419 Int_t ibeg = 1, jbeg = 1, kbeg = 1;
1420 Int_t iend = ncx1, jend = ncy1, kend = ncz1;
1421 if (opt.Contains("U")) {ibeg = 0; jbeg = 0; kbeg = 0;}
1422 if (opt.Contains("O")) {iend = ncx1+1; jend = ncy1+1; kend = ncz1+1;}
1423
1424 Int_t i,j,k,bin;
1425 Double_t sum1 = 0;
1426 Double_t sum2 = 0;
1427 Double_t w1 = 0;
1428 Double_t w2 = 0;
1429 for (i = ibeg; i <= iend; i++) {
1430 for (j = jbeg; j <= jend; j++) {
1431 for (k = kbeg; k <= kend; k++) {
1432 bin = h1->GetBin(i,j,k);
1433 sum1 += h1->GetBinContent(bin);
1434 sum2 += h2->GetBinContent(bin);
1435 Double_t ew1 = h1->GetBinError(bin);
1436 Double_t ew2 = h2->GetBinError(bin);
1437 w1 += ew1*ew1;
1438 w2 += ew2*ew2;
1439 }
1440 }
1441 }
1442
1443
1444 // Check that both scatterplots contain events
1445 if (sum1 == 0) {
1446 Error("KolmogorovTest","Integral is zero for h1=%s\n",h1->GetName());
1447 return 0;
1448 }
1449 if (sum2 == 0) {
1450 Error("KolmogorovTest","Integral is zero for h2=%s\n",h2->GetName());
1451 return 0;
1452 }
1453 // calculate the effective entries.
1454 // the case when errors are zero (w1 == 0 or w2 ==0) are equivalent to
1455 // compare to a function. In that case the rescaling is done only on sqrt(esum2) or sqrt(esum1)
1456 Double_t esum1 = 0, esum2 = 0;
1457 if (w1 > 0)
1458 esum1 = sum1 * sum1 / w1;
1459 else
1460 afunc1 = kTRUE; // use later for calculating z
1461
1462 if (w2 > 0)
1463 esum2 = sum2 * sum2 / w2;
1464 else
1465 afunc2 = kTRUE; // use later for calculating z
1466
1467 if (afunc2 && afunc1) {
1468 Error("KolmogorovTest","Errors are zero for both histograms\n");
1469 return 0;
1470 }
1471
1472 // Find Kolmogorov distance
1473 // order is arbitrary take average of all possible 6 starting orders x,y,z
1474 int order[3] = {0,1,2};
1475 int binbeg[3];
1476 int binend[3];
1477 int ibin[3];
1478 binbeg[0] = ibeg; binbeg[1] = jbeg; binbeg[2] = kbeg;
1479 binend[0] = iend; binend[1] = jend; binend[2] = kend;
1480 Double_t vdfmax[6]; // there are in total 6 combinations
1481 int icomb = 0;
1482 Double_t s1 = 1./(6.*sum1);
1483 Double_t s2 = 1./(6.*sum2);
1484 Double_t rsum1=0, rsum2=0;
1485 do {
1486 // loop on bins
1487 Double_t dmax = 0;
1488 for (i = binbeg[order[0] ]; i <= binend[order[0] ]; i++) {
1489 for ( j = binbeg[order[1] ]; j <= binend[order[1] ]; j++) {
1490 for ( k = binbeg[order[2] ]; k <= binend[order[2] ]; k++) {
1491 ibin[ order[0] ] = i;
1492 ibin[ order[1] ] = j;
1493 ibin[ order[2] ] = k;
1494 bin = h1->GetBin(ibin[0],ibin[1],ibin[2]);
1495 rsum1 += s1*h1->GetBinContent(bin);
1496 rsum2 += s2*h2->GetBinContent(bin);
1497 dmax = TMath::Max(dmax, TMath::Abs(rsum1-rsum2));
1498 }
1499 }
1500 }
1501 vdfmax[icomb] = dmax;
1502 icomb++;
1503 } while (TMath::Permute(3,order) );
1504
1505
1506 // get average of distances
1507 Double_t dfmax = TMath::Mean(6,vdfmax);
1508
1509 // Get Kolmogorov probability
1510 Double_t factnm;
1511 if (afunc1) factnm = TMath::Sqrt(sum2);
1512 else if (afunc2) factnm = TMath::Sqrt(sum1);
1513 else factnm = TMath::Sqrt(sum1*sum2/(sum1+sum2));
1514 Double_t z = dfmax*factnm;
1515
1516 prb = TMath::KolmogorovProb(z);
1517
1518 Double_t prb1 = 0, prb2 = 0;
1519 // option N to combine normalization makes sense if both afunc1 and afunc2 are false
1520 if (opt.Contains("N") && !(afunc1 || afunc2 ) ) {
1521 // Combine probabilities for shape and normalization
1522 prb1 = prb;
1523 Double_t d12 = esum1-esum2;
1524 Double_t chi2 = d12*d12/(esum1+esum2);
1525 prb2 = TMath::Prob(chi2,1);
1526 // see Eadie et al., section 11.6.2
1527 if (prb > 0 && prb2 > 0) prb = prb*prb2*(1-TMath::Log(prb*prb2));
1528 else prb = 0;
1529 }
1530
1531 // debug printout
1532 if (opt.Contains("D")) {
1533 printf(" Kolmo Prob h1 = %s, sum1=%g\n",h1->GetName(),sum1);
1534 printf(" Kolmo Prob h2 = %s, sum2=%g\n",h2->GetName(),sum2);
1535 printf(" Kolmo Probabil = %f, Max Dist = %g\n",prb,dfmax);
1536 if (opt.Contains("N"))
1537 printf(" Kolmo Probabil = %f for shape alone, =%f for normalisation alone\n",prb1,prb2);
1538 }
1539 // This numerical error condition should never occur:
1540 if (TMath::Abs(rsum1-1) > 0.002) Warning("KolmogorovTest","Numerical problems with h1=%s\n",h1->GetName());
1541 if (TMath::Abs(rsum2-1) > 0.002) Warning("KolmogorovTest","Numerical problems with h2=%s\n",h2->GetName());
1542
1543 if (opt.Contains("M")) return dfmax; // return average of max distance
1544
1545 return prb;
1546}
1547
1548
1549////////////////////////////////////////////////////////////////////////////////
1550/// Project a 3-D histogram into a 1-D histogram along X.
1551///
1552/// The projection is always of the type TH1D.
1553/// The projection is made from the cells along the X axis
1554/// ranging from iymin to iymax and izmin to izmax included.
1555/// By default, underflow and overflows are included in both the Y and Z axis.
1556/// By Setting iymin=1 and iymax=NbinsY the underflow and/or overflow in Y will be excluded
1557/// By setting izmin=1 and izmax=NbinsZ the underflow and/or overflow in Z will be excluded
1558///
1559/// if option "e" is specified, the errors are computed.
1560/// if option "d" is specified, the projection is drawn in the current pad.
1561/// if option "o" original axis range of the target axes will be
1562/// kept, but only bins inside the selected range will be filled.
1563///
1564/// NOTE that if a TH1D named "name" exists in the current directory or pad
1565/// the histogram is reset and filled again with the projected contents of the TH3.
1566///
1567/// implemented using Project3D
1568
1569TH1D *TH3::ProjectionX(const char *name, Int_t iymin, Int_t iymax,
1570 Int_t izmin, Int_t izmax, Option_t *option) const
1571{
1572 // in case of default name append the parent name
1573 TString hname = name;
1574 if (hname == "_px") hname = TString::Format("%s%s", GetName(), name);
1575 TString title = TString::Format("%s ( Projection X )",GetTitle());
1576
1577 // when projecting in Z outer axis are Y and Z (order is important. It is defined in the DoProject1D function)
1578 return DoProject1D(hname, title, iymin, iymax, izmin, izmax, &fXaxis, &fYaxis, &fZaxis, option);
1579}
1580
1581
1582////////////////////////////////////////////////////////////////////////////////
1583/// Project a 3-D histogram into a 1-D histogram along Y.
1584///
1585/// The projection is always of the type TH1D.
1586/// The projection is made from the cells along the Y axis
1587/// ranging from ixmin to ixmax and izmin to izmax included.
1588/// By default, underflow and overflow are included in both the X and Z axis.
1589/// By setting ixmin=1 and ixmax=NbinsX the underflow and/or overflow in X will be excluded
1590/// By setting izmin=1 and izmax=NbinsZ the underflow and/or overflow in Z will be excluded
1591///
1592/// if option "e" is specified, the errors are computed.
1593/// if option "d" is specified, the projection is drawn in the current pad.
1594/// if option "o" original axis range of the target axes will be
1595/// kept, but only bins inside the selected range will be filled.
1596///
1597/// NOTE that if a TH1D named "name" exists in the current directory or pad,
1598/// the histogram is reset and filled again with the projected contents of the TH3.
1599///
1600/// implemented using Project3D
1601
1602TH1D *TH3::ProjectionY(const char *name, Int_t ixmin, Int_t ixmax,
1603 Int_t izmin, Int_t izmax, Option_t *option) const
1604{
1605 TString hname = name;
1606 if (hname == "_py") hname = TString::Format("%s%s", GetName(), name);
1607 TString title = TString::Format("%s ( Projection Y )",GetTitle());
1608
1609 // when projecting in Z outer axis are X and Y (order is important. It is defined in the DoProject1D function)
1610 return DoProject1D(hname, title, ixmin, ixmax, izmin, izmax, &fYaxis, &fXaxis, &fZaxis, option);
1611}
1612
1613////////////////////////////////////////////////////////////////////////////////
1614/// Project a 3-D histogram into a 1-D histogram along Z.
1615///
1616/// The projection is always of the type TH1D.
1617/// The projection is made from the cells along the Z axis
1618/// ranging from ixmin to ixmax and iymin to iymax included.
1619/// By default, bins 1 to nx and 1 to ny are included
1620/// By default, underflow and overflow are included in both the X and Y axis.
1621/// By Setting ixmin=1 and ixmax=NbinsX the underflow and/or overflow in X will be excluded
1622/// By setting iymin=1 and/or iymax=NbinsY the underflow and/or overflow in Y will be excluded
1623///
1624/// if option "e" is specified, the errors are computed.
1625/// if option "d" is specified, the projection is drawn in the current pad.
1626/// if option "o" original axis range of the target axes will be
1627/// kept, but only bins inside the selected range will be filled.
1628///
1629/// NOTE that if a TH1D named "name" exists in the current directory or pad,
1630/// the histogram is reset and filled again with the projected contents of the TH3.
1631///
1632/// implemented using Project3D
1633
1634TH1D *TH3::ProjectionZ(const char *name, Int_t ixmin, Int_t ixmax,
1635 Int_t iymin, Int_t iymax, Option_t *option) const
1636{
1637
1638 TString hname = name;
1639 if (hname == "_pz") hname = TString::Format("%s%s", GetName(), name);
1640 TString title = TString::Format("%s ( Projection Z )",GetTitle());
1641
1642 // when projecting in Z outer axis are X and Y (order is important. It is defined in the DoProject1D function)
1643 return DoProject1D(hname, title, ixmin, ixmax, iymin, iymax, &fZaxis, &fXaxis, &fYaxis, option);
1644}
1645
1646
1647////////////////////////////////////////////////////////////////////////////////
1648/// internal method performing the projection to 1D histogram
1649/// called from TH3::Project3D
1650
1651TH1D *TH3::DoProject1D(const char* name, const char * title, int imin1, int imax1, int imin2, int imax2,
1652 const TAxis* projAxis, const TAxis * axis1, const TAxis * axis2, Option_t * option) const
1653{
1654
1655 TString opt = option;
1656 opt.ToLower();
1657
1658 // save previous axis range and bits
1659 // Int_t iminOld1 = axis1->GetFirst();
1660 // Int_t imaxOld1 = axis1->GetLast();
1661 // Int_t iminOld2 = axis2->GetFirst();
1662 // Int_t imaxOld2 = axis2->GetLast();
1663 // Bool_t hadRange1 = axis1->TestBit(TAxis::kAxisRange);
1664 // Bool_t hadRange2 = axis2->TestBit(TAxis::kAxisRange);
1665
1666 // need to cast-away constness to set range
1667 TAxis out1(*axis1);
1668 TAxis out2(*axis2);
1669 // const_cast<TAxis *>(axis1)->SetRange(imin1, imax1);
1670 // const_cast<TAxis*>(axis2)->SetRange(imin2,imax2);
1671 out1.SetRange(imin1, imax1);
1672 out2.SetRange(imin2, imax2);
1673
1674 Bool_t computeErrors = GetSumw2N();
1675 if (opt.Contains("e") ) {
1676 computeErrors = kTRUE;
1677 opt.Remove(opt.First("e"),1);
1678 }
1679 Bool_t originalRange = kFALSE;
1680 if (opt.Contains('o') ) {
1681 originalRange = kTRUE;
1682 opt.Remove(opt.First("o"),1);
1683 }
1684
1685 TH1D * h1 = DoProject1D(name, title, projAxis, &out1, &out2, computeErrors, originalRange,true,true);
1686
1687 // // restore original range
1688 // if (axis1->TestBit(TAxis::kAxisRange)) {
1689 // if (hadRange1) const_cast<TAxis*>(axis1)->SetRange(iminOld1,imaxOld1);
1690 // if (axis2->TestBit(TAxis::kAxisRange)) const_cast<TAxis*>(axis2)->SetRange(iminOld2,imaxOld2);
1691 // // we need also to restore the original bits
1692
1693 // draw in current pad
1694 if (h1 && opt.Contains("d")) {
1695 opt.Remove(opt.First("d"),1);
1696 TVirtualPad *padsav = gPad;
1697 TVirtualPad *pad = gROOT->GetSelectedPad();
1698 if (pad) pad->cd();
1699 if (!gPad || !gPad->FindObject(h1)) {
1700 h1->Draw(opt);
1701 } else {
1702 h1->Paint(opt);
1703 }
1704 if (padsav) padsav->cd();
1705 }
1706
1707 return h1;
1708}
1709
1710////////////////////////////////////////////////////////////////////////////////
1711/// internal methdod performing the projection to 1D histogram
1712/// called from other TH3::DoProject1D
1713
1714TH1D *TH3::DoProject1D(const char* name, const char * title, const TAxis* projX,
1715 const TAxis * out1, const TAxis * out2,
1716 bool computeErrors, bool originalRange,
1717 bool useUF, bool useOF) const
1718{
1719 // Create the projection histogram
1720 TH1D *h1 = 0;
1721
1722 // Get range to use as well as bin limits
1723 // Projected range must be inside and not outside original one (ROOT-8781)
1724 Int_t ixmin = std::max(projX->GetFirst(),1);
1725 Int_t ixmax = std::min(projX->GetLast(),projX->GetNbins());
1726 Int_t nx = ixmax-ixmin+1;
1727
1728 // Create the histogram, either reseting a preexisting one
1729 TObject *h1obj = gROOT->FindObject(name);
1730 if (h1obj && h1obj->InheritsFrom(TH1::Class())) {
1731 if (h1obj->IsA() != TH1D::Class() ) {
1732 Error("DoProject1D","Histogram with name %s must be a TH1D and is a %s",name,h1obj->ClassName());
1733 return 0;
1734 }
1735 h1 = (TH1D*)h1obj;
1736 // reset histogram and re-set the axis in any case
1737 h1->Reset();
1738 const TArrayD *bins = projX->GetXbins();
1739 if ( originalRange )
1740 {
1741 if (bins->fN == 0) {
1742 h1->SetBins(projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
1743 } else {
1744 h1->SetBins(projX->GetNbins(),bins->fArray);
1745 }
1746 } else {
1747 if (bins->fN == 0) {
1748 h1->SetBins(nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
1749 } else {
1750 h1->SetBins(nx,&bins->fArray[ixmin-1]);
1751 }
1752 }
1753 }
1754
1755 if (!h1) {
1756 const TArrayD *bins = projX->GetXbins();
1757 if ( originalRange )
1758 {
1759 if (bins->fN == 0) {
1760 h1 = new TH1D(name,title,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
1761 } else {
1762 h1 = new TH1D(name,title,projX->GetNbins(),bins->fArray);
1763 }
1764 } else {
1765 if (bins->fN == 0) {
1766 h1 = new TH1D(name,title,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
1767 } else {
1768 h1 = new TH1D(name,title,nx,&bins->fArray[ixmin-1]);
1769 }
1770 }
1771 }
1772
1773 // Copy the axis attributes and the axis labels if needed.
1774 h1->GetXaxis()->ImportAttributes(projX);
1775 THashList* labels = projX->GetLabels();
1776 if (labels) {
1777 TIter iL(labels);
1778 TObjString* lb;
1779 Int_t i = 1;
1780 while ((lb=(TObjString*)iL())) {
1781 h1->GetXaxis()->SetBinLabel(i,lb->String().Data());
1782 i++;
1783 }
1784 }
1785 h1->SetLineColor(this->GetLineColor());
1786 h1->SetFillColor(this->GetFillColor());
1787 h1->SetMarkerColor(this->GetMarkerColor());
1788 h1->SetMarkerStyle(this->GetMarkerStyle());
1789
1790 // Activate errors
1791 if ( computeErrors && (h1->GetSumw2N() != h1->GetNcells() ) ) h1->Sumw2();
1792
1793 // Set references to the axies in case out1 or out2 ar enot provided
1794 // and one can use the histogram axis given projX
1795 if (out1 == nullptr && out2 == nullptr) {
1796 if (projX == GetXaxis()) {
1797 out1 = GetYaxis();
1798 out2 = GetZaxis();
1799 } else if (projX == GetYaxis()) {
1800 out1 = GetXaxis();
1801 out2 = GetZaxis();
1802 } else {
1803 out1 = GetXaxis();
1804 out2 = GetYaxis();
1805 }
1806 }
1807 R__ASSERT(out1 != nullptr && out2 != nullptr);
1808
1809 Int_t *refX = 0, *refY = 0, *refZ = 0;
1810 Int_t ixbin, out1bin, out2bin;
1811 if (projX == GetXaxis()) {
1812 refX = &ixbin;
1813 refY = &out1bin;
1814 refZ = &out2bin;
1815 }
1816 if (projX == GetYaxis()) {
1817 refX = &out1bin;
1818 refY = &ixbin;
1819 refZ = &out2bin;
1820 }
1821 if (projX == GetZaxis()) {
1822 refX = &out1bin;
1823 refY = &out2bin;
1824 refZ = &ixbin;
1825 }
1826 R__ASSERT (refX != 0 && refY != 0 && refZ != 0);
1827
1828 // Fill the projected histogram excluding underflow/overflows if considered in the option
1829 // if specified in the option (by default they considered)
1830 Double_t totcont = 0;
1831
1832 Int_t out1min = out1->GetFirst();
1833 Int_t out1max = out1->GetLast();
1834 // GetFirst(), GetLast() can return (0,0) when the range bit is set artificially (see TAxis::SetRange)
1835 //if (out1min == 0 && out1max == 0) { out1min = 1; out1max = out1->GetNbins(); }
1836 // correct for underflow/overflows
1837 if (useUF && !out1->TestBit(TAxis::kAxisRange) ) out1min -= 1;
1838 if (useOF && !out1->TestBit(TAxis::kAxisRange) ) out1max += 1;
1839 Int_t out2min = out2->GetFirst();
1840 Int_t out2max = out2->GetLast();
1841// if (out2min == 0 && out2max == 0) { out2min = 1; out2max = out2->GetNbins(); }
1842 if (useUF && !out2->TestBit(TAxis::kAxisRange) ) out2min -= 1;
1843 if (useOF && !out2->TestBit(TAxis::kAxisRange) ) out2max += 1;
1844
1845 for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++) {
1846 if ( projX->TestBit(TAxis::kAxisRange) && ( ixbin < ixmin || ixbin > ixmax )) continue;
1847
1848 Double_t cont = 0;
1849 Double_t err2 = 0;
1850
1851 // loop on the bins to be integrated (outbin should be called inbin)
1852 for (out1bin = out1min; out1bin <= out1max; out1bin++) {
1853 for (out2bin = out2min; out2bin <= out2max; out2bin++) {
1854
1855 Int_t bin = GetBin(*refX, *refY, *refZ);
1856
1857 // sum the bin contents and errors if needed
1858 cont += RetrieveBinContent(bin);
1859 if (computeErrors) {
1860 Double_t exyz = GetBinError(bin);
1861 err2 += exyz*exyz;
1862 }
1863 }
1864 }
1865 Int_t ix = h1->FindBin( projX->GetBinCenter(ixbin) );
1866 h1->SetBinContent(ix ,cont);
1867 if (computeErrors) h1->SetBinError(ix, TMath::Sqrt(err2) );
1868 // sum all content
1869 totcont += cont;
1870
1871 }
1872
1873 // since we use a combination of fill and SetBinError we need to reset and recalculate the statistics
1874 // for weighted histograms otherwise sumw2 will be wrong.
1875 // We can keep the original statistics from the TH3 if the projected sumw is consistent with original one
1876 // i.e. when no events are thrown away
1877 bool resetStats = true;
1878 double eps = 1.E-12;
1879 if (IsA() == TH3F::Class() ) eps = 1.E-6;
1880 if (fTsumw != 0 && TMath::Abs( fTsumw - totcont) < TMath::Abs(fTsumw) * eps) resetStats = false;
1881
1882 bool resetEntries = resetStats;
1883 // entries are calculated using underflow/overflow. If excluded entries must be reset
1884 resetEntries |= !useUF || !useOF;
1885
1886
1887 if (!resetStats) {
1888 Double_t stats[kNstat];
1889 GetStats(stats);
1890 if ( projX == GetYaxis() ) {
1891 stats[2] = stats[4];
1892 stats[3] = stats[5];
1893 }
1894 else if ( projX == GetZaxis() ) {
1895 stats[2] = stats[7];
1896 stats[3] = stats[8];
1897 }
1898 h1->PutStats(stats);
1899 }
1900 else {
1901 // reset statistics
1902 h1->ResetStats();
1903 }
1904 if (resetEntries) {
1905 // in case of error calculation (i.e. when Sumw2() is set)
1906 // use the effective entries for the entries
1907 // since this is the only way to estimate them
1908 Double_t entries = TMath::Floor( totcont + 0.5); // to avoid numerical rounding
1909 if (computeErrors) entries = h1->GetEffectiveEntries();
1910 h1->SetEntries( entries );
1911 }
1912 else {
1914 }
1915
1916 return h1;
1917}
1918
1919
1920////////////////////////////////////////////////////////////////////////////////
1921/// internal method performing the projection to a 2D histogram
1922/// called from TH3::Project3D
1923
1924TH2D *TH3::DoProject2D(const char* name, const char * title, const TAxis* projX, const TAxis* projY,
1925 bool computeErrors, bool originalRange,
1926 bool useUF, bool useOF) const
1927{
1928 TH2D *h2 = 0;
1929
1930 // Get range to use as well as bin limits
1931 Int_t ixmin = std::max(projX->GetFirst(),1);
1932 Int_t ixmax = std::min(projX->GetLast(),projX->GetNbins());
1933 Int_t iymin = std::max(projY->GetFirst(),1);
1934 Int_t iymax = std::min(projY->GetLast(),projY->GetNbins());
1935
1936 Int_t nx = ixmax-ixmin+1;
1937 Int_t ny = iymax-iymin+1;
1938
1939 // Create the histogram, either reseting a preexisting one
1940 // or creating one from scratch.
1941 // Does an object with the same name exists?
1942 TObject *h2obj = gROOT->FindObject(name);
1943 if (h2obj && h2obj->InheritsFrom(TH1::Class())) {
1944 if ( h2obj->IsA() != TH2D::Class() ) {
1945 Error("DoProject2D","Histogram with name %s must be a TH2D and is a %s",name,h2obj->ClassName());
1946 return 0;
1947 }
1948 h2 = (TH2D*)h2obj;
1949 // reset histogram and its axes
1950 h2->Reset();
1951 const TArrayD *xbins = projX->GetXbins();
1952 const TArrayD *ybins = projY->GetXbins();
1953 if ( originalRange ) {
1954 h2->SetBins(projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
1955 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
1956 // set bins for mixed axis do not exists - need to set afterwards the variable bins
1957 if (ybins->fN != 0)
1958 h2->GetXaxis()->Set(projY->GetNbins(),&ybins->fArray[iymin-1]);
1959 if (xbins->fN != 0)
1960 h2->GetYaxis()->Set(projX->GetNbins(),&xbins->fArray[ixmin-1]);
1961 } else {
1962 h2->SetBins(ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
1963 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
1964 if (ybins->fN != 0)
1965 h2->GetXaxis()->Set(ny,&ybins->fArray[iymin-1]);
1966 if (xbins->fN != 0)
1967 h2->GetYaxis()->Set(nx,&xbins->fArray[ixmin-1]);
1968 }
1969 }
1970
1971
1972 if (!h2) {
1973 const TArrayD *xbins = projX->GetXbins();
1974 const TArrayD *ybins = projY->GetXbins();
1975 if ( originalRange )
1976 {
1977 if (xbins->fN == 0 && ybins->fN == 0) {
1978 h2 = new TH2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
1979 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
1980 } else if (ybins->fN == 0) {
1981 h2 = new TH2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
1982 ,projX->GetNbins(),&xbins->fArray[ixmin-1]);
1983 } else if (xbins->fN == 0) {
1984 h2 = new TH2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1]
1985 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
1986 } else {
1987 h2 = new TH2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1],projX->GetNbins(),&xbins->fArray[ixmin-1]);
1988 }
1989 } else {
1990 if (xbins->fN == 0 && ybins->fN == 0) {
1991 h2 = new TH2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
1992 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
1993 } else if (ybins->fN == 0) {
1994 h2 = new TH2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
1995 ,nx,&xbins->fArray[ixmin-1]);
1996 } else if (xbins->fN == 0) {
1997 h2 = new TH2D(name,title,ny,&ybins->fArray[iymin-1]
1998 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
1999 } else {
2000 h2 = new TH2D(name,title,ny,&ybins->fArray[iymin-1],nx,&xbins->fArray[ixmin-1]);
2001 }
2002 }
2003 }
2004
2005 // Copy the axis attributes and the axis labels if needed.
2006 THashList* labels1 = 0;
2007 THashList* labels2 = 0;
2008 // "xy"
2009 h2->GetXaxis()->ImportAttributes(projY);
2010 h2->GetYaxis()->ImportAttributes(projX);
2011 labels1 = projY->GetLabels();
2012 labels2 = projX->GetLabels();
2013 if (labels1) {
2014 TIter iL(labels1);
2015 TObjString* lb;
2016 Int_t i = 1;
2017 while ((lb=(TObjString*)iL())) {
2018 h2->GetXaxis()->SetBinLabel(i,lb->String().Data());
2019 i++;
2020 }
2021 }
2022 if (labels2) {
2023 TIter iL(labels2);
2024 TObjString* lb;
2025 Int_t i = 1;
2026 while ((lb=(TObjString*)iL())) {
2027 h2->GetYaxis()->SetBinLabel(i,lb->String().Data());
2028 i++;
2029 }
2030 }
2031 h2->SetLineColor(this->GetLineColor());
2032 h2->SetFillColor(this->GetFillColor());
2033 h2->SetMarkerColor(this->GetMarkerColor());
2034 h2->SetMarkerStyle(this->GetMarkerStyle());
2035
2036 // Activate errors
2037 if ( computeErrors && (h2->GetSumw2N() != h2->GetNcells()) ) h2->Sumw2();
2038
2039 // Set references to the axis, so that the bucle has no branches.
2040 const TAxis* out = 0;
2041 if ( projX != GetXaxis() && projY != GetXaxis() ) {
2042 out = GetXaxis();
2043 } else if ( projX != GetYaxis() && projY != GetYaxis() ) {
2044 out = GetYaxis();
2045 } else {
2046 out = GetZaxis();
2047 }
2048
2049 Int_t *refX = 0, *refY = 0, *refZ = 0;
2050 Int_t ixbin, iybin, outbin;
2051 if ( projX == GetXaxis() && projY == GetYaxis() ) { refX = &ixbin; refY = &iybin; refZ = &outbin; }
2052 if ( projX == GetYaxis() && projY == GetXaxis() ) { refX = &iybin; refY = &ixbin; refZ = &outbin; }
2053 if ( projX == GetXaxis() && projY == GetZaxis() ) { refX = &ixbin; refY = &outbin; refZ = &iybin; }
2054 if ( projX == GetZaxis() && projY == GetXaxis() ) { refX = &iybin; refY = &outbin; refZ = &ixbin; }
2055 if ( projX == GetYaxis() && projY == GetZaxis() ) { refX = &outbin; refY = &ixbin; refZ = &iybin; }
2056 if ( projX == GetZaxis() && projY == GetYaxis() ) { refX = &outbin; refY = &iybin; refZ = &ixbin; }
2057 R__ASSERT (refX != 0 && refY != 0 && refZ != 0);
2058
2059 // Fill the projected histogram excluding underflow/overflows if considered in the option
2060 // if specified in the option (by default they considered)
2061 Double_t totcont = 0;
2062
2063 Int_t outmin = out->GetFirst();
2064 Int_t outmax = out->GetLast();
2065 // GetFirst(), GetLast() can return (0,0) when the range bit is set artificially (see TAxis::SetRange)
2066 if (outmin == 0 && outmax == 0) { outmin = 1; outmax = out->GetNbins(); }
2067 // correct for underflow/overflows
2068 if (useUF && !out->TestBit(TAxis::kAxisRange) ) outmin -= 1;
2069 if (useOF && !out->TestBit(TAxis::kAxisRange) ) outmax += 1;
2070
2071 for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++) {
2072 if ( projX->TestBit(TAxis::kAxisRange) && ( ixbin < ixmin || ixbin > ixmax )) continue;
2073 Int_t ix = h2->GetYaxis()->FindBin( projX->GetBinCenter(ixbin) );
2074
2075 for (iybin=0;iybin<=1+projY->GetNbins();iybin++) {
2076 if ( projY->TestBit(TAxis::kAxisRange) && ( iybin < iymin || iybin > iymax )) continue;
2077 Int_t iy = h2->GetXaxis()->FindBin( projY->GetBinCenter(iybin) );
2078
2079 Double_t cont = 0;
2080 Double_t err2 = 0;
2081
2082 // loop on the bins to be integrated (outbin should be called inbin)
2083 for (outbin = outmin; outbin <= outmax; outbin++) {
2084
2085 Int_t bin = GetBin(*refX,*refY,*refZ);
2086
2087 // sum the bin contents and errors if needed
2088 cont += RetrieveBinContent(bin);
2089 if (computeErrors) {
2090 Double_t exyz = GetBinError(bin);
2091 err2 += exyz*exyz;
2092 }
2093
2094 }
2095
2096 // remember axis are inverted
2097 h2->SetBinContent(iy , ix, cont);
2098 if (computeErrors) h2->SetBinError(iy, ix, TMath::Sqrt(err2) );
2099 // sum all content
2100 totcont += cont;
2101
2102 }
2103 }
2104
2105 // since we use fill we need to reset and recalculate the statistics (see comment in DoProject1D )
2106 // or keep original statistics if consistent sumw2
2107 bool resetStats = true;
2108 double eps = 1.E-12;
2109 if (IsA() == TH3F::Class() ) eps = 1.E-6;
2110 if (fTsumw != 0 && TMath::Abs( fTsumw - totcont) < TMath::Abs(fTsumw) * eps) resetStats = false;
2111
2112 bool resetEntries = resetStats;
2113 // entries are calculated using underflow/overflow. If excluded entries must be reset
2114 resetEntries |= !useUF || !useOF;
2115
2116 if (!resetStats) {
2117 Double_t stats[kNstat];
2118 Double_t oldst[kNstat]; // old statistics
2119 for (Int_t i = 0; i < kNstat; ++i) { oldst[i] = 0; }
2120 GetStats(oldst);
2121 std::copy(oldst,oldst+kNstat,stats);
2122 // not that projX refer to Y axis and projX refer to the X axis of projected histogram
2123 // nothing to do for projection in Y vs X
2124 if ( projY == GetXaxis() && projX == GetZaxis() ) { // case XZ
2125 stats[4] = oldst[7];
2126 stats[5] = oldst[8];
2127 stats[6] = oldst[9];
2128 }
2129 if ( projY == GetYaxis() ) {
2130 stats[2] = oldst[4];
2131 stats[3] = oldst[5];
2132 if ( projX == GetXaxis() ) { // case YX
2133 stats[4] = oldst[2];
2134 stats[5] = oldst[3];
2135 }
2136 if ( projX == GetZaxis() ) { // case YZ
2137 stats[4] = oldst[7];
2138 stats[5] = oldst[8];
2139 stats[6] = oldst[10];
2140 }
2141 }
2142 else if ( projY == GetZaxis() ) {
2143 stats[2] = oldst[7];
2144 stats[3] = oldst[8];
2145 if ( projX == GetXaxis() ) { // case ZX
2146 stats[4] = oldst[2];
2147 stats[5] = oldst[3];
2148 stats[6] = oldst[9];
2149 }
2150 if ( projX == GetYaxis() ) { // case ZY
2151 stats[4] = oldst[4];
2152 stats[5] = oldst[5];
2153 stats[6] = oldst[10];
2154 }
2155 }
2156 // set the new statistics
2157 h2->PutStats(stats);
2158 }
2159 else {
2160 // recalculate the statistics
2161 h2->ResetStats();
2162 }
2163
2164 if (resetEntries) {
2165 // use the effective entries for the entries
2166 // since this is the only way to estimate them
2167 Double_t entries = h2->GetEffectiveEntries();
2168 if (!computeErrors) entries = TMath::Floor( entries + 0.5); // to avoid numerical rounding
2169 h2->SetEntries( entries );
2170 }
2171 else {
2172 h2->SetEntries( fEntries );
2173 }
2174
2175
2176 return h2;
2177}
2178
2179
2180////////////////////////////////////////////////////////////////////////////////
2181/// Project a 3-d histogram into 1 or 2-d histograms depending on the
2182/// option parameter, which may contain a combination of the characters x,y,z,e
2183/// - option = "x" return the x projection into a TH1D histogram
2184/// - option = "y" return the y projection into a TH1D histogram
2185/// - option = "z" return the z projection into a TH1D histogram
2186/// - option = "xy" return the x versus y projection into a TH2D histogram
2187/// - option = "yx" return the y versus x projection into a TH2D histogram
2188/// - option = "xz" return the x versus z projection into a TH2D histogram
2189/// - option = "zx" return the z versus x projection into a TH2D histogram
2190/// - option = "yz" return the y versus z projection into a TH2D histogram
2191/// - option = "zy" return the z versus y projection into a TH2D histogram
2192///
2193/// NB: the notation "a vs b" means "a" vertical and "b" horizontal
2194///
2195/// option = "o" original axis range of the target axes will be
2196/// kept, but only bins inside the selected range will be filled.
2197///
2198/// If option contains the string "e", errors are computed
2199///
2200/// The projection is made for the selected bins only.
2201/// To select a bin range along an axis, use TAxis::SetRange, eg
2202/// h3.GetYaxis()->SetRange(23,56);
2203///
2204/// NOTE 1: The generated histogram is named th3name + option
2205/// eg if the TH3* h histogram is named "myhist", then
2206/// h->Project3D("xy"); produces a TH2D histogram named "myhist_xy"
2207/// if a histogram of the same type already exists, it is overwritten.
2208/// The following sequence
2209/// h->Project3D("xy");
2210/// h->Project3D("xy2");
2211/// will generate two TH2D histograms named "myhist_xy" and "myhist_xy2"
2212/// A different name can be generated by attaching a string to the option
2213/// For example h->Project3D("name_xy") will generate an histogram with the name: h3dname_name_xy.
2214///
2215/// NOTE 2: If an histogram of the same type already exists,
2216/// the histogram is reset and filled again with the projected contents of the TH3.
2217///
2218/// NOTE 3: The number of entries in the projected histogram is estimated from the number of
2219/// effective entries for all the cells included in the projection.
2220///
2221/// NOTE 4: underflow/overflow are included by default in the projection
2222/// To exclude underflow and/or overflow (for both axis in case of a projection to a 1D histogram) use option "NUF" and/or "NOF"
2223/// With SetRange() you can have all bins except underflow/overflow only if you set the axis bit range as
2224/// following after having called SetRange: axis->SetRange(1, axis->GetNbins());
2225
2227{
2228 TString opt = option; opt.ToLower();
2229 Int_t pcase = 0;
2230 TString ptype;
2231 if (opt.Contains("x")) { pcase = 1; ptype = "x"; }
2232 if (opt.Contains("y")) { pcase = 2; ptype = "y"; }
2233 if (opt.Contains("z")) { pcase = 3; ptype = "z"; }
2234 if (opt.Contains("xy")) { pcase = 4; ptype = "xy"; }
2235 if (opt.Contains("yx")) { pcase = 5; ptype = "yx"; }
2236 if (opt.Contains("xz")) { pcase = 6; ptype = "xz"; }
2237 if (opt.Contains("zx")) { pcase = 7; ptype = "zx"; }
2238 if (opt.Contains("yz")) { pcase = 8; ptype = "yz"; }
2239 if (opt.Contains("zy")) { pcase = 9; ptype = "zy"; }
2240
2241 if (pcase == 0) {
2242 Error("Project3D","No projection axis specified - return a NULL pointer");
2243 return 0;
2244 }
2245 // do not remove ptype from opt to use later in the projected histo name
2246
2247 Bool_t computeErrors = GetSumw2N();
2248 if (opt.Contains("e") ) {
2249 computeErrors = kTRUE;
2250 opt.Remove(opt.First("e"),1);
2251 }
2252
2253 Bool_t useUF = kTRUE;
2254 Bool_t useOF = kTRUE;
2255 if (opt.Contains("nuf") ) {
2256 useUF = kFALSE;
2257 opt.Remove(opt.Index("nuf"),3);
2258 }
2259 if (opt.Contains("nof") ) {
2260 useOF = kFALSE;
2261 opt.Remove(opt.Index("nof"),3);
2262 }
2263
2264 Bool_t originalRange = kFALSE;
2265 if (opt.Contains('o') ) {
2266 originalRange = kTRUE;
2267 opt.Remove(opt.First("o"),1);
2268 }
2269
2270
2271 // Create the projection histogram
2272 TH1 *h = 0;
2273
2274 TString name = GetName();
2275 TString title = GetTitle();
2276 name += "_"; name += opt; // opt may include a user defined name
2277 title += " "; title += ptype; title += " projection";
2278
2279 switch (pcase) {
2280 case 1:
2281 // "x"
2282 h = DoProject1D(name, title, this->GetXaxis(), nullptr, nullptr,
2283 computeErrors, originalRange, useUF, useOF);
2284 break;
2285
2286 case 2:
2287 // "y"
2288 h = DoProject1D(name, title, this->GetYaxis(), nullptr, nullptr,
2289 computeErrors, originalRange, useUF, useOF);
2290 break;
2291
2292 case 3:
2293 // "z"
2294 h = DoProject1D(name, title, this->GetZaxis(), nullptr, nullptr,
2295 computeErrors, originalRange, useUF, useOF);
2296 break;
2297
2298 case 4:
2299 // "xy"
2300 h = DoProject2D(name, title, this->GetXaxis(),this->GetYaxis(),
2301 computeErrors, originalRange, useUF, useOF);
2302 break;
2303
2304 case 5:
2305 // "yx"
2306 h = DoProject2D(name, title, this->GetYaxis(),this->GetXaxis(),
2307 computeErrors, originalRange, useUF, useOF);
2308 break;
2309
2310 case 6:
2311 // "xz"
2312 h = DoProject2D(name, title, this->GetXaxis(),this->GetZaxis(),
2313 computeErrors, originalRange, useUF, useOF);
2314 break;
2315
2316 case 7:
2317 // "zx"
2318 h = DoProject2D(name, title, this->GetZaxis(),this->GetXaxis(),
2319 computeErrors, originalRange, useUF, useOF);
2320 break;
2321
2322 case 8:
2323 // "yz"
2324 h = DoProject2D(name, title, this->GetYaxis(),this->GetZaxis(),
2325 computeErrors, originalRange, useUF, useOF);
2326 break;
2327
2328 case 9:
2329 // "zy"
2330 h = DoProject2D(name, title, this->GetZaxis(),this->GetYaxis(),
2331 computeErrors, originalRange, useUF, useOF);
2332 break;
2333
2334 }
2335
2336 // draw in current pad
2337 if (h && opt.Contains("d")) {
2338 opt.Remove(opt.First("d"),1);
2339 TVirtualPad *padsav = gPad;
2340 TVirtualPad *pad = gROOT->GetSelectedPad();
2341 if (pad) pad->cd();
2342 if (!gPad || !gPad->FindObject(h)) {
2343 h->Draw(opt);
2344 } else {
2345 h->Paint(opt);
2346 }
2347 if (padsav) padsav->cd();
2348 }
2349
2350 return h;
2351}
2352
2353
2354////////////////////////////////////////////////////////////////////////////////
2355/// internal function to fill the bins of the projected profile 2D histogram
2356/// called from DoProjectProfile2D
2357
2359 const TAxis & a1, const TAxis & a2, const TAxis & a3,
2360 Int_t bin1, Int_t bin2, Int_t bin3,
2361 Int_t inBin, Bool_t useWeights ) const {
2362 Double_t cont = GetBinContent(inBin);
2363 if (!cont) return;
2364 TArrayD & binSumw2 = *(p2->GetBinSumw2());
2365 if (useWeights && binSumw2.fN <= 0) useWeights = false;
2366 if (!useWeights) p2->SetBit(TH1::kIsNotW); // to use Fill for setting the bin contents of the Profile
2367 // the following fill update wrongly the fBinSumw2- need to save it before
2368 Double_t u = a1.GetBinCenter(bin1);
2369 Double_t v = a2.GetBinCenter(bin2);
2370 Double_t w = a3.GetBinCenter(bin3);
2371 Int_t outBin = p2->FindBin(u, v);
2372 if (outBin <0) return;
2373 Double_t tmp = 0;
2374 if ( useWeights ) tmp = binSumw2.fArray[outBin];
2375 p2->Fill( u , v, w, cont);
2376 if (useWeights ) binSumw2.fArray[outBin] = tmp + fSumw2.fArray[inBin];
2377}
2378
2379
2380////////////////////////////////////////////////////////////////////////////////
2381/// internal method to project to a 2D Profile
2382/// called from TH3::Project3DProfile
2383
2384TProfile2D *TH3::DoProjectProfile2D(const char* name, const char * title, const TAxis* projX, const TAxis* projY,
2385 bool originalRange, bool useUF, bool useOF) const
2386{
2387 // Get the ranges where we will work.
2388 Int_t ixmin = std::max(projX->GetFirst(),1);
2389 Int_t ixmax = std::min(projX->GetLast(),projX->GetNbins());
2390 Int_t iymin = std::max(projY->GetFirst(),1);
2391 Int_t iymax = std::min(projY->GetLast(),projY->GetNbins());
2392
2393 Int_t nx = ixmax-ixmin+1;
2394 Int_t ny = iymax-iymin+1;
2395
2396 // Create the projected profiles
2397 TProfile2D *p2 = 0;
2398
2399 // Create the histogram, either reseting a preexisting one
2400 // Does an object with the same name exists?
2401 TObject *p2obj = gROOT->FindObject(name);
2402 if (p2obj && p2obj->InheritsFrom(TH1::Class())) {
2403 if (p2obj->IsA() != TProfile2D::Class() ) {
2404 Error("DoProjectProfile2D","Histogram with name %s must be a TProfile2D and is a %s",name,p2obj->ClassName());
2405 return 0;
2406 }
2407 p2 = (TProfile2D*)p2obj;
2408 // reset existing profile and re-set bins
2409 p2->Reset();
2410 const TArrayD *xbins = projX->GetXbins();
2411 const TArrayD *ybins = projY->GetXbins();
2412 if ( originalRange ) {
2413 p2->SetBins(projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
2414 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
2415 // set bins for mixed axis do not exists - need to set afterwards the variable bins
2416 if (ybins->fN != 0)
2417 p2->GetXaxis()->Set(projY->GetNbins(),&ybins->fArray[iymin-1]);
2418 if (xbins->fN != 0)
2419 p2->GetYaxis()->Set(projX->GetNbins(),&xbins->fArray[ixmin-1]);
2420 } else {
2421 p2->SetBins(ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
2422 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
2423 if (ybins->fN != 0)
2424 p2->GetXaxis()->Set(ny,&ybins->fArray[iymin-1]);
2425 if (xbins->fN != 0)
2426 p2->GetYaxis()->Set(nx,&xbins->fArray[ixmin-1]);
2427 }
2428 }
2429
2430 if (!p2) {
2431 const TArrayD *xbins = projX->GetXbins();
2432 const TArrayD *ybins = projY->GetXbins();
2433 if ( originalRange ) {
2434 if (xbins->fN == 0 && ybins->fN == 0) {
2435 p2 = new TProfile2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
2436 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
2437 } else if (ybins->fN == 0) {
2438 p2 = new TProfile2D(name,title,projY->GetNbins(),projY->GetXmin(),projY->GetXmax()
2439 ,projX->GetNbins(),&xbins->fArray[ixmin-1]);
2440 } else if (xbins->fN == 0) {
2441 p2 = new TProfile2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1]
2442 ,projX->GetNbins(),projX->GetXmin(),projX->GetXmax());
2443 } else {
2444 p2 = new TProfile2D(name,title,projY->GetNbins(),&ybins->fArray[iymin-1],projX->GetNbins(),&xbins->fArray[ixmin-1]);
2445 }
2446 } else {
2447 if (xbins->fN == 0 && ybins->fN == 0) {
2448 p2 = new TProfile2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
2449 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
2450 } else if (ybins->fN == 0) {
2451 p2 = new TProfile2D(name,title,ny,projY->GetBinLowEdge(iymin),projY->GetBinUpEdge(iymax)
2452 ,nx,&xbins->fArray[ixmin-1]);
2453 } else if (xbins->fN == 0) {
2454 p2 = new TProfile2D(name,title,ny,&ybins->fArray[iymin-1]
2455 ,nx,projX->GetBinLowEdge(ixmin),projX->GetBinUpEdge(ixmax));
2456 } else {
2457 p2 = new TProfile2D(name,title,ny,&ybins->fArray[iymin-1],nx,&xbins->fArray[ixmin-1]);
2458 }
2459 }
2460 }
2461
2462 // Set references to the axis, so that the loop has no branches.
2463 const TAxis* outAxis = 0;
2464 if ( projX != GetXaxis() && projY != GetXaxis() ) {
2465 outAxis = GetXaxis();
2466 } else if ( projX != GetYaxis() && projY != GetYaxis() ) {
2467 outAxis = GetYaxis();
2468 } else {
2469 outAxis = GetZaxis();
2470 }
2471
2472 // Weights management
2473 bool useWeights = (GetSumw2N() > 0);
2474 // store sum of w2 in profile if histo is weighted
2475 if (useWeights && (p2->GetBinSumw2()->fN != p2->GetNcells() ) ) p2->Sumw2();
2476
2477 // Set references to the bins, so that the loop has no branches.
2478 Int_t *refX = 0, *refY = 0, *refZ = 0;
2479 Int_t ixbin, iybin, outbin;
2480 if ( projX == GetXaxis() && projY == GetYaxis() ) { refX = &ixbin; refY = &iybin; refZ = &outbin; }
2481 if ( projX == GetYaxis() && projY == GetXaxis() ) { refX = &iybin; refY = &ixbin; refZ = &outbin; }
2482 if ( projX == GetXaxis() && projY == GetZaxis() ) { refX = &ixbin; refY = &outbin; refZ = &iybin; }
2483 if ( projX == GetZaxis() && projY == GetXaxis() ) { refX = &iybin; refY = &outbin; refZ = &ixbin; }
2484 if ( projX == GetYaxis() && projY == GetZaxis() ) { refX = &outbin; refY = &ixbin; refZ = &iybin; }
2485 if ( projX == GetZaxis() && projY == GetYaxis() ) { refX = &outbin; refY = &iybin; refZ = &ixbin; }
2486 R__ASSERT (refX != 0 && refY != 0 && refZ != 0);
2487
2488 Int_t outmin = outAxis->GetFirst();
2489 Int_t outmax = outAxis->GetLast();
2490 // GetFirst, GetLast can return underflow or overflow bins
2491 // correct for underflow/overflows
2492 if (useUF && !outAxis->TestBit(TAxis::kAxisRange) ) outmin -= 1;
2493 if (useOF && !outAxis->TestBit(TAxis::kAxisRange) ) outmax += 1;
2494
2495 TArrayD & binSumw2 = *(p2->GetBinSumw2());
2496 if (useWeights && binSumw2.fN <= 0) useWeights = false;
2497 if (!useWeights) p2->SetBit(TH1::kIsNotW);
2498
2499 // Call specific method for the projection
2500 for (ixbin=0;ixbin<=1+projX->GetNbins();ixbin++) {
2501 if ( (ixbin < ixmin || ixbin > ixmax) && projX->TestBit(TAxis::kAxisRange)) continue;
2502 for ( iybin=0;iybin<=1+projY->GetNbins();iybin++) {
2503 if ( (iybin < iymin || iybin > iymax) && projX->TestBit(TAxis::kAxisRange)) continue;
2504
2505 // profile output bin
2506 Int_t poutBin = p2->FindBin(projY->GetBinCenter(iybin), projX->GetBinCenter(ixbin));
2507 if (poutBin <0) continue;
2508 // loop on the bins to be integrated (outbin should be called inbin)
2509 for (outbin = outmin; outbin <= outmax; outbin++) {
2510
2511 Int_t bin = GetBin(*refX,*refY,*refZ);
2512
2513 //DoFillProfileProjection(p2, *projY, *projX, *outAxis, iybin, ixbin, outbin, bin, useWeights);
2514
2515 Double_t cont = RetrieveBinContent(bin);
2516 if (!cont) continue;
2517
2518 Double_t tmp = 0;
2519 // the following fill update wrongly the fBinSumw2- need to save it before
2520 if ( useWeights ) tmp = binSumw2.fArray[poutBin];
2521 p2->Fill( projY->GetBinCenter(iybin) , projX->GetBinCenter(ixbin), outAxis->GetBinCenter(outbin), cont);
2522 if (useWeights ) binSumw2.fArray[poutBin] = tmp + fSumw2.fArray[bin];
2523
2524 }
2525 }
2526 }
2527
2528 // recompute statistics for the projected profiles
2529 // forget about preserving old statistics
2530 bool resetStats = true;
2531 Double_t stats[kNstat];
2532 // reset statistics
2533 if (resetStats)
2534 for (Int_t i=0;i<kNstat;i++) stats[i] = 0;
2535
2536 p2->PutStats(stats);
2537 Double_t entries = fEntries;
2538 // recalculate the statistics
2539 if (resetStats) {
2540 entries = p2->GetEffectiveEntries();
2541 if (!useWeights) entries = TMath::Floor( entries + 0.5); // to avoid numerical rounding
2542 p2->SetEntries( entries );
2543 }
2544
2545 p2->SetEntries(entries);
2546
2547 return p2;
2548}
2549
2550
2551////////////////////////////////////////////////////////////////////////////////
2552/// Project a 3-d histogram into a 2-d profile histograms depending
2553/// on the option parameter
2554/// option may contain a combination of the characters x,y,z
2555/// option = "xy" return the x versus y projection into a TProfile2D histogram
2556/// option = "yx" return the y versus x projection into a TProfile2D histogram
2557/// option = "xz" return the x versus z projection into a TProfile2D histogram
2558/// option = "zx" return the z versus x projection into a TProfile2D histogram
2559/// option = "yz" return the y versus z projection into a TProfile2D histogram
2560/// option = "zy" return the z versus y projection into a TProfile2D histogram
2561/// NB: the notation "a vs b" means "a" vertical and "b" horizontal
2562///
2563/// option = "o" original axis range of the target axes will be
2564/// kept, but only bins inside the selected range will be filled.
2565///
2566/// The projection is made for the selected bins only.
2567/// To select a bin range along an axis, use TAxis::SetRange, eg
2568/// h3.GetYaxis()->SetRange(23,56);
2569///
2570/// NOTE 1: The generated histogram is named th3name + "_p" + option
2571/// eg if the TH3* h histogram is named "myhist", then
2572/// h->Project3D("xy"); produces a TProfile2D histogram named "myhist_pxy".
2573/// The following sequence
2574/// h->Project3DProfile("xy");
2575/// h->Project3DProfile("xy2");
2576/// will generate two TProfile2D histograms named "myhist_pxy" and "myhist_pxy2"
2577/// So, passing additional characters in the option string one can customize the name.
2578///
2579/// NOTE 2: If a profile of the same type already exists with compatible axes,
2580/// the profile is reset and filled again with the projected contents of the TH3.
2581/// In the case of axes incompatibility, an error is reported and a NULL pointer is returned.
2582///
2583/// NOTE 3: The number of entries in the projected profile is estimated from the number of
2584/// effective entries for all the cells included in the projection.
2585///
2586/// NOTE 4: underflow/overflow are by default excluded from the projection
2587/// (Note that this is a different default behavior compared to the projection to an histogram)
2588/// To include the underflow and/or overflow use option "UF" and/or "OF"
2589
2591{
2592 TString opt = option; opt.ToLower();
2593 Int_t pcase = 0;
2594 TString ptype;
2595 if (opt.Contains("xy")) { pcase = 4; ptype = "xy"; }
2596 if (opt.Contains("yx")) { pcase = 5; ptype = "yx"; }
2597 if (opt.Contains("xz")) { pcase = 6; ptype = "xz"; }
2598 if (opt.Contains("zx")) { pcase = 7; ptype = "zx"; }
2599 if (opt.Contains("yz")) { pcase = 8; ptype = "yz"; }
2600 if (opt.Contains("zy")) { pcase = 9; ptype = "zy"; }
2601
2602 if (pcase == 0) {
2603 Error("Project3D","No projection axis specified - return a NULL pointer");
2604 return 0;
2605 }
2606 // do not remove ptype from opt to use later in the projected histo name
2607
2608 Bool_t useUF = kFALSE;
2609 if (opt.Contains("uf") ) {
2610 useUF = kTRUE;
2611 opt.Remove(opt.Index("uf"),2);
2612 }
2613 Bool_t useOF = kFALSE;
2614 if (opt.Contains("of") ) {
2615 useOF = kTRUE;
2616 opt.Remove(opt.Index("of"),2);
2617 }
2618
2619 Bool_t originalRange = kFALSE;
2620 if (opt.Contains('o') ) {
2621 originalRange = kTRUE;
2622 opt.Remove(opt.First("o"),1);
2623 }
2624
2625 // Create the projected profile
2626 TProfile2D *p2 = 0;
2627 TString name = GetName();
2628 TString title = GetTitle();
2629 name += "_p"; name += opt; // opt may include a user defined name
2630 title += " profile "; title += ptype; title += " projection";
2631
2632 // Call the method with the specific projected axes.
2633 switch (pcase) {
2634 case 4:
2635 // "xy"
2636 p2 = DoProjectProfile2D(name, title, GetXaxis(), GetYaxis(), originalRange, useUF, useOF);
2637 break;
2638
2639 case 5:
2640 // "yx"
2641 p2 = DoProjectProfile2D(name, title, GetYaxis(), GetXaxis(), originalRange, useUF, useOF);
2642 break;
2643
2644 case 6:
2645 // "xz"
2646 p2 = DoProjectProfile2D(name, title, GetXaxis(), GetZaxis(), originalRange, useUF, useOF);
2647 break;
2648
2649 case 7:
2650 // "zx"
2651 p2 = DoProjectProfile2D(name, title, GetZaxis(), GetXaxis(), originalRange, useUF, useOF);
2652 break;
2653
2654 case 8:
2655 // "yz"
2656 p2 = DoProjectProfile2D(name, title, GetYaxis(), GetZaxis(), originalRange, useUF, useOF);
2657 break;
2658
2659 case 9:
2660 // "zy"
2661 p2 = DoProjectProfile2D(name, title, GetZaxis(), GetYaxis(), originalRange, useUF, useOF);
2662 break;
2663
2664 }
2665
2666 return p2;
2667}
2668
2669
2670////////////////////////////////////////////////////////////////////////////////
2671/// Replace current statistics with the values in array stats
2672
2674{
2675 TH1::PutStats(stats);
2676 fTsumwy = stats[4];
2677 fTsumwy2 = stats[5];
2678 fTsumwxy = stats[6];
2679 fTsumwz = stats[7];
2680 fTsumwz2 = stats[8];
2681 fTsumwxz = stats[9];
2682 fTsumwyz = stats[10];
2683}
2684
2685
2686////////////////////////////////////////////////////////////////////////////////
2687/// Rebin only the X axis
2688/// see Rebin3D
2689
2690TH3 *TH3::RebinX(Int_t ngroup, const char *newname)
2691{
2692 return Rebin3D(ngroup, 1, 1, newname);
2693}
2694
2695
2696////////////////////////////////////////////////////////////////////////////////
2697/// Rebin only the Y axis
2698/// see Rebin3D
2699
2700TH3 *TH3::RebinY(Int_t ngroup, const char *newname)
2701{
2702 return Rebin3D(1, ngroup, 1, newname);
2703}
2704
2705
2706////////////////////////////////////////////////////////////////////////////////
2707/// Rebin only the Z axis
2708/// see Rebin3D
2709
2710TH3 *TH3::RebinZ(Int_t ngroup, const char *newname)
2711{
2712 return Rebin3D(1, 1, ngroup, newname);
2713
2714}
2715
2716
2717////////////////////////////////////////////////////////////////////////////////
2718/// Rebin this histogram grouping nxgroup/nygroup/nzgroup bins along the xaxis/yaxis/zaxis together.
2719///
2720/// if newname is not blank a new temporary histogram hnew is created.
2721/// else the current histogram is modified (default)
2722/// The parameter nxgroup/nygroup indicate how many bins along the xaxis/yaxis of this
2723/// have to me merged into one bin of hnew
2724/// If the original histogram has errors stored (via Sumw2), the resulting
2725/// histograms has new errors correctly calculated.
2726///
2727/// examples: if hpxpy is an existing TH3 histogram with 40 x 40 x 40 bins
2728/// hpxpypz->Rebin3D(); // merges two bins along the xaxis and yaxis in one in hpxpypz
2729/// // Carefull: previous contents of hpxpy are lost
2730/// hpxpypz->RebinX(5); //merges five bins along the xaxis in one in hpxpypz
2731/// TH3 *hnew = hpxpypz->RebinY(5,"hnew"); // creates a new histogram hnew
2732/// // merging 5 bins of h1 along the yaxis in one bin
2733///
2734/// NOTE : If nxgroup/nygroup is not an exact divider of the number of bins,
2735/// along the xaxis/yaxis the top limit(s) of the rebinned histogram
2736/// is changed to the upper edge of the xbin=newxbins*nxgroup resp.
2737/// ybin=newybins*nygroup and the corresponding bins are added to
2738/// the overflow bin.
2739/// Statistics will be recomputed from the new bin contents.
2740
2741TH3 *TH3::Rebin3D(Int_t nxgroup, Int_t nygroup, Int_t nzgroup, const char *newname)
2742{
2743 Int_t i,j,k,xbin,ybin,zbin;
2744 Int_t nxbins = fXaxis.GetNbins();
2745 Int_t nybins = fYaxis.GetNbins();
2746 Int_t nzbins = fZaxis.GetNbins();
2751 Double_t zmin = fZaxis.GetXmin();
2752 Double_t zmax = fZaxis.GetXmax();
2753 if ((nxgroup <= 0) || (nxgroup > nxbins)) {
2754 Error("Rebin", "Illegal value of nxgroup=%d",nxgroup);
2755 return 0;
2756 }
2757 if ((nygroup <= 0) || (nygroup > nybins)) {
2758 Error("Rebin", "Illegal value of nygroup=%d",nygroup);
2759 return 0;
2760 }
2761 if ((nzgroup <= 0) || (nzgroup > nzbins)) {
2762 Error("Rebin", "Illegal value of nzgroup=%d",nzgroup);
2763 return 0;
2764 }
2765
2766 Int_t newxbins = nxbins/nxgroup;
2767 Int_t newybins = nybins/nygroup;
2768 Int_t newzbins = nzbins/nzgroup;
2769
2770 // Save old bin contents into a new array
2771 Double_t entries = fEntries;
2772 Double_t *oldBins = new Double_t[fNcells];
2773 for (Int_t ibin = 0; ibin < fNcells; ibin++) {
2774 oldBins[ibin] = RetrieveBinContent(ibin);
2775 }
2776 Double_t *oldSumw2 = 0;
2777 if (fSumw2.fN != 0) {
2778 oldSumw2 = new Double_t[fNcells];
2779 for (Int_t ibin = 0; ibin < fNcells; ibin++) {
2780 oldSumw2[ibin] = fSumw2.fArray[ibin];
2781 }
2782 }
2783
2784 // create a clone of the old histogram if newname is specified
2785 TH3 *hnew = this;
2786 if (newname && strlen(newname)) {
2787 hnew = (TH3*)Clone();
2788 hnew->SetName(newname);
2789 }
2790
2791 // save original statistics
2792 Double_t stat[kNstat];
2793 GetStats(stat);
2794 bool resetStat = false;
2795
2796
2797 // change axis specs and rebuild bin contents array
2798 if (newxbins*nxgroup != nxbins) {
2799 xmax = fXaxis.GetBinUpEdge(newxbins*nxgroup);
2800 resetStat = true; //stats must be reset because top bins will be moved to overflow bin
2801 }
2802 if (newybins*nygroup != nybins) {
2803 ymax = fYaxis.GetBinUpEdge(newybins*nygroup);
2804 resetStat = true; //stats must be reset because top bins will be moved to overflow bin
2805 }
2806 if (newzbins*nzgroup != nzbins) {
2807 zmax = fZaxis.GetBinUpEdge(newzbins*nzgroup);
2808 resetStat = true; //stats must be reset because top bins will be moved to overflow bin
2809 }
2810 // save the TAttAxis members (reset by SetBins) for x axis
2811 Int_t nXdivisions = fXaxis.GetNdivisions();
2812 Color_t xAxisColor = fXaxis.GetAxisColor();
2813 Color_t xLabelColor = fXaxis.GetLabelColor();
2814 Style_t xLabelFont = fXaxis.GetLabelFont();
2815 Float_t xLabelOffset = fXaxis.GetLabelOffset();
2816 Float_t xLabelSize = fXaxis.GetLabelSize();
2817 Float_t xTickLength = fXaxis.GetTickLength();
2818 Float_t xTitleOffset = fXaxis.GetTitleOffset();
2819 Float_t xTitleSize = fXaxis.GetTitleSize();
2820 Color_t xTitleColor = fXaxis.GetTitleColor();
2821 Style_t xTitleFont = fXaxis.GetTitleFont();
2822 // save the TAttAxis members (reset by SetBins) for y axis
2823 Int_t nYdivisions = fYaxis.GetNdivisions();
2824 Color_t yAxisColor = fYaxis.GetAxisColor();
2825 Color_t yLabelColor = fYaxis.GetLabelColor();
2826 Style_t yLabelFont = fYaxis.GetLabelFont();
2827 Float_t yLabelOffset = fYaxis.GetLabelOffset();
2828 Float_t yLabelSize = fYaxis.GetLabelSize();
2829 Float_t yTickLength = fYaxis.GetTickLength();
2830 Float_t yTitleOffset = fYaxis.GetTitleOffset();
2831 Float_t yTitleSize = fYaxis.GetTitleSize();
2832 Color_t yTitleColor = fYaxis.GetTitleColor();
2833 Style_t yTitleFont = fYaxis.GetTitleFont();
2834 // save the TAttAxis members (reset by SetBins) for z axis
2835 Int_t nZdivisions = fZaxis.GetNdivisions();
2836 Color_t zAxisColor = fZaxis.GetAxisColor();
2837 Color_t zLabelColor = fZaxis.GetLabelColor();
2838 Style_t zLabelFont = fZaxis.GetLabelFont();
2839 Float_t zLabelOffset = fZaxis.GetLabelOffset();
2840 Float_t zLabelSize = fZaxis.GetLabelSize();
2841 Float_t zTickLength = fZaxis.GetTickLength();
2842 Float_t zTitleOffset = fZaxis.GetTitleOffset();
2843 Float_t zTitleSize = fZaxis.GetTitleSize();
2844 Color_t zTitleColor = fZaxis.GetTitleColor();
2845 Style_t zTitleFont = fZaxis.GetTitleFont();
2846
2847 // copy merged bin contents (ignore under/overflows)
2848 if (nxgroup != 1 || nygroup != 1 || nzgroup != 1) {
2849 if (fXaxis.GetXbins()->GetSize() > 0 || fYaxis.GetXbins()->GetSize() > 0 || fZaxis.GetXbins()->GetSize() > 0) {
2850 // variable bin sizes in x or y, don't treat both cases separately
2851 Double_t *xbins = new Double_t[newxbins+1];
2852 for (i = 0; i <= newxbins; ++i) xbins[i] = fXaxis.GetBinLowEdge(1+i*nxgroup);
2853 Double_t *ybins = new Double_t[newybins+1];
2854 for (i = 0; i <= newybins; ++i) ybins[i] = fYaxis.GetBinLowEdge(1+i*nygroup);
2855 Double_t *zbins = new Double_t[newzbins+1];
2856 for (i = 0; i <= newzbins; ++i) zbins[i] = fZaxis.GetBinLowEdge(1+i*nzgroup);
2857 hnew->SetBins(newxbins,xbins, newybins, ybins, newzbins, zbins);//changes also errors array (if any)
2858 delete [] xbins;
2859 delete [] ybins;
2860 delete [] zbins;
2861 } else {
2862 hnew->SetBins(newxbins, xmin, xmax, newybins, ymin, ymax, newzbins, zmin, zmax);//changes also errors array
2863 }
2864
2865 Double_t binContent, binSumw2;
2866 Int_t oldxbin = 1;
2867 Int_t oldybin = 1;
2868 Int_t oldzbin = 1;
2869 Int_t bin;
2870 for (xbin = 1; xbin <= newxbins; xbin++) {
2871 oldybin=1;
2872 oldzbin=1;
2873 for (ybin = 1; ybin <= newybins; ybin++) {
2874 oldzbin=1;
2875 for (zbin = 1; zbin <= newzbins; zbin++) {
2876 binContent = 0;
2877 binSumw2 = 0;
2878 for (i = 0; i < nxgroup; i++) {
2879 if (oldxbin+i > nxbins) break;
2880 for (j =0; j < nygroup; j++) {
2881 if (oldybin+j > nybins) break;
2882 for (k =0; k < nzgroup; k++) {
2883 if (oldzbin+k > nzbins) break;
2884 //get global bin (same conventions as in TH1::GetBin(xbin,ybin)
2885 bin = oldxbin + i + (oldybin + j)*(nxbins + 2) + (oldzbin + k)*(nxbins + 2)*(nybins + 2);
2886 binContent += oldBins[bin];
2887 if (oldSumw2) binSumw2 += oldSumw2[bin];
2888 }
2889 }
2890 }
2891 Int_t ibin = hnew->GetBin(xbin,ybin,zbin); // new bin number
2892 hnew->SetBinContent(ibin, binContent);
2893 if (oldSumw2) hnew->fSumw2.fArray[ibin] = binSumw2;
2894 oldzbin += nzgroup;
2895 }
2896 oldybin += nygroup;
2897 }
2898 oldxbin += nxgroup;
2899 }
2900
2901 // compute new underflow/overflows for the 8 vertices
2902 for (Int_t xover = 0; xover <= 1; xover++) {
2903 for (Int_t yover = 0; yover <= 1; yover++) {
2904 for (Int_t zover = 0; zover <= 1; zover++) {
2905 binContent = 0;
2906 binSumw2 = 0;
2907 // make loop in case of only underflow/overflow
2908 for (xbin = xover*oldxbin; xbin <= xover*(nxbins+1); xbin++) {
2909 for (ybin = yover*oldybin; ybin <= yover*(nybins+1); ybin++) {
2910 for (zbin = zover*oldzbin; zbin <= zover*(nzbins+1); zbin++) {
2911 bin = GetBin(xbin,ybin,zbin);
2912 binContent += oldBins[bin];
2913 if (oldSumw2) binSumw2 += oldSumw2[bin];
2914 }
2915 }
2916 }
2917 Int_t binNew = hnew->GetBin( xover *(newxbins+1),
2918 yover*(newybins+1), zover*(newzbins+1) );
2919 hnew->SetBinContent(binNew,binContent);
2920 if (oldSumw2) hnew->fSumw2.fArray[binNew] = binSumw2;
2921 }
2922 }
2923 }
2924
2925 Double_t binContent0, binContent2, binContent3, binContent4;
2926 Double_t binError0, binError2, binError3, binError4;
2927 Int_t oldxbin2, oldybin2, oldzbin2;
2928 Int_t ufbin, ofbin, ofbin2, ofbin3, ofbin4;
2929
2930 // recompute under/overflow contents in y for the new x and z bins
2931 oldxbin2 = 1;
2932 oldybin2 = 1;
2933 oldzbin2 = 1;
2934 for (xbin = 1; xbin<=newxbins; xbin++) {
2935 oldzbin2 = 1;
2936 for (zbin = 1; zbin<=newzbins; zbin++) {
2937 binContent0 = binContent2 = 0;
2938 binError0 = binError2 = 0;
2939 for (i=0; i<nxgroup; i++) {
2940 if (oldxbin2+i > nxbins) break;
2941 for (k=0; k<nzgroup; k++) {
2942 if (oldzbin2+k > nzbins) break;
2943 //old underflow bin (in y)
2944 ufbin = oldxbin2 + i + (nxbins+2)*(nybins+2)*(oldzbin2+k);
2945 binContent0 += oldBins[ufbin];
2946 if (oldSumw2) binError0 += oldSumw2[ufbin];
2947 for (ybin = oldybin; ybin <= nybins + 1; ybin++) {
2948 //old overflow bin (in y)
2949 ofbin = ufbin + ybin*(nxbins+2);
2950 binContent2 += oldBins[ofbin];
2951 if (oldSumw2) binError2 += oldSumw2[ofbin];
2952 }
2953 }
2954 }
2955 hnew->SetBinContent(xbin,0,zbin,binContent0);
2956 hnew->SetBinContent(xbin,newybins+1,zbin,binContent2);
2957 if (oldSumw2) {
2958 hnew->SetBinError(xbin,0,zbin,TMath::Sqrt(binError0));
2959 hnew->SetBinError(xbin,newybins+1,zbin,TMath::Sqrt(binError2) );
2960 }
2961 oldzbin2 += nzgroup;
2962 }
2963 oldxbin2 += nxgroup;
2964 }
2965
2966 // recompute under/overflow contents in x for the new y and z bins
2967 oldxbin2 = 1;
2968 oldybin2 = 1;
2969 oldzbin2 = 1;
2970 for (ybin = 1; ybin<=newybins; ybin++) {
2971 oldzbin2 = 1;
2972 for (zbin = 1; zbin<=newzbins; zbin++) {
2973 binContent0 = binContent2 = 0;
2974 binError0 = binError2 = 0;
2975 for (j=0; j<nygroup; j++) {
2976 if (oldybin2+j > nybins) break;
2977 for (k=0; k<nzgroup; k++) {
2978 if (oldzbin2+k > nzbins) break;
2979 //old underflow bin (in y)
2980 ufbin = (oldybin2 + j)*(nxbins+2) + (nxbins+2)*(nybins+2)*(oldzbin2+k);
2981 binContent0 += oldBins[ufbin];
2982 if (oldSumw2) binError0 += oldSumw2[ufbin];
2983 for (xbin = oldxbin; xbin <= nxbins + 1; xbin++) {
2984 //old overflow bin (in x)
2985 ofbin = ufbin + xbin;
2986 binContent2 += oldBins[ofbin];
2987 if (oldSumw2) binError2 += oldSumw2[ofbin];
2988 }
2989 }
2990 }
2991 hnew->SetBinContent(0,ybin,zbin,binContent0);
2992 hnew->SetBinContent(newxbins+1,ybin,zbin,binContent2);
2993 if (oldSumw2) {
2994 hnew->SetBinError(0,ybin,zbin,TMath::Sqrt(binError0));
2995 hnew->SetBinError(newxbins+1,ybin,zbin,TMath::Sqrt(binError2) );
2996 }
2997 oldzbin2 += nzgroup;
2998 }
2999 oldybin2 += nygroup;
3000 }
3001
3002 // recompute under/overflow contents in z for the new x and y bins
3003 oldxbin2 = 1;
3004 oldybin2 = 1;
3005 oldzbin2 = 1;
3006 for (xbin = 1; xbin<=newxbins; xbin++) {
3007 oldybin2 = 1;
3008 for (ybin = 1; ybin<=newybins; ybin++) {
3009 binContent0 = binContent2 = 0;
3010 binError0 = binError2 = 0;
3011 for (i=0; i<nxgroup; i++) {
3012 if (oldxbin2+i > nxbins) break;
3013 for (j=0; j<nygroup; j++) {
3014 if (oldybin2+j > nybins) break;
3015 //old underflow bin (in z)
3016 ufbin = oldxbin2 + i + (nxbins+2)*(oldybin2+j);
3017 binContent0 += oldBins[ufbin];
3018 if (oldSumw2) binError0 += oldSumw2[ufbin];
3019 for (zbin = oldzbin; zbin <= nzbins + 1; zbin++) {
3020 //old overflow bin (in z)
3021 ofbin = ufbin + (nxbins+2)*(nybins+2)*zbin;
3022 binContent2 += oldBins[ofbin];
3023 if (oldSumw2) binError2 += oldSumw2[ofbin];
3024 }
3025 }
3026 }
3027 hnew->SetBinContent(xbin,ybin,0,binContent0);
3028 hnew->SetBinContent(xbin,ybin,newzbins+1,binContent2);
3029 if (oldSumw2) {
3030 hnew->SetBinError(xbin,ybin,0,TMath::Sqrt(binError0));
3031 hnew->SetBinError(xbin,ybin,newzbins+1,TMath::Sqrt(binError2) );
3032 }
3033 oldybin2 += nygroup;
3034 }
3035 oldxbin2 += nxgroup;
3036 }
3037
3038 // recompute under/overflow contents in y, z for the new x
3039 oldxbin2 = 1;
3040 oldybin2 = 1;
3041 oldzbin2 = 1;
3042 for (xbin = 1; xbin<=newxbins; xbin++) {
3043 binContent0 = 0;
3044 binContent2 = 0;
3045 binContent3 = 0;
3046 binContent4 = 0;
3047 binError0 = 0;
3048 binError2 = 0;
3049 binError3 = 0;
3050 binError4 = 0;
3051 for (i=0; i<nxgroup; i++) {
3052 if (oldxbin2+i > nxbins) break;
3053 ufbin = oldxbin2 + i; //
3054 binContent0 += oldBins[ufbin];
3055 if (oldSumw2) binError0 += oldSumw2[ufbin];
3056 for (ybin = oldybin; ybin <= nybins + 1; ybin++) {
3057 ofbin3 = ufbin+ybin*(nxbins+2);
3058 binContent3 += oldBins[ ofbin3 ];
3059 if (oldSumw2) binError3 += oldSumw2[ofbin3];
3060 for (zbin = oldzbin; zbin <= nzbins + 1; zbin++) {
3061 //old overflow bin (in z)
3062 ofbin4 = oldxbin2 + i + ybin*(nxbins+2) + (nxbins+2)*(nybins+2)*zbin;
3063 binContent4 += oldBins[ofbin4];
3064 if (oldSumw2) binError4 += oldSumw2[ofbin4];
3065 }
3066 }
3067 for (zbin = oldzbin; zbin <= nzbins + 1; zbin++) {
3068 ofbin2 = ufbin+zbin*(nxbins+2)*(nybins+2);
3069 binContent2 += oldBins[ ofbin2 ];
3070 if (oldSumw2) binError2 += oldSumw2[ofbin2];
3071 }
3072 }
3073 hnew->SetBinContent(xbin,0,0,binContent0);
3074 hnew->SetBinContent(xbin,0,newzbins+1,binContent2);
3075 hnew->SetBinContent(xbin,newybins+1,0,binContent3);
3076 hnew->SetBinContent(xbin,newybins+1,newzbins+1,binContent4);
3077 if (oldSumw2) {
3078 hnew->SetBinError(xbin,0,0,TMath::Sqrt(binError0));
3079 hnew->SetBinError(xbin,0,newzbins+1,TMath::Sqrt(binError2) );
3080 hnew->SetBinError(xbin,newybins+1,0,TMath::Sqrt(binError3) );
3081 hnew->SetBinError(xbin,newybins+1,newzbins+1,TMath::Sqrt(binError4) );
3082 }
3083 oldxbin2 += nxgroup;
3084 }
3085
3086 // recompute under/overflow contents in x, y for the new z
3087 oldxbin2 = 1;
3088 oldybin2 = 1;
3089 oldzbin2 = 1;
3090 for (zbin = 1; zbin<=newzbins; zbin++) {
3091 binContent0 = 0;
3092 binContent2 = 0;
3093 binContent3 = 0;
3094 binContent4 = 0;
3095 binError0 = 0;
3096 binError2 = 0;
3097 binError3 = 0;
3098 binError4 = 0;
3099 for (i=0; i<nzgroup; i++) {
3100 if (oldzbin2+i > nzbins) break;
3101 ufbin = (oldzbin2 + i)*(nxbins+2)*(nybins+2); //
3102 binContent0 += oldBins[ufbin];
3103 if (oldSumw2) binError0 += oldSumw2[ufbin];
3104 for (ybin = oldybin; ybin <= nybins + 1; ybin++) {
3105 ofbin3 = ufbin+ybin*(nxbins+2);
3106 binContent3 += oldBins[ ofbin3 ];
3107 if (oldSumw2) binError3 += oldSumw2[ofbin3];
3108 for (xbin = oldxbin; xbin <= nxbins + 1; xbin++) {
3109 //old overflow bin (in z)
3110 ofbin4 = ufbin + xbin + ybin*(nxbins+2);
3111 binContent4 += oldBins[ofbin4];
3112 if (oldSumw2) binError4 += oldSumw2[ofbin4];
3113 }
3114 }
3115 for (xbin = oldxbin; xbin <= nxbins + 1; xbin++) {
3116 ofbin2 = xbin +(oldzbin2+i)*(nxbins+2)*(nybins+2);
3117 binContent2 += oldBins[ ofbin2 ];
3118 if (oldSumw2) binError2 += oldSumw2[ofbin2];
3119 }
3120 }
3121 hnew->SetBinContent(0,0,zbin,binContent0);
3122 hnew->SetBinContent(0,newybins+1,zbin,binContent3);
3123 hnew->SetBinContent(newxbins+1,0,zbin,binContent2);
3124 hnew->SetBinContent(newxbins+1,newybins+1,zbin,binContent4);
3125 if (oldSumw2) {
3126 hnew->SetBinError(0,0,zbin,TMath::Sqrt(binError0));
3127 hnew->SetBinError(0,newybins+1,zbin,TMath::Sqrt(binError3) );
3128 hnew->SetBinError(newxbins+1,0,zbin,TMath::Sqrt(binError2) );
3129 hnew->SetBinError(newxbins+1,newybins+1,zbin,TMath::Sqrt(binError4) );
3130 }
3131 oldzbin2 += nzgroup;
3132 }
3133
3134 // recompute under/overflow contents in x, z for the new y
3135 oldxbin2 = 1;
3136 oldybin2 = 1;
3137 oldzbin2 = 1;
3138 for (ybin = 1; ybin<=newybins; ybin++) {
3139 binContent0 = 0;
3140 binContent2 = 0;
3141 binContent3 = 0;
3142 binContent4 = 0;
3143 binError0 = 0;
3144 binError2 = 0;
3145 binError3 = 0;
3146 binError4 = 0;
3147 for (i=0; i<nygroup; i++) {
3148 if (oldybin2+i > nybins) break;
3149 ufbin = (oldybin2 + i)*(nxbins+2); //
3150 binContent0 += oldBins[ufbin];
3151 if (oldSumw2) binError0 += oldSumw2[ufbin];
3152 for (xbin = oldxbin; xbin <= nxbins + 1; xbin++) {
3153 ofbin3 = ufbin+xbin;
3154 binContent3 += oldBins[ ofbin3 ];
3155 if (oldSumw2) binError3 += oldSumw2[ofbin3];
3156 for (zbin = oldzbin; zbin <= nzbins + 1; zbin++) {
3157 //old overflow bin (in z)
3158 ofbin4 = xbin + (nxbins+2)*(nybins+2)*zbin+(oldybin2+i)*(nxbins+2);
3159 binContent4 += oldBins[ofbin4];
3160 if (oldSumw2) binError4 += oldSumw2[ofbin4];
3161 }
3162 }
3163 for (zbin = oldzbin; zbin <= nzbins + 1; zbin++) {
3164 ofbin2 = (oldybin2+i)*(nxbins+2)+zbin*(nxbins+2)*(nybins+2);
3165 binContent2 += oldBins[ ofbin2 ];
3166 if (oldSumw2) binError2 += oldSumw2[ofbin2];
3167 }
3168 }
3169 hnew->SetBinContent(0,ybin,0,binContent0);
3170 hnew->SetBinContent(0,ybin,newzbins+1,binContent2);
3171 hnew->SetBinContent(newxbins+1,ybin,0,binContent3);
3172 hnew->SetBinContent(newxbins+1,ybin,newzbins+1,binContent4);
3173 if (oldSumw2) {
3174 hnew->SetBinError(0,ybin,0,TMath::Sqrt(binError0));
3175 hnew->SetBinError(0,ybin,newzbins+1,TMath::Sqrt(binError2) );
3176 hnew->SetBinError(newxbins+1,ybin,0,TMath::Sqrt(binError3) );
3177 hnew->SetBinError(newxbins+1,ybin,newzbins+1,TMath::Sqrt(binError4) );
3178 }
3179 oldybin2 += nygroup;
3180 }
3181 }
3182
3183 // Restore x axis attributes
3184 fXaxis.SetNdivisions(nXdivisions);
3185 fXaxis.SetAxisColor(xAxisColor);
3186 fXaxis.SetLabelColor(xLabelColor);
3187 fXaxis.SetLabelFont(xLabelFont);
3188 fXaxis.SetLabelOffset(xLabelOffset);
3189 fXaxis.SetLabelSize(xLabelSize);
3190 fXaxis.SetTickLength(xTickLength);
3191 fXaxis.SetTitleOffset(xTitleOffset);
3192 fXaxis.SetTitleSize(xTitleSize);
3193 fXaxis.SetTitleColor(xTitleColor);
3194 fXaxis.SetTitleFont(xTitleFont);
3195 // Restore y axis attributes
3196 fYaxis.SetNdivisions(nYdivisions);
3197 fYaxis.SetAxisColor(yAxisColor);
3198 fYaxis.SetLabelColor(yLabelColor);
3199 fYaxis.SetLabelFont(yLabelFont);
3200 fYaxis.SetLabelOffset(yLabelOffset);
3201 fYaxis.SetLabelSize(yLabelSize);
3202 fYaxis.SetTickLength(yTickLength);
3203 fYaxis.SetTitleOffset(yTitleOffset);
3204 fYaxis.SetTitleSize(yTitleSize);
3205 fYaxis.SetTitleColor(yTitleColor);
3206 fYaxis.SetTitleFont(yTitleFont);
3207 // Restore z axis attributes
3208 fZaxis.SetNdivisions(nZdivisions);
3209 fZaxis.SetAxisColor(zAxisColor);
3210 fZaxis.SetLabelColor(zLabelColor);
3211 fZaxis.SetLabelFont(zLabelFont);
3212 fZaxis.SetLabelOffset(zLabelOffset);
3213 fZaxis.SetLabelSize(zLabelSize);
3214 fZaxis.SetTickLength(zTickLength);
3215 fZaxis.SetTitleOffset(zTitleOffset);
3216 fZaxis.SetTitleSize(zTitleSize);
3217 fZaxis.SetTitleColor(zTitleColor);
3218 fZaxis.SetTitleFont(zTitleFont);
3219
3220 //restore statistics and entries modified by SetBinContent
3221 hnew->SetEntries(entries);
3222 if (!resetStat) hnew->PutStats(stat);
3223
3224 delete [] oldBins;
3225 if (oldSumw2) delete [] oldSumw2;
3226 return hnew;
3227}
3228
3229
3230////////////////////////////////////////////////////////////////////////////////
3231/// Reset this histogram: contents, errors, etc.
3232
3234{
3235 TH1::Reset(option);
3236 TString opt = option;
3237 opt.ToUpper();
3238 if (opt.Contains("ICE") && !opt.Contains("S")) return;
3239 fTsumwy = 0;
3240 fTsumwy2 = 0;
3241 fTsumwxy = 0;
3242 fTsumwz = 0;
3243 fTsumwz2 = 0;
3244 fTsumwxz = 0;
3245 fTsumwyz = 0;
3246}
3247
3248
3249////////////////////////////////////////////////////////////////////////////////
3250/// Set bin content.
3251
3253{
3254 fEntries++;
3255 fTsumw = 0;
3256 if (bin < 0) return;
3257 if (bin >= fNcells) return;
3258 UpdateBinContent(bin, content);
3259}
3260
3261
3262////////////////////////////////////////////////////////////////////////////////
3263/// Stream an object of class TH3.
3264
3265void TH3::Streamer(TBuffer &R__b)
3266{
3267 if (R__b.IsReading()) {
3268 UInt_t R__s, R__c;
3269 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
3270 if (R__v > 2) {
3271 R__b.ReadClassBuffer(TH3::Class(), this, R__v, R__s, R__c);
3272 return;
3273 }
3274 //====process old versions before automatic schema evolution
3275 TH1::Streamer(R__b);
3276 TAtt3D::Streamer(R__b);
3277 R__b.CheckByteCount(R__s, R__c, TH3::IsA());
3278 //====end of old versions
3279
3280 } else {
3281 R__b.WriteClassBuffer(TH3::Class(),this);
3282 }
3283}
3284
3285
3286//______________________________________________________________________________
3287// TH3C methods
3288// TH3C a 3-D histogram with one byte per cell (char)
3289//______________________________________________________________________________
3290
3291ClassImp(TH3C);
3292
3293
3294////////////////////////////////////////////////////////////////////////////////
3295/// Constructor.
3296
3298{
3299 SetBinsLength(27);
3300 if (fgDefaultSumw2) Sumw2();
3301}
3302
3303
3304////////////////////////////////////////////////////////////////////////////////
3305/// Destructor.
3306
3308{
3309}
3310
3311
3312////////////////////////////////////////////////////////////////////////////////
3313/// Normal constructor for fix bin size 3-D histograms.
3314
3315TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
3316 ,Int_t nbinsy,Double_t ylow,Double_t yup
3317 ,Int_t nbinsz,Double_t zlow,Double_t zup)
3318 :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
3319{
3321 if (fgDefaultSumw2) Sumw2();
3322
3323 if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
3324}
3325
3326
3327////////////////////////////////////////////////////////////////////////////////
3328/// Normal constructor for variable bin size 3-D histograms.
3329
3330TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
3331 ,Int_t nbinsy,const Float_t *ybins
3332 ,Int_t nbinsz,const Float_t *zbins)
3333 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
3334{
3336 if (fgDefaultSumw2) Sumw2();
3337}
3338
3339
3340////////////////////////////////////////////////////////////////////////////////
3341/// Normal constructor for variable bin size 3-D histograms.
3342
3343TH3C::TH3C(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
3344 ,Int_t nbinsy,const Double_t *ybins
3345 ,Int_t nbinsz,const Double_t *zbins)
3346 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
3347{
3349 if (fgDefaultSumw2) Sumw2();
3350}
3351
3352
3353////////////////////////////////////////////////////////////////////////////////
3354/// Copy constructor.
3355
3356TH3C::TH3C(const TH3C &h3c) : TH3(), TArrayC()
3357{
3358 ((TH3C&)h3c).Copy(*this);
3359}
3360
3361
3362////////////////////////////////////////////////////////////////////////////////
3363/// Increment bin content by 1.
3364
3366{
3367 if (fArray[bin] < 127) fArray[bin]++;
3368}
3369
3370
3371////////////////////////////////////////////////////////////////////////////////
3372/// Increment bin content by w.
3373
3375{
3376 Int_t newval = fArray[bin] + Int_t(w);
3377 if (newval > -128 && newval < 128) {fArray[bin] = Char_t(newval); return;}
3378 if (newval < -127) fArray[bin] = -127;
3379 if (newval > 127) fArray[bin] = 127;
3380}
3381
3382
3383////////////////////////////////////////////////////////////////////////////////
3384/// Copy this 3-D histogram structure to newth3.
3385
3386void TH3C::Copy(TObject &newth3) const
3387{
3388 TH3::Copy((TH3C&)newth3);
3389}
3390
3391
3392////////////////////////////////////////////////////////////////////////////////
3393/// Reset this histogram: contents, errors, etc.
3394
3396{
3397 TH3::Reset(option);
3399 // should also reset statistics once statistics are implemented for TH3
3400}
3401
3402
3403////////////////////////////////////////////////////////////////////////////////
3404/// Set total number of bins including under/overflow
3405/// Reallocate bin contents array
3406
3408{
3409 if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
3410 fNcells = n;
3411 TArrayC::Set(n);
3412}
3413
3414
3415////////////////////////////////////////////////////////////////////////////////
3416/// When the mouse is moved in a pad containing a 3-d view of this histogram
3417/// a second canvas shows a projection type given as option.
3418/// To stop the generation of the projections, delete the canvas
3419/// containing the projection.
3420/// option may contain a combination of the characters x,y,z,e
3421/// option = "x" return the x projection into a TH1D histogram
3422/// option = "y" return the y projection into a TH1D histogram
3423/// option = "z" return the z projection into a TH1D histogram
3424/// option = "xy" return the x versus y projection into a TH2D histogram
3425/// option = "yx" return the y versus x projection into a TH2D histogram
3426/// option = "xz" return the x versus z projection into a TH2D histogram
3427/// option = "zx" return the z versus x projection into a TH2D histogram
3428/// option = "yz" return the y versus z projection into a TH2D histogram
3429/// option = "zy" return the z versus y projection into a TH2D histogram
3430/// option can also include the drawing option for the projection, eg to draw
3431/// the xy projection using the draw option "box" do
3432/// myhist.SetShowProjection("xy box");
3433/// This function is typically called from the context menu.
3434/// NB: the notation "a vs b" means "a" vertical and "b" horizontal
3435
3436void TH3::SetShowProjection(const char *option,Int_t nbins)
3437{
3438 GetPainter();
3439
3440 if (fPainter) fPainter->SetShowProjection(option,nbins);
3441}
3442
3443
3444////////////////////////////////////////////////////////////////////////////////
3445/// Stream an object of class TH3C.
3446
3447void TH3C::Streamer(TBuffer &R__b)
3448{
3449 if (R__b.IsReading()) {
3450 UInt_t R__s, R__c;
3451 if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
3452 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
3453 if (R__v > 2) {
3454 R__b.ReadClassBuffer(TH3C::Class(), this, R__v, R__s, R__c);
3455 return;
3456 }
3457 //====process old versions before automatic schema evolution
3458 if (R__v < 2) {
3459 R__b.ReadVersion();
3460 TH1::Streamer(R__b);
3461 TArrayC::Streamer(R__b);
3462 R__b.ReadVersion(&R__s, &R__c);
3463 TAtt3D::Streamer(R__b);
3464 } else {
3465 TH3::Streamer(R__b);
3466 TArrayC::Streamer(R__b);
3467 R__b.CheckByteCount(R__s, R__c, TH3C::IsA());
3468 }
3469 //====end of old versions
3470
3471 } else {
3472 R__b.WriteClassBuffer(TH3C::Class(),this);
3473 }
3474}
3475
3476
3477////////////////////////////////////////////////////////////////////////////////
3478/// Operator =
3479
3481{
3482 if (this != &h1) ((TH3C&)h1).Copy(*this);
3483 return *this;
3484}
3485
3486
3487////////////////////////////////////////////////////////////////////////////////
3488/// Operator *
3489
3491{
3492 TH3C hnew = h1;
3493 hnew.Scale(c1);
3494 hnew.SetDirectory(0);
3495 return hnew;
3496}
3497
3498
3499////////////////////////////////////////////////////////////////////////////////
3500/// Operator +
3501
3503{
3504 TH3C hnew = h1;
3505 hnew.Add(&h2,1);
3506 hnew.SetDirectory(0);
3507 return hnew;
3508}
3509
3510
3511////////////////////////////////////////////////////////////////////////////////
3512/// Operator -
3513
3515{
3516 TH3C hnew = h1;
3517 hnew.Add(&h2,-1);
3518 hnew.SetDirectory(0);
3519 return hnew;
3520}
3521
3522
3523////////////////////////////////////////////////////////////////////////////////
3524/// Operator *
3525
3527{
3528 TH3C hnew = h1;
3529 hnew.Multiply(&h2);
3530 hnew.SetDirectory(0);
3531 return hnew;
3532}
3533
3534
3535////////////////////////////////////////////////////////////////////////////////
3536/// Operator /
3537
3539{
3540 TH3C hnew = h1;
3541 hnew.Divide(&h2);
3542 hnew.SetDirectory(0);
3543 return hnew;
3544}
3545
3546
3547//______________________________________________________________________________
3548// TH3S methods
3549// TH3S a 3-D histogram with two bytes per cell (short integer)
3550//______________________________________________________________________________
3551
3552ClassImp(TH3S);
3553
3554
3555////////////////////////////////////////////////////////////////////////////////
3556/// Constructor.
3557
3559{
3560 SetBinsLength(27);
3561 if (fgDefaultSumw2) Sumw2();
3562}
3563
3564
3565////////////////////////////////////////////////////////////////////////////////
3566/// Destructor.
3567
3569{
3570}
3571
3572
3573////////////////////////////////////////////////////////////////////////////////
3574/// Normal constructor for fix bin size 3-D histograms.
3575
3576TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
3577 ,Int_t nbinsy,Double_t ylow,Double_t yup
3578 ,Int_t nbinsz,Double_t zlow,Double_t zup)
3579 :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
3580{
3582 if (fgDefaultSumw2) Sumw2();
3583
3584 if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
3585}
3586
3587
3588////////////////////////////////////////////////////////////////////////////////
3589/// Normal constructor for variable bin size 3-D histograms.
3590
3591TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
3592 ,Int_t nbinsy,const Float_t *ybins
3593 ,Int_t nbinsz,const Float_t *zbins)
3594 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
3595{
3597 if (fgDefaultSumw2) Sumw2();
3598}
3599
3600
3601////////////////////////////////////////////////////////////////////////////////
3602/// Normal constructor for variable bin size 3-D histograms.
3603
3604TH3S::TH3S(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
3605 ,Int_t nbinsy,const Double_t *ybins
3606 ,Int_t nbinsz,const Double_t *zbins)
3607 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
3608{
3610 if (fgDefaultSumw2) Sumw2();
3611}
3612
3613
3614////////////////////////////////////////////////////////////////////////////////
3615/// Copy Constructor.
3616
3617TH3S::TH3S(const TH3S &h3s) : TH3(), TArrayS()
3618{
3619 ((TH3S&)h3s).Copy(*this);
3620}
3621
3622
3623////////////////////////////////////////////////////////////////////////////////
3624/// Increment bin content by 1.
3625
3627{
3628 if (fArray[bin] < 32767) fArray[bin]++;
3629}
3630
3631
3632////////////////////////////////////////////////////////////////////////////////
3633/// Increment bin content by w.
3634
3636{
3637 Int_t newval = fArray[bin] + Int_t(w);
3638 if (newval > -32768 && newval < 32768) {fArray[bin] = Short_t(newval); return;}
3639 if (newval < -32767) fArray[bin] = -32767;
3640 if (newval > 32767) fArray[bin] = 32767;
3641}
3642
3643
3644////////////////////////////////////////////////////////////////////////////////
3645/// Copy this 3-D histogram structure to newth3.
3646
3647void TH3S::Copy(TObject &newth3) const
3648{
3649 TH3::Copy((TH3S&)newth3);
3650}
3651
3652
3653////////////////////////////////////////////////////////////////////////////////
3654/// Reset this histogram: contents, errors, etc.
3655
3657{
3658 TH3::Reset(option);
3660 // should also reset statistics once statistics are implemented for TH3
3661}
3662
3663
3664////////////////////////////////////////////////////////////////////////////////
3665/// Set total number of bins including under/overflow
3666/// Reallocate bin contents array
3667
3669{
3670 if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
3671 fNcells = n;
3672 TArrayS::Set(n);
3673}
3674
3675
3676////////////////////////////////////////////////////////////////////////////////
3677/// Stream an object of class TH3S.
3678
3679void TH3S::Streamer(TBuffer &R__b)
3680{
3681 if (R__b.IsReading()) {
3682 UInt_t R__s, R__c;
3683 if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
3684 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
3685 if (R__v > 2) {
3686 R__b.ReadClassBuffer(TH3S::Class(), this, R__v, R__s, R__c);
3687 return;
3688 }
3689 //====process old versions before automatic schema evolution
3690 if (R__v < 2) {
3691 R__b.ReadVersion();
3692 TH1::Streamer(R__b);
3693 TArrayS::Streamer(R__b);
3694 R__b.ReadVersion(&R__s, &R__c);
3695 TAtt3D::Streamer(R__b);
3696 } else {
3697 TH3::Streamer(R__b);
3698 TArrayS::Streamer(R__b);
3699 R__b.CheckByteCount(R__s, R__c, TH3S::IsA());
3700 }
3701 //====end of old versions
3702
3703 } else {
3704 R__b.WriteClassBuffer(TH3S::Class(),this);
3705 }
3706}
3707
3708
3709////////////////////////////////////////////////////////////////////////////////
3710/// Operator =
3711
3713{
3714 if (this != &h1) ((TH3S&)h1).Copy(*this);
3715 return *this;
3716}
3717
3718
3719////////////////////////////////////////////////////////////////////////////////
3720/// Operator *
3721
3723{
3724 TH3S hnew = h1;
3725 hnew.Scale(c1);
3726 hnew.SetDirectory(0);
3727 return hnew;
3728}
3729
3730
3731////////////////////////////////////////////////////////////////////////////////
3732/// Operator +
3733
3735{
3736 TH3S hnew = h1;
3737 hnew.Add(&h2,1);
3738 hnew.SetDirectory(0);
3739 return hnew;
3740}
3741
3742
3743////////////////////////////////////////////////////////////////////////////////
3744/// Operator -
3745
3747{
3748 TH3S hnew = h1;
3749 hnew.Add(&h2,-1);
3750 hnew.SetDirectory(0);
3751 return hnew;
3752}
3753
3754
3755////////////////////////////////////////////////////////////////////////////////
3756/// Operator *
3757
3759{
3760 TH3S hnew = h1;
3761 hnew.Multiply(&h2);
3762 hnew.SetDirectory(0);
3763 return hnew;
3764}
3765
3766
3767////////////////////////////////////////////////////////////////////////////////
3768/// Operator /
3769
3771{
3772 TH3S hnew = h1;
3773 hnew.Divide(&h2);
3774 hnew.SetDirectory(0);
3775 return hnew;
3776}
3777
3778
3779//______________________________________________________________________________
3780// TH3I methods
3781// TH3I a 3-D histogram with four bytes per cell (32 bits integer)
3782//______________________________________________________________________________
3783
3784ClassImp(TH3I);
3785
3786
3787////////////////////////////////////////////////////////////////////////////////
3788/// Constructor.
3789
3791{
3792 SetBinsLength(27);
3793 if (fgDefaultSumw2) Sumw2();
3794}
3795
3796
3797////////////////////////////////////////////////////////////////////////////////
3798/// Destructor.
3799
3801{
3802}
3803
3804
3805////////////////////////////////////////////////////////////////////////////////
3806/// Normal constructor for fix bin size 3-D histograms.
3807
3808TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
3809 ,Int_t nbinsy,Double_t ylow,Double_t yup
3810 ,Int_t nbinsz,Double_t zlow,Double_t zup)
3811 :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
3812{
3814 if (fgDefaultSumw2) Sumw2();
3815
3816 if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
3817}
3818
3819
3820////////////////////////////////////////////////////////////////////////////////
3821/// Normal constructor for variable bin size 3-D histograms.
3822
3823TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
3824 ,Int_t nbinsy,const Float_t *ybins
3825 ,Int_t nbinsz,const Float_t *zbins)
3826 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
3827{
3829 if (fgDefaultSumw2) Sumw2();
3830}
3831
3832
3833////////////////////////////////////////////////////////////////////////////////
3834/// Normal constructor for variable bin size 3-D histograms.
3835
3836TH3I::TH3I(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
3837 ,Int_t nbinsy,const Double_t *ybins
3838 ,Int_t nbinsz,const Double_t *zbins)
3839 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
3840{
3842 if (fgDefaultSumw2) Sumw2();
3843}
3844
3845
3846////////////////////////////////////////////////////////////////////////////////
3847/// Copy constructor.
3848
3849TH3I::TH3I(const TH3I &h3i) : TH3(), TArrayI()
3850{
3851 ((TH3I&)h3i).Copy(*this);
3852}
3853
3854
3855////////////////////////////////////////////////////////////////////////////////
3856/// Increment bin content by 1.
3857
3859{
3860 if (fArray[bin] < 2147483647) fArray[bin]++;
3861}
3862
3863
3864////////////////////////////////////////////////////////////////////////////////
3865/// Increment bin content by w.
3866
3868{
3869 Long64_t newval = fArray[bin] + Long64_t(w);
3870 if (newval > -2147483647 && newval < 2147483647) {fArray[bin] = Int_t(newval); return;}
3871 if (newval < -2147483647) fArray[bin] = -2147483647;
3872 if (newval > 2147483647) fArray[bin] = 2147483647;
3873}
3874
3875
3876////////////////////////////////////////////////////////////////////////////////
3877/// Copy this 3-D histogram structure to newth3.
3878
3879void TH3I::Copy(TObject &newth3) const
3880{
3881 TH3::Copy((TH3I&)newth3);
3882}
3883
3884
3885////////////////////////////////////////////////////////////////////////////////
3886/// Reset this histogram: contents, errors, etc.
3887
3889{
3890 TH3::Reset(option);
3892 // should also reset statistics once statistics are implemented for TH3
3893}
3894
3895
3896////////////////////////////////////////////////////////////////////////////////
3897/// Set total number of bins including under/overflow
3898/// Reallocate bin contents array
3899
3901{
3902 if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
3903 fNcells = n;
3904 TArrayI::Set(n);
3905}
3906
3907
3908////////////////////////////////////////////////////////////////////////////////
3909/// Operator =
3910
3912{
3913 if (this != &h1) ((TH3I&)h1).Copy(*this);
3914 return *this;
3915}
3916
3917
3918////////////////////////////////////////////////////////////////////////////////
3919/// Operator *
3920
3922{
3923 TH3I hnew = h1;
3924 hnew.Scale(c1);
3925 hnew.SetDirectory(0);
3926 return hnew;
3927}
3928
3929
3930////////////////////////////////////////////////////////////////////////////////
3931/// Operator +
3932
3934{
3935 TH3I hnew = h1;
3936 hnew.Add(&h2,1);
3937 hnew.SetDirectory(0);
3938 return hnew;
3939}
3940
3941
3942////////////////////////////////////////////////////////////////////////////////
3943/// Operator _
3944
3946{
3947 TH3I hnew = h1;
3948 hnew.Add(&h2,-1);
3949 hnew.SetDirectory(0);
3950 return hnew;
3951}
3952
3953
3954////////////////////////////////////////////////////////////////////////////////
3955/// Operator *
3956
3958{
3959 TH3I hnew = h1;
3960 hnew.Multiply(&h2);
3961 hnew.SetDirectory(0);
3962 return hnew;
3963}
3964
3965
3966////////////////////////////////////////////////////////////////////////////////
3967/// Operator /
3968
3970{
3971 TH3I hnew = h1;
3972 hnew.Divide(&h2);
3973 hnew.SetDirectory(0);
3974 return hnew;
3975}
3976
3977
3978//______________________________________________________________________________
3979// TH3F methods
3980// TH3F a 3-D histogram with four bytes per cell (float)
3981//______________________________________________________________________________
3982
3983ClassImp(TH3F);
3984
3985
3986////////////////////////////////////////////////////////////////////////////////
3987/// Constructor.
3988
3990{
3991 SetBinsLength(27);
3992 if (fgDefaultSumw2) Sumw2();
3993}
3994
3995
3996////////////////////////////////////////////////////////////////////////////////
3997/// Destructor.
3998
4000{
4001}
4002
4003
4004////////////////////////////////////////////////////////////////////////////////
4005/// Normal constructor for fix bin size 3-D histograms.
4006
4007TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
4008 ,Int_t nbinsy,Double_t ylow,Double_t yup
4009 ,Int_t nbinsz,Double_t zlow,Double_t zup)
4010 :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
4011{
4013 if (fgDefaultSumw2) Sumw2();
4014
4015 if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
4016}
4017
4018
4019////////////////////////////////////////////////////////////////////////////////
4020/// Normal constructor for variable bin size 3-D histograms.
4021
4022TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
4023 ,Int_t nbinsy,const Float_t *ybins
4024 ,Int_t nbinsz,const Float_t *zbins)
4025 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
4026{
4028 if (fgDefaultSumw2) Sumw2();
4029}
4030
4031
4032////////////////////////////////////////////////////////////////////////////////
4033/// Normal constructor for variable bin size 3-D histograms.
4034
4035TH3F::TH3F(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
4036 ,Int_t nbinsy,const Double_t *ybins
4037 ,Int_t nbinsz,const Double_t *zbins)
4038 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
4039{
4041 if (fgDefaultSumw2) Sumw2();
4042}
4043
4044
4045////////////////////////////////////////////////////////////////////////////////
4046/// Copy constructor.
4047
4048TH3F::TH3F(const TH3F &h3f) : TH3(), TArrayF()
4049{
4050 ((TH3F&)h3f).Copy(*this);
4051}
4052
4053
4054////////////////////////////////////////////////////////////////////////////////
4055/// Copy this 3-D histogram structure to newth3.
4056
4057void TH3F::Copy(TObject &newth3) const
4058{
4059 TH3::Copy((TH3F&)newth3);
4060}
4061
4062
4063////////////////////////////////////////////////////////////////////////////////
4064/// Reset this histogram: contents, errors, etc.
4065
4067{
4068 TH3::Reset(option);
4070 // should also reset statistics once statistics are implemented for TH3
4071}
4072
4073
4074////////////////////////////////////////////////////////////////////////////////
4075/// Set total number of bins including under/overflow
4076/// Reallocate bin contents array
4077
4079{
4080 if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
4081 fNcells = n;
4082 TArrayF::Set(n);
4083}
4084
4085
4086////////////////////////////////////////////////////////////////////////////////
4087/// Stream an object of class TH3F.
4088
4089void TH3F::Streamer(TBuffer &R__b)
4090{
4091 if (R__b.IsReading()) {
4092 UInt_t R__s, R__c;
4093 if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
4094 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
4095 if (R__v > 2) {
4096 R__b.ReadClassBuffer(TH3F::Class(), this, R__v, R__s, R__c);
4097 return;
4098 }
4099 //====process old versions before automatic schema evolution
4100 if (R__v < 2) {
4101 R__b.ReadVersion();
4102 TH1::Streamer(R__b);
4103 TArrayF::Streamer(R__b);
4104 R__b.ReadVersion(&R__s, &R__c);
4105 TAtt3D::Streamer(R__b);
4106 } else {
4107 TH3::Streamer(R__b);
4108 TArrayF::Streamer(R__b);
4109 R__b.CheckByteCount(R__s, R__c, TH3F::IsA());
4110 }
4111 //====end of old versions
4112
4113 } else {
4114 R__b.WriteClassBuffer(TH3F::Class(),this);
4115 }
4116}
4117
4118
4119////////////////////////////////////////////////////////////////////////////////
4120/// Operator =
4121
4123{
4124 if (this != &h1) ((TH3F&)h1).Copy(*this);
4125 return *this;
4126}
4127
4128
4129////////////////////////////////////////////////////////////////////////////////
4130/// Operator *
4131
4133{
4134 TH3F hnew = h1;
4135 hnew.Scale(c1);
4136 hnew.SetDirectory(0);
4137 return hnew;
4138}
4139
4140
4141////////////////////////////////////////////////////////////////////////////////
4142/// Operator +
4143
4145{
4146 TH3F hnew = h1;
4147 hnew.Add(&h2,1);
4148 hnew.SetDirectory(0);
4149 return hnew;
4150}
4151
4152
4153////////////////////////////////////////////////////////////////////////////////
4154/// Operator -
4155
4157{
4158 TH3F hnew = h1;
4159 hnew.Add(&h2,-1);
4160 hnew.SetDirectory(0);
4161 return hnew;
4162}
4163
4164
4165////////////////////////////////////////////////////////////////////////////////
4166/// Operator *
4167
4169{
4170 TH3F hnew = h1;
4171 hnew.Multiply(&h2);
4172 hnew.SetDirectory(0);
4173 return hnew;
4174}
4175
4176
4177////////////////////////////////////////////////////////////////////////////////
4178/// Operator /
4179
4181{
4182 TH3F hnew = h1;
4183 hnew.Divide(&h2);
4184 hnew.SetDirectory(0);
4185 return hnew;
4186}
4187
4188
4189//______________________________________________________________________________
4190// TH3D methods
4191// TH3D a 3-D histogram with eight bytes per cell (double)
4192//______________________________________________________________________________
4193
4194ClassImp(TH3D);
4195
4196
4197////////////////////////////////////////////////////////////////////////////////
4198/// Constructor.
4199
4201{
4202 SetBinsLength(27);
4203 if (fgDefaultSumw2) Sumw2();
4204}
4205
4206
4207////////////////////////////////////////////////////////////////////////////////
4208/// Destructor.
4209
4211{
4212}
4213
4214
4215////////////////////////////////////////////////////////////////////////////////
4216/// Normal constructor for fix bin size 3-D histograms.
4217
4218TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,Double_t xlow,Double_t xup
4219 ,Int_t nbinsy,Double_t ylow,Double_t yup
4220 ,Int_t nbinsz,Double_t zlow,Double_t zup)
4221 :TH3(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup)
4222{
4224 if (fgDefaultSumw2) Sumw2();
4225
4226 if (xlow >= xup || ylow >= yup || zlow >= zup) SetBuffer(fgBufferSize);
4227}
4228
4229
4230////////////////////////////////////////////////////////////////////////////////
4231/// Normal constructor for variable bin size 3-D histograms.
4232
4233TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,const Float_t *xbins
4234 ,Int_t nbinsy,const Float_t *ybins
4235 ,Int_t nbinsz,const Float_t *zbins)
4236 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
4237{
4239 if (fgDefaultSumw2) Sumw2();
4240}
4241
4242
4243////////////////////////////////////////////////////////////////////////////////
4244/// Normal constructor for variable bin size 3-D histograms.
4245
4246TH3D::TH3D(const char *name,const char *title,Int_t nbinsx,const Double_t *xbins
4247 ,Int_t nbinsy,const Double_t *ybins
4248 ,Int_t nbinsz,const Double_t *zbins)
4249 :TH3(name,title,nbinsx,xbins,nbinsy,ybins,nbinsz,zbins)
4250{
4252 if (fgDefaultSumw2) Sumw2();
4253}
4254
4255
4256////////////////////////////////////////////////////////////////////////////////
4257/// Copy constructor.
4258
4259TH3D::TH3D(const TH3D &h3d) : TH3(), TArrayD()
4260{
4261 ((TH3D&)h3d).Copy(*this);
4262}
4263
4264
4265////////////////////////////////////////////////////////////////////////////////
4266/// Copy this 3-D histogram structure to newth3.
4267
4268void TH3D::Copy(TObject &newth3) const
4269{
4270 TH3::Copy((TH3D&)newth3);
4271}
4272
4273
4274////////////////////////////////////////////////////////////////////////////////
4275/// Reset this histogram: contents, errors, etc.
4276
4278{
4279 TH3::Reset(option);
4281 // should also reset statistics once statistics are implemented for TH3
4282}
4283
4284
4285////////////////////////////////////////////////////////////////////////////////
4286/// Set total number of bins including under/overflow
4287/// Reallocate bin contents array
4288
4290{
4291 if (n < 0) n = (fXaxis.GetNbins()+2)*(fYaxis.GetNbins()+2)*(fZaxis.GetNbins()+2);
4292 fNcells = n;
4293 TArrayD::Set(n);
4294}
4295
4296
4297////////////////////////////////////////////////////////////////////////////////
4298/// Stream an object of class TH3D.
4299
4300void TH3D::Streamer(TBuffer &R__b)
4301{
4302 if (R__b.IsReading()) {
4303 UInt_t R__s, R__c;
4304 if (R__b.GetParent() && R__b.GetVersionOwner() < 22300) return;
4305 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
4306 if (R__v > 2) {
4307 R__b.ReadClassBuffer(TH3D::Class(), this, R__v, R__s, R__c);
4308 return;
4309 }
4310 //====process old versions before automatic schema evolution
4311 if (R__v < 2) {
4312 R__b.ReadVersion();
4313 TH1::Streamer(R__b);
4314 TArrayD::Streamer(R__b);
4315 R__b.ReadVersion(&R__s, &R__c);
4316 TAtt3D::Streamer(R__b);
4317 } else {
4318 TH3::Streamer(R__b);
4319 TArrayD::Streamer(R__b);
4320 R__b.CheckByteCount(R__s, R__c, TH3D::IsA());
4321 }
4322 //====end of old versions
4323
4324 } else {
4325 R__b.WriteClassBuffer(TH3D::Class(),this);
4326 }
4327}
4328
4329
4330////////////////////////////////////////////////////////////////////////////////
4331/// Operator =
4332
4334{
4335 if (this != &h1) ((TH3D&)h1).Copy(*this);
4336 return *this;
4337}
4338
4339
4340////////////////////////////////////////////////////////////////////////////////
4341/// Operator *
4342
4344{
4345 TH3D hnew = h1;
4346 hnew.Scale(c1);
4347 hnew.SetDirectory(0);
4348 return hnew;
4349}
4350
4351
4352////////////////////////////////////////////////////////////////////////////////
4353/// Operator +
4354
4356{
4357 TH3D hnew = h1;
4358 hnew.Add(&h2,1);
4359 hnew.SetDirectory(0);
4360 return hnew;
4361}
4362
4363
4364////////////////////////////////////////////////////////////////////////////////
4365/// Operator -
4366
4368{
4369 TH3D hnew = h1;
4370 hnew.Add(&h2,-1);
4371 hnew.SetDirectory(0);
4372 return hnew;
4373}
4374
4375
4376////////////////////////////////////////////////////////////////////////////////
4377/// Operator *
4378
4380{
4381 TH3D hnew = h1;
4382 hnew.Multiply(&h2);
4383 hnew.SetDirectory(0);
4384 return hnew;
4385}
4386
4387
4388////////////////////////////////////////////////////////////////////////////////
4389/// Operator /
4390
4392{
4393 TH3D hnew = h1;
4394 hnew.Divide(&h2);
4395 hnew.SetDirectory(0);
4396 return hnew;
4397}
void Class()
Definition: Class.C:29
#define c(i)
Definition: RSha256.hxx:101
#define s1(x)
Definition: RSha256.hxx:91
#define h(i)
Definition: RSha256.hxx:106
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:43
short Version_t
Definition: RtypesCore.h:63
char Char_t
Definition: RtypesCore.h:31
unsigned int UInt_t
Definition: RtypesCore.h:44
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
short Short_t
Definition: RtypesCore.h:37
double Double_t
Definition: RtypesCore.h:57
short Color_t
Definition: RtypesCore.h:81
long long Long64_t
Definition: RtypesCore.h:71
short Style_t
Definition: RtypesCore.h:78
float Float_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
#define R__ASSERT(e)
Definition: TError.h:96
void Warning(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
TH3C operator/(TH3C &h1, TH3C &h2)
Operator /.
Definition: TH3.cxx:3538
TH3C operator*(Float_t c1, TH3C &h1)
Operator *.
Definition: TH3.cxx:3490
TH3C operator-(TH3C &h1, TH3C &h2)
Operator -.
Definition: TH3.cxx:3514
TH3C operator+(TH3C &h1, TH3C &h2)
Operator +.
Definition: TH3.cxx:3502
float xmin
Definition: THbookFile.cxx:93
int nentries
Definition: THbookFile.cxx:89
float ymin
Definition: THbookFile.cxx:93
float xmax
Definition: THbookFile.cxx:93
float ymax
Definition: THbookFile.cxx:93
#define gROOT
Definition: TROOT.h:406
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
#define gPad
Definition: TVirtualPad.h:287
Array of chars or bytes (8 bits per element).
Definition: TArrayC.h:27
void Set(Int_t n)
Set size of this array to n chars.
Definition: TArrayC.cxx:105
Char_t * fArray
Definition: TArrayC.h:30
void Copy(TArrayC &array) const
Definition: TArrayC.h:42
void Reset(Char_t val=0)
Definition: TArrayC.h:47
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
void Reset()
Definition: TArrayD.h:47
Array of floats (32 bits per element).
Definition: TArrayF.h:27
void Copy(TArrayF &array) const
Definition: TArrayF.h:42
void Reset()
Definition: TArrayF.h:47
void Set(Int_t n)
Set size of this array to n floats.
Definition: TArrayF.cxx:105
Array of integers (32 bits per element).
Definition: TArrayI.h:27
Int_t * fArray
Definition: TArrayI.h:30
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:105
void Reset()
Definition: TArrayI.h:47
void Copy(TArrayI &array) const
Definition: TArrayI.h:42
Array of shorts (16 bits per element).
Definition: TArrayS.h:27
void Set(Int_t n)
Set size of this array to n shorts.
Definition: TArrayS.cxx:105
void Reset()
Definition: TArrayS.h:47
void Copy(TArrayS &array) const
Definition: TArrayS.h:42
Short_t * fArray
Definition: TArrayS.h:30
Int_t fN
Definition: TArray.h:38
Int_t GetSize() const
Definition: TArray.h:47
Use this attribute class when an object should have 3D capabilities.
Definition: TAtt3D.h:19
virtual Color_t GetTitleColor() const
Definition: TAttAxis.h:46
virtual Color_t GetLabelColor() const
Definition: TAttAxis.h:38
virtual Int_t GetNdivisions() const
Definition: TAttAxis.h:36
virtual Color_t GetAxisColor() const
Definition: TAttAxis.h:37
virtual void SetTitleOffset(Float_t offset=1)
Set distance between the axis and the axis title.
Definition: TAttAxis.cxx:294
virtual Style_t GetTitleFont() const
Definition: TAttAxis.h:47
virtual Float_t GetLabelOffset() const
Definition: TAttAxis.h:40
virtual void SetAxisColor(Color_t color=1, Float_t alpha=1.)
Set color of the line axis and tick marks.
Definition: TAttAxis.cxx:163
virtual void SetLabelSize(Float_t size=0.04)
Set size of axis labels.
Definition: TAttAxis.cxx:204
virtual Style_t GetLabelFont() const
Definition: TAttAxis.h:39
virtual void SetTitleFont(Style_t font=62)
Set the title font.
Definition: TAttAxis.cxx:322
virtual void SetLabelOffset(Float_t offset=0.005)
Set distance between the axis and the labels.
Definition: TAttAxis.cxx:193
virtual void SetLabelFont(Style_t font=62)
Set labels' font.
Definition: TAttAxis.cxx:183
virtual void SetTitleSize(Float_t size=0.04)
Set size of axis title.
Definition: TAttAxis.cxx:304
virtual void SetTitleColor(Color_t color=1)
Set color of axis title.
Definition: TAttAxis.cxx:313
virtual Float_t GetTitleSize() const
Definition: TAttAxis.h:44
virtual Float_t GetLabelSize() const
Definition: TAttAxis.h:41
virtual Float_t GetTickLength() const
Definition: TAttAxis.h:45
virtual Float_t GetTitleOffset() const
Definition: TAttAxis.h:43
virtual void SetTickLength(Float_t length=0.03)
Set tick mark length.
Definition: TAttAxis.cxx:280
virtual void SetNdivisions(Int_t n=510, Bool_t optim=kTRUE)
Set the number of divisions for this axis.
Definition: TAttAxis.cxx:229
virtual void SetLabelColor(Color_t color=1, Float_t alpha=1.)
Set color of labels.
Definition: TAttAxis.cxx:173
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
Class to manage histogram axis.
Definition: TAxis.h:30
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition: TAxis.cxx:820
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:475
const TArrayD * GetXbins() const
Definition: TAxis.h:130
Double_t GetXmax() const
Definition: TAxis.h:134
@ kAxisRange
Definition: TAxis.h:61
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:290
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:515
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition: TAxis.cxx:728
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:416
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:466
virtual void ImportAttributes(const TAxis *axis)
Copy axis attributes to this.
Definition: TAxis.cxx:628
Double_t GetXmin() const
Definition: TAxis.h:133
Int_t GetNbins() const
Definition: TAxis.h:121
const char * GetTitle() const
Returns title of object.
Definition: TAxis.h:129
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis from bin first to last.
Definition: TAxis.cxx:914
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition: TAxis.cxx:537
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:525
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:455
THashList * GetLabels() const
Definition: TAxis.h:117
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:262
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
virtual Int_t GetVersionOwner() const =0
Bool_t IsReading() const
Definition: TBuffer.h:85
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
1-Dim function class
Definition: TF1.h:210
virtual TH1 * GetHistogram() const
Return a pointer to the histogram used to visualise the function.
Definition: TF1.cxx:1567
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition: TF1.cxx:1913
Double_t GetChisquare() const
Definition: TF1.h:438
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition: TF1.cxx:3521
virtual Int_t GetNpar() const
Definition: TF1.h:475
virtual Int_t GetNumberFitPoints() const
Definition: TF1.h:497
virtual Double_t * GetParameters() const
Definition: TF1.h:514
virtual Double_t EvalPar(const Double_t *x, const Double_t *params=0)
Evaluate function with given coordinates and parameters.
Definition: TF1.cxx:1461
virtual void GetRange(Double_t *xmin, Double_t *xmax) const
Return range of a generic N-D function.
Definition: TF1.cxx:2266
virtual const char * GetParName(Int_t ipar) const
Definition: TF1.h:523
virtual void SetParameters(const Double_t *params)
Definition: TF1.h:638
virtual Double_t GetParameter(Int_t ipar) const
Definition: TF1.h:506
A 3-Dim function with parameters.
Definition: TF3.h:28
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:614
virtual void Reset(Option_t *option="")
Reset.
Definition: TH1.cxx:9562
The TH1 histogram class.
Definition: TH1.h:56
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition: TH1.cxx:8393
Double_t * fBuffer
[fBufferSize] entry buffer
Definition: TH1.h:105
virtual Double_t GetEffectiveEntries() const
Number of effective entries of the histogram.
Definition: TH1.cxx:4327
TAxis * GetZaxis()
Definition: TH1.h:318
virtual Bool_t Multiply(TF1 *f1, Double_t c1=1)
Performs the operation:
Definition: TH1.cxx:5662
Int_t fNcells
number of bins(1D), cells (2D) +U/Overflows
Definition: TH1.h:86
Double_t fTsumw
Total Sum of weights.
Definition: TH1.h:93
Double_t fTsumw2
Total Sum of squares of weights.
Definition: TH1.h:94
virtual Double_t DoIntegral(Int_t ix1, Int_t ix2, Int_t iy1, Int_t iy2, Int_t iz1, Int_t iz2, Double_t &err, Option_t *opt, Bool_t doerr=kFALSE) const
Internal function compute integral and optionally the error between the limits specified by the bin n...
Definition: TH1.cxx:7486
Double_t fTsumwx2
Total Sum of weight*X*X.
Definition: TH1.h:96
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition: TH1.cxx:7140
virtual Int_t GetNbinsY() const
Definition: TH1.h:293
virtual void AddBinContent(Int_t bin)
Increment bin content by 1.
Definition: TH1.cxx:1201
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8519
virtual Int_t GetNbinsZ() const
Definition: TH1.h:294
virtual Int_t GetDimension() const
Definition: TH1.h:278
@ kIsNotW
Histogram is forced to be not weighted even when the histogram is filled with weighted different than...
Definition: TH1.h:167
virtual Bool_t CanExtendAllAxes() const
Returns true if all axes are extendable.
Definition: TH1.cxx:6278
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:6736
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:316
virtual Int_t GetNcells() const
Definition: TH1.h:295
virtual void PutStats(Double_t *stats)
Replace current statistics with the values in array stats.
Definition: TH1.cxx:7396
TVirtualHistPainter * GetPainter(Option_t *option="")
Return pointer to painter.
Definition: TH1.cxx:4368
TObject * Clone(const char *newname=0) const
Make a complete copy of the underlying object.
Definition: TH1.cxx:2665
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Double_t xmin=0, Double_t xmax=0)
Fit histogram with function fname.
Definition: TH1.cxx:3808
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition: TH1.cxx:4809
virtual Int_t GetNbinsX() const
Definition: TH1.h:292
virtual Bool_t Add(TF1 *h1, Double_t c1=1, Option_t *option="")
Performs the operation: this = this + c1*f1 if errors are defined (see TH1::Sumw2),...
Definition: TH1.cxx:778
Int_t fBufferSize
fBuffer size
Definition: TH1.h:104
virtual Double_t RetrieveBinContent(Int_t bin) const
Raw retrieval of bin content on internal data structure see convention for numbering bins in TH1::Get...
Definition: TH1.cxx:8896
Int_t fDimension
!Histogram dimension (1, 2 or 3 dim)
Definition: TH1.h:107
virtual void 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:8662
static Int_t fgBufferSize
!default buffer size for automatic histograms
Definition: TH1.h:112
TAxis * GetYaxis()
Definition: TH1.h:317
Double_t * fIntegral
!Integral of bins used by GetRandom
Definition: TH1.h:108