Belle II Software development
XTFunction.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include "TProfile.h"
9#include "TCanvas.h"
10#include "TF1.h"
11#include "TH1D.h"
12#include "Math/ChebyshevPol.h"
13#include "iostream"
14
15
16namespace Belle2 {
21 namespace CDC {
22
26 // cppcheck-suppress constParameter
27 Double_t pol5pol1(Double_t* x, Double_t* par)
28 {
29 Double_t xx = x[0];
30 Double_t x6, x2;
31 Double_t f, ctp;
32 if (xx < par[6]) {
33 f = par[0] + par[1] * xx + par[2] * xx * xx + par[3] * xx * xx * xx + par[4] * xx * xx * xx * xx + par[5] * xx * xx * xx * xx * xx;
34 } else {
35 x6 = par[6];
36 x2 = xx - x6;
37 ctp = par[0] + par[1] * x6 + par[2] * x6 * x6 + par[3] * x6 * x6 * x6 + par[4] * x6 * x6 * x6 * x6 + par[5] * x6 * x6 * x6 * x6 *
38 x6;
39 f = par[7] * x2 + ctp;
40 }
41 return f;
42 }
43
47 // cppcheck-suppress constParameter
48 Double_t cheby5pol1(Double_t* x, Double_t* par)
49 {
50 Double_t xx = x[0];
51 Double_t x6, x2;
52 Double_t f, ctp;
53
54 if (xx < par[6]) {
55 f = ROOT::Math::Chebyshev5(xx, par[0], par[1], par[2], par[3], par[4], par[5]);
56 } else {
57 x6 = par[6];
58 x2 = xx - x6;
59 ctp = ROOT::Math::Chebyshev5(x6, par[0], par[1], par[2], par[3], par[4], par[5]);
60 f = par[7] * x2 + ctp;
61 }
62 return f;
63 }
64
69 class XTFunction {
70 public:
74 explicit XTFunction(TProfile* h1)
75 {
76 m_h1 = (TProfile*)h1->Clone();
77 m_h1->SetDirectory(0);
78 if (m_mode == c_Chebyshev) {
79 m_fitFunc = new TF1("xtCheb5", cheby5pol1, 0.0, 700, 8);
80 } else {
81 m_fitFunc = new TF1("xtpol5", pol5pol1, 0.0, 700, 8);
82 }
83 }
87 XTFunction(TProfile* h1, int mode)
88 {
89 m_h1 = (TProfile*)h1->Clone();
90 m_h1->SetDirectory(0);
91 m_mode = mode;
92 if (m_mode == c_Chebyshev) {
93 m_fitFunc = new TF1("xtCheb5", cheby5pol1, 0.0, 700, 8);
94 } else {
95 m_fitFunc = new TF1("xtpol5", pol5pol1, 0.0, 700, 8);
96 }
97
98 }
99
103 XTFunction(TH1F* h1, int mode)
104 {
105 m_h1 = (TProfile*)h1->Clone();
106 m_h1->SetDirectory(0);
107 m_mode = mode;
108 if (m_mode == c_Chebyshev) {
109 m_fitFunc = new TF1("xtCheb5", cheby5pol1, 0.0, 700, 8);
110 } else {
111 m_fitFunc = new TF1("xtpol5", pol5pol1, 0.0, 700, 8);
112 }
113 }
114
119 m_h1(x.m_h1),
120 m_mode(x.m_mode),
121 m_debug(x.m_debug),
122 m_draw(x.m_draw),
126 m_Prob(x.m_Prob),
127 m_tmin(x.m_tmin),
128 m_tmax(x.m_tmax)
129 {
130 m_fitFunc = (TF1*) x.m_fitFunc->Clone();
131 for (int i = 0; i < 8; ++i) {
132 m_XTParam[i] = x.m_XTParam[i];
133 m_FittedXTParams[i] = x.m_XTParam[i];
134 }
135 }
136
141 {
142 if (this != &x) {
143 m_h1 = x.m_h1;
144 m_fitFunc = x.m_fitFunc;
145 m_mode = x.m_mode;
146 m_debug = x.m_debug;
147 m_draw = x.m_draw;
148 m_bField = x.m_bField;
149 m_minRequiredEntry = x.m_minRequiredEntry;
150 m_fitflag = x.m_fitflag;
151 m_Prob = x.m_Prob;
152 m_tmin = x.m_tmin;
153 m_tmax = x.m_tmax;
154
155 for (int i = 0; i < 8; ++i) {
156 m_XTParam[i] = x.m_XTParam[i];
157 m_FittedXTParams[i] = x.m_XTParam[i];
158 }
159 }
160 return *this;
161 }
162
163
167 void setP6(double p6)
168 {
169 m_XTParam[6] = p6;
170 }
171
175 bool isValid()
176 {
177 if (m_fitFunc->IsValid() == true) {
178 return true;
179 } else {
180 return false;
181 }
182 }
183
189 void setMode(int mode)
190 {
191 m_mode = mode;
192 }
196 void setBField(bool bfield) {m_bField = bfield;}
197
201 void setXTParams(const double p[8])
202 {
203 for (int i = 0; i < 8; ++i) {m_XTParam[i] = p[i];}
204 m_tmax = p[6] + 50;
205 }
209 void setXTParams(double p0, double p1, double p2, double p3,
210 double p4, double p5, double p6, double p7)
211 {
212 m_XTParam[0] = p0; m_XTParam[1] = p1; m_XTParam[2] = p2;
213 m_XTParam[3] = p3; m_XTParam[4] = p4; m_XTParam[5] = p5;
214 m_XTParam[6] = p6; m_XTParam[7] = p7;
215 m_tmax = p6 + 50;
216 }
217
221 void setFitRange(double tmin, double tmax)
222 {
223 m_tmin = tmin;
224 m_tmax = tmax;
225 }
230 {
231 m_minRequiredEntry = min;
232 }
236 void setDebug(bool debug)
237 {
238 m_debug = debug;
239 }
244 {
245 return m_fitflag;
246 }
247
251 double getProb()
252 {
253 return m_Prob;
254 }
258 void getFittedXTParams(double pa[8])
259 {
260 for (int i = 0; i < 8; ++i) {pa[i] = m_FittedXTParams[i];}
261 }
266 {
267 return m_fitFunc;
268 }
272 TProfile* getFittedHisto() {return m_h1;}
273
277 void fitXT()
278 {
279 if (m_mode == c_Polynomial) {
280 FitPol5();
281 } else if (m_mode == c_Chebyshev) {
282 FitChebyshev();
283 } else {
284 B2ERROR("Undefined fitting function");
285 }
286 }
287
291 void FitPol5();
295 void FitChebyshev();
300 bool validate();
301 private:
302
303 TProfile* m_h1;
306 // TF1* xtpol5 = new TF1("xtpol5", pol5pol1, 0.0, 700, 8); /**< 5th order polynomial function*/
307 // TF1* xtCheb5 = new TF1("xtCheb5", Cheb5pol1, 0.0, 700, 8); /**< 5th order Cheb. polynomial function*/
308
309 int m_mode = c_Chebyshev;
310 bool m_debug = true;
311 bool m_draw = false;
312 bool m_bField = true;
314 double m_XTParam[8] = {};
315 double m_FittedXTParams[8] = {};
325 int m_fitflag = 0;
326 double m_Prob = 0;
327 double m_tmin = 20;
328 double m_tmax = m_XTParam[6] + 50;
329 };
330
332 {
333 if (m_mode != c_Polynomial) {
334 B2ERROR("Fitting function is wrong");
335 }
336 double max_dif = 0.12;
337 double max_dif2 = 0.05;
338 double par[8];
339 m_h1->Fit("pol1", "MQ", "", m_tmin, 50);
340 TF1* f1 = (TF1*)m_h1->GetFunction("pol1");
341 double p0 = f1->GetParameter(0);
342 double p1 = f1->GetParameter(1);
343 double f10 = f1->Eval(10);
344 /****************************/
345 int in = 0; /*how many time inner part change fit limit*/
346 int out = 0; /*how many time outer part change fit limit*/
347 m_fitFunc->SetParameters(p0, p1, 0, 0, 0, 0, m_XTParam[6], 0);
348 double p6default = m_XTParam[6];
349 if (m_bField) {
350 m_fitFunc->SetParLimits(7, 0.0, 0.001);
351 m_fitFunc->SetParLimits(1, 0.0, 0.01);
352 } else {
353 m_fitFunc->SetParLimits(7, 0.0, 0.01);
354 m_fitFunc->SetParLimits(1, 0.0, 0.01);
355 }
356
357 for (int i = 0; i < 10; ++i) {
358 m_fitflag = 1;
359 std::cout << "Fitting" << std::endl;
360 double stat = m_h1->Fit(m_fitFunc, "M", "0", m_tmin, m_tmax);
361 m_fitFunc->GetParameters(par);
362
363 /*Eval outer region,*/
364 double fp6 = m_fitFunc->Eval(par[6]);
365 double fbehindp6 = m_fitFunc->Eval(par[6] - 12) - 0.01;
366 if (fp6 < fbehindp6 || fp6 > 1) { /*may be change to good value*/
367 m_fitflag = 2;
368 out += 1;
369 m_fitFunc->SetParameters(p0, p1, 0, 0, 0, 0, p6default, 0);
370 m_fitFunc->SetParLimits(6, p6default - 10, p6default + 10 - out / 2);
371 m_tmax += 2;
372 if (m_tmax < p6default + 30) {
373 m_tmax = p6default + 30;
374 }
375 }
376 /* EVal inner region*/
377 /* compare p0 of linear fit vs p0 of xtfun fit and eval point t=10)*/
378 if (fabs(par[0] - p0) > max_dif || fabs(f10 - m_fitFunc->Eval(10)) > max_dif2) {
379 m_fitflag = 3;
380 if (i == 9) std::cout << "ERROR XT FIT inner part" << std::endl;
381 in += 1;
382 m_fitFunc->SetParameters(p0, p1, 0, 0, 0, 0, p6default, 0);
383 m_fitFunc->SetParLimits(1, 0, 0.08);
384 m_tmin -= 0.5;
385
386 if (m_tmin < 14) {
387 m_tmin = 14; std::cout << "ERROR: tmin so small, fit iter: " << std::endl;
388 }
389 }
390
391 if (stat == 0) {
392 m_fitflag = 0;
393 if (m_debug) {std::cout << "FIT Failure; Layer: " << std::endl;}
394 }
395
396 if (m_debug) {printf("P6default= %3.2f, p6 fit = %3.2f", p6default, par[6]);}
397
398 if (m_fitflag == 1) {
399 if (m_debug) std::cout << "Fit success" << std::endl;
400 m_fitFunc->GetParameters(m_FittedXTParams);
401 m_Prob = m_fitFunc->GetProb();
402 break;
403 }
404
405 } //end loop of fitting
406 if (m_debug) B2INFO("Number of failures due to inner (outer) regions " << in << "(" << out << ")");
407
408 if (m_draw) {
409 TString hname = m_h1->GetName();
410 TString name = hname + ".pdf";
411 TCanvas* c1 = new TCanvas("c1", "", 800, 600);
412 m_h1->Draw();
413 m_fitFunc->SetLineColor(kBlack);
414 m_fitFunc->DrawF1(0, 400, "same");
415 c1->SaveAs(name);
416 }
417 }
418
420 {
421
422 const double p6 = m_fitFunc->GetParameter(6);
423 if (fabs(m_fitFunc->Eval(0)) > 0.3) {
424 B2WARNING("Bad xt function");
425 m_fitflag = 0;
426 return false;
427 } else if (p6 < 50.0) {
428 B2WARNING("Unrealistic p6");
429 m_fitflag = 0;
430 return false;
431 } else {
432 return true;
433 }
434 }
435
437 {
438 if (m_mode != c_Chebyshev) {
439 B2ERROR("Fitting function is wrong");
440 }
441
442 if (m_h1->GetEntries() < m_minRequiredEntry) {
443 m_fitflag = -1;
444 return;
445 }
446 // m_tmax = m_XTParam[6] + 100;
447 //xtCheb5->SetParameters(0.0, 0.005, 0., 0., 0., 0., m_XTParam[6], 0.001);
448 double par[8] = {0.0};
449 m_fitFunc->SetParLimits(7, 0., 0.001);
450 int fitresult = m_h1->Fit("chebyshev5", "QME", "", m_tmin, m_XTParam[6]);
451 if (fitresult >= 0) {
452 m_h1->GetFunction("chebyshev5")->GetParameters(par);
453 m_fitFunc->SetParameters(par[0], par[1], par[2], par[3], par[4], par[5], m_XTParam[6], 0.000);
454 }
455 double stat;
456 for (int i = 0; i < 10; ++i) {
457 stat = m_h1->Fit(m_fitFunc, "MQ", "0", m_tmin, m_tmax);
458 if (stat == 0) {
459 m_fitFunc->SetParameters(par[0], par[1], par[2], par[3], par[4], par[5], m_XTParam[6] - 20, 0.000);
460 m_tmax -= 10;
461 continue;
462 }
463 m_fitFunc->GetParameters(par);
464 if (par[1] < 0) { // negative c1
465 // std::cout << " neg c1 converted" << std::endl;
466 par[1] *= -1.0;
467 m_fitFunc->SetParLimits(1, 0., 0.01);
468 m_tmin += 10.0;
469 continue;
470 }
471
472 /*Eval outer region,*/
473 double fp6 = m_fitFunc->Eval(par[6]);
474 double fbehindp6 = m_fitFunc->Eval(par[6] - 10) - 0.005;
475 if (fp6 < fbehindp6 || fp6 > 1) { /*may be change to good value*/
476 m_fitflag = 2;
477 // out += 1;
478 m_fitFunc->SetParameters(par[0], par[1], par[2], par[3], par[4], par[5], par[6] - 20, 0.000);
479 m_fitFunc->SetParLimits(6, par[6] - 50, par[6] - 10);
480 m_tmax -= 10;
481 // if (m_tmax < p6default + 30) {
482 // m_tmax = p6default + 30;
483 // }
484 } else {
485 break;
486 }
487 // m_tmax +=10;
488 //if (stat != 0) break;
489 }
490 if (par[1] > 0) {
491 m_fitFunc->GetParameters(m_FittedXTParams);
492 m_Prob = m_fitFunc->GetProb();
493 }
494 if (stat == 0)
495 m_fitflag = 0;
496 else
497 m_fitflag = 1;
498 // m_fitFunc->DrawF1(0,400,"same");
499 if (m_draw) {
500 TString hname = m_h1->GetName();
501 TString name = hname + ".pdf";
502 TCanvas* c1 = new TCanvas("c1", "", 800, 600);
503 m_h1->Draw();
504 m_fitFunc->SetLineColor(kBlack);
505 m_fitFunc->DrawF1(0, 400, "same");
506 c1->SaveAs(name);
507 }
508 }
509 }
511}
Class to perform fitting for each xt function.
Definition: XTFunction.h:69
void setXTParams(const double p[8])
Set Parameters for fit.
Definition: XTFunction.h:201
int m_minRequiredEntry
Minimum entry required for each histo.
Definition: XTFunction.h:313
double m_FittedXTParams[8]
Fitted parameters.
Definition: XTFunction.h:315
bool validate()
Validate the xt has proper shape.
Definition: XTFunction.h:419
void setP6(double p6)
Set Parameter 6 for polynomia fit.
Definition: XTFunction.h:167
void setFitRange(double tmin, double tmax)
Set Fit range.
Definition: XTFunction.h:221
void FitChebyshev()
Fit xt histogram incase 5th order Chebeshev polynomial is used.
Definition: XTFunction.h:436
XTFunction & operator=(const XTFunction &x)
Assignment operator.
Definition: XTFunction.h:140
double getProb()
Get the chi2 probability.
Definition: XTFunction.h:251
TF1 * getXTFunction()
Get XT function.
Definition: XTFunction.h:265
TF1 * m_fitFunc
Fit function.
Definition: XTFunction.h:304
int m_mode
XT mode, 0 is for 5th order polynomial, 1 is Chebshev polynomial.
Definition: XTFunction.h:309
int m_fitflag
Fit Flag =-1: low statitic =1: good =0: Fit failure =2: Error Outer =3: Error Inner part;.
Definition: XTFunction.h:325
bool m_debug
Print debug durring fitting or not.
Definition: XTFunction.h:310
XTFunction(TProfile *h1, int mode)
Initialized with TProfile histogram and mode.
Definition: XTFunction.h:87
XTFunction(TH1F *h1, int mode)
Initialized with TH1D histogram and mode.
Definition: XTFunction.h:103
void setDebug(bool debug)
Set Debug.
Definition: XTFunction.h:236
double m_Prob
Chi2 prob of fitting.
Definition: XTFunction.h:326
void fitXT()
Do fitting.
Definition: XTFunction.h:277
bool m_bField
With magnetic field or not.
Definition: XTFunction.h:312
void setMode(int mode)
Set XT mode.
Definition: XTFunction.h:189
void setBField(bool bfield)
set to use BField
Definition: XTFunction.h:196
void setSmallestEntryRequired(int min)
Set minimum number of entry required for fit.
Definition: XTFunction.h:229
double m_tmin
lower boundary of fit range
Definition: XTFunction.h:327
XTFunction(const XTFunction &x)
Copy constructor.
Definition: XTFunction.h:118
double m_tmax
upper boundary of fit range
Definition: XTFunction.h:328
void getFittedXTParams(double pa[8])
get fit parameters.
Definition: XTFunction.h:258
void setXTParams(double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7)
Set Initial parameters for fitting.
Definition: XTFunction.h:209
TProfile * m_h1
Histogram of xt relation.
Definition: XTFunction.h:303
bool m_draw
Draw and store png plot of each histo or not.
Definition: XTFunction.h:311
XTFunction(TProfile *h1)
Initialized with TProfile histogram.
Definition: XTFunction.h:74
double m_XTParam[8]
Parameter fo xt.
Definition: XTFunction.h:314
TProfile * getFittedHisto()
Get histogram.
Definition: XTFunction.h:272
void FitPol5()
Fit xt histogram incase 5th order polynomial is used.
Definition: XTFunction.h:331
int getFitStatus()
get fitted flag.
Definition: XTFunction.h:243
bool isValid()
Is valid.
Definition: XTFunction.h:175
Double_t cheby5pol1(Double_t *x, Double_t *par)
helper function to initialize xt function with 5th order Chebshev Polynomial + linear.
Definition: XTFunction.h:48
Double_t pol5pol1(Double_t *x, Double_t *par)
helper function to initialize xt function with 5th order polynomial + linear.
Definition: XTFunction.h:27
Abstract base class for different kinds of events.