Belle II Software  release-08-01-10
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 
16 namespace 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 
118  XTFunction(const XTFunction& x) :
119  m_h1(x.m_h1),
120  m_mode(x.m_mode),
121  m_debug(x.m_debug),
122  m_draw(x.m_draw),
123  m_bField(x.m_bField),
125  m_fitflag(x.m_fitflag),
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;
304  TF1* m_fitFunc;
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;
313  int m_minRequiredEntry = 800;
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
double getProb()
Get the chi2 probability.
Definition: XTFunction.h:251
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
TProfile * getFittedHisto()
Get histogram.
Definition: XTFunction.h:272
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
XTFunction & operator=(const XTFunction &x)
Assignment operator.
Definition: XTFunction.h:140
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
void FitPol5()
Fit xt histogram incase 5th order polynomial is used.
Definition: XTFunction.h:331
int getFitStatus()
get fitted flag.
Definition: XTFunction.h:243
TF1 * getXTFunction()
Get XT function.
Definition: XTFunction.h:265
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.