Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TestBinomial.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_fit
3/// \notebook -js
4/// Perform a fit to a set of data with binomial errors
5/// like those derived from the division of two histograms.
6/// Three different fits are performed and compared:
7///
8/// - simple least square fit to the divided histogram obtained
9/// from TH1::Divide with option b
10/// - least square fit to the TGraphAsymmErrors obtained from
11/// TGraphAsymmErrors::BayesDivide
12/// - likelihood fit performed on the dividing histograms using
13/// binomial statistics with the TBinomialEfficiency class
14///
15/// The first two methods are biased while the last one is statistical correct.
16/// Running the script passing an integer value n larger than 1, n fits are
17/// performed and the bias are also shown.
18/// To run the script :
19///
20/// to show the bias performing 100 fits for 1000 events per "experiment"
21///
22/// ~~~{.cpp}
23/// root[0]: .x TestBinomial.C+
24/// ~~~
25///
26/// to show the bias performing 100 fits for 1000 events per "experiment"
27///
28/// ~~~{.cpp}
29/// .x TestBinomial.C+(100, 1000)
30/// ~~~
31///
32/// \macro_image
33/// \macro_output
34/// \macro_code
35///
36/// \author Rene Brun
37
39#include <TVirtualFitter.h>
40#include <TH1.h>
41#include <TRandom3.h>
42#include <TF1.h>
43#include <TFitResult.h>
44#include <TStyle.h>
45#include <TCanvas.h>
46#include <TLegend.h>
47#include <TPaveStats.h>
48#include <TGraphErrors.h>
49#include <TObjArray.h>
50#include <HFitInterface.h>
51#include <Fit/BinData.h>
53
54#include <cassert>
55#include <iostream>
56
57void TestBinomial(int nloop = 100, int nevts = 100, bool plot = false, bool debug = false, int seed = 111)
58{
60 gStyle->SetLineWidth(2.0);
61 gStyle->SetOptStat(11);
62
63 TObjArray hbiasNorm;
64 hbiasNorm.Add(new TH1D("h0Norm", "Bias Histogram fit",100,-5,5));
65 hbiasNorm.Add(new TH1D("h1Norm","Bias Binomial fit",100,-5,5));
66 TObjArray hbiasThreshold;
67 hbiasThreshold.Add(new TH1D("h0Threshold", "Bias Histogram fit",100,-5,5));
68 hbiasThreshold.Add(new TH1D("h1Threshold","Bias Binomial fit",100,-5,5));
69 TObjArray hbiasWidth;
70 hbiasWidth.Add(new TH1D("h0Width", "Bias Histogram fit",100,-5,5));
71 hbiasWidth.Add(new TH1D("h1Width","Bias Binomial fit",100,-5,5));
72 TH1D* hChisquared = new TH1D("hChisquared",
73 "#chi^{2} probability (Baker-Cousins)", 200, 0.0, 1.0);
74
77
78 // Note: in order to be able to use TH1::FillRandom() to generate
79 // pseudo-experiments, we use a trick: generate "selected"
80 // and "non-selected" samples independently. These are
81 // statistically independent and therefore can be safely
82 // added to yield the "before selection" sample.
83
84
85 // Define (arbitrarily?) a distribution of input events.
86 // Here: assume a x^(-2) distribution. Boundaries: [10, 100].
87
88 double xmin =10, xmax = 100;
89 TH1D* hM2D = new TH1D("hM2D", "x^(-2) denominator distribution",
90 45, xmin, xmax);
91 TH1D* hM2N = new TH1D("hM2N", "x^(-2) numerator distribution",
92 45, xmin, xmax);
93 TH1D* hM2E = new TH1D("hM2E", "x^(-2) efficiency",
94 45, xmin, xmax);
95
96 TF1* fM2D = new TF1("fM2D", "(1-[0]/(1+exp(([1]-x)/[2])))/(x*x)",
97 xmin, xmax);
98 TF1* fM2N = new TF1("fM2N", "[0]/(1+exp(([1]-x)/[2]))/(x*x)",
99 xmin, xmax);
100 TF1* fM2Fit = new TF1("fM2Fit", "[0]/(1+exp(([1]-x)/[2]))",
101 xmin, xmax);
102 TF1* fM2Fit2 = nullptr;
103
104 TRandom3 rb(seed);
105
106 // First try: use a single set of parameters.
107 // For each try, we need to find the overall normalization
108
109 double normalization = 0.80;
110 double threshold = 25.0;
111 double width = 5.0;
112
113 fM2D->SetParameter(0, normalization);
114 fM2D->SetParameter(1, threshold);
115 fM2D->SetParameter(2, width);
116 fM2N->SetParameter(0, normalization);
117 fM2N->SetParameter(1, threshold);
118 fM2N->SetParameter(2, width);
119 double integralN = fM2N->Integral(xmin, xmax);
120 double integralD = fM2D->Integral(xmin, xmax);
121 double fracN = integralN/(integralN+integralD);
122 int nevtsN = rb.Binomial(nevts, fracN);
123 int nevtsD = nevts - nevtsN;
124
125 std::cout << nevtsN << " " << nevtsD << std::endl;
126
127 gStyle->SetOptFit(1111);
128
129 // generate many times to see the bias
130 for (int iloop = 0; iloop < nloop; ++iloop) {
131
132 // generate pseudo-experiments
133 hM2D->Reset();
134 hM2N->Reset();
135 hM2D->FillRandom(fM2D->GetName(), nevtsD);
136 hM2N->FillRandom(fM2N->GetName(), nevtsN);
137 hM2D->Add(hM2N);
138
139 // construct the "efficiency" histogram
140 hM2N->Sumw2();
141 hM2E->Divide(hM2N, hM2D, 1, 1, "b");
142
143 // Fit twice, using the same fit function.
144 // In the first (standard) fit, initialize to (arbitrary) values.
145 // In the second fit, use the results from the first fit (this
146 // makes it easier for the fit -- but the purpose here is not to
147 // show how easy or difficult it is to obtain results, but whether
148 // the CORRECT results are obtained or not!).
149
150 fM2Fit->SetParameter(0, 0.5);
151 fM2Fit->SetParameter(1, 15.0);
152 fM2Fit->SetParameter(2, 2.0);
153 fM2Fit->SetParError(0, 0.1);
154 fM2Fit->SetParError(1, 1.0);
155 fM2Fit->SetParError(2, 0.2);
156 TH1 * hf = fM2Fit->GetHistogram();
157 // std::cout << "Function values " << std::endl;
158 // for (int i = 1; i <= hf->GetNbinsX(); ++i)
159 // std::cout << hf->GetBinContent(i) << " ";
160 // std::cout << std::endl;
161
162 TCanvas* cEvt;
163 if (plot) {
164 cEvt = new TCanvas(Form("cEnv%d",iloop),
165 Form("plots for experiment %d", iloop),
166 1000, 600);
167 cEvt->Divide(1,2);
168 cEvt->cd(1);
169 hM2D->DrawCopy("HIST");
170 hM2N->SetLineColor(kRed);
171 hM2N->DrawCopy("HIST SAME");
172 cEvt->cd(2);
173 }
174 for (int fit = 0; fit < 2; ++fit) {
175 int status = 0;
176 switch (fit) {
177 case 0:
178 {
179 // TVirtualPad * pad = gPad;
180 // new TCanvas();
181 // fM2Fit->Draw();
182 // gPad = pad;
183 TString optFit = "RN";
184 if (debug) optFit += TString("SV");
185 TFitResultPtr res = hM2E->Fit(fM2Fit, optFit);
186 if (plot) {
187 hM2E->DrawCopy("E");
188 fM2Fit->SetLineColor(kBlue);
189 fM2Fit->DrawCopy("SAME");
190 }
191 if (debug) res->Print();
192 status = res;
193 break;
194 }
195 case 1:
196 {
197 // if (fM2Fit2) delete fM2Fit2;
198 // fM2Fit2 = dynamic_cast<TF1*>(fM2Fit->Clone("fM2Fit2"));
199 fM2Fit2 = fM2Fit; // do not clone/copy the function
200 if (fM2Fit2->GetParameter(0) >= 1.0)
201 fM2Fit2->SetParameter(0, 0.95);
202 fM2Fit2->SetParLimits(0, 0.0, 1.0);
203
204 // TVirtualPad * pad = gPad;
205 // new TCanvas();
206 // fM2Fit2->Draw();
207 // gPad = pad;
208
209 TBinomialEfficiencyFitter bef(hM2N, hM2D);
210 TString optFit = "RI S";
211 if (debug) optFit += TString("V");
212 TFitResultPtr res = bef.Fit(fM2Fit2,optFit);
213 status = res;
214 if (status !=0) {
215 std::cerr << "Error performing binomial efficiency fit, result = "
216 << status << std::endl;
217 res->Print();
218 continue;
219 }
220 if (plot) {
221 fM2Fit2->SetLineColor(kRed);
222 fM2Fit2->DrawCopy("SAME");
223
224 bool confint = (status == 0);
225 if (confint) {
226 // compute confidence interval on fitted function
227 auto htemp = fM2Fit2->GetHistogram();
228 ROOT::Fit::BinData xdata;
229 ROOT::Fit::FillData(xdata, fM2Fit2->GetHistogram() );
230 TGraphErrors gr(fM2Fit2->GetHistogram() );
231 res->GetConfidenceIntervals(xdata, gr.GetEY(), 0.68, false);
232 gr.SetFillColor(6);
233 gr.SetFillStyle(3005);
234 gr.DrawClone("4 same");
235 }
236 }
237 if (debug) {
238 res->Print();
239 }
240 }
241 }
242
243 if (status != 0) break;
244
245 double fnorm = fM2Fit->GetParameter(0);
246 double enorm = fM2Fit->GetParError(0);
247 double fthreshold = fM2Fit->GetParameter(1);
248 double ethreshold = fM2Fit->GetParError(1);
249 double fwidth = fM2Fit->GetParameter(2);
250 double ewidth = fM2Fit->GetParError(2);
251 if (fit == 1) {
252 fnorm = fM2Fit2->GetParameter(0);
253 enorm = fM2Fit2->GetParError(0);
254 fthreshold = fM2Fit2->GetParameter(1);
255 ethreshold = fM2Fit2->GetParError(1);
256 fwidth = fM2Fit2->GetParameter(2);
257 ewidth = fM2Fit2->GetParError(2);
258 hChisquared->Fill(fM2Fit2->GetProb());
259 }
260
261 TH1D* h = dynamic_cast<TH1D*>(hbiasNorm[fit]);
262 h->Fill((fnorm-normalization)/enorm);
263 h = dynamic_cast<TH1D*>(hbiasThreshold[fit]);
264 h->Fill((fthreshold-threshold)/ethreshold);
265 h = dynamic_cast<TH1D*>(hbiasWidth[fit]);
266 h->Fill((fwidth-width)/ewidth);
267 }
268 }
269
270
271 TCanvas* c1 = new TCanvas("c1",
272 "Efficiency fit biases",10,10,1000,800);
273 c1->Divide(2,2);
274
275 TH1D *h0, *h1;
276 c1->cd(1);
277 h0 = dynamic_cast<TH1D*>(hbiasNorm[0]);
278 h0->Draw("HIST");
279 h1 = dynamic_cast<TH1D*>(hbiasNorm[1]);
281 h1->Draw("HIST SAMES");
282 TLegend* l1 = new TLegend(0.1, 0.75, 0.5, 0.9,
283 "plateau parameter", "ndc");
284 l1->AddEntry(h0, Form("histogram: mean = %4.2f RMS = \
285 %4.2f", h0->GetMean(), h0->GetRMS()), "l");
286 l1->AddEntry(h1, Form("binomial : mean = %4.2f RMS = \
287 %4.2f", h1->GetMean(), h1->GetRMS()), "l");
288 l1->Draw();
289
290 c1->cd(2);
291 h0 = dynamic_cast<TH1D*>(hbiasThreshold[0]);
292 h0->Draw("HIST");
293 h1 = dynamic_cast<TH1D*>(hbiasThreshold[1]);
295 h1->Draw("HIST SAMES");
296 TLegend* l2 = new TLegend(0.1, 0.75, 0.5, 0.9,
297 "threshold parameter", "ndc");
298 l2->AddEntry(h0, Form("histogram: mean = %4.2f RMS = \
299 %4.2f", h0->GetMean(), h0->GetRMS()), "l");
300 l2->AddEntry(h1, Form("binomial : mean = %4.2f RMS = \
301 %4.2f", h1->GetMean(), h1->GetRMS()), "l");
302 l2->Draw();
303
304 c1->cd(3);
305 h0 = dynamic_cast<TH1D*>(hbiasWidth[0]);
306 h0->Draw("HIST");
307 h1 = dynamic_cast<TH1D*>(hbiasWidth[1]);
309 h1->Draw("HIST SAMES");
310 TLegend* l3 = new TLegend(0.1, 0.75, 0.5, 0.9, "width parameter", "ndc");
311 l3->AddEntry(h0, Form("histogram: mean = %4.2f RMS = \
312 %4.2f", h0->GetMean(), h0->GetRMS()), "l");
313 l3->AddEntry(h1, Form("binomial : mean = %4.2f RMS = \
314 %4.2f", h1->GetMean(), h1->GetRMS()), "l");
315 l3->Draw();
316
317 c1->cd(4);
318 hChisquared->Draw("HIST");
319}
320
321int main() {
322 TestBinomial();
323}
int main()
Definition Prototype.cxx:12
#define h(i)
Definition RSha256.hxx:106
@ kRed
Definition Rtypes.h:66
@ kBlue
Definition Rtypes.h:66
winID h TVirtualViewer3D TVirtualGLPainter char TVirtualGLPainter plot
Option_t Option_t width
float xmin
float xmax
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition BinData.h:52
void GetConfidenceIntervals(unsigned int n, unsigned int stride1, unsigned int stride2, const double *x, double *ci, double cl=0.95, bool norm=false) const
get confidence intervals for an array of n points x.
static void SetDefaultIntegrator(const char *name)
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
Binomial fitter for the division of two histograms.
The Canvas class.
Definition TCanvas.h:23
TVirtualPad * cd(Int_t subpadnumber=0) override
Set current canvas & pad.
Definition TCanvas.cxx:716
1-Dim function class
Definition TF1.h:233
virtual void SetParError(Int_t ipar, Double_t error)
Set error for parameter number ipar.
Definition TF1.cxx:3479
virtual TH1 * GetHistogram() const
Return a pointer to the histogram used to visualise the function Note that this histogram is managed ...
Definition TF1.cxx:1586
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1932
virtual Double_t GetProb() const
Return the fit probability.
Definition TF1.cxx:1957
virtual Double_t Integral(Double_t a, Double_t b, Double_t epsrel=1.e-12)
IntegralOneDim or analytical integral.
Definition TF1.cxx:2531
virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
Set lower and upper limits for parameter ipar.
Definition TF1.cxx:3507
virtual TF1 * DrawCopy(Option_t *option="") const
Draw a copy of this function with its current attributes.
Definition TF1.cxx:1365
virtual void SetParameter(Int_t param, Double_t value)
Definition TF1.h:660
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:538
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
void Print(Option_t *option="") const override
Print result of the fit, by default chi2, parameter values and errors.
A TGraphErrors is a TGraph with error bars.
Double_t * GetEY() const override
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:669
void Reset(Option_t *option="") override
Reset.
Definition TH1.cxx:10459
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7503
virtual void FillRandom(const char *fname, Int_t ntimes=5000, TRandom *rng=nullptr)
Fill histogram following distribution in function fname.
Definition TH1.cxx:3519
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Double_t xmin=0, Double_t xmax=0)
Fit histogram with function fname.
Definition TH1.cxx:3898
virtual Bool_t Add(TF1 *h1, Double_t c1=1, Option_t *option="")
Performs the operation: this = this + c1*f1 if errors are defined (see TH1::Sumw2),...
Definition TH1.cxx:826
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3344
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3066
Double_t GetRMS(Int_t axis=1) const
This function returns the Standard Deviation (Sigma) of the distribution not the Root Mean Square (RM...
Definition TH1.h:319
virtual TH1 * DrawCopy(Option_t *option="", const char *name_postfix="_copy") const
Copy this histogram and Draw in the current pad.
Definition TH1.cxx:3113
virtual Bool_t Divide(TF1 *f1, Double_t c1=1)
Performs the operation: this = this/(c1*f1) if errors are defined (see TH1::Sumw2),...
Definition TH1.cxx:2840
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:8988
This class displays a legend box (TPaveText) containing several legend entries.
Definition TLegend.h:23
TLegendEntry * AddEntry(const TObject *obj, const char *label="", Option_t *option="lpf")
Add a new entry to this legend.
Definition TLegend.cxx:317
void Draw(Option_t *option="") override
Draw this legend with its current attributes.
Definition TLegend.cxx:422
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:31
void Add(TObject *obj) override
Definition TObjArray.h:68
virtual TObject * DrawClone(Option_t *option="") const
Draw a clone of this object in the current selected pad with: gROOT->SetSelectedPad(c1).
Definition TObject.cxx:299
void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0) override
Automatic pad generation by division.
Definition TPad.cxx:1153
Random number generator class based on M.
Definition TRandom3.h:27
Basic string class.
Definition TString.h:139
void SetOptStat(Int_t stat=1)
The type of information printed in the histogram statistics box can be selected via the parameter mod...
Definition TStyle.cxx:1636
void SetOptFit(Int_t fit=1)
The type of information about fit parameters printed in the histogram statistics box can be selected ...
Definition TStyle.cxx:1589
static void SetDefaultFitter(const char *name="")
static: set name of default fitter
return c1
Definition legend1.C:41
TGraphErrors * gr
Definition legend1.C:25
TH1F * h1
Definition legend1.C:5
fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, criterion, save_best, scheduler)
void FillData(BinData &dv, const TH1 *hist, TF1 *func=nullptr)
fill the data vector from a TH1.