DAS  3.0
Das Analysis System
fit.h
Go to the documentation of this file.
1 #include <cmath>
2 
3 #include <utility>
4 #include <optional>
5 #include <memory>
6 #include <iostream>
7 #include <iomanip>
8 
9 #include <TF1.h>
10 #include <TFitResult.h>
11 #include <TH1.h>
12 #include <TString.h>
13 
14 #include <darwin.h>
15 
16 namespace DAS::JetEnergy {
17 
21 struct AbstractFit {
22 
23  const std::unique_ptr<TH1>& h;
24  std::uint32_t status;
25  std::ostream& cout;
26 
27  double * p,
28  * e;
29 
30  std::unique_ptr<TF1> f;
31  std::optional<double> chi2ndf, chi2ndfErr;
32  std::pair<float, float> interval;
33 
34  inline virtual bool good () const { return chi2ndf && status; }
35 
36 protected:
37 
38  AbstractFit (const unique_ptr<TH1>& h, ostream& cout, int npars) :
39  h(h), status(0), cout(cout),
40  p(new double[npars]), e(new double[npars])
41  { }
42 
43  virtual ~AbstractFit ()
44  {
45  for (int i = 0; i < f->GetNpar(); ++i) {
46  if (isfinite(p[i])) continue;
47  const char * what = Form("Fit parameter %d is not finite", i);
48  BOOST_THROW_EXCEPTION( std::runtime_error(what) );
49  }
50  delete p;
51  delete e;
52  }
53 
61  void fit (std::pair<float,float>, const char *);
62 
65  inline virtual void Write (const char * name)
66  {
67  if (good()) // successful fit
68  f->SetTitle(Form("%.1f", *chi2ndf));
69  else {
70  f->SetLineStyle(kDashed);
71  f->SetTitle("fail");
72  }
73 
74  f->SetParameters(p);
75  f->SetParErrors (e);
76  f->SetRange(interval.first, interval.second);
77  f->Write(name);
78  }
79 };
80 
81 } // end of DAS::JetEnergy namespace
82 
83 inline std::ostream& operator<< (std::ostream& s, const DAS::JetEnergy::AbstractFit& fit)
84 {
85  using namespace std;
86  s << fixed << setprecision(3);
87  for (int i = 0; i < fit.f->GetNpar(); ++i) {
88  double m, M;
89  fit.f->GetParLimits(i, m, M);
90  if (m < M) s << bold;
91  s << setw(10) << fit.f->GetParameter(i);
92  if (m < M) s << normal;
93  }
94  s << defaultfloat;
95  return s;
96 }
97 
98 void DAS::JetEnergy::AbstractFit::fit (std::pair<float,float> range,
99  const char * fitName)
100 {
101  using namespace std;
102 
103  // reinitialise the params to the best known fit
104  f->SetParameters(p);
105  f->SetParErrors (e);
106  f->SetRange(range.first, range.second);
107  for (int i = 0; i < f->GetNpar(); ++i) {
108  double m, M;
109  f->GetParLimits(i,m,M);
110  if (p[i] >= m && p[i] <= M) continue;
111  cerr << orange << setw(2) << i
112  << setw(10) << m
113  << setw(10) << M
114  << setw(10) << p[i]
115  << def << '\n';
116  }
117 
118  // run the fit
119  TFitResultPtr result = h->Fit(f.get(), "QS0NRE");
121  // Q: quiet
122  // S: return smart pointer to fit restult (automatic conversion to integer provides fit status)
123  // 0: do not draw
124  // N: do not store graphics
125  // R: use fit range
127 
128  // get result
129  double currentChi2ndf = f->GetChisquare()/f->GetNDF();
130 
131  bool success = result >= 0 && result % 10 == 0 && currentChi2ndf < 10000;
132  // status = migradStatus + 10*minosStatus + 100*hesseStatus + 1000*improveStatus.
133  // 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).
134  // For example, for an error only in Minos but not in Migrad a fitStatus of 40 will be returned.
135  // Minuit2 returns 0 in case of success and different values in migrad,minos or hesse depending on the error.
136  // See in this case the documentation of Minuit2Minimizer::Minimize for the migrad return status,
137  // Minuit2Minimizer::GetMinosError for the minos return status,
138  // and Minuit2Minimizer::Hesse for the hesse return status.
139 
140  bool improvement = !chi2ndf || abs(currentChi2ndf-1) <= abs(*chi2ndf-1);
141 
142  cout << h->GetTitle() << " with " << bold << fitName << normal << " in ["
143  << fixed << setprecision(2) << range.first << "," << range.second << "]: " << defaultfloat
144  << (success ? (improvement ? green : orange) : red) << *this
145  << fixed << setprecision(3) << setw(15) << currentChi2ndf << defaultfloat
146  << "\t(status = " << (int) result << ")" << def << endl;
147 
148  // skip if the new attempt isn't improving the performance
149  if (!success || !improvement) return;
150 
151  // at this stage, we can consider that the fit has improved,
152  // therefore we save the current parameter estimates
153  chi2ndf = currentChi2ndf;
154  chi2ndfErr = sqrt(2./f->GetNDF());
155  for (int i = 0; i < f->GetNpar(); ++i) {
156  p[i] = f->GetParameter(i);
157  e[i] = f->GetParError (i);
158  }
159  interval = range;
160 }
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.name
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:93
DAS::JetEnergy::AbstractFit::fit
void fit(std::pair< float, float >, const char *)
Definition: fit.h:98
Step::def
static const char * def
Definition: Step.h:36
DAS::JetEnergy::AbstractFit
Definition: fit.h:21
DAS::JetEnergy::AbstractFit::~AbstractFit
virtual ~AbstractFit()
Definition: fit.h:43
DAS::JetEnergy::AbstractFit::Write
virtual void Write(const char *name)
Write the function to the current TDirectory.
Definition: fit.h:65
Step::red
static const char * red
Definition: Step.h:34
operator<<
std::ostream & operator<<(std::ostream &s, const DAS::JetEnergy::AbstractFit &fit)
Definition: fit.h:83
orange
static const char * orange
Definition: colours.h:6
DAS::JetEnergy::AbstractFit::interval
std::pair< float, float > interval
best fit range
Definition: fit.h:32
DAS::JetEnergy::AbstractFit::cout
std::ostream & cout
output stream, can be overwritten to reduce I/O
Definition: fit.h:25
normal
static const char * normal
Definition: colours.h:8
Step::green
static const char * green
Definition: Step.h:33
DAS::JetEnergy::AbstractFit::chi2ndfErr
std::optional< double > chi2ndfErr
best chi2/ndf
Definition: fit.h:31
DAS::JetEnergy::AbstractFit::good
virtual bool good() const
Definition: fit.h:34
DAS::JetEnergy::AbstractFit::chi2ndf
std::optional< double > chi2ndf
Definition: fit.h:31
DAS::JetEnergy::AbstractFit::e
double * e
uncertainties on best parameter estimates
Definition: fit.h:28
DAS::JetEnergy::AbstractFit::AbstractFit
AbstractFit(const unique_ptr< TH1 > &h, ostream &cout, int npars)
Definition: fit.h:38
DAS::JetEnergy::AbstractFit::status
std::uint32_t status
a bit-field to be used in daughter classes
Definition: fit.h:24
DAS::JetEnergy::AbstractFit::h
const std::unique_ptr< TH1 > & h
histogram ready to be fitted
Definition: fit.h:23
metPhiCorrectionExample.range
range
Definition: metPhiCorrectionExample.py:100
DAS::JetEnergy
Definition: applyJERsmearing.cc:41
DAS::JetEnergy::AbstractFit::p
double * p
best parameter estimation
Definition: fit.h:27
DAS::JetEnergy::AbstractFit::f
std::unique_ptr< TF1 > f
Starting by passing Gaussian range.
Definition: fit.h:30
Step::bold
static const char * bold
Definition: Step.h:35