All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sbnana/sbnana/CAFAna/Analysis/Surface.cxx
Go to the documentation of this file.
2 
10 
11 #include "OscLib/IOscCalc.h"
12 
13 #include "TCanvas.h"
14 #include "TGraph.h"
15 #include "TH2.h"
16 #include "TMarker.h"
17 #include "Minuit2/StackAllocator.h"
18 #include "TObjArray.h"
19 #include "TPad.h"
20 #include "TROOT.h"
21 #include "TStyle.h"
22 #include "TKey.h"
23 #include "TVectorD.h"
24 #include "TObjString.h"
25 #include "TCollection.h"
26 
27 #include <iostream>
28 #include <functional>
29 
30 namespace ana
31 {
32  inline double BinCenter(const TAxis* ax, int bin, bool islog)
33  {
34  return islog ? ax->GetBinCenterLog(bin) : ax->GetBinCenter(bin);
35  }
36 
37  //----------------------------------------------------------------------
40  const FitAxis& xax,
41  const FitAxis& yax,
42  const std::vector<const IFitVar*>& profVars,
43  const std::vector<const ISyst*>& profSysts,
44  const std::map<const IFitVar*, std::vector<double>>& seedPts,
45  const std::vector<SystShifts>& systSeedPts,
46  bool parallel,
48  : fParallel(parallel), fPrec(prec), fLogX(xax.islog), fLogY(yax.islog)
49  {
50  fHist = ExpandedHistogram(";"+xax.var->LatexName()+";"+yax.var->LatexName(),
51  xax.nbins, xax.min, xax.max, xax.islog,
52  yax.nbins, yax.min, yax.max, yax.islog);
53 
54  for(unsigned int i = 0; i < profVars.size()+profSysts.size(); ++i){
55  std::string title;
56  if(i < profVars.size())
57  title = profVars[i]->LatexName();
58  else
59  title = profSysts[i-profVars.size()]->LatexName();
60 
62  (title+";"+xax.var->LatexName()+";"+yax.var->LatexName(),
63  xax.nbins, xax.min, xax.max, xax.islog,
64  yax.nbins, yax.min, yax.max, yax.islog));
65  }
66 
67  std::string progTitle = "Filling surface for "+yax.var->ShortName()+" vs "+xax.var->ShortName();
68 
69  if(!profVars.empty() || !profSysts.empty()){
70  progTitle += " (profiling ";
71 
72  for(const IFitVar* v: profVars) {
73  progTitle += v->ShortName() + ", ";
74  fSeedValues.push_back( v->GetValue( calc ) );
75  }
76  for(const ISyst* s: profSysts)
77  progTitle += s->ShortName() + ", ";
78 
79  // Always have one superfluous ", " at the end
80  progTitle.resize(progTitle.size()-2);
81  progTitle += ")";
82  }
83 
84  FillSurface(progTitle, expt, calc, xax, yax, profVars, profSysts, seedPts, systSeedPts);
85 
86  // Location of the best minimum found from filled surface
87  double minchi = 1e10;
88  int minx = xax.nbins/2;
89  int miny = yax.nbins/2;
90  for(int x = 1; x < xax.nbins+1; ++x){
91  for(int y = 1; y < yax.nbins+1; ++y){
92  const int bin = (y-1)*fHist->GetNbinsX() + (x-1);
93  if(RunningOnGrid() && NumJobs() > 1
94  && !std::count(fBinMask.begin(), fBinMask.end(), bin)) continue;
95  const double chi = fHist->GetBinContent(x, y);
96  if(chi < minchi && !isnan(chi) && !isinf(chi)){
97  minchi = chi;
98  minx = x;
99  miny = y;
100  }
101  }
102  }
103 
104  std::vector<const IFitVar*> allVars = {xax.var, yax.var};
105  allVars.insert(allVars.end(), profVars.begin(), profVars.end());
106  Fitter fit(expt, allVars, profSysts);
107  fit.SetPrecision(fPrec);
108  // Seed from best grid point
109  xax.var->SetValue(calc, BinCenter(fHist->GetXaxis(), minx, xax.islog));
110  yax.var->SetValue(calc, BinCenter(fHist->GetYaxis(), miny, yax.islog));
111  for(int i = 0; i < (int)fSeedValues.size(); ++i) profVars[i]->SetValue( calc, fSeedValues[i] );
112  SystShifts systSeed = SystShifts::Nominal();
113  fMinChi = fit.Fit(calc, systSeed, seedPts);
114  fMinX = xax.var->GetValue(calc);
115  fMinY = yax.var->GetValue(calc);
116 
117  for(int x = 0; x < xax.nbins+2; ++x){
118  for(int y = 0; y < yax.nbins+2; ++y){
119  fHist->SetBinContent(x, y, fHist->GetBinContent(x, y)-fMinChi);
120  }
121  }
122 
123  fHist->SetMinimum(0);
124  }
125 
126  //----------------------------------------------------------------------
129  const IFitVar* xvar, int nbinsx, double xmin, double xmax,
130  const IFitVar* yvar, int nbinsy, double ymin, double ymax,
131  const std::vector<const IFitVar*>& profVars,
132  const std::vector<const ISyst*>& profSysts,
133  const std::map<const IFitVar*, std::vector<double>>& seedPts,
134  const std::vector<SystShifts>& systSeedPts,
135  bool parallel,
137  : Surface(expt, calc,
138  FitAxis(xvar, nbinsx, xmin, xmax),
139  FitAxis(yvar, nbinsy, ymin, ymax),
140  profVars, profSysts, seedPts, systSeedPts, parallel, prec)
141  {
142  }
143 
144  //---------------------------------------------------------------------
145  void Surface::FillSurface(const std::string& progTitle,
146  const IExperiment* expt,
148  const FitAxis& xax, const FitAxis& yax,
149  const std::vector<const IFitVar*>& profVars,
150  const std::vector<const ISyst*>& profSysts,
151  const std::map<const IFitVar*, std::vector<double>>& seedPts,
152  const std::vector<SystShifts>& systSeedPts)
153  {
154  if(fParallel && !(profVars.empty() && profSysts.empty())){
155  // Minuit calls this at some point, and it creates a static. Which
156  // doesn't like happening on multiple threads at once. So do it upfront
157  // while we're still single-threaded.
158  ROOT::Minuit2::StackAllocatorHolder::Get();
159  }
160 
161  // Nothing created during surface filling belongs in a
162  // directory. Unfortunately the local guards in Spectrum etc are racey when
163  // run in parallel. But this should cover the whole lot safely.
164  DontAddDirectory guard;
165 
166  Progress* prog = 0;
167  // Difficult to keep a progress bar properly up to date when threaded
168  if(!fParallel) prog = new Progress(progTitle);
169  ThreadPool* pool = 0;
170  if(fParallel){
171  pool = new ThreadPool;
172  pool->ShowProgress(progTitle);
173  }
174 
175  const int Nx = fHist->GetNbinsX();
176  const int Ny = fHist->GetNbinsY();
177 
178  // Fill bins in "random" order so that the progress bar is accurate
179  // straight away instead of possibly being misled by whatever atypical
180  // points we start with. This step is a prime which guarantees we get every
181  // cell.
182  int step = 7919;
183  // Very unlikely (Nx or Ny is a multiple of step), but just to be safe.
184  if((Nx*Ny)%step == 0) step = 1;
185 
186  int bin = 0;
187  int neval = 0;
188 
189  // Allow the surface to be parallelised across multiple jobs by splitting
190  // up the full surface into patches, and only running bins that fall inside
191  // a certain patch
192  int grid_stride = 1;
193  if(RunningOnGrid() && NumJobs() > 1){
194  grid_stride = NumJobs();
195  bin = (step*JobNumber()) % (Nx*Ny);
196  }
197 
198  do{
199  const int x = bin%Nx+1;
200  const int y = bin/Nx+1;
201 
202  const double xv = BinCenter(fHist->GetXaxis(), x, xax.islog);
203  const double yv = BinCenter(fHist->GetYaxis(), y, yax.islog);
204 
205  // For parallel running need to set these at point of use otherwise we
206  // race.
207  if(!fParallel){
208  xax.var->SetValue(calc, xv);
209  yax.var->SetValue(calc, yv);
210  }
211 
212  if(xax.var->Penalty(xv, calc) > 1e-10){
213  std::cerr << "Warning! " << xax.var->ShortName() << " = " << xv
214  << " has penalty of " << xax.var->Penalty(xv, calc)
215  << " that could have been applied in surface. "
216  << "This should never happen." << std::endl;
217  }
218  if(yax.var->Penalty(yv, calc) > 1e-10){
219  std::cerr << "Warning! " << yax.var->ShortName() << " = " << yv
220  << " has penalty of " << yax.var->Penalty(yv, calc)
221  << " that could have been applied in surface. "
222  << "This should never happen." << std::endl;
223  }
224 
225  if(fParallel){
227  expt, calc,
228  xax, xv, yax, yv,
229  profVars, profSysts, seedPts, systSeedPts);
230  }
231  else{
232  FillSurfacePoint(expt, calc,
233  xax, xv, yax, yv,
234  profVars, profSysts, seedPts, systSeedPts);
235  ++neval;
236  prog->SetProgress(neval*grid_stride/double(Nx*Ny));
237  }
238 
239  if(grid_stride > 1) fBinMask.push_back(bin);
240 
241  for(int i = 0; i < grid_stride; ++i){
242  bin = (bin + step) % (Nx * Ny);
243  if(bin == 0) break;
244  }
245  } while(bin != 0);
246 
247 
248  if(fParallel){
249  pool->Finish();
250  delete pool;
251  }
252  else{
253  prog->Done();
254  delete prog;
255  }
256  }
257 
258  /// \brief Helper for Surface::FillSurfacePoint
259  ///
260  /// The cacheing of the nominal done in PredictionInterp is not
261  /// threadsafe. This is an inelegant but pragmatic way of surpressing it.
263  {
264  public:
266 
267  osc::IOscCalcAdjustable* Copy() const override
268  {
269  std::cout << "Surface::OscCalcNoHash not copyable." << std::endl;
270  abort();
271  }
272  double P(int a, int b, double E) override {return fCalc->P(a, b, E);}
273  /// Marks this calc "unhashable" so the cacheing won't occur
274  TMD5* GetParamsHash() const override {return 0;}
275 
276  // It's a shame we have to forward all the getters and setters explicitly,
277  // but I don't see how to avoid it. Take away some drudgery with a macro.
278  void SetL(double x) override {fCalc->SetL(x);}
279  void SetRho(double x) override {fCalc->SetRho(x);}
280 #define F(v)\
281  void Set##v(const double& x) override {fCalc->Set##v(x);}\
282  double Get##v() const override {return fCalc->Get##v();}
283  F(Dmsq21); F(Dmsq32); F(Th12); F(Th13); F(Th23); F(dCP);
284 #undef F
285 
286  protected:
288  };
289 
290  //----------------------------------------------------------------------
293  const FitAxis& xax, double x,
294  const FitAxis& yax, double y,
295  const std::vector<const IFitVar*>& profVars,
296  const std::vector<const ISyst*>& profSysts,
297  const std::map<const IFitVar*, std::vector<double>>& seedPts,
298  const std::vector<SystShifts>& systSeedPts)
299  {
300  osc::IOscCalcAdjustable* calcNoHash = 0; // specific to parallel mode
301 
302  if(fParallel){
303  // Need to take our own copy so that we don't get overwritten by someone
304  // else's changes.
305  calc = calc->Copy();
306  xax.var->SetValue(calc, x);
307  yax.var->SetValue(calc, y);
308 
309  calcNoHash = new OscCalcNoHash(calc);
310  }
311 
312  //Make sure that the profiled values of fitvars do not persist between steps.
313  for(int i = 0; i < (int)fSeedValues.size(); ++i) profVars[i]->SetValue( calc, fSeedValues[i] );
314 
315  double chi;
316  if(profVars.empty() && profSysts.empty()){
317  chi = expt->ChiSq(fParallel ? calcNoHash : calc);
318  }
319  else{
320  Fitter fitter(expt, profVars, profSysts);
321  fitter.SetPrecision(fPrec);
322  SystShifts bestSysts;
323  chi = fitter.Fit(calc, bestSysts, seedPts, systSeedPts, Fitter::kQuiet);
324 
325  for(unsigned int i = 0; i < profVars.size(); ++i){
326  fProfHists[i]->Fill(x, y, profVars[i]->GetValue(calc));
327  }
328  for(unsigned int j = 0; j < profSysts.size(); ++j){
329  fProfHists[j+profVars.size()]->Fill(x, y, bestSysts.GetShift(profSysts[j]));
330  }
331  }
332 
333  fHist->Fill(x, y, chi);
334 
335  if(fParallel){
336  delete calc;
337  delete calcNoHash;
338  }
339  }
340 
341  //---------------------------------------------------------------------
342  void Surface::EnsureAxes() const
343  {
344  // Could have a file temporarily open
345  DontAddDirectory guard;
346 
347  // If this pad has already been drawn in, already has axes
348  if(gPad && !gPad->GetListOfPrimitives()->IsEmpty()) return;
349 
350  // Old, hackier solution
351  /*
352  std::cout << gPad->GetListOfPrimitives()->GetEntries() << std::endl;
353  // Which pads have we already drawn axes in? Never draw axes in them
354  // again. Unfortunately UniqueID() never seems to be set. If that's the
355  // case, set it to a random value and hope...
356  static std::set<UInt_t> already;
357  if(already.count(gPad->GetUniqueID())) return;
358  if(gPad->GetUniqueID() == 0) gPad->SetUniqueID(rand());
359  already.insert(gPad->GetUniqueID());
360  */
361 
362  const TAxis* ax = fHist->GetXaxis();
363  const TAxis* ay = fHist->GetYaxis();
364  const double Nx = ax->GetNbins();
365  const double Ny = ay->GetNbins();
366 
367  // Axes with limits where the user originally requested them, which we
368  // adjusted to be the centres of the first and last bins.
369  TH2* axes = new TH2C(UniqueName().c_str(),
370  TString::Format(";%s;%s",
371  ax->GetTitle(), ay->GetTitle()),
372  Nx-1, BinCenter(ax, 1, fLogX), BinCenter(ax, Nx, fLogX),
373  Ny-1, BinCenter(ay, 1, fLogY), BinCenter(ay, Ny, fLogY));
374  axes->Draw();
375 
376  if(fHist){
377  // "colz same" will reuse axis's min and max, so set them helpfully here
378  axes->SetMinimum(fHist->GetMinimum());
379  axes->SetMaximum(fHist->GetMaximum());
380  }
381 
382  axes->SetTitle(fHist->GetTitle());
383  axes->GetXaxis()->SetLabelSize(ax->GetLabelSize());
384  axes->GetYaxis()->SetLabelSize(ay->GetLabelSize());
385  axes->GetXaxis()->SetLabelOffset(ax->GetLabelOffset());
386  axes->GetYaxis()->SetLabelOffset(ay->GetLabelOffset());
387  axes->GetXaxis()->CenterTitle();
388  axes->GetYaxis()->CenterTitle();
389 
390  if(fLogX) gPad->SetLogx();
391  if(fLogY) gPad->SetLogy();
392 
393  gPad->Update();
394  }
395 
396  //---------------------------------------------------------------------
397  void Surface::Draw() const
398  {
399  EnsureAxes();
400 
401  fHist->Draw("colz same");
402 
403  // colz obliterated them
404  gPad->RedrawAxis();
405 
406  gPad->Update();
407  }
408 
409  //---------------------------------------------------------------------
410  void Surface::DrawBestFit(Color_t color, Int_t marker) const
411  {
412  CheckMask("DrawBestFit");
413  EnsureAxes();
414 
415  TMarker* mark = new TMarker(fMinX, fMinY, marker);
416  mark->SetMarkerSize(1.5);
417  mark->SetMarkerColor(color);
418  mark->Draw();
419  gPad->Update();
420  }
421 
422  //----------------------------------------------------------------------
423  std::vector<TGraph*> Surface::GetGraphs(TH2* fc, double minchi)
424  {
425  CheckMask("GetGraphs");
426 
427  std::vector<TGraph*> ret;
428 
429  if(minchi < 0) minchi = fMinChi;
430  std::unique_ptr<TH2> surf((TH2*)fHist->Clone(UniqueName().c_str()));
431  surf->Add(fc, -1);
432 
433  TVirtualPad* bak = gPad;
434 
435  const bool wasbatch = gROOT->IsBatch();
436  gROOT->SetBatch(); // User doesn't want to see our temporary canvas
437  TCanvas tmp;
438 
439  gStyle->SetOptStat(0);
440 
441  const double level = minchi-fMinChi;
442  surf->SetContour(1, &level);
443  surf->Draw("cont list");
444 
445  tmp.Update();
446  tmp.Paint();
447 
448  gROOT->SetBatch(wasbatch);
449  gPad = bak;
450 
451  // The graphs we need (contained inside TLists, contained inside
452  // TObjArrays) are in the list of specials. But we need to be careful about
453  // types, because other stuff can get in here too (TDatabasePDG for
454  // example).
455  TCollection* specs = gROOT->GetListOfSpecials();
456 
457  TIter nextSpec(specs);
458  while(TObject* spec = nextSpec()){
459  if(!spec->InheritsFrom(TObjArray::Class())) continue;
460  TObjArray* conts = (TObjArray*)spec;
461 
462  if(conts->IsEmpty()) continue;
463 
464  if(!conts->At(0)->InheritsFrom(TList::Class())) continue;
465  TList* cont = (TList*)conts->At(0);
466 
467  TIter nextObj(cont);
468  // Contour could be split into multiple pieces
469  while(TObject* obj = nextObj()){
470  if(!obj->InheritsFrom(TGraph::Class())) continue;
471 
472  ret.push_back((TGraph*)obj->Clone(UniqueName().c_str()));
473  } // end for obj
474  } // end for spec
475 
476  return ret;
477  }
478 
479  //----------------------------------------------------------------------
480  void Surface::DrawContour(TH2* fc, Style_t style, Color_t color,
481  double minchi)
482  {
483  CheckMask("DrawContour");
484  EnsureAxes();
485 
486  std::vector<TGraph*> gs = GetGraphs(fc, minchi);
487 
488  for(TGraph* g: gs){
489  g->SetLineWidth(3);//2);
490  g->SetLineStyle(style);
491  g->SetLineColor(color);
492  g->Draw("l");
493  }
494 
495  gPad->Update();
496  }
497 
498  //----------------------------------------------------------------------
499  TH2F* Surface::ToTH2(double minchi) const
500  {
501  // Could have a file temporarily open
502  DontAddDirectory guard;
503 
504  TH2F* ret = new TH2F(*fHist);
505 
506  if(minchi >= 0){
507  for(int x = 0; x < ret->GetNbinsX()+2; ++x){
508  for(int y = 0; y < ret->GetNbinsY()+2; ++y){
509  ret->SetBinContent(x, y, ret->GetBinContent(x, y)+fMinChi-minchi);
510  }
511  }
512  }
513 
514  return ret;
515  }
516 
517  //----------------------------------------------------------------------
518  void Surface::SetTitle(const char* str)
519  {
520  fHist->SetTitle(str);
521  }
522 
523  //----------------------------------------------------------------------
524  /// Helper function for the gaussian approximation surfaces
525  TH2* Flat(double level, const Surface& s)
526  {
527  TH2* h = s.ToTH2();
528 
529  for(int x = 0; x < h->GetNbinsX()+2; ++x)
530  for(int y = 0; y < h->GetNbinsY()+2; ++y)
531  h->SetBinContent(x, y, level);
532 
533  return h;
534  }
535 
536  // See eg the statistics section of the PDG
537  TH2* Gaussian68Percent2D(const Surface& s){return Flat(2.30, s);}
538  TH2* Gaussian90Percent2D(const Surface& s){return Flat(4.61, s);}
539  TH2* Gaussian95Percent2D(const Surface& s){return Flat(5.99, s);}
540  TH2* Gaussian2Sigma2D (const Surface& s){return Flat(6.18, s);}
541  TH2* Gaussian99Percent2D(const Surface& s){return Flat(9.21, s);}
542  TH2* Gaussian3Sigma2D (const Surface& s){return Flat(11.83, s);}
543  TH2* Gaussian5Sigma2D (const Surface& s){return Flat(28.74, s);}
544 
545  TH2* Gaussian68Percent1D(const Surface& s){return Flat(1.00, s);}
546  TH2* Gaussian90Percent1D(const Surface& s){return Flat(2.71, s);}
547  TH2* Gaussian95Percent1D(const Surface& s){return Flat(3.84, s);}
548  TH2* Gaussian2Sigma1D (const Surface& s){return Flat(4.00, s);}
549  TH2* Gaussian99Percent1D(const Surface& s){return Flat(6.63, s);}
550  TH2* Gaussian3Sigma1D (const Surface& s){return Flat(9.00, s);}
551 
552  TH2* Gaussian90Percent1D1Sided(const Surface& s){return Flat(1.64, s);}
553  TH2* Gaussian95Percent1D1Sided(const Surface& s){return Flat(2.71, s);}
554  TH2* Gaussian99Percent1D1Sided(const Surface& s){return Flat(5.41, s);}
555  TH2* Gaussian3Sigma1D1Sided(const Surface& s){return Flat(7.74, s);}
556  TH2* Gaussian5Sigma1D1Sided(const Surface& s){return Flat(23.66, s);}
557 
558  //----------------------------------------------------------------------
559  void Surface::SaveTo(TDirectory* dir) const
560  {
561  TDirectory* tmp = gDirectory;
562  dir->cd();
563  TObjString("Surface").Write("type");
564 
565  TVectorD v(3);
566  v[0] = fMinChi;
567  v[1] = fMinX;
568  v[2] = fMinY;
569  v.Write("minValues");
570 
571  fHist->Write("hist");
572 
573  TVectorD s(fSeedValues.size(), &fSeedValues[0]);
574  s.Write("seeds");
575 
576  TDirectory* profDir = dir->mkdir("profHists");
577  int idx = 0;
578  for(auto it: fProfHists){
579  profDir->cd();
580  it->Write( TString::Format("hist%d", idx++));
581  }
582 
583  if(!fBinMask.empty()){
584  const std::vector<double> tmp(fBinMask.begin(), fBinMask.end());
585  TVectorD m(tmp.size(), &tmp[0]);
586  m.Write("mask");
587  }
588 
589  dir->cd();
590  TObjString(fLogX ? "yes" : "no").Write("logx");
591  TObjString(fLogY ? "yes" : "no").Write("logy");
592 
593  tmp->cd();
594  }
595 
596  //----------------------------------------------------------------------
597  std::unique_ptr< Surface > Surface::LoadFrom(TDirectory* dir)
598  {
599  DontAddDirectory guard;
600 
601  TObjString* tag = (TObjString*)dir->Get("type");
602  assert(tag);
603  assert(tag->GetString() == "Surface");
604 
605  const TVectorD v = *(TVectorD*)dir->Get("minValues");
606  const TVectorD s = *(TVectorD*)dir->Get("seeds");
607  const TVectorD* m = (TVectorD*)dir->Get("mask");
608 
609  std::unique_ptr<Surface> surf(new Surface);
610  surf->fHist = (TH2F*)dir->Get("hist");
611  surf->fMinChi = v[0];
612  surf->fMinX = v[1];
613  surf->fMinY = v[2];
614 
615  for(int idx = 0; idx < s.GetNrows(); ++idx){
616  surf->fSeedValues.push_back(s[idx]);
617  }
618 
619  for(int idx = 0; ; ++idx){
620  TH2* h = (TH2*)dir->Get(TString::Format("profHists/hist%d", idx));
621  if(h) surf->fProfHists.push_back(h); else break;
622  }
623 
624  if(m){
625  for(int idx = 0; idx < m->GetNrows(); ++idx)
626  surf->fBinMask.push_back((*m)[idx]);
627  }
628 
629  const TObjString* logx = (TObjString*)dir->Get("logx");
630  const TObjString* logy = (TObjString*)dir->Get("logy");
631  // Tolerate missing log tags for backwards compatibility
632  surf->fLogX = (logx && logx->GetString() == "yes");
633  surf->fLogY = (logy && logy->GetString() == "yes");
634 
635  return surf;
636  }
637 
638  //----------------------------------------------------------------------
639  std::unique_ptr<Surface> Surface::
640  LoadFromMulti(const std::vector<TFile*>& files, const std::string& label)
641  {
642  std::vector<std::unique_ptr<Surface>> surfs;
643  for(TFile* f: files) {
644  surfs.push_back(Surface::LoadFrom(f->GetDirectory(label.c_str())));
645  }
646 
647  int Nx = surfs[0]->fHist->GetNbinsX();
648  int Ny = surfs[0]->fHist->GetNbinsY();
649  size_t nbins = Nx * Ny;
650  std::vector<int> binMask;
651 
652  // Loop over the surfaces to check all bins are present
653  for(size_t i = 0; i < surfs.size(); ++i) {
654  for(int bin : surfs[i]->fBinMask) {
655  if (std::count(binMask.begin(), binMask.end(), bin))
656  assert(false && "Repeated bin found in surfaces being merged.");
657  binMask.push_back(bin);
658  }
659  }
660  if(binMask.size() != nbins) {
661  std::cout << "Missing bins found in surfaces being merged. "
662  << "Are you sure you included all files for this surface?"
663  << std::endl;
664  assert(false);
665  }
666 
667  // Create return surface and initialise with first in list
668  std::unique_ptr<Surface> ret(new Surface);
669  ret->fHist = new TH2F(*(TH2F*)surfs[0]->ToTH2(0));
670  ret->fMinChi = surfs[0]->fMinChi;
671  ret->fMinX = surfs[0]->fMinX;
672  ret->fMinY = surfs[0]->fMinY;
673  ret->fLogX = surfs[0]->fLogX;
674  ret->fLogY = surfs[0]->fLogY;
675  ret->fSeedValues = surfs[0]->fSeedValues;
676  for(TH2* h: surfs[0]->fProfHists)
677  ret->fProfHists.push_back((TH2F*)h->Clone());
678 
679  // Loop over other surfaces and add them in
680  for(size_t i = 1; i < surfs.size(); ++i) {
681  ret->fHist->Add(surfs[i]->ToTH2(0));
682  if(surfs[i]->fMinChi < ret->fMinChi) {
683  ret->fMinChi = surfs[i]->fMinChi;
684  ret->fMinX = surfs[i]->fMinX;
685  ret->fMinY = surfs[i]->fMinY;
686  }
687  for(size_t j = 0; j < ret->fProfHists.size(); ++j)
688  ret->fProfHists[j]->Add(surfs[i]->fProfHists[j]);
689  }
690 
691  // Scale hist by global minimum
692  for(int x = 0; x < ret->fHist->GetNbinsX()+2; ++x){
693  for(int y = 0; y < ret->fHist->GetNbinsY()+2; ++y){
694  ret->fHist->SetBinContent(x, y, ret->fHist->GetBinContent(x, y)-ret->fMinChi);
695  }
696  }
697 
698  ret->fHist->SetMinimum(0);
699 
700  return ret;
701  }
702 
703  //----------------------------------------------------------------------
704  std::unique_ptr<Surface> Surface::
705  LoadFromMulti(const std::string& wildcard, const std::string& label)
706  {
707  std::vector<std::string> fileNames = Wildcard(wildcard);
708  std::vector<TFile*> files;
709  for(std::string fileName : fileNames){
710  files.push_back(TFile::Open(fileName.c_str()));
711  }
712  std::unique_ptr<Surface> ret = LoadFromMulti(files, label);
713  for(TFile* f: files) delete f;
714  return ret;
715  }
716 
717  //----------------------------------------------------------------------
718  void Surface::CheckMask(const std::string& func) const
719  {
720  if(!fBinMask.empty()) {
721  std::cout << "Cannot call " << func << "() on a partial surface!" << std::endl;
722  abort();
723  }
724  }
725 
726 } // namespace
double BinCenter(const TAxis *ax, int bin, bool islog)
void Finish()
Wait for all threads to complete before returning.
Definition: ThreadPool.cxx:44
TH2 * Gaussian2Sigma1D(const Surface &s)
Up-value surface for 2 sigma confidence in 1D in gaussian approximation.
TH2 * Gaussian2Sigma2D(const Surface &s)
Up-value surface for 2 sigma confidence in 2D in gaussian approximation.
virtual std::string LatexName() const =0
void DrawBestFit(Color_t color, Int_t marker=kFullCircle) const
Draw the best fit point.
virtual double GetValue(const osc::IOscCalcAdjustable *osc) const =0
virtual std::string ShortName() const =0
Helper for Surface::FillSurfacePoint.
process_name opflash particleana ie x
BEGIN_PROLOG could also be cerr
TMD5 * GetParamsHash() const override
Marks this calc &quot;unhashable&quot; so the cacheing won&#39;t occur.
Log-likelihood scan across two parameters.
TH2 * Gaussian90Percent1D(const Surface &s)
Up-value surface for 90% confidence in 1D in gaussian approximation.
void SaveTo(TDirectory *dir) const
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
void FillSurfacePoint(const IExperiment *expt, osc::IOscCalcAdjustable *calc, const FitAxis &xax, double x, const FitAxis &yax, double y, 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)
TH2 * Gaussian95Percent2D(const Surface &s)
Up-value surface for 95% confidence in 2D in gaussian approximation.
void DrawContour(TH2 *fc, Style_t style, Color_t color, double minchi=-1)
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
const IFitVar * var
Definition: FitAxis.h:17
TH2 * Gaussian68Percent1D(const Surface &s)
Up-value surface for 68% confidence in 1D in gaussian approximation.
TH2 * Gaussian68Percent2D(const Surface &s)
Up-value surface for 68% confidence in 2D in gaussian approximation.
std::vector< std::string > Wildcard(const std::string &wildcardString)
process_name E
def style
Definition: util.py:237
void SetPrecision(Precision prec)
Definition: Fit.cxx:270
process_name opflashCryoW ana
TH2 * Gaussian90Percent2D(const Surface &s)
Up-value surface for 90% confidence in 2D in gaussian approximation.
static SystShifts Nominal()
Definition: SystShifts.h:23
void FillSurface(const std::string &progTitle, const IExperiment *expt, osc::IOscCalcAdjustable *calc, const FitAxis &xax, const FitAxis &yax, 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)
BEGIN_PROLOG g
Encapsulate code to systematically shift a caf::StandardRecord.
Definition: ISyst.h:14
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
Perform MINUIT fits in one or two dimensions.
Definition: Fit.h:37
TH2 * Gaussian95Percent1D(const Surface &s)
Up-value surface for 95% confidence in 1D in gaussian approximation.
TH2 * Gaussian3Sigma1D(const Surface &s)
Up-value surface for 3 sigma confidence in 1D in gaussian approximation.
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
TH2 * Gaussian5Sigma2D(const Surface &s)
Up-value surface for 5 sigma confidence in 2D in gaussian approximation.
process_name gaushit a
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
static std::unique_ptr< Surface > LoadFromMulti(const std::vector< TFile * > &files, const std::string &label)
while getopts h
TH2 * Gaussian99Percent2D(const Surface &s)
Up-value surface for 99% confidence in 2D in gaussian approximation.
TH2F * ExpandedHistogram(const std::string &title, int nbinsx, double xmin, double xmax, bool xlog, int nbinsy, double ymin, double ymax, bool ylog)
OscCalcNoHash(osc::IOscCalcAdjustable *c)
process_name opflash particleana ie ie y
double min
Definition: FitAxis.h:19
virtual void SetValue(osc::IOscCalcAdjustable *osc, double val) const =0
static std::unique_ptr< Surface > LoadFrom(TDirectory *dir)
TH2 * Gaussian3Sigma2D(const Surface &s)
Up-value surface for 3 sigma confidence in 2D in gaussian approximation.
virtual double Penalty(double, osc::IOscCalcAdjustable *) const
Definition: IFitVar.h:21
bool islog
Definition: FitAxis.h:21
int nbins
Definition: FitAxis.h:18
void AddMemberTask(T *obj, M meth, A...args)
Add member function task, with arguments.
Definition: ThreadPool.h:78
TH2 * Gaussian99Percent1D1Sided(const Surface &s)
Up-value surface for 99% confidence in 1D in 1-sided gaussian approxiamtion.
double max
Definition: FitAxis.h:20
TH2 * Gaussian90Percent1D1Sided(const Surface &s)
Up-value surface for 90% confidence in 1D in 1-sided gaussian approximation.
TH2 * Gaussian95Percent1D1Sided(const Surface &s)
Up-value surface for 95% confidence in 1D in 1-sided gaussian approximation.
void CheckMask(const std::string &func) const
double GetShift(const ISyst *syst) const
Definition: SystShifts.cxx:56
osc::IOscCalcAdjustable * Copy() const override
tuple dir
Definition: dropbox.py:28
void SetProgress(double frac)
Update the progress fraction between zero and one.
Definition: Progress.cxx:44
int prec
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
TH2 * Gaussian3Sigma1D1Sided(const Surface &s)
Up-value surface for 3 sigma confidence in 1D in 1-sided gaussian approximation.
Base class defining interface for experiments.
Definition: IExperiment.h:21
TH2 * Gaussian5Sigma1D1Sided(const Surface &s)
Up-value surface for 5 sigma confidence in 1D in 1-sided gaussian approximation.
do i e
void Draw() const
Draw the surface itself.
A very simple thread pool for use by Surface.
Definition: ThreadPool.h:17
A simple ascii-art progress bar.
Definition: Progress.h:9
void ShowProgress(const std::string &title)
Definition: ThreadPool.cxx:38
Interface definition for fittable variables.
Definition: IFitVar.h:14
TH2F * ToTH2(double minchi=-1) const
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
TH2 * Flat(double level, const Surface &s)
Helper function for the gaussian approximation surfaces.
std::size_t count(Cont const &cont)
Prevent histograms being added to the current directory.
prog
Definition: just_cmake.sh:3
void Done()
Call this when action is completed.
Definition: Progress.cxx:91
Precision
Definition: Fit.h:42
TH2 * Gaussian99Percent1D(const Surface &s)
Up-value surface for 99% confidence in 1D in gaussian approximation.
std::string UniqueName()
Return a different string each time, for creating histograms.
std::string LatexName(int pdgcode)
Convert PDG code to a latex string (root-style)
Definition: TruthText.cxx:12
BEGIN_PROLOG could also be cout
std::vector< TGraph * > GetGraphs(TH2 *fc, double minchi=-1)
For expert use, custom painting of contours.
Collect information describing the axis of a fit variable.
Definition: FitAxis.h:10
double P(int a, int b, double E) override