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