All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PredictionInterp.cxx
Go to the documentation of this file.
7 
8 #include "TDirectory.h"
9 #include "TH2.h"
10 #include "TMatrixD.h"
11 #include "TObjString.h"
12 #include "TVectorD.h"
13 
14 // For debug plots
15 #include "TGraph.h"
16 #include "TCanvas.h"
17 
18 #include "OscLib/IOscCalc.h"
20 
22 
23 #include <algorithm>
24 #include <malloc.h>
25 
26 namespace ana
27 {
28  //----------------------------------------------------------------------
29  PredictionInterp::PredictionInterp(std::vector<const ISyst*> systs,
30  osc::IOscCalc* osc,
31  const IPredictionGenerator& predGen,
32  Loaders& loaders,
33  const SystShifts& shiftMC,
34  EMode_t mode)
35  : fOscOrigin(osc ? osc->Copy() : 0),
36  fBinning(0, {}, {}, 0, 0),
37  fSplitBySign(mode == kSplitBySign)
38  {
39  for(const ISyst* syst: systs){
40  ShiftedPreds sp;
41  sp.systName = syst->ShortName();
42 
43  for(int x = -syst->PredInterpMaxNSigma(); x <= +syst->PredInterpMaxNSigma(); ++x){
44  sp.shifts.push_back(x);
45  }
46 
47  for(int sigma: sp.shifts){
48  SystShifts shiftHere = shiftMC;
49  shiftHere.SetShift(syst, sigma);
50  sp.preds.push_back(predGen.Generate(loaders, shiftHere).release());
51  }
52 
53  fPreds.emplace(syst, sp);
54  } // end for syst
55 
56  fPredNom = predGen.Generate(loaders, shiftMC);
57  }
58 
59  //----------------------------------------------------------------------
61  {
62  // for(auto it: fPreds) for(IPrediction* p: it.second.preds) delete p;
63  // delete fOscOrigin;
64 
65  // It isn't really a unique ptr when we use PredictionInterpTemplates
66  fPredNom.release();
67  }
68 
69  //----------------------------------------------------------------------
70  std::vector<std::vector<PredictionInterp::Coeffs>> PredictionInterp::
71  FitRatios(const std::vector<double>& shifts,
72  const std::vector<std::unique_ptr<TH1>>& ratios) const
73  {
74  assert(shifts.size() == ratios.size());
75 
76  std::vector<std::vector<Coeffs>> ret;
77 
78  const int binMax = ratios[0]->GetNbinsX();
79 
80  // Linear interpolation
81  if(ratios.size() == 2){
82  for(int binIdx = 0; binIdx < binMax+2; ++binIdx){
83  ret.push_back({});
84  const double y1 = ratios[0]->GetBinContent(binIdx);
85  const double y2 = ratios[1]->GetBinContent(binIdx);
86  ret.back().emplace_back(0, 0, y2-y1, y1);
87  }
88  return ret;
89  }
90 
91  for(int binIdx = 0; binIdx < binMax+2; ++binIdx){
92  ret.push_back({});
93 
94  // This is cubic interpolation. For each adjacent set of four points we
95  // determine coefficients for a cubic which will be the curve between the
96  // center two. We constrain the function to match the two center points
97  // and to have the right mean gradient at them. This causes this patch to
98  // match smoothly with the next one along. The resulting function is
99  // continuous and first and second differentiable. At the ends of the
100  // range we fit a quadratic instead with only one constraint on the
101  // slope. The coordinate conventions are that point y1 sits at x=0 and y2
102  // at x=1. The matrices are simply the inverses of writing out the
103  // constraints expressed above.
104 
105  {
106  const double y1 = ratios[0]->GetBinContent(binIdx);
107  const double y2 = ratios[1]->GetBinContent(binIdx);
108  const double y3 = ratios[2]->GetBinContent(binIdx);
109  const double v[3] = {y1, y2, (y3-y1)/2};
110  const double m[9] = { 1, -1, 1,
111  -2, 2, -1,
112  1, 0, 0};
113  const TVectorD res = TMatrixD(3, 3, m) * TVectorD(3, v);
114  ret.back().emplace_back(0, res(0), res(1), res(2));
115  }
116 
117  // We're assuming here that the shifts are separated by exactly 1 sigma.
118  for(unsigned int shiftIdx = 1; shiftIdx < ratios.size()-2; ++shiftIdx){
119  const double y0 = ratios[shiftIdx-1]->GetBinContent(binIdx);
120  const double y1 = ratios[shiftIdx ]->GetBinContent(binIdx);
121  const double y2 = ratios[shiftIdx+1]->GetBinContent(binIdx);
122  const double y3 = ratios[shiftIdx+2]->GetBinContent(binIdx);
123 
124  const double v[4] = {y1, y2, (y2-y0)/2, (y3-y1)/2};
125  const double m[16] = { 2, -2, 1, 1,
126  -3, 3, -2, -1,
127  0, 0, 1, 0,
128  1, 0, 0, 0};
129  const TVectorD res = TMatrixD(4, 4, m) * TVectorD(4, v);
130  ret.back().emplace_back(res(0), res(1), res(2), res(3));
131  } // end for shiftIdx
132 
133  {
134  const int N = ratios.size()-3;
135  const double y0 = ratios[N ]->GetBinContent(binIdx);
136  const double y1 = ratios[N+1]->GetBinContent(binIdx);
137  const double y2 = ratios[N+2]->GetBinContent(binIdx);
138  const double v[3] = {y1, y2, (y2-y0)/2};
139  const double m[9] = {-1, 1, -1,
140  0, 0, 1,
141  1, 0, 0};
142  const TVectorD res = TMatrixD(3, 3, m) * TVectorD(3, v);
143  ret.back().emplace_back(0, res(0), res(1), res(2));
144  }
145  } // end for binIdx
146 
147  double stride = -1;
148  for(unsigned int i = 0; i < shifts.size()-1; ++i){
149  const double newStride = shifts[i+1]-shifts[i];
150  assert((stride < 0 || fabs(stride-newStride) < 1e-3) &&
151  "Variably-spaced syst templates are unsupported");
152  stride = newStride;
153  }
154 
155  // If the stride is actually not 1, need to rescale all the coefficients
156  for(std::vector<Coeffs>& cs: ret)
157  for(Coeffs& c: cs){
158  c = Coeffs(c.a/util::cube(stride),
159  c.b/util::sqr(stride),
160  c.c/stride,
161  c.d);}
162  return ret;
163  }
164 
165  //----------------------------------------------------------------------
166  std::vector<std::vector<PredictionInterp::Coeffs>> PredictionInterp::
167  FitComponent(const std::vector<double>& shifts,
168  const std::vector<IPrediction*>& preds,
169  Flavors::Flavors_t flav,
170  Current::Current_t curr,
172  const std::string& shortName) const
173  {
174  IPrediction* pNom = 0;
175  for(unsigned int i = 0; i < shifts.size(); ++i){
176  if(shifts[i] == 0) pNom = preds[i];
177  }
178  assert(pNom);
179 
180  // Do it this way rather than via fPredNom so that systematics evaluated
181  // relative to some alternate nominal (eg Birks C where the appropriate
182  // nominal is no-rock) can work.
183  const Spectrum nom = pNom->PredictComponent(fOscOrigin,
184  flav, curr, sign);
185 
186  std::vector<std::unique_ptr<TH1>> ratios;
187  for(auto& p: preds){
188  ratios.emplace_back(Ratio(p->PredictComponent(fOscOrigin,
189  flav, curr, sign),
190  nom).ToTH1());
191 
192  // Check none of the ratio values is utterly crazy
193  std::unique_ptr<TH1>& r = ratios.back();
194  for(int i = 0; i < r->GetNbinsX()+2; ++i){
195  const double y = r->GetBinContent(i);
196  if(y > 500){
197  std::cout << "PredictionInterp: WARNING, ratio in bin "
198  << i << " is " << y
199  << " for '" << shortName << "'. Ignoring." << std::endl;
200  r->SetBinContent(i, 1);
201  }
202  }
203  }
204 
205  return FitRatios(shifts, ratios);
206  }
207 
208  //----------------------------------------------------------------------
210  std::vector<std::vector<std::vector<Coeffs>>>& fits,
211  Sign::Sign_t sign) const
212  {
213  fits.resize(kNCoeffTypes);
214 
218 
219  fits[kNC] = FitComponent(sp.shifts, sp.preds, Flavors::kAll, Current::kNC, sign, sp.systName);
220 
222  }
223 
224  //----------------------------------------------------------------------
226  {
227  // No systs
228  if(fPreds.empty()){
229  if(fBinning.POT() > 0 || fBinning.Livetime() > 0) return;
230  }
231  // Already initialized
232  else if(!fPreds.empty() && !fPreds.begin()->second.fits.empty()) return;
233 
234  for(auto& it: fPreds){
235  ShiftedPreds& sp = it.second;
236 
237  if(fSplitBySign){
238  InitFitsHelper(sp, sp.fits, Sign::kNu);
240  }
241  else{
243  }
244  sp.nCoeffs = sp.fits[0][0].size();
245  }
246 
247  // Predict something, anything, so that we can know what binning to use
248  fBinning = fPredNom->Predict(fOscOrigin);
249  fBinning.Clear();
250  }
251 
252  //----------------------------------------------------------------------
254  fOscOrigin = oscSeed->Copy();
255  for(auto& it: fPreds) it.second.fits.clear();
256  }
257 
258  //----------------------------------------------------------------------
260  {
261  return fPredNom->Predict(calc);
262  }
263 
264  //----------------------------------------------------------------------
266  Flavors::Flavors_t flav,
267  Current::Current_t curr,
268  Sign::Sign_t sign) const
269  {
270  return fPredNom->PredictComponent(calc, flav, curr, sign);
271  }
272 
273  //----------------------------------------------------------------------
275  const SystShifts& shift) const
276  {
277  InitFits();
278 
279  return PredictComponentSyst(calc, shift,
282  Sign::kBoth);
283  }
284 
285  //----------------------------------------------------------------------
289  bool nubar,
290  const SystShifts& shift) const
291  {
292  // Save time by not shifting a spectrum that is all zeros anyway
293  if(s.POT() == 0 && s.Livetime() == 0) return s;
294 
295  if(nubar) assert(fSplitBySign);
296 
297  InitFits();
298 
299  // TODO histogram operations could be too slow
300  TH1D* h = s.ToTH1(s.POT());
301 
302  const unsigned int N = h->GetNbinsX()+2;
303  std::vector<double> corr(N,1.0);
304 
305  for(auto& it: fPreds){
306  const ISyst* syst = it.first;
307  const ShiftedPreds& sp = it.second;
308 
309  auto& fits = nubar ? sp.fitsNubar : sp.fits;
310 
311  double x = shift.GetShift(syst);
312 
313  if(x == 0) continue;
314 
315  int shiftBin = (x - sp.shifts[0])/sp.Stride();
316  shiftBin = std::max(0, shiftBin);
317  shiftBin = std::min(shiftBin, sp.nCoeffs-1);
318 
319  x -= sp.shifts[shiftBin];
320 
321  const double x_cube = util::cube(x);
322  const double x_sqr = util::sqr(x);
323 
324  for(unsigned int n = 0; n < N; ++n){
325  // Uncomment to debug crashes in this function
326  // assert(type < fits.size());
327  // assert(n < sp.fits[type].size());
328  // assert(shiftBin < int(sp.fits[type][n].size()));
329  const Coeffs& f = fits[type][n][shiftBin];
330 
331  corr[n] *= f.a*x_cube + f.b*x_sqr + f.c*x + f.d;
332  } // end for n
333  } // end for syst
334 
335  double* arr = h->GetArray();
336  for(unsigned int n = 0; n < N; ++n){
337  arr[n] *= std::max(corr[n], 0.);
338  }
339 
340  return Spectrum(std::unique_ptr<TH1D>(h), s.GetLabels(), s.GetBinnings(), s.POT(), s.Livetime());
341  }
342 
343  //----------------------------------------------------------------------
346  const TMD5* hash,
347  const SystShifts& shift,
348  Flavors::Flavors_t flav,
349  Current::Current_t curr,
351  CoeffsType type) const
352  {
353  if(fSplitBySign && sign == Sign::kBoth){
354  return (ShiftedComponent(calc, hash, shift, flav, curr, Sign::kAntiNu, type)+
355  ShiftedComponent(calc, hash, shift, flav, curr, Sign::kNu, type));
356  }
357 
358  // Must be the base case of the recursion to use the cache. Otherwise we
359  // can cache systematically shifted versions of our children, which is
360  // wrong. Also, some calcs won't hash themselves.
361  const bool canCache = (hash != 0);
362 
363  const Key_t key = {flav, curr, sign};
364  auto it = fNomCache.find(key);
365 
366  // Should the interpolation use the nubar fits?
367  const bool nubar = (fSplitBySign && sign == Sign::kAntiNu);
368 
369  // We have the nominal for this exact combination of flav, curr, sign, calc
370  // stored. Shift it and return.
371  if(canCache && it != fNomCache.end() && it->second.hash == *hash){
372  return ShiftSpectrum(it->second.nom, type, nubar, shift);
373  }
374 
375  // We need to compute the nominal again for whatever reason
376  const Spectrum nom = fPredNom->PredictComponent(calc, flav, curr, sign);
377 
378  if(canCache){
379  // Insert into the cache if not already there, or update if there but
380  // with old oscillation parameters.
381  if(it == fNomCache.end())
382  fNomCache.emplace(key, Val_t({*hash, nom}));
383  else
384  it->second = {*hash, nom};
385  }
386 
387  return ShiftSpectrum(nom, type, nubar, shift);
388  }
389 
390  //----------------------------------------------------------------------
392  const SystShifts& shift,
393  Flavors::Flavors_t flav,
394  Current::Current_t curr,
395  Sign::Sign_t sign) const
396  {
397  InitFits();
398 
399  Spectrum& ret = fBinning;
400  ret.Clear();
401 
402  if(ret.POT()==0) ret.OverridePOT(1e24);
403 
404  // Check that we're able to handle all the systs we were passed
405  for(const ISyst* syst: shift.ActiveSysts()){
406  if(fPreds.find(syst) == fPreds.end()){
407  std::cerr << "This PredictionInterp is not set up to handle the requested systematic: " << syst->ShortName() << std::endl;
408  abort();
409  }
410  } // end for syst
411 
412 
413  const TMD5* hash = calc ? calc->GetParamsHash() : 0;
414 
415  if(curr & Current::kCC){
416  if(flav & Flavors::kNuEToNuE) ret += ShiftedComponent(calc, hash, shift, Flavors::kNuEToNuE, Current::kCC, sign, kNueSurv);
417  if(flav & Flavors::kNuEToNuMu) ret += ShiftedComponent(calc, hash, shift, Flavors::kNuEToNuMu, Current::kCC, sign, kOther );
418  if(flav & Flavors::kNuEToNuTau) ret += ShiftedComponent(calc, hash, shift, Flavors::kNuEToNuTau, Current::kCC, sign, kOther );
419 
420  if(flav & Flavors::kNuMuToNuE) ret += ShiftedComponent(calc, hash, shift, Flavors::kNuMuToNuE, Current::kCC, sign, kNueApp );
421  if(flav & Flavors::kNuMuToNuMu) ret += ShiftedComponent(calc, hash, shift, Flavors::kNuMuToNuMu, Current::kCC, sign, kNumuSurv);
422  if(flav & Flavors::kNuMuToNuTau) ret += ShiftedComponent(calc, hash, shift, Flavors::kNuMuToNuTau, Current::kCC, sign, kOther );
423  }
424  if(curr & Current::kNC){
425  assert(flav == Flavors::kAll); // Don't know how to calculate anything else
426 
427  ret += ShiftedComponent(calc, hash, shift, Flavors::kAll, Current::kNC, sign, kNC);
428  }
429 
430  delete hash;
431 
432  return ret;
433  }
434 
435  //----------------------------------------------------------------------
436  void PredictionInterp::SaveTo(TDirectory* dir) const
437  {
438  TDirectory* tmp = gDirectory;
439 
440  dir->cd();
441  TObjString("PredictionInterp").Write("type");
442 
443 
444  fPredNom->SaveTo(dir->mkdir("pred_nom"));
445 
446 
447  for(auto it: fPreds){
448  const ShiftedPreds& sp = it.second;
449 
450  for(unsigned int i = 0; i < sp.shifts.size(); ++i){
451  if(!sp.preds[i]){
452  std::cout << "Can't save a PredictionInterp after MinimizeMemory()" << std::endl;
453  abort();
454  }
455  sp.preds[i]->SaveTo(dir->mkdir(TString::Format("pred_%s_%+d",
456  sp.systName.c_str(),
457  int(sp.shifts[i])).Data()));
458  } // end for i
459  } // end for it
460 
461  ana::SaveTo(*fOscOrigin, dir->mkdir("osc_origin"));
462 
463  if(!fPreds.empty()){
464  TH1F hSystNames("syst_names", ";Syst names", fPreds.size(), 0, fPreds.size());
465  int binIdx = 1;
466  for(auto it: fPreds){
467  hSystNames.GetXaxis()->SetBinLabel(binIdx++, it.second.systName.c_str());
468  }
469  hSystNames.Write("syst_names");
470  }
471 
472  TObjString split_sign = fSplitBySign ? "yes" : "no";
473  split_sign.Write("split_sign");
474 
475  tmp->cd();
476  }
477 
478  //----------------------------------------------------------------------
479  std::unique_ptr<PredictionInterp> PredictionInterp::LoadFrom(TDirectory* dir)
480  {
481  TObjString* tag = (TObjString*)dir->Get("type");
482  assert(tag);
483  assert(tag->GetString() == "PredictionInterp" ||
484  tag->GetString() == "PredictionInterp2"); // backwards compatibility
485 
486  std::unique_ptr<PredictionInterp> ret(new PredictionInterp);
487 
488  LoadFromBody(dir, ret.get());
489 
490  TObjString* split_sign = (TObjString*)dir->Get("split_sign");
491  // Can be missing from old files
492  ret->fSplitBySign = (split_sign && split_sign->String() == "yes");
493 
494  return ret;
495  }
496 
497  //----------------------------------------------------------------------
498  void PredictionInterp::LoadFromBody(TDirectory* dir, PredictionInterp* ret,
499  std::vector<const ISyst*> veto)
500  {
501  ret->fPredNom = ana::LoadFrom<IPrediction>(dir->GetDirectory("pred_nom"));
502 
503  TH1* hSystNames = (TH1*)dir->Get("syst_names");
504  if(hSystNames){
505  for(int systIdx = 0; systIdx < hSystNames->GetNbinsX(); ++systIdx){
506  ShiftedPreds sp;
507  sp.systName = hSystNames->GetXaxis()->GetBinLabel(systIdx+1);
508 
509  const ISyst* syst = SystRegistry::ShortNameToSyst(sp.systName);
510 
511  if(std::find(veto.begin(), veto.end(), syst) != veto.end()) continue;
512 
513  for(int shift = -3; shift <= +3; ++shift){
514  TDirectory* preddir = dir->GetDirectory(TString::Format("pred_%s_%+d", sp.systName.c_str(), shift).Data());
515  if(!preddir) continue; // Can happen for genie systs
516 
517  IPrediction* pred = ana::LoadFrom<IPrediction>(preddir).release();
518 
519  sp.shifts.push_back(shift);
520  sp.preds.push_back(pred);
521  } // end for shift
522 
523  ret->fPreds.emplace(syst, sp);
524  } // end for systIdx
525  } // end if hSystNames
526 
527  ret->fOscOrigin = ana::LoadFrom<osc::IOscCalc>(dir->GetDirectory("osc_origin")).release();
528  }
529 
530  //----------------------------------------------------------------------
532  {
533  InitFits();
534 
535  std::set<IPrediction*> todel;
536  for(auto& it: fPreds){
537  std::vector<IPrediction*>& preds = it.second.preds;
538  for(unsigned int i = 0; i < preds.size(); ++i){
539  if(preds[i] != fPredNom.get()){
540  todel.insert(preds[i]);
541  preds[i] = 0;
542  }
543  }
544  }
545 
546  for(IPrediction* p: todel) delete p;
547 
548  // We probably just freed up a lot of memory, but malloc by default hangs
549  // on to all of it as cache.
550  #ifndef DARWINBUILD
551  malloc_trim(0);
552  #endif
553  }
554 
555  //----------------------------------------------------------------------
557  osc::IOscCalc* calc,
558  Flavors::Flavors_t flav,
559  Current::Current_t curr,
560  Sign::Sign_t sign) const
561  {
562  DontAddDirectory guard;
563 
564  InitFits();
565 
566  auto it = fPreds.find(syst);
567  if(it == fPreds.end()){
568  std::cout << "PredictionInterp::DebugPlots(): "
569  << syst->ShortName() << " not found" << std::endl;
570  return;
571  }
572 
573  std::unique_ptr<TH1> nom(fPredNom->PredictComponent(calc, flav, curr, sign).ToTH1(18e20));
574  const int nbins = nom->GetNbinsX();
575 
576  std::vector<TGraph*> curves(nbins);
577  std::vector<TGraph*> points(nbins);
578 
579  for(int i = 0; i <= 80; ++i){
580  const double x = .1*i-4;
581  const SystShifts ss(it->first, x);
582  std::unique_ptr<TH1> h(PredictComponentSyst(calc, ss, flav, curr, sign).ToTH1(18e20));
583 
584  for(int bin = 0; bin < nbins; ++bin){
585  if(i == 0){
586  curves[bin] = new TGraph;
587  points[bin] = new TGraph;
588  }
589 
590  const double ratio = h->GetBinContent(bin+1)/nom->GetBinContent(bin+1);
591 
592  if(!std::isnan(ratio)) curves[bin]->SetPoint(curves[bin]->GetN(), x, ratio);
593  else curves[bin]->SetPoint(curves[bin]->GetN(), x, 1);
594  } // end for bin
595  } // end for i (x)
596 
597  // As elswhere, to allow BirksC etc that need a different nominal to plot
598  // right.
599  IPrediction* pNom = 0;
600  for(unsigned int shiftIdx = 0; shiftIdx < it->second.shifts.size(); ++shiftIdx){
601  if(it->second.shifts[shiftIdx] == 0) pNom = it->second.preds[shiftIdx];
602  }
603  assert(pNom);
604  std::unique_ptr<TH1> hnom(pNom->PredictComponent(calc, flav, curr, sign).ToTH1(18e20));
605 
606  for(unsigned int shiftIdx = 0; shiftIdx < it->second.shifts.size(); ++shiftIdx){
607  if(!it->second.preds[shiftIdx]) continue; // Probably MinimizeMemory()
608  std::unique_ptr<TH1> h(it->second.preds[shiftIdx]->PredictComponent(calc, flav, curr, sign).ToTH1(18e20));
609 
610  for(int bin = 0; bin < nbins; ++bin){
611  const double ratio = h->GetBinContent(bin+1)/hnom->GetBinContent(bin+1);
612  if(!std::isnan(ratio)) points[bin]->SetPoint(points[bin]->GetN(), it->second.shifts[shiftIdx], ratio);
613  else points[bin]->SetPoint(points[bin]->GetN(), it->second.shifts[shiftIdx], 1);
614  }
615  } // end for shiftIdx
616 
617 
618  int nx = int(sqrt(nbins));
619  int ny = int(sqrt(nbins));
620  if(nx*ny < nbins) ++nx;
621  if(nx*ny < nbins) ++ny;
622 
623  TCanvas* c = new TCanvas;
624  c->Divide(nx, ny);
625 
626  for(int bin = 0; bin < nbins; ++bin){
627  c->cd(bin+1);
628  (new TH2F(UniqueName().c_str(),
629  TString::Format("%s %g < %s < %g;Shift;Ratio",
630  it->second.systName.c_str(),
631  nom->GetXaxis()->GetBinLowEdge(bin+1),
632  nom->GetXaxis()->GetTitle(),
633  nom->GetXaxis()->GetBinUpEdge(bin+1)),
634  100, -4, +4, 100, .5, 1.5))->Draw();
635  curves[bin]->Draw("l same");
636  points[bin]->SetMarkerStyle(kFullDotMedium);
637  points[bin]->Draw("p same");
638  } // end for bin
639 
640  c->cd(0);
641  }
642 
643  //----------------------------------------------------------------------
645  const std::string& savePattern,
646  Flavors::Flavors_t flav,
647  Current::Current_t curr,
648  Sign::Sign_t sign) const
649  {
650  const bool save = !savePattern.empty();
651  const bool multiFile = savePattern.find("%s") != std::string::npos;
652 
653  if(save && !multiFile){
654  new TCanvas;
655  gPad->Print((savePattern+"[").c_str());
656  }
657 
658  for(auto& it: fPreds){
659  DebugPlot(it.first, calc, flav, curr, sign);
660 
661  if(save){
662  if(multiFile){
663  gPad->Print(TString::Format(savePattern.c_str(), it.second.systName.c_str()).Data());
664  }
665  else{
666  gPad->Print(savePattern.c_str());
667  }
668  }
669  } // end for it
670 
671  if(save && !multiFile){
672  gPad->Print((savePattern+"]").c_str());
673  }
674  }
675 
676  //----------------------------------------------------------------------
678  osc::IOscCalc* calc,
679  Flavors::Flavors_t flav,
680  Current::Current_t curr,
681  Sign::Sign_t sign) const
682  {
683  InitFits();
684 
685  std::unique_ptr<TH1> nom(fPredNom->PredictComponent(calc, flav, curr, sign).ToTH1(18e20));
686  const int nbins = nom->GetNbinsX();
687 
688  TH2* h2 = new TH2F("", (syst->LatexName()+";;#sigma").c_str(),
689  nbins, nom->GetXaxis()->GetXmin(), nom->GetXaxis()->GetXmax(),
690  80, -4, +4);
691  h2->GetXaxis()->SetTitle(nom->GetXaxis()->GetTitle());
692 
693  for(int i = 1; i <= 80; ++i){
694  const double y = h2->GetYaxis()->GetBinCenter(i);
695  const SystShifts ss(syst, y);
696  std::unique_ptr<TH1> h(PredictComponentSyst(calc, ss, flav, curr, sign).ToTH1(18e20));
697 
698  for(int bin = 0; bin < nbins; ++bin){
699  const double ratio = h->GetBinContent(bin+1)/nom->GetBinContent(bin+1);
700 
701  if(!isnan(ratio) && !isinf(ratio))
702  h2->Fill(h2->GetXaxis()->GetBinCenter(bin), y, ratio);
703  } // end for bin
704  } // end for i (x)
705 
706  h2->Draw("colz");
707  h2->SetMinimum(0.5);
708  h2->SetMaximum(1.5);
709  }
710 
711  //----------------------------------------------------------------------
713  const std::string& savePattern,
714  Flavors::Flavors_t flav,
715  Current::Current_t curr,
716  Sign::Sign_t sign) const
717  {
718  const bool save = !savePattern.empty();
719  const bool multiFile = savePattern.find("%s") != std::string::npos;
720 
721  if(save && !multiFile){
722  new TCanvas;
723  gPad->Print((savePattern+"[").c_str());
724  }
725 
726  for(auto it: fPreds){
727  new TCanvas;
728  DebugPlotColz(it.first, calc, flav, curr, sign);
729 
730  if(save){
731  if(multiFile){
732  gPad->Print(TString::Format(savePattern.c_str(), it.second.systName.c_str()).Data());
733  }
734  else{
735  gPad->Print(savePattern.c_str());
736  }
737  }
738  } // end for it
739 
740  if(save && !multiFile){
741  gPad->Print((savePattern+"]").c_str());
742  }
743  }
744 
745 } // namespace
virtual Spectrum PredictComponent(osc::IOscCalc *calc, Flavors::Flavors_t flav, Current::Current_t curr, Sign::Sign_t sign) const override
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.
Implements systematic errors by interpolation between shifted templates.
Antineutrinos-only.
Definition: IPrediction.h:49
void SetShift(const ISyst *syst, double shift)
Shifts are 0=nominal, -1,+1 = 1 sigma shifts.
Definition: SystShifts.cxx:47
virtual Spectrum PredictSyst(osc::IOscCalc *calc, const SystShifts &shift) const override
std::string systName
What systematic we&#39;re interpolating.
process_name opflash particleana ie x
(&#39; appearance&#39;)
Definition: IPrediction.h:17
BEGIN_PROLOG could also be cerr
Simple record of shifts applied to systematic parameters.
Definition: SystShifts.h:16
void OverridePOT(double newpot)
DO NOT USE UNLESS YOU ARE 110% CERTAIN THERE ISN&#39;T A BETTER WAY!
Definition: Spectrum.h:295
(&#39;beam &#39;)
Definition: IPrediction.h:14
Collection of SpectrumLoaders for many configurations.
Definition: Loaders.h:12
pdgs p
Definition: selectors.fcl:22
std::vector< std::vector< std::vector< Coeffs > > > fitsNubar
Will be filled if signs are separated, otherwise not.
virtual void SaveTo(TDirectory *dir) const override
void SetOscSeed(osc::IOscCalc *oscSeed)
std::vector< std::vector< Coeffs > > FitRatios(const std::vector< double > &shifts, const std::vector< std::unique_ptr< TH1 >> &ratios) const
Find coefficients describing this set of shifts.
process_name opflashCryoW ana
T cube(T x)
More efficient cube function than pow(x,3)
Definition: MathUtil.h:26
void DebugPlotsColz(osc::IOscCalc *calc, const std::string &savePattern="", Flavors::Flavors_t flav=Flavors::kAll, Current::Current_t curr=Current::kBoth, Sign::Sign_t sign=Sign::kBoth) const
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
virtual std::string ShortName() const final
The name printed out to the screen.
Definition: ISyst.h:30
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
fSplitBySign(mode==kSplitBySign)
Representation of a spectrum in any variable, with associated POT.
Definition: Spectrum.h:30
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
std::unique_ptr< IPrediction > fPredNom
The nominal prediction.
std::map< Key_t, Val_t > fNomCache
while getopts h
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Charged-current interactions.
Definition: IPrediction.h:38
Interactions of both types.
Definition: IPrediction.h:41
process_name opflash particleana ie ie y
std::vector< double > shifts
Shift values sampled.
const char mode
Definition: noise_ana.cxx:20
std::vector< IPrediction * > preds
double GetShift(const ISyst *syst) const
Definition: SystShifts.cxx:56
Spectrum fBinning
Dummy spectrum to provide binning.
double POT() const
Definition: Spectrum.h:289
void DebugPlots(osc::IOscCalc *calc, const std::string &savePattern="", Flavors::Flavors_t flav=Flavors::kAll, Current::Current_t curr=Current::kBoth, Sign::Sign_t sign=Sign::kBoth) const
Represent the ratio between two spectra.
Definition: Ratio.h:8
Neutrinos-only.
Definition: IPrediction.h:48
static std::unique_ptr< PredictionInterp > LoadFrom(TDirectory *dir)
(&#39; survival&#39;)
Definition: IPrediction.h:18
tuple dir
Definition: dropbox.py:28
Taus, numu appearance.
static const ISyst * ShortNameToSyst(const std::string &s, bool allowFail=false)
int sign(double val)
Definition: UtilFunc.cxx:104
void DebugPlotColz(const ISyst *syst, osc::IOscCalc *calc, Flavors::Flavors_t flav=Flavors::kAll, Current::Current_t curr=Current::kBoth, Sign::Sign_t sign=Sign::kBoth) const
std::unique_ptr< IPrediction > LoadFrom< IPrediction >(TDirectory *dir)
Definition: IPrediction.cxx:26
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
process_name largeant stream1 can override from command line with o or output physics producers generator N
do i e
Neutral-current interactions.
Definition: IPrediction.h:39
virtual Spectrum PredictComponent(osc::IOscCalc *calc, Flavors::Flavors_t flav, Current::Current_t curr, Sign::Sign_t sign) const =0
Both neutrinos and antineutrinos.
Definition: IPrediction.h:51
Standard interface to all prediction techniques.
Definition: IPrediction.h:58
std::vector< const ISyst * > ActiveSysts() const
Definition: SystShifts.cxx:120
void DebugPlot(const ISyst *syst, osc::IOscCalc *calc, Flavors::Flavors_t flav=Flavors::kAll, Current::Current_t curr=Current::kBoth, Sign::Sign_t sign=Sign::kBoth) const
void InitFitsHelper(ShiftedPreds &sp, std::vector< std::vector< std::vector< Coeffs >>> &fits, Sign::Sign_t sign) const
virtual std::string LatexName() const final
The name used on plots (ROOT&#39;s TLatex syntax)
Definition: ISyst.h:33
Given loaders and an MC shift, Generate() generates an IPrediction.
std::vector< std::string > GetLabels() const
Definition: Spectrum.h:324
std::unordered_map< const ISyst *, ShiftedPreds > fPreds
osc::IOscCalc * fOscOrigin
The oscillation values we assume when evaluating the coefficients.
All neutrinos, any flavor.
Definition: IPrediction.h:25
(&#39; appearance&#39;)
Definition: IPrediction.h:15
Prevent histograms being added to the current directory.
std::vector< std::vector< Coeffs > > FitComponent(const std::vector< double > &shifts, const std::vector< IPrediction * > &preds, Flavors::Flavors_t flav, Current::Current_t curr, Sign::Sign_t sign, const std::string &shortName) const
Find coefficients describing the ratios from this component.
esac echo uname r
virtual Spectrum PredictComponentSyst(osc::IOscCalc *calc, const SystShifts &shift, Flavors::Flavors_t flav, Current::Current_t curr, Sign::Sign_t sign) const override
double Livetime() const
Seconds. For informational purposes only. No calculations use this.
Definition: Spectrum.h:292
virtual Spectrum Predict(osc::IOscCalc *calc) const override
Spectrum ShiftedComponent(osc::IOscCalc *calc, const TMD5 *hash, const SystShifts &shift, Flavors::Flavors_t flav, Current::Current_t curr, Sign::Sign_t sign, CoeffsType type) const
Helper for PredictComponentSyst.
std::string UniqueName()
Return a different string each time, for creating histograms.
void SaveTo(const osc::IOscCalc &x, TDirectory *dir)
Spectrum ShiftSpectrum(const Spectrum &s, CoeffsType type, bool nubar, const SystShifts &shift) const
BEGIN_PROLOG could also be cout
std::vector< Binning > GetBinnings() const
Definition: Spectrum.h:325
std::vector< std::vector< std::vector< Coeffs > > > fits
Indices: [type][histogram bin][shift bin].