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