Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TH1.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: Rene Brun 26/12/94
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 <array>
13#include <cctype>
14#include <climits>
15#include <cmath>
16#include <cstdio>
17#include <cstdlib>
18#include <cstring>
19#include <iostream>
20#include <memory>
21#include <sstream>
22#include <fstream>
23#include <limits>
24#include <iomanip>
25
26#include "TROOT.h"
27#include "TBuffer.h"
28#include "TEnv.h"
29#include "TClass.h"
30#include "TMath.h"
31#include "THashList.h"
32#include "TH1.h"
33#include "TH2.h"
34#include "TH3.h"
35#include "TF2.h"
36#include "TF3.h"
37#include "TPluginManager.h"
38#include "TVirtualPad.h"
39#include "TRandom.h"
40#include "TVirtualFitter.h"
41#include "THLimitsFinder.h"
42#include "TProfile.h"
43#include "TStyle.h"
44#include "TVectorF.h"
45#include "TVectorD.h"
46#include "TBrowser.h"
47#include "TError.h"
48#include "TVirtualHistPainter.h"
49#include "TVirtualFFT.h"
50#include "TVirtualPaveStats.h"
51
52#include "HFitInterface.h"
53#include "Fit/DataRange.h"
54#include "Fit/BinData.h"
55#include "Math/GoFTest.h"
58
59#include "TH1Merger.h"
60
61/** \addtogroup Histograms
62@{
63\class TH1C
64\brief 1-D histogram with a byte per channel (see TH1 documentation)
65\class TH1S
66\brief 1-D histogram with a short per channel (see TH1 documentation)
67\class TH1I
68\brief 1-D histogram with an int per channel (see TH1 documentation)
69\class TH1L
70\brief 1-D histogram with a long64 per channel (see TH1 documentation)
71\class TH1F
72\brief 1-D histogram with a float per channel (see TH1 documentation)
73\class TH1D
74\brief 1-D histogram with a double per channel (see TH1 documentation)
75@}
76*/
77
78// clang-format off
79
80/** \class TH1
81 \ingroup Histograms
82TH1 is the base class of all histogram classes in %ROOT.
83
84It provides the common interface for operations such as binning, filling, drawing, which
85will be detailed below.
86
87-# [Creating histograms](\ref creating-histograms)
88 - [Labelling axes](\ref labelling-axis)
89-# [Binning](\ref binning)
90 - [Fix or variable bin size](\ref fix-var)
91 - [Convention for numbering bins](\ref convention)
92 - [Alphanumeric Bin Labels](\ref alpha)
93 - [Histograms with automatic bins](\ref auto-bin)
94 - [Rebinning](\ref rebinning)
95-# [Filling histograms](\ref filling-histograms)
96 - [Associated errors](\ref associated-errors)
97 - [Associated functions](\ref associated-functions)
98 - [Projections of histograms](\ref prof-hist)
99 - [Random Numbers and histograms](\ref random-numbers)
100 - [Making a copy of a histogram](\ref making-a-copy)
101 - [Normalizing histograms](\ref normalizing)
102-# [Drawing histograms](\ref drawing-histograms)
103 - [Setting Drawing histogram contour levels (2-D hists only)](\ref cont-level)
104 - [Setting histogram graphics attributes](\ref graph-att)
105 - [Customising how axes are drawn](\ref axis-drawing)
106-# [Fitting histograms](\ref fitting-histograms)
107-# [Saving/reading histograms to/from a ROOT file](\ref saving-histograms)
108-# [Operations on histograms](\ref operations-on-histograms)
109-# [Miscellaneous operations](\ref misc)
110
111ROOT supports the following histogram types:
112
113 - 1-D histograms:
114 - TH1C : histograms with one byte per channel. Maximum bin content = 127
115 - TH1S : histograms with one short per channel. Maximum bin content = 32767
116 - TH1I : histograms with one int per channel. Maximum bin content = INT_MAX (\ref intmax "*")
117 - TH1L : histograms with one long64 per channel. Maximum bin content = LLONG_MAX (\ref llongmax "**")
118 - TH1F : histograms with one float per channel. Maximum precision 7 digits, maximum integer bin content =
119+/-16777216 (\ref floatmax "***")
120 - TH1D : histograms with one double per channel. Maximum precision 14 digits, maximum integer bin content =
121+/-9007199254740992 (\ref doublemax "****")
122 - 2-D histograms:
123 - TH2C : histograms with one byte per channel. Maximum bin content = 127
124 - TH2S : histograms with one short per channel. Maximum bin content = 32767
125 - TH2I : histograms with one int per channel. Maximum bin content = INT_MAX (\ref intmax "*")
126 - TH2L : histograms with one long64 per channel. Maximum bin content = LLONG_MAX (\ref llongmax "**")
127 - TH2F : histograms with one float per channel. Maximum precision 7 digits, maximum integer bin content =
128+/-16777216 (\ref floatmax "***")
129 - TH2D : histograms with one double per channel. Maximum precision 14 digits, maximum integer bin content =
130+/-9007199254740992 (\ref doublemax "****")
131 - 3-D histograms:
132 - TH3C : histograms with one byte per channel. Maximum bin content = 127
133 - TH3S : histograms with one short per channel. Maximum bin content = 32767
134 - TH3I : histograms with one int per channel. Maximum bin content = INT_MAX (\ref intmax "*")
135 - TH3L : histograms with one long64 per channel. Maximum bin content = LLONG_MAX (\ref llongmax "**")
136 - TH3F : histograms with one float per channel. Maximum precision 7 digits, maximum integer bin content =
137+/-16777216 (\ref floatmax "***")
138 - TH3D : histograms with one double per channel. Maximum precision 14 digits, maximum integer bin content =
139+/-9007199254740992 (\ref doublemax "****")
140 - Profile histograms: See classes TProfile, TProfile2D and TProfile3D.
141 Profile histograms are used to display the mean value of Y and its standard deviation
142 for each bin in X. Profile histograms are in many cases an elegant
143 replacement of two-dimensional histograms : the inter-relation of two
144 measured quantities X and Y can always be visualized by a two-dimensional
145 histogram or scatter-plot; If Y is an unknown (but single-valued)
146 approximate function of X, this function is displayed by a profile
147 histogram with much better precision than by a scatter-plot.
148
149<sup>
150\anchor intmax (*) INT_MAX = 2147483647 is the [maximum value for a variable of type int.](https://docs.microsoft.com/en-us/cpp/c-language/cpp-integer-limits)<br>
151\anchor llongmax (**) LLONG_MAX = 9223372036854775807 is the [maximum value for a variable of type long64.](https://docs.microsoft.com/en-us/cpp/c-language/cpp-integer-limits)<br>
152\anchor floatmax (***) 2^24 = 16777216 is the [maximum integer that can be properly represented by a float32 with 23-bit mantissa.](https://stackoverflow.com/a/3793950/7471760)<br>
153\anchor doublemax (****) 2^53 = 9007199254740992 is the [maximum integer that can be properly represented by a double64 with 52-bit mantissa.](https://stackoverflow.com/a/3793950/7471760)
154</sup>
155
156The inheritance hierarchy looks as follows:
157
158\image html classTH1__inherit__graph_org.svg width=100%
159
160\anchor creating-histograms
161## Creating histograms
162
163Histograms are created by invoking one of the constructors, e.g.
164~~~ {.cpp}
165 TH1F *h1 = new TH1F("h1", "h1 title", 100, 0, 4.4);
166 TH2F *h2 = new TH2F("h2", "h2 title", 40, 0, 4, 30, -3, 3);
167~~~
168Histograms may also be created by:
169
170 - calling the Clone() function, see below
171 - making a projection from a 2-D or 3-D histogram, see below
172 - reading a histogram from a file
173
174 When a histogram is created in ROOT 6, a reference to it is automatically added
175 to the list of in-memory objects for the current file or directory.
176 Then the pointer to this histogram in the current directory can be found
177 by its name, doing:
178~~~ {.cpp}
179 TH1F *h1 = (TH1F*)gDirectory->FindObject(name);
180~~~
181
182 This default behaviour can be changed by:
183~~~ {.cpp}
184 h->SetDirectory(nullptr); // for one histogram h
185 TH1::AddDirectory(kFALSE); // deprecated, see below
186~~~
187 When the histogram is deleted, the reference to it is removed from
188 the list of objects in memory.
189 When a file is closed, all histograms in memory associated with this file
190 are automatically deleted.
191
192In ROOT 7, this auto registration will be phased out. This mode can be tested in ROOT 6 using
193ROOT::Experimental::DisableObjectAutoRegistration(). To opt in to the ROOT-6-style registration
194in ROOT 7, use ROOT::Experimental::EnableObjectAutoRegistration().
195
196\anchor labelling-axis
197### Labelling axes
198
199 Axis titles can be specified in the title argument of the constructor.
200 They must be separated by ";":
201~~~ {.cpp}
202 TH1F* h=new TH1F("h", "Histogram title;X Axis;Y Axis", 100, 0, 1);
203~~~
204 The histogram title and the axis titles can be any TLatex string, and
205 are persisted if a histogram is written to a file.
206
207 Any title can be omitted:
208~~~ {.cpp}
209 TH1F* h=new TH1F("h", "Histogram title;;Y Axis", 100, 0, 1);
210 TH1F* h=new TH1F("h", ";;Y Axis", 100, 0, 1);
211~~~
212 The method SetTitle() has the same syntax:
213~~~ {.cpp}
214 h->SetTitle("Histogram title;Another X title Axis");
215~~~
216Alternatively, the title of each axis can be set directly:
217~~~ {.cpp}
218 h->GetXaxis()->SetTitle("X axis title");
219 h->GetYaxis()->SetTitle("Y axis title");
220~~~
221For bin labels see \ref binning.
222
223\anchor binning
224## Binning
225
226\anchor fix-var
227### Fix or variable bin size
228
229 All histogram types support either fix or variable bin sizes.
230 2-D histograms may have fix size bins along X and variable size bins
231 along Y or vice-versa. The functions to fill, manipulate, draw or access
232 histograms are identical in both cases.
233
234 Each histogram always contains 3 axis objects of type TAxis: fXaxis, fYaxis and fZaxis.
235 To access the axis parameters, use:
236~~~ {.cpp}
237 TAxis *xaxis = h->GetXaxis(); etc.
238 Double_t binCenter = xaxis->GetBinCenter(bin), etc.
239~~~
240 See class TAxis for a description of all the access functions.
241 The axis range is always stored internally in double precision.
242
243\anchor convention
244### Convention for numbering bins
245
246 For all histogram types: nbins, xlow, xup
247~~~ {.cpp}
248 bin = 0; underflow bin
249 bin = 1; first bin with low-edge xlow INCLUDED
250 bin = nbins; last bin with upper-edge xup EXCLUDED
251 bin = nbins+1; overflow bin
252~~~
253 In case of 2-D or 3-D histograms, a "global bin" number is defined.
254 For example, assuming a 3-D histogram with (binx, biny, binz), the function
255~~~ {.cpp}
256 Int_t gbin = h->GetBin(binx, biny, binz);
257~~~
258 returns a global/linearized gbin number. This global gbin is useful
259 to access the bin content/error information independently of the dimension.
260 Note that to access the information other than bin content and errors
261 one should use the TAxis object directly with e.g.:
262~~~ {.cpp}
263 Double_t xcenter = h3->GetZaxis()->GetBinCenter(27);
264~~~
265 returns the center along z of bin number 27 (not the global bin)
266 in the 3-D histogram h3.
267
268\anchor alpha
269### Alphanumeric Bin Labels
270
271 By default, a histogram axis is drawn with its numeric bin labels.
272 One can specify alphanumeric labels instead with:
273
274 - call TAxis::SetBinLabel(bin, label);
275 This can always be done before or after filling.
276 When the histogram is drawn, bin labels will be automatically drawn.
277 See examples labels1.C and labels2.C
278 - call to a Fill function with one of the arguments being a string, e.g.
279~~~ {.cpp}
280 hist1->Fill(somename, weight);
281 hist2->Fill(x, somename, weight);
282 hist2->Fill(somename, y, weight);
283 hist2->Fill(somenamex, somenamey, weight);
284~~~
285 See examples hlabels1.C and hlabels2.C
286 - via TTree::Draw. see for example cernstaff.C
287~~~ {.cpp}
288 tree.Draw("Nation::Division");
289~~~
290 where "Nation" and "Division" are two branches of a Tree.
291
292When using the options 2 or 3 above, the labels are automatically
293 added to the list (THashList) of labels for a given axis.
294 By default, an axis is drawn with the order of bins corresponding
295 to the filling sequence. It is possible to reorder the axis
296
297 - alphabetically
298 - by increasing or decreasing values
299
300 The reordering can be triggered via the TAxis context menu by selecting
301 the menu item "LabelsOption" or by calling directly
302 TH1::LabelsOption(option, axis) where
303
304 - axis may be "X", "Y" or "Z"
305 - option may be:
306 - "a" sort by alphabetic order
307 - ">" sort by decreasing values
308 - "<" sort by increasing values
309 - "h" draw labels horizontal
310 - "v" draw labels vertical
311 - "u" draw labels up (end of label right adjusted)
312 - "d" draw labels down (start of label left adjusted)
313
314 When using the option 2 above, new labels are added by doubling the current
315 number of bins in case one label does not exist yet.
316 When the Filling is terminated, it is possible to trim the number
317 of bins to match the number of active labels by calling
318~~~ {.cpp}
319 TH1::LabelsDeflate(axis) with axis = "X", "Y" or "Z"
320~~~
321 This operation is automatic when using TTree::Draw.
322 Once bin labels have been created, they become persistent if the histogram
323 is written to a file or when generating the C++ code via SavePrimitive.
324
325\anchor auto-bin
326### Histograms with automatic bins
327
328 When a histogram is created with an axis lower limit greater or equal
329 to its upper limit, the SetBuffer is automatically called with an
330 argument fBufferSize equal to fgBufferSize (default value=1000).
331 fgBufferSize may be reset via the static function TH1::SetDefaultBufferSize.
332 The axis limits will be automatically computed when the buffer will
333 be full or when the function BufferEmpty is called.
334
335\anchor rebinning
336### Rebinning
337
338 At any time, a histogram can be rebinned via TH1::Rebin. This function
339 returns a new histogram with the rebinned contents.
340 If bin errors were stored, they are recomputed during the rebinning.
341
342
343\anchor filling-histograms
344## Filling histograms
345
346 A histogram is typically filled with statements like:
347~~~ {.cpp}
348 h1->Fill(x);
349 h1->Fill(x, w); //fill with weight
350 h2->Fill(x, y)
351 h2->Fill(x, y, w)
352 h3->Fill(x, y, z)
353 h3->Fill(x, y, z, w)
354~~~
355 or via one of the Fill functions accepting names described above.
356 The Fill functions compute the bin number corresponding to the given
357 x, y or z argument and increment this bin by the given weight.
358 The Fill functions return the bin number for 1-D histograms or global
359 bin number for 2-D and 3-D histograms.
360 If TH1::Sumw2 has been called before filling, the sum of squares of
361 weights is also stored.
362 One can also increment directly a bin number via TH1::AddBinContent
363 or replace the existing content via TH1::SetBinContent. Passing an
364 out-of-range bin to TH1::AddBinContent leads to undefined behavior.
365 To access the bin content of a given bin, do:
366~~~ {.cpp}
367 Double_t binContent = h->GetBinContent(bin);
368~~~
369
370 By default, the bin number is computed using the current axis ranges.
371 If the automatic binning option has been set via
372~~~ {.cpp}
373 h->SetCanExtend(TH1::kAllAxes);
374~~~
375 then, the Fill Function will automatically extend the axis range to
376 accommodate the new value specified in the Fill argument. The method
377 used is to double the bin size until the new value fits in the range,
378 merging bins two by two. This automatic binning options is extensively
379 used by the TTree::Draw function when histogramming Tree variables
380 with an unknown range.
381 This automatic binning option is supported for 1-D, 2-D and 3-D histograms.
382
383 During filling, some statistics parameters are incremented to compute
384 the mean value and Root Mean Square with the maximum precision.
385
386 In case of histograms of type TH1C, TH1S, TH2C, TH2S, TH3C, TH3S
387 a check is made that the bin contents do not exceed the maximum positive
388 capacity (127 or 32767). Histograms of all types may have positive
389 or/and negative bin contents.
390
391\anchor associated-errors
392### Associated errors
393 By default, for each bin, the sum of weights is computed at fill time.
394 One can also call TH1::Sumw2 to force the storage and computation
395 of the sum of the square of weights per bin.
396 If Sumw2 has been called, the error per bin is computed as the
397 sqrt(sum of squares of weights), otherwise the error is set equal
398 to the sqrt(bin content).
399 To return the error for a given bin number, do:
400~~~ {.cpp}
401 Double_t error = h->GetBinError(bin);
402~~~
403
404\anchor associated-functions
405### Associated functions
406 One or more objects (typically a TF1*) can be added to the list
407 of functions (fFunctions) associated to each histogram.
408 When TH1::Fit is invoked, the fitted function is added to this list.
409 Given a histogram (or TGraph) `h`, one can retrieve an associated function
410 with:
411~~~ {.cpp}
412 TF1 *myfunc = h->GetFunction("myfunc");
413~~~
414
415
416\anchor operations-on-histograms
417## Operations on histograms
418
419 Many types of operations are supported on histograms or between histograms
420
421 - Addition of a histogram to the current histogram.
422 - Additions of two histograms with coefficients and storage into the current
423 histogram.
424 - Multiplications and Divisions are supported in the same way as additions.
425 - The Add, Divide and Multiply functions also exist to add, divide or multiply
426 a histogram by a function.
427
428 If a histogram has associated error bars (TH1::Sumw2 has been called),
429 the resulting error bars are also computed assuming independent histograms.
430 In case of divisions, Binomial errors are also supported.
431 One can mark a histogram to be an "average" histogram by setting its bit kIsAverage via
432 myhist.SetBit(TH1::kIsAverage);
433 When adding (see TH1::Add) average histograms, the histograms are averaged and not summed.
434
435
436\anchor prof-hist
437### Projections of histograms
438
439 One can:
440
441 - make a 1-D projection of a 2-D histogram or Profile
442 see functions TH2::ProjectionX,Y, TH2::ProfileX,Y, TProfile::ProjectionX
443 - make a 1-D, 2-D or profile out of a 3-D histogram
444 see functions TH3::ProjectionZ, TH3::Project3D.
445
446 One can fit these projections via:
447~~~ {.cpp}
448 TH2::FitSlicesX,Y, TH3::FitSlicesZ.
449~~~
450
451\anchor random-numbers
452### Random Numbers and histograms
453
454 TH1::FillRandom can be used to randomly fill a histogram using
455 the contents of an existing TF1 function or another
456 TH1 histogram (for all dimensions).
457 For example, the following two statements create and fill a histogram
458 10000 times with a default gaussian distribution of mean 0 and sigma 1:
459~~~ {.cpp}
460 TH1F h1("h1", "histo from a gaussian", 100, -3, 3);
461 h1.FillRandom("gaus", 10000);
462~~~
463 TH1::GetRandom can be used to return a random number distributed
464 according to the contents of a histogram.
465
466\anchor making-a-copy
467### Making a copy of a histogram
468 Like for any other ROOT object derived from TObject, one can use
469 the Clone() function. This makes an identical copy of the original
470 histogram including all associated errors and functions, e.g.:
471~~~ {.cpp}
472 TH1F *hnew = (TH1F*)h->Clone("hnew");
473~~~
474
475\anchor normalizing
476### Normalizing histograms
477
478 One can scale a histogram such that the bins integral is equal to
479 the normalization parameter via TH1::Scale(Double_t norm), where norm
480 is the desired normalization divided by the integral of the histogram.
481
482
483\anchor drawing-histograms
484## Drawing histograms
485
486 Histograms are drawn via the THistPainter class. Each histogram has
487 a pointer to its own painter (to be usable in a multithreaded program).
488 Many drawing options are supported.
489 See THistPainter::Paint() for more details.
490
491 The same histogram can be drawn with different options in different pads.
492 When a histogram drawn in a pad is deleted, the histogram is
493 automatically removed from all pads where it was drawn.
494 If a histogram is drawn in a pad, then modified, the new status
495 of the histogram will be automatically shown in the pad next time
496 the pad is updated. One does not need to redraw the histogram.
497 To draw the current version of a histogram in a pad, one can use
498~~~ {.cpp}
499 h->DrawCopy();
500~~~
501 DrawCopy() is also useful when a temporary histogram should be drawn, for
502 example in
503~~~ {.cpp}
504 void drawHisto() {
505 TH1D histo("histo", "An example histogram", 10, 0, 10);
506 // ...
507 histo.DrawCopy();
508 } // histo goes out of scope here, but the copy stays visible
509~~~
510
511 One can use TH1::SetMaximum() and TH1::SetMinimum() to force a particular
512 value for the maximum or the minimum scale on the plot. (For 1-D
513 histograms this means the y-axis, while for 2-D histograms these
514 functions affect the z-axis).
516 TH1::UseCurrentStyle() can be used to change all histogram graphics
517 attributes to correspond to the current selected style.
518 This function must be called for each histogram.
519 In case one reads and draws many histograms from a file, one can force
520 the histograms to inherit automatically the current graphics style
521 by calling before gROOT->ForceStyle().
522
523\anchor cont-level
524### Setting Drawing histogram contour levels (2-D hists only)
525
526 By default contours are automatically generated at equidistant
527 intervals. A default value of 20 levels is used. This can be modified
528 via TH1::SetContour() or TH1::SetContourLevel().
529 the contours level info is used by the drawing options "cont", "surf",
530 and "lego".
531
532\anchor graph-att
533### Setting histogram graphics attributes
534
535 The histogram classes inherit from the attribute classes:
536 TAttLine, TAttFill, and TAttMarker.
537 See the member functions of these classes for the list of options.
538
539\anchor axis-drawing
540### Customizing how axes are drawn
541
542 Use the functions of TAxis, such as
543~~~ {.cpp}
544 histogram.GetXaxis()->SetTicks("+");
545 histogram.GetYaxis()->SetRangeUser(1., 5.);
546~~~
547
548\anchor fitting-histograms
549## Fitting histograms
550
551 Histograms (1-D, 2-D, 3-D and Profiles) can be fitted with a user
552 specified function or a pre-defined function via TH1::Fit.
553 See TH1::Fit(TF1*, Option_t *, Option_t *, Double_t, Double_t) for the fitting documentation and the possible [fitting options](\ref HFitOpt)
554
555 The FitPanel can also be used for fitting an histogram. See the [FitPanel documentation](https://root.cern/manual/fitting/#using-the-fit-panel).
556
557\anchor saving-histograms
558## Saving/reading histograms to/from a ROOT file
559
560 The following statements create a ROOT file and store a histogram
561 on the file. Because TH1 derives from TNamed, the key identifier on
562 the file is the histogram name:
563~~~ {.cpp}
564 TFile f("histos.root", "new");
565 TH1F h1("hgaus", "histo from a gaussian", 100, -3, 3);
566 h1.FillRandom("gaus", 10000);
567 h1->Write();
568~~~
569 To read this histogram in another Root session, do:
570~~~ {.cpp}
571 TFile f("histos.root");
572 TH1F *h = (TH1F*)f.Get("hgaus");
573~~~
574 One can save all histograms in memory to the file by:
575~~~ {.cpp}
576 file->Write();
577~~~
580\anchor misc
581## Miscellaneous operations
582
583~~~ {.cpp}
584 TH1::KolmogorovTest(): statistical test of compatibility in shape
585 between two histograms
586 TH1::Smooth() smooths the bin contents of a 1-d histogram
587 TH1::Integral() returns the integral of bin contents in a given bin range
588 TH1::GetMean(int axis) returns the mean value along axis
589 TH1::GetStdDev(int axis) returns the sigma distribution along axis
590 TH1::GetEntries() returns the number of entries
591 TH1::Reset() resets the bin contents and errors of a histogram
592~~~
593 IMPORTANT NOTE: The returned values for GetMean and GetStdDev depend on how the
594 histogram statistics are calculated. By default, if no range has been set, the
595 returned values are the (unbinned) ones calculated at fill time. If a range has been
596 set, however, the values are calculated using the bins in range; THIS IS TRUE EVEN
597 IF THE RANGE INCLUDES ALL BINS--use TAxis::SetRange(0, 0) to unset the range.
598 To ensure that the returned values are always those of the binned data stored in the
599 histogram, call TH1::ResetStats. See TH1::GetStats.
600*/
601
602// clang-format on
603
604TF1 *gF1=nullptr; //left for back compatibility (use TVirtualFitter::GetUserFunc instead)
605
610
611extern void H1InitGaus();
612extern void H1InitExpo();
613extern void H1InitPolynom();
614extern void H1LeastSquareFit(Int_t n, Int_t m, Double_t *a);
617
618
619////////////////////////////////////////////////////////////////////////////////
620/// Histogram default constructor.
621
623{
624 fDirectory = nullptr;
625 fFunctions = new TList;
626 // ROOT's Python bindings use TCollection::IsOwner to decide whether objects
627 // inserted into a collection (like `TH1::fFunctions`) should be deleted
628 // (see `_TCollection_Add` pythonization). To ensure the Python bindings
629 // get the correct ownership signal, set the ownership on TH1::fFunctions.
630 // Although, in reality, TH1's destructor actually handles ownership, this
631 // solution still works, since the destructor removes all entries before
632 // deleting the collection.
633 fFunctions->SetOwner(true);
634 fNcells = 0;
635 fIntegral = nullptr;
636 fPainter = nullptr;
637 fEntries = 0;
638 fNormFactor = 0;
640 fMaximum = -1111;
641 fMinimum = -1111;
642 fBufferSize = 0;
643 fBuffer = nullptr;
646 fXaxis.SetName("xaxis");
647 fYaxis.SetName("yaxis");
648 fZaxis.SetName("zaxis");
649 fXaxis.SetParent(this);
650 fYaxis.SetParent(this);
651 fZaxis.SetParent(this);
653}
654
655////////////////////////////////////////////////////////////////////////////////
656/// Histogram default destructor.
657
659{
661 return;
662 }
663 delete[] fIntegral;
664 fIntegral = nullptr;
665 delete[] fBuffer;
666 fBuffer = nullptr;
667 if (fFunctions) {
669
671 TObject* obj = nullptr;
672 //special logic to support the case where the same object is
673 //added multiple times in fFunctions.
674 //This case happens when the same object is added with different
675 //drawing modes
676 //In the loop below we must be careful with objects (eg TCutG) that may
677 // have been added to the list of functions of several histograms
678 //and may have been already deleted.
679 while ((obj = fFunctions->First())) {
680 while(fFunctions->Remove(obj)) { }
682 break;
683 }
684 delete obj;
685 obj = nullptr;
686 }
687 delete fFunctions;
688 fFunctions = nullptr;
689 }
690 if (fDirectory) {
691 fDirectory->Remove(this);
692 fDirectory = nullptr;
693 }
694 delete fPainter;
695 fPainter = nullptr;
696}
697
698////////////////////////////////////////////////////////////////////////////////
699/// Constructor for fix bin size histograms.
700/// Creates the main histogram structure.
701///
702/// \param[in] name name of histogram (avoid blanks)
703/// \param[in] title histogram title.
704/// If title is of the form `stringt;stringx;stringy;stringz`,
705/// the histogram title is set to `stringt`,
706/// the x axis title to `stringx`, the y axis title to `stringy`, etc.
707/// \param[in] nbins number of bins
708/// \param[in] xlow low edge of first bin
709/// \param[in] xup upper edge of last bin (not included in last bin)
710/// \note if xup <= xlow, automatic bins are calculated when buffer size is reached
711
712TH1::TH1(const char *name,const char *title,Int_t nbins,Double_t xlow,Double_t xup)
713 :TNamed(name,title)
714{
715 Build();
716 if (nbins <= 0) {Warning("TH1","nbins is <=0 - set to nbins = 1"); nbins = 1; }
717 fXaxis.Set(nbins,xlow,xup);
718 fNcells = fXaxis.GetNbins()+2;
719}
720
721////////////////////////////////////////////////////////////////////////////////
722/// Constructor for variable bin size histograms using an input array of type float.
723/// Creates the main histogram structure.
724///
725/// \param[in] name name of histogram (avoid blanks)
726/// \param[in] title histogram title.
727/// If title is of the form `stringt;stringx;stringy;stringz`
728/// the histogram title is set to `stringt`,
729/// the x axis title to `stringx`, the y axis title to `stringy`, etc.
730/// \param[in] nbins number of bins
731/// \param[in] xbins array of low-edges for each bin.
732/// This is an array of type float and size nbins+1
733
734TH1::TH1(const char *name,const char *title,Int_t nbins,const Float_t *xbins)
735 :TNamed(name,title)
736{
737 Build();
738 if (nbins <= 0) {Warning("TH1","nbins is <=0 - set to nbins = 1"); nbins = 1; }
739 if (xbins) fXaxis.Set(nbins,xbins);
740 else fXaxis.Set(nbins,0,1);
741 fNcells = fXaxis.GetNbins()+2;
742}
743
744////////////////////////////////////////////////////////////////////////////////
745/// Constructor for variable bin size histograms using an input array of type double.
746///
747/// \param[in] name name of histogram (avoid blanks)
748/// \param[in] title histogram title.
749/// If title is of the form `stringt;stringx;stringy;stringz`
750/// the histogram title is set to `stringt`,
751/// the x axis title to `stringx`, the y axis title to `stringy`, etc.
752/// \param[in] nbins number of bins
753/// \param[in] xbins array of low-edges for each bin.
754/// This is an array of type double and size nbins+1
755
756TH1::TH1(const char *name,const char *title,Int_t nbins,const Double_t *xbins)
757 :TNamed(name,title)
758{
759 Build();
760 if (nbins <= 0) {Warning("TH1","nbins is <=0 - set to nbins = 1"); nbins = 1; }
761 if (xbins) fXaxis.Set(nbins,xbins);
762 else fXaxis.Set(nbins,0,1);
763 fNcells = fXaxis.GetNbins()+2;
764}
765
766////////////////////////////////////////////////////////////////////////////////
767/// Check whether TH1-derived classes should register themselves to the current gDirectory.
768/// \note Even if this returns true, the state of
769/// ROOT::Experimental::ObjectAutoRegistrationEnabled() might prevent the registration of
770/// histograms, since it has higher precedence.
771
776
777////////////////////////////////////////////////////////////////////////////////
778/// Browse the Histogram object.
779
781{
782 Draw(b ? b->GetDrawOption() : "");
783 gPad->Update();
784}
785
786////////////////////////////////////////////////////////////////////////////////
787/// Creates histogram basic data structure.
788
790{
791 fDirectory = nullptr;
792 fPainter = nullptr;
793 fIntegral = nullptr;
794 fEntries = 0;
795 fNormFactor = 0;
797 fMaximum = -1111;
798 fMinimum = -1111;
799 fBufferSize = 0;
800 fBuffer = nullptr;
803 fXaxis.SetName("xaxis");
804 fYaxis.SetName("yaxis");
805 fZaxis.SetName("zaxis");
806 fYaxis.Set(1,0.,1.);
807 fZaxis.Set(1,0.,1.);
808 fXaxis.SetParent(this);
809 fYaxis.SetParent(this);
810 fZaxis.SetParent(this);
811
813
814 fFunctions = new TList;
815 // ROOT's Python bindings use TCollection::IsOwner to decide whether objects
816 // inserted into a collection (like `TH1::fFunctions`) should be deleted
817 // (see `_TCollection_Add` pythonization). To ensure the Python bindings
818 // get the correct ownership signal, set the ownership on TH1::fFunctions.
819 // Although, in reality, TH1's destructor actually handles ownership, this
820 // solution still works, since the destructor removes all entries before
821 // deleting the collection.
822 fFunctions->SetOwner(true);
823
825
828 if (fDirectory) {
830 fDirectory->Append(this,kTRUE);
831 }
832 }
833}
834
835////////////////////////////////////////////////////////////////////////////////
836/// Performs the operation: `this = this + c1*f1`
837/// if errors are defined (see TH1::Sumw2), errors are also recalculated.
838///
839/// By default, the function is computed at the centre of the bin.
840/// if option "I" is specified (1-d histogram only), the integral of the
841/// function in each bin is used instead of the value of the function at
842/// the centre of the bin.
843///
844/// Only bins inside the function range are recomputed.
845///
846/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
847/// you should call Sumw2 before making this operation.
848/// This is particularly important if you fit the histogram after TH1::Add
849///
850/// The function return kFALSE if the Add operation failed
851
853{
854 if (!f1) {
855 Error("Add","Attempt to add a non-existing function");
856 return kFALSE;
857 }
858
859 TString opt = option;
860 opt.ToLower();
861 Bool_t integral = kFALSE;
862 if (opt.Contains("i") && fDimension == 1) integral = kTRUE;
863
864 Int_t ncellsx = GetNbinsX() + 2; // cells = normal bins + underflow bin + overflow bin
865 Int_t ncellsy = GetNbinsY() + 2;
866 Int_t ncellsz = GetNbinsZ() + 2;
867 if (fDimension < 2) ncellsy = 1;
868 if (fDimension < 3) ncellsz = 1;
869
870 // delete buffer if it is there since it will become invalid
871 if (fBuffer) BufferEmpty(1);
872
873 // - Add statistics
874 Double_t s1[10];
875 for (Int_t i = 0; i < 10; ++i) s1[i] = 0;
876 PutStats(s1);
877 SetMinimum();
878 SetMaximum();
879
880 // - Loop on bins (including underflows/overflows)
882 Double_t cu=0;
883 Double_t xx[3];
884 Double_t *params = nullptr;
885 f1->InitArgs(xx,params);
886 for (binz = 0; binz < ncellsz; ++binz) {
888 for (biny = 0; biny < ncellsy; ++biny) {
890 for (binx = 0; binx < ncellsx; ++binx) {
892 if (!f1->IsInside(xx)) continue;
894 bin = binx + ncellsx * (biny + ncellsy * binz);
895 if (integral) {
897 } else {
898 cu = c1*f1->EvalPar(xx);
899 }
900 if (TF1::RejectedPoint()) continue;
902 }
903 }
904 }
905
906 return kTRUE;
907}
908
909int TH1::LoggedInconsistency(const char *name, const TH1 *h1, const TH1 *h2, bool useMerge) const
910{
911 const auto inconsistency = CheckConsistency(h1, h2);
912
914 if (useMerge)
915 Info(name, "Histograms have different dimensions - trying to use TH1::Merge");
916 else {
917 Error(name, "Histograms have different dimensions");
918 }
920 if (useMerge)
921 Info(name, "Histograms have different number of bins - trying to use TH1::Merge");
922 else {
923 Error(name, "Histograms have different number of bins");
924 }
925 } else if (inconsistency & kDifferentAxisLimits) {
926 if (useMerge)
927 Info(name, "Histograms have different axis limits - trying to use TH1::Merge");
928 else
929 Warning(name, "Histograms have different axis limits");
930 } else if (inconsistency & kDifferentBinLimits) {
931 if (useMerge)
932 Info(name, "Histograms have different bin limits - trying to use TH1::Merge");
933 else
934 Warning(name, "Histograms have different bin limits");
935 } else if (inconsistency & kDifferentLabels) {
936 // in case of different labels -
937 if (useMerge)
938 Info(name, "Histograms have different labels - trying to use TH1::Merge");
939 else
940 Info(name, "Histograms have different labels");
941 }
942
943 return inconsistency;
944}
945
946////////////////////////////////////////////////////////////////////////////////
947/// Performs the operation: `this = this + c1*h1`
948/// If errors are defined (see TH1::Sumw2), errors are also recalculated.
949///
950/// Note that if h1 has Sumw2 set, Sumw2 is automatically called for this
951/// if not already set.
952///
953/// Note also that adding histogram with labels is not supported, histogram will be
954/// added merging them by bin number independently of the labels.
955/// For adding histogram with labels one should use TH1::Merge
956///
957/// SPECIAL CASE (Average/Efficiency histograms)
958/// For histograms representing averages or efficiencies, one should compute the average
959/// of the two histograms and not the sum. One can mark a histogram to be an average
960/// histogram by setting its bit kIsAverage with
961/// myhist.SetBit(TH1::kIsAverage);
962/// Note that the two histograms must have their kIsAverage bit set
963///
964/// IMPORTANT NOTE1: If you intend to use the errors of this histogram later
965/// you should call Sumw2 before making this operation.
966/// This is particularly important if you fit the histogram after TH1::Add
967///
968/// IMPORTANT NOTE2: if h1 has a normalisation factor, the normalisation factor
969/// is used , ie this = this + c1*factor*h1
970/// Use the other TH1::Add function if you do not want this feature
971///
972/// IMPORTANT NOTE3: You should be careful about the statistics of the
973/// returned histogram, whose statistics may be binned or unbinned,
974/// depending on whether c1 is negative, whether TAxis::kAxisRange is true,
975/// and whether TH1::ResetStats has been called on either this or h1.
976/// See TH1::GetStats.
977///
978/// The function return kFALSE if the Add operation failed
979
981{
982 if (!h1) {
983 Error("Add","Attempt to add a non-existing histogram");
984 return kFALSE;
985 }
986
987 // delete buffer if it is there since it will become invalid
988 if (fBuffer) BufferEmpty(1);
989
990 bool useMerge = false;
991 const bool considerMerge = (c1 == 1. && !this->TestBit(kIsAverage) && !h1->TestBit(kIsAverage) );
992 const auto inconsistency = LoggedInconsistency("Add", this, h1, considerMerge);
993 // If there is a bad inconsistency and we can't even consider merging, just give up
995 return false;
996 }
997 // If there is an inconsistency, we try to use merging
1000 }
1001
1002 if (useMerge) {
1003 TList l;
1004 l.Add(const_cast<TH1*>(h1));
1005 auto iret = Merge(&l);
1006 return (iret >= 0);
1007 }
1008
1009 // Create Sumw2 if h1 has Sumw2 set
1010 if (fSumw2.fN == 0 && h1->GetSumw2N() != 0) Sumw2();
1011 // In addition, create Sumw2 if is not a simple addition, otherwise errors will not be correctly computed
1012 if (fSumw2.fN == 0 && c1 != 1.0) Sumw2();
1013
1014 // - Add statistics (for c1=1)
1016
1017 // statistics can be preserved only in case of positive coefficients
1018 // otherwise with negative c1 (histogram subtraction) one risks to get negative variances
1019 Bool_t resetStats = (c1 < 0);
1020 Double_t s1[kNstat] = {0};
1021 Double_t s2[kNstat] = {0};
1022 if (!resetStats) {
1023 // need to initialize to zero s1 and s2 since
1024 // GetStats fills only used elements depending on dimension and type
1025 GetStats(s1);
1026 h1->GetStats(s2);
1027 }
1028
1029 SetMinimum();
1030 SetMaximum();
1031
1032 // - Loop on bins (including underflows/overflows)
1033 Double_t factor = 1;
1034 if (h1->GetNormFactor() != 0) factor = h1->GetNormFactor()/h1->GetSumOfWeights();
1035 Double_t c1sq = c1 * c1;
1036 Double_t factsq = factor * factor;
1037
1038 for (Int_t bin = 0; bin < fNcells; ++bin) {
1039 //special case where histograms have the kIsAverage bit set
1040 if (this->TestBit(kIsAverage) && h1->TestBit(kIsAverage)) {
1045 Double_t w1 = 1., w2 = 1.;
1046
1047 // consider all special cases when bin errors are zero
1048 // see http://root-forum.cern.ch/viewtopic.php?f=3&t=13299
1049 if (e1sq) w1 = 1. / e1sq;
1050 else if (h1->fSumw2.fN) {
1051 w1 = 1.E200; // use an arbitrary huge value
1052 if (y1 == 0) {
1053 // use an estimated error from the global histogram scale
1054 double sf = (s2[0] != 0) ? s2[1]/s2[0] : 1;
1055 w1 = 1./(sf*sf);
1056 }
1057 }
1058 if (e2sq) w2 = 1. / e2sq;
1059 else if (fSumw2.fN) {
1060 w2 = 1.E200; // use an arbitrary huge value
1061 if (y2 == 0) {
1062 // use an estimated error from the global histogram scale
1063 double sf = (s1[0] != 0) ? s1[1]/s1[0] : 1;
1064 w2 = 1./(sf*sf);
1065 }
1066 }
1067
1068 double y = (w1*y1 + w2*y2)/(w1 + w2);
1070 if (fSumw2.fN) {
1071 double err2 = 1./(w1 + w2);
1072 if (err2 < 1.E-200) err2 = 0; // to remove arbitrary value when e1=0 AND e2=0
1073 fSumw2.fArray[bin] = err2;
1074 }
1075 } else { // normal case of addition between histograms
1078 }
1079 }
1080
1081 // update statistics (do here to avoid changes by SetBinContent)
1082 if (resetStats) {
1083 // statistics need to be reset in case coefficient are negative
1084 ResetStats();
1085 }
1086 else {
1087 for (Int_t i=0;i<kNstat;i++) {
1088 if (i == 1) s1[i] += c1*c1*s2[i];
1089 else s1[i] += c1*s2[i];
1090 }
1091 PutStats(s1);
1092 if (c1 == 1.0)
1094 else {
1095 // compute entries as effective entries in case of
1096 // weights different than 1
1097 double sumw2 = 0;
1098 double sumw = GetSumOfAllWeights(true, &sumw2);
1099 if (sumw2 > 0) SetEntries( sumw*sumw/sumw2);
1100 }
1101 }
1102 return kTRUE;
1103}
1104
1105////////////////////////////////////////////////////////////////////////////////
1106/// Replace contents of this histogram by the addition of h1 and h2.
1107///
1108/// `this = c1*h1 + c2*h2`
1109/// if errors are defined (see TH1::Sumw2), errors are also recalculated
1110///
1111/// Note that if h1 or h2 have Sumw2 set, Sumw2 is automatically called for this
1112/// if not already set.
1113///
1114/// Note also that adding histogram with labels is not supported, histogram will be
1115/// added merging them by bin number independently of the labels.
1116/// For adding histogram ith labels one should use TH1::Merge
1117///
1118/// SPECIAL CASE (Average/Efficiency histograms)
1119/// For histograms representing averages or efficiencies, one should compute the average
1120/// of the two histograms and not the sum. One can mark a histogram to be an average
1121/// histogram by setting its bit kIsAverage with
1122/// myhist.SetBit(TH1::kIsAverage);
1123/// Note that the two histograms must have their kIsAverage bit set
1124///
1125/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
1126/// you should call Sumw2 before making this operation.
1127/// This is particularly important if you fit the histogram after TH1::Add
1128///
1129/// IMPORTANT NOTE2: You should be careful about the statistics of the
1130/// returned histogram, whose statistics may be binned or unbinned,
1131/// depending on whether c1 is negative, whether TAxis::kAxisRange is true,
1132/// and whether TH1::ResetStats has been called on either this or h1.
1133/// See TH1::GetStats.
1134///
1135/// ANOTHER SPECIAL CASE : h1 = h2 and c2 < 0
1136/// do a scaling this = c1 * h1 / (bin Volume)
1137///
1138/// The function returns kFALSE if the Add operation failed
1139
1141{
1142
1143 if (!h1 || !h2) {
1144 Error("Add","Attempt to add a non-existing histogram");
1145 return kFALSE;
1146 }
1147
1148 // delete buffer if it is there since it will become invalid
1149 if (fBuffer) BufferEmpty(1);
1150
1152 if (h1 == h2 && c2 < 0) {c2 = 0; normWidth = kTRUE;}
1153
1154 if (h1 != h2) {
1155 bool useMerge = false;
1156 const bool considerMerge = (c1 == 1. && c2 == 1. && !this->TestBit(kIsAverage) && !h1->TestBit(kIsAverage) );
1157
1158 // We can combine inconsistencies like this, since they are ordered and a
1159 // higher inconsistency is worse
1160 auto const inconsistency = std::max(LoggedInconsistency("Add", this, h1, considerMerge),
1161 LoggedInconsistency("Add", h1, h2, considerMerge));
1162
1163 // If there is a bad inconsistency and we can't even consider merging, just give up
1165 return false;
1166 }
1167 // If there is an inconsistency, we try to use merging
1170 }
1171
1172 if (useMerge) {
1173 TList l;
1174 // why TList takes non-const pointers ????
1175 l.Add(const_cast<TH1*>(h1));
1176 l.Add(const_cast<TH1*>(h2));
1177 Reset("ICE");
1178 auto iret = Merge(&l);
1179 return (iret >= 0);
1180 }
1181 }
1182
1183 // Create Sumw2 if h1 or h2 have Sumw2 set
1184 if (fSumw2.fN == 0 && (h1->GetSumw2N() != 0 || h2->GetSumw2N() != 0)) Sumw2();
1185 // Create also Sumw2 if not a simple addition (c1 = 1, c2 = 1)
1186 if (fSumw2.fN == 0 && (c1 != 1.0 || c2 != 1.0)) Sumw2();
1187 // - Add statistics
1189
1190 // TODO remove
1191 // statistics can be preserved only in case of positive coefficients
1192 // otherwise with negative c1 (histogram subtraction) one risks to get negative variances
1193 // also in case of scaling with the width we cannot preserve the statistics
1194 Double_t s1[kNstat] = {0};
1195 Double_t s2[kNstat] = {0};
1197
1198
1199 Bool_t resetStats = (c1*c2 < 0) || normWidth;
1200 if (!resetStats) {
1201 // need to initialize to zero s1 and s2 since
1202 // GetStats fills only used elements depending on dimension and type
1203 h1->GetStats(s1);
1204 h2->GetStats(s2);
1205 for (Int_t i=0;i<kNstat;i++) {
1206 if (i == 1) s3[i] = c1*c1*s1[i] + c2*c2*s2[i];
1207 //else s3[i] = TMath::Abs(c1)*s1[i] + TMath::Abs(c2)*s2[i];
1208 else s3[i] = c1*s1[i] + c2*s2[i];
1209 }
1210 }
1211
1212 SetMinimum();
1213 SetMaximum();
1214
1215 if (normWidth) { // DEPRECATED CASE: belongs to fitting / drawing modules
1216
1217 Int_t nbinsx = GetNbinsX() + 2; // normal bins + underflow, overflow
1218 Int_t nbinsy = GetNbinsY() + 2;
1219 Int_t nbinsz = GetNbinsZ() + 2;
1220
1221 if (fDimension < 2) nbinsy = 1;
1222 if (fDimension < 3) nbinsz = 1;
1223
1224 Int_t bin, binx, biny, binz;
1225 for (binz = 0; binz < nbinsz; ++binz) {
1227 for (biny = 0; biny < nbinsy; ++biny) {
1229 for (binx = 0; binx < nbinsx; ++binx) {
1231 bin = GetBin(binx, biny, binz);
1232 Double_t w = wx*wy*wz;
1234 if (fSumw2.fN) {
1236 fSumw2.fArray[bin] = c1*c1*e1*e1;
1237 }
1238 }
1239 }
1240 }
1241 } else if (h1->TestBit(kIsAverage) && h2->TestBit(kIsAverage)) {
1242 for (Int_t i = 0; i < fNcells; ++i) { // loop on cells (bins including underflow / overflow)
1243 // special case where histograms have the kIsAverage bit set
1248 Double_t w1 = 1., w2 = 1.;
1249
1250 // consider all special cases when bin errors are zero
1251 // see http://root-forum.cern.ch/viewtopic.php?f=3&t=13299
1252 if (e1sq) w1 = 1./ e1sq;
1253 else if (h1->fSumw2.fN) {
1254 w1 = 1.E200; // use an arbitrary huge value
1255 if (y1 == 0 ) { // use an estimated error from the global histogram scale
1256 double sf = (s1[0] != 0) ? s1[1]/s1[0] : 1;
1257 w1 = 1./(sf*sf);
1258 }
1259 }
1260 if (e2sq) w2 = 1./ e2sq;
1261 else if (h2->fSumw2.fN) {
1262 w2 = 1.E200; // use an arbitrary huge value
1263 if (y2 == 0) { // use an estimated error from the global histogram scale
1264 double sf = (s2[0] != 0) ? s2[1]/s2[0] : 1;
1265 w2 = 1./(sf*sf);
1266 }
1267 }
1268
1269 double y = (w1*y1 + w2*y2)/(w1 + w2);
1270 UpdateBinContent(i, y);
1271 if (fSumw2.fN) {
1272 double err2 = 1./(w1 + w2);
1273 if (err2 < 1.E-200) err2 = 0; // to remove arbitrary value when e1=0 AND e2=0
1274 fSumw2.fArray[i] = err2;
1275 }
1276 }
1277 } else { // case of simple histogram addition
1278 Double_t c1sq = c1 * c1;
1279 Double_t c2sq = c2 * c2;
1280 for (Int_t i = 0; i < fNcells; ++i) { // Loop on cells (bins including underflows/overflows)
1282 if (fSumw2.fN) {
1284 }
1285 }
1286 }
1287
1288 if (resetStats) {
1289 // statistics need to be reset in case coefficient are negative
1290 ResetStats();
1291 }
1292 else {
1293 // update statistics
1294 PutStats(s3);
1295 // previous entries are correct only if c1=1 and c2=1
1296 if (c1 == 1.0 && c2 == 1.0)
1298 else {
1299 // compute entries as effective entries in case of
1300 // weights different than 1
1301 double sumw2 = 0;
1302 double sumw = GetSumOfAllWeights(true, &sumw2);
1303 if (sumw2 > 0) SetEntries( sumw*sumw/sumw2);
1304 }
1305 }
1306
1307 return kTRUE;
1308}
1309
1310////////////////////////////////////////////////////////////////////////////////
1311/// Sets the flag controlling the automatic add of histograms in memory.
1312///
1313/// By default (fAddDirectory = kTRUE), histograms are automatically added
1314/// to the current directory (gDirectory).
1315/// Note that one histogram can be removed from its support directory
1316/// by calling h->SetDirectory(nullptr) or h->SetDirectory(dir) to add it
1317/// to the list of objects in the directory dir.
1318///
1319/// This is a static function. To call it, use `TH1::AddDirectory`
1320///
1321/// \deprecated Use ROOT::Experimental::ObjectAutoRegistrationEnabled(). It can be
1322/// set using an entry in rootrc or an environment variable, is initialised in a
1323/// thread-safe manner and covers more cases.
1324
1326{
1327 fgAddDirectory = add;
1328}
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Auxiliary function to get the power of 2 next (larger) or previous (smaller)
1332/// a given x
1333///
1334/// next = kTRUE : next larger
1335/// next = kFALSE : previous smaller
1336///
1337/// Used by the autobin power of 2 algorithm
1338
1340{
1341 Int_t nn;
1342 Double_t f2 = std::frexp(x, &nn);
1343 return ((next && x > 0.) || (!next && x <= 0.)) ? std::ldexp(std::copysign(1., f2), nn)
1344 : std::ldexp(std::copysign(1., f2), --nn);
1345}
1346
1347////////////////////////////////////////////////////////////////////////////////
1348/// Auxiliary function to get the next power of 2 integer value larger then n
1349///
1350/// Used by the autobin power of 2 algorithm
1351
1353{
1354 Int_t nn;
1355 Double_t f2 = std::frexp(n, &nn);
1356 if (TMath::Abs(f2 - .5) > 0.001)
1357 return (Int_t)std::ldexp(1., nn);
1358 return n;
1359}
1360
1361////////////////////////////////////////////////////////////////////////////////
1362/// Buffer-based estimate of the histogram range using the power of 2 algorithm.
1363///
1364/// Used by the autobin power of 2 algorithm.
1365///
1366/// Works on arguments (min and max from fBuffer) and internal inputs: fXmin,
1367/// fXmax, NBinsX (from fXaxis), ...
1368/// Result save internally in fXaxis.
1369///
1370/// Overloaded by TH2 and TH3.
1371///
1372/// Return -1 if internal inputs are inconsistent, 0 otherwise.
1373
1375{
1376 // We need meaningful raw limits
1377 if (xmi >= xma)
1378 return -1;
1379
1380 THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this, xmi, xma);
1383
1384 // Now adjust
1385 if (TMath::Abs(xhma) > TMath::Abs(xhmi)) {
1386 // Start from the upper limit
1389 } else {
1390 // Start from the lower limit
1393 }
1394
1395 // Round the bins to the next power of 2; take into account the possible inflation
1396 // of the range
1397 Double_t rr = (xhma - xhmi) / (xma - xmi);
1399
1400 // Adjust using the same bin width and offsets
1401 Double_t bw = (xhma - xhmi) / nb;
1402 // Bins to left free on each side
1403 Double_t autoside = gEnv->GetValue("Hist.Binning.Auto.Side", 0.05);
1404 Int_t nbside = (Int_t)(nb * autoside);
1405
1406 // Side up
1407 Int_t nbup = (xhma - xma) / bw;
1408 if (nbup % 2 != 0)
1409 nbup++; // Must be even
1410 if (nbup != nbside) {
1411 // Accounts also for both case: larger or smaller
1412 xhma -= bw * (nbup - nbside);
1413 nb -= (nbup - nbside);
1414 }
1415
1416 // Side low
1417 Int_t nblw = (xmi - xhmi) / bw;
1418 if (nblw % 2 != 0)
1419 nblw++; // Must be even
1420 if (nblw != nbside) {
1421 // Accounts also for both case: larger or smaller
1422 xhmi += bw * (nblw - nbside);
1423 nb -= (nblw - nbside);
1424 }
1425
1426 // Set everything and project
1427 SetBins(nb, xhmi, xhma);
1428
1429 // Done
1430 return 0;
1431}
1432
1433/// Fill histogram with all entries in the buffer.
1434///
1435/// - action = -1 histogram is reset and refilled from the buffer (called by THistPainter::Paint)
1436/// - action = 0 histogram is reset and filled from the buffer. When the histogram is filled from the
1437/// buffer the value fBuffer[0] is set to a negative number (= - number of entries)
1438/// When calling with action == 0 the histogram is NOT refilled when fBuffer[0] is < 0
1439/// While when calling with action = -1 the histogram is reset and ALWAYS refilled independently if
1440/// the histogram was filled before. This is needed when drawing the histogram
1441/// - action = 1 histogram is filled and buffer is deleted
1442/// The buffer is automatically deleted when filling the histogram and the entries is
1443/// larger than the buffer size
1444
1446{
1447 // do we need to compute the bin size?
1448 if (!fBuffer) return 0;
1450
1451 // nbentries correspond to the number of entries of histogram
1452
1453 if (nbentries == 0) {
1454 // if action is 1 we delete the buffer
1455 // this will avoid infinite recursion
1456 if (action > 0) {
1457 delete [] fBuffer;
1458 fBuffer = nullptr;
1459 fBufferSize = 0;
1460 }
1461 return 0;
1462 }
1463 if (nbentries < 0 && action == 0) return 0; // case histogram has been already filled from the buffer
1464
1465 Double_t *buffer = fBuffer;
1466 if (nbentries < 0) {
1468 // a reset might call BufferEmpty() giving an infinite recursion
1469 // Protect it by setting fBuffer = nullptr
1470 fBuffer = nullptr;
1471 //do not reset the list of functions
1472 Reset("ICES");
1473 fBuffer = buffer;
1474 }
1475 if (CanExtendAllAxes() || (fXaxis.GetXmax() <= fXaxis.GetXmin())) {
1476 //find min, max of entries in buffer
1479 for (Int_t i=0;i<nbentries;i++) {
1480 Double_t x = fBuffer[2*i+2];
1481 // skip infinity or NaN values
1482 if (!std::isfinite(x)) continue;
1483 if (x < xmin) xmin = x;
1484 if (x > xmax) xmax = x;
1485 }
1486 if (fXaxis.GetXmax() <= fXaxis.GetXmin()) {
1487 Int_t rc = -1;
1489 if ((rc = AutoP2FindLimits(xmin, xmax)) < 0)
1490 Warning("BufferEmpty",
1491 "inconsistency found by power-of-2 autobin algorithm: fallback to standard method");
1492 }
1493 if (rc < 0)
1494 THLimitsFinder::GetLimitsFinder()->FindGoodLimits(this, xmin, xmax);
1495 } else {
1496 fBuffer = nullptr;
1499 if (xmax >= fXaxis.GetXmax()) ExtendAxis(xmax, &fXaxis);
1500 fBuffer = buffer;
1501 fBufferSize = keep;
1502 }
1503 }
1504
1505 // call DoFillN which will not put entries in the buffer as FillN does
1506 // set fBuffer to zero to avoid re-emptying the buffer from functions called
1507 // by DoFillN (e.g Sumw2)
1508 buffer = fBuffer; fBuffer = nullptr;
1509 DoFillN(nbentries,&buffer[2],&buffer[1],2);
1510 fBuffer = buffer;
1511
1512 // if action == 1 - delete the buffer
1513 if (action > 0) {
1514 delete [] fBuffer;
1515 fBuffer = nullptr;
1516 fBufferSize = 0;
1517 } else {
1518 // if number of entries is consistent with buffer - set it negative to avoid
1519 // refilling the histogram every time BufferEmpty(0) is called
1520 // In case it is not consistent, by setting fBuffer[0]=0 is like resetting the buffer
1521 // (it will not be used anymore the next time BufferEmpty is called)
1522 if (nbentries == (Int_t)fEntries)
1523 fBuffer[0] = -nbentries;
1524 else
1525 fBuffer[0] = 0;
1526 }
1527 return nbentries;
1528}
1529
1530////////////////////////////////////////////////////////////////////////////////
1531/// accumulate arguments in buffer. When buffer is full, empty the buffer
1532///
1533/// - `fBuffer[0]` = number of entries in buffer
1534/// - `fBuffer[1]` = w of first entry
1535/// - `fBuffer[2]` = x of first entry
1536
1538{
1539 if (!fBuffer) return -2;
1541
1542
1543 if (nbentries < 0) {
1544 // reset nbentries to a positive value so next time BufferEmpty() is called
1545 // the histogram will be refilled
1547 fBuffer[0] = nbentries;
1548 if (fEntries > 0) {
1549 // set fBuffer to zero to avoid calling BufferEmpty in Reset
1550 Double_t *buffer = fBuffer; fBuffer=nullptr;
1551 Reset("ICES"); // do not reset list of functions
1552 fBuffer = buffer;
1553 }
1554 }
1555 if (2*nbentries+2 >= fBufferSize) {
1556 BufferEmpty(1);
1557 if (!fBuffer)
1558 // to avoid infinite recursion Fill->BufferFill->Fill
1559 return Fill(x,w);
1560 // this cannot happen
1561 R__ASSERT(0);
1562 }
1563 fBuffer[2*nbentries+1] = w;
1564 fBuffer[2*nbentries+2] = x;
1565 fBuffer[0] += 1;
1566 return -2;
1567}
1568
1569////////////////////////////////////////////////////////////////////////////////
1570/// Check bin limits.
1571
1572bool TH1::CheckBinLimits(const TAxis* a1, const TAxis * a2)
1573{
1574 const TArrayD * h1Array = a1->GetXbins();
1575 const TArrayD * h2Array = a2->GetXbins();
1576 Int_t fN = h1Array->fN;
1577 if ( fN != 0 ) {
1578 if ( h2Array->fN != fN ) {
1579 return false;
1580 }
1581 else {
1582 for ( int i = 0; i < fN; ++i ) {
1583 // for i==fN (nbin+1) a->GetBinWidth() returns last bin width
1584 // we do not need to exclude that case
1585 double binWidth = a1->GetBinWidth(i);
1586 if ( ! TMath::AreEqualAbs( h1Array->GetAt(i), h2Array->GetAt(i), binWidth*1E-10 ) ) {
1587 return false;
1588 }
1589 }
1590 }
1591 }
1592
1593 return true;
1594}
1595
1596////////////////////////////////////////////////////////////////////////////////
1597/// Check that axis have same labels.
1598
1599bool TH1::CheckBinLabels(const TAxis* a1, const TAxis * a2)
1600{
1601 THashList *l1 = a1->GetLabels();
1602 THashList *l2 = a2->GetLabels();
1603
1604 if (!l1 && !l2 )
1605 return true;
1606 if (!l1 || !l2 ) {
1607 return false;
1608 }
1609 // check now labels sizes are the same
1610 if (l1->GetSize() != l2->GetSize() ) {
1611 return false;
1612 }
1613 for (int i = 1; i <= a1->GetNbins(); ++i) {
1614 TString label1 = a1->GetBinLabel(i);
1615 TString label2 = a2->GetBinLabel(i);
1616 if (label1 != label2) {
1617 return false;
1618 }
1619 }
1620
1621 return true;
1622}
1623
1624////////////////////////////////////////////////////////////////////////////////
1625/// Check that the axis limits of the histograms are the same.
1626/// If a first and last bin is passed the axis is compared between the given range
1627
1628bool TH1::CheckAxisLimits(const TAxis *a1, const TAxis *a2 )
1629{
1630 double firstBin = a1->GetBinWidth(1);
1631 double lastBin = a1->GetBinWidth( a1->GetNbins() );
1632 if ( ! TMath::AreEqualAbs(a1->GetXmin(), a2->GetXmin(), firstBin* 1.E-10) ||
1633 ! TMath::AreEqualAbs(a1->GetXmax(), a2->GetXmax(), lastBin*1.E-10) ) {
1634 return false;
1635 }
1636 return true;
1637}
1638
1639////////////////////////////////////////////////////////////////////////////////
1640/// Check that the axis are the same
1641
1642bool TH1::CheckEqualAxes(const TAxis *a1, const TAxis *a2 )
1643{
1644 if (a1->GetNbins() != a2->GetNbins() ) {
1645 ::Info("CheckEqualAxes","Axes have different number of bins : nbin1 = %d nbin2 = %d",a1->GetNbins(),a2->GetNbins() );
1646 return false;
1647 }
1648 if(!CheckAxisLimits(a1,a2)) {
1649 ::Info("CheckEqualAxes","Axes have different limits");
1650 return false;
1651 }
1652 if(!CheckBinLimits(a1,a2)) {
1653 ::Info("CheckEqualAxes","Axes have different bin limits");
1654 return false;
1655 }
1656
1657 // check labels
1658 if(!CheckBinLabels(a1,a2)) {
1659 ::Info("CheckEqualAxes","Axes have different labels");
1660 return false;
1661 }
1662
1663 return true;
1664}
1665
1666////////////////////////////////////////////////////////////////////////////////
1667/// Check that two sub axis are the same.
1668/// The limits are defined by first bin and last bin
1669/// N.B. no check is done in this case for variable bins
1670
1672{
1673 // By default is assumed that no bins are given for the second axis
1675 Double_t xmin1 = a1->GetBinLowEdge(firstBin1);
1676 Double_t xmax1 = a1->GetBinUpEdge(lastBin1);
1677
1678 Int_t nbins2 = a2->GetNbins();
1679 Double_t xmin2 = a2->GetXmin();
1680 Double_t xmax2 = a2->GetXmax();
1681
1682 if (firstBin2 < lastBin2) {
1683 // in this case assume no bins are given for the second axis
1685 xmin2 = a1->GetBinLowEdge(firstBin1);
1686 xmax2 = a1->GetBinUpEdge(lastBin1);
1687 }
1688
1689 if (nbins1 != nbins2 ) {
1690 ::Info("CheckConsistentSubAxes","Axes have different number of bins");
1691 return false;
1692 }
1693
1694 Double_t firstBin = a1->GetBinWidth(firstBin1);
1695 Double_t lastBin = a1->GetBinWidth(lastBin1);
1696 if ( ! TMath::AreEqualAbs(xmin1,xmin2,1.E-10 * firstBin) ||
1697 ! TMath::AreEqualAbs(xmax1,xmax2,1.E-10 * lastBin) ) {
1698 ::Info("CheckConsistentSubAxes","Axes have different limits");
1699 return false;
1700 }
1701
1702 return true;
1703}
1704
1705////////////////////////////////////////////////////////////////////////////////
1706/// Check histogram compatibility.
1707/// The returned integer is part of EInconsistencyBits
1708/// The value 0 means that the histograms are compatible
1709
1711{
1712 if (h1 == h2) return kFullyConsistent;
1713
1714 if (h1->GetDimension() != h2->GetDimension() ) {
1715 return kDifferentDimensions;
1716 }
1717 Int_t dim = h1->GetDimension();
1718
1719 // returns kTRUE if number of bins and bin limits are identical
1720 Int_t nbinsx = h1->GetNbinsX();
1721 Int_t nbinsy = h1->GetNbinsY();
1722 Int_t nbinsz = h1->GetNbinsZ();
1723
1724 // Check whether the histograms have the same number of bins.
1725 if (nbinsx != h2->GetNbinsX() ||
1726 (dim > 1 && nbinsy != h2->GetNbinsY()) ||
1727 (dim > 2 && nbinsz != h2->GetNbinsZ()) ) {
1729 }
1730
1731 bool ret = true;
1732
1733 // check axis limits
1734 ret &= CheckAxisLimits(h1->GetXaxis(), h2->GetXaxis());
1735 if (dim > 1) ret &= CheckAxisLimits(h1->GetYaxis(), h2->GetYaxis());
1736 if (dim > 2) ret &= CheckAxisLimits(h1->GetZaxis(), h2->GetZaxis());
1737 if (!ret) return kDifferentAxisLimits;
1738
1739 // check bin limits
1740 ret &= CheckBinLimits(h1->GetXaxis(), h2->GetXaxis());
1741 if (dim > 1) ret &= CheckBinLimits(h1->GetYaxis(), h2->GetYaxis());
1742 if (dim > 2) ret &= CheckBinLimits(h1->GetZaxis(), h2->GetZaxis());
1743 if (!ret) return kDifferentBinLimits;
1744
1745 // check labels if histograms are both not empty
1746 if ( !h1->IsEmpty() && !h2->IsEmpty() ) {
1747 ret &= CheckBinLabels(h1->GetXaxis(), h2->GetXaxis());
1748 if (dim > 1) ret &= CheckBinLabels(h1->GetYaxis(), h2->GetYaxis());
1749 if (dim > 2) ret &= CheckBinLabels(h1->GetZaxis(), h2->GetZaxis());
1750 if (!ret) return kDifferentLabels;
1751 }
1752
1753 return kFullyConsistent;
1754}
1755
1756////////////////////////////////////////////////////////////////////////////////
1757/// \f$ \chi^{2} \f$ test for comparing weighted and unweighted histograms.
1758///
1759/// Compares the histograms' adjusted (normalized) residuals.
1760/// Function: Returns p-value. Other return values are specified by the 3rd parameter
1761///
1762/// \param[in] h2 the second histogram
1763/// \param[in] option
1764/// - "UU" = experiment experiment comparison (unweighted-unweighted)
1765/// - "UW" = experiment MC comparison (unweighted-weighted). Note that
1766/// the first histogram should be unweighted
1767/// - "WW" = MC MC comparison (weighted-weighted)
1768/// - "NORM" = to be used when one or both of the histograms is scaled
1769/// but the histogram originally was unweighted
1770/// - by default underflows and overflows are not included:
1771/// * "OF" = overflows included
1772/// * "UF" = underflows included
1773/// - "P" = print chi2, ndf, p_value, igood
1774/// - "CHI2" = returns chi2 instead of p-value
1775/// - "CHI2/NDF" = returns \f$ \chi^{2} \f$/ndf
1776/// \param[in] res not empty - computes normalized residuals and returns them in this array
1777///
1778/// The current implementation is based on the papers \f$ \chi^{2} \f$ test for comparison
1779/// of weighted and unweighted histograms" in Proceedings of PHYSTAT05 and
1780/// "Comparison weighted and unweighted histograms", arXiv:physics/0605123
1781/// by N.Gagunashvili. This function has been implemented by Daniel Haertl in August 2006.
1782///
1783/// #### Introduction:
1784///
1785/// A frequently used technique in data analysis is the comparison of
1786/// histograms. First suggested by Pearson [1] the \f$ \chi^{2} \f$ test of
1787/// homogeneity is used widely for comparing usual (unweighted) histograms.
1788/// This paper describes the implementation modified \f$ \chi^{2} \f$ tests
1789/// for comparison of weighted and unweighted histograms and two weighted
1790/// histograms [2] as well as usual Pearson's \f$ \chi^{2} \f$ test for
1791/// comparison two usual (unweighted) histograms.
1792///
1793/// #### Overview:
1794///
1795/// Comparison of two histograms expect hypotheses that two histograms
1796/// represent identical distributions. To make a decision p-value should
1797/// be calculated. The hypotheses of identity is rejected if the p-value is
1798/// lower then some significance level. Traditionally significance levels
1799/// 0.1, 0.05 and 0.01 are used. The comparison procedure should include an
1800/// analysis of the residuals which is often helpful in identifying the
1801/// bins of histograms responsible for a significant overall \f$ \chi^{2} \f$ value.
1802/// Residuals are the difference between bin contents and expected bin
1803/// contents. Most convenient for analysis are the normalized residuals. If
1804/// hypotheses of identity are valid then normalized residuals are
1805/// approximately independent and identically distributed random variables
1806/// having N(0,1) distribution. Analysis of residuals expect test of above
1807/// mentioned properties of residuals. Notice that indirectly the analysis
1808/// of residuals increase the power of \f$ \chi^{2} \f$ test.
1809///
1810/// #### Methods of comparison:
1811///
1812/// \f$ \chi^{2} \f$ test for comparison two (unweighted) histograms:
1813/// Let us consider two histograms with the same binning and the number
1814/// of bins equal to r. Let us denote the number of events in the ith bin
1815/// in the first histogram as ni and as mi in the second one. The total
1816/// number of events in the first histogram is equal to:
1817/// \f[
1818/// N = \sum_{i=1}^{r} n_{i}
1819/// \f]
1820/// and
1821/// \f[
1822/// M = \sum_{i=1}^{r} m_{i}
1823/// \f]
1824/// in the second histogram. The hypothesis of identity (homogeneity) [3]
1825/// is that the two histograms represent random values with identical
1826/// distributions. It is equivalent that there exist r constants p1,...,pr,
1827/// such that
1828/// \f[
1829///\sum_{i=1}^{r} p_{i}=1
1830/// \f]
1831/// and the probability of belonging to the ith bin for some measured value
1832/// in both experiments is equal to pi. The number of events in the ith
1833/// bin is a random variable with a distribution approximated by a Poisson
1834/// probability distribution
1835/// \f[
1836///\frac{e^{-Np_{i}}(Np_{i})^{n_{i}}}{n_{i}!}
1837/// \f]
1838///for the first histogram and with distribution
1839/// \f[
1840///\frac{e^{-Mp_{i}}(Mp_{i})^{m_{i}}}{m_{i}!}
1841/// \f]
1842/// for the second histogram. If the hypothesis of homogeneity is valid,
1843/// then the maximum likelihood estimator of pi, i=1,...,r, is
1844/// \f[
1845///\hat{p}_{i}= \frac{n_{i}+m_{i}}{N+M}
1846/// \f]
1847/// and then
1848/// \f[
1849/// X^{2} = \sum_{i=1}^{r}\frac{(n_{i}-N\hat{p}_{i})^{2}}{N\hat{p}_{i}} + \sum_{i=1}^{r}\frac{(m_{i}-M\hat{p}_{i})^{2}}{M\hat{p}_{i}} =\frac{1}{MN} \sum_{i=1}^{r}\frac{(Mn_{i}-Nm_{i})^{2}}{n_{i}+m_{i}}
1850/// \f]
1851/// has approximately a \f$ \chi^{2}_{(r-1)} \f$ distribution [3].
1852/// The comparison procedure can include an analysis of the residuals which
1853/// is often helpful in identifying the bins of histograms responsible for
1854/// a significant overall \f$ \chi^{2} \f$ value. Most convenient for
1855/// analysis are the adjusted (normalized) residuals [4]
1856/// \f[
1857/// r_{i} = \frac{n_{i}-N\hat{p}_{i}}{\sqrt{N\hat{p}_{i}}\sqrt{(1-N/(N+M))(1-(n_{i}+m_{i})/(N+M))}}
1858/// \f]
1859/// If hypotheses of homogeneity are valid then residuals ri are
1860/// approximately independent and identically distributed random variables
1861/// having N(0,1) distribution. The application of the \f$ \chi^{2} \f$ test has
1862/// restrictions related to the value of the expected frequencies Npi,
1863/// Mpi, i=1,...,r. A conservative rule formulated in [5] is that all the
1864/// expectations must be 1 or greater for both histograms. In practical
1865/// cases when expected frequencies are not known the estimated expected
1866/// frequencies \f$ M\hat{p}_{i}, N\hat{p}_{i}, i=1,...,r \f$ can be used.
1867///
1868/// #### Unweighted and weighted histograms comparison:
1869///
1870/// A simple modification of the ideas described above can be used for the
1871/// comparison of the usual (unweighted) and weighted histograms. Let us
1872/// denote the number of events in the ith bin in the unweighted
1873/// histogram as ni and the common weight of events in the ith bin of the
1874/// weighted histogram as wi. The total number of events in the
1875/// unweighted histogram is equal to
1876///\f[
1877/// N = \sum_{i=1}^{r} n_{i}
1878///\f]
1879/// and the total weight of events in the weighted histogram is equal to
1880///\f[
1881/// W = \sum_{i=1}^{r} w_{i}
1882///\f]
1883/// Let us formulate the hypothesis of identity of an unweighted histogram
1884/// to a weighted histogram so that there exist r constants p1,...,pr, such
1885/// that
1886///\f[
1887/// \sum_{i=1}^{r} p_{i} = 1
1888///\f]
1889/// for the unweighted histogram. The weight wi is a random variable with a
1890/// distribution approximated by the normal probability distribution
1891/// \f$ N(Wp_{i},\sigma_{i}^{2}) \f$ where \f$ \sigma_{i}^{2} \f$ is the variance of the weight wi.
1892/// If we replace the variance \f$ \sigma_{i}^{2} \f$
1893/// with estimate \f$ s_{i}^{2} \f$ (sum of squares of weights of
1894/// events in the ith bin) and the hypothesis of identity is valid, then the
1895/// maximum likelihood estimator of pi,i=1,...,r, is
1896///\f[
1897/// \hat{p}_{i} = \frac{Ww_{i}-Ns_{i}^{2}+\sqrt{(Ww_{i}-Ns_{i}^{2})^{2}+4W^{2}s_{i}^{2}n_{i}}}{2W^{2}}
1898///\f]
1899/// We may then use the test statistic
1900///\f[
1901/// X^{2} = \sum_{i=1}^{r} \frac{(n_{i}-N\hat{p}_{i})^{2}}{N\hat{p}_{i}} + \sum_{i=1}^{r} \frac{(w_{i}-W\hat{p}_{i})^{2}}{s_{i}^{2}}
1902///\f]
1903/// and it has approximately a \f$ \sigma^{2}_{(r-1)} \f$ distribution [2]. This test, as well
1904/// as the original one [3], has a restriction on the expected frequencies. The
1905/// expected frequencies recommended for the weighted histogram is more than 25.
1906/// The value of the minimal expected frequency can be decreased down to 10 for
1907/// the case when the weights of the events are close to constant. In the case
1908/// of a weighted histogram if the number of events is unknown, then we can
1909/// apply this recommendation for the equivalent number of events as
1910///\f[
1911/// n_{i}^{equiv} = \frac{ w_{i}^{2} }{ s_{i}^{2} }
1912///\f]
1913/// The minimal expected frequency for an unweighted histogram must be 1. Notice
1914/// that any usual (unweighted) histogram can be considered as a weighted
1915/// histogram with events that have constant weights equal to 1.
1916/// The variance \f$ z_{i}^{2} \f$ of the difference between the weight wi
1917/// and the estimated expectation value of the weight is approximately equal to:
1918///\f[
1919/// z_{i}^{2} = Var(w_{i}-W\hat{p}_{i}) = N\hat{p}_{i}(1-N\hat{p}_{i})\left(\frac{Ws_{i}^{2}}{\sqrt{(Ns_{i}^{2}-w_{i}W)^{2}+4W^{2}s_{i}^{2}n_{i}}}\right)^{2}+\frac{s_{i}^{2}}{4}\left(1+\frac{Ns_{i}^{2}-w_{i}W}{\sqrt{(Ns_{i}^{2}-w_{i}W)^{2}+4W^{2}s_{i}^{2}n_{i}}}\right)^{2}
1920///\f]
1921/// The residuals
1922///\f[
1923/// r_{i} = \frac{w_{i}-W\hat{p}_{i}}{z_{i}}
1924///\f]
1925/// have approximately a normal distribution with mean equal to 0 and standard
1926/// deviation equal to 1.
1927///
1928/// #### Two weighted histograms comparison:
1929///
1930/// Let us denote the common weight of events of the ith bin in the first
1931/// histogram as w1i and as w2i in the second one. The total weight of events
1932/// in the first histogram is equal to
1933///\f[
1934/// W_{1} = \sum_{i=1}^{r} w_{1i}
1935///\f]
1936/// and
1937///\f[
1938/// W_{2} = \sum_{i=1}^{r} w_{2i}
1939///\f]
1940/// in the second histogram. Let us formulate the hypothesis of identity of
1941/// weighted histograms so that there exist r constants p1,...,pr, such that
1942///\f[
1943/// \sum_{i=1}^{r} p_{i} = 1
1944///\f]
1945/// and also expectation value of weight w1i equal to W1pi and expectation value
1946/// of weight w2i equal to W2pi. Weights in both the histograms are random
1947/// variables with distributions which can be approximated by a normal
1948/// probability distribution \f$ N(W_{1}p_{i},\sigma_{1i}^{2}) \f$ for the first histogram
1949/// and by a distribution \f$ N(W_{2}p_{i},\sigma_{2i}^{2}) \f$ for the second.
1950/// Here \f$ \sigma_{1i}^{2} \f$ and \f$ \sigma_{2i}^{2} \f$ are the variances
1951/// of w1i and w2i with estimators \f$ s_{1i}^{2} \f$ and \f$ s_{2i}^{2} \f$ respectively.
1952/// If the hypothesis of identity is valid, then the maximum likelihood and
1953/// Least Square Method estimator of pi,i=1,...,r, is
1954///\f[
1955/// \hat{p}_{i} = \frac{w_{1i}W_{1}/s_{1i}^{2}+w_{2i}W_{2} /s_{2i}^{2}}{W_{1}^{2}/s_{1i}^{2}+W_{2}^{2}/s_{2i}^{2}}
1956///\f]
1957/// We may then use the test statistic
1958///\f[
1959/// X^{2} = \sum_{i=1}^{r} \frac{(w_{1i}-W_{1}\hat{p}_{i})^{2}}{s_{1i}^{2}} + \sum_{i=1}^{r} \frac{(w_{2i}-W_{2}\hat{p}_{i})^{2}}{s_{2i}^{2}} = \sum_{i=1}^{r} \frac{(W_{1}w_{2i}-W_{2}w_{1i})^{2}}{W_{1}^{2}s_{2i}^{2}+W_{2}^{2}s_{1i}^{2}}
1960///\f]
1961/// and it has approximately a \f$ \chi^{2}_{(r-1)} \f$ distribution [2].
1962/// The normalized or studentised residuals [6]
1963///\f[
1964/// r_{i} = \frac{w_{1i}-W_{1}\hat{p}_{i}}{s_{1i}\sqrt{1 - \frac{1}{(1+W_{2}^{2}s_{1i}^{2}/W_{1}^{2}s_{2i}^{2})}}}
1965///\f]
1966/// have approximately a normal distribution with mean equal to 0 and standard
1967/// deviation 1. A recommended minimal expected frequency is equal to 10 for
1968/// the proposed test.
1969///
1970/// #### Numerical examples:
1971///
1972/// The method described herein is now illustrated with an example.
1973/// We take a distribution
1974///\f[
1975/// \phi(x) = \frac{2}{(x-10)^{2}+1} + \frac{1}{(x-14)^{2}+1} (1)
1976///\f]
1977/// defined on the interval [4,16]. Events distributed according to the formula
1978/// (1) are simulated to create the unweighted histogram. Uniformly distributed
1979/// events are simulated for the weighted histogram with weights calculated by
1980/// formula (1). Each histogram has the same number of bins: 20. Fig.1 shows
1981/// the result of comparison of the unweighted histogram with 200 events
1982/// (minimal expected frequency equal to one) and the weighted histogram with
1983/// 500 events (minimal expected frequency equal to 25)
1984/// Begin_Macro
1985/// ../../../tutorials/math/chi2test.C
1986/// End_Macro
1987/// Fig 1. An example of comparison of the unweighted histogram with 200 events
1988/// and the weighted histogram with 500 events:
1989/// 1. unweighted histogram;
1990/// 2. weighted histogram;
1991/// 3. normalized residuals plot;
1992/// 4. normal Q-Q plot of residuals.
1993///
1994/// The value of the test statistic \f$ \chi^{2} \f$ is equal to
1995/// 21.09 with p-value equal to 0.33, therefore the hypothesis of identity of
1996/// the two histograms can be accepted for 0.05 significant level. The behavior
1997/// of the normalized residuals plot (see Fig. 1c) and the normal Q-Q plot
1998/// (see Fig. 1d) of residuals are regular and we cannot identify the outliers
1999/// or bins with a big influence on \f$ \chi^{2} \f$.
2000///
2001/// The second example presents the same two histograms but 17 events was added
2002/// to content of bin number 15 in unweighted histogram. Fig.2 shows the result
2003/// of comparison of the unweighted histogram with 217 events (minimal expected
2004/// frequency equal to one) and the weighted histogram with 500 events (minimal
2005/// expected frequency equal to 25)
2006/// Begin_Macro
2007/// ../../../tutorials/math/chi2test.C(17)
2008/// End_Macro
2009/// Fig 2. An example of comparison of the unweighted histogram with 217 events
2010/// and the weighted histogram with 500 events:
2011/// 1. unweighted histogram;
2012/// 2. weighted histogram;
2013/// 3. normalized residuals plot;
2014/// 4. normal Q-Q plot of residuals.
2015///
2016/// The value of the test statistic \f$ \chi^{2} \f$ is equal to
2017/// 32.33 with p-value equal to 0.029, therefore the hypothesis of identity of
2018/// the two histograms is rejected for 0.05 significant level. The behavior of
2019/// the normalized residuals plot (see Fig. 2c) and the normal Q-Q plot (see
2020/// Fig. 2d) of residuals are not regular and we can identify the outlier or
2021/// bin with a big influence on \f$ \chi^{2} \f$.
2022///
2023/// #### References:
2024///
2025/// - [1] Pearson, K., 1904. On the Theory of Contingency and Its Relation to
2026/// Association and Normal Correlation. Drapers' Co. Memoirs, Biometric
2027/// Series No. 1, London.
2028/// - [2] Gagunashvili, N., 2006. \f$ \sigma^{2} \f$ test for comparison
2029/// of weighted and unweighted histograms. Statistical Problems in Particle
2030/// Physics, Astrophysics and Cosmology, Proceedings of PHYSTAT05,
2031/// Oxford, UK, 12-15 September 2005, Imperial College Press, London, 43-44.
2032/// Gagunashvili,N., Comparison of weighted and unweighted histograms,
2033/// arXiv:physics/0605123, 2006.
2034/// - [3] Cramer, H., 1946. Mathematical methods of statistics.
2035/// Princeton University Press, Princeton.
2036/// - [4] Haberman, S.J., 1973. The analysis of residuals in cross-classified tables.
2037/// Biometrics 29, 205-220.
2038/// - [5] Lewontin, R.C. and Felsenstein, J., 1965. The robustness of homogeneity
2039/// test in 2xN tables. Biometrics 21, 19-33.
2040/// - [6] Seber, G.A.F., Lee, A.J., 2003, Linear Regression Analysis.
2041/// John Wiley & Sons Inc., New York.
2042
2043Double_t TH1::Chi2Test(const TH1* h2, Option_t *option, Double_t *res) const
2044{
2045 Double_t chi2 = 0;
2046 Int_t ndf = 0, igood = 0;
2047
2048 TString opt = option;
2049 opt.ToUpper();
2050
2051 Double_t prob = Chi2TestX(h2,chi2,ndf,igood,option,res);
2052
2053 if(opt.Contains("P")) {
2054 printf("Chi2 = %f, Prob = %g, NDF = %d, igood = %d\n", chi2,prob,ndf,igood);
2055 }
2056 if(opt.Contains("CHI2/NDF")) {
2057 if (ndf == 0) return 0;
2058 return chi2/ndf;
2059 }
2060 if(opt.Contains("CHI2")) {
2061 return chi2;
2062 }
2063
2064 return prob;
2065}
2066
2067////////////////////////////////////////////////////////////////////////////////
2068/// The computation routine of the Chisquare test. For the method description,
2069/// see Chi2Test() function.
2070///
2071/// \return p-value
2072/// \param[in] h2 the second histogram
2073/// \param[in] option
2074/// - "UU" = experiment experiment comparison (unweighted-unweighted)
2075/// - "UW" = experiment MC comparison (unweighted-weighted). Note that the first
2076/// histogram should be unweighted
2077/// - "WW" = MC MC comparison (weighted-weighted)
2078/// - "NORM" = if one or both histograms is scaled
2079/// - "OF" = overflows included
2080/// - "UF" = underflows included
2081/// by default underflows and overflows are not included
2082/// \param[out] igood test output
2083/// - igood=0 - no problems
2084/// - For unweighted unweighted comparison
2085/// - igood=1'There is a bin in the 1st histogram with less than 1 event'
2086/// - igood=2'There is a bin in the 2nd histogram with less than 1 event'
2087/// - igood=3'when the conditions for igood=1 and igood=2 are satisfied'
2088/// - For unweighted weighted comparison
2089/// - igood=1'There is a bin in the 1st histogram with less then 1 event'
2090/// - igood=2'There is a bin in the 2nd histogram with less then 10 effective number of events'
2091/// - igood=3'when the conditions for igood=1 and igood=2 are satisfied'
2092/// - For weighted weighted comparison
2093/// - igood=1'There is a bin in the 1st histogram with less then 10 effective
2094/// number of events'
2095/// - igood=2'There is a bin in the 2nd histogram with less then 10 effective
2096/// number of events'
2097/// - igood=3'when the conditions for igood=1 and igood=2 are satisfied'
2098/// \param[out] chi2 chisquare of the test
2099/// \param[out] ndf number of degrees of freedom (important, when both histograms have the same empty bins)
2100/// \param[out] res normalized residuals for further analysis
2101
2102Double_t TH1::Chi2TestX(const TH1* h2, Double_t &chi2, Int_t &ndf, Int_t &igood, Option_t *option, Double_t *res) const
2103{
2104
2108
2109 Double_t sum1 = 0.0, sumw1 = 0.0;
2110 Double_t sum2 = 0.0, sumw2 = 0.0;
2111
2112 chi2 = 0.0;
2113 ndf = 0;
2114
2115 TString opt = option;
2116 opt.ToUpper();
2117
2118 if (fBuffer) const_cast<TH1*>(this)->BufferEmpty();
2119
2120 const TAxis *xaxis1 = GetXaxis();
2121 const TAxis *xaxis2 = h2->GetXaxis();
2122 const TAxis *yaxis1 = GetYaxis();
2123 const TAxis *yaxis2 = h2->GetYaxis();
2124 const TAxis *zaxis1 = GetZaxis();
2125 const TAxis *zaxis2 = h2->GetZaxis();
2126
2127 Int_t nbinx1 = xaxis1->GetNbins();
2128 Int_t nbinx2 = xaxis2->GetNbins();
2129 Int_t nbiny1 = yaxis1->GetNbins();
2130 Int_t nbiny2 = yaxis2->GetNbins();
2131 Int_t nbinz1 = zaxis1->GetNbins();
2132 Int_t nbinz2 = zaxis2->GetNbins();
2133
2134 //check dimensions
2135 if (this->GetDimension() != h2->GetDimension() ){
2136 Error("Chi2TestX","Histograms have different dimensions.");
2137 return 0.0;
2138 }
2139
2140 //check number of channels
2141 if (nbinx1 != nbinx2) {
2142 Error("Chi2TestX","different number of x channels");
2143 }
2144 if (nbiny1 != nbiny2) {
2145 Error("Chi2TestX","different number of y channels");
2146 }
2147 if (nbinz1 != nbinz2) {
2148 Error("Chi2TestX","different number of z channels");
2149 }
2150
2151 //check for ranges
2152 i_start = j_start = k_start = 1;
2153 i_end = nbinx1;
2154 j_end = nbiny1;
2155 k_end = nbinz1;
2156
2157 if (xaxis1->TestBit(TAxis::kAxisRange)) {
2158 i_start = xaxis1->GetFirst();
2159 i_end = xaxis1->GetLast();
2160 }
2161 if (yaxis1->TestBit(TAxis::kAxisRange)) {
2162 j_start = yaxis1->GetFirst();
2163 j_end = yaxis1->GetLast();
2164 }
2165 if (zaxis1->TestBit(TAxis::kAxisRange)) {
2166 k_start = zaxis1->GetFirst();
2167 k_end = zaxis1->GetLast();
2168 }
2169
2170
2171 if (opt.Contains("OF")) {
2172 if (GetDimension() == 3) k_end = ++nbinz1;
2173 if (GetDimension() >= 2) j_end = ++nbiny1;
2174 if (GetDimension() >= 1) i_end = ++nbinx1;
2175 }
2176
2177 if (opt.Contains("UF")) {
2178 if (GetDimension() == 3) k_start = 0;
2179 if (GetDimension() >= 2) j_start = 0;
2180 if (GetDimension() >= 1) i_start = 0;
2181 }
2182
2183 ndf = (i_end - i_start + 1) * (j_end - j_start + 1) * (k_end - k_start + 1) - 1;
2184
2185 Bool_t comparisonUU = opt.Contains("UU");
2186 Bool_t comparisonUW = opt.Contains("UW");
2187 Bool_t comparisonWW = opt.Contains("WW");
2188 Bool_t scaledHistogram = opt.Contains("NORM");
2189
2190 if (scaledHistogram && !comparisonUU) {
2191 Info("Chi2TestX", "NORM option should be used together with UU option. It is ignored");
2192 }
2193
2194 // look at histo global bin content and effective entries
2195 Stat_t s[kNstat];
2196 GetStats(s);// s[1] sum of squares of weights, s[0] sum of weights
2197 Double_t sumBinContent1 = s[0];
2198 Double_t effEntries1 = (s[1] ? s[0] * s[0] / s[1] : 0.0);
2199
2200 h2->GetStats(s);// s[1] sum of squares of weights, s[0] sum of weights
2201 Double_t sumBinContent2 = s[0];
2202 Double_t effEntries2 = (s[1] ? s[0] * s[0] / s[1] : 0.0);
2203
2204 if (!comparisonUU && !comparisonUW && !comparisonWW ) {
2205 // deduce automatically from type of histogram
2208 else comparisonUW = true;
2209 }
2210 else comparisonWW = true;
2211 }
2212 // check unweighted histogram
2213 if (comparisonUW) {
2215 Warning("Chi2TestX","First histogram is not unweighted and option UW has been requested");
2216 }
2217 }
2218 if ( (!scaledHistogram && comparisonUU) ) {
2220 Warning("Chi2TestX","Both histograms are not unweighted and option UU has been requested");
2221 }
2222 }
2223
2224
2225 //get number of events in histogram
2227 for (Int_t i = i_start; i <= i_end; ++i) {
2228 for (Int_t j = j_start; j <= j_end; ++j) {
2229 for (Int_t k = k_start; k <= k_end; ++k) {
2230
2231 Int_t bin = GetBin(i, j, k);
2232
2237
2238 if (e1sq > 0.0) cnt1 = TMath::Floor(cnt1 * cnt1 / e1sq + 0.5); // avoid rounding errors
2239 else cnt1 = 0.0;
2240
2241 if (e2sq > 0.0) cnt2 = TMath::Floor(cnt2 * cnt2 / e2sq + 0.5); // avoid rounding errors
2242 else cnt2 = 0.0;
2243
2244 // sum contents
2245 sum1 += cnt1;
2246 sum2 += cnt2;
2247 sumw1 += e1sq;
2248 sumw2 += e2sq;
2249 }
2250 }
2251 }
2252 if (sumw1 <= 0.0 || sumw2 <= 0.0) {
2253 Error("Chi2TestX", "Cannot use option NORM when one histogram has all zero errors");
2254 return 0.0;
2255 }
2256
2257 } else {
2258 for (Int_t i = i_start; i <= i_end; ++i) {
2259 for (Int_t j = j_start; j <= j_end; ++j) {
2260 for (Int_t k = k_start; k <= k_end; ++k) {
2261
2262 Int_t bin = GetBin(i, j, k);
2263
2265 sum2 += h2->RetrieveBinContent(bin);
2266
2269 }
2270 }
2271 }
2272 }
2273 //checks that the histograms are not empty
2274 if (sum1 == 0.0 || sum2 == 0.0) {
2275 Error("Chi2TestX","one histogram is empty");
2276 return 0.0;
2277 }
2278
2279 if ( comparisonWW && ( sumw1 <= 0.0 && sumw2 <= 0.0 ) ){
2280 Error("Chi2TestX","Hist1 and Hist2 have both all zero errors\n");
2281 return 0.0;
2282 }
2283
2284 //THE TEST
2285 Int_t m = 0, n = 0;
2286 //Experiment - experiment comparison
2287 if (comparisonUU) {
2288 Int_t resIndex = 0;
2289 Double_t sum = sum1 + sum2;
2290 for (Int_t i = i_start; i <= i_end; ++i) {
2291 for (Int_t j = j_start; j <= j_end; ++j) {
2292 for (Int_t k = k_start; k <= k_end; ++k) {
2293
2294 Int_t bin = GetBin(i, j, k);
2295
2298
2299 if (scaledHistogram) {
2300 // scale bin value to effective bin entries
2303
2304 if (e1sq > 0) cnt1 = TMath::Floor(cnt1 * cnt1 / e1sq + 0.5); // avoid rounding errors
2305 else cnt1 = 0;
2306
2307 if (e2sq > 0) cnt2 = TMath::Floor(cnt2 * cnt2 / e2sq + 0.5); // avoid rounding errors
2308 else cnt2 = 0;
2309 }
2310
2311 if (Int_t(cnt1) == 0 && Int_t(cnt2) == 0) --ndf; // no data means one degree of freedom less
2312 else {
2313
2316 //Double_t nexp2 = binsum*sum2/sum;
2317
2318 if (res) res[resIndex] = (cnt1 - nexp1) / TMath::Sqrt(nexp1);
2319
2320 if (cnt1 < 1) ++m;
2321 if (cnt2 < 1) ++n;
2322
2323 //Habermann correction for residuals
2324 Double_t correc = (1. - sum1 / sum) * (1. - cntsum / sum);
2325 if (res) res[resIndex] /= TMath::Sqrt(correc);
2326 if (res) resIndex++;
2327 Double_t delta = sum2 * cnt1 - sum1 * cnt2;
2328 chi2 += delta * delta / cntsum;
2329 }
2330 }
2331 }
2332 }
2333 chi2 /= sum1 * sum2;
2334
2335 // flag error only when of the two histogram is zero
2336 if (m) {
2337 igood += 1;
2338 Info("Chi2TestX","There is a bin in h1 with less than 1 event.\n");
2339 }
2340 if (n) {
2341 igood += 2;
2342 Info("Chi2TestX","There is a bin in h2 with less than 1 event.\n");
2343 }
2344
2346 return prob;
2347
2348 }
2349
2350 // unweighted - weighted comparison
2351 // case of error = 0 and content not zero is treated without problems by excluding second chi2 sum
2352 // and can be considered as a data-theory comparison
2353 if ( comparisonUW ) {
2354 Int_t resIndex = 0;
2355 for (Int_t i = i_start; i <= i_end; ++i) {
2356 for (Int_t j = j_start; j <= j_end; ++j) {
2357 for (Int_t k = k_start; k <= k_end; ++k) {
2358
2359 Int_t bin = GetBin(i, j, k);
2360
2364
2365 // case both histogram have zero bin contents
2366 if (cnt1 * cnt1 == 0 && cnt2 * cnt2 == 0) {
2367 --ndf; //no data means one degree of freedom less
2368 continue;
2369 }
2370
2371 // case weighted histogram has zero bin content and error
2372 if (cnt2 * cnt2 == 0 && e2sq == 0) {
2373 if (sumw2 > 0) {
2374 // use as approximated error as 1 scaled by a scaling ratio
2375 // estimated from the total sum weight and sum weight squared
2376 e2sq = sumw2 / sum2;
2377 }
2378 else {
2379 // return error because infinite discrepancy here:
2380 // bin1 != 0 and bin2 =0 in a histogram with all errors zero
2381 Error("Chi2TestX","Hist2 has in bin (%d,%d,%d) zero content and zero errors\n", i, j, k);
2382 chi2 = 0; return 0;
2383 }
2384 }
2385
2386 if (cnt1 < 1) m++;
2387 if (e2sq > 0 && cnt2 * cnt2 / e2sq < 10) n++;
2388
2389 Double_t var1 = sum2 * cnt2 - sum1 * e2sq;
2390 Double_t var2 = var1 * var1 + 4. * sum2 * sum2 * cnt1 * e2sq;
2391
2392 // if cnt1 is zero and cnt2 = 1 and sum1 = sum2 var1 = 0 && var2 == 0
2393 // approximate by incrementing cnt1
2394 // LM (this need to be fixed for numerical errors)
2395 while (var1 * var1 + cnt1 == 0 || var1 + var2 == 0) {
2396 sum1++;
2397 cnt1++;
2398 var1 = sum2 * cnt2 - sum1 * e2sq;
2399 var2 = var1 * var1 + 4. * sum2 * sum2 * cnt1 * e2sq;
2400 }
2402
2403 while (var1 + var2 == 0) {
2404 sum1++;
2405 cnt1++;
2406 var1 = sum2 * cnt2 - sum1 * e2sq;
2407 var2 = var1 * var1 + 4. * sum2 * sum2 * cnt1 * e2sq;
2408 while (var1 * var1 + cnt1 == 0 || var1 + var2 == 0) {
2409 sum1++;
2410 cnt1++;
2411 var1 = sum2 * cnt2 - sum1 * e2sq;
2412 var2 = var1 * var1 + 4. * sum2 * sum2 * cnt1 * e2sq;
2413 }
2415 }
2416
2417 Double_t probb = (var1 + var2) / (2. * sum2 * sum2);
2418
2421
2424
2425 chi2 += delta1 * delta1 / nexp1;
2426
2427 if (e2sq > 0) {
2428 chi2 += delta2 * delta2 / e2sq;
2429 }
2430
2431 if (res) {
2432 if (e2sq > 0) {
2433 Double_t temp1 = sum2 * e2sq / var2;
2434 Double_t temp2 = 1.0 + (sum1 * e2sq - sum2 * cnt2) / var2;
2435 temp2 = temp1 * temp1 * sum1 * probb * (1.0 - probb) + temp2 * temp2 * e2sq / 4.0;
2436 // invert sign here
2437 res[resIndex] = - delta2 / TMath::Sqrt(temp2);
2438 }
2439 else
2440 res[resIndex] = delta1 / TMath::Sqrt(nexp1);
2441 resIndex++;
2442 }
2443 }
2444 }
2445 }
2446
2447 if (m) {
2448 igood += 1;
2449 Info("Chi2TestX","There is a bin in h1 with less than 1 event.\n");
2450 }
2451 if (n) {
2452 igood += 2;
2453 Info("Chi2TestX","There is a bin in h2 with less than 10 effective events.\n");
2454 }
2455
2456 Double_t prob = TMath::Prob(chi2, ndf);
2457
2458 return prob;
2459 }
2460
2461 // weighted - weighted comparison
2462 if (comparisonWW) {
2463 Int_t resIndex = 0;
2464 for (Int_t i = i_start; i <= i_end; ++i) {
2465 for (Int_t j = j_start; j <= j_end; ++j) {
2466 for (Int_t k = k_start; k <= k_end; ++k) {
2467
2468 Int_t bin = GetBin(i, j, k);
2473
2474 // case both histogram have zero bin contents
2475 // (use square of content to avoid numerical errors)
2476 if (cnt1 * cnt1 == 0 && cnt2 * cnt2 == 0) {
2477 --ndf; //no data means one degree of freedom less
2478 continue;
2479 }
2480
2481 if (e1sq == 0 && e2sq == 0) {
2482 // cannot treat case of booth histogram have zero zero errors
2483 Error("Chi2TestX","h1 and h2 both have bin %d,%d,%d with all zero errors\n", i,j,k);
2484 chi2 = 0; return 0;
2485 }
2486
2487 Double_t sigma = sum1 * sum1 * e2sq + sum2 * sum2 * e1sq;
2488 Double_t delta = sum2 * cnt1 - sum1 * cnt2;
2489 chi2 += delta * delta / sigma;
2490
2491 if (res) {
2492 Double_t temp = cnt1 * sum1 * e2sq + cnt2 * sum2 * e1sq;
2493 Double_t probb = temp / sigma;
2494 Double_t z = 0;
2495 if (e1sq > e2sq) {
2496 Double_t d1 = cnt1 - sum1 * probb;
2497 Double_t s1 = e1sq * ( 1. - e2sq * sum1 * sum1 / sigma );
2498 z = d1 / TMath::Sqrt(s1);
2499 }
2500 else {
2501 Double_t d2 = cnt2 - sum2 * probb;
2502 Double_t s2 = e2sq * ( 1. - e1sq * sum2 * sum2 / sigma );
2503 z = -d2 / TMath::Sqrt(s2);
2504 }
2505 res[resIndex] = z;
2506 resIndex++;
2507 }
2508
2509 if (e1sq > 0 && cnt1 * cnt1 / e1sq < 10) m++;
2510 if (e2sq > 0 && cnt2 * cnt2 / e2sq < 10) n++;
2511 }
2512 }
2513 }
2514 if (m) {
2515 igood += 1;
2516 Info("Chi2TestX","There is a bin in h1 with less than 10 effective events.\n");
2517 }
2518 if (n) {
2519 igood += 2;
2520 Info("Chi2TestX","There is a bin in h2 with less than 10 effective events.\n");
2521 }
2522 Double_t prob = TMath::Prob(chi2, ndf);
2523 return prob;
2524 }
2525 return 0;
2526}
2527////////////////////////////////////////////////////////////////////////////////
2528/// Compute and return the chisquare of this histogram with respect to a function
2529/// The chisquare is computed by weighting each histogram point by the bin error
2530/// By default the full range of the histogram is used, unless TAxis::SetRange or TAxis::SetRangeUser was called before.
2531/// Use option "R" for restricting the chisquare calculation to the given range of the function
2532/// Use option "L" for using the chisquare based on the poisson likelihood (Baker-Cousins Chisquare)
2533/// Use option "P" for using the Pearson chisquare based on the expected bin errors
2534/// Use option "I" for using the integral of the function in each bin instead of the value at the bin center
2535
2537{
2538 if (!func) {
2539 Error("Chisquare","Function pointer is Null - return -1");
2540 return -1;
2541 }
2542
2543 TString opt(option); opt.ToUpper();
2544 bool useRange = opt.Contains("R");
2545 bool useIntegral = opt.Contains("I");
2546 ROOT::Fit::EChisquareType type = ROOT::Fit::EChisquareType::kNeyman; // default chi2 with observed error
2549
2550 return ROOT::Fit::Chisquare(*this, *func, useRange, type, useIntegral);
2551}
2552
2553////////////////////////////////////////////////////////////////////////////////
2554/// Remove all the content from the underflow and overflow bins, without changing the number of entries
2555/// After calling this method, every undeflow and overflow bins will have content 0.0
2556/// The Sumw2 is also cleared, since there is no more content in the bins
2557
2559{
2560 for (Int_t bin = 0; bin < fNcells; ++bin)
2562 UpdateBinContent(bin, 0.0);
2563 if (fSumw2.fN) fSumw2.fArray[bin] = 0.0;
2564 }
2565}
2566
2567////////////////////////////////////////////////////////////////////////////////
2568/// Compute integral (normalized cumulative sum of bins) w/o under/overflows
2569/// The result is stored in fIntegral and used by the GetRandom functions.
2570/// This function is automatically called by GetRandom when the fIntegral
2571/// array does not exist or when the number of entries in the histogram
2572/// has changed since the previous call to GetRandom.
2573/// The resulting integral is normalized to 1.
2574/// If the routine is called with the onlyPositive flag set an error will
2575/// be produced in case of negative bin content and a NaN value returned
2576/// \param onlyPositive If set to true, an error will be produced and NaN will be returned
2577/// when a bin with negative number of entries is encountered.
2578/// \param option
2579/// - `""` (default) Compute the cumulative density function assuming current bin contents represent counts.
2580/// - `"width"` Computes the cumulative density function assuming current bin contents represent densities.
2581/// \return 1 if success, 0 if integral is zero, NAN if onlyPositive-test fails
2582
2584{
2585 if (fBuffer) BufferEmpty();
2587 // delete previously computed integral (if any)
2588 if (fIntegral) delete [] fIntegral;
2589
2590 // - Allocate space to store the integral and compute integral
2595
2596 fIntegral = new Double_t[nbins + 2];
2597 Int_t ibin = 0; fIntegral[ibin] = 0;
2598
2599 for (Int_t binz=1; binz <= nbinsz; ++binz) {
2601 for (Int_t biny=1; biny <= nbinsy; ++biny) {
2603 for (Int_t binx=1; binx <= nbinsx; ++binx) {
2605 ++ibin;
2607 if (useArea)
2608 y *= xWidth * yWidth * zWidth;
2609
2610 if (onlyPositive && y < 0) {
2611 Error("ComputeIntegral","Bin content is negative - return a NaN value");
2613 break;
2614 }
2615 fIntegral[ibin] = fIntegral[ibin - 1] + y;
2616 }
2617 }
2618 }
2619
2620 // - Normalize integral to 1
2621 if (fIntegral[nbins] == 0 ) {
2622 Error("ComputeIntegral", "Integral = 0, no hits in histogram bins (excluding over/underflow).");
2623 return 0;
2624 }
2625 for (Int_t bin=1; bin <= nbins; ++bin) fIntegral[bin] /= fIntegral[nbins];
2627 return fIntegral[nbins];
2628}
2629
2630////////////////////////////////////////////////////////////////////////////////
2631/// Return a pointer to the array of bins integral.
2632/// if the pointer fIntegral is null, TH1::ComputeIntegral is called
2633/// The array dimension is the number of bins in the histograms
2634/// including underflow and overflow (fNCells)
2635/// the last value integral[fNCells] is set to the number of entries of
2636/// the histogram
2637
2639{
2640 if (!fIntegral) ComputeIntegral();
2641 return fIntegral;
2642}
2643
2644////////////////////////////////////////////////////////////////////////////////
2645/**
2646 * Return a pointer to the corresponding cumulative histogram.
2647 *
2648 * The cumulative can be computed both in the forward (default) or backward
2649 * direction; the name of the new histogram is constructed from
2650 * the name of this histogram with a custom suffix (`suffix`) appended,
2651 * which defaults to "_cumulative".
2652 *
2653 * The cumulative distribution is formed by filling each bin of the
2654 * resulting histogram with the sum of all the bins whose indices are
2655 * no greater than (forward) or no less than (backward)
2656 * those of the target bin. To be exact,
2657 * \f[
2658 * S_{i_x, i_y, i_z} =
2659 * \begin{cases}
2660 * \sum_{j_x = 1}^{i_x} \sum_{j_y = 1}^{i_y} \sum_{j_z = 1}^{i_z} a_{j_x, j_y, j_z} & \text{(forward)} \\
2661 * \sum_{j_x = i_x}^{n_x} \sum_{j_y = i_y}^{n_y} \sum_{j_z = i_z}^{n_z} a_{j_x, j_y, j_z} & \text{(backward)}
2662 * \end{cases}
2663 * \f]
2664 *
2665 * The implementation is based on the Inclusion-Exclusion principle. That is,
2666 * for the forward case,
2667 * \f[
2668 * S_{i_x, i_y, i_z} = a_{i_x, i_y, i_z}
2669 * + S_{i_x-1, i_y, i_z} + S_{i_x, i_y-1, i_z} + S_{i_x, i_y, i_z-1}
2670 * - S_{i_x-1, i_y-1, i_z} - S_{i_x-1, i_y, i_z-1} - S_{i_x, i_y-1, i_z-1}
2671 * + S_{i_x-1, i_y-1, i_z-1}
2672 * \f]
2673 * where any term referring to a bin outside the summation range is taken to
2674 * be zero (and the backward case is obtained by replacing the \f$-1\f$ index
2675 * offsets with \f$+1\f$).
2676 *
2677 * This ensures that the result makes sense in higher dimensions,
2678 * especially in the case of selection efficiency computing.
2679 * For example, one can get a histogram (`*h2_eff_pt_eta`) in which each bin represents
2680 * the selection efficiency where pt and eta are greater than or equal to the lower edges of the bin
2681 * from the 2D histogram of these variables (`*h2_pt_eta`) with the following code,
2682 * ~~~{.cpp}
2683 * TH2 *h2_eff_pt_eta = h2_pt_eta->GetCumulative(kFALSE, "_efficiency");
2684 * h2_eff_pt_eta->Scale(1. / h2_eff_pt_eta->GetBinContent(1, 1));
2685 * ~~~
2686 *
2687 * Note: By default, the cumulative is computed from bin 1 to Nbins.
2688 * If an axis range is set,
2689 * values between the minimum and maximum of the range are set.
2690 * Setting an axis range can also be used for including underflow and overflow in
2691 * the cumulative (e.g. by setting h->GetXaxis()->SetRange(0, h->GetNbinsX()+1); )
2692 **/
2693
2694TH1 *TH1::GetCumulative(Bool_t forward, const char *suffix) const
2695{
2696 const Int_t firstX = fXaxis.GetFirst();
2697 const Int_t lastX = fXaxis.GetLast();
2698 const Int_t firstY = (fDimension >= 2) ? fYaxis.GetFirst() : 1;
2699 const Int_t lastY = (fDimension >= 2) ? fYaxis.GetLast() : 1;
2700 const Int_t firstZ = (fDimension >= 3) ? fZaxis.GetFirst() : 1;
2701 const Int_t lastZ = (fDimension >= 3) ? fZaxis.GetLast() : 1;
2702
2703 TH1 *hintegrated = static_cast<TH1 *>(Clone(fName + suffix));
2704 hintegrated->Reset();
2705 if (forward) { // Forward computation
2706 for (Int_t binz = firstZ; binz <= lastZ; ++binz) {
2707 for (Int_t biny = firstY; biny <= lastY; ++biny) {
2708 for (Int_t binx = firstX; binx <= lastX; ++binx) {
2709 const Int_t bin = hintegrated->GetBin(binx, biny, binz);
2711 if (binz != firstZ)
2712 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx, biny, binz - 1));
2713 if (biny != firstY)
2714 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx, biny - 1, binz));
2715 if (binx != firstX)
2716 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx - 1, biny, binz));
2717 if (binz != firstZ && biny != firstY)
2718 sum -= hintegrated->RetrieveBinContent(hintegrated->GetBin(binx, biny - 1, binz - 1));
2719 if (biny != firstY && binx != firstX)
2720 sum -= hintegrated->RetrieveBinContent(hintegrated->GetBin(binx - 1, biny - 1, binz));
2721 if (binx != firstX && binz != firstZ)
2722 sum -= hintegrated->RetrieveBinContent(hintegrated->GetBin(binx - 1, biny, binz - 1));
2723 if (binz != firstZ && biny != firstY && binx != firstX)
2724 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx - 1, biny - 1, binz - 1));
2725 hintegrated->SetBinContent(bin, sum);
2726 if (fSumw2.fN) {
2728 if (binz != firstZ)
2729 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx, biny, binz - 1)];
2730 if (biny != firstY)
2731 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx, biny - 1, binz)];
2732 if (binx != firstX)
2733 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx - 1, biny, binz)];
2734 if (binz != firstZ && biny != firstY)
2735 esum -= hintegrated->fSumw2.fArray[hintegrated->GetBin(binx, biny - 1, binz - 1)];
2736 if (biny != firstY && binx != firstX)
2737 esum -= hintegrated->fSumw2.fArray[hintegrated->GetBin(binx - 1, biny - 1, binz)];
2738 if (binx != firstX && binz != firstZ)
2739 esum -= hintegrated->fSumw2.fArray[hintegrated->GetBin(binx - 1, biny, binz - 1)];
2740 if (binz != firstZ && biny != firstY && binx != firstX)
2741 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx - 1, biny - 1, binz - 1)];
2742 hintegrated->fSumw2.fArray[bin] = esum;
2743 }
2744 }
2745 }
2746 }
2747 } else { // Backward computation
2748 for (Int_t binz = lastZ; binz >= firstZ; --binz) {
2749 for (Int_t biny = lastY; biny >= firstY; --biny) {
2750 for (Int_t binx = lastX; binx >= firstX; --binx) {
2751 const Int_t bin = hintegrated->GetBin(binx, biny, binz);
2753 if (binz != lastZ)
2754 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx, biny, binz + 1));
2755 if (biny != lastY)
2756 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx, biny + 1, binz));
2757 if (binx != lastX)
2758 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx + 1, biny, binz));
2759 if (binz != lastZ && biny != lastY)
2760 sum -= hintegrated->RetrieveBinContent(hintegrated->GetBin(binx, biny + 1, binz + 1));
2761 if (biny != lastY && binx != lastX)
2762 sum -= hintegrated->RetrieveBinContent(hintegrated->GetBin(binx + 1, biny + 1, binz));
2763 if (binx != lastX && binz != lastZ)
2764 sum -= hintegrated->RetrieveBinContent(hintegrated->GetBin(binx + 1, biny, binz + 1));
2765 if (binz != lastZ && biny != lastY && binx != lastX)
2766 sum += hintegrated->RetrieveBinContent(hintegrated->GetBin(binx + 1, biny + 1, binz + 1));
2767 hintegrated->SetBinContent(bin, sum);
2768 if (fSumw2.fN) {
2770 if (binz != lastZ)
2771 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx, biny, binz + 1)];
2772 if (biny != lastY)
2773 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx, biny + 1, binz)];
2774 if (binx != lastX)
2775 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx + 1, biny, binz)];
2776 if (binz != lastZ && biny != lastY)
2777 esum -= hintegrated->fSumw2.fArray[hintegrated->GetBin(binx, biny + 1, binz + 1)];
2778 if (biny != lastY && binx != lastX)
2779 esum -= hintegrated->fSumw2.fArray[hintegrated->GetBin(binx + 1, biny + 1, binz)];
2780 if (binx != lastX && binz != lastZ)
2781 esum -= hintegrated->fSumw2.fArray[hintegrated->GetBin(binx + 1, biny, binz + 1)];
2782 if (binz != lastZ && biny != lastY && binx != lastX)
2783 esum += hintegrated->fSumw2.fArray[hintegrated->GetBin(binx + 1, biny + 1, binz + 1)];
2784 hintegrated->fSumw2.fArray[bin] = esum;
2785 }
2786 }
2787 }
2788 }
2789 }
2790 return hintegrated;
2791}
2792
2793////////////////////////////////////////////////////////////////////////////////
2794/// Copy this histogram structure to newth1.
2795///
2796/// Note that this function does not copy the list of associated functions.
2797/// Use TObject::Clone to make a full copy of a histogram.
2798///
2799/// Note also that the histogram it will be created in gDirectory (if AddDirectoryStatus()=true)
2800/// or will not be added to any directory if AddDirectoryStatus()=false
2801/// independently of the current directory stored in the original histogram
2802
2803void TH1::Copy(TObject &obj) const
2804{
2805 if (((TH1&)obj).fDirectory) {
2806 // We are likely to change the hash value of this object
2807 // with TNamed::Copy, to keep things correct, we need to
2808 // clean up its existing entries.
2809 ((TH1&)obj).fDirectory->Remove(&obj);
2810 ((TH1&)obj).fDirectory = nullptr;
2811 }
2812 TNamed::Copy(obj);
2813 ((TH1&)obj).fDimension = fDimension;
2814 ((TH1&)obj).fNormFactor= fNormFactor;
2815 ((TH1&)obj).fNcells = fNcells;
2816 ((TH1&)obj).fBarOffset = fBarOffset;
2817 ((TH1&)obj).fBarWidth = fBarWidth;
2818 ((TH1&)obj).fOption = fOption;
2819 ((TH1&)obj).fBinStatErrOpt = fBinStatErrOpt;
2820 ((TH1&)obj).fBufferSize= fBufferSize;
2821 // copy the Buffer
2822 // delete first a previously existing buffer
2823 if (((TH1&)obj).fBuffer != nullptr) {
2824 delete [] ((TH1&)obj).fBuffer;
2825 ((TH1&)obj).fBuffer = nullptr;
2826 }
2827 if (fBuffer) {
2829 for (Int_t i=0;i<fBufferSize;i++) buf[i] = fBuffer[i];
2830 // obj.fBuffer has been deleted before
2831 ((TH1&)obj).fBuffer = buf;
2832 }
2833
2834 // copy bin contents (this should be done by the derived classes, since TH1 does not store the bin content)
2835 // Do this in case derived from TArray
2836 TArray* a = dynamic_cast<TArray*>(&obj);
2837 if (a) {
2838 a->Set(fNcells);
2839 for (Int_t i = 0; i < fNcells; i++)
2841 }
2842
2843 ((TH1&)obj).fEntries = fEntries;
2844
2845 // which will call BufferEmpty(0) and set fBuffer[0] to a Maybe one should call
2846 // assignment operator on the TArrayD
2847
2848 ((TH1&)obj).fTsumw = fTsumw;
2849 ((TH1&)obj).fTsumw2 = fTsumw2;
2850 ((TH1&)obj).fTsumwx = fTsumwx;
2851 ((TH1&)obj).fTsumwx2 = fTsumwx2;
2852 ((TH1&)obj).fMaximum = fMaximum;
2853 ((TH1&)obj).fMinimum = fMinimum;
2854
2855 TAttLine::Copy(((TH1&)obj));
2856 TAttFill::Copy(((TH1&)obj));
2857 TAttMarker::Copy(((TH1&)obj));
2858 fXaxis.Copy(((TH1&)obj).fXaxis);
2859 fYaxis.Copy(((TH1&)obj).fYaxis);
2860 fZaxis.Copy(((TH1&)obj).fZaxis);
2861 ((TH1&)obj).fXaxis.SetParent(&obj);
2862 ((TH1&)obj).fYaxis.SetParent(&obj);
2863 ((TH1&)obj).fZaxis.SetParent(&obj);
2864 fContour.Copy(((TH1&)obj).fContour);
2865 fSumw2.Copy(((TH1&)obj).fSumw2);
2866 // fFunctions->Copy(((TH1&)obj).fFunctions);
2867 // when copying an histogram if the AddDirectoryStatus() is true it
2868 // will be added to gDirectory independently of the fDirectory stored.
2869 // and if the AddDirectoryStatus() is false it will not be added to
2870 // any directory (fDirectory = nullptr)
2872 gDirectory->Append(&obj);
2873 ((TH1&)obj).fFunctions->UseRWLock();
2874 ((TH1&)obj).fDirectory = gDirectory;
2875 } else
2876 ((TH1&)obj).fDirectory = nullptr;
2877
2878}
2879
2880////////////////////////////////////////////////////////////////////////////////
2881/// Make a complete copy of the underlying object. If 'newname' is set,
2882/// the copy's name will be set to that name.
2883
2884TObject* TH1::Clone(const char* newname) const
2885{
2886 TH1* obj = (TH1*)IsA()->GetNew()(nullptr);
2887 Copy(*obj);
2888
2889 // Now handle the parts that Copy doesn't do
2890 if(fFunctions) {
2891 // The Copy above might have published 'obj' to the ListOfCleanups.
2892 // Clone can call RecursiveRemove, for example via TCheckHashRecursiveRemoveConsistency
2893 // when dictionary information is initialized, so we need to
2894 // keep obj->fFunction valid during its execution and
2895 // protect the update with the write lock.
2896
2897 // Reset stats parent - else cloning the stats will clone this histogram, too.
2898 auto oldstats = dynamic_cast<TVirtualPaveStats*>(fFunctions->FindObject("stats"));
2899 TObject *oldparent = nullptr;
2900 if (oldstats) {
2901 oldparent = oldstats->GetParent();
2902 oldstats->SetParent(nullptr);
2903 }
2904
2905 auto newlist = (TList*)fFunctions->Clone();
2906
2907 if (oldstats)
2908 oldstats->SetParent(oldparent);
2909 auto newstats = dynamic_cast<TVirtualPaveStats*>(obj->fFunctions->FindObject("stats"));
2910 if (newstats)
2911 newstats->SetParent(obj);
2912
2913 auto oldlist = obj->fFunctions;
2914 {
2916 obj->fFunctions = newlist;
2917 }
2918 delete oldlist;
2919 }
2920 if(newname && strlen(newname) ) {
2921 obj->SetName(newname);
2922 }
2923 return obj;
2924}
2925
2926////////////////////////////////////////////////////////////////////////////////
2927/// Callback to perform the automatic addition of the histogram to the given directory.
2928///
2929/// This callback is used to register a histogram to the current directory when a TKey
2930/// is read or an object is being cloned using TDirectory::CloneObject().
2931
2933{
2935 if (addStatus) {
2936 SetDirectory(dir);
2937 if (dir) {
2939 }
2940 }
2941}
2942
2943////////////////////////////////////////////////////////////////////////////////
2944/// Compute distance from point px,py to a line.
2945///
2946/// Compute the closest distance of approach from point px,py to elements
2947/// of a histogram.
2948/// The distance is computed in pixels units.
2949///
2950/// #### Algorithm:
2951/// Currently, this simple model computes the distance from the mouse
2952/// to the histogram contour only.
2953
2955{
2956 if (!fPainter) return 9999;
2957 return fPainter->DistancetoPrimitive(px,py);
2958}
2959
2960////////////////////////////////////////////////////////////////////////////////
2961/// Performs the operation: `this = this/(c1*f1)`
2962/// if errors are defined (see TH1::Sumw2), errors are also recalculated.
2963///
2964/// Only bins inside the function range are recomputed.
2965/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
2966/// you should call Sumw2 before making this operation.
2967/// This is particularly important if you fit the histogram after TH1::Divide
2968///
2969/// The function return kFALSE if the divide operation failed
2970
2972{
2973 if (!f1) {
2974 Error("Divide","Attempt to divide by a non-existing function");
2975 return kFALSE;
2976 }
2977
2978 // delete buffer if it is there since it will become invalid
2979 if (fBuffer) BufferEmpty(1);
2980
2981 Int_t nx = GetNbinsX() + 2; // normal bins + uf / of
2982 Int_t ny = GetNbinsY() + 2;
2983 Int_t nz = GetNbinsZ() + 2;
2984 if (fDimension < 2) ny = 1;
2985 if (fDimension < 3) nz = 1;
2986
2987
2988 SetMinimum();
2989 SetMaximum();
2990
2991 // - Loop on bins (including underflows/overflows)
2992 Int_t bin, binx, biny, binz;
2993 Double_t cu, w;
2994 Double_t xx[3];
2995 Double_t *params = nullptr;
2996 f1->InitArgs(xx,params);
2997 for (binz = 0; binz < nz; ++binz) {
2998 xx[2] = fZaxis.GetBinCenter(binz);
2999 for (biny = 0; biny < ny; ++biny) {
3000 xx[1] = fYaxis.GetBinCenter(biny);
3001 for (binx = 0; binx < nx; ++binx) {
3002 xx[0] = fXaxis.GetBinCenter(binx);
3003 if (!f1->IsInside(xx)) continue;
3005 bin = binx + nx * (biny + ny * binz);
3006 cu = c1 * f1->EvalPar(xx);
3007 if (TF1::RejectedPoint()) continue;
3008 if (cu) w = RetrieveBinContent(bin) / cu;
3009 else w = 0;
3011 if (fSumw2.fN) {
3012 if (cu != 0) fSumw2.fArray[bin] = GetBinErrorSqUnchecked(bin) / (cu * cu);
3013 else fSumw2.fArray[bin] = 0;
3014 }
3015 }
3016 }
3017 }
3018 ResetStats();
3019 return kTRUE;
3020}
3021
3022////////////////////////////////////////////////////////////////////////////////
3023/// Divide this histogram by h1.
3024///
3025/// `this = this/h1`
3026/// if errors are defined (see TH1::Sumw2), errors are also recalculated.
3027/// Note that if h1 has Sumw2 set, Sumw2 is automatically called for this
3028/// if not already set.
3029/// The resulting errors are calculated assuming uncorrelated histograms.
3030/// See the other TH1::Divide that gives the possibility to optionally
3031/// compute binomial errors.
3032///
3033/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
3034/// you should call Sumw2 before making this operation.
3035/// This is particularly important if you fit the histogram after TH1::Scale
3036///
3037/// The function return kFALSE if the divide operation failed
3038
3039Bool_t TH1::Divide(const TH1 *h1)
3040{
3041 if (!h1) {
3042 Error("Divide", "Input histogram passed does not exist (NULL).");
3043 return kFALSE;
3044 }
3045
3046 // delete buffer if it is there since it will become invalid
3047 if (fBuffer) BufferEmpty(1);
3048
3049 if (LoggedInconsistency("Divide", this, h1) >= kDifferentNumberOfBins) {
3050 return false;
3051 }
3052
3053 // Create Sumw2 if h1 has Sumw2 set
3054 if (fSumw2.fN == 0 && h1->GetSumw2N() != 0) Sumw2();
3055
3056 // - Loop on bins (including underflows/overflows)
3057 for (Int_t i = 0; i < fNcells; ++i) {
3060 if (c1) UpdateBinContent(i, c0 / c1);
3061 else UpdateBinContent(i, 0);
3062
3063 if(fSumw2.fN) {
3064 if (c1 == 0) { fSumw2.fArray[i] = 0; continue; }
3065 Double_t c1sq = c1 * c1;
3067 }
3068 }
3069 ResetStats();
3070 return kTRUE;
3071}
3072
3073////////////////////////////////////////////////////////////////////////////////
3074/// Replace contents of this histogram by the division of h1 by h2.
3075///
3076/// `this = c1*h1/(c2*h2)`
3077///
3078/// If errors are defined (see TH1::Sumw2), errors are also recalculated
3079/// Note that if h1 or h2 have Sumw2 set, Sumw2 is automatically called for this
3080/// if not already set.
3081/// The resulting errors are calculated assuming uncorrelated histograms.
3082/// However, if option ="B" is specified, Binomial errors are computed.
3083/// In this case c1 and c2 do not make real sense and they are ignored.
3084///
3085/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
3086/// you should call Sumw2 before making this operation.
3087/// This is particularly important if you fit the histogram after TH1::Divide
3088///
3089/// Please note also that in the binomial case errors are calculated using standard
3090/// binomial statistics, which means when b1 = b2, the error is zero.
3091/// If you prefer to have efficiency errors not going to zero when the efficiency is 1, you must
3092/// use the function TGraphAsymmErrors::BayesDivide, which will return an asymmetric and non-zero lower
3093/// error for the case b1=b2.
3094///
3095/// The function return kFALSE if the divide operation failed
3096
3098{
3099
3100 TString opt = option;
3101 opt.ToLower();
3102 Bool_t binomial = kFALSE;
3103 if (opt.Contains("b")) binomial = kTRUE;
3104 if (!h1 || !h2) {
3105 Error("Divide", "At least one of the input histograms passed does not exist (NULL).");
3106 return kFALSE;
3107 }
3108
3109 // delete buffer if it is there since it will become invalid
3110 if (fBuffer) BufferEmpty(1);
3111
3112 if (LoggedInconsistency("Divide", this, h1) >= kDifferentNumberOfBins ||
3113 LoggedInconsistency("Divide", h1, h2) >= kDifferentNumberOfBins) {
3114 return false;
3115 }
3116
3117 if (!c2) {
3118 Error("Divide","Coefficient of dividing histogram cannot be zero");
3119 return kFALSE;
3120 }
3121
3122 // Create Sumw2 if h1 or h2 have Sumw2 set, or if binomial errors are explicitly requested
3123 if (fSumw2.fN == 0 && (h1->GetSumw2N() != 0 || h2->GetSumw2N() != 0 || binomial)) Sumw2();
3124
3125 SetMinimum();
3126 SetMaximum();
3127
3128 // - Loop on bins (including underflows/overflows)
3129 for (Int_t i = 0; i < fNcells; ++i) {
3131 Double_t b2 = h2->RetrieveBinContent(i);
3132 if (b2) UpdateBinContent(i, c1 * b1 / (c2 * b2));
3133 else UpdateBinContent(i, 0);
3134
3135 if (fSumw2.fN) {
3136 if (b2 == 0) { fSumw2.fArray[i] = 0; continue; }
3137 Double_t b1sq = b1 * b1; Double_t b2sq = b2 * b2;
3138 Double_t c1sq = c1 * c1; Double_t c2sq = c2 * c2;
3141 if (binomial) {
3142 if (b1 != b2) {
3143 // in the case of binomial statistics c1 and c2 must be 1 otherwise it does not make sense
3144 // c1 and c2 are ignored
3145 //fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/(c2*b2));//this is the formula in Hbook/Hoper1
3146 //fSumw2.fArray[bin] = TMath::Abs(w*(1-w)/b2); // old formula from G. Flucke
3147 // formula which works also for weighted histogram (see http://root-forum.cern.ch/viewtopic.php?t=3753 )
3148 fSumw2.fArray[i] = TMath::Abs( ( (1. - 2.* b1 / b2) * e1sq + b1sq * e2sq / b2sq ) / b2sq );
3149 } else {
3150 //in case b1=b2 error is zero
3151 //use TGraphAsymmErrors::BayesDivide for getting the asymmetric error not equal to zero
3152 fSumw2.fArray[i] = 0;
3153 }
3154 } else {
3155 fSumw2.fArray[i] = c1sq * c2sq * (e1sq * b2sq + e2sq * b1sq) / (c2sq * c2sq * b2sq * b2sq);
3156 }
3157 }
3158 }
3159 ResetStats();
3160 if (binomial)
3161 // in case of binomial division use denominator for number of entries
3162 SetEntries ( h2->GetEntries() );
3163
3164 return kTRUE;
3165}
3166
3167////////////////////////////////////////////////////////////////////////////////
3168/// Draw this histogram with options.
3169///
3170/// Histograms are drawn via the THistPainter class. Each histogram has
3171/// a pointer to its own painter (to be usable in a multithreaded program).
3172/// The same histogram can be drawn with different options in different pads.
3173/// If a histogram is updated after it has been drawn, the updated data will
3174/// be shown the next time the pad is updated. One does not need to
3175/// redraw the histogram.
3176///
3177/// When a histogram is deleted, the histogram is **automatically removed from
3178/// all pads where it was drawn**. If a histogram should be modified or deleted
3179/// without affecting what is drawn, it should be drawn using DrawCopy().
3180///
3181/// By default, TH1::Draw clears the current pad. Passing the option "SAME", the
3182/// histogram will be drawn on top of what's in the pad.
3183/// One can use TH1::SetMaximum and TH1::SetMinimum to force a particular
3184/// value for the maximum or the minimum scale on the plot.
3185///
3186/// TH1::UseCurrentStyle can be used to change all histogram graphics
3187/// attributes to correspond to the current selected style.
3188/// This function must be called for each histogram.
3189/// In case one reads and draws many histograms from a file, one can force
3190/// the histograms to inherit automatically the current graphics style
3191/// by calling before gROOT->ForceStyle();
3192///
3193/// See the THistPainter class for a description of all the drawing options.
3194
3196{
3197 TString opt1 = option; opt1.ToLower();
3199 Int_t index = opt1.Index("same");
3200
3201 // Check if the string "same" is part of a TCutg name.
3202 if (index>=0) {
3203 Int_t indb = opt1.Index("[");
3204 if (indb>=0) {
3205 Int_t indk = opt1.Index("]");
3206 if (index>indb && index<indk) index = -1;
3207 }
3208 }
3209
3210 // If there is no pad or an empty pad the "same" option is ignored.
3211 if (gPad) {
3212 if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
3213 if (index>=0) {
3214 if (gPad->GetX1() == 0 && gPad->GetX2() == 1 &&
3215 gPad->GetY1() == 0 && gPad->GetY2() == 1 &&
3216 gPad->GetListOfPrimitives()->GetSize()==0) opt2.Remove(index,4);
3217 } else {
3218 //the following statement is necessary in case one attempts to draw
3219 //a temporary histogram already in the current pad
3220 if (TestBit(kCanDelete)) gPad->Remove(this);
3221 gPad->Clear();
3222 }
3223 gPad->IncrementPaletteColor(1, opt1);
3224 } else {
3225 if (index>=0) opt2.Remove(index,4);
3226 }
3227
3228 AppendPad(opt2.Data());
3229}
3230
3231////////////////////////////////////////////////////////////////////////////////
3232/// Copy this histogram and Draw in the current pad.
3233///
3234/// Once the histogram is drawn into the pad, the original and its drawn copy can be modified or deleted without
3235/// affecting each other. The copied histogram will be owned by the pad, and is deleted when the pad is cleared.
3236///
3237/// DrawCopy() is useful if the original histogram is a temporary, e.g. from code such as
3238/// ~~~ {.cpp}
3239/// void someFunction(...) {
3240/// TH1D histogram(...);
3241/// histogram.DrawCopy();
3242///
3243/// // or equivalently
3244/// std::unique_ptr<TH1F> histogram(...);
3245/// histogram->DrawCopy();
3246/// }
3247/// ~~~
3248/// If Draw() has been used, the histograms would disappear from the canvas at the end of this function.
3249///
3250/// By default a postfix "_copy" is added to the histogram name. Pass an empty postfix in case
3251/// you want to draw a histogram with the same name.
3252///
3253/// See Draw() for the list of options.
3254///
3255/// In contrast to TObject::DrawClone(), DrawCopy
3256/// - Ignores `gROOT->SetSelectedPad()`.
3257/// - Does not register the histogram to any directory.
3258/// - And can cycle through a colour palette when multiple objects are drawn with auto colouring.
3259
3260TH1 *TH1::DrawCopy(Option_t *option, const char * name_postfix) const
3261{
3262 TString opt = option;
3263 opt.ToLower();
3264 if (gPad && !opt.Contains("same")) gPad->Clear();
3266 if (name_postfix) newName.Form("%s%s", GetName(), name_postfix);
3267 TH1 *newth1 = (TH1 *)Clone(newName.Data());
3268 newth1->SetDirectory(nullptr);
3269 newth1->SetBit(kCanDelete);
3270 if (gPad) gPad->IncrementPaletteColor(1, opt);
3271
3272 newth1->AppendPad(option);
3273 return newth1;
3274}
3275
3276////////////////////////////////////////////////////////////////////////////////
3277/// Draw a normalized copy of this histogram.
3278///
3279/// A clone of this histogram is normalized to norm and drawn with option.
3280/// A pointer to the normalized histogram is returned.
3281/// The contents of the histogram copy are scaled such that the new
3282/// sum of weights (excluding under and overflow) is equal to norm.
3283/// Note that the returned normalized histogram is not added to the list
3284/// of histograms in the current directory in memory.
3285/// It is the user's responsibility to delete this histogram.
3286/// The kCanDelete bit is set for the returned object. If a pad containing
3287/// this copy is cleared, the histogram will be automatically deleted.
3288///
3289/// See Draw for the list of options
3290
3292{
3294 if (sum == 0) {
3295 Error("DrawNormalized","Sum of weights is null. Cannot normalize histogram: %s",GetName());
3296 return nullptr;
3297 }
3298
3299 TDirectory::TContext ctx{nullptr};
3300 TH1 *h = (TH1*)Clone();
3302 // in case of drawing with error options - scale correctly the error
3303 TString opt(option); opt.ToUpper();
3304 if (fSumw2.fN == 0) {
3305 h->Sumw2();
3306 // do not use in this case the "Error option " for drawing which is enabled by default since the normalized histogram has now errors
3307 if (opt.IsNull() || opt == "SAME") opt += "HIST";
3308 }
3309 h->Scale(norm/sum);
3310 if (TMath::Abs(fMaximum+1111) > 1e-3) h->SetMaximum(fMaximum*norm/sum);
3311 if (TMath::Abs(fMinimum+1111) > 1e-3) h->SetMinimum(fMinimum*norm/sum);
3312 h->Draw(opt);
3313
3314 return h;
3315}
3316
3317////////////////////////////////////////////////////////////////////////////////
3318/// Display a panel with all histogram drawing options.
3319///
3320/// See class TDrawPanelHist for example
3321
3322void TH1::DrawPanel()
3323{
3324 if (!fPainter) {Draw(); if (gPad) gPad->Update();}
3325 if (fPainter) fPainter->DrawPanel();
3326}
3327
3328////////////////////////////////////////////////////////////////////////////////
3329/// Evaluate function f1 at the center of bins of this histogram.
3330///
3331/// - If option "R" is specified, the function is evaluated only
3332/// for the bins included in the function range.
3333/// - If option "A" is specified, the value of the function is added to the
3334/// existing bin contents
3335/// - If option "S" is specified, the value of the function is used to
3336/// generate a value, distributed according to the Poisson
3337/// distribution, with f1 as the mean.
3338
3340{
3341 Double_t x[3];
3342 Int_t range, stat, add;
3343 if (!f1) return;
3344
3345 TString opt = option;
3346 opt.ToLower();
3347 if (opt.Contains("a")) add = 1;
3348 else add = 0;
3349 if (opt.Contains("s")) stat = 1;
3350 else stat = 0;
3351 if (opt.Contains("r")) range = 1;
3352 else range = 0;
3353
3354 // delete buffer if it is there since it will become invalid
3355 if (fBuffer) BufferEmpty(1);
3356
3360 if (!add) Reset();
3361
3362 for (Int_t binz = 1; binz <= nbinsz; ++binz) {
3363 x[2] = fZaxis.GetBinCenter(binz);
3364 for (Int_t biny = 1; biny <= nbinsy; ++biny) {
3365 x[1] = fYaxis.GetBinCenter(biny);
3366 for (Int_t binx = 1; binx <= nbinsx; ++binx) {
3368 x[0] = fXaxis.GetBinCenter(binx);
3369 if (range && !f1->IsInside(x)) continue;
3370 Double_t fu = f1->Eval(x[0], x[1], x[2]);
3371 if (stat) fu = gRandom->PoissonD(fu);
3374 }
3375 }
3376 }
3377}
3378
3379////////////////////////////////////////////////////////////////////////////////
3380/// Execute action corresponding to one event.
3381///
3382/// This member function is called when a histogram is clicked with the locator
3383///
3384/// If Left button clicked on the bin top value, then the content of this bin
3385/// is modified according to the new position of the mouse when it is released.
3386
3387void TH1::ExecuteEvent(Int_t event, Int_t px, Int_t py)
3388{
3389 if (fPainter) fPainter->ExecuteEvent(event, px, py);
3390}
3391
3392////////////////////////////////////////////////////////////////////////////////
3393/// This function allows to do discrete Fourier transforms of TH1 and TH2.
3394/// Available transform types and flags are described below.
3395///
3396/// To extract more information about the transform, use the function
3397/// TVirtualFFT::GetCurrentTransform() to get a pointer to the current
3398/// transform object.
3399///
3400/// \param[out] h_output histogram for the output. If a null pointer is passed, a new histogram is created
3401/// and returned, otherwise, the provided histogram is used and should be big enough
3402/// \param[in] option option parameters consists of 3 parts:
3403/// - option on what to return
3404/// - "RE" - returns a histogram of the real part of the output
3405/// - "IM" - returns a histogram of the imaginary part of the output
3406/// - "MAG"- returns a histogram of the magnitude of the output
3407/// - "PH" - returns a histogram of the phase of the output
3408/// - option of transform type
3409/// - "R2C" - real to complex transforms - default
3410/// - "R2HC" - real to halfcomplex (special format of storing output data,
3411/// results the same as for R2C)
3412/// - "DHT" - discrete Hartley transform
3413/// real to real transforms (sine and cosine):
3414/// - "R2R_0", "R2R_1", "R2R_2", "R2R_3" - discrete cosine transforms of types I-IV
3415/// - "R2R_4", "R2R_5", "R2R_6", "R2R_7" - discrete sine transforms of types I-IV
3416/// To specify the type of each dimension of a 2-dimensional real to real
3417/// transform, use options of form "R2R_XX", for example, "R2R_02" for a transform,
3418/// which is of type "R2R_0" in 1st dimension and "R2R_2" in the 2nd.
3419/// - option of transform flag
3420/// - "ES" (from "estimate") - no time in preparing the transform, but probably sub-optimal
3421/// performance
3422/// - "M" (from "measure") - some time spend in finding the optimal way to do the transform
3423/// - "P" (from "patient") - more time spend in finding the optimal way to do the transform
3424/// - "EX" (from "exhaustive") - the most optimal way is found
3425/// This option should be chosen depending on how many transforms of the same size and
3426/// type are going to be done. Planning is only done once, for the first transform of this
3427/// size and type. Default is "ES".
3428///
3429/// Examples of valid options: "Mag R2C M" "Re R2R_11" "Im R2C ES" "PH R2HC EX"
3430
3432{
3433
3434 Int_t ndim[3];
3435 ndim[0] = this->GetNbinsX();
3436 ndim[1] = this->GetNbinsY();
3437 ndim[2] = this->GetNbinsZ();
3438
3440 TString opt = option;
3441 opt.ToUpper();
3442 if (!opt.Contains("2R")){
3443 if (!opt.Contains("2C") && !opt.Contains("2HC") && !opt.Contains("DHT")) {
3444 //no type specified, "R2C" by default
3445 opt.Append("R2C");
3446 }
3447 fft = TVirtualFFT::FFT(this->GetDimension(), ndim, opt.Data());
3448 }
3449 else {
3450 //find the kind of transform
3451 Int_t ind = opt.Index("R2R", 3);
3452 Int_t *kind = new Int_t[2];
3453 char t;
3454 t = opt[ind+4];
3455 kind[0] = atoi(&t);
3456 if (h_output->GetDimension()>1) {
3457 t = opt[ind+5];
3458 kind[1] = atoi(&t);
3459 }
3460 fft = TVirtualFFT::SineCosine(this->GetDimension(), ndim, kind, option);
3461 delete [] kind;
3462 }
3463
3464 if (!fft) return nullptr;
3465 Int_t in=0;
3466 for (Int_t binx = 1; binx<=ndim[0]; binx++) {
3467 for (Int_t biny=1; biny<=ndim[1]; biny++) {
3468 for (Int_t binz=1; binz<=ndim[2]; binz++) {
3469 fft->SetPoint(in, this->GetBinContent(binx, biny, binz));
3470 in++;
3471 }
3472 }
3473 }
3474 fft->Transform();
3476 return h_output;
3477}
3478
3479////////////////////////////////////////////////////////////////////////////////
3480/// Increment bin with abscissa X by 1.
3481///
3482/// if x is less than the low-edge of the first bin, the Underflow bin is incremented
3483/// if x is equal to or greater than the upper edge of last bin, the Overflow bin is incremented
3484///
3485/// If the storage of the sum of squares of weights has been triggered,
3486/// via the function Sumw2, then the sum of the squares of weights is incremented
3487/// by 1 in the bin corresponding to x.
3488///
3489/// The function returns the corresponding bin number which has its content incremented by 1
3490
3492{
3493 if (fBuffer) return BufferFill(x,1);
3494
3495 Int_t bin;
3496 fEntries++;
3497 bin =fXaxis.FindBin(x);
3498 if (bin <0) return -1;
3500 if (fSumw2.fN) ++fSumw2.fArray[bin];
3501 if (bin == 0 || bin > fXaxis.GetNbins()) {
3502 if (!GetStatOverflowsBehaviour()) return -1;
3503 }
3504 ++fTsumw;
3505 ++fTsumw2;
3506 fTsumwx += x;
3507 fTsumwx2 += x*x;
3508 return bin;
3509}
3510
3511////////////////////////////////////////////////////////////////////////////////
3512/// Increment bin with abscissa X with a weight w.
3513///
3514/// if x is less than the low-edge of the first bin, the Underflow bin is incremented
3515/// if x is equal to or greater than the upper edge of last bin, the Overflow bin is incremented
3516///
3517/// If the weight is not equal to 1, the storage of the sum of squares of
3518/// weights is automatically triggered and the sum of the squares of weights is incremented
3519/// by \f$ w^2 \f$ in the bin corresponding to x.
3520///
3521/// The function returns the corresponding bin number which has its content incremented by w
3522
3524{
3525
3526 if (fBuffer) return BufferFill(x,w);
3527
3528 Int_t bin;
3529 fEntries++;
3530 bin =fXaxis.FindBin(x);
3531 if (bin <0) return -1;
3532 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW) ) Sumw2(); // must be called before AddBinContent
3533 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
3535 if (bin == 0 || bin > fXaxis.GetNbins()) {
3536 if (!GetStatOverflowsBehaviour()) return -1;
3537 }
3538 Double_t z= w;
3539 fTsumw += z;
3540 fTsumw2 += z*z;
3541 fTsumwx += z*x;
3542 fTsumwx2 += z*x*x;
3543 return bin;
3544}
3545
3546////////////////////////////////////////////////////////////////////////////////
3547/// Increment bin with namex with a weight w
3548///
3549/// if x is less than the low-edge of the first bin, the Underflow bin is incremented
3550/// if x is equal to or greater than the upper edge of last bin, the Overflow bin is incremented
3551///
3552/// If the weight is not equal to 1, the storage of the sum of squares of
3553/// weights is automatically triggered and the sum of the squares of weights is incremented
3554/// by \f$ w^2 \f$ in the bin corresponding to x.
3555///
3556/// The function returns the corresponding bin number which has its content
3557/// incremented by w.
3558
3559Int_t TH1::Fill(const char *namex, Double_t w)
3560{
3561 Int_t bin;
3562 fEntries++;
3564 if (bin <0) return -1;
3565 if (!fSumw2.fN && w != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2();
3566 if (fSumw2.fN) fSumw2.fArray[bin] += w*w;
3568 if (bin == 0 || bin > fXaxis.GetNbins()) return -1;
3569 Double_t z= w;
3570 fTsumw += z;
3571 fTsumw2 += z*z;
3572 // this make sense if the histogram is not expanding (the x axis cannot be extended)
3573 if (!fXaxis.CanExtend() || !fXaxis.IsAlphanumeric()) {
3575 fTsumwx += z*x;
3576 fTsumwx2 += z*x*x;
3577 }
3578 return bin;
3579}
3580
3581////////////////////////////////////////////////////////////////////////////////
3582/// Fill this histogram with an array x and weights w.
3583///
3584/// \param[in] ntimes number of entries in arrays x and w (array size must be ntimes*stride)
3585/// \param[in] x array of values to be histogrammed
3586/// \param[in] w array of weighs
3587/// \param[in] stride step size through arrays x and w
3588///
3589/// If the weight is not equal to 1, the storage of the sum of squares of
3590/// weights is automatically triggered and the sum of the squares of weights is incremented
3591/// by \f$ w^2 \f$ in the bin corresponding to x.
3592/// if w is NULL each entry is assumed a weight=1
3593
3594void TH1::FillN(Int_t ntimes, const Double_t *x, const Double_t *w, Int_t stride)
3595{
3596 //If a buffer is activated, fill buffer
3597 if (fBuffer) {
3598 ntimes *= stride;
3599 Int_t i = 0;
3600 for (i=0;i<ntimes;i+=stride) {
3601 if (!fBuffer) break; // buffer can be deleted in BufferFill when is empty
3602 if (w) BufferFill(x[i],w[i]);
3603 else BufferFill(x[i], 1.);
3604 }
3605 // fill the remaining entries if the buffer has been deleted
3606 if (i < ntimes && !fBuffer) {
3607 auto weights = w ? &w[i] : nullptr;
3608 DoFillN((ntimes-i)/stride,&x[i],weights,stride);
3609 }
3610 return;
3611 }
3612 // call internal method
3613 DoFillN(ntimes, x, w, stride);
3614}
3615
3616////////////////////////////////////////////////////////////////////////////////
3617/// Internal method to fill histogram content from a vector
3618/// called directly by TH1::BufferEmpty
3619
3620void TH1::DoFillN(Int_t ntimes, const Double_t *x, const Double_t *w, Int_t stride)
3621{
3622 Int_t bin,i;
3623
3624 fEntries += ntimes;
3625 Double_t ww = 1;
3627 ntimes *= stride;
3628 for (i=0;i<ntimes;i+=stride) {
3629 bin =fXaxis.FindBin(x[i]);
3630 if (bin <0) continue;
3631 if (w) ww = w[i];
3632 if (!fSumw2.fN && ww != 1.0 && !TestBit(TH1::kIsNotW)) Sumw2();
3633 if (fSumw2.fN) fSumw2.fArray[bin] += ww*ww;
3634 AddBinContent(bin, ww);
3635 if (bin == 0 || bin > nbins) {
3636 if (!GetStatOverflowsBehaviour()) continue;
3637 }
3638 Double_t z= ww;
3639 fTsumw += z;
3640 fTsumw2 += z*z;
3641 fTsumwx += z*x[i];
3642 fTsumwx2 += z*x[i]*x[i];
3643 }
3644}
3645
3646////////////////////////////////////////////////////////////////////////////////
3647/// Fill histogram following distribution in function fname.
3648///
3649/// @param fname : Function name used for filling the histogram
3650/// @param ntimes : number of times the histogram is filled
3651/// @param rng : (optional) Random number generator used to sample
3652///
3653///
3654/// The distribution contained in the function fname (TF1) is integrated
3655/// over the channel contents for the bin range of this histogram.
3656/// It is normalized to 1.
3657///
3658/// Getting one random number implies:
3659/// - Generating a random number between 0 and 1 (say r1)
3660/// - Look in which bin in the normalized integral r1 corresponds to
3661/// - Fill histogram channel
3662/// ntimes random numbers are generated
3663///
3664/// One can also call TF1::GetRandom to get a random variate from a function.
3665
3666void TH1::FillRandom(const char *fname, Int_t ntimes, TRandom * rng)
3667{
3668 // - Search for fname in the list of ROOT defined functions
3669 TF1 *f1 = (TF1*)gROOT->GetFunction(fname);
3670 if (!f1) { Error("FillRandom", "Unknown function: %s",fname); return; }
3671
3674
3676{
3677 Int_t bin, binx, ibin, loop;
3678 Double_t r1, x;
3679
3680 // - Allocate temporary space to store the integral and compute integral
3681
3682 TAxis * xAxis = &fXaxis;
3683
3684 // in case axis of histogram is not defined use the function axis
3685 if (fXaxis.GetXmax() <= fXaxis.GetXmin()) {
3687 f1->GetRange(xmin,xmax);
3688 Info("FillRandom","Using function axis and range [%g,%g]",xmin, xmax);
3689 xAxis = f1->GetHistogram()->GetXaxis();
3690 }
3691
3692 Int_t first = xAxis->GetFirst();
3693 Int_t last = xAxis->GetLast();
3694 Int_t nbinsx = last-first+1;
3695
3696 Double_t *integral = new Double_t[nbinsx+1];
3697 integral[0] = 0;
3698 for (binx=1;binx<=nbinsx;binx++) {
3699 Double_t fint = f1->Integral(xAxis->GetBinLowEdge(binx+first-1),xAxis->GetBinUpEdge(binx+first-1), 0.);
3700 integral[binx] = integral[binx-1] + fint;
3701 }
3702
3703 // - Normalize integral to 1
3704 if (integral[nbinsx] == 0 ) {
3705 delete [] integral;
3706 Error("FillRandom", "Integral = zero"); return;
3707 }
3708 for (bin=1;bin<=nbinsx;bin++) integral[bin] /= integral[nbinsx];
3709
3710 // --------------Start main loop ntimes
3711 for (loop=0;loop<ntimes;loop++) {
3712 r1 = (rng) ? rng->Rndm() : gRandom->Rndm();
3713 ibin = TMath::BinarySearch(nbinsx,&integral[0],r1);
3714 //binx = 1 + ibin;
3715 //x = xAxis->GetBinCenter(binx); //this is not OK when SetBuffer is used
3716 x = xAxis->GetBinLowEdge(ibin+first)
3717 +xAxis->GetBinWidth(ibin+first)*(r1-integral[ibin])/(integral[ibin+1] - integral[ibin]);
3718 Fill(x);
3719 }
3720 delete [] integral;
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Fill histogram following distribution in histogram h.
3725///
3726/// @param h : Histogram pointer used for sampling random number
3727/// @param ntimes : number of times the histogram is filled
3728/// @param rng : (optional) Random number generator used for sampling
3729///
3730/// The distribution contained in the histogram h (TH1) is integrated
3731/// over the channel contents for the bin range of this histogram.
3732/// It is normalized to 1.
3733///
3734/// Getting one random number implies:
3735/// - Generating a random number between 0 and 1 (say r1)
3736/// - Look in which bin in the normalized integral r1 corresponds to
3737/// - Fill histogram channel ntimes random numbers are generated
3738///
3739/// SPECIAL CASE when the target histogram has the same binning as the source.
3740/// in this case we simply use a poisson distribution where
3741/// the mean value per bin = bincontent/integral.
3742
3744{
3745 if (!h) { Error("FillRandom", "Null histogram"); return; }
3746 if (fDimension != h->GetDimension()) {
3747 Error("FillRandom", "Histograms with different dimensions"); return;
3748 }
3749 if (std::isnan(h->ComputeIntegral(true))) {
3750 Error("FillRandom", "Histograms contains negative bins, does not represent probabilities");
3751 return;
3752 }
3753
3754 //in case the target histogram has the same binning and ntimes much greater
3755 //than the number of bins we can use a fast method
3756 Int_t first = fXaxis.GetFirst();
3757 Int_t last = fXaxis.GetLast();
3758 Int_t nbins = last-first+1;
3759 if (ntimes > 10*nbins) {
3760 auto inconsistency = CheckConsistency(this,h);
3761 if (inconsistency != kFullyConsistent) return; // do nothing
3762 Double_t sumw = h->Integral(first,last);
3763 if (sumw == 0) return;
3764 Double_t sumgen = 0;
3765 for (Int_t bin=first;bin<=last;bin++) {
3766 Double_t mean = h->RetrieveBinContent(bin)*ntimes/sumw;
3767 Double_t cont = (rng) ? rng->Poisson(mean) : gRandom->Poisson(mean);
3768 sumgen += cont;
3770 if (fSumw2.fN) fSumw2.fArray[bin] += cont;
3771 }
3772
3773 // fix for the fluctuations in the total number n
3774 // since we use Poisson instead of multinomial
3775 // add a correction to have ntimes as generated entries
3776 Int_t i;
3777 if (sumgen < ntimes) {
3778 // add missing entries
3779 for (i = Int_t(sumgen+0.5); i < ntimes; ++i)
3780 {
3781 Double_t x = h->GetRandom();
3782 Fill(x);
3783 }
3784 }
3785 else if (sumgen > ntimes) {
3786 // remove extra entries
3787 i = Int_t(sumgen+0.5);
3788 while( i > ntimes) {
3789 Double_t x = h->GetRandom(rng);
3792 // skip in case bin is empty
3793 if (y > 0) {
3794 SetBinContent(ibin, y-1.);
3795 i--;
3796 }
3797 }
3798 }
3799
3800 ResetStats();
3801 return;
3802 }
3803 // case of different axis and not too large ntimes
3804
3805 if (h->ComputeIntegral() ==0) return;
3806 Int_t loop;
3807 Double_t x;
3808 for (loop=0;loop<ntimes;loop++) {
3809 x = h->GetRandom();
3810 Fill(x);
3811 }
3812}
3813
3814////////////////////////////////////////////////////////////////////////////////
3815/// Return Global bin number corresponding to x,y,z
3816///
3817/// 2-D and 3-D histograms are represented with a one dimensional
3818/// structure. This has the advantage that all existing functions, such as
3819/// GetBinContent, GetBinError, GetBinFunction work for all dimensions.
3820/// This function tries to extend the axis if the given point belongs to an
3821/// under-/overflow bin AND if CanExtendAllAxes() is true.
3822///
3823/// See also TH1::GetBin, TAxis::FindBin and TAxis::FindFixBin
3824
3826{
3827 if (GetDimension() < 2) {
3828 return fXaxis.FindBin(x);
3829 }
3830 if (GetDimension() < 3) {
3831 Int_t nx = fXaxis.GetNbins()+2;
3834 return binx + nx*biny;
3835 }
3836 if (GetDimension() < 4) {
3837 Int_t nx = fXaxis.GetNbins()+2;
3838 Int_t ny = fYaxis.GetNbins()+2;
3841 Int_t binz = fZaxis.FindBin(z);
3842 return binx + nx*(biny +ny*binz);
3843 }
3844 return -1;
3845}
3846
3847////////////////////////////////////////////////////////////////////////////////
3848/// Return Global bin number corresponding to x,y,z.
3849///
3850/// 2-D and 3-D histograms are represented with a one dimensional
3851/// structure. This has the advantage that all existing functions, such as
3852/// GetBinContent, GetBinError, GetBinFunction work for all dimensions.
3853/// This function DOES NOT try to extend the axis if the given point belongs
3854/// to an under-/overflow bin.
3855///
3856/// See also TH1::GetBin, TAxis::FindBin and TAxis::FindFixBin
3857
3859{
3860 if (GetDimension() < 2) {
3861 return fXaxis.FindFixBin(x);
3862 }
3863 if (GetDimension() < 3) {
3864 Int_t nx = fXaxis.GetNbins()+2;
3867 return binx + nx*biny;
3868 }
3869 if (GetDimension() < 4) {
3870 Int_t nx = fXaxis.GetNbins()+2;
3871 Int_t ny = fYaxis.GetNbins()+2;
3875 return binx + nx*(biny +ny*binz);
3876 }
3877 return -1;
3878}
3879
3880////////////////////////////////////////////////////////////////////////////////
3881/// Find first bin with content > threshold for axis (1=x, 2=y, 3=z)
3882/// if no bins with content > threshold is found the function returns -1.
3883/// The search will occur between the specified first and last bin. Specifying
3884/// the value of the last bin to search to less than zero will search until the
3885/// last defined bin.
3886
3888{
3889 if (fBuffer) ((TH1*)this)->BufferEmpty();
3890
3891 if (axis < 1 || (axis > 1 && GetDimension() == 1 ) ||
3892 ( axis > 2 && GetDimension() == 2 ) || ( axis > 3 && GetDimension() > 3 ) ) {
3893 Warning("FindFirstBinAbove","Invalid axis number : %d, axis x assumed\n",axis);
3894 axis = 1;
3895 }
3896 if (firstBin < 1) {
3897 firstBin = 1;
3898 }
3900 Int_t nbinsy = (GetDimension() > 1 ) ? fYaxis.GetNbins() : 1;
3901 Int_t nbinsz = (GetDimension() > 2 ) ? fZaxis.GetNbins() : 1;
3902
3903 if (axis == 1) {
3906 }
3907 for (Int_t binx = firstBin; binx <= lastBin; binx++) {
3908 for (Int_t biny = 1; biny <= nbinsy; biny++) {
3909 for (Int_t binz = 1; binz <= nbinsz; binz++) {
3911 }
3912 }
3913 }
3914 }
3915 else if (axis == 2) {
3918 }
3919 for (Int_t biny = firstBin; biny <= lastBin; biny++) {
3920 for (Int_t binx = 1; binx <= nbinsx; binx++) {
3921 for (Int_t binz = 1; binz <= nbinsz; binz++) {
3923 }
3924 }
3925 }
3926 }
3927 else if (axis == 3) {
3930 }
3931 for (Int_t binz = firstBin; binz <= lastBin; binz++) {
3932 for (Int_t binx = 1; binx <= nbinsx; binx++) {
3933 for (Int_t biny = 1; biny <= nbinsy; biny++) {
3935 }
3936 }
3937 }
3938 }
3939
3940 return -1;
3941}
3942
3943////////////////////////////////////////////////////////////////////////////////
3944/// Find last bin with content > threshold for axis (1=x, 2=y, 3=z)
3945/// if no bins with content > threshold is found the function returns -1.
3946/// The search will occur between the specified first and last bin. Specifying
3947/// the value of the last bin to search to less than zero will search until the
3948/// last defined bin.
3949
3951{
3952 if (fBuffer) ((TH1*)this)->BufferEmpty();
3953
3954
3955 if (axis < 1 || ( axis > 1 && GetDimension() == 1 ) ||
3956 ( axis > 2 && GetDimension() == 2 ) || ( axis > 3 && GetDimension() > 3) ) {
3957 Warning("FindFirstBinAbove","Invalid axis number : %d, axis x assumed\n",axis);
3958 axis = 1;
3959 }
3960 if (firstBin < 1) {
3961 firstBin = 1;
3962 }
3964 Int_t nbinsy = (GetDimension() > 1 ) ? fYaxis.GetNbins() : 1;
3965 Int_t nbinsz = (GetDimension() > 2 ) ? fZaxis.GetNbins() : 1;
3966
3967 if (axis == 1) {
3970 }
3971 for (Int_t binx = lastBin; binx >= firstBin; binx--) {
3972 for (Int_t biny = 1; biny <= nbinsy; biny++) {
3973 for (Int_t binz = 1; binz <= nbinsz; binz++) {
3975 }
3976 }
3977 }
3978 }
3979 else if (axis == 2) {
3982 }
3983 for (Int_t biny = lastBin; biny >= firstBin; biny--) {
3984 for (Int_t binx = 1; binx <= nbinsx; binx++) {
3985 for (Int_t binz = 1; binz <= nbinsz; binz++) {
3987 }
3988 }
3989 }
3990 }
3991 else if (axis == 3) {
3994 }
3995 for (Int_t binz = lastBin; binz >= firstBin; binz--) {
3996 for (Int_t binx = 1; binx <= nbinsx; binx++) {
3997 for (Int_t biny = 1; biny <= nbinsy; biny++) {
3999 }
4000 }
4001 }
4002 }
4003
4004 return -1;
4005}
4006
4007////////////////////////////////////////////////////////////////////////////////
4008/// Search object named name in the list of functions.
4009
4010TObject *TH1::FindObject(const char *name) const
4011{
4012 if (fFunctions) return fFunctions->FindObject(name);
4013 return nullptr;
4014}
4015
4016////////////////////////////////////////////////////////////////////////////////
4017/// Search object obj in the list of functions.
4018
4019TObject *TH1::FindObject(const TObject *obj) const
4020{
4021 if (fFunctions) return fFunctions->FindObject(obj);
4022 return nullptr;
4023}
4024
4025////////////////////////////////////////////////////////////////////////////////
4026/// Fit histogram with function fname.
4027///
4028///
4029/// fname is the name of a function available in the global ROOT list of functions
4030/// `gROOT->GetListOfFunctions`. Note that this is not thread safe.
4031/// The list include any TF1 object created by the user plus some pre-defined functions
4032/// which are automatically created by ROOT the first time a pre-defined function is requested from `gROOT`
4033/// (i.e. when calling `gROOT->GetFunction(const char *name)`).
4034/// These pre-defined functions are:
4035/// - `gaus, gausn` where gausn is the normalized Gaussian
4036/// - `landau, landaun`
4037/// - `expo`
4038/// - `pol1,...9, chebyshev1,...9`.
4039///
4040/// For printing the list of all available functions do:
4041///
4042/// TF1::InitStandardFunctions(); // not needed if `gROOT->GetFunction` is called before
4043/// TF2::InitStandardFunctions(); TF3::InitStandardFunctions(); // For 2D or 3D
4044/// gROOT->GetListOfFunctions()->ls()
4045///
4046/// `fname` can also be a formula that is accepted by the linear fitter containing the special operator `++`,
4047/// representing linear components separated by `++` sign, for example `x++sin(x)` for fitting `[0]*x+[1]*sin(x)`
4048///
4049/// This function finds a pointer to the TF1 object with name `fname` and calls TH1::Fit(TF1 *, Option_t *, Option_t *,
4050/// Double_t, Double_t). See there for the fitting options and the details about fitting histograms
4051
4053{
4054 char *linear;
4055 linear= (char*)strstr(fname, "++");
4056 Int_t ndim=GetDimension();
4057 if (linear){
4058 if (ndim<2){
4060 return Fit(&f1,option,goption,xxmin,xxmax);
4061 }
4062 else if (ndim<3){
4063 TF2 f2(fname, fname);
4064 return Fit(&f2,option,goption,xxmin,xxmax);
4065 }
4066 else{
4067 TF3 f3(fname, fname);
4068 return Fit(&f3,option,goption,xxmin,xxmax);
4069 }
4070 }
4071 else{
4072 TF1 * f1 = (TF1*)gROOT->GetFunction(fname);
4073 if (!f1) { Printf("Unknown function: %s",fname); return -1; }
4074 return Fit(f1,option,goption,xxmin,xxmax);
4075 }
4076}
4077
4078////////////////////////////////////////////////////////////////////////////////
4079/// Fit histogram with the function pointer f1.
4080///
4081/// \param[in] f1 pointer to the function object
4082/// \param[in] option string defining the fit options (see table below).
4083/// \param[in] goption specify a list of graphics options. See TH1::Draw for a complete list of these options.
4084/// \param[in] xxmin lower fitting range
4085/// \param[in] xxmax upper fitting range
4086/// \return A smart pointer to the TFitResult class
4087///
4088/// \anchor HFitOpt
4089/// ### Histogram Fitting Options
4090///
4091/// Here is the full list of fit options that can be given in the parameter `option`.
4092/// Several options can be used together by concatanating the strings without the need of any delimiters.
4093///
4094/// option | description
4095/// -------|------------
4096/// "L" | Uses a log likelihood method (default is chi-square method). To be used when the histogram represents counts.
4097/// "WL" | Weighted log likelihood method. To be used when the histogram has been filled with weights different than 1. This is needed for getting correct parameter uncertainties for weighted fits.
4098/// "P" | Uses Pearson chi-square method. Uses expected errors instead of the observed one (default case). The expected error is instead estimated from the square-root of the bin function value.
4099/// "MULTI" | Uses Loglikelihood method based on multi-nomial distribution. In this case the function must be normalized and one fits only the function shape.
4100/// "W" | Fit using the chi-square method and ignoring the bin uncertainties and skip empty bins.
4101/// "WW" | Fit using the chi-square method and ignoring the bin uncertainties and include the empty bins.
4102/// "I" | Uses the integral of function in the bin instead of the default bin center value.
4103/// "F" | Uses the default minimizer (e.g. Minuit) when fitting a linear function (e.g. polN) instead of the linear fitter.
4104/// "U" | Uses a user specified objective function (e.g. user providedlikelihood function) defined using `TVirtualFitter::SetFCN`
4105/// "E" | Performs a better parameter errors estimation using the Minos technique for all fit parameters.
4106/// "M" | Uses the IMPROVE algorithm (available only in TMinuit). This algorithm attempts improve the found local minimum by searching for a better one.
4107/// "S" | The full result of the fit is returned in the `TFitResultPtr`. This is needed to get the covariance matrix of the fit. See `TFitResult` and the base class `ROOT::Math::FitResult`.
4108/// "Q" | Quiet mode (minimum printing)
4109/// "V" | Verbose mode (default is between Q and V)
4110/// "+" | Adds this new fitted function to the list of fitted functions. By default, the previous function is deleted and only the last one is kept.
4111/// "N" | Does not store the graphics function, does not draw the histogram with the function after fitting.
4112/// "0" | Does not draw the histogram and the fitted function after fitting, but in contrast to option "N", it stores the fitted function in the histogram list of functions.
4113/// "R" | Fit using a fitting range specified in the function range with `TF1::SetRange`.
4114/// "B" | Use this option when you want to fix or set limits on one or more parameters and the fitting function is a predefined one (e.g gaus, expo,..), otherwise in case of pre-defined functions, some default initial values and limits will be used.
4115/// "C" | In case of linear fitting, do no calculate the chisquare (saves CPU time).
4116/// "G" | Uses the gradient implemented in `TF1::GradientPar` for the minimization. This allows to use Automatic Differentiation when it is supported by the provided TF1 function.
4117/// "WIDTH" | Scales the histogran bin content by the bin width (useful for variable bins histograms)
4118/// "SERIAL" | Runs in serial mode. By default if ROOT is built with MT support and MT is enables, the fit is perfomed in multi-thread - "E" Perform better Errors estimation using Minos technique
4119/// "MULTITHREAD" | Forces usage of multi-thread execution whenever possible
4120///
4121/// The default fitting of an histogram (when no option is given) is perfomed as following:
4122/// - a chi-square fit (see below Chi-square Fits) computed using the bin histogram errors and excluding bins with zero errors (empty bins);
4123/// - the full range of the histogram is used, unless TAxis::SetRange or TAxis::SetRangeUser was called before;
4124/// - the default Minimizer with its default configuration is used (see below Minimizer Configuration) except for linear function;
4125/// - for linear functions (`polN`, `chenbyshev` or formula expressions combined using operator `++`) a linear minimization is used.
4126/// - only the status of the fit is returned;
4127/// - the fit is performed in Multithread whenever is enabled in ROOT;
4128/// - only the last fitted function is saved in the histogram;
4129/// - the histogram is drawn after fitting overalyed with the resulting fitting function
4130///
4131/// \anchor HFitMinimizer
4132/// ### Minimizer Configuration
4133///
4134/// The Fit is perfomed using the default Minimizer, defined in the `ROOT::Math::MinimizerOptions` class.
4135/// It is possible to change the default minimizer and its configuration parameters by calling these static functions before fitting (before calling `TH1::Fit`):
4136/// - `ROOT::Math::MinimizerOptions::SetDefaultMinimizer(minimizerName, minimizerAgorithm)` for changing the minmizer and/or the corresponding algorithm.
4137/// For example `ROOT::Math::MinimizerOptions::SetDefaultMinimizer("GSLMultiMin","BFGS");` will set the usage of the BFGS algorithm of the GSL multi-dimensional minimization
4138/// The current defaults are ("Minuit","Migrad").
4139/// See the documentation of the `ROOT::Math::MinimizerOptions` for the available minimizers in ROOT and their corresponding algorithms.
4140/// - `ROOT::Math::MinimizerOptions::SetDefaultTolerance` for setting a different tolerance value for the minimization.
4141/// - `ROOT::Math::MinimizerOptions::SetDefaultMaxFunctionCalls` for setting the maximum number of function calls.
4142/// - `ROOT::Math::MinimizerOptions::SetDefaultPrintLevel` for changing the minimizer print level from level=0 (minimal printing) to level=3 maximum printing
4143///
4144/// Other options are possible depending on the Minimizer used, see the corresponding documentation.
4145/// The default minimizer can be also set in the resource file in etc/system.rootrc. For example
4146///
4147/// ~~~ {.cpp}
4148/// Root.Fitter: Minuit2
4149/// ~~~
4150///
4151/// \anchor HFitChi2
4152/// ### Chi-square Fits
4153///
4154/// By default a chi-square (least-square) fit is performed on the histogram. The so-called modified least-square method
4155/// is used where the residual for each bin is computed using as error the observed value (the bin error) returned by `TH1::GetBinError`
4156///
4157/// \f[
4158/// Chi2 = \sum_{i}{ \left(\frac{y(i) - f(x(i) | p )}{e(i)} \right)^2 }
4159/// \f]
4160///
4161/// where `y(i)` is the bin content for each bin `i`, `x(i)` is the bin center and `e(i)` is the bin error (`sqrt(y(i)` for
4162/// an un-weighted histogram). Bins with zero errors are excluded from the fit. See also later the note on the treatment
4163/// of empty bins. When using option "I" the residual is computed not using the function value at the bin center, `f(x(i)|p)`,
4164/// but the integral of the function in the bin, Integral{ f(x|p)dx }, divided by the bin volume.
4165/// When using option `P` (Pearson chi2), the expected error computed as `e(i) = sqrt(f(x(i)|p))` is used.
4166/// In this case empty bins are considered in the fit.
4167/// Both chi-square methods should not be used when the bin content represent counts, especially in case of low bin statistics,
4168/// because they could return a biased result.
4169///
4170/// \anchor HFitNLL
4171/// ### Likelihood Fits
4172///
4173/// When using option "L" a likelihood fit is used instead of the default chi-square fit.
4174/// The likelihood is built assuming a Poisson probability density function for each bin.
4175/// The negative log-likelihood to be minimized is
4176///
4177/// \f[
4178/// NLL = - \sum_{i}{ \log {\mathrm P} ( y(i) | f(x(i) | p ) ) }
4179/// \f]
4180/// where `P(y|f)` is the Poisson distribution of observing a count `y(i)` in the bin when the expected count is `f(x(i)|p)`.
4181/// The exact likelihood used is the Poisson likelihood described in this paper:
4182/// S. Baker and R. D. Cousins, “Clarification of the use of chi-square and likelihood functions in fits to histograms,”
4183/// Nucl. Instrum. Meth. 221 (1984) 437.
4184///
4185/// \f[
4186/// NLL = \sum_{i}{( f(x(i) | p ) + y(i)\log(y(i)/ f(x(i) | p )) - y(i)) }
4187/// \f]
4188/// By using this formulation, `2*NLL` can be interpreted as the chi-square resulting from the fit.
4189///
4190/// This method should be always used when the bin content represents counts (i.e. errors are sqrt(N) ).
4191/// The likelihood method has the advantage of treating correctly bins with low statistics. In case of high
4192/// statistics/bin the distribution of the bin content becomes a normal distribution and the likelihood and the chi2 fit
4193/// give the same result.
4194///
4195/// The likelihood method, although a bit slower, it is therefore the recommended method,
4196/// when the histogram represent counts (Poisson statistics), where the chi-square methods may
4197/// give incorrect results, especially in case of low statistics.
4198/// In case of a weighted histogram, it is possible to perform also a likelihood fit by using the
4199/// option "WL". Note a weighted histogram is a histogram which has been filled with weights and it
4200/// has the information on the sum of the weight square for each bin ( TH1::Sumw2() has been called).
4201/// The bin error for a weighted histogram is the square root of the sum of the weight square.
4202///
4203/// \anchor HFitRes
4204/// ### Fit Result
4205///
4206/// The function returns a TFitResultPtr which can hold a pointer to a TFitResult object.
4207/// By default the TFitResultPtr contains only the status of the fit which is return by an
4208/// automatic conversion of the TFitResultPtr to an integer. One can write in this case directly:
4209///
4210/// ~~~ {.cpp}
4211/// Int_t fitStatus = h->Fit(myFunc);
4212/// ~~~
4213///
4214/// If the option "S" is instead used, TFitResultPtr behaves as a smart
4215/// pointer to the TFitResult object. This is useful for retrieving the full result information from the fit, such as the covariance matrix,
4216/// as shown in this example code:
4217///
4218/// ~~~ {.cpp}
4219/// TFitResultPtr r = h->Fit(myFunc,"S");
4220/// TMatrixDSym cov = r->GetCovarianceMatrix(); // to access the covariance matrix
4221/// Double_t chi2 = r->Chi2(); // to retrieve the fit chi2
4222/// Double_t par0 = r->Parameter(0); // retrieve the value for the parameter 0
4223/// Double_t err0 = r->ParError(0); // retrieve the error for the parameter 0
4224/// r->Print("V"); // print full information of fit including covariance matrix
4225/// r->Write(); // store the result in a file
4226/// ~~~
4227///
4228/// The fit parameters, error and chi-square (but not covariance matrix) can be retrieved also
4229/// directly from the fitted function that is passed to this call.
4230/// Given a pointer to an associated fitted function `myfunc`, one can retrieve the function/fit
4231/// parameters with calls such as:
4232///
4233/// ~~~ {.cpp}
4234/// Double_t chi2 = myfunc->GetChisquare();
4235/// Double_t par0 = myfunc->GetParameter(0); //value of 1st parameter
4236/// Double_t err0 = myfunc->GetParError(0); //error on first parameter
4237/// ~~~
4238///
4239/// ##### Associated functions
4240///
4241/// One or more objects (typically a TF1*) can be added to the list
4242/// of functions (fFunctions) associated to each histogram.
4243/// When TH1::Fit is invoked, the fitted function is added to the histogram list of functions (fFunctions).
4244/// If the histogram is made persistent, the list of associated functions is also persistent.
4245/// Given a histogram h, one can retrieve an associated function with:
4246///
4247/// ~~~ {.cpp}
4248/// TF1 *myfunc = h->GetFunction("myfunc");
4249/// ~~~
4250/// or by quering directly the list obtained by calling `TH1::GetListOfFunctions`.
4251///
4252/// \anchor HFitStatus
4253/// ### Fit status
4254///
4255/// The status of the fit is obtained converting the TFitResultPtr to an integer
4256/// independently if the fit option "S" is used or not:
4257///
4258/// ~~~ {.cpp}
4259/// TFitResultPtr r = h->Fit(myFunc,opt);
4260/// Int_t fitStatus = r;
4261/// ~~~
4262///
4263/// - `status = 0` : the fit has been performed successfully (i.e no error occurred).
4264/// - `status < 0` : there is an error not connected with the minimization procedure, for example when a wrong function is used.
4265/// - `status > 0` : return status from Minimizer, depends on used Minimizer. For example for TMinuit and Minuit2 we have:
4266/// - `status = migradStatus + 10*minosStatus + 100*hesseStatus + 1000*improveStatus`.
4267/// TMinuit returns 0 (for migrad, minos, hesse or improve) in case of success and 4 in case of error (see the documentation of TMinuit::mnexcm). For example, for an error
4268/// only in Minos but not in Migrad a fitStatus of 40 will be returned.
4269/// Minuit2 returns 0 in case of success and different values in migrad,minos or
4270/// hesse depending on the error. See in this case the documentation of
4271/// Minuit2Minimizer::Minimize for the migrad return status, Minuit2Minimizer::GetMinosError for the
4272/// minos return status and Minuit2Minimizer::Hesse for the hesse return status.
4273/// If other minimizers are used see their specific documentation for the status code returned.
4274/// For example in the case of Fumili, see TFumili::Minimize.
4275///
4276/// \anchor HFitRange
4277/// ### Fitting in a range
4278///
4279/// In order to fit in a sub-range of the histogram you have two options:
4280/// - pass to this function the lower (`xxmin`) and upper (`xxmax`) values for the fitting range;
4281/// - define a specific range in the fitted function and use the fitting option "R".
4282/// For example, if your histogram has a defined range between -4 and 4 and you want to fit a gaussian
4283/// only in the interval 1 to 3, you can do:
4284///
4285/// ~~~ {.cpp}
4286/// TF1 *f1 = new TF1("f1", "gaus", 1, 3);
4287/// histo->Fit("f1", "R");
4288/// ~~~
4289///
4290/// The fitting range is also limited by the histogram range defined using TAxis::SetRange
4291/// or TAxis::SetRangeUser. Therefore the fitting range is the smallest range between the
4292/// histogram one and the one defined by one of the two previous options described above.
4293///
4294/// \anchor HFitInitial
4295/// ### Setting initial conditions
4296///
4297/// Parameters must be initialized before invoking the Fit function.
4298/// The setting of the parameter initial values is automatic for the
4299/// predefined functions such as poln, expo, gaus, landau. One can however disable
4300/// this automatic computation by using the option "B".
4301/// Note that if a predefined function is defined with an argument,
4302/// eg, gaus(0), expo(1), you must specify the initial values for
4303/// the parameters.
4304/// You can specify boundary limits for some or all parameters via
4305///
4306/// ~~~ {.cpp}
4307/// f1->SetParLimits(p_number, parmin, parmax);
4308/// ~~~
4309///
4310/// if `parmin >= parmax`, the parameter is fixed
4311/// Note that you are not forced to fix the limits for all parameters.
4312/// For example, if you fit a function with 6 parameters, you can do:
4313///
4314/// ~~~ {.cpp}
4315/// func->SetParameters(0, 3.1, 1.e-6, -8, 0, 100);
4316/// func->SetParLimits(3, -10, -4);
4317/// func->FixParameter(4, 0);
4318/// func->SetParLimits(5, 1, 1);
4319/// ~~~
4320///
4321/// With this setup, parameters 0->2 can vary freely
4322/// Parameter 3 has boundaries [-10,-4] with initial value -8
4323/// Parameter 4 is fixed to 0
4324/// Parameter 5 is fixed to 100.
4325/// When the lower limit and upper limit are equal, the parameter is fixed.
4326/// However to fix a parameter to 0, one must call the FixParameter function.
4327///
4328/// \anchor HFitStatBox
4329/// ### Fit Statistics Box
4330///
4331/// The statistics box can display the result of the fit.
4332/// You can change the statistics box to display the fit parameters with
4333/// the TStyle::SetOptFit(mode) method. This mode has four digits.
4334/// mode = pcev (default = 0111)
4335///
4336/// v = 1; print name/values of parameters
4337/// e = 1; print errors (if e=1, v must be 1)
4338/// c = 1; print Chisquare/Number of degrees of freedom
4339/// p = 1; print Probability
4340///
4341/// For example: gStyle->SetOptFit(1011);
4342/// prints the fit probability, parameter names/values, and errors.
4343/// You can change the position of the statistics box with these lines
4344/// (where g is a pointer to the TGraph):
4345///
4346/// TPaveStats *st = (TPaveStats*)g->GetListOfFunctions()->FindObject("stats");
4347/// st->SetX1NDC(newx1); //new x start position
4348/// st->SetX2NDC(newx2); //new x end position
4349///
4350/// \anchor HFitExtra
4351/// ### Additional Notes on Fitting
4352///
4353/// #### Fitting a histogram of dimension N with a function of dimension N-1
4354///
4355/// It is possible to fit a TH2 with a TF1 or a TH3 with a TF2.
4356/// In this case the chi-square is computed from the squared error distance between the function values and the bin centers weighted by the bin content.
4357/// For correct error scaling, the obtained parameter error are corrected as in the case when the
4358/// option "W" is used.
4359///
4360/// #### User defined objective functions
4361///
4362/// By default when fitting a chi square function is used for fitting. When option "L" is used
4363/// a Poisson likelihood function is used. Using option "MULTI" a multinomial likelihood fit is used.
4364/// Thes functions are defined in the header Fit/Chi2Func.h or Fit/PoissonLikelihoodFCN and they
4365/// are implemented using the routines FitUtil::EvaluateChi2 or FitUtil::EvaluatePoissonLogL in
4366/// the file math/mathcore/src/FitUtil.cxx.
4367/// It is possible to specify a user defined fitting function, using option "U" and
4368/// calling the following functions:
4369///
4370/// ~~~ {.cpp}
4371/// TVirtualFitter::Fitter(myhist)->SetFCN(MyFittingFunction);
4372/// ~~~
4373///
4374/// where MyFittingFunction is of type:
4375///
4376/// ~~~ {.cpp}
4377/// extern void MyFittingFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
4378/// ~~~
4379///
4380/// #### Note on treatment of empty bins
4381///
4382/// Empty bins, which have the content equal to zero AND error equal to zero,
4383/// are excluded by default from the chi-square fit, but they are considered in the likelihood fit.
4384/// since they affect the likelihood if the function value in these bins is not negligible.
4385/// Note that if the histogram is having bins with zero content and non zero-errors they are considered as
4386/// any other bins in the fit. Instead bins with zero error and non-zero content are by default excluded in the chi-squared fit.
4387/// In general, one should not fit a histogram with non-empty bins and zero errors.
4388///
4389/// If the bin errors are not known, one should use the fit option "W", which gives a weight=1 for each bin (it is an unweighted least-square
4390/// fit). When using option "WW" the empty bins will be also considered in the chi-square fit with an error of 1.
4391/// Note that in this fitting case (option "W" or "WW") the resulting fitted parameter errors
4392/// are corrected by the obtained chi2 value using this scaling expression:
4393/// `errorp *= sqrt(chisquare/(ndf-1))` as it is done when fitting a TGraph with
4394/// no point errors.
4395///
4396/// #### Excluding points
4397///
4398/// You can use TF1::RejectPoint inside your fitting function to exclude some points
4399/// within a certain range from the fit. See the tutorial `fit/fitExclude.C`.
4400///
4401///
4402/// #### Warning when using the option "0"
4403///
4404/// When selecting the option "0", the fitted function is added to
4405/// the list of functions of the histogram, but it is not drawn when the histogram is drawn.
4406/// You can undo this behaviour resetting its corresponding bit in the TF1 object as following:
4407///
4408/// ~~~ {.cpp}
4409/// h.Fit("myFunction", "0"); // fit, store function but do not draw
4410/// h.Draw(); // function is not drawn
4411/// h.GetFunction("myFunction")->ResetBit(TF1::kNotDraw);
4412/// h.Draw(); // function is visible again
4413/// ~~~
4415
4417{
4418 // implementation of Fit method is in file hist/src/HFitImpl.cxx
4421
4422 // create range and minimizer options with default values
4425
4426 // need to empty the buffer before
4427 // (t.b.d. do a ML unbinned fit with buffer data)
4428 if (fBuffer) BufferEmpty();
4429
4431}
4432
4433////////////////////////////////////////////////////////////////////////////////
4434/// Display a panel with all histogram fit options.
4435///
4436/// See class TFitPanel for example
4437
4438void TH1::FitPanel()
4439{
4440 if (!gPad)
4441 gROOT->MakeDefCanvas();
4442
4443 if (!gPad) {
4444 Error("FitPanel", "Unable to create a default canvas");
4445 return;
4446 }
4447
4448
4449 // use plugin manager to create instance of TFitEditor
4450 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TFitEditor");
4451 if (handler && handler->LoadPlugin() != -1) {
4452 if (handler->ExecPlugin(2, gPad, this) == 0)
4453 Error("FitPanel", "Unable to create the FitPanel");
4454 }
4455 else
4456 Error("FitPanel", "Unable to find the FitPanel plug-in");
4457}
4458
4459////////////////////////////////////////////////////////////////////////////////
4460/// Return a histogram containing the asymmetry of this histogram with h2,
4461/// where the asymmetry is defined as:
4462///
4463/// ~~~ {.cpp}
4464/// Asymmetry = (h1 - h2)/(h1 + h2) where h1 = this
4465/// ~~~
4466///
4467/// works for 1D, 2D, etc. histograms
4468/// c2 is an optional argument that gives a relative weight between the two
4469/// histograms, and dc2 is the error on this weight. This is useful, for example,
4470/// when forming an asymmetry between two histograms from 2 different data sets that
4471/// need to be normalized to each other in some way. The function calculates
4472/// the errors assuming Poisson statistics on h1 and h2 (that is, dh = sqrt(h)).
4473///
4474/// example: assuming 'h1' and 'h2' are already filled
4475///
4476/// ~~~ {.cpp}
4477/// h3 = h1->GetAsymmetry(h2)
4478/// ~~~
4479///
4480/// then 'h3' is created and filled with the asymmetry between 'h1' and 'h2';
4481/// h1 and h2 are left intact.
4482///
4483/// Note that it is the user's responsibility to manage the created histogram.
4484/// The name of the returned histogram will be `Asymmetry_nameOfh1-nameOfh2`
4485///
4486/// code proposed by Jason Seely (seely@mit.edu) and adapted by R.Brun
4487///
4488/// clone the histograms so top and bottom will have the
4489/// correct dimensions:
4490/// Sumw2 just makes sure the errors will be computed properly
4491/// when we form sums and ratios below.
4492
4494{
4495 TH1 *h1 = this;
4496 TString name = TString::Format("Asymmetry_%s-%s",h1->GetName(),h2->GetName() );
4497 TH1 *asym = (TH1*)Clone(name);
4498
4499 // set also the title
4500 TString title = TString::Format("(%s - %s)/(%s+%s)",h1->GetName(),h2->GetName(),h1->GetName(),h2->GetName() );
4501 asym->SetTitle(title);
4502
4503 asym->Sumw2();
4504
4505 TDirectory::TContext ctx{nullptr};
4506 TH1 *top = (TH1*)asym->Clone();
4507 TH1 *bottom = (TH1*)asym->Clone();
4508
4509 // form the top and bottom of the asymmetry, and then divide:
4510 top->Add(h1,h2,1,-c2);
4511 bottom->Add(h1,h2,1,c2);
4512 asym->Divide(top,bottom);
4513
4514 Int_t xmax = asym->GetNbinsX();
4515 Int_t ymax = asym->GetNbinsY();
4516 Int_t zmax = asym->GetNbinsZ();
4517
4518 if (h1->fBuffer) h1->BufferEmpty(1);
4519 if (h2->fBuffer) h2->BufferEmpty(1);
4520 if (bottom->fBuffer) bottom->BufferEmpty(1);
4521
4522 // now loop over bins to calculate the correct errors
4523 // the reason this error calculation looks complex is because of c2
4524 for(Int_t i=1; i<= xmax; i++){
4525 for(Int_t j=1; j<= ymax; j++){
4526 for(Int_t k=1; k<= zmax; k++){
4527 Int_t bin = GetBin(i, j, k);
4528 // here some bin contents are written into variables to make the error
4529 // calculation a little more legible:
4533
4534 // make sure there are some events, if not, then the errors are set = 0
4535 // automatically.
4536 //if(bot < 1){} was changed to the next line from recommendation of Jason Seely (28 Nov 2005)
4537 if(bot < 1e-6){}
4538 else{
4539 // computation of errors by Christos Leonidopoulos
4542 Double_t error = 2*TMath::Sqrt(a*a*c2*c2*dbsq + c2*c2*b*b*dasq+a*a*b*b*dc2*dc2)/(bot*bot);
4543 asym->SetBinError(i,j,k,error);
4544 }
4545 }
4546 }
4547 }
4548 delete top;
4549 delete bottom;
4550
4551 return asym;
4552}
4553
4554////////////////////////////////////////////////////////////////////////////////
4555/// Static function
4556/// return the default buffer size for automatic histograms
4557/// the parameter fgBufferSize may be changed via SetDefaultBufferSize
4558
4560{
4561 return fgBufferSize;
4562}
4563
4564////////////////////////////////////////////////////////////////////////////////
4565/// Return kTRUE if TH1::Sumw2 must be called when creating new histograms.
4566/// see TH1::SetDefaultSumw2.
4567
4569{
4570 return fgDefaultSumw2;
4571}
4572
4573////////////////////////////////////////////////////////////////////////////////
4574/// Return the current number of entries.
4575
4577{
4578 if (fBuffer) {
4579 Int_t nentries = (Int_t) fBuffer[0];
4580 if (nentries > 0) return nentries;
4581 }
4582
4583 return fEntries;
4584}
4585
4586////////////////////////////////////////////////////////////////////////////////
4587/// Number of effective entries of the histogram.
4588///
4589/// \f[
4590/// neff = \frac{(\sum Weights )^2}{(\sum Weight^2 )}
4591/// \f]
4592///
4593/// In case of an unweighted histogram this number is equivalent to the
4594/// number of entries of the histogram.
4595/// For a weighted histogram, this number corresponds to the hypothetical number of unweighted entries
4596/// a histogram would need to have the same statistical power as this weighted histogram.
4597/// Note: The underflow/overflow are included if one has set the TH1::StatOverFlows flag
4598/// and if the statistics has been computed at filling time.
4599/// If a range is set in the histogram the number is computed from the given range.
4600
4602{
4603 Stat_t s[kNstat];
4604 this->GetStats(s);// s[1] sum of squares of weights, s[0] sum of weights
4605 return (s[1] ? s[0]*s[0]/s[1] : TMath::Abs(s[0]) );
4606}
4607
4608////////////////////////////////////////////////////////////////////////////////
4609/// Shortcut to set the three histogram colors with a single call.
4610///
4611/// By default: linecolor = markercolor = fillcolor = -1
4612/// If a color is < 0 this method does not change the corresponding color if positive or null it set the color.
4613///
4614/// For instance:
4615/// ~~~ {.cpp}
4616/// h->SetColors(kRed, kRed);
4617/// ~~~
4618/// will set the line color and the marker color to red.
4619
4621{
4622 if (linecolor >= 0)
4624 if (markercolor >= 0)
4626 if (fillcolor >= 0)
4628}
4629
4630
4631////////////////////////////////////////////////////////////////////////////////
4632/// Set highlight (enable/disable) mode for the histogram
4633/// by default highlight mode is disable
4634
4635void TH1::SetHighlight(Bool_t set)
4636{
4637 if (IsHighlight() == set)
4638 return;
4639 if (fDimension > 2) {
4640 Info("SetHighlight", "Supported only 1-D or 2-D histograms");
4641 return;
4642 }
4643
4644 SetBit(kIsHighlight, set);
4645
4646 if (fPainter)
4648}
4649
4650////////////////////////////////////////////////////////////////////////////////
4651/// Redefines TObject::GetObjectInfo.
4652/// Displays the histogram info (bin number, contents, integral up to bin
4653/// corresponding to cursor position px,py
4654
4655char *TH1::GetObjectInfo(Int_t px, Int_t py) const
4656{
4657 return ((TH1*)this)->GetPainter()->GetObjectInfo(px,py);
4658}
4659
4660////////////////////////////////////////////////////////////////////////////////
4661/// Return pointer to painter.
4662/// If painter does not exist, it is created
4663
4665{
4666 if (!fPainter) {
4667 TString opt = option;
4668 opt.ToLower();
4669 if (opt.Contains("gl") || gStyle->GetCanvasPreferGL()) {
4670 //try to create TGLHistPainter
4671 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TGLHistPainter");
4672
4673 if (handler && handler->LoadPlugin() != -1)
4674 fPainter = reinterpret_cast<TVirtualHistPainter *>(handler->ExecPlugin(1, this));
4675 }
4676 }
4677
4679
4680 return fPainter;
4681}
4682
4683////////////////////////////////////////////////////////////////////////////////
4684/// Compute Quantiles for this histogram.
4685/// A quantile x_p := Q(p) is defined as the value x_p such that the cumulative
4686/// probability distribution Function F of variable X yields:
4687///
4688/// ~~~ {.cpp}
4689/// F(x_p) = Pr(X <= x_p) = p with 0 <= p <= 1.
4690/// x_p = Q(p) = F_inv(p)
4691/// ~~~
4692///
4693/// For instance the median x_0.5 of a distribution is defined as that value
4694/// of the random variable X for which the distribution function equals 0.5:
4695///
4696/// ~~~ {.cpp}
4697/// F(x_0.5) = Probability(X < x_0.5) = 0.5
4698/// x_0.5 = Q(0.5)
4699/// ~~~
4700///
4701/// \author Eddy Offermann
4702/// code from Eddy Offermann, Renaissance
4703///
4704/// \param[in] n maximum size of the arrays xp and p (if given)
4705/// \param[out] xp array to be filled with nq quantiles evaluated at (p). Memory has to be preallocated by caller.
4706/// - If `p == nullptr`, the quantiles are computed at the (first `n`) probabilities p given by the CDF of the histogram;
4707/// `n` must thus be smaller or equal Nbins+1, otherwise the extra values of `xp` will not be filled and `nq` will be smaller than `n`.
4708/// If all bins have non-zero entries, the quantiles happen to be the bin centres.
4709/// Empty bins will, however, be skipped in the quantiles.
4710/// If the CDF is e.g. [0., 0., 0.1, ...], the quantiles would be, [3., 3., 3., ...], with the third bin starting
4711/// at 3.
4712/// \param[in] p array of cumulative probabilities where quantiles should be evaluated.
4713/// - if `p == nullptr`, the CDF of the histogram will be used to compute the quantiles, and will
4714/// have a size of n.
4715/// - Otherwise, it is assumed to contain at least n values.
4716/// \return number of quantiles computed
4717/// \note Unlike in TF1::GetQuantiles, `p` is here an optional argument
4718///
4719/// Note that the Integral of the histogram is automatically recomputed
4720/// if the number of entries is different of the number of entries when
4721/// the integral was computed last time. In case you do not use the Fill
4722/// functions to fill your histogram, but SetBinContent, you must call
4723/// TH1::ComputeIntegral before calling this function.
4724///
4725/// Getting quantiles xp from two histograms and storing results in a TGraph,
4726/// a so-called QQ-plot
4727///
4728/// ~~~ {.cpp}
4729/// TGraph *gr = new TGraph(nprob);
4730/// h1->GetQuantiles(nprob,gr->GetX());
4731/// h2->GetQuantiles(nprob,gr->GetY());
4732/// gr->Draw("alp");
4733/// ~~~
4734///
4735/// Example:
4736///
4737/// ~~~ {.cpp}
4738/// void quantiles() {
4739/// // demo for quantiles
4740/// const Int_t nq = 20;
4741/// TH1F *h = new TH1F("h","demo quantiles",100,-3,3);
4742/// h->FillRandom("gaus",5000);
4743/// h->GetXaxis()->SetTitle("x");
4744/// h->GetYaxis()->SetTitle("Counts");
4745///
4746/// Double_t p[nq]; // probabilities where to evaluate the quantiles in [0,1]
4747/// Double_t xp[nq]; // array of positions X to store the resulting quantiles
4748/// for (Int_t i=0;i<nq;i++) p[i] = Float_t(i+1)/nq;
4749/// h->GetQuantiles(nq,xp,p);
4750///
4751/// //show the original histogram in the top pad
4752/// TCanvas *c1 = new TCanvas("c1","demo quantiles",10,10,700,900);
4753/// c1->Divide(1,2);
4754/// c1->cd(1);
4755/// h->Draw();
4756///
4757/// // show the quantiles in the bottom pad
4758/// c1->cd(2);
4759/// gPad->SetGrid();
4760/// TGraph *gr = new TGraph(nq,p,xp);
4761/// gr->SetMarkerStyle(21);
4762/// gr->GetXaxis()->SetTitle("p");
4763/// gr->GetYaxis()->SetTitle("x");
4764/// gr->Draw("alp");
4765/// }
4766/// ~~~
4767
4769{
4770 if (GetDimension() > 1) {
4771 Error("GetQuantiles","Only available for 1-d histograms");
4772 return 0;
4773 }
4774
4775 const Int_t nbins = GetXaxis()->GetNbins();
4776 if (!fIntegral) ComputeIntegral();
4778
4779 Int_t i, ibin;
4780 Int_t nq = n;
4781 std::unique_ptr<Double_t[]> localProb;
4782 if (p == nullptr) {
4783 nq = nbins+1;
4784 localProb.reset(new Double_t[nq]);
4785 localProb[0] = 0;
4786 for (i=1;i<nq;i++) {
4788 }
4789 }
4790 Double_t const *const prob = p ? p : localProb.get();
4791
4792 for (i = 0; i < nq; i++) {
4794 if (fIntegral[ibin] == prob[i]) {
4795 if (prob[i] == 0.) {
4796 for (; ibin+1 <= nbins && fIntegral[ibin+1] == 0.; ++ibin) {
4797
4798 }
4799 xp[i] = fXaxis.GetBinUpEdge(ibin);
4800 }
4801 else if (prob[i] == 1.) {
4802 xp[i] = fXaxis.GetBinUpEdge(ibin);
4803 }
4804 else {
4805 // Find equal integral in later bins (ie their entries are zero)
4806 Double_t width = 0;
4807 for (Int_t j = ibin+1; j <= nbins; ++j) {
4808 if (prob[i] == fIntegral[j]) {
4810 }
4811 else
4812 break;
4813 }
4815 }
4816 }
4817 else {
4818 xp[i] = GetBinLowEdge(ibin+1);
4820 if (dint > 0) xp[i] += GetBinWidth(ibin+1)*(prob[i]-fIntegral[ibin])/dint;
4821 }
4822 }
4823
4824 return nq;
4825}
4826
4827////////////////////////////////////////////////////////////////////////////////
4833 return 1;
4834}
4835
4836////////////////////////////////////////////////////////////////////////////////
4837/// Compute Initial values of parameters for a gaussian.
4838
4839void H1InitGaus()
4840{
4841 Double_t allcha, sumx, sumx2, x, val, stddev, mean;
4842 Int_t bin;
4843 const Double_t sqrtpi = 2.506628;
4844
4845 // - Compute mean value and StdDev of the histogram in the given range
4847 TH1 *curHist = (TH1*)hFitter->GetObjectFit();
4848 Int_t hxfirst = hFitter->GetXfirst();
4849 Int_t hxlast = hFitter->GetXlast();
4850 Double_t valmax = curHist->GetBinContent(hxfirst);
4851 Double_t binwidx = curHist->GetBinWidth(hxfirst);
4852 allcha = sumx = sumx2 = 0;
4853 for (bin=hxfirst;bin<=hxlast;bin++) {
4854 x = curHist->GetBinCenter(bin);
4855 val = TMath::Abs(curHist->GetBinContent(bin));
4856 if (val > valmax) valmax = val;
4857 sumx += val*x;
4858 sumx2 += val*x*x;
4859 allcha += val;
4860 }
4861 if (allcha == 0) return;
4862 mean = sumx/allcha;
4863 stddev = sumx2/allcha - mean*mean;
4864 if (stddev > 0) stddev = TMath::Sqrt(stddev);
4865 else stddev = 0;
4866 if (stddev == 0) stddev = binwidx*(hxlast-hxfirst+1)/4;
4867 //if the distribution is really gaussian, the best approximation
4868 //is binwidx*allcha/(sqrtpi*stddev)
4869 //However, in case of non-gaussian tails, this underestimates
4870 //the normalisation constant. In this case the maximum value
4871 //is a better approximation.
4872 //We take the average of both quantities
4874
4875 //In case the mean value is outside the histo limits and
4876 //the StdDev is bigger than the range, we take
4877 // mean = center of bins
4878 // stddev = half range
4879 Double_t xmin = curHist->GetXaxis()->GetXmin();
4880 Double_t xmax = curHist->GetXaxis()->GetXmax();
4881 if ((mean < xmin || mean > xmax) && stddev > (xmax-xmin)) {
4882 mean = 0.5*(xmax+xmin);
4883 stddev = 0.5*(xmax-xmin);
4884 }
4885 TF1 *f1 = (TF1*)hFitter->GetUserFunc();
4887 f1->SetParameter(1,mean);
4889 f1->SetParLimits(2,0,10*stddev);
4890}
4891
4892////////////////////////////////////////////////////////////////////////////////
4893/// Compute Initial values of parameters for an exponential.
4894
4895void H1InitExpo()
4896{
4898 Int_t ifail;
4900 Int_t hxfirst = hFitter->GetXfirst();
4901 Int_t hxlast = hFitter->GetXlast();
4902 Int_t nchanx = hxlast - hxfirst + 1;
4903
4905
4906 TF1 *f1 = (TF1*)hFitter->GetUserFunc();
4908 f1->SetParameter(1,slope);
4909
4910}
4911
4912////////////////////////////////////////////////////////////////////////////////
4913/// Compute Initial values of parameters for a polynom.
4914
4915void H1InitPolynom()
4916{
4917 Double_t fitpar[25];
4918
4920 TF1 *f1 = (TF1*)hFitter->GetUserFunc();
4921 Int_t hxfirst = hFitter->GetXfirst();
4922 Int_t hxlast = hFitter->GetXlast();
4923 Int_t nchanx = hxlast - hxfirst + 1;
4924 Int_t npar = f1->GetNpar();
4925
4926 if (nchanx <=1 || npar == 1) {
4927 TH1 *curHist = (TH1*)hFitter->GetObjectFit();
4928 fitpar[0] = curHist->GetSumOfWeights()/Double_t(nchanx);
4929 } else {
4931 }
4932 for (Int_t i=0;i<npar;i++) f1->SetParameter(i, fitpar[i]);
4933}
4934
4935////////////////////////////////////////////////////////////////////////////////
4936/// Least squares lpolynomial fitting without weights.
4937///
4938/// \param[in] n number of points to fit
4939/// \param[in] m number of parameters
4940/// \param[in] a array of parameters
4941///
4942/// based on CERNLIB routine LSQ: Translated to C++ by Rene Brun
4943/// (E.Keil. revised by B.Schorr, 23.10.1981.)
4944
4946{
4947 const Double_t zero = 0.;
4948 const Double_t one = 1.;
4949 const Int_t idim = 20;
4950
4951 Double_t b[400] /* was [20][20] */;
4952 Int_t i, k, l, ifail;
4954 Double_t da[20], xk, yk;
4955
4956 if (m <= 2) {
4957 H1LeastSquareLinearFit(n, a[0], a[1], ifail);
4958 return;
4959 }
4960 if (m > idim || m > n) return;
4961 b[0] = Double_t(n);
4962 da[0] = zero;
4963 for (l = 2; l <= m; ++l) {
4964 b[l-1] = zero;
4965 b[m + l*20 - 21] = zero;
4966 da[l-1] = zero;
4967 }
4969 TH1 *curHist = (TH1*)hFitter->GetObjectFit();
4970 Int_t hxfirst = hFitter->GetXfirst();
4971 Int_t hxlast = hFitter->GetXlast();
4972 for (k = hxfirst; k <= hxlast; ++k) {
4973 xk = curHist->GetBinCenter(k);
4974 yk = curHist->GetBinContent(k);
4975 power = one;
4976 da[0] += yk;
4977 for (l = 2; l <= m; ++l) {
4978 power *= xk;
4979 b[l-1] += power;
4980 da[l-1] += power*yk;
4981 }
4982 for (l = 2; l <= m; ++l) {
4983 power *= xk;
4984 b[m + l*20 - 21] += power;
4985 }
4986 }
4987 for (i = 3; i <= m; ++i) {
4988 for (k = i; k <= m; ++k) {
4989 b[k - 1 + (i-1)*20 - 21] = b[k + (i-2)*20 - 21];
4990 }
4991 }
4993
4994 for (i=0; i<m; ++i) a[i] = da[i];
4995
4996}
4997
4998////////////////////////////////////////////////////////////////////////////////
4999/// Least square linear fit without weights.
5000///
5001/// extracted from CERNLIB LLSQ: Translated to C++ by Rene Brun
5002/// (added to LSQ by B. Schorr, 15.02.1982.)
5003
5005{
5007 Int_t i, n;
5009 Double_t fn, xk, yk;
5010 Double_t det;
5011
5012 n = TMath::Abs(ndata);
5013 ifail = -2;
5014 xbar = ybar = x2bar = xybar = 0;
5016 TH1 *curHist = (TH1*)hFitter->GetObjectFit();
5017 Int_t hxfirst = hFitter->GetXfirst();
5018 Int_t hxlast = hFitter->GetXlast();
5019 for (i = hxfirst; i <= hxlast; ++i) {
5020 xk = curHist->GetBinCenter(i);
5021 yk = curHist->GetBinContent(i);
5022 if (ndata < 0) {
5023 if (yk <= 0) yk = 1e-9;
5024 yk = TMath::Log(yk);
5025 }
5026 xbar += xk;
5027 ybar += yk;
5028 x2bar += xk*xk;
5029 xybar += xk*yk;
5030 }
5031 fn = Double_t(n);
5032 det = fn*x2bar - xbar*xbar;
5033 ifail = -1;
5034 if (det <= 0) {
5035 a0 = ybar/fn;
5036 a1 = 0;
5037 return;
5038 }
5039 ifail = 0;
5040 a0 = (x2bar*ybar - xbar*xybar) / det;
5041 a1 = (fn*xybar - xbar*ybar) / det;
5042
5043}
5044
5045////////////////////////////////////////////////////////////////////////////////
5046/// Extracted from CERN Program library routine DSEQN.
5047///
5048/// Translated to C++ by Rene Brun
5049
5051{
5053 Int_t nmjp1, i, j, l;
5054 Int_t im1, jp1, nm1, nmi;
5055 Double_t s1, s21, s22;
5056 const Double_t one = 1.;
5057
5058 /* Parameter adjustments */
5059 b_dim1 = idim;
5060 b_offset = b_dim1 + 1;
5061 b -= b_offset;
5062 a_dim1 = idim;
5063 a_offset = a_dim1 + 1;
5064 a -= a_offset;
5065
5066 if (idim < n) return;
5067
5068 ifail = 0;
5069 for (j = 1; j <= n; ++j) {
5070 if (a[j + j*a_dim1] <= 0) { ifail = -1; return; }
5071 a[j + j*a_dim1] = one / a[j + j*a_dim1];
5072 if (j == n) continue;
5073 jp1 = j + 1;
5074 for (l = jp1; l <= n; ++l) {
5075 a[j + l*a_dim1] = a[j + j*a_dim1] * a[l + j*a_dim1];
5076 s1 = -a[l + (j+1)*a_dim1];
5077 for (i = 1; i <= j; ++i) { s1 = a[l + i*a_dim1] * a[i + (j+1)*a_dim1] + s1; }
5078 a[l + (j+1)*a_dim1] = -s1;
5079 }
5080 }
5081 if (k <= 0) return;
5082
5083 for (l = 1; l <= k; ++l) {
5084 b[l*b_dim1 + 1] = a[a_dim1 + 1]*b[l*b_dim1 + 1];
5085 }
5086 if (n == 1) return;
5087 for (l = 1; l <= k; ++l) {
5088 for (i = 2; i <= n; ++i) {
5089 im1 = i - 1;
5090 s21 = -b[i + l*b_dim1];
5091 for (j = 1; j <= im1; ++j) {
5092 s21 = a[i + j*a_dim1]*b[j + l*b_dim1] + s21;
5093 }
5094 b[i + l*b_dim1] = -a[i + i*a_dim1]*s21;
5095 }
5096 nm1 = n - 1;
5097 for (i = 1; i <= nm1; ++i) {
5098 nmi = n - i;
5099 s22 = -b[nmi + l*b_dim1];
5100 for (j = 1; j <= i; ++j) {
5101 nmjp1 = n - j + 1;
5102 s22 = a[nmi + nmjp1*a_dim1]*b[nmjp1 + l*b_dim1] + s22;
5103 }
5104 b[nmi + l*b_dim1] = -s22;
5105 }
5106 }
5107}
5108
5109////////////////////////////////////////////////////////////////////////////////
5110/// Return Global bin number corresponding to binx,y,z.
5111///
5112/// 2-D and 3-D histograms are represented with a one dimensional
5113/// structure.
5114/// This has the advantage that all existing functions, such as
5115/// GetBinContent, GetBinError, GetBinFunction work for all dimensions.
5116///
5117/// In case of a TH1x, returns binx directly.
5118/// see TH1::GetBinXYZ for the inverse transformation.
5119///
5120/// Convention for numbering bins
5121///
5122/// For all histogram types: nbins, xlow, xup
5123///
5124/// - bin = 0; underflow bin
5125/// - bin = 1; first bin with low-edge xlow INCLUDED
5126/// - bin = nbins; last bin with upper-edge xup EXCLUDED
5127/// - bin = nbins+1; overflow bin
5128///
5129/// In case of 2-D or 3-D histograms, a "global bin" number is defined.
5130/// For example, assuming a 3-D histogram with binx,biny,binz, the function
5131///
5132/// ~~~ {.cpp}
5133/// Int_t bin = h->GetBin(binx,biny,binz);
5134/// ~~~
5135///
5136/// returns a global/linearized bin number. This global bin is useful
5137/// to access the bin information independently of the dimension.
5138
5140{
5141 Int_t ofx = fXaxis.GetNbins() + 1; // overflow bin
5142 if (binx < 0) binx = 0;
5143 if (binx > ofx) binx = ofx;
5144
5145 return binx;
5146}
5147
5148////////////////////////////////////////////////////////////////////////////////
5149/// Return binx, biny, binz corresponding to the global bin number globalbin
5150/// see TH1::GetBin function above
5151
5153{
5154 Int_t nx = fXaxis.GetNbins()+2;
5155 Int_t ny = fYaxis.GetNbins()+2;
5156
5157 if (GetDimension() == 1) {
5158 binx = binglobal%nx;
5159 biny = 0;
5160 binz = 0;
5161 return;
5162 }
5163 if (GetDimension() == 2) {
5164 binx = binglobal%nx;
5165 biny = ((binglobal-binx)/nx)%ny;
5166 binz = 0;
5167 return;
5168 }
5169 if (GetDimension() == 3) {
5170 binx = binglobal%nx;
5171 biny = ((binglobal-binx)/nx)%ny;
5172 binz = ((binglobal-binx)/nx -biny)/ny;
5173 }
5174}
5175
5176////////////////////////////////////////////////////////////////////////////////
5177/// Return a random number distributed according the histogram bin contents.
5178/// This function checks if the bins integral exists. If not, the integral
5179/// is evaluated, normalized to one.
5180///
5181/// @param rng (optional) Random number generator pointer used (default is gRandom)
5182/// @param option (optional) Set it to "width" if your non-uniform bin contents represent a density rather than counts
5183///
5184/// The integral is automatically recomputed if the number of entries
5185/// is not the same then when the integral was computed.
5186/// @note Only valid for 1-d histograms. Use GetRandom2 or GetRandom3 otherwise.
5187/// If the histogram has a bin with negative content, a NaN is returned.
5188
5190{
5191 if (fDimension > 1) {
5192 Error("GetRandom","Function only valid for 1-d histograms");
5193 return 0;
5194 }
5196 Double_t integral = 0;
5197 // compute integral checking that all bins have positive content (see ROOT-5894)
5198 if (fIntegral) {
5199 if (fIntegral[nbinsx + 1] != fEntries)
5200 integral = const_cast<TH1 *>(this)->ComputeIntegral(true, option);
5201 else integral = fIntegral[nbinsx];
5202 } else {
5203 integral = const_cast<TH1 *>(this)->ComputeIntegral(true, option);
5204 }
5205 if (integral == 0) return 0;
5206 // return a NaN in case some bins have negative content
5207 if (integral == TMath::QuietNaN() ) return TMath::QuietNaN();
5208
5209 Double_t r1 = (rng) ? rng->Rndm() : gRandom->Rndm();
5212 if (r1 > fIntegral[ibin]) x +=
5214 return x;
5215}
5216
5217////////////////////////////////////////////////////////////////////////////////
5218/// Return content of bin number bin.
5219///
5220/// Implemented in TH1C,S,F,D
5221///
5222/// Convention for numbering bins
5223///
5224/// For all histogram types: nbins, xlow, xup
5225///
5226/// - bin = 0; underflow bin
5227/// - bin = 1; first bin with low-edge xlow INCLUDED
5228/// - bin = nbins; last bin with upper-edge xup EXCLUDED
5229/// - bin = nbins+1; overflow bin
5230///
5231/// In case of 2-D or 3-D histograms, a "global bin" number is defined.
5232/// For example, assuming a 3-D histogram with binx,biny,binz, the function
5233///
5234/// ~~~ {.cpp}
5235/// Int_t bin = h->GetBin(binx,biny,binz);
5236/// ~~~
5237///
5238/// returns a global/linearized bin number. This global bin is useful
5239/// to access the bin information independently of the dimension.
5240
5242{
5243 if (fBuffer) const_cast<TH1*>(this)->BufferEmpty();
5244 if (bin < 0) bin = 0;
5245 if (bin >= fNcells) bin = fNcells-1;
5246
5247 return RetrieveBinContent(bin);
5248}
5249
5250////////////////////////////////////////////////////////////////////////////////
5251/// Compute first binx in the range [firstx,lastx] for which
5252/// diff = abs(bin_content-c) <= maxdiff
5253///
5254/// In case several bins in the specified range with diff=0 are found
5255/// the first bin found is returned in binx.
5256/// In case several bins in the specified range satisfy diff <=maxdiff
5257/// the bin with the smallest difference is returned in binx.
5258/// In all cases the function returns the smallest difference.
5259///
5260/// NOTE1: if firstx <= 0, firstx is set to bin 1
5261/// if (lastx < firstx then firstx is set to the number of bins
5262/// ie if firstx=0 and lastx=0 (default) the search is on all bins.
5263///
5264/// NOTE2: if maxdiff=0 (default), the first bin with content=c is returned.
5265
5267{
5268 if (fDimension > 1) {
5269 binx = 0;
5270 Error("GetBinWithContent","function is only valid for 1-D histograms");
5271 return 0;
5272 }
5273
5274 if (fBuffer) ((TH1*)this)->BufferEmpty();
5275
5276 if (firstx <= 0) firstx = 1;
5277 if (lastx < firstx) lastx = fXaxis.GetNbins();
5278 Int_t binminx = 0;
5279 Double_t diff, curmax = 1.e240;
5280 for (Int_t i=firstx;i<=lastx;i++) {
5282 if (diff <= 0) {binx = i; return diff;}
5283 if (diff < curmax && diff <= maxdiff) {curmax = diff, binminx=i;}
5284 }
5285 binx = binminx;
5286 return curmax;
5287}
5288
5289////////////////////////////////////////////////////////////////////////////////
5290/// Given a point x, approximates the value via linear interpolation
5291/// based on the two nearest bin centers
5292///
5293/// Andy Mastbaum 10/21/08
5294
5296{
5297 if (fBuffer) ((TH1*)this)->BufferEmpty();
5298
5300 Double_t x0,x1,y0,y1;
5301
5302 if(x<=GetBinCenter(1)) {
5303 return RetrieveBinContent(1);
5304 } else if(x>=GetBinCenter(GetNbinsX())) {
5305 return RetrieveBinContent(GetNbinsX());
5306 } else {
5307 if(x<=GetBinCenter(xbin)) {
5309 x0 = GetBinCenter(xbin-1);
5311 x1 = GetBinCenter(xbin);
5312 } else {
5314 x0 = GetBinCenter(xbin);
5316 x1 = GetBinCenter(xbin+1);
5317 }
5318 return y0 + (x-x0)*((y1-y0)/(x1-x0));
5319 }
5320}
5321
5322////////////////////////////////////////////////////////////////////////////////
5323/// 2d Interpolation. Not yet implemented.
5324
5326{
5327 Error("Interpolate","This function must be called with 1 argument for a TH1");
5328 return 0;
5329}
5330
5331////////////////////////////////////////////////////////////////////////////////
5332/// 3d Interpolation. Not yet implemented.
5333
5335{
5336 Error("Interpolate","This function must be called with 1 argument for a TH1");
5337 return 0;
5338}
5339
5340///////////////////////////////////////////////////////////////////////////////
5341/// Check if a histogram is empty
5342/// (this is a protected method used mainly by TH1Merger )
5343
5344Bool_t TH1::IsEmpty() const
5345{
5346 // if fTsumw or fentries are not zero histogram is not empty
5347 // need to use GetEntries() instead of fEntries in case of bugger histograms
5348 // so we will flash the buffer
5349 if (fTsumw != 0) return kFALSE;
5350 if (GetEntries() != 0) return kFALSE;
5351 // case fTSumw == 0 amd entries are also zero
5352 // this should not really happening, but if one sets content by hand
5353 // it can happen. a call to ResetStats() should be done in such cases
5354 double sumw = 0;
5355 for (int i = 0; i< GetNcells(); ++i) sumw += RetrieveBinContent(i);
5356 return (sumw != 0) ? kFALSE : kTRUE;
5357}
5358
5359////////////////////////////////////////////////////////////////////////////////
5360/// Return true if the bin is overflow.
5361
5363{
5364 Int_t binx, biny, binz;
5366
5367 if (iaxis == 0) {
5368 if ( fDimension == 1 )
5369 return binx >= GetNbinsX() + 1;
5370 if ( fDimension == 2 )
5371 return (binx >= GetNbinsX() + 1) ||
5372 (biny >= GetNbinsY() + 1);
5373 if ( fDimension == 3 )
5374 return (binx >= GetNbinsX() + 1) ||
5375 (biny >= GetNbinsY() + 1) ||
5376 (binz >= GetNbinsZ() + 1);
5377 return kFALSE;
5378 }
5379 if (iaxis == 1)
5380 return binx >= GetNbinsX() + 1;
5381 if (iaxis == 2)
5382 return biny >= GetNbinsY() + 1;
5383 if (iaxis == 3)
5384 return binz >= GetNbinsZ() + 1;
5385
5386 Error("IsBinOverflow","Invalid axis value");
5387 return kFALSE;
5388}
5389
5390////////////////////////////////////////////////////////////////////////////////
5391/// Return true if the bin is underflow.
5392/// If iaxis = 0 make OR with all axes otherwise check only for the given axis
5393
5395{
5396 Int_t binx, biny, binz;
5398
5399 if (iaxis == 0) {
5400 if ( fDimension == 1 )
5401 return (binx <= 0);
5402 else if ( fDimension == 2 )
5403 return (binx <= 0 || biny <= 0);
5404 else if ( fDimension == 3 )
5405 return (binx <= 0 || biny <= 0 || binz <= 0);
5406 else
5407 return kFALSE;
5408 }
5409 if (iaxis == 1)
5410 return (binx <= 0);
5411 if (iaxis == 2)
5412 return (biny <= 0);
5413 if (iaxis == 3)
5414 return (binz <= 0);
5415
5416 Error("IsBinUnderflow","Invalid axis value");
5417 return kFALSE;
5418}
5419
5420////////////////////////////////////////////////////////////////////////////////
5421/// Reduce the number of bins for the axis passed in the option to the number of bins having a label.
5422/// The method will remove only the extra bins existing after the last "labeled" bin.
5423/// Note that if there are "un-labeled" bins present between "labeled" bins they will not be removed
5424
5426{
5428 TAxis *axis = nullptr;
5429 if (iaxis == 1) axis = GetXaxis();
5430 if (iaxis == 2) axis = GetYaxis();
5431 if (iaxis == 3) axis = GetZaxis();
5432 if (!axis) {
5433 Error("LabelsDeflate","Invalid axis option %s",ax);
5434 return;
5435 }
5436 if (!axis->GetLabels()) return;
5437
5438 // find bin with last labels
5439 // bin number is object ID in list of labels
5440 // therefore max bin number is number of bins of the deflated histograms
5441 TIter next(axis->GetLabels());
5442 TObject *obj;
5443 Int_t nbins = 0;
5444 while ((obj = next())) {
5445 Int_t ibin = obj->GetUniqueID();
5446 if (ibin > nbins) nbins = ibin;
5447 }
5448 if (nbins < 1) nbins = 1;
5449
5450 // Do nothing in case it was the last bin
5451 if (nbins==axis->GetNbins()) return;
5452
5453 TH1 *hold = (TH1*)IsA()->New();
5454 R__ASSERT(hold);
5455 hold->SetDirectory(nullptr);
5456 Copy(*hold);
5457
5458 Bool_t timedisp = axis->GetTimeDisplay();
5459 Double_t xmin = axis->GetXmin();
5461 if (xmax <= xmin) xmax = xmin +nbins;
5462 axis->SetRange(0,0);
5463 axis->Set(nbins,xmin,xmax);
5464 SetBinsLength(-1); // reset the number of cells
5466 if (errors) fSumw2.Set(fNcells);
5467 axis->SetTimeDisplay(timedisp);
5468 // reset histogram content
5469 Reset("ICE");
5470
5471 //now loop on all bins and refill
5472 // NOTE that if the bins without labels have content
5473 // it will be put in the underflow/overflow.
5474 // For this reason we use AddBinContent method
5477 for (bin=0; bin < hold->fNcells; ++bin) {
5478 hold->GetBinXYZ(bin,binx,biny,binz);
5480 Double_t cu = hold->RetrieveBinContent(bin);
5482 if (errors) {
5483 fSumw2.fArray[ibin] += hold->fSumw2.fArray[bin];
5484 }
5485 }
5487 delete hold;
5488}
5489
5490////////////////////////////////////////////////////////////////////////////////
5491/// Double the number of bins for axis.
5492/// Refill histogram.
5493/// This function is called by TAxis::FindBin(const char *label)
5494
5496{
5498 TAxis *axis = nullptr;
5499 if (iaxis == 1) axis = GetXaxis();
5500 if (iaxis == 2) axis = GetYaxis();
5501 if (iaxis == 3) axis = GetZaxis();
5502 if (!axis) return;
5503
5504 TH1 *hold = (TH1*)IsA()->New();
5505 hold->SetDirectory(nullptr);
5506 Copy(*hold);
5507 hold->ResetBit(kMustCleanup);
5508
5509 Bool_t timedisp = axis->GetTimeDisplay();
5510 Int_t nbins = axis->GetNbins();
5511 Double_t xmin = axis->GetXmin();
5512 Double_t xmax = axis->GetXmax();
5513 xmax = xmin + 2*(xmax-xmin);
5514 axis->SetRange(0,0);
5515 // double the bins and recompute ncells
5516 axis->Set(2*nbins,xmin,xmax);
5517 SetBinsLength(-1);
5519 if (errors) fSumw2.Set(fNcells);
5520 axis->SetTimeDisplay(timedisp);
5521
5522 Reset("ICE"); // reset content and error
5523
5524 //now loop on all bins and refill
5527 for (ibin =0; ibin < hold->fNcells; ibin++) {
5528 // get the binx,y,z values . The x-y-z (axis) bin values will stay the same between new-old after the expanding
5529 hold->GetBinXYZ(ibin,binx,biny,binz);
5530 bin = GetBin(binx,biny,binz);
5531
5532 // underflow and overflow will be cleaned up because their meaning has been altered
5533 if (hold->IsBinUnderflow(ibin,iaxis) || hold->IsBinOverflow(ibin,iaxis)) {
5534 continue;
5535 }
5536 else {
5537 AddBinContent(bin, hold->RetrieveBinContent(ibin));
5538 if (errors) fSumw2.fArray[bin] += hold->fSumw2.fArray[ibin];
5539 }
5540 }
5542 delete hold;
5543}
5544
5545////////////////////////////////////////////////////////////////////////////////
5546/// Sort bins with labels or set option(s) to draw axis with labels
5547/// \param[in] option
5548/// - "a" sort by alphabetic order
5549/// - ">" sort by decreasing values
5550/// - "<" sort by increasing values
5551/// - "h" draw labels horizontal
5552/// - "v" draw labels vertical
5553/// - "u" draw labels up (end of label right adjusted)
5554/// - "d" draw labels down (start of label left adjusted)
5555///
5556/// In case not all bins have labels sorting will work only in the case
5557/// the first `n` consecutive bins have all labels and sorting will be performed on
5558/// those label bins.
5559///
5560/// \param[in] ax axis
5561
5563{
5565 TAxis *axis = nullptr;
5566 if (iaxis == 1)
5567 axis = GetXaxis();
5568 if (iaxis == 2)
5569 axis = GetYaxis();
5570 if (iaxis == 3)
5571 axis = GetZaxis();
5572 if (!axis)
5573 return;
5574 THashList *labels = axis->GetLabels();
5575 if (!labels) {
5576 Warning("LabelsOption", "Axis %s has no labels!",axis->GetName());
5577 return;
5578 }
5579 TString opt = option;
5580 opt.ToLower();
5581 Int_t iopt = -1;
5582 if (opt.Contains("h")) {
5587 iopt = 0;
5588 }
5589 if (opt.Contains("v")) {
5594 iopt = 1;
5595 }
5596 if (opt.Contains("u")) {
5597 axis->SetBit(TAxis::kLabelsUp);
5601 iopt = 2;
5602 }
5603 if (opt.Contains("d")) {
5608 iopt = 3;
5609 }
5610 Int_t sort = -1;
5611 if (opt.Contains("a"))
5612 sort = 0;
5613 if (opt.Contains(">"))
5614 sort = 1;
5615 if (opt.Contains("<"))
5616 sort = 2;
5617 if (sort < 0) {
5618 if (iopt < 0)
5619 Error("LabelsOption", "%s is an invalid label placement option!",opt.Data());
5620 return;
5621 }
5622
5623 // Code works only if first n bins have labels if we uncomment following line
5624 // but we don't want to support this special case
5625 // Int_t n = TMath::Min(axis->GetNbins(), labels->GetSize());
5626
5627 // support only cases where each bin has a labels (should be when axis is alphanumeric)
5628 Int_t n = labels->GetSize();
5629 if (n != axis->GetNbins()) {
5630 // check if labels are all consecutive and starts from the first bin
5631 // in that case the current code will work fine
5632 Int_t firstLabelBin = axis->GetNbins()+1;
5633 Int_t lastLabelBin = -1;
5634 for (Int_t i = 0; i < n; ++i) {
5635 Int_t bin = labels->At(i)->GetUniqueID();
5638 }
5639 if (firstLabelBin != 1 || lastLabelBin-firstLabelBin +1 != n) {
5640 Error("LabelsOption", "%s of Histogram %s contains bins without labels. Sorting will not work correctly - return",
5641 axis->GetName(), GetName());
5642 return;
5643 }
5644 // case where label bins are consecutive starting from first bin will work
5645 // calling before a TH1::LabelsDeflate() will avoid this error message
5646 Warning("LabelsOption", "axis %s of Histogram %s has extra following bins without labels. Sorting will work only for first label bins",
5647 axis->GetName(), GetName());
5648 }
5649 std::vector<Int_t> a(n);
5650 std::vector<Int_t> b(n);
5651
5652
5653 Int_t i, j, k;
5654 std::vector<Double_t> cont;
5655 std::vector<Double_t> errors2;
5656 THashList *labold = new THashList(labels->GetSize(), 1);
5657 TIter nextold(labels);
5658 TObject *obj = nullptr;
5659 labold->AddAll(labels);
5660 labels->Clear();
5661
5662 // delete buffer if it is there since bins will be reordered.
5663 if (fBuffer)
5664 BufferEmpty(1);
5665
5666 if (sort > 0) {
5667 //---sort by values of bins
5668 if (GetDimension() == 1) {
5669 cont.resize(n);
5670 if (fSumw2.fN)
5671 errors2.resize(n);
5672 for (i = 0; i < n; i++) {
5673 cont[i] = RetrieveBinContent(i + 1);
5674 if (!errors2.empty())
5675 errors2[i] = GetBinErrorSqUnchecked(i + 1);
5676 b[i] = labold->At(i)->GetUniqueID(); // this is the bin corresponding to the label
5677 a[i] = i;
5678 }
5679 if (sort == 1)
5680 TMath::Sort(n, cont.data(), a.data(), kTRUE); // sort by decreasing values
5681 else
5682 TMath::Sort(n, cont.data(), a.data(), kFALSE); // sort by increasing values
5683 for (i = 0; i < n; i++) {
5684 // use UpdateBinCOntent to not screw up histogram entries
5685 UpdateBinContent(i + 1, cont[b[a[i]] - 1]); // b[a[i]] returns bin number. .we need to subtract 1
5686 if (gDebug)
5687 Info("LabelsOption","setting bin %d value %f from bin %d label %s at pos %d ",
5688 i+1,cont[b[a[i]] - 1],b[a[i]],labold->At(a[i])->GetName(),a[i]);
5689 if (!errors2.empty())
5690 fSumw2.fArray[i + 1] = errors2[b[a[i]] - 1];
5691 }
5692 for (i = 0; i < n; i++) {
5693 obj = labold->At(a[i]);
5694 labels->Add(obj);
5695 obj->SetUniqueID(i + 1);
5696 }
5697 } else if (GetDimension() == 2) {
5698 std::vector<Double_t> pcont(n + 2);
5699 Int_t nx = fXaxis.GetNbins() + 2;
5700 Int_t ny = fYaxis.GetNbins() + 2;
5701 cont.resize((nx + 2) * (ny + 2));
5702 if (fSumw2.fN)
5703 errors2.resize((nx + 2) * (ny + 2));
5704 for (i = 0; i < nx; i++) {
5705 for (j = 0; j < ny; j++) {
5706 Int_t bin = GetBin(i,j);
5707 cont[i + nx * j] = RetrieveBinContent(bin);
5708 if (!errors2.empty())
5710 if (axis == GetXaxis())
5711 k = i - 1;
5712 else
5713 k = j - 1;
5714 if (k >= 0 && k < n) { // we consider underflow/overflows in y for ordering the bins
5715 pcont[k] += cont[i + nx * j];
5716 a[k] = k;
5717 }
5718 }
5719 }
5720 if (sort == 1)
5721 TMath::Sort(n, pcont.data(), a.data(), kTRUE); // sort by decreasing values
5722 else
5723 TMath::Sort(n, pcont.data(), a.data(), kFALSE); // sort by increasing values
5724 for (i = 0; i < n; i++) {
5725 // iterate on old label list to find corresponding bin match
5726 TIter next(labold);
5727 UInt_t bin = a[i] + 1;
5728 while ((obj = next())) {
5729 if (obj->GetUniqueID() == (UInt_t)bin)
5730 break;
5731 else
5732 obj = nullptr;
5733 }
5734 if (!obj) {
5735 // this should not really happen
5736 R__ASSERT("LabelsOption - No corresponding bin found when ordering labels");
5737 return;
5738 }
5739
5740 labels->Add(obj);
5741 if (gDebug)
5742 std::cout << " set label " << obj->GetName() << " to bin " << i + 1 << " from order " << a[i] << " bin "
5743 << b[a[i]] << "content " << pcont[a[i]] << std::endl;
5744 }
5745 // need to set here new ordered labels - otherwise loop before does not work since labold and labels list
5746 // contain same objects
5747 for (i = 0; i < n; i++) {
5748 labels->At(i)->SetUniqueID(i + 1);
5749 }
5750 // set now the bin contents
5751 if (axis == GetXaxis()) {
5752 for (i = 0; i < n; i++) {
5753 Int_t ix = a[i] + 1;
5754 for (j = 0; j < ny; j++) {
5755 Int_t bin = GetBin(i + 1, j);
5756 UpdateBinContent(bin, cont[ix + nx * j]);
5757 if (!errors2.empty())
5758 fSumw2.fArray[bin] = errors2[ix + nx * j];
5759 }
5760 }
5761 } else {
5762 // using y axis
5763 for (i = 0; i < nx; i++) {
5764 for (j = 0; j < n; j++) {
5765 Int_t iy = a[j] + 1;
5766 Int_t bin = GetBin(i, j + 1);
5767 UpdateBinContent(bin, cont[i + nx * iy]);
5768 if (!errors2.empty())
5769 fSumw2.fArray[bin] = errors2[i + nx * iy];
5770 }
5771 }
5772 }
5773 } else {
5774 // sorting histograms: 3D case
5775 std::vector<Double_t> pcont(n + 2);
5776 Int_t nx = fXaxis.GetNbins() + 2;
5777 Int_t ny = fYaxis.GetNbins() + 2;
5778 Int_t nz = fZaxis.GetNbins() + 2;
5779 Int_t l = 0;
5780 cont.resize((nx + 2) * (ny + 2) * (nz + 2));
5781 if (fSumw2.fN)
5782 errors2.resize((nx + 2) * (ny + 2) * (nz + 2));
5783 for (i = 0; i < nx; i++) {
5784 for (j = 0; j < ny; j++) {
5785 for (k = 0; k < nz; k++) {
5786 Int_t bin = GetBin(i,j,k);
5788 if (axis == GetXaxis())
5789 l = i - 1;
5790 else if (axis == GetYaxis())
5791 l = j - 1;
5792 else
5793 l = k - 1;
5794 if (l >= 0 && l < n) { // we consider underflow/overflows in y for ordering the bins
5795 pcont[l] += c;
5796 a[l] = l;
5797 }
5798 cont[i + nx * (j + ny * k)] = c;
5799 if (!errors2.empty())
5800 errors2[i + nx * (j + ny * k)] = GetBinErrorSqUnchecked(bin);
5801 }
5802 }
5803 }
5804 if (sort == 1)
5805 TMath::Sort(n, pcont.data(), a.data(), kTRUE); // sort by decreasing values
5806 else
5807 TMath::Sort(n, pcont.data(), a.data(), kFALSE); // sort by increasing values
5808 for (i = 0; i < n; i++) {
5809 // iterate on the old label list to find corresponding bin match
5810 TIter next(labold);
5811 UInt_t bin = a[i] + 1;
5812 obj = nullptr;
5813 while ((obj = next())) {
5814 if (obj->GetUniqueID() == (UInt_t)bin) {
5815 break;
5816 }
5817 else
5818 obj = nullptr;
5819 }
5820 if (!obj) {
5821 R__ASSERT("LabelsOption - No corresponding bin found when ordering labels");
5822 return;
5823 }
5824 labels->Add(obj);
5825 if (gDebug)
5826 std::cout << " set label " << obj->GetName() << " to bin " << i + 1 << " from bin " << a[i] << "content "
5827 << pcont[a[i]] << std::endl;
5828 }
5829
5830 // need to set here new ordered labels - otherwise loop before does not work since labold and llabels list
5831 // contain same objects
5832 for (i = 0; i < n; i++) {
5833 labels->At(i)->SetUniqueID(i + 1);
5834 }
5835 // set now the bin contents
5836 if (axis == GetXaxis()) {
5837 for (i = 0; i < n; i++) {
5838 Int_t ix = a[i] + 1;
5839 for (j = 0; j < ny; j++) {
5840 for (k = 0; k < nz; k++) {
5841 Int_t bin = GetBin(i + 1, j, k);
5842 UpdateBinContent(bin, cont[ix + nx * (j + ny * k)]);
5843 if (!errors2.empty())
5844 fSumw2.fArray[bin] = errors2[ix + nx * (j + ny * k)];
5845 }
5846 }
5847 }
5848 } else if (axis == GetYaxis()) {
5849 // using y axis
5850 for (i = 0; i < nx; i++) {
5851 for (j = 0; j < n; j++) {
5852 Int_t iy = a[j] + 1;
5853 for (k = 0; k < nz; k++) {
5854 Int_t bin = GetBin(i, j + 1, k);
5855 UpdateBinContent(bin, cont[i + nx * (iy + ny * k)]);
5856 if (!errors2.empty())
5857 fSumw2.fArray[bin] = errors2[i + nx * (iy + ny * k)];
5858 }
5859 }
5860 }
5861 } else {
5862 // using z axis
5863 for (i = 0; i < nx; i++) {
5864 for (j = 0; j < ny; j++) {
5865 for (k = 0; k < n; k++) {
5866 Int_t iz = a[k] + 1;
5867 Int_t bin = GetBin(i, j , k +1);
5868 UpdateBinContent(bin, cont[i + nx * (j + ny * iz)]);
5869 if (!errors2.empty())
5870 fSumw2.fArray[bin] = errors2[i + nx * (j + ny * iz)];
5871 }
5872 }
5873 }
5874 }
5875 }
5876 } else {
5877 //---alphabetic sort
5878 // sort labels using vector of strings and TMath::Sort
5879 // I need to array because labels order in list is not necessary that of the bins
5880 std::vector<std::string> vecLabels(n);
5881 for (i = 0; i < n; i++) {
5882 vecLabels[i] = labold->At(i)->GetName();
5883 b[i] = labold->At(i)->GetUniqueID(); // this is the bin corresponding to the label
5884 a[i] = i;
5885 }
5886 // sort in ascending order for strings
5887 TMath::Sort(n, vecLabels.data(), a.data(), kFALSE);
5888 // set the new labels
5889 for (i = 0; i < n; i++) {
5890 TObject *labelObj = labold->At(a[i]);
5891 labels->Add(labold->At(a[i]));
5892 // set the corresponding bin. NB bin starts from 1
5893 labelObj->SetUniqueID(i + 1);
5894 if (gDebug)
5895 std::cout << "bin " << i + 1 << " setting new labels for axis " << labold->At(a[i])->GetName() << " from "
5896 << b[a[i]] << std::endl;
5897 }
5898
5899 if (GetDimension() == 1) {
5900 cont.resize(n + 2);
5901 if (fSumw2.fN)
5902 errors2.resize(n + 2);
5903 for (i = 0; i < n; i++) {
5904 cont[i] = RetrieveBinContent(b[a[i]]);
5905 if (!errors2.empty())
5907 }
5908 for (i = 0; i < n; i++) {
5909 UpdateBinContent(i + 1, cont[i]);
5910 if (!errors2.empty())
5911 fSumw2.fArray[i+1] = errors2[i];
5912 }
5913 } else if (GetDimension() == 2) {
5914 Int_t nx = fXaxis.GetNbins() + 2;
5915 Int_t ny = fYaxis.GetNbins() + 2;
5916 cont.resize(nx * ny);
5917 if (fSumw2.fN)
5918 errors2.resize(nx * ny);
5919 // copy old bin contents and then set to new ordered bins
5920 // N.B. bin in histograms starts from 1, but in y we consider under/overflows
5921 for (i = 0; i < nx; i++) {
5922 for (j = 0; j < ny; j++) { // ny is nbins+2
5923 Int_t bin = GetBin(i, j);
5924 cont[i + nx * j] = RetrieveBinContent(bin);
5925 if (!errors2.empty())
5927 }
5928 }
5929 if (axis == GetXaxis()) {
5930 for (i = 0; i < n; i++) {
5931 for (j = 0; j < ny; j++) {
5932 Int_t bin = GetBin(i + 1 , j);
5933 UpdateBinContent(bin, cont[b[a[i]] + nx * j]);
5934 if (!errors2.empty())
5935 fSumw2.fArray[bin] = errors2[b[a[i]] + nx * j];
5936 }
5937 }
5938 } else {
5939 for (i = 0; i < nx; i++) {
5940 for (j = 0; j < n; j++) {
5941 Int_t bin = GetBin(i, j + 1);
5942 UpdateBinContent(bin, cont[i + nx * b[a[j]]]);
5943 if (!errors2.empty())
5944 fSumw2.fArray[bin] = errors2[i + nx * b[a[j]]];
5945 }
5946 }
5947 }
5948 } else {
5949 // case of 3D (needs to be tested)
5950 Int_t nx = fXaxis.GetNbins() + 2;
5951 Int_t ny = fYaxis.GetNbins() + 2;
5952 Int_t nz = fZaxis.GetNbins() + 2;
5953 cont.resize(nx * ny * nz);
5954 if (fSumw2.fN)
5955 errors2.resize(nx * ny * nz);
5956 for (i = 0; i < nx; i++) {
5957 for (j = 0; j < ny; j++) {
5958 for (k = 0; k < nz; k++) {
5959 Int_t bin = GetBin(i, j, k);
5960 cont[i + nx * (j + ny * k)] = RetrieveBinContent(bin);
5961 if (!errors2.empty())
5962 errors2[i + nx * (j + ny * k)] = GetBinErrorSqUnchecked(bin);
5963 }
5964 }
5965 }
5966 if (axis == GetXaxis()) {
5967 // labels on x axis
5968 for (i = 0; i < n; i++) { // for x we loop only on bins with the labels
5969 for (j = 0; j < ny; j++) {
5970 for (k = 0; k < nz; k++) {
5971 Int_t bin = GetBin(i + 1, j, k);
5972 UpdateBinContent(bin, cont[b[a[i]] + nx * (j + ny * k)]);
5973 if (!errors2.empty())
5974 fSumw2.fArray[bin] = errors2[b[a[i]] + nx * (j + ny * k)];
5975 }
5976 }
5977 }
5978 } else if (axis == GetYaxis()) {
5979 // labels on y axis
5980 for (i = 0; i < nx; i++) {
5981 for (j = 0; j < n; j++) {
5982 for (k = 0; k < nz; k++) {
5983 Int_t bin = GetBin(i, j+1, k);
5984 UpdateBinContent(bin, cont[i + nx * (b[a[j]] + ny * k)]);
5985 if (!errors2.empty())
5986 fSumw2.fArray[bin] = errors2[i + nx * (b[a[j]] + ny * k)];
5987 }
5988 }
5989 }
5990 } else {
5991 // labels on z axis
5992 for (i = 0; i < nx; i++) {
5993 for (j = 0; j < ny; j++) {
5994 for (k = 0; k < n; k++) {
5995 Int_t bin = GetBin(i, j, k+1);
5996 UpdateBinContent(bin, cont[i + nx * (j + ny * b[a[k]])]);
5997 if (!errors2.empty())
5998 fSumw2.fArray[bin] = errors2[i + nx * (j + ny * b[a[k]])];
5999 }
6000 }
6001 }
6002 }
6003 }
6004 }
6005 // need to set to zero the statistics if axis has been sorted
6006 // see for example TH3::PutStats for definition of s vector
6007 bool labelsAreSorted = kFALSE;
6008 for (i = 0; i < n; ++i) {
6009 if (a[i] != i) {
6011 break;
6012 }
6013 }
6014 if (labelsAreSorted) {
6015 double s[TH1::kNstat];
6016 GetStats(s);
6017 if (iaxis == 1) {
6018 s[2] = 0; // fTsumwx
6019 s[3] = 0; // fTsumwx2
6020 s[6] = 0; // fTsumwxy
6021 s[9] = 0; // fTsumwxz
6022 } else if (iaxis == 2) {
6023 s[4] = 0; // fTsumwy
6024 s[5] = 0; // fTsumwy2
6025 s[6] = 0; // fTsumwxy
6026 s[10] = 0; // fTsumwyz
6027 } else if (iaxis == 3) {
6028 s[7] = 0; // fTsumwz
6029 s[8] = 0; // fTsumwz2
6030 s[9] = 0; // fTsumwxz
6031 s[10] = 0; // fTsumwyz
6032 }
6033 PutStats(s);
6034 }
6035 delete labold;
6036}
6037
6038////////////////////////////////////////////////////////////////////////////////
6039/// Test if two double are almost equal.
6040
6041static inline Bool_t AlmostEqual(Double_t a, Double_t b, Double_t epsilon = 0.00000001)
6042{
6043 return TMath::Abs(a - b) < epsilon;
6044}
6045
6046////////////////////////////////////////////////////////////////////////////////
6047/// Test if a double is almost an integer.
6048
6049static inline Bool_t AlmostInteger(Double_t a, Double_t epsilon = 0.00000001)
6050{
6051 return AlmostEqual(a - TMath::Floor(a), 0, epsilon) ||
6052 AlmostEqual(a - TMath::Floor(a), 1, epsilon);
6053}
6054
6055////////////////////////////////////////////////////////////////////////////////
6056/// Test if the binning is equidistant.
6057
6058static inline bool IsEquidistantBinning(const TAxis& axis)
6059{
6060 // check if axis bin are equals
6061 if (!axis.GetXbins()->fN) return true; //
6062 // not able to check if there is only one axis entry
6063 bool isEquidistant = true;
6064 const Double_t firstBinWidth = axis.GetBinWidth(1);
6065 for (int i = 1; i < axis.GetNbins(); ++i) {
6066 const Double_t binWidth = axis.GetBinWidth(i);
6067 const bool match = TMath::AreEqualRel(firstBinWidth, binWidth, 1.E-10);
6068 isEquidistant &= match;
6069 if (!match)
6070 break;
6071 }
6072 return isEquidistant;
6073}
6074
6075////////////////////////////////////////////////////////////////////////////////
6076/// Same limits and bins.
6077
6079 return axis1.GetNbins() == axis2.GetNbins() &&
6080 TMath::AreEqualAbs(axis1.GetXmin(), axis2.GetXmin(), axis1.GetBinWidth(axis1.GetNbins()) * 1.E-10) &&
6081 TMath::AreEqualAbs(axis1.GetXmax(), axis2.GetXmax(), axis1.GetBinWidth(axis1.GetNbins()) * 1.E-10);
6082}
6083
6084////////////////////////////////////////////////////////////////////////////////
6085/// Finds new limits for the axis for the Merge function.
6086/// returns false if the limits are incompatible
6087
6089{
6091 return kTRUE;
6092
6094 return kFALSE; // not equidistant user binning not supported
6095
6096 Double_t width1 = destAxis.GetBinWidth(0);
6097 Double_t width2 = anAxis.GetBinWidth(0);
6098 if (width1 == 0 || width2 == 0)
6099 return kFALSE; // no binning not supported
6100
6101 Double_t xmin = TMath::Min(destAxis.GetXmin(), anAxis.GetXmin());
6102 Double_t xmax = TMath::Max(destAxis.GetXmax(), anAxis.GetXmax());
6104
6105 // check the bin size
6107 return kFALSE;
6108
6109 // std::cout << "Find new limit using given axis " << anAxis.GetXmin() << " , " << anAxis.GetXmax() << " bin width " << width2 << std::endl;
6110 // std::cout << " and destination axis " << destAxis.GetXmin() << " , " << destAxis.GetXmax() << " bin width " << width1 << std::endl;
6111
6112
6113 // check the limits
6114 Double_t delta;
6115 delta = (destAxis.GetXmin() - xmin)/width1;
6116 if (!AlmostInteger(delta))
6117 xmin -= (TMath::Ceil(delta) - delta)*width1;
6118
6119 delta = (anAxis.GetXmin() - xmin)/width2;
6120 if (!AlmostInteger(delta))
6121 xmin -= (TMath::Ceil(delta) - delta)*width2;
6122
6123
6124 delta = (destAxis.GetXmin() - xmin)/width1;
6125 if (!AlmostInteger(delta))
6126 return kFALSE;
6127
6128
6129 delta = (xmax - destAxis.GetXmax())/width1;
6130 if (!AlmostInteger(delta))
6131 xmax += (TMath::Ceil(delta) - delta)*width1;
6132
6133
6134 delta = (xmax - anAxis.GetXmax())/width2;
6135 if (!AlmostInteger(delta))
6136 xmax += (TMath::Ceil(delta) - delta)*width2;
6137
6138
6139 delta = (xmax - destAxis.GetXmax())/width1;
6140 if (!AlmostInteger(delta))
6141 return kFALSE;
6142#ifdef DEBUG
6143 if (!AlmostInteger((xmax - xmin) / width)) { // unnecessary check
6144 printf("TH1::RecomputeAxisLimits - Impossible\n");
6145 return kFALSE;
6146 }
6147#endif
6148
6149
6151
6152 //std::cout << "New re-computed axis : [ " << xmin << " , " << xmax << " ] width = " << width << " nbins " << destAxis.GetNbins() << std::endl;
6153
6154 return kTRUE;
6155}
6156
6157////////////////////////////////////////////////////////////////////////////////
6158/// Add all histograms in the collection to this histogram.
6159/// This function computes the min/max for the x axis,
6160/// compute a new number of bins, if necessary,
6161/// add bin contents, errors and statistics.
6162/// If all histograms have bin labels, bins with identical labels
6163/// will be merged, no matter what their order is.
6164/// If overflows are present and limits are different the function will fail.
6165/// The function returns the total number of entries in the result histogram
6166/// if the merge is successful, -1 otherwise.
6167///
6168/// Possible option:
6169/// -NOL : the merger will ignore the labels and merge the histograms bin by bin using bin center values to match bins
6170/// -NOCHECK: the histogram will not perform a check for duplicate labels in case of axes with labels. The check
6171/// (enabled by default) slows down the merging
6172///
6173/// IMPORTANT remark. The axis x may have different number
6174/// of bins and different limits, BUT the largest bin width must be
6175/// a multiple of the smallest bin width and the upper limit must also
6176/// be a multiple of the bin width.
6177/// Example:
6178///
6179/// ~~~ {.cpp}
6180/// void atest() {
6181/// TH1F *h1 = new TH1F("h1","h1",110,-110,0);
6182/// TH1F *h2 = new TH1F("h2","h2",220,0,110);
6183/// TH1F *h3 = new TH1F("h3","h3",330,-55,55);
6184/// TRandom r;
6185/// for (Int_t i=0;i<10000;i++) {
6186/// h1->Fill(r.Gaus(-55,10));
6187/// h2->Fill(r.Gaus(55,10));
6188/// h3->Fill(r.Gaus(0,10));
6189/// }
6190///
6191/// TList *list = new TList;
6192/// list->Add(h1);
6193/// list->Add(h2);
6194/// list->Add(h3);
6195/// TH1F *h = (TH1F*)h1->Clone("h");
6196/// h->Reset();
6197/// h->Merge(list);
6198/// h->Draw();
6199/// }
6200/// ~~~
6201
6203{
6204 if (!li) return 0;
6205 if (li->IsEmpty()) return (Long64_t) GetEntries();
6206
6207 // use TH1Merger class
6208 TH1Merger merger(*this,*li,opt);
6209 Bool_t ret = merger();
6210
6211 return (ret) ? GetEntries() : -1;
6212}
6213
6214
6215////////////////////////////////////////////////////////////////////////////////
6216/// Performs the operation:
6217///
6218/// `this = this*c1*f1`
6219///
6220/// If errors are defined (see TH1::Sumw2), errors are also recalculated.
6221///
6222/// Only bins inside the function range are recomputed.
6223/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
6224/// you should call Sumw2 before making this operation.
6225/// This is particularly important if you fit the histogram after TH1::Multiply
6226///
6227/// The function return kFALSE if the Multiply operation failed
6228
6230{
6231 if (!f1) {
6232 Error("Multiply","Attempt to multiply by a non-existing function");
6233 return kFALSE;
6234 }
6235
6236 // delete buffer if it is there since it will become invalid
6237 if (fBuffer) BufferEmpty(1);
6238
6239 Int_t nx = GetNbinsX() + 2; // normal bins + uf / of (cells)
6240 Int_t ny = GetNbinsY() + 2;
6241 Int_t nz = GetNbinsZ() + 2;
6242 if (fDimension < 2) ny = 1;
6243 if (fDimension < 3) nz = 1;
6244
6245 // reset min-maximum
6246 SetMinimum();
6247 SetMaximum();
6248
6249 // - Loop on bins (including underflows/overflows)
6250 Double_t xx[3];
6251 Double_t *params = nullptr;
6252 f1->InitArgs(xx,params);
6253
6254 for (Int_t binz = 0; binz < nz; ++binz) {
6255 xx[2] = fZaxis.GetBinCenter(binz);
6256 for (Int_t biny = 0; biny < ny; ++biny) {
6257 xx[1] = fYaxis.GetBinCenter(biny);
6258 for (Int_t binx = 0; binx < nx; ++binx) {
6259 xx[0] = fXaxis.GetBinCenter(binx);
6260 if (!f1->IsInside(xx)) continue;
6262 Int_t bin = binx + nx * (biny + ny *binz);
6263 Double_t cu = c1*f1->EvalPar(xx);
6264 if (TF1::RejectedPoint()) continue;
6266 if (fSumw2.fN) {
6268 }
6269 }
6270 }
6271 }
6272 ResetStats();
6273 return kTRUE;
6274}
6275
6276////////////////////////////////////////////////////////////////////////////////
6277/// Multiply this histogram by h1.
6278///
6279/// `this = this*h1`
6280///
6281/// If errors of this are available (TH1::Sumw2), errors are recalculated.
6282/// Note that if h1 has Sumw2 set, Sumw2 is automatically called for this
6283/// if not already set.
6284///
6285/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
6286/// you should call Sumw2 before making this operation.
6287/// This is particularly important if you fit the histogram after TH1::Multiply
6288///
6289/// The function return kFALSE if the Multiply operation failed
6290
6291Bool_t TH1::Multiply(const TH1 *h1)
6292{
6293 if (!h1) {
6294 Error("Multiply","Attempt to multiply by a non-existing histogram");
6295 return kFALSE;
6296 }
6297
6298 // delete buffer if it is there since it will become invalid
6299 if (fBuffer) BufferEmpty(1);
6300
6301 if (LoggedInconsistency("Multiply", this, h1) >= kDifferentNumberOfBins) {
6302 return false;
6303 }
6304
6305 // Create Sumw2 if h1 has Sumw2 set
6306 if (fSumw2.fN == 0 && h1->GetSumw2N() != 0) Sumw2();
6307
6308 // - Reset min- maximum
6309 SetMinimum();
6310 SetMaximum();
6311
6312 // - Loop on bins (including underflows/overflows)
6313 for (Int_t i = 0; i < fNcells; ++i) {
6316 UpdateBinContent(i, c0 * c1);
6317 if (fSumw2.fN) {
6319 }
6320 }
6321 ResetStats();
6322 return kTRUE;
6323}
6324
6325////////////////////////////////////////////////////////////////////////////////
6326/// Replace contents of this histogram by multiplication of h1 by h2.
6327///
6328/// `this = (c1*h1)*(c2*h2)`
6329///
6330/// If errors of this are available (TH1::Sumw2), errors are recalculated.
6331/// Note that if h1 or h2 have Sumw2 set, Sumw2 is automatically called for this
6332/// if not already set.
6333///
6334/// IMPORTANT NOTE: If you intend to use the errors of this histogram later
6335/// you should call Sumw2 before making this operation.
6336/// This is particularly important if you fit the histogram after TH1::Multiply
6337///
6338/// The function return kFALSE if the Multiply operation failed
6339
6341{
6342 TString opt = option;
6343 opt.ToLower();
6344 // Bool_t binomial = kFALSE;
6345 // if (opt.Contains("b")) binomial = kTRUE;
6346 if (!h1 || !h2) {
6347 Error("Multiply","Attempt to multiply by a non-existing histogram");
6348 return kFALSE;
6349 }
6350
6351 // delete buffer if it is there since it will become invalid
6352 if (fBuffer) BufferEmpty(1);
6353
6354 if (LoggedInconsistency("Multiply", this, h1) >= kDifferentNumberOfBins ||
6355 LoggedInconsistency("Multiply", h1, h2) >= kDifferentNumberOfBins) {
6356 return false;
6357 }
6358
6359 // Create Sumw2 if h1 or h2 have Sumw2 set
6360 if (fSumw2.fN == 0 && (h1->GetSumw2N() != 0 || h2->GetSumw2N() != 0)) Sumw2();
6361
6362 // - Reset min - maximum
6363 SetMinimum();
6364 SetMaximum();
6365
6366 // - Loop on bins (including underflows/overflows)
6367 Double_t c1sq = c1 * c1; Double_t c2sq = c2 * c2;
6368 for (Int_t i = 0; i < fNcells; ++i) {
6370 Double_t b2 = h2->RetrieveBinContent(i);
6371 UpdateBinContent(i, c1 * b1 * c2 * b2);
6372 if (fSumw2.fN) {
6373 fSumw2.fArray[i] = c1sq * c2sq * (h1->GetBinErrorSqUnchecked(i) * b2 * b2 + h2->GetBinErrorSqUnchecked(i) * b1 * b1);
6374 }
6375 }
6376 ResetStats();
6377 return kTRUE;
6378}
6379
6380////////////////////////////////////////////////////////////////////////////////
6381/// @brief Normalize a histogram to its integral or to its maximum.
6382/// @note Works for TH1, TH2, TH3, ...
6383/// @param option: normalization strategy ("", "max" or "sum")
6384/// - "": Scale to `1/(sum*bin_width)`.
6385/// - max: Scale to `1/GetMaximum()`
6386/// - sum: Scale to `1/sum`.
6387///
6388/// In case the norm is zero, it raises an error.
6389/// @sa https://root-forum.cern.ch/t/different-ways-of-normalizing-histograms/15582/
6390
6392{
6393 TString opt = option;
6394 opt.ToLower();
6395 if (!opt.IsNull() && (opt != "max") && (opt != "sum")) {
6396 Error("Normalize", "Unrecognized option %s", option);
6397 return;
6398 }
6399
6400 const Double_t norm = (opt == "max") ? GetMaximum() : Integral(opt.IsNull() ? "width" : "");
6401
6402 if (norm == 0) {
6403 Error("Normalize", "Attempt to normalize histogram with zero integral");
6404 } else {
6405 Scale(1.0 / norm, "");
6406 // An alternative could have been to call Integral("") and Scale(1/norm, "width"), but this
6407 // will lead to a different value of GetEntries.
6408 // Instead, doing simultaneously Integral("width") and Scale(1/norm, "width") leads to an error since you are
6409 // dividing twice by bin width.
6410 }
6411}
6412
6413////////////////////////////////////////////////////////////////////////////////
6414/// Control routine to paint any kind of histograms.
6415///
6416/// This function is automatically called by TCanvas::Update.
6417/// (see TH1::Draw for the list of options)
6418
6420{
6422
6423 if (fPainter) {
6424 if (option && strlen(option) > 0)
6426 else
6428 }
6429}
6430
6431////////////////////////////////////////////////////////////////////////////////
6432/// Rebin this histogram
6433///
6434/// #### case 1 xbins=0
6435///
6436/// If newname is blank (default), the current histogram is modified and
6437/// a pointer to it is returned.
6438///
6439/// If newname is not blank, the current histogram is not modified, and a
6440/// new histogram is returned which is a Clone of the current histogram
6441/// with its name set to newname.
6442///
6443/// The parameter ngroup indicates how many bins of this have to be merged
6444/// into one bin of the result.
6445///
6446/// If the original histogram has errors stored (via Sumw2), the resulting
6447/// histograms has new errors correctly calculated.
6448///
6449/// examples: if h1 is an existing TH1F histogram with 100 bins
6450///
6451/// ~~~ {.cpp}
6452/// h1->Rebin(); //merges two bins in one in h1: previous contents of h1 are lost
6453/// h1->Rebin(5); //merges five bins in one in h1
6454/// TH1F *hnew = dynamic_cast<TH1F*>(h1->Rebin(5,"hnew")); // creates a new histogram hnew
6455/// // merging 5 bins of h1 in one bin
6456/// ~~~
6457///
6458/// NOTE: If ngroup is not an exact divider of the number of bins,
6459/// the top limit of the rebinned histogram is reduced
6460/// to the upper edge of the last bin that can make a complete
6461/// group. The remaining bins are added to the overflow bin.
6462/// Statistics will be recomputed from the new bin contents.
6463///
6464/// #### case 2 xbins!=0
6465///
6466/// A new histogram is created (you should specify newname).
6467/// The parameter ngroup is the number of variable size bins in the created histogram.
6468/// The array xbins must contain ngroup+1 elements that represent the low-edges
6469/// of the bins.
6470/// If the original histogram has errors stored (via Sumw2), the resulting
6471/// histograms has new errors correctly calculated.
6472///
6473/// NOTE: The bin edges specified in xbins should correspond to bin edges
6474/// in the original histogram. If a bin edge in the new histogram is
6475/// in the middle of a bin in the original histogram, all entries in
6476/// the split bin in the original histogram will be transferred to the
6477/// lower of the two possible bins in the new histogram. This is
6478/// probably not what you want. A warning message is emitted in this
6479/// case
6480///
6481/// examples: if h1 is an existing TH1F histogram with 100 bins
6482///
6483/// ~~~ {.cpp}
6484/// Double_t xbins[25] = {...} array of low-edges (xbins[25] is the upper edge of last bin
6485/// h1->Rebin(24,"hnew",xbins); //creates a new variable bin size histogram hnew
6486/// ~~~
6487
6488TH1 *TH1::Rebin(Int_t ngroup, const char*newname, const Double_t *xbins)
6489{
6493 if ((ngroup <= 0) || (ngroup > nbins)) {
6494 Error("Rebin", "Illegal value of ngroup=%d",ngroup);
6495 return nullptr;
6496 }
6497
6498 if (fDimension > 1 || InheritsFrom(TProfile::Class())) {
6499 Error("Rebin", "Operation valid on 1-D histograms only");
6500 return nullptr;
6501 }
6502 if (!newname && xbins) {
6503 Error("Rebin","if xbins is specified, newname must be given");
6504 return nullptr;
6505 }
6506
6508 if (!xbins) {
6510 if (nbg*ngroup != nbins) {
6511 Warning("Rebin", "ngroup=%d is not an exact divider of nbins=%d.",ngroup,nbins);
6512 }
6513 }
6514 else {
6515 // in the case that xbins is given (rebinning in variable bins), ngroup is
6516 // the new number of bins and number of grouped bins is not constant.
6517 // when looping for setting the contents for the new histogram we
6518 // need to loop on all bins of original histogram. Then set ngroup=nbins
6519 newbins = ngroup;
6520 ngroup = nbins;
6521 }
6522
6523 // Save old bin contents into a new array
6525 Double_t *oldBins = new Double_t[nbins+2];
6526 Int_t bin, i;
6527 for (bin=0;bin<nbins+2;bin++) oldBins[bin] = RetrieveBinContent(bin);
6528 Double_t *oldErrors = nullptr;
6529 if (fSumw2.fN != 0) {
6530 oldErrors = new Double_t[nbins+2];
6531 for (bin=0;bin<nbins+2;bin++) oldErrors[bin] = GetBinError(bin);
6532 }
6533 // rebin will not include underflow/overflow if new axis range is larger than old axis range
6534 if (xbins) {
6535 if (xbins[0] < fXaxis.GetXmin() && oldBins[0] != 0 )
6536 Warning("Rebin","underflow entries will not be used when rebinning");
6537 if (xbins[newbins] > fXaxis.GetXmax() && oldBins[nbins+1] != 0 )
6538 Warning("Rebin","overflow entries will not be used when rebinning");
6539 }
6540
6541
6542 // create a clone of the old histogram if newname is specified
6543 TH1 *hnew = this;
6544 if ((newname && strlen(newname) > 0) || xbins) {
6545 hnew = (TH1*)Clone(newname);
6546 }
6547
6548 //reset can extend bit to avoid an axis extension in SetBinContent
6549 UInt_t oldExtendBitMask = hnew->SetCanExtend(kNoAxis);
6550
6551 // save original statistics
6553 GetStats(stat);
6554 bool resetStat = false;
6555 // change axis specs and rebuild bin contents array::RebinAx
6556 if(!xbins && (newbins*ngroup != nbins)) {
6558 resetStat = true; //stats must be reset because top bins will be moved to overflow bin
6559 }
6560 // save the TAttAxis members (reset by SetBins)
6572
6573 if(!xbins && (fXaxis.GetXbins()->GetSize() > 0)){ // variable bin sizes
6574 Double_t *bins = new Double_t[newbins+1];
6575 for(i = 0; i <= newbins; ++i) bins[i] = fXaxis.GetBinLowEdge(1+i*ngroup);
6576 hnew->SetBins(newbins,bins); //this also changes errors array (if any)
6577 delete [] bins;
6578 } else if (xbins) {
6579 hnew->SetBins(newbins,xbins);
6580 } else {
6581 hnew->SetBins(newbins,xmin,xmax);
6582 }
6583
6584 // Restore axis attributes
6596
6597 // copy merged bin contents (ignore under/overflows)
6598 // Start merging only once the new lowest edge is reached
6599 Int_t startbin = 1;
6600 const Double_t newxmin = hnew->GetXaxis()->GetBinLowEdge(1);
6601 while( fXaxis.GetBinCenter(startbin) < newxmin && startbin <= nbins ) {
6602 startbin++;
6603 }
6606 for (bin = 1;bin<=newbins;bin++) {
6607 binContent = 0;
6608 binError = 0;
6609 Int_t imax = ngroup;
6610 Double_t xbinmax = hnew->GetXaxis()->GetBinUpEdge(bin);
6611 // check bin edges for the cases when we provide an array of bins
6612 // be careful in case bins can have zero width
6614 hnew->GetXaxis()->GetBinLowEdge(bin),
6615 TMath::Max(1.E-8 * fXaxis.GetBinWidth(oldbin), 1.E-16 )) )
6616 {
6617 Warning("Rebin","Bin edge %d of rebinned histogram does not match any bin edges of the old histogram. Result can be inconsistent",bin);
6618 }
6619 for (i=0;i<ngroup;i++) {
6620 if( (oldbin+i > nbins) ||
6621 ( hnew != this && (fXaxis.GetBinCenter(oldbin+i) > xbinmax)) ) {
6622 imax = i;
6623 break;
6624 }
6627 }
6628 hnew->SetBinContent(bin,binContent);
6629 if (oldErrors) hnew->SetBinError(bin,TMath::Sqrt(binError));
6630 oldbin += imax;
6631 }
6632
6633 // sum underflow and overflow contents until startbin
6634 binContent = 0;
6635 binError = 0;
6636 for (i = 0; i < startbin; ++i) {
6637 binContent += oldBins[i];
6638 if (oldErrors) binError += oldErrors[i]*oldErrors[i];
6639 }
6640 hnew->SetBinContent(0,binContent);
6641 if (oldErrors) hnew->SetBinError(0,TMath::Sqrt(binError));
6642 // sum overflow
6643 binContent = 0;
6644 binError = 0;
6645 for (i = oldbin; i <= nbins+1; ++i) {
6646 binContent += oldBins[i];
6647 if (oldErrors) binError += oldErrors[i]*oldErrors[i];
6648 }
6649 hnew->SetBinContent(newbins+1,binContent);
6650 if (oldErrors) hnew->SetBinError(newbins+1,TMath::Sqrt(binError));
6651
6652 hnew->SetCanExtend(oldExtendBitMask); // restore previous state
6653
6654 // restore statistics and entries modified by SetBinContent
6655 hnew->SetEntries(entries);
6656 if (!resetStat) hnew->PutStats(stat);
6657 delete [] oldBins;
6658 if (oldErrors) delete [] oldErrors;
6659 return hnew;
6660}
6661
6662////////////////////////////////////////////////////////////////////////////////
6663/// finds new limits for the axis so that *point* is within the range and
6664/// the limits are compatible with the previous ones (see TH1::Merge).
6665/// new limits are put into *newMin* and *newMax* variables.
6666/// axis - axis whose limits are to be recomputed
6667/// point - point that should fit within the new axis limits
6668/// newMin - new minimum will be stored here
6669/// newMax - new maximum will be stored here.
6670/// false if failed (e.g. if the initial axis limits are wrong
6671/// or the new range is more than \f$ 2^{64} \f$ times the old one).
6672
6674{
6675 Double_t xmin = axis->GetXmin();
6676 Double_t xmax = axis->GetXmax();
6677 if (xmin >= xmax) return kFALSE;
6679
6680 //recompute new axis limits by doubling the current range
6681 Int_t ntimes = 0;
6682 while (point < xmin) {
6683 if (ntimes++ > 64)
6684 return kFALSE;
6685 xmin = xmin - range;
6686 range *= 2;
6687 }
6688 while (point >= xmax) {
6689 if (ntimes++ > 64)
6690 return kFALSE;
6691 xmax = xmax + range;
6692 range *= 2;
6693 }
6694 newMin = xmin;
6695 newMax = xmax;
6696 // Info("FindNewAxisLimits", "OldAxis: (%lf, %lf), new: (%lf, %lf), point: %lf",
6697 // axis->GetXmin(), axis->GetXmax(), xmin, xmax, point);
6698
6699 return kTRUE;
6700}
6701
6702////////////////////////////////////////////////////////////////////////////////
6703/// Histogram is resized along axis such that x is in the axis range.
6704/// The new axis limits are recomputed by doubling iteratively
6705/// the current axis range until the specified value x is within the limits.
6706/// The algorithm makes a copy of the histogram, then loops on all bins
6707/// of the old histogram to fill the extended histogram.
6708/// Takes into account errors (Sumw2) if any.
6709/// The algorithm works for 1-d, 2-D and 3-D histograms.
6710/// The axis must be extendable before invoking this function.
6711/// Ex:
6712///
6713/// ~~~ {.cpp}
6714/// h->GetXaxis()->SetCanExtend(kTRUE);
6715/// ~~~
6716
6717void TH1::ExtendAxis(Double_t x, TAxis *axis)
6718{
6719 if (!axis->CanExtend()) return;
6720 if (TMath::IsNaN(x)) { // x may be a NaN
6722 return;
6723 }
6724
6725 if (axis->GetXmin() >= axis->GetXmax()) return;
6726 if (axis->GetNbins() <= 0) return;
6727
6729 if (!FindNewAxisLimits(axis, x, xmin, xmax))
6730 return;
6731
6732 //save a copy of this histogram
6733 TH1 *hold = (TH1*)IsA()->New();
6734 hold->SetDirectory(nullptr);
6735 Copy(*hold);
6736 //set new axis limits
6737 axis->SetLimits(xmin,xmax);
6738
6739
6740 //now loop on all bins and refill
6742
6743 Reset("ICE"); //reset only Integral, contents and Errors
6744
6745 int iaxis = 0;
6746 if (axis == &fXaxis) iaxis = 1;
6747 if (axis == &fYaxis) iaxis = 2;
6748 if (axis == &fZaxis) iaxis = 3;
6749 bool firstw = kTRUE;
6750 Int_t binx,biny, binz = 0;
6751 Int_t ix = 0,iy = 0,iz = 0;
6752 Double_t bx,by,bz;
6753 Int_t ncells = hold->GetNcells();
6754 for (Int_t bin = 0; bin < ncells; ++bin) {
6755 hold->GetBinXYZ(bin,binx,biny,binz);
6756 bx = hold->GetXaxis()->GetBinCenter(binx);
6757 ix = fXaxis.FindFixBin(bx);
6758 if (fDimension > 1) {
6759 by = hold->GetYaxis()->GetBinCenter(biny);
6760 iy = fYaxis.FindFixBin(by);
6761 if (fDimension > 2) {
6762 bz = hold->GetZaxis()->GetBinCenter(binz);
6763 iz = fZaxis.FindFixBin(bz);
6764 }
6765 }
6766 // exclude underflow/overflow
6767 double content = hold->RetrieveBinContent(bin);
6768 if (content == 0) continue;
6770 if (firstw) {
6771 Warning("ExtendAxis","Histogram %s has underflow or overflow in the axis that is extendable"
6772 " their content will be lost",GetName() );
6773 firstw= kFALSE;
6774 }
6775 continue;
6776 }
6777 Int_t ibin= GetBin(ix,iy,iz);
6779 if (errors) {
6780 fSumw2.fArray[ibin] += hold->GetBinErrorSqUnchecked(bin);
6781 }
6782 }
6783 delete hold;
6784}
6785
6786////////////////////////////////////////////////////////////////////////////////
6787/// Recursively remove object from the list of functions
6788
6790{
6791 // Rely on TROOT::RecursiveRemove to take the readlock.
6792
6793 if (fFunctions) {
6795 }
6796}
6797
6798////////////////////////////////////////////////////////////////////////////////
6799/// Multiply this histogram by a constant c1.
6800///
6801/// `this = c1*this`
6802///
6803/// Note that both contents and errors (if any) are scaled.
6804/// This function uses the services of TH1::Add
6805///
6806/// IMPORTANT NOTE: Sumw2() is called automatically when scaling.
6807/// If you are not interested in the histogram statistics you can call
6808/// Sumw2(kFALSE) or use the option "nosw2"
6809///
6810/// One can scale a histogram such that the bins integral is equal to
6811/// the normalization parameter via TH1::Scale(Double_t norm), where norm
6812/// is the desired normalization divided by the integral of the histogram.
6813///
6814/// If option contains "width" the bin contents and errors are divided
6815/// by the bin width.
6816
6818{
6819
6820 TString opt = option; opt.ToLower();
6821 // store bin errors when scaling since cannot anymore be computed as sqrt(N)
6822 if (!opt.Contains("nosw2") && GetSumw2N() == 0) Sumw2();
6823 if (opt.Contains("width")) Add(this, this, c1, -1);
6824 else {
6825 if (fBuffer) BufferEmpty(1);
6826 for(Int_t i = 0; i < fNcells; ++i) UpdateBinContent(i, c1 * RetrieveBinContent(i));
6827 if (fSumw2.fN) for(Int_t i = 0; i < fNcells; ++i) fSumw2.fArray[i] *= (c1 * c1); // update errors
6828 // update global histograms statistics
6829 Double_t s[kNstat] = {0};
6830 GetStats(s);
6831 for (Int_t i=0 ; i < kNstat; i++) {
6832 if (i == 1) s[i] = c1*c1*s[i];
6833 else s[i] = c1*s[i];
6834 }
6835 PutStats(s);
6836 SetMinimum(); SetMaximum(); // minimum and maximum value will be recalculated the next time
6837 }
6838
6839 // if contours set, must also scale contours
6841 if (ncontours == 0) return;
6843 for (Int_t i = 0; i < ncontours; ++i) levels[i] *= c1;
6844}
6845
6846////////////////////////////////////////////////////////////////////////////////
6847/// Returns true if all axes are extendable.
6848
6850{
6852 if (GetDimension() > 1) canExtend &= fYaxis.CanExtend();
6853 if (GetDimension() > 2) canExtend &= fZaxis.CanExtend();
6854
6855 return canExtend;
6856}
6857
6858////////////////////////////////////////////////////////////////////////////////
6859/// Make the histogram axes extendable / not extendable according to the bit mask
6860/// returns the previous bit mask specifying which axes are extendable
6861
6863{
6865
6869
6870 if (GetDimension() > 1) {
6874 }
6875
6876 if (GetDimension() > 2) {
6880 }
6881
6882 return oldExtendBitMask;
6883}
6884
6885///////////////////////////////////////////////////////////////////////////////
6886/// Internal function used in TH1::Fill to see which axis is full alphanumeric,
6887/// i.e. can be extended and is alphanumeric
6889{
6893 bitMask |= kYaxis;
6895 bitMask |= kZaxis;
6896
6897 return bitMask;
6898}
6899
6900////////////////////////////////////////////////////////////////////////////////
6901/// Static function to set the default buffer size for automatic histograms.
6902/// When a histogram is created with one of its axis lower limit greater
6903/// or equal to its upper limit, the function SetBuffer is automatically
6904/// called with the default buffer size.
6905
6907{
6908 fgBufferSize = bufsize > 0 ? bufsize : 0;
6909}
6910
6911////////////////////////////////////////////////////////////////////////////////
6912/// When this static function is called with `sumw2=kTRUE`, all new
6913/// histograms will automatically activate the storage
6914/// of the sum of squares of errors, ie TH1::Sumw2 is automatically called.
6915
6917{
6919}
6920
6921////////////////////////////////////////////////////////////////////////////////
6922/// Change/set the title.
6923///
6924/// If title is in the form `stringt;stringx;stringy;stringz;stringc`
6925/// the histogram title is set to `stringt`, the x axis title to `stringx`,
6926/// the y axis title to `stringy`, the z axis title to `stringz`, and the c
6927/// axis title for the palette is ignored at this stage.
6928/// Note that you can use e.g. `stringt;stringx` if you only want to specify
6929/// title and x axis title.
6930///
6931/// To insert the character `;` in one of the titles, one should use `#;`
6932/// or `#semicolon`.
6933
6934void TH1::SetTitle(const char *title)
6935{
6936 fTitle = title;
6937 fTitle.ReplaceAll("#;",2,"#semicolon",10);
6938
6939 // Decode fTitle. It may contain X, Y and Z titles
6941 Int_t isc = str1.Index(";");
6942 Int_t lns = str1.Length();
6943
6944 if (isc >=0 ) {
6945 fTitle = str1(0,isc);
6946 str1 = str1(isc+1, lns);
6947 isc = str1.Index(";");
6948 if (isc >=0 ) {
6949 str2 = str1(0,isc);
6950 str2.ReplaceAll("#semicolon",10,";",1);
6951 fXaxis.SetTitle(str2.Data());
6952 lns = str1.Length();
6953 str1 = str1(isc+1, lns);
6954 isc = str1.Index(";");
6955 if (isc >=0 ) {
6956 str2 = str1(0,isc);
6957 str2.ReplaceAll("#semicolon",10,";",1);
6958 fYaxis.SetTitle(str2.Data());
6959 lns = str1.Length();
6960 str1 = str1(isc+1, lns);
6961 isc = str1.Index(";");
6962 if (isc >=0 ) {
6963 str2 = str1(0,isc);
6964 str2.ReplaceAll("#semicolon",10,";",1);
6965 fZaxis.SetTitle(str2.Data());
6966 } else {
6967 str1.ReplaceAll("#semicolon",10,";",1);
6968 fZaxis.SetTitle(str1.Data());
6969 }
6970 } else {
6971 str1.ReplaceAll("#semicolon",10,";",1);
6972 fYaxis.SetTitle(str1.Data());
6973 }
6974 } else {
6975 str1.ReplaceAll("#semicolon",10,";",1);
6976 fXaxis.SetTitle(str1.Data());
6977 }
6978 }
6979
6980 fTitle.ReplaceAll("#semicolon",10,";",1);
6981
6982 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
6983}
6984
6985////////////////////////////////////////////////////////////////////////////////
6986/// Smooth array xx, translation of Hbook routine `hsmoof.F`.
6987/// Based on algorithm 353QH twice presented by J. Friedman
6988/// in [Proc. of the 1974 CERN School of Computing, Norway, 11-24 August, 1974](https://cds.cern.ch/record/186223).
6989/// See also Section 4.2 in [J. Friedman, Data Analysis Techniques for High Energy Physics](https://www.slac.stanford.edu/pubs/slacreports/reports16/slac-r-176.pdf).
6990
6992{
6993 if (nn < 3 ) {
6994 ::Error("SmoothArray","Need at least 3 points for smoothing: n = %d",nn);
6995 return;
6996 }
6997
6998 Int_t ii;
6999 std::array<double, 3> hh{};
7000
7001 std::vector<double> yy(nn);
7002 std::vector<double> zz(nn);
7003 std::vector<double> rr(nn);
7004
7005 for (Int_t pass=0;pass<ntimes;pass++) {
7006 // first copy original data into temp array
7007 std::copy(xx, xx+nn, zz.begin() );
7008
7009 for (int noent = 0; noent < 2; ++noent) { // run algorithm two times
7010
7011 // do 353 i.e. running median 3, 5, and 3 in a single loop
7012 for (int kk = 0; kk < 3; kk++) {
7013 std::copy(zz.begin(), zz.end(), yy.begin());
7014 int medianType = (kk != 1) ? 3 : 5;
7015 int ifirst = (kk != 1 ) ? 1 : 2;
7016 int ilast = (kk != 1 ) ? nn-1 : nn -2;
7017 //nn2 = nn - ik - 1;
7018 // do all elements beside the first and last point for median 3
7019 // and first two and last 2 for median 5
7020 for ( ii = ifirst; ii < ilast; ii++) {
7021 zz[ii] = TMath::Median(medianType, yy.data() + ii - ifirst);
7022 }
7023
7024 if (kk == 0) { // first median 3
7025 // first point
7026 hh[0] = zz[1];
7027 hh[1] = zz[0];
7028 hh[2] = 3*zz[1] - 2*zz[2];
7029 zz[0] = TMath::Median(3, hh.data());
7030 // last point
7031 hh[0] = zz[nn - 2];
7032 hh[1] = zz[nn - 1];
7033 hh[2] = 3*zz[nn - 2] - 2*zz[nn - 3];
7034 zz[nn - 1] = TMath::Median(3, hh.data());
7035 }
7036
7037 if (kk == 1) { // median 5
7038 // second point with window length 3
7039 zz[1] = TMath::Median(3, yy.data());
7040 // second-to-last point with window length 3
7041 zz[nn - 2] = TMath::Median(3, yy.data() + nn - 3);
7042 }
7043
7044 // In the third iteration (kk == 2), the first and last point stay
7045 // the same (see paper linked in the documentation).
7046 }
7047
7048 std::copy ( zz.begin(), zz.end(), yy.begin() );
7049
7050 // quadratic interpolation for flat segments
7051 for (ii = 2; ii < (nn - 2); ii++) {
7052 if (zz[ii - 1] != zz[ii]) continue;
7053 if (zz[ii] != zz[ii + 1]) continue;
7054 const double tmp0 = zz[ii - 2] - zz[ii];
7055 const double tmp1 = zz[ii + 2] - zz[ii];
7056 if (tmp0 * tmp1 <= 0) continue;
7057 int jk = 1;
7058 if ( std::abs(tmp1) > std::abs(tmp0) ) jk = -1;
7059 yy[ii] = -0.5*zz[ii - 2*jk] + zz[ii]/0.75 + zz[ii + 2*jk] /6.;
7060 yy[ii + jk] = 0.5*(zz[ii + 2*jk] - zz[ii - 2*jk]) + zz[ii];
7061 }
7062
7063 // running means
7064 //std::copy(zz.begin(), zz.end(), yy.begin());
7065 for (ii = 1; ii < nn - 1; ii++) {
7066 zz[ii] = 0.25*yy[ii - 1] + 0.5*yy[ii] + 0.25*yy[ii + 1];
7067 }
7068 zz[0] = yy[0];
7069 zz[nn - 1] = yy[nn - 1];
7070
7071 if (noent == 0) {
7072
7073 // save computed values
7074 std::copy(zz.begin(), zz.end(), rr.begin());
7075
7076 // COMPUTE residuals
7077 for (ii = 0; ii < nn; ii++) {
7078 zz[ii] = xx[ii] - zz[ii];
7079 }
7080 }
7081
7082 } // end loop on noent
7083
7084
7085 double xmin = TMath::MinElement(nn,xx);
7086 for (ii = 0; ii < nn; ii++) {
7087 if (xmin < 0) xx[ii] = rr[ii] + zz[ii];
7088 // make smoothing defined positive - not better using 0 ?
7089 else xx[ii] = std::max((rr[ii] + zz[ii]),0.0 );
7090 }
7091 }
7092}
7093
7094////////////////////////////////////////////////////////////////////////////////
7095/// Smooth bin contents of this histogram.
7096/// if option contains "R" smoothing is applied only to the bins
7097/// defined in the X axis range (default is to smooth all bins)
7098/// Bin contents are replaced by their smooth values.
7099/// Errors (if any) are not modified.
7100/// the smoothing procedure is repeated ntimes (default=1)
7101
7103{
7104 if (fDimension != 1) {
7105 Error("Smooth","Smooth only supported for 1-d histograms");
7106 return;
7107 }
7109 if (nbins < 3) {
7110 Error("Smooth","Smooth only supported for histograms with >= 3 bins. Nbins = %d",nbins);
7111 return;
7112 }
7113
7114 // delete buffer if it is there since it will become invalid
7115 if (fBuffer) BufferEmpty(1);
7116
7117 Int_t firstbin = 1, lastbin = nbins;
7118 TString opt = option;
7119 opt.ToLower();
7120 if (opt.Contains("r")) {
7123 }
7124 nbins = lastbin - firstbin + 1;
7125 Double_t *xx = new Double_t[nbins];
7127 Int_t i;
7128 for (i=0;i<nbins;i++) {
7130 }
7131
7133
7134 for (i=0;i<nbins;i++) {
7136 }
7137 fEntries = nent;
7138 delete [] xx;
7139
7140 if (gPad) gPad->Modified();
7141}
7142
7143////////////////////////////////////////////////////////////////////////////////
7144/// if flag=kTRUE, underflows and overflows are used by the Fill functions
7145/// in the computation of statistics (mean value, StdDev).
7146/// By default, underflows or overflows are not used.
7147
7149{
7151}
7152
7153////////////////////////////////////////////////////////////////////////////////
7154/// Stream a class object.
7155
7156void TH1::Streamer(TBuffer &b)
7157{
7158 if (b.IsReading()) {
7159 UInt_t R__s, R__c;
7160 Version_t R__v = b.ReadVersion(&R__s, &R__c);
7161 if (fDirectory) fDirectory->Remove(this);
7162 fDirectory = nullptr;
7163 if (R__v > 2) {
7164 b.ReadClassBuffer(TH1::Class(), this, R__v, R__s, R__c);
7165
7167 fXaxis.SetParent(this);
7168 fYaxis.SetParent(this);
7169 fZaxis.SetParent(this);
7170 TIter next(fFunctions);
7171 TObject *obj;
7172 while ((obj=next())) {
7173 if (obj->InheritsFrom(TF1::Class())) ((TF1*)obj)->SetParent(this);
7174 }
7175 return;
7176 }
7177 //process old versions before automatic schema evolution
7182 b >> fNcells;
7183 fXaxis.Streamer(b);
7184 fYaxis.Streamer(b);
7185 fZaxis.Streamer(b);
7186 fXaxis.SetParent(this);
7187 fYaxis.SetParent(this);
7188 fZaxis.SetParent(this);
7189 b >> fBarOffset;
7190 b >> fBarWidth;
7191 b >> fEntries;
7192 b >> fTsumw;
7193 b >> fTsumw2;
7194 b >> fTsumwx;
7195 b >> fTsumwx2;
7196 if (R__v < 2) {
7198 Float_t *contour=nullptr;
7199 b >> maximum; fMaximum = maximum;
7200 b >> minimum; fMinimum = minimum;
7201 b >> norm; fNormFactor = norm;
7202 Int_t n = b.ReadArray(contour);
7203 fContour.Set(n);
7204 for (Int_t i=0;i<n;i++) fContour.fArray[i] = contour[i];
7205 delete [] contour;
7206 } else {
7207 b >> fMaximum;
7208 b >> fMinimum;
7209 b >> fNormFactor;
7211 }
7212 fSumw2.Streamer(b);
7214 fFunctions->Delete();
7216 b.CheckByteCount(R__s, R__c, TH1::IsA());
7217
7218 } else {
7219 b.WriteClassBuffer(TH1::Class(),this);
7220 }
7221}
7222
7223////////////////////////////////////////////////////////////////////////////////
7224/// Print some global quantities for this histogram.
7225/// \param[in] option
7226/// - "base" is given, number of bins and ranges are also printed
7227/// - "range" is given, bin contents and errors are also printed
7228/// for all bins in the current range (default 1-->nbins)
7229/// - "all" is given, bin contents and errors are also printed
7230/// for all bins including under and overflows.
7231
7232void TH1::Print(Option_t *option) const
7233{
7234 if (fBuffer) const_cast<TH1*>(this)->BufferEmpty();
7235 printf( "TH1.Print Name = %s, Entries= %d, Total sum= %g\n",GetName(),Int_t(fEntries),GetSumOfWeights());
7236 TString opt = option;
7237 opt.ToLower();
7238 Int_t all;
7239 if (opt.Contains("all")) all = 0;
7240 else if (opt.Contains("range")) all = 1;
7241 else if (opt.Contains("base")) all = 2;
7242 else return;
7243
7244 Int_t bin, binx, biny, binz;
7246 if (all == 0) {
7247 lastx = fXaxis.GetNbins()+1;
7248 if (fDimension > 1) lasty = fYaxis.GetNbins()+1;
7249 if (fDimension > 2) lastz = fZaxis.GetNbins()+1;
7250 } else {
7252 if (fDimension > 1) {firsty = fYaxis.GetFirst(); lasty = fYaxis.GetLast();}
7253 if (fDimension > 2) {firstz = fZaxis.GetFirst(); lastz = fZaxis.GetLast();}
7254 }
7255
7256 if (all== 2) {
7257 printf(" Title = %s\n", GetTitle());
7258 printf(" NbinsX= %d, xmin= %g, xmax=%g", fXaxis.GetNbins(), fXaxis.GetXmin(), fXaxis.GetXmax());
7259 if( fDimension > 1) printf(", NbinsY= %d, ymin= %g, ymax=%g", fYaxis.GetNbins(), fYaxis.GetXmin(), fYaxis.GetXmax());
7260 if( fDimension > 2) printf(", NbinsZ= %d, zmin= %g, zmax=%g", fZaxis.GetNbins(), fZaxis.GetXmin(), fZaxis.GetXmax());
7261 printf("\n");
7262 return;
7263 }
7264
7265 Double_t w,e;
7266 Double_t x,y,z;
7267 if (fDimension == 1) {
7268 for (binx=firstx;binx<=lastx;binx++) {
7271 e = GetBinError(binx);
7272 if(fSumw2.fN) printf(" fSumw[%d]=%g, x=%g, error=%g\n",binx,w,x,e);
7273 else printf(" fSumw[%d]=%g, x=%g\n",binx,w,x);
7274 }
7275 }
7276 if (fDimension == 2) {
7277 for (biny=firsty;biny<=lasty;biny++) {
7279 for (binx=firstx;binx<=lastx;binx++) {
7280 bin = GetBin(binx,biny);
7283 e = GetBinError(bin);
7284 if(fSumw2.fN) printf(" fSumw[%d][%d]=%g, x=%g, y=%g, error=%g\n",binx,biny,w,x,y,e);
7285 else printf(" fSumw[%d][%d]=%g, x=%g, y=%g\n",binx,biny,w,x,y);
7286 }
7287 }
7288 }
7289 if (fDimension == 3) {
7290 for (binz=firstz;binz<=lastz;binz++) {
7292 for (biny=firsty;biny<=lasty;biny++) {
7294 for (binx=firstx;binx<=lastx;binx++) {
7295 bin = GetBin(binx,biny,binz);
7298 e = GetBinError(bin);
7299 if(fSumw2.fN) printf(" fSumw[%d][%d][%d]=%g, x=%g, y=%g, z=%g, error=%g\n",binx,biny,binz,w,x,y,z,e);
7300 else printf(" fSumw[%d][%d][%d]=%g, x=%g, y=%g, z=%g\n",binx,biny,binz,w,x,y,z);
7301 }
7302 }
7303 }
7304 }
7305}
7306
7307////////////////////////////////////////////////////////////////////////////////
7308/// Using the current bin info, recompute the arrays for contents and errors
7309
7310void TH1::Rebuild(Option_t *)
7311{
7312 SetBinsLength();
7313 if (fSumw2.fN) {
7315 }
7316}
7317
7318////////////////////////////////////////////////////////////////////////////////
7319/// Reset this histogram: contents, errors, etc.
7320/// \param[in] option
7321/// - if "ICE" is specified, resets only Integral, Contents and Errors.
7322/// - if "ICES" is specified, resets only Integral, Contents, Errors and Statistics
7323/// This option is used
7324/// - if "M" is specified, resets also Minimum and Maximum
7325
7327{
7328 // The option "ICE" is used when extending the histogram (in ExtendAxis, LabelInflate, etc..)
7329 // The option "ICES is used in combination with the buffer (see BufferEmpty and BufferFill)
7330
7331 TString opt = option;
7332 opt.ToUpper();
7333 fSumw2.Reset();
7334 if (fIntegral) {
7335 delete [] fIntegral;
7336 fIntegral = nullptr;
7337 }
7338
7339 if (opt.Contains("M")) {
7340 SetMinimum();
7341 SetMaximum();
7342 }
7343
7344 if (opt.Contains("ICE") && !opt.Contains("S")) return;
7345
7346 // Setting fBuffer[0] = 0 is like resetting the buffer but not deleting it
7347 // But what is the sense of calling BufferEmpty() ? For making the axes ?
7348 // BufferEmpty will update contents that later will be
7349 // reset in calling TH1D::Reset. For this we need to reset the stats afterwards
7350 // It may be needed for computing the axis limits....
7351 if (fBuffer) {BufferEmpty(); fBuffer[0] = 0;}
7352
7353 // need to reset also the statistics
7354 // (needs to be done after calling BufferEmpty() )
7355 fTsumw = 0;
7356 fTsumw2 = 0;
7357 fTsumwx = 0;
7358 fTsumwx2 = 0;
7359 fEntries = 0;
7360
7361 if (opt == "ICES") return;
7362
7363
7364 TObject *stats = fFunctions->FindObject("stats");
7365 fFunctions->Remove(stats);
7366 //special logic to support the case where the same object is
7367 //added multiple times in fFunctions.
7368 //This case happens when the same object is added with different
7369 //drawing modes
7370 TObject *obj;
7371 while ((obj = fFunctions->First())) {
7372 while(fFunctions->Remove(obj)) { }
7373 delete obj;
7374 }
7375 if(stats) fFunctions->Add(stats);
7376 fContour.Set(0);
7377}
7378
7379////////////////////////////////////////////////////////////////////////////////
7380/// Save the histogram as .csv, .tsv or .txt. In case of any other extension, fall
7381/// back to TObject::SaveAs, which saves as a .C macro (but with the file name
7382/// extension specified by the user)
7383///
7384/// The Under/Overflow bins are also exported (as first and last lines)
7385/// The fist 2 columns are the lower and upper edges of the bins
7386/// Column 3 contains the bin contents
7387/// The last column contains the error in y. If errors are not present, the column
7388/// is left empty
7389///
7390/// The result can be immediately imported into Excel, gnuplot, Python or whatever,
7391/// without the needing to install pyroot, etc.
7392///
7393/// \param filename the name of the file where to store the histogram
7394/// \param option some tuning options
7395///
7396/// The file extension defines the delimiter used:
7397/// - `.csv` : comma
7398/// - `.tsv` : tab
7399/// - `.txt` : space
7400///
7401/// If option = "title" a title line is generated. If the y-axis has a title,
7402/// this title is displayed as column 3 name, otherwise, it shows "BinContent"
7403
7404void TH1::SaveAs(const char *filename, Option_t *option) const
7405{
7406 char del = '\0';
7407 TString ext = "";
7409 TString opt = option;
7410
7411 if (filename) {
7412 if (fname.EndsWith(".csv")) {
7413 del = ',';
7414 ext = "csv";
7415 } else if (fname.EndsWith(".tsv")) {
7416 del = '\t';
7417 ext = "tsv";
7418 } else if (fname.EndsWith(".txt")) {
7419 del = ' ';
7420 ext = "txt";
7421 }
7422 }
7423 if (!del) {
7425 return;
7426 }
7427 std::ofstream out;
7428 out.open(filename, std::ios::out);
7429 if (!out.good()) {
7430 Error("SaveAs", "cannot open file: %s", filename);
7431 return;
7432 }
7433 if (opt.Contains("title")) {
7434 if (std::strcmp(GetYaxis()->GetTitle(), "") == 0) {
7435 out << "# " << "BinLowEdge" << del << "BinUpEdge" << del
7436 << "BinContent"
7437 << del << "ey" << std::endl;
7438 } else {
7439 out << "# " << "BinLowEdge" << del << "BinUpEdge" << del << GetYaxis()->GetTitle() << del << "ey" << std::endl;
7440 }
7441 }
7442 if (fSumw2.fN) {
7443 for (Int_t i = 0; i < fNcells; ++i) { // loop on cells (bins including underflow / overflow)
7444 out << GetXaxis()->GetBinLowEdge(i) << del << GetXaxis()->GetBinUpEdge(i) << del << GetBinContent(i) << del
7445 << GetBinError(i) << std::endl;
7446 }
7447 } else {
7448 for (Int_t i = 0; i < fNcells; ++i) { // loop on cells (bins including underflow / overflow)
7449 out << GetXaxis()->GetBinLowEdge(i) << del << GetXaxis()->GetBinUpEdge(i) << del << GetBinContent(i) << del
7450 << std::endl;
7451 }
7452 }
7453 out.close();
7454 Info("SaveAs", "%s file: %s has been generated", ext.Data(), filename);
7455}
7456
7457////////////////////////////////////////////////////////////////////////////////
7458/// Provide variable name for histogram for saving as primitive
7459/// Histogram pointer has by default the histogram name with an incremental suffix.
7460/// If the histogram belongs to a graph or a stack the suffix is not added because
7461/// the graph and stack objects are not aware of this new name. Same thing if
7462/// the histogram is drawn with the option COLZ because the TPaletteAxis drawn
7463/// when this option is selected, does not know this new name either.
7464
7466{
7467 thread_local Int_t storeNumber = 0;
7468
7469 TString opt = option;
7470 opt.ToLower();
7471 TString histName = GetName();
7472 // for TProfile and TH2Poly also fDirectory should be tested
7473 if (!histName.Contains("Graph") && !histName.Contains("_stack_") && !opt.Contains("colz") &&
7474 (!testfdir || !fDirectory)) {
7475 storeNumber++;
7476 histName += "__";
7477 histName += storeNumber;
7478 }
7479 if (histName.IsNull())
7480 histName = "unnamed";
7481 return gInterpreter->MapCppName(histName);
7482}
7483
7484////////////////////////////////////////////////////////////////////////////////
7485/// Save primitive as a C++ statement(s) on output stream out
7486
7487void TH1::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
7488{
7489 // empty the buffer before if it exists
7490 if (fBuffer)
7491 BufferEmpty();
7492
7494
7497 SetName(hname);
7498
7499 out <<" \n";
7500
7501 // Check if the histogram has equidistant X bins or not. If not, we
7502 // create an array holding the bins.
7503 if (GetXaxis()->GetXbins()->fN && GetXaxis()->GetXbins()->fArray)
7504 sxaxis = SavePrimitiveVector(out, hname + "_x", GetXaxis()->GetXbins()->fN, GetXaxis()->GetXbins()->fArray);
7505 // If the histogram is 2 or 3 dimensional, check if the histogram
7506 // has equidistant Y bins or not. If not, we create an array
7507 // holding the bins.
7508 if (fDimension > 1 && GetYaxis()->GetXbins()->fN && GetYaxis()->GetXbins()->fArray)
7509 syaxis = SavePrimitiveVector(out, hname + "_y", GetYaxis()->GetXbins()->fN, GetYaxis()->GetXbins()->fArray);
7510 // IF the histogram is 3 dimensional, check if the histogram
7511 // has equidistant Z bins or not. If not, we create an array
7512 // holding the bins.
7513 if (fDimension > 2 && GetZaxis()->GetXbins()->fN && GetZaxis()->GetXbins()->fArray)
7514 szaxis = SavePrimitiveVector(out, hname + "_z", GetZaxis()->GetXbins()->fN, GetZaxis()->GetXbins()->fArray);
7515
7516 const auto old_precision{out.precision()};
7517 constexpr auto max_precision{std::numeric_limits<double>::digits10 + 1};
7518 out << std::setprecision(max_precision);
7519
7520 out << " " << ClassName() << " *" << hname << " = new " << ClassName() << "(\"" << TString(savedName).ReplaceSpecialCppChars() << "\", \""
7521 << TString(GetTitle()).ReplaceSpecialCppChars() << "\", " << GetXaxis()->GetNbins();
7522 if (!sxaxis.IsNull())
7523 out << ", " << sxaxis << ".data()";
7524 else
7525 out << ", " << GetXaxis()->GetXmin() << ", " << GetXaxis()->GetXmax();
7526 if (fDimension > 1) {
7527 out << ", " << GetYaxis()->GetNbins();
7528 if (!syaxis.IsNull())
7529 out << ", " << syaxis << ".data()";
7530 else
7531 out << ", " << GetYaxis()->GetXmin() << ", " << GetYaxis()->GetXmax();
7532 }
7533 if (fDimension > 2) {
7534 out << ", " << GetZaxis()->GetNbins();
7535 if (!szaxis.IsNull())
7536 out << ", " << szaxis << ".data()";
7537 else
7538 out << ", " << GetZaxis()->GetXmin() << ", " << GetZaxis()->GetXmax();
7539 }
7540 out << ");\n";
7541
7543 Int_t numbins = 0, numerrors = 0;
7544
7545 std::vector<Double_t> content(fNcells), errors(save_errors ? fNcells : 0);
7546 for (Int_t bin = 0; bin < fNcells; bin++) {
7548 if (content[bin])
7549 numbins++;
7550 if (save_errors) {
7552 if (errors[bin])
7553 numerrors++;
7554 }
7555 }
7556
7557 if ((numbins < 100) && (numerrors < 100)) {
7558 // in case of few non-empty bins store them as before
7559 for (Int_t bin = 0; bin < fNcells; bin++) {
7560 if (content[bin])
7561 out << " " << hname << "->SetBinContent(" << bin << "," << content[bin] << ");\n";
7562 }
7563 if (save_errors)
7564 for (Int_t bin = 0; bin < fNcells; bin++) {
7565 if (errors[bin])
7566 out << " " << hname << "->SetBinError(" << bin << "," << errors[bin] << ");\n";
7567 }
7568 } else {
7569 if (numbins > 0) {
7571 out << " for (Int_t bin = 0; bin < " << fNcells << "; bin++)\n";
7572 out << " if (" << vectname << "[bin])\n";
7573 out << " " << hname << "->SetBinContent(bin, " << vectname << "[bin]);\n";
7574 }
7575 if (numerrors > 0) {
7577 out << " for (Int_t bin = 0; bin < " << fNcells << "; bin++)\n";
7578 out << " if (" << vectname << "[bin])\n";
7579 out << " " << hname << "->SetBinError(bin, " << vectname << "[bin]);\n";
7580 }
7581 }
7582
7584 out << std::setprecision(old_precision);
7585 SetName(savedName.Data());
7586}
7587
7588////////////////////////////////////////////////////////////////////////////////
7589/// Helper function for the SavePrimitive functions from TH1
7590/// or classes derived from TH1, eg TProfile, TProfile2D.
7591
7592void TH1::SavePrimitiveHelp(std::ostream &out, const char *hname, Option_t *option /*= ""*/)
7593{
7594 if (TMath::Abs(GetBarOffset()) > 1e-5)
7595 out << " " << hname << "->SetBarOffset(" << GetBarOffset() << ");\n";
7596 if (TMath::Abs(GetBarWidth() - 1) > 1e-5)
7597 out << " " << hname << "->SetBarWidth(" << GetBarWidth() << ");\n";
7598 if (fMinimum != -1111)
7599 out << " " << hname << "->SetMinimum(" << fMinimum << ");\n";
7600 if (fMaximum != -1111)
7601 out << " " << hname << "->SetMaximum(" << fMaximum << ");\n";
7602 if (fNormFactor != 0)
7603 out << " " << hname << "->SetNormFactor(" << fNormFactor << ");\n";
7604 if (fEntries != 0)
7605 out << " " << hname << "->SetEntries(" << fEntries << ");\n";
7606 if (!fDirectory)
7607 out << " " << hname << "->SetDirectory(nullptr);\n";
7608 if (TestBit(kNoStats))
7609 out << " " << hname << "->SetStats(0);\n";
7610 if (fOption.Length() != 0)
7611 out << " " << hname << "->SetOption(\n" << TString(fOption).ReplaceSpecialCppChars() << "\");\n";
7612
7613 // save contour levels
7615 if (ncontours > 0) {
7617 if (TestBit(kUserContour)) {
7618 std::vector<Double_t> levels(ncontours);
7619 for (Int_t bin = 0; bin < ncontours; bin++)
7622 }
7623 out << " " << hname << "->SetContour(" << ncontours;
7624 if (!vectname.IsNull())
7625 out << ", " << vectname << ".data()";
7626 out << ");\n";
7627 }
7628
7630
7631 // save attributes
7632 SaveFillAttributes(out, hname, -1, -1);
7633 SaveLineAttributes(out, hname, 1, 1, 1);
7634 SaveMarkerAttributes(out, hname, 1, 1, 1);
7635 fXaxis.SaveAttributes(out, hname, "->GetXaxis()");
7636 fYaxis.SaveAttributes(out, hname, "->GetYaxis()");
7637 fZaxis.SaveAttributes(out, hname, "->GetZaxis()");
7638
7640}
7641
7642////////////////////////////////////////////////////////////////////////////////
7643/// Save list of functions
7644/// Also can be used by TGraph classes
7645
7646void TH1::SavePrimitiveFunctions(std::ostream &out, const char *varname, TList *lst)
7647{
7648 thread_local Int_t funcNumber = 0;
7649
7650 TObjLink *lnk = lst ? lst->FirstLink() : nullptr;
7651 while (lnk) {
7652 auto obj = lnk->GetObject();
7653 obj->SavePrimitive(out, TString::Format("nodraw #%d\n", ++funcNumber).Data());
7654 TString objvarname = obj->GetName();
7656 if (obj->InheritsFrom(TF1::Class())) {
7658 objvarname = gInterpreter->MapCppName(objvarname);
7659 out << " " << objvarname << "->SetParent(" << varname << ");\n";
7660 } else if (obj->InheritsFrom("TPaveStats")) {
7661 objvarname = "ptstats";
7662 withopt = kFALSE; // pave stats preserve own draw options
7663 out << " " << objvarname << "->SetParent(" << varname << ");\n";
7664 } else if (obj->InheritsFrom("TPolyMarker")) {
7665 objvarname = "pmarker";
7666 }
7667
7668 out << " " << varname << "->GetListOfFunctions()->Add(" << objvarname;
7669 if (withopt)
7670 out << ",\"" << TString(lnk->GetOption()).ReplaceSpecialCppChars() << "\"";
7671 out << ");\n";
7672
7673 lnk = lnk->Next();
7674 }
7675}
7676
7677////////////////////////////////////////////////////////////////////////////////
7718 }
7719}
7720
7721////////////////////////////////////////////////////////////////////////////////
7722/// For axis = 1,2 or 3 returns the mean value of the histogram along
7723/// X,Y or Z axis.
7724///
7725/// For axis = 11, 12, 13 returns the standard error of the mean value
7726/// of the histogram along X, Y or Z axis
7727///
7728/// Note that the mean value/StdDev is computed using the bins in the currently
7729/// defined range (see TAxis::SetRange). By default the range includes
7730/// all bins from 1 to nbins included, excluding underflows and overflows.
7731/// To force the underflows and overflows in the computation, one must
7732/// call the static function TH1::StatOverflows(kTRUE) before filling
7733/// the histogram.
7734///
7735/// IMPORTANT NOTE: The returned value depends on how the histogram statistics
7736/// are calculated. By default, if no range has been set, the returned mean is
7737/// the (unbinned) one calculated at fill time. If a range has been set, however,
7738/// the mean is calculated using the bins in range, as described above; THIS
7739/// IS TRUE EVEN IF THE RANGE INCLUDES ALL BINS--use TAxis::SetRange(0, 0) to unset
7740/// the range. To ensure that the returned mean (and all other statistics) is
7741/// always that of the binned data stored in the histogram, call TH1::ResetStats.
7742/// See TH1::GetStats.
7743///
7744/// Return mean value of this histogram along the X axis.
7745
7746Double_t TH1::GetMean(Int_t axis) const
7747{
7748 if (axis<1 || (axis>3 && axis<11) || axis>13) return 0;
7749 Double_t stats[kNstat];
7750 for (Int_t i=4;i<kNstat;i++) stats[i] = 0;
7751 GetStats(stats);
7752 if (stats[0] == 0) return 0;
7753 if (axis<4){
7754 Int_t ax[3] = {2,4,7};
7755 return stats[ax[axis-1]]/stats[0];
7756 } else {
7757 // mean error = StdDev / sqrt( Neff )
7758 Double_t stddev = GetStdDev(axis-10);
7760 return ( neff > 0 ? stddev/TMath::Sqrt(neff) : 0. );
7761 }
7762}
7763
7764////////////////////////////////////////////////////////////////////////////////
7765/// Return standard error of mean of this histogram along the X axis.
7766///
7767/// Note that the mean value/StdDev is computed using the bins in the currently
7768/// defined range (see TAxis::SetRange). By default the range includes
7769/// all bins from 1 to nbins included, excluding underflows and overflows.
7770/// To force the underflows and overflows in the computation, one must
7771/// call the static function TH1::StatOverflows(kTRUE) before filling
7772/// the histogram.
7773///
7774/// Also note, that although the definition of standard error doesn't include the
7775/// assumption of normality, many uses of this feature implicitly assume it.
7776///
7777/// IMPORTANT NOTE: The returned value depends on how the histogram statistics
7778/// are calculated. By default, if no range has been set, the returned value is
7779/// the (unbinned) one calculated at fill time. If a range has been set, however,
7780/// the value is calculated using the bins in range, as described above; THIS
7781/// IS TRUE EVEN IF THE RANGE INCLUDES ALL BINS--use TAxis::SetRange(0, 0) to unset
7782/// the range. To ensure that the returned value (and all other statistics) is
7783/// always that of the binned data stored in the histogram, call TH1::ResetStats.
7784/// See TH1::GetStats.
7785
7787{
7788 return GetMean(axis+10);
7789}
7790
7791////////////////////////////////////////////////////////////////////////////////
7792/// Returns the Standard Deviation (Sigma).
7793/// The Sigma estimate is computed as
7794/// \f[
7795/// \sqrt{\frac{1}{N}(\sum(x_i-x_{mean})^2)}
7796/// \f]
7797/// For axis = 1,2 or 3 returns the Sigma value of the histogram along
7798/// X, Y or Z axis
7799/// For axis = 11, 12 or 13 returns the error of StdDev estimation along
7800/// X, Y or Z axis for Normal distribution
7801///
7802/// Note that the mean value/sigma is computed using the bins in the currently
7803/// defined range (see TAxis::SetRange). By default the range includes
7804/// all bins from 1 to nbins included, excluding underflows and overflows.
7805/// To force the underflows and overflows in the computation, one must
7806/// call the static function TH1::StatOverflows(kTRUE) before filling
7807/// the histogram.
7808///
7809/// IMPORTANT NOTE: The returned value depends on how the histogram statistics
7810/// are calculated. By default, if no range has been set, the returned standard
7811/// deviation is the (unbinned) one calculated at fill time. If a range has been
7812/// set, however, the standard deviation is calculated using the bins in range,
7813/// as described above; THIS IS TRUE EVEN IF THE RANGE INCLUDES ALL BINS--use
7814/// TAxis::SetRange(0, 0) to unset the range. To ensure that the returned standard
7815/// deviation (and all other statistics) is always that of the binned data stored
7816/// in the histogram, call TH1::ResetStats. See TH1::GetStats.
7817
7818Double_t TH1::GetStdDev(Int_t axis) const
7819{
7820 if (axis<1 || (axis>3 && axis<11) || axis>13) return 0;
7821
7822 Double_t x, stddev2, stats[kNstat];
7823 for (Int_t i=4;i<kNstat;i++) stats[i] = 0;
7824 GetStats(stats);
7825 if (stats[0] == 0) return 0;
7826 Int_t ax[3] = {2,4,7};
7827 Int_t axm = ax[axis%10 - 1];
7828 x = stats[axm]/stats[0];
7829 // for negative stddev (e.g. when having negative weights) - return stdev=0
7830 stddev2 = TMath::Max( stats[axm+1]/stats[0] -x*x, 0.0 );
7831 if (axis<10)
7832 return TMath::Sqrt(stddev2);
7833 else {
7834 // The right formula for StdDev error depends on 4th momentum (see Kendall-Stuart Vol 1 pag 243)
7835 // formula valid for only gaussian distribution ( 4-th momentum = 3 * sigma^4 )
7837 return ( neff > 0 ? TMath::Sqrt(stddev2/(2*neff) ) : 0. );
7838 }
7839}
7840
7841////////////////////////////////////////////////////////////////////////////////
7842/// Return error of standard deviation estimation for Normal distribution
7843///
7844/// Note that the mean value/StdDev is computed using the bins in the currently
7845/// defined range (see TAxis::SetRange). By default the range includes
7846/// all bins from 1 to nbins included, excluding underflows and overflows.
7847/// To force the underflows and overflows in the computation, one must
7848/// call the static function TH1::StatOverflows(kTRUE) before filling
7849/// the histogram.
7850///
7851/// Value returned is standard deviation of sample standard deviation.
7852/// Note that it is an approximated value which is valid only in the case that the
7853/// original data distribution is Normal. The correct one would require
7854/// the 4-th momentum value, which cannot be accurately estimated from a histogram since
7855/// the x-information for all entries is not kept.
7856///
7857/// IMPORTANT NOTE: The returned value depends on how the histogram statistics
7858/// are calculated. By default, if no range has been set, the returned value is
7859/// the (unbinned) one calculated at fill time. If a range has been set, however,
7860/// the value is calculated using the bins in range, as described above; THIS
7861/// IS TRUE EVEN IF THE RANGE INCLUDES ALL BINS--use TAxis::SetRange(0, 0) to unset
7862/// the range. To ensure that the returned value (and all other statistics) is
7863/// always that of the binned data stored in the histogram, call TH1::ResetStats.
7864/// See TH1::GetStats.
7865
7867{
7868 return GetStdDev(axis+10);
7869}
7870
7871////////////////////////////////////////////////////////////////////////////////
7872/// - For axis = 1, 2 or 3 returns skewness of the histogram along x, y or z axis.
7873/// - For axis = 11, 12 or 13 returns the approximate standard error of skewness
7874/// of the histogram along x, y or z axis
7875///
7876///Note, that since third and fourth moment are not calculated
7877///at the fill time, skewness and its standard error are computed bin by bin
7878///
7879/// IMPORTANT NOTE: The returned value depends on how the histogram statistics
7880/// are calculated. See TH1::GetMean and TH1::GetStdDev.
7881
7883{
7884
7885 if (axis > 0 && axis <= 3){
7886
7887 Double_t mean = GetMean(axis);
7888 Double_t stddev = GetStdDev(axis);
7890
7897 // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
7900 if (firstBinX == 1) firstBinX = 0;
7901 if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
7902 }
7904 if (firstBinY == 1) firstBinY = 0;
7905 if (lastBinY == fYaxis.GetNbins() ) lastBinY += 1;
7906 }
7908 if (firstBinZ == 1) firstBinZ = 0;
7909 if (lastBinZ == fZaxis.GetNbins() ) lastBinZ += 1;
7910 }
7911 }
7912
7913 Double_t x = 0;
7914 Double_t sum=0;
7915 Double_t np=0;
7916 for (Int_t binx = firstBinX; binx <= lastBinX; binx++) {
7917 for (Int_t biny = firstBinY; biny <= lastBinY; biny++) {
7918 for (Int_t binz = firstBinZ; binz <= lastBinZ; binz++) {
7919 if (axis==1 ) x = fXaxis.GetBinCenter(binx);
7920 else if (axis==2 ) x = fYaxis.GetBinCenter(biny);
7921 else if (axis==3 ) x = fZaxis.GetBinCenter(binz);
7923 np+=w;
7924 sum+=w*(x-mean)*(x-mean)*(x-mean);
7925 }
7926 }
7927 }
7928 sum/=np*stddev3;
7929 return sum;
7930 }
7931 else if (axis > 10 && axis <= 13) {
7932 //compute standard error of skewness
7933 // assume parent normal distribution use formula from Kendall-Stuart, Vol 1 pag 243, second edition
7935 return ( neff > 0 ? TMath::Sqrt(6./neff ) : 0. );
7936 }
7937 else {
7938 Error("GetSkewness", "illegal value of parameter");
7939 return 0;
7940 }
7941}
7942
7943////////////////////////////////////////////////////////////////////////////////
7944/// - For axis =1, 2 or 3 returns kurtosis of the histogram along x, y or z axis.
7945/// Kurtosis(gaussian(0, 1)) = 0.
7946/// - For axis =11, 12 or 13 returns the approximate standard error of kurtosis
7947/// of the histogram along x, y or z axis
7948////
7949/// Note, that since third and fourth moment are not calculated
7950/// at the fill time, kurtosis and its standard error are computed bin by bin
7951///
7952/// IMPORTANT NOTE: The returned value depends on how the histogram statistics
7953/// are calculated. See TH1::GetMean and TH1::GetStdDev.
7954
7956{
7957 if (axis > 0 && axis <= 3){
7958
7959 Double_t mean = GetMean(axis);
7960 Double_t stddev = GetStdDev(axis);
7962
7969 // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
7972 if (firstBinX == 1) firstBinX = 0;
7973 if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
7974 }
7976 if (firstBinY == 1) firstBinY = 0;
7977 if (lastBinY == fYaxis.GetNbins() ) lastBinY += 1;
7978 }
7980 if (firstBinZ == 1) firstBinZ = 0;
7981 if (lastBinZ == fZaxis.GetNbins() ) lastBinZ += 1;
7982 }
7983 }
7984
7985 Double_t x = 0;
7986 Double_t sum=0;
7987 Double_t np=0;
7988 for (Int_t binx = firstBinX; binx <= lastBinX; binx++) {
7989 for (Int_t biny = firstBinY; biny <= lastBinY; biny++) {
7990 for (Int_t binz = firstBinZ; binz <= lastBinZ; binz++) {
7991 if (axis==1 ) x = fXaxis.GetBinCenter(binx);
7992 else if (axis==2 ) x = fYaxis.GetBinCenter(biny);
7993 else if (axis==3 ) x = fZaxis.GetBinCenter(binz);
7995 np+=w;
7996 sum+=w*(x-mean)*(x-mean)*(x-mean)*(x-mean);
7997 }
7998 }
7999 }
8000 sum/=(np*stddev4);
8001 return sum-3;
8002
8003 } else if (axis > 10 && axis <= 13) {
8004 //compute standard error of skewness
8005 // assume parent normal distribution use formula from Kendall-Stuart, Vol 1 pag 243, second edition
8007 return ( neff > 0 ? TMath::Sqrt(24./neff ) : 0. );
8008 }
8009 else {
8010 Error("GetKurtosis", "illegal value of parameter");
8011 return 0;
8012 }
8013}
8014
8015////////////////////////////////////////////////////////////////////////////////
8016/// fill the array stats from the contents of this histogram
8017/// The array stats must be correctly dimensioned in the calling program.
8018///
8019/// ~~~ {.cpp}
8020/// stats[0] = sumw
8021/// stats[1] = sumw2
8022/// stats[2] = sumwx
8023/// stats[3] = sumwx2
8024/// ~~~
8025///
8026/// If no axis-subrange is specified (via TAxis::SetRange), the array stats
8027/// is simply a copy of the statistics quantities computed at filling time.
8028/// If a sub-range is specified, the function recomputes these quantities
8029/// from the bin contents in the current axis range.
8030///
8031/// IMPORTANT NOTE: This means that the returned statistics are context-dependent.
8032/// If TAxis::kAxisRange, the returned statistics are dependent on the binning;
8033/// otherwise, they are a copy of the histogram statistics computed at fill time,
8034/// which are unbinned by default (calling TH1::ResetStats forces them to use
8035/// binned statistics). You can reset TAxis::kAxisRange using TAxis::SetRange(0, 0).
8036///
8037/// Note that the mean value/StdDev is computed using the bins in the currently
8038/// defined range (see TAxis::SetRange). By default the range includes
8039/// all bins from 1 to nbins included, excluding underflows and overflows.
8040/// To force the underflows and overflows in the computation, one must
8041/// call the static function TH1::StatOverflows(kTRUE) before filling
8042/// the histogram.
8043
8044void TH1::GetStats(Double_t *stats) const
8045{
8046 if (fBuffer) ((TH1*)this)->BufferEmpty();
8047
8048 // Loop on bins (possibly including underflows/overflows)
8049 Int_t bin, binx;
8050 Double_t w,err;
8051 Double_t x;
8052 // identify the case of labels with extension of axis range
8053 // in this case the statistics in x does not make any sense
8054 Bool_t labelHist = ((const_cast<TAxis&>(fXaxis)).GetLabels() && fXaxis.CanExtend() );
8055 // fTsumw == 0 && fEntries > 0 is a special case when uses SetBinContent or calls ResetStats before
8056 if ( (fTsumw == 0 && fEntries > 0) || fXaxis.TestBit(TAxis::kAxisRange) ) {
8057 for (bin=0;bin<4;bin++) stats[bin] = 0;
8058
8061 // include underflow/overflow if TH1::StatOverflows(kTRUE) in case no range is set on the axis
8063 if (firstBinX == 1) firstBinX = 0;
8064 if (lastBinX == fXaxis.GetNbins() ) lastBinX += 1;
8065 }
8066 for (binx = firstBinX; binx <= lastBinX; binx++) {
8068 //w = TMath::Abs(RetrieveBinContent(binx));
8069 // not sure what to do here if w < 0
8071 err = TMath::Abs(GetBinError(binx));
8072 stats[0] += w;
8073 stats[1] += err*err;
8074 // statistics in x makes sense only for not labels histograms
8075 if (!labelHist) {
8076 stats[2] += w*x;
8077 stats[3] += w*x*x;
8078 }
8079 }
8080 // if (stats[0] < 0) {
8081 // // in case total is negative do something ??
8082 // stats[0] = 0;
8083 // }
8084 } else {
8085 stats[0] = fTsumw;
8086 stats[1] = fTsumw2;
8087 stats[2] = fTsumwx;
8088 stats[3] = fTsumwx2;
8089 }
8090}
8091
8092////////////////////////////////////////////////////////////////////////////////
8093/// Replace current statistics with the values in array stats
8094
8095void TH1::PutStats(Double_t *stats)
8096{
8097 fTsumw = stats[0];
8098 fTsumw2 = stats[1];
8099 fTsumwx = stats[2];
8100 fTsumwx2 = stats[3];
8101}
8102
8103////////////////////////////////////////////////////////////////////////////////
8104/// Reset the statistics including the number of entries
8105/// and replace with values calculated from bin content
8106///
8107/// The number of entries is set to the total bin content or (in case of weighted histogram)
8108/// to number of effective entries
8109///
8110/// \note By default, before calling this function, statistics are those
8111/// computed at fill time, which are unbinned. See TH1::GetStats.
8112
8113void TH1::ResetStats()
8114{
8115 Double_t stats[kNstat] = {0};
8116 fTsumw = 0;
8117 fEntries = 1; // to force re-calculation of the statistics in TH1::GetStats
8118 GetStats(stats);
8119 PutStats(stats);
8120 // histogram entries should include always underflows and overflows
8123 else {
8124 Double_t sumw2 = 0;
8125 Double_t * p_sumw2 = (fSumw2.fN > 0) ? &sumw2 : nullptr;
8127 // use effective entries for weighted histograms: (sum_w) ^2 / sum_w2
8129 }
8130}
8131
8132////////////////////////////////////////////////////////////////////////////////
8133/// Return the sum of all weights and optionally also the sum of weight squares
8134/// \param includeOverflow true to include under/overflows bins, false to exclude those.
8135/// \note Different from TH1::GetSumOfWeights, that always excludes those
8136
8138{
8139 if (fBuffer) const_cast<TH1*>(this)->BufferEmpty();
8140
8141 const Int_t start = (includeOverflow ? 0 : 1);
8142 const Int_t lastX = fXaxis.GetNbins() + (includeOverflow ? 1 : 0);
8143 const Int_t lastY = (fDimension > 1) ? (fYaxis.GetNbins() + (includeOverflow ? 1 : 0)) : start;
8144 const Int_t lastZ = (fDimension > 2) ? (fZaxis.GetNbins() + (includeOverflow ? 1 : 0)) : start;
8145 Double_t sum =0;
8146 Double_t sum2 = 0;
8147 for(auto binz = start; binz <= lastZ; binz++) {
8148 for(auto biny = start; biny <= lastY; biny++) {
8149 for(auto binx = start; binx <= lastX; binx++) {
8150 const auto bin = GetBin(binx, biny, binz);
8153 }
8154 }
8155 }
8156 if (sumWeightSquare) {
8157 if (fSumw2.fN > 0)
8159 else
8161 }
8162 return sum;
8163}
8164
8165////////////////////////////////////////////////////////////////////////////////
8166///Return integral of bin contents. Only bins in the bins range are considered.
8167///
8168/// By default the integral is computed as the sum of bin contents in the range.
8169/// if option "width" is specified, the integral is the sum of
8170/// the bin contents multiplied by the bin width in x.
8171
8173{
8175}
8176
8177////////////////////////////////////////////////////////////////////////////////
8178/// Return integral of bin contents in range [binx1,binx2].
8179///
8180/// By default the integral is computed as the sum of bin contents in the range.
8181/// if option "width" is specified, the integral is the sum of
8182/// the bin contents multiplied by the bin width in x.
8183
8185{
8186 double err = 0;
8187 return DoIntegral(binx1,binx2,0,-1,0,-1,err,option);
8188}
8189
8190////////////////////////////////////////////////////////////////////////////////
8191/// Return integral of bin contents in range [binx1,binx2] and its error.
8192///
8193/// By default the integral is computed as the sum of bin contents in the range.
8194/// if option "width" is specified, the integral is the sum of
8195/// the bin contents multiplied by the bin width in x.
8196/// the error is computed using error propagation from the bin errors assuming that
8197/// all the bins are uncorrelated
8198
8200{
8201 return DoIntegral(binx1,binx2,0,-1,0,-1,error,option,kTRUE);
8202}
8203
8204////////////////////////////////////////////////////////////////////////////////
8205/// Internal function compute integral and optionally the error between the limits
8206/// specified by the bin number values working for all histograms (1D, 2D and 3D)
8207
8209 Option_t *option, Bool_t doError) const
8210{
8211 if (fBuffer) ((TH1*)this)->BufferEmpty();
8212
8213 Int_t nx = GetNbinsX() + 2;
8214 if (binx1 < 0) binx1 = 0;
8215 if (binx2 >= nx || binx2 < binx1) binx2 = nx - 1;
8216
8217 if (GetDimension() > 1) {
8218 Int_t ny = GetNbinsY() + 2;
8219 if (biny1 < 0) biny1 = 0;
8220 if (biny2 >= ny || biny2 < biny1) biny2 = ny - 1;
8221 } else {
8222 biny1 = 0; biny2 = 0;
8223 }
8224
8225 if (GetDimension() > 2) {
8226 Int_t nz = GetNbinsZ() + 2;
8227 if (binz1 < 0) binz1 = 0;
8228 if (binz2 >= nz || binz2 < binz1) binz2 = nz - 1;
8229 } else {
8230 binz1 = 0; binz2 = 0;
8231 }
8232
8233 // - Loop on bins in specified range
8234 TString opt = option;
8235 opt.ToLower();
8237 if (opt.Contains("width")) width = kTRUE;
8238
8239
8240 Double_t dx = 1., dy = .1, dz =.1;
8241 Double_t integral = 0;
8242 Double_t igerr2 = 0;
8243 for (Int_t binx = binx1; binx <= binx2; ++binx) {
8244 if (width) dx = fXaxis.GetBinWidth(binx);
8245 for (Int_t biny = biny1; biny <= biny2; ++biny) {
8246 if (width) dy = fYaxis.GetBinWidth(biny);
8247 for (Int_t binz = binz1; binz <= binz2; ++binz) {
8249 Double_t dv = 0.0;
8250 if (width) {
8252 dv = dx * dy * dz;
8253 integral += RetrieveBinContent(bin) * dv;
8254 } else {
8255 integral += RetrieveBinContent(bin);
8256 }
8257 if (doError) {
8260 }
8261 }
8262 }
8263 }
8264
8265 if (doError) error = TMath::Sqrt(igerr2);
8266 return integral;
8267}
8268
8269////////////////////////////////////////////////////////////////////////////////
8270/// Statistical test of compatibility in shape between
8271/// this histogram and h2, using the Anderson-Darling 2 sample test.
8272///
8273/// The AD 2 sample test formula are derived from the paper
8274/// F.W Scholz, M.A. Stephens "k-Sample Anderson-Darling Test".
8275///
8276/// The test is implemented in root in the ROOT::Math::GoFTest class
8277/// It is the same formula ( (6) in the paper), and also shown in
8278/// [this preprint](http://arxiv.org/pdf/0804.0380v1.pdf)
8279///
8280/// Binned data are considered as un-binned data
8281/// with identical observation happening in the bin center.
8282///
8283/// \param[in] h2 Pointer to 1D histogram
8284/// \param[in] option is a character string to specify options
8285/// - "D" Put out a line of "Debug" printout
8286/// - "T" Return the normalized A-D test statistic
8287///
8288/// - Note1: Underflow and overflow are not considered in the test
8289/// - Note2: The test works only for un-weighted histogram (i.e. representing counts)
8290/// - Note3: The histograms are not required to have the same X axis
8291/// - Note4: The test works only for 1-dimensional histograms
8292
8294{
8295 Double_t advalue = 0;
8297
8298 TString opt = option;
8299 opt.ToUpper();
8300 if (opt.Contains("D") ) {
8301 printf(" AndersonDarlingTest Prob = %g, AD TestStatistic = %g\n",pvalue,advalue);
8302 }
8303 if (opt.Contains("T") ) return advalue;
8304
8305 return pvalue;
8306}
8307
8308////////////////////////////////////////////////////////////////////////////////
8309/// Same function as above but returning also the test statistic value
8310
8312{
8313 if (GetDimension() != 1 || h2->GetDimension() != 1) {
8314 Error("AndersonDarlingTest","Histograms must be 1-D");
8315 return -1;
8316 }
8317
8318 // empty the buffer. Probably we could add as an unbinned test
8319 if (fBuffer) ((TH1*)this)->BufferEmpty();
8320
8321 // use the BinData class
8324
8325 ROOT::Fit::FillData(data1, this, nullptr);
8326 ROOT::Fit::FillData(data2, h2, nullptr);
8327
8328 double pvalue;
8330
8331 return pvalue;
8332}
8333
8334////////////////////////////////////////////////////////////////////////////////
8335/// Statistical test of compatibility in shape between
8336/// this histogram and h2, using Kolmogorov test.
8337/// Note that the KolmogorovTest (KS) test should in theory be used only for unbinned data
8338/// and not for binned data as in the case of the histogram (see NOTE 3 below).
8339/// So, before using this method blindly, read the NOTE 3.
8340///
8341/// Default: Ignore under- and overflow bins in comparison
8342///
8343/// \param[in] h2 histogram
8344/// \param[in] option is a character string to specify options
8345/// - "U" include Underflows in test (also for 2-dim)
8346/// - "O" include Overflows (also valid for 2-dim)
8347/// - "N" include comparison of normalizations
8348/// - "D" Put out a line of "Debug" printout
8349/// - "M" Return the Maximum Kolmogorov distance instead of prob
8350/// - "X" Run the pseudo experiments post-processor with the following procedure:
8351/// make pseudoexperiments based on random values from the parent distribution,
8352/// compare the KS distance of the pseudoexperiment to the parent
8353/// distribution, and count all the KS values above the value
8354/// obtained from the original data to Monte Carlo distribution.
8355/// The number of pseudo-experiments nEXPT is by default 1000, and
8356/// it can be changed by specifying the option as "X=number",
8357/// for example "X=10000" for 10000 toys.
8358/// The function returns the probability.
8359/// (thanks to Ben Kilminster to submit this procedure). Note that
8360/// this option "X" is much slower.
8361///
8362/// The returned function value is the probability of test
8363/// (much less than one means NOT compatible)
8364///
8365/// Code adapted by Rene Brun from original HBOOK routine HDIFF
8366///
8367/// NOTE1
8368/// A good description of the Kolmogorov test can be seen at:
8369/// http://www.itl.nist.gov/div898/handbook/eda/section3/eda35g.htm
8370///
8371/// NOTE2
8372/// see also alternative function TH1::Chi2Test
8373/// The Kolmogorov test is assumed to give better results than Chi2Test
8374/// in case of histograms with low statistics.
8375///
8376/// NOTE3 (Jan Conrad, Fred James)
8377/// "The returned value PROB is calculated such that it will be
8378/// uniformly distributed between zero and one for compatible histograms,
8379/// provided the data are not binned (or the number of bins is very large
8380/// compared with the number of events). Users who have access to unbinned
8381/// data and wish exact confidence levels should therefore not put their data
8382/// into histograms, but should call directly TMath::KolmogorovTest. On
8383/// the other hand, since TH1 is a convenient way of collecting data and
8384/// saving space, this function has been provided. However, the values of
8385/// PROB for binned data will be shifted slightly higher than expected,
8386/// depending on the effects of the binning. For example, when comparing two
8387/// uniform distributions of 500 events in 100 bins, the values of PROB,
8388/// instead of being exactly uniformly distributed between zero and one, have
8389/// a mean value of about 0.56. We can apply a useful
8390/// rule: As long as the bin width is small compared with any significant
8391/// physical effect (for example the experimental resolution) then the binning
8392/// cannot have an important effect. Therefore, we believe that for all
8393/// practical purposes, the probability value PROB is calculated correctly
8394/// provided the user is aware that:
8395///
8396/// 1. The value of PROB should not be expected to have exactly the correct
8397/// distribution for binned data.
8398/// 2. The user is responsible for seeing to it that the bin widths are
8399/// small compared with any physical phenomena of interest.
8400/// 3. The effect of binning (if any) is always to make the value of PROB
8401/// slightly too big. That is, setting an acceptance criterion of (PROB>0.05
8402/// will assure that at most 5% of truly compatible histograms are rejected,
8403/// and usually somewhat less."
8404///
8405/// Note also that for GoF test of unbinned data ROOT provides also the class
8406/// ROOT::Math::GoFTest. The class has also method for doing one sample tests
8407/// (i.e. comparing the data with a given distribution).
8408
8410{
8411 TString opt = option;
8412 opt.ToUpper();
8413
8414 Double_t prob = 0;
8415 TH1 *h1 = (TH1*)this;
8416 if (h2 == nullptr) return 0;
8417 const TAxis *axis1 = h1->GetXaxis();
8418 const TAxis *axis2 = h2->GetXaxis();
8419 Int_t ncx1 = axis1->GetNbins();
8420 Int_t ncx2 = axis2->GetNbins();
8421
8422 // Check consistency of dimensions
8423 if (h1->GetDimension() != 1 || h2->GetDimension() != 1) {
8424 Error("KolmogorovTest","Histograms must be 1-D\n");
8425 return 0;
8426 }
8427
8428 // Check consistency in number of channels
8429 if (ncx1 != ncx2) {
8430 Error("KolmogorovTest","Histograms have different number of bins, %d and %d\n",ncx1,ncx2);
8431 return 0;
8432 }
8433
8434 // empty the buffer. Probably we could add as an unbinned test
8435 if (fBuffer) ((TH1*)this)->BufferEmpty();
8436
8437 // Check consistency in bin edges
8438 for(Int_t i = 1; i <= axis1->GetNbins() + 1; ++i) {
8439 if(!TMath::AreEqualRel(axis1->GetBinLowEdge(i), axis2->GetBinLowEdge(i), 1.E-15)) {
8440 Error("KolmogorovTest","Histograms are not consistent: they have different bin edges");
8441 return 0;
8442 }
8443 }
8444
8447 Double_t sum1 = 0, sum2 = 0;
8448 Double_t ew1, ew2, w1 = 0, w2 = 0;
8449 Int_t bin;
8450 Int_t ifirst = 1;
8451 Int_t ilast = ncx1;
8452 // integral of all bins (use underflow/overflow if option)
8453 if (opt.Contains("U")) ifirst = 0;
8454 if (opt.Contains("O")) ilast = ncx1 +1;
8455 for (bin = ifirst; bin <= ilast; bin++) {
8457 sum2 += h2->RetrieveBinContent(bin);
8458 ew1 = h1->GetBinError(bin);
8459 ew2 = h2->GetBinError(bin);
8460 w1 += ew1*ew1;
8461 w2 += ew2*ew2;
8462 }
8463 if (sum1 == 0) {
8464 Error("KolmogorovTest","Histogram1 %s integral is zero\n",h1->GetName());
8465 return 0;
8466 }
8467 if (sum2 == 0) {
8468 Error("KolmogorovTest","Histogram2 %s integral is zero\n",h2->GetName());
8469 return 0;
8470 }
8471
8472 // calculate the effective entries.
8473 // the case when errors are zero (w1 == 0 or w2 ==0) are equivalent to
8474 // compare to a function. In that case the rescaling is done only on sqrt(esum2) or sqrt(esum1)
8475 Double_t esum1 = 0, esum2 = 0;
8476 if (w1 > 0)
8477 esum1 = sum1 * sum1 / w1;
8478 else
8479 afunc1 = kTRUE; // use later for calculating z
8480
8481 if (w2 > 0)
8482 esum2 = sum2 * sum2 / w2;
8483 else
8484 afunc2 = kTRUE; // use later for calculating z
8485
8486 if (afunc2 && afunc1) {
8487 Error("KolmogorovTest","Errors are zero for both histograms\n");
8488 return 0;
8489 }
8490
8491
8492 Double_t s1 = 1/sum1;
8493 Double_t s2 = 1/sum2;
8494
8495 // Find largest difference for Kolmogorov Test
8496 Double_t dfmax =0, rsum1 = 0, rsum2 = 0;
8497
8498 for (bin=ifirst;bin<=ilast;bin++) {
8502 }
8503
8504 // Get Kolmogorov probability
8505 Double_t z, prb1=0, prb2=0, prb3=0;
8506
8507 // case h1 is exact (has zero errors)
8508 if (afunc1)
8509 z = dfmax*TMath::Sqrt(esum2);
8510 // case h2 has zero errors
8511 else if (afunc2)
8512 z = dfmax*TMath::Sqrt(esum1);
8513 else
8514 // for comparison between two data sets
8516
8518
8519 // option N to combine normalization makes sense if both afunc1 and afunc2 are false
8520 if (opt.Contains("N") && !(afunc1 || afunc2 ) ) {
8521 // Combine probabilities for shape and normalization,
8522 prb1 = prob;
8525 prb2 = TMath::Prob(chi2,1);
8526 // see Eadie et al., section 11.6.2
8527 if (prob > 0 && prb2 > 0) prob *= prb2*(1-TMath::Log(prob*prb2));
8528 else prob = 0;
8529 }
8530 // X option. Run Pseudo-experiments to determine NULL distribution of the
8531 // KS distance. We can find the probability from the number of pseudo-experiment that have a
8532 // KS distance larger than the one opbserved in the data.
8533 // We use the histogram with the largest statistics as a parent distribution for the NULL.
8534 // Note if one histogram has zero errors is considered as a function. In that case we use it
8535 // as parent distribution for the toys.
8536 //
8537 Int_t nEXPT = 1000;
8538 if (opt.Contains("X")) {
8539 // get number of pseudo-experiment of specified
8540 if (opt.Contains("X=")) {