All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Fit.cxx
Go to the documentation of this file.
2 
8 
9 #include "OscLib/IOscCalc.h"
11 
12 #include "TError.h"
13 #include "TGraph.h"
14 #include "TH1.h"
15 #include "TMatrixDSym.h"
16 
17 // ROOT fitter interface
18 #include "Fit/Fitter.h"
19 #include "Math/Factory.h"
20 #include "Math/Functor.h"
21 
22 #include <cassert>
23 #include <iostream>
24 
25 namespace ana
26 {
27  //----------------------------------------------------------------------
28  double SimpleFOM(const Spectrum& obs, const Spectrum& unosc, double pot)
29  {
30  if(pot == 0) pot = obs.POT();
31 
32  std::unique_ptr<TH1> oh(obs.ToTH1(pot));
33  std::unique_ptr<TH1> bh(unosc.ToTH1(pot));
34  assert(oh->GetNbinsX() == bh->GetNbinsX());
35 
36  double fomSq = 0;
37 
38  // Combine s/sqrt(s+b) in quadrature between bins
39  for(int i = 0; i < oh->GetNbinsX(); ++i){
40  const double o = oh->GetBinContent(i);
41  const double b = bh->GetBinContent(i);
42  const double s = o-b;
43 
44  if(s <= 0) continue;
45 
46  fomSq += util::sqr(s)/(s+b);
47  }
48 
49  return sqrt(fomSq);
50  }
51 
52  //----------------------------------------------------------------------
54  std::vector<const IFitVar*> vars,
55  std::vector<const ISyst*> systs,
57  : fExpt(expt), fVars(vars), fSysts(systs), fPrec(prec), fCalc(0),
58  fCovar(0), fCovarStatus(-1)
59  {
60  }
61 
62  //----------------------------------------------------------------------
63  std::vector<Fitter::SeedPt> Fitter::
64  ExpandSeeds(const std::map<const IFitVar*,
65  std::vector<double>>& seedPts,
66  std::vector<SystShifts> systSeedPts) const
67  {
68  std::vector<SeedPt> ret;
69  ret.push_back(SeedPt());
70 
71  for(auto it: seedPts){
72  // For every variable, duplicate every entry in ret with the value set to
73  // each possibility.
74  const IFitVar* fv = it.first;
75  std::vector<SeedPt> newret;
76  for(double val: it.second){
77  for(SeedPt pt: ret){
78  pt.fitvars[fv] = val;
79  newret.push_back(pt);
80  }
81  } // end for val
82  ret = newret;
83  } // end for it
84 
85  // Now duplicate as many times as required for the syst seeds
86  if(!systSeedPts.empty()){
87  std::vector<SeedPt> newret;
88  for(const SystShifts& s: systSeedPts){
89  for(SeedPt pt: ret){
90  pt.shift = s;
91  newret.push_back(pt);
92  }
93  }
94  ret = newret;
95  }
96 
97  return ret;
98  }
99 
100  //----------------------------------------------------------------------
101  std::unique_ptr<ROOT::Math::Minimizer>
103  SystShifts& systSeed, Verbosity verb) const
104  {
105  // Why, when this is called for each seed?
106  fCalc = seed;
107  fShifts = systSeed;
108 
109  if(fPrec & kIncludeSimplex) std::cout << "Simplex option specified but not implemented. Ignored." << std::endl;
110  if((fPrec & kAlgoMask) == kGradDesc){
111  std::cout << "GradDesc option specified but not implemented. Abort." << std::endl;
112  abort();
113  }
114 
115  std::unique_ptr<ROOT::Math::Minimizer> mnMin(
116  ROOT::Math::Factory::CreateMinimizer("Minuit2", "Combined"));
117  mnMin->SetStrategy(int(fPrec & kAlgoMask));
118  mnMin->SetMaxFunctionCalls(1E8);
119  mnMin->SetMaxIterations(1E8);
120 
121  for(const IFitVar* v: fVars){
122  const double val = v->GetValue(seed);
123  // name, value, error
124  mnMin->SetVariable(mnMin->NFree(), v->ShortName(), val, val ? fabs(val/2) : .1);
125  fParamNames.push_back(v->ShortName());
126  fPreFitValues.push_back(val);
127  fPreFitErrors.push_back(val ? val/2 : .1);
128  }
129  // One way this can go wrong is if two variables have the same ShortName
130  assert(mnMin->NFree() == fVars.size());
131  for(const ISyst*s: fSysts){
132  const double val = systSeed.GetShift(s);
133  // name, value, error
134  mnMin->SetVariable(mnMin->NFree(), s->ShortName(), val, 1);
135  fParamNames.push_back(s->ShortName());
136  fPreFitValues.push_back(val);
137  fPreFitErrors.push_back(1);
138  }
139  // One way this can go wrong is if two variables have the same ShortName
140  assert(mnMin->NFree() == fVars.size()+fSysts.size());
141 
142  mnMin->SetFunction(*this);
143 
144  if(verb == Verbosity::kQuiet) mnMin->SetPrintLevel(0);
145 
146  if(!mnMin->Minimize()){
147  std::cout << "*** ERROR: minimum is not valid ***" << std::endl;
148  std::cout << "*** Precision: " << mnMin->Precision() << std::endl;
149 
150  std::cout << "-- Stopped at: \n";
151  for(uint i = 0; i < mnMin->NFree(); ++i){
152  std::cout << "\t" << mnMin->VariableName(i) << " = " << mnMin->X()[i] << "\n";
153  }
154  }
155 
156  if (fPrec & kIncludeHesse){
157  std::cout << "It's Hesse o'clock" << std::endl;
158  mnMin->Hesse();
159  }
160 
161  if (fPrec & kIncludeMinos){
162  std::cout << "It's minos time" << std::endl;
163  fTempMinosErrors.clear();
164  for (uint i = 0; i < mnMin->NDim(); ++i){
165  double errLow = 0, errHigh = 0;
166  mnMin->GetMinosError(i, errLow, errHigh);
167  std::cout << i << "/" << mnMin->NDim() << " " << fParamNames[i] << ": " << errLow << ", +" << errHigh << " (" << mnMin->Errors()[i] << ")" << std::endl;
168  fTempMinosErrors.push_back(std::make_pair(errLow,errHigh));
169  }
170  }
171 
172  return mnMin;
173  }
174 
175  //----------------------------------------------------------------------
177  SystShifts& bestSysts,
178  const std::map<const IFitVar*, std::vector<double>>& seedPts,
179  std::vector<SystShifts> systSeedPts,
180  Verbosity verb) const
181  {
182  const std::vector<SeedPt> pts = ExpandSeeds(seedPts, systSeedPts);
183  double minchi = 1e10;
184  std::vector<double> bestFitPars, bestSystPars;
185 
186  for(const SeedPt& pt: pts){
187  osc::IOscCalcAdjustable *seed = initseed->Copy();
188 
189  for(auto it: pt.fitvars) it.first->SetValue(seed, it.second);
190 
191  // Need to deal with parameters that are not fit values!
192  SystShifts shift = pt.shift;
193 
194  // Need to copy over syst values into the seed for this fit
195  // that were in the input syst shifts, but are not being fit for,
196  // and therefore not part of the seedPts list
197  for(auto s: bestSysts.ActiveSysts()) {
198  auto fit_systs = shift.ActiveSysts();
199  if(std::find(fit_systs.begin(), fit_systs.end(), s) == fit_systs.end()) {
200  shift.SetShift(s, bestSysts.GetShift(s));
201  }
202  }
203 
204  std::unique_ptr<ROOT::Math::Minimizer> thisMin =
205  FitHelperSeeded(seed, shift, verb);
206 
207  // Check whether this is the best minimum we've found so far
208  if (thisMin->MinValue() < minchi) {
209  minchi = thisMin->MinValue();
210 
211  // Need to do Prefit here too...
212  fParamNames .clear();
213  fPreFitValues .clear();
214  fPreFitErrors .clear();
215  fPostFitValues .clear();
216  fPostFitErrors .clear();
217  fMinosErrors .clear();
219 
220  // Save pre-fit info
221  // In principle, these can change with the seed, so have to save them here...
222  for(const IFitVar* v: fVars){
223  const double val = v->GetValue(seed);
224  fParamNames .push_back(v->ShortName());
225  fPreFitValues.push_back(val);
226  fPreFitErrors.push_back(val ? val/2 : .1);
227  }
228  for(const ISyst* s: fSysts){
229  const double val = shift.GetShift(s);
230  fParamNames .push_back(s->ShortName());
231  fPreFitValues.push_back(val);
232  fPreFitErrors.push_back(1);
233  }
234 
235  // Now save postfit
236  fPostFitValues = std::vector<double>(thisMin->X(), thisMin->X()+thisMin->NDim());
237  fPostFitErrors = std::vector<double>(thisMin->Errors(), thisMin->Errors()+thisMin->NDim());
238 
239  fEdm = thisMin->Edm();
240  fIsValid = !thisMin->Status();
241 
242  delete fCovar;
243  fCovar = new TMatrixDSym(thisMin->NDim());
244 
245  for(unsigned int row = 0; row < thisMin->NDim(); ++row){
246  for(unsigned int col = 0; col < thisMin->NDim(); ++col){
247  (*fCovar)(row, col) = thisMin->CovMatrix(row, col);
248  }
249  }
250 
251  // Store the best fit values of all the parameters we know are being varied.
252  for(unsigned int i = 0; i < fVars.size(); ++i)
253  bestFitPars.push_back(fPostFitValues[i]);
254  for(unsigned int j = 0; j < fSysts.size(); ++j)
255  bestSystPars.push_back(fPostFitValues[fVars.size()+j]);
256  }
257  delete seed;
258  }
259 
260  // Stuff the results of the actual best fit back into the seeds
261  for(unsigned int i = 0; i < fVars.size(); ++i)
262  fVars[i]->SetValue(initseed, bestFitPars[i]);
263  for(unsigned int i = 0; i < fSysts.size(); ++i)
264  bestSysts.SetShift(fSysts[i], bestSystPars[i]);
265 
266  return minchi;
267  }
268 
269  //----------------------------------------------------------------------
271  {
272  fPrec = prec;
273  }
274 
275  //----------------------------------------------------------------------
277  SystShifts& bestSysts,
278  const std::map<const IFitVar*, std::vector<double>>& seedPts,
279  const std::vector<SystShifts>& systSeedPts,
280  Verbosity verb) const
281  {
282  // Fits with no osc calc shouldn't be trying to optimize any
283  // oscilation parameters...
284  assert(seed || fVars.empty());
285 
286  for(const auto& it: seedPts){
287  if(std::find(fVars.begin(), fVars.end(), it.first) == fVars.end()){
288  std::cout << "ERROR Fitter::Fit() trying to seed '"
289  << it.first->ShortName()
290  << "' which is not part of the fit." << std::endl;
291  abort();
292  }
293  }
294  for(const auto& it: systSeedPts){
295  for(const ISyst* s: it.ActiveSysts()){
296  if(std::find(fSysts.begin(), fSysts.end(), s) == fSysts.end()){
297  std::cout << "ERROR Fitter::Fit() trying to seed '"
298  << s->ShortName()
299  << "' which is not part of the fit." << std::endl;
300  abort();
301  }
302  }
303  }
304 
305  if(verb == kVerbose){
306  std::cout << "Finding best fit for";
307  for(const IFitVar* v: fVars) std::cout << " " << v->ShortName();
308  for(const ISyst* s: fSysts) std::cout << " " << s->ShortName();
309  std::cout << "..." << std::endl;
310  }
311 
312  // Do all the actual work. This wrapper function is just so we can have
313  // better control of printing.
314  const double chi = FitHelper(seed, bestSysts, seedPts, systSeedPts, verb);
315 
316  if(verb == kVerbose){
317  std::cout << "Best fit";
318  for(const IFitVar* v: fVars){
319  std::cout << ", " << v->ShortName() << " = " << v->GetValue(seed);
320  }
321  for(const ISyst* s: fSysts){
322  std::cout << ", " << s->ShortName() << " = " << bestSysts.GetShift(s);
323  }
324  std::cout << ", LL = " << chi << std::endl;
325 
326  std::cout << " found with " << fNEval << " evaluations of the likelihood";
327  if(fNEvalFiniteDiff > 0)
328  std::cout << " (" << fNEvalFiniteDiff << " to evaluate gradients numerically)";
329  if(fNEvalGrad > 0)
330  std::cout << " and " << fNEvalGrad << " evaluations of the gradient";
331  std::cout << std::endl;
332  }
333 
334  return chi;
335  }
336 
337  //----------------------------------------------------------------------
338  void Fitter::DecodePars(const double* pars) const
339  {
340  for(unsigned int i = 0; i < fVars.size(); ++i){
341  const double val = pars[i];
342  if(isnan(val) || isinf(val)){
343  std::cout << "Fitter::DecodePars(). Minuit wants to set " << fVars[i]->ShortName() << " = " << val << ". Will ignore it and hope for the best." << std::endl;
344  // To debug this problem uncomment this abort and run in gdb
345  // abort();
346  }
347  else{
348  fVars[i]->SetValue(fCalc, val);
349  }
350  }
351  for(unsigned int j = 0; j < fSysts.size(); ++j){
352  const double val = pars[fVars.size()+j];
353  if(isnan(val) || isinf(val)){
354  std::cout << "Fitter::DecodePars(). Minuit wants to set " << fSysts[j]->ShortName() << " = " << val << ". Will ignore it and hope for the best." << std::endl;
355  // To debug this problem uncomment this abort and run in gdb
356  // abort();
357  }
358  else{
359  fShifts.SetShift(fSysts[j], val);
360  }
361  }
362  }
363 
364  //----------------------------------------------------------------------
365  double Fitter::DoEval(const double* pars) const
366  {
367  ++fNEval;
368 
369  DecodePars(pars); // Updates fCalc and fShifts
370 
371  // Have to re-fetch the values because DecodePars() will have truncated
372  // values to the physical range where necessary.
373  double penalty = 0;
374  for(unsigned int i = 0; i < fVars.size(); ++i){
375  const double x = pars[i];
376  if(isinf(x) || isnan(x)) continue; // DecodePars() should have warned
377  penalty += fVars[i]->Penalty(x, fCalc);
378  }
379  for(unsigned int j = 0; j < fSysts.size(); ++j){
380  const double x = pars[fVars.size()+j];
381  if(isinf(x) || isnan(x)) continue; // DecodePars() should have warned
382  penalty += fSysts[j]->Penalty(x);
383  }
384 
385  if(fNEval%1000 == 0) std::cout << fNEval << ": EXPT chi2 = " << fExpt->ChiSq(fCalc, fShifts) << "; penalty = " << penalty << std::endl;
386  return fExpt->ChiSq(fCalc, fShifts) + penalty;
387  }
388 
389  //----------------------------------------------------------------------
390  TH1* Profile(const IExperiment* expt,
391  osc::IOscCalcAdjustable* calc, const IFitVar* v,
392  int nbinsx, double minx, double maxx,
393  double input_minchi,
394  const std::vector<const IFitVar*>& profVars,
395  const std::vector<const ISyst*>& profSysts,
396  const std::map<const IFitVar*, std::vector<double>>& seedPts,
397  const std::vector<SystShifts>& systSeedPts,
398  std::map<const IFitVar*, TGraph*>& profVarsMap,
399  std::map<const ISyst*, TGraph*>& profSystsMap)
400  {
401  Progress prog ("Filling profile");
402  // If we're called with the default arguments they could already have stuff
403  // in from before.
404  for(auto it: profVarsMap) delete it.second;
405  for(auto it: profSystsMap) delete it.second;
406  profVarsMap.clear();
407  profSystsMap.clear();
408 
409  // And then create the plots we'll be filling
410  for(const IFitVar* v: profVars) profVarsMap[v] = new TGraph;
411  for(const ISyst* s: profSysts) profSystsMap[s] = new TGraph;
412 
413  TH1* ret = new TH1F(UniqueName().c_str(),
414  (";"+v->LatexName()+ (input_minchi == 0? ";#chi^{2}" : ";#Delta#chi^{2}") ).c_str(),
415  nbinsx, minx, maxx);
416 
417  // Save the values of the fit vars as they were in the seed so we can put
418  // them back to that value every iteration.
419  std::vector<double> seedValues;
420  for(const IFitVar* v: profVars) seedValues.push_back(v->GetValue(calc));
421 
422  double minpos = 0;
423  double minchi = 1e10;
424 
425  Fitter fit(expt, profVars, profSysts);
426 
427  for(int n = 0; n < nbinsx; ++n){
428  prog.SetProgress((double) n/nbinsx);
429 
430  const double x = ret->GetXaxis()->GetBinCenter(n+1);
431  v->SetValue(calc, x);
432 
433  // Put oscillation values back to their seed position each iteration
434  for(unsigned int i = 0; i < seedValues.size(); ++i)
435  profVars[i]->SetValue( calc, seedValues[i] );
436 
437  SystShifts systshift = SystShifts::Nominal();
438  const double chi = fit.Fit(calc, systshift, seedPts, systSeedPts, Fitter::kQuiet);
439 
440  ret->Fill(x, chi);
441 
442  if(chi < minchi){
443  minchi = chi;
444  minpos = x;
445  }
446  for(const IFitVar* var: profVars){
447  profVarsMap[var]->SetPoint(n, x, var->GetValue(calc));
448  }
449  for(const ISyst* s: profSysts){
450  profSystsMap[s]->SetPoint(n, x, systshift.GetShift(s));
451  }
452  }
453  prog.Done();
454  // If we weren't given an explicit minimum chisq, go find one
455  if(input_minchi == -1){
456  std::vector<const IFitVar*> allVars = {v};
457  for(unsigned int i = 0; i < seedValues.size(); ++i) {
458  profVars[i]->SetValue(calc, seedValues[i]);
459  allVars.push_back(profVars[i]);
460  }
461  Fitter fit(expt, allVars, profSysts);
462  // Seed from best grid point
463  v->SetValue(calc, minpos);
464  minchi = fit.Fit(calc); // get a better value
465  }
466  else{
467  minchi = input_minchi;
468  }
469 
470  // Zero-subtract the result histogram
471  for(int n = 0; n < nbinsx; ++n) ret->AddBinContent(n+1, -minchi);
472 
473  return ret;
474  }
475 
476  //----------------------------------------------------------------------
477  TH1* Profile(const IExperiment* expt,
478  osc::IOscCalcAdjustable* calc, const ISyst* s,
479  int nbinsx, double minx, double maxx,
480  double input_minchi,
481  const std::vector<const IFitVar*>& profVars,
482  const std::vector<const ISyst*>& profSysts,
483  const std::map<const IFitVar*, std::vector<double>>& seedPts,
484  const std::vector<SystShifts>& systSeedPts,
485  std::map<const IFitVar*, TGraph*>& profVarsMap,
486  std::map<const ISyst*, TGraph*>& profSystsMap)
487  {
488  Progress prog ("Filling profile");
489  // If we're called with the default arguments they could already have stuff
490  // in from before.
491  for(auto it: profVarsMap) delete it.second;
492  for(auto it: profSystsMap) delete it.second;
493  profVarsMap.clear();
494  profSystsMap.clear();
495 
496  // And then create the plots we'll be filling
497  for(const IFitVar* v: profVars) profVarsMap[v] = new TGraph;
498  for(const ISyst* prof_syst: profSysts) profSystsMap[prof_syst] = new TGraph;
499 
500  TH1* ret = new TH1F(UniqueName().c_str(),
501  (";"+s->LatexName()+ (input_minchi == 0? ";#chi^{2}" : ";#Delta#chi^{2}") ).c_str(),
502  nbinsx, minx, maxx);
503 
504  // Save the values of the fit vars as they were in the seed so we can put
505  // them back to that value every iteration.
506  std::vector<double> seedValues;
507  for(const IFitVar* v: profVars) seedValues.push_back(v->GetValue(calc));
508 
509  double minpos = 0;
510  double minchi = 1e10;
511 
512  Fitter fit(expt, profVars, profSysts);
513 
514  for(int n = 0; n < nbinsx; ++n){
515  prog.SetProgress((double) n/nbinsx);
516 
517  const double x = ret->GetXaxis()->GetBinCenter(n+1);
518  SystShifts systshift(s, x);
519 
520  // Put oscillation values back to their seed position each iteration
521  for(unsigned int i = 0; i < seedValues.size(); ++i)
522  profVars[i]->SetValue( calc, seedValues[i] );
523 
524  const double chi = fit.Fit(calc, systshift, seedPts, systSeedPts, Fitter::kQuiet);
525 
526  ret->Fill(x, chi);
527 
528  if(chi < minchi){
529  minchi = chi;
530  minpos = x;
531  }
532  for(const IFitVar* var: profVars){
533  profVarsMap[var]->SetPoint(n, x, var->GetValue(calc));
534  }
535  for(const ISyst* s: profSysts){
536  profSystsMap[s]->SetPoint(n, x, systshift.GetShift(s));
537  }
538  }
539  prog.Done();
540  // If we weren't given an explicit minimum chisq, go find one
541  if(input_minchi == -1){
542  std::vector<const ISyst*> allSysts = {s};
543  for(unsigned int i = 0; i < seedValues.size(); ++i) {
544  profVars[i]->SetValue(calc, seedValues[i]);
545  }
546  for(unsigned int i = 0; i < profSysts.size(); ++i) {
547  allSysts.push_back(profSysts[i]);
548  }
549  Fitter fit(expt, profVars, allSysts);
550  // Seed from best grid point
551  SystShifts systshift(s, minpos);
552  minchi = fit.Fit(calc, systshift); // get a better value
553  }
554  else{
555  minchi = input_minchi;
556  }
557 
558  // Zero-subtract the result histogram
559  for(int n = 0; n < nbinsx; ++n) ret->AddBinContent(n+1, -minchi);
560 
561  return ret;
562  }
563 
564  //----------------------------------------------------------------------
565  TH1* SqrtProfile(const IExperiment* expt,
566  osc::IOscCalcAdjustable* calc, const IFitVar* v,
567  int nbinsx, double minx, double maxx, double minchi,
568  std::vector<const IFitVar*> profVars,
569  std::vector<const ISyst*> profSysts,
570  const std::map<const IFitVar*, std::vector<double>>& seedPts,
571  const std::vector<SystShifts>& systSeedPts,
572  std::map<const IFitVar*, TGraph*>& profVarsMap,
573  std::map<const ISyst*, TGraph*>& systsMap)
574  {
575  TH1* ret = Profile(expt, calc,
576  v, nbinsx, minx, maxx,
577  minchi, profVars, profSysts, seedPts, systSeedPts,
578  profVarsMap, systsMap);
579  for(int n = 0; n < ret->GetNbinsX()+2; ++n){
580  const double v = ret->GetBinContent(n);
581  ret->SetBinContent(n, v > 0 ? sqrt(v) : 0);
582  }
583  ret->GetYaxis()->SetTitle("#sigma");
584  return ret;
585  }
586 
587  //----------------------------------------------------------------------
588  TH1* SqrtProfile(const IExperiment* expt,
589  osc::IOscCalcAdjustable* calc, const ISyst* s,
590  int nbinsx, double minx, double maxx, double minchi,
591  std::vector<const IFitVar*> profVars,
592  std::vector<const ISyst*> profSysts,
593  const std::map<const IFitVar*, std::vector<double>>& seedPts,
594  const std::vector<SystShifts>& systSeedPts,
595  std::map<const IFitVar*, TGraph*>& profVarsMap,
596  std::map<const ISyst*, TGraph*>& systsMap)
597  {
598  TH1* ret = Profile(expt, calc,
599  s, nbinsx, minx, maxx,
600  minchi, profVars, profSysts, seedPts, systSeedPts,
601  profVarsMap, systsMap);
602  for(int n = 0; n < ret->GetNbinsX()+2; ++n){
603  const double v = ret->GetBinContent(n);
604  ret->SetBinContent(n, v > 0 ? sqrt(v) : 0);
605  }
606  ret->GetYaxis()->SetTitle("#sigma");
607  return ret;
608  }
609 
610  //----------------------------------------------------------------------
611  TH1* Slice(const IExperiment* expt,
612  osc::IOscCalcAdjustable* calc, const IFitVar* v,
613  int nbinsx, double minx, double maxx,
614  double minchi)
615  {
616  return Profile(expt, calc, v, nbinsx, minx, maxx, minchi);
617  }
618 
619  //----------------------------------------------------------------------
620  TH1* Slice(const IExperiment* expt,
621  osc::IOscCalcAdjustable* calc, const ISyst* s,
622  int nbinsx, double minx, double maxx,
623  double minchi)
624  {
625  return Profile(expt, calc, s, nbinsx, minx, maxx, minchi);
626  }
627 
628  //----------------------------------------------------------------------
629  TH1* SqrtSlice(const IExperiment* expt,
630  osc::IOscCalcAdjustable* calc, const IFitVar* v,
631  int nbinsx, double minx, double maxx, double minchi)
632  {
633  TH1* ret = Slice(expt, calc, v, nbinsx, minx, maxx, minchi);
634  for(int n = 0; n < ret->GetNbinsX()+2; ++n){
635  const double v = ret->GetBinContent(n);
636  ret->SetBinContent(n, v > 0 ? sqrt(v) : 0);
637  }
638  ret->GetYaxis()->SetTitle("#sigma");
639  return ret;
640  }
641 
642  //----------------------------------------------------------------------
643  TH1* SqrtSlice(const IExperiment* expt,
644  osc::IOscCalcAdjustable* calc, const ISyst* s,
645  int nbinsx, double minx, double maxx, double minchi)
646  {
647  TH1* ret = Slice(expt, calc, s, nbinsx, minx, maxx, minchi);
648  for(int n = 0; n < ret->GetNbinsX()+2; ++n){
649  const double v = ret->GetBinContent(n);
650  ret->SetBinContent(n, v > 0 ? sqrt(v) : 0);
651  }
652  ret->GetYaxis()->SetTitle("#sigma");
653  return ret;
654  }
655 
656  //----------------------------------------------------------------------
657  TGraph* FindValley(const IExperiment* expt,
659  const IFitVar& scanVar,
660  const IFitVar& fitVar,
661  int nbinsx, double xmin, double xmax,
662  const std::vector<const IFitVar*>& profVars,
663  const std::vector<const ISyst*>& profSysts,
664  const std::map<const IFitVar*, std::vector<double>>& seedPts,
665  const std::vector<SystShifts>& systSeedPts,
666  bool transpose)
667  {
668  TGraph* g = new TGraph;
669  g->SetLineWidth(2);
670 
671  std::vector<const IFitVar*> vars = profVars;
672  vars.push_back(&fitVar);
673 
674  for(int i = 0; i <= nbinsx; ++i){
675  const double x = xmin + i*(xmax-xmin)/nbinsx;
676  scanVar.SetValue(calc, x);
677  Fitter fit(expt, vars, profSysts);
678  SystShifts shiftSeed = SystShifts::Nominal();
679  fit.Fit(calc, shiftSeed, seedPts, systSeedPts, Fitter::kQuiet);
680  const double y = fitVar.GetValue(calc);
681  if(transpose)
682  g->SetPoint(i, y, x);
683  else
684  g->SetPoint(i, x, y);
685  }
686 
687  return g;
688  }
689 
690  //----------------------------------------------------------------------
691  std::vector<double> FindCurveCrossings(TH1* h, double critVal)
692  {
693  std::vector<double> ret;
694 
695  // Don't look at the under/overflow bins because they don't have properly
696  // defined centre positions in any case. Stop one short because we compare
697  // i and i+1 inside the loop.
698  for(int i = 1; i < h->GetNbinsX(); ++i){
699  const double x0 = h->GetXaxis()->GetBinCenter(i);
700  const double x1 = h->GetXaxis()->GetBinCenter(i+1);
701 
702  const double y0 = h->GetBinContent(i);
703  const double y1 = h->GetBinContent(i+1);
704 
705  // Passed the critical value between the two points
706  if((y0 < critVal) != (y1 < critVal)){
707  // Interpolate the actual crossing point
708  const double x = x0 + (x1-x0)*(critVal-y0)/(y1-y0);
709  ret.push_back(x);
710  }
711  } // end for i
712 
713  return ret;
714  }
715 }
std::vector< std::pair< double, double > > fMinosErrors
Definition: Fit.h:193
std::vector< std::pair< double, double > > fTempMinosErrors
Definition: Fit.h:194
TH1 * SqrtProfile(const IExperiment *expt, osc::IOscCalcAdjustable *calc, const IFitVar *v, int nbinsx, double minx, double maxx, double minchi, std::vector< const IFitVar * > profVars, std::vector< const ISyst * > profSysts, const std::map< const IFitVar *, std::vector< double >> &seedPts, const std::vector< SystShifts > &systSeedPts, std::map< const IFitVar *, TGraph * > &profVarsMap, std::map< const ISyst *, TGraph * > &systsMap)
Forward to Profile but sqrt the result for a crude significance.
Definition: Fit.cxx:565
TH1D * ToTH1(double exposure, Color_t col=kBlack, Style_t style=kSolid, EExposureType expotype=kPOT, EBinType bintype=kBinContent) const
Histogram made from this Spectrum, scaled to some exposure.
virtual std::string LatexName() const =0
double FitHelper(osc::IOscCalcAdjustable *seed, SystShifts &bestSysts, const std::map< const IFitVar *, std::vector< double >> &seedPts, std::vector< SystShifts > systSeedPts, Verbosity verb) const
Helper for Fit.
Definition: Fit.cxx:176
virtual double GetValue(const osc::IOscCalcAdjustable *osc) const =0
void SetShift(const ISyst *syst, double shift)
Shifts are 0=nominal, -1,+1 = 1 sigma shifts.
Definition: SystShifts.cxx:47
process_name opflash particleana ie x
TGraph * FindValley(const IExperiment *expt, osc::IOscCalcAdjustable *calc, const IFitVar &scanVar, const IFitVar &fitVar, int nbinsx, double xmin, double xmax, const std::vector< const IFitVar * > &profVars, const std::vector< const ISyst * > &profSysts, const std::map< const IFitVar *, std::vector< double >> &seedPts, const std::vector< SystShifts > &systSeedPts, bool transpose)
Find the minimum in one variable as a function of another.
Definition: Fit.cxx:657
int fNEvalGrad
Definition: Fit.h:180
Simple record of shifts applied to systematic parameters.
Definition: SystShifts.h:16
virtual double ChiSq(osc::IOscCalcAdjustable *osc, const SystShifts &syst=SystShifts::Nominal()) const =0
double Fit(osc::IOscCalcAdjustable *seed, SystShifts &bestSysts=junkShifts, const std::map< const IFitVar *, std::vector< double >> &seedPts={}, const std::vector< SystShifts > &systSeedPts={}, Verbosity verb=kVerbose) const
Definition: Fit.cxx:276
std::vector< SeedPt > ExpandSeeds(const std::map< const IFitVar *, std::vector< double >> &seedPts, std::vector< SystShifts > systSeedPts) const
Definition: Fit.cxx:64
std::vector< double > FindCurveCrossings(TH1 *h, double critVal)
Intended for use on the output of Profile.
Definition: Fit.cxx:691
double fEdm
Definition: Fit.h:184
void SetPrecision(Precision prec)
Definition: Fit.cxx:270
process_name opflashCryoW ana
int fNEval
Definition: Fit.h:179
static SystShifts Nominal()
Definition: SystShifts.h:23
BEGIN_PROLOG g
shift
Definition: fcl_checks.sh:26
T sqr(T x)
More efficient square function than pow(x,2)
Definition: MathUtil.h:23
Encapsulate code to systematically shift a caf::StandardRecord.
Definition: ISyst.h:14
Perform MINUIT fits in one or two dimensions.
Definition: Fit.h:37
TH1 * Profile(const IExperiment *expt, osc::IOscCalcAdjustable *calc, const IFitVar *v, int nbinsx, double minx, double maxx, double input_minchi, const std::vector< const IFitVar * > &profVars, const std::vector< const ISyst * > &profSysts, const std::map< const IFitVar *, std::vector< double >> &seedPts, const std::vector< SystShifts > &systSeedPts, std::map< const IFitVar *, TGraph * > &profVarsMap, std::map< const ISyst *, TGraph * > &profSystsMap)
scan in one variable, profiling over all others
Definition: Fit.cxx:390
Representation of a spectrum in any variable, with associated POT.
Definition: Spectrum.h:30
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
while getopts h
int fNEvalFiniteDiff
Definition: Fit.h:181
Verbosity
Definition: Fit.h:40
process_name opflash particleana ie ie y
std::vector< double > fPreFitValues
Definition: Fit.h:189
virtual void SetValue(osc::IOscCalcAdjustable *osc, double val) const =0
std::vector< const IFitVar * > fVars
Definition: Fit.h:173
Precision fPrec
Definition: Fit.h:175
bool fIsValid
Definition: Fit.h:185
TMatrixDSym * fCovar
Definition: Fit.h:186
unsigned int seed
std::unique_ptr< ROOT::Math::Minimizer > FitHelperSeeded(osc::IOscCalcAdjustable *seed, SystShifts &systSeed, Verbosity verb) const
Helper for FitHelper.
Definition: Fit.cxx:102
std::vector< double > fPostFitValues
Definition: Fit.h:191
std::vector< double > fPreFitErrors
Definition: Fit.h:190
double GetShift(const ISyst *syst) const
Definition: SystShifts.cxx:56
std::vector< const ISyst * > allSysts
Definition: toysysts.h:42
Fitter(const IExperiment *expt, std::vector< const IFitVar * > vars, std::vector< const ISyst * > systs={}, Precision prec=kNormal)
Definition: Fit.cxx:53
osc::IOscCalcAdjustable * fCalc
Definition: Fit.h:176
SystShifts fShifts
Definition: Fit.h:177
double POT() const
Definition: Spectrum.h:289
TH1 * SqrtSlice(const IExperiment *expt, osc::IOscCalcAdjustable *calc, const IFitVar *v, int nbinsx, double minx, double maxx, double minchi)
Forward to Slice but sqrt the result for a crude significance.
Definition: Fit.cxx:629
void DecodePars(const double *pars) const
Updates mutable fCalc and fShifts.
Definition: Fit.cxx:338
std::vector< const ISyst * > fSysts
Definition: Fit.h:174
void SetProgress(double frac)
Update the progress fraction between zero and one.
Definition: Progress.cxx:44
int prec
std::vector< std::string > fParamNames
Definition: Fit.h:188
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
fVars({varX, varY})
Definition: HistAxis.cxx:39
double SimpleFOM(const Spectrum &obs, const Spectrum &unosc, double pot)
Figure-of-merit with no systematics, for binned data.
Definition: Fit.cxx:28
Base class defining interface for experiments.
Definition: IExperiment.h:21
const IExperiment * fExpt
Definition: Fit.h:172
A simple ascii-art progress bar.
Definition: Progress.h:9
Interface definition for fittable variables.
Definition: IFitVar.h:14
then echo ***************************************echo Variable FHICL_FILE_PATH not found echo You porbably haven t set up larsoft echo Try setup uboonecode vXX_XX_XX q e10
Definition: find_fhicl.sh:6
std::vector< double > fPostFitErrors
Definition: Fit.h:192
std::vector< const ISyst * > ActiveSysts() const
Definition: SystShifts.cxx:120
virtual std::string LatexName() const final
The name used on plots (ROOT&#39;s TLatex syntax)
Definition: ISyst.h:33
TH1 * Slice(const IExperiment *expt, osc::IOscCalcAdjustable *calc, const IFitVar *v, int nbinsx, double minx, double maxx, double minchi)
scan in one variable, holding all others constant
Definition: Fit.cxx:611
prog
Definition: just_cmake.sh:3
void Done()
Call this when action is completed.
Definition: Progress.cxx:91
virtual double DoEval(const double *pars) const override
Evaluate the log-likelihood, as required by MINUT interface.
Definition: Fit.cxx:365
Precision
Definition: Fit.h:42
std::string UniqueName()
Return a different string each time, for creating histograms.
BEGIN_PROLOG could also be cout