MaCh3  2.8.0
Reference Guide
PlotSigmaVariation.cpp
Go to the documentation of this file.
1 //MaCh3 Includes
4 
5 #pragma GCC diagnostic ignored "-Wfloat-conversion"
6 #pragma GCC diagnostic ignored "-Wconversion"
7 
12 
13 std::vector<std::string> DialNameVector;
14 std::vector<std::string> SampleNameVector;
15 std::vector<int> SampleMaxDim;
16 std::vector<double> sigmaArray;
17 
19 
20 constexpr const int NVars = 5;
21 constexpr Color_t Colours[NVars] = {kRed, kGreen+1, kBlack, kBlue+1, kOrange+1};
22 constexpr ELineStyle Style[NVars] = {kDotted, kDashed, kSolid, kDashDotted, kDashDotted};
23 
26 
28 void FindKnot(std::vector<double>& SigmaValues,
29  const std::string& dirname,
30  const std::string& subdirname,
31  const std::string& ProjName,
32  std::string histname) {
33  auto StripPrefix = [](std::string& str, const std::string& prefix) {
34  if (str.find(prefix + "_") == 0) {
35  str.erase(0, prefix.length() + 1);
36  if (str.find(prefix) == 0) {
37  MACH3LOG_ERROR("Failed to strip prefix '{}' from string '{}'", prefix, str);
38  throw MaCh3Exception(__FILE__, __LINE__);
39  }
40  } else {
41  MACH3LOG_ERROR("String '{}' does not start with expected prefix '{}'", str, prefix);
42  throw MaCh3Exception(__FILE__, __LINE__);
43  }
44  };
45 
46  // Remove sample and dial name to avoid potential issues
47  StripPrefix(histname, subdirname);
48  StripPrefix(histname, ProjName);
49  StripPrefix(histname, dirname);
50 
51  MACH3LOG_DEBUG("Name afters striping {}", histname);
52 
53  double sigma = 0.0;
54  // Find the "_sig_" part in the name
55  size_t sig_pos = histname.find("_sig_");
56 
57  // Extract the part after "_sig_"
58  std::string sigma_part = histname.substr(sig_pos + 5);
59 
60  // Check if it starts with 'n' (negative) or 'p' (positive) or 'nom' (0 or prior)
61  if (histname.find("nom_") != std::string::npos) {
62  sigma = 0.0;
63  PriorKnot = static_cast<int>(SigmaValues.size());
64  MACH3LOG_DEBUG("Found prior knot {}", PriorKnot);
65  } else if (sigma_part.size() > 0 && sigma_part[0] == 'n') {
66  sigma = -std::stod(sigma_part.substr(1));
67  } else if (sigma_part.size() > 0 && sigma_part[0] == 'p') {
68  sigma = std::stod(sigma_part.substr(1));
69  } else {
70  MACH3LOG_ERROR("Weirdly formatted string {}", sigma_part);
71  throw MaCh3Exception(__FILE__ , __LINE__ );
72  }
73  MACH3LOG_DEBUG("Adding sigma {}", sigma);
74 
75  SigmaValues.push_back(sigma);
76 }
77 
78 std::unique_ptr<TLegend> MakeLegend(double x1, double y1, double x2, double y2,
79  double textSize = 0.04)
80 {
81  auto leg = std::make_unique<TLegend>(x1, y1, x2, y2);
82  leg->SetTextSize(textSize);
83  leg->SetLineColor(0);
84  leg->SetLineStyle(0);
85  leg->SetFillColor(0);
86  leg->SetFillStyle(0);
87  leg->SetBorderSize(0);
88 
89  return leg;
90 }
91 
93 void ScanInput(std::vector<std::string>& DialNameVecr,
94  std::vector<std::string>& SampleNameVec,
95  std::vector<int>& SampleDimVec,
96  std::vector<double>& SigmaValues,
97  const std::string& filename)
98 {
99  MACH3LOG_DEBUG("Starting {}", __func__);
100  TFile *infile = M3::Open(filename, "OPEN", __FILE__, __LINE__);
101  TDirectoryFile *SigmaDir = infile->Get<TDirectoryFile>("SigmaVar");
102 
103  //Get all entries in input file
104  TIter next(SigmaDir->GetListOfKeys());
105  TKey *key = nullptr;
106 
107  // Loop over directory with dial names
108  while ((key = static_cast<TKey*>(next()))) {
109  // get directory names, ignore flux
110  auto classname = std::string(key->GetClassName());
111  auto dirname = std::string(key->GetName());
112 
113  if (classname != "TDirectoryFile") continue;
114  dirname = std::string(key->GetName());
115 
116  SigmaDir->cd(dirname.c_str());
117  TIter nextsub(gDirectory->GetListOfKeys());
118  TKey *subkey = nullptr;
119 
120  DialNameVecr.push_back(dirname);
121  MACH3LOG_DEBUG("Entering Dial {}", dirname);
122 
123  if(SampleNameVec.size() != 0) continue;
124  //loop over directories with sample names
125  while ((subkey = static_cast<TKey*>(nextsub())))
126  {
127  auto subdirname = std::string(subkey->GetName());
128  SampleNameVec.push_back(subdirname);
129  SampleDimVec.push_back(0);
130  MACH3LOG_DEBUG("Entering Sample {}", subdirname);
131  SigmaDir->cd((dirname + "/" + subdirname).c_str());
132 
133  TKey *subsubkey = nullptr;
134  TIter nextsubsub(gDirectory->GetListOfKeys());
135 
136  // Check if we already filled sigma vector
137  bool FillSigma = false;
138  if(SigmaValues.size() == 0) FillSigma = true;
139  // loop over histograms
140  while ((subsubkey = static_cast<TKey*>(nextsubsub())))
141  {
142  auto subsubdirname = std::string(subsubkey->GetTitle());
143  MACH3LOG_DEBUG("Entering Hist {}", subsubdirname);
144  std::string histname = subsubdirname;
145 
146  classname = std::string(subsubkey->GetClassName());
147 
148  if (classname != "TH1D") continue;
149  // Find if there is more dimensions
150  size_t proj_pos = histname.find("_1DProj");
151  int proj_number = -1;
152 
153  if (proj_pos != std::string::npos) {
154  size_t number_start = proj_pos + 7; // skip "_1DProj"
155  size_t number_end = histname.find_first_not_of("0123456789", number_start);
156  proj_number = std::stoi(histname.substr(number_start, number_end - number_start));
157  }
158  SampleDimVec.back() = std::max(proj_number, SampleDimVec.back());
159  MACH3LOG_DEBUG("Found dimension {} with dimension", proj_number);
160 
161  // KS: Extract knot position from hist only we haven't done this before and for projection X
162  // Sigma are same for projection Y and Z and beyond
163  if(FillSigma && proj_number == 0) FindKnot(SigmaValues, dirname, subdirname, "1DProj" + std::to_string(proj_number), histname);
164  }
165  }
166  }
167 
168  if(PriorKnot == M3::_BAD_INT_){
169  MACH3LOG_ERROR("Didn't find prior knot, something is not right...");
170  throw MaCh3Exception(__FILE__ , __LINE__ );
171  }
172 
173  if(sigmaArray.size() < NVars){
174  MACH3LOG_ERROR("Found sigma {}, while I have some hardcoding for {}",sigmaArray.size(), NVars);
175  throw MaCh3Exception(__FILE__ , __LINE__ );
176  }
177 
178  if(SampleNameVec.size() != SampleDimVec.size()) {
179  MACH3LOG_ERROR("Sample name vec ({}) and sample dimension vec ({}) have different sizes, something is not right");
180  throw MaCh3Exception(__FILE__ , __LINE__ );
181  }
182 
183  infile->Close();
184  delete infile;
185 }
186 
188 bool SkipDirectory(const std::vector<std::string>& ExcludeString, const std::vector<std::string>& IncludeString, const std::string& dirname)
189 {
190  bool Skip = false;
191  for(unsigned int i = 0; i < ExcludeString.size(); i++)
192  {
193  if (dirname.find(ExcludeString[i]) != std::string::npos){ Skip = true; break; }
194  }
195  for(unsigned int i = 0; i < IncludeString.size(); i++)
196  {
197  if (!(dirname.find(IncludeString[i]) != std::string::npos)){ Skip = true; break; }
198  }
199  return Skip;
200 }
201 
203 std::vector<double> GetDialValues(const std::vector<std::unique_ptr<TH1D>>& Poly) {
204  std::vector<double> values;
205  for (const auto& hist : Poly) {
206  std::string title = hist->GetTitle();
207  auto pos = title.rfind("_val_");
208  if (pos != std::string::npos) {
209  std::string val_str = title.substr(pos + 5); // skip "_val_"
210  double val = std::stod(val_str);
211  values.push_back(val);
212  MACH3LOG_DEBUG("Extracted dial value {} from title '{}'", val, title);
213  } else {
214  MACH3LOG_DEBUG("Failed to extract dial value from title '{}'", title);
215  throw MaCh3Exception(__FILE__, __LINE__);
216  }
217  }
218  return values;
219 }
220 
221 
222 void InitializePads(TCanvas* canv, TPad*& pad1, TPad*& pad2, double Pad1Bottom = 0.25, double Pad2Top = 0.25)
223 {
224  // Delete existing pads if they exist
225  if (pad1) delete pad1;
226  if (pad2) delete pad2;
227 
228  // Allocate new pads
229  pad1 = new TPad("pad1", "pad1", 0., Pad2Top, 1., 1.0);
230  pad2 = new TPad("pad2", "pad2", 0., 0., 1., Pad1Bottom);
231 
232  // Append pads to canvas
233  pad1->AppendPad();
234  pad2->AppendPad();
235 
236  // Set margins for pad1
237  pad1->SetLeftMargin(canv->GetLeftMargin());
238  pad1->SetRightMargin(canv->GetRightMargin());
239  pad1->SetTopMargin(canv->GetTopMargin());
240  pad1->SetBottomMargin(0);
241 
242  // Set margins for pad2
243  pad2->SetLeftMargin(canv->GetLeftMargin());
244  pad2->SetRightMargin(canv->GetRightMargin());
245  pad2->SetTopMargin(0);
246  pad2->SetBottomMargin(0.30);
247 
248  // Enable grid for both pads
249  pad1->SetGrid();
250  pad2->SetGrid();
251 }
252 
253 void MakeRatio(const std::vector<std::unique_ptr<TH1D>>& Poly,
254  std::vector<std::unique_ptr<TH1D>>& Ratio) {
255  size_t ratio_index = 0; // Track position in Ratio vector
256  for (int i = 0; i < static_cast<int>(Poly.size()); ++i) {
257  if (i == PriorKnot) continue; // Skip PriorKnot
258  Ratio[ratio_index] = M3::Clone(Poly[i].get());
259  Ratio[ratio_index]->Divide(Poly[PriorKnot].get());
260  ratio_index++;
261  }
262 
263  Ratio[0]->GetYaxis()->SetTitle("Ratio to Prior");
264  Ratio[0]->SetBit(TH1D::kNoTitle);
265 
267 }
268 
269 void PlotRatio(const std::vector<std::unique_ptr<TH1D>>& Poly,
270  const std::unique_ptr<TCanvas>& canv,
271  const std::string& Title,
272  const std::string& outfilename)
273 {
274  canv->Clear();
275  gStyle->SetDrawBorder(0);
276  gStyle->SetTitleBorderSize(2);
277  gStyle->SetOptStat(0); //Set 0 to disable statistic box
278  canv->SetGrid();
279  canv->SetTopMargin(0.10);
280  canv->SetBottomMargin(0.08);
281  canv->SetRightMargin(0.05);
282  canv->SetLeftMargin(0.12);
283 
284  TPad* pad1 = nullptr;
285  TPad* pad2 = nullptr;
286  InitializePads(canv.get(), pad1, pad2);
287 
288  pad1->cd();
289 
290  auto DialValues = GetDialValues(Poly);
291  double max = 0;
292  for(int ik = 0; ik < static_cast<int>(sigmaArray.size()); ++ik)
293  {
294  Poly[ik]->SetLineWidth(2.);
295  Poly[ik]->SetLineColor(Colours[ik]);
296  Poly[ik]->SetLineStyle(Style[ik]);
297  PlotMan->style().setTH1XRange(Poly[ik].get());
298  auto BinWidthScale = PlotMan->style().getBinWidthScale(Poly[ik]->GetXaxis()->GetTitle());
299  Poly[ik]->GetYaxis()->SetTitle(fmt::format("Events/{:.0f}", BinWidthScale).c_str());
300  M3::ScaleHistogram(Poly[ik].get(), BinWidthScale);
301  max = std::max(max, Poly[ik]->GetMaximum());
302  }
303  Poly[0]->SetTitle(Title.c_str());
304  Poly[0]->SetMaximum(max*1.2);
305  Poly[0]->Draw("HIST");
306  for(int ik = 1; ik < static_cast<int>(sigmaArray.size()); ++ik)
307  {
308  Poly[ik]->Draw("HIST SAME");
309  }
310 
311  std::vector<double> Integral(sigmaArray.size());
312  for(int ik = 0; ik < static_cast<int>(sigmaArray.size()); ++ik)
313  Integral[ik] = Poly[ik]->Integral();
314 
315  auto leg = MakeLegend(0.55, 0.55, 0.8, 0.88, 0.04);
316  leg->SetTextSize(0.04);
317  for (int j = 0; j < static_cast<int>(sigmaArray.size()); j++)
318  {
319  if(j == PriorKnot) {
320  leg->AddEntry(Poly[j].get(), Form("Prior (%.2f), #int=%.2f", DialValues[j], Integral[j]), "l");
321  } else {
322  leg->AddEntry(Poly[j].get(), Form("%.0f#sigma (%.2f), #int=%.2f", sigmaArray[j], DialValues[j], Integral[j]), "l");
323  }
324  }
325  leg->Draw("SAME");
326 
327  pad2->cd();
328 
329  TLine line(Poly[0]->GetXaxis()->GetBinLowEdge(Poly[0]->GetXaxis()->GetFirst()),
330  1.0, Poly[0]->GetXaxis()->GetBinUpEdge(Poly[0]->GetXaxis()->GetLast()), 1.0);
331  std::vector<std::unique_ptr<TH1D>> Ratio(sigmaArray.size()-1);
332 
333  MakeRatio(Poly, Ratio);
334 
335  auto PrettyX = PlotMan->style().prettifyKinematicName(Ratio[0]->GetXaxis()->GetTitle());
336  PlotMan->style().setTH1XRange(Ratio[0].get());
337  Ratio[0]->GetXaxis()->SetTitle(PrettyX.c_str());
338  Ratio[0]->GetXaxis()->SetTitleSize(0.12);
339  Ratio[0]->GetYaxis()->SetTitleOffset(0.4);
340  Ratio[0]->GetYaxis()->SetTitleSize(0.10);
341 
342  Ratio[0]->GetXaxis()->SetLabelSize(0.10);
343  Ratio[0]->GetYaxis()->SetLabelSize(0.10);
344  Ratio[0]->Draw("HIST");
345  for(int ik = 1; ik < static_cast<int>(sigmaArray.size())-1; ++ik)
346  {
347  Ratio[ik]->Draw("HIST SAME");
348  }
349 
350  line.SetLineWidth(2);
351  line.SetLineColor(kBlack);
352  line.Draw("SAME");
353 
354  canv->Print((outfilename).c_str());
355 
356  delete pad1;
357  delete pad2;
358 }
359 
360 void CompareSigVar1D(const std::string& filename, const YAML::Node& Settings)
361 {
362  //Get input file, make canvas and output file
363  auto canvas = std::make_unique<TCanvas>("canv", "canv", 1080, 1080);
364  TFile *infile = M3::Open(filename, "OPEN", __FILE__, __LINE__);
365  TDirectoryFile *SigmaDir = infile->Get<TDirectoryFile>("SigmaVar");
366 
367  std::string outfilename = filename.substr(0, filename.find(".root"));
368  outfilename = outfilename + "_RatioPlots1d.pdf";
369  gErrorIgnoreLevel = kWarning;
370  canvas->Print((outfilename+"[").c_str());
371 
372  auto IncludeString = GetFromManager<std::vector<std::string>>(Settings["IncludeString"], {}, __FILE__ , __LINE__);
373  auto ExcludeString = GetFromManager<std::vector<std::string>>(Settings["ExcludeString"], {}, __FILE__ , __LINE__);
374  TDirectory *dir = nullptr;
375 
376  for(size_t id = 0; id < DialNameVector.size(); id++)
377  {
378  for(size_t is = 0; is < SampleNameVector.size(); is++)
379  {
380  if(SkipDirectory(ExcludeString, IncludeString, (DialNameVector[id] + "/" + SampleNameVector[is]).c_str())) continue;
381  MACH3LOG_INFO("{} Entering {}/{}", __func__, DialNameVector[id], SampleNameVector[is]);
382  SigmaDir->cd((DialNameVector[id] + "/" + SampleNameVector[is]).c_str());
383 
384  //set dir to current directory
385  dir = gDirectory;
386 
387  // Loop over dimensions
388  for(int iDim = 0; iDim <= SampleMaxDim[is]; iDim++)
389  {
390  MACH3LOG_DEBUG("Starting loop over dimension {}", iDim);
391  //make -3,-1,0,1,3 polys
392  std::vector<std::unique_ptr<TH1D>> Projection;
393  TIter nextsub(dir->GetListOfKeys());
394  TKey *subsubkey = nullptr;
395 
396  //loop over items in directory, hard code which th2poly we want
397  while ((subsubkey = static_cast<TKey*>(nextsub())))
398  {
399  auto name = std::string(subsubkey->GetName());
400  auto classname = std::string(subsubkey->GetClassName());
401  // Looking
402  const std::string ProjectionName = "_1DProj" + std::to_string(iDim);
403  const bool IsProjection = (name.find(ProjectionName) != std::string::npos);
404  if (classname == "TH1D" && IsProjection)
405  {
406  name = DialNameVector[id] + "/" + SampleNameVector[is] + "/" + name;
407  Projection.emplace_back(M3::Clone(SigmaDir->Get<TH1D>(name.c_str())));
408  MACH3LOG_DEBUG("Adding hist {}", name);
409  }
410  }
411  std::string Title = PlotMan->style().prettifyParamName(DialNameVector[id]) + " "
413  PlotRatio(Projection, canvas, Title, outfilename);
414  gDirectory->cd("..");
415  }
416  }
417  }
418 
419  canvas->Print((outfilename+"]").c_str());
420  infile->Close();
421  delete infile;
422 }
423 
424 void PlotRatio2D(const std::vector<std::unique_ptr<TH2>>& Poly,
425  const std::unique_ptr<TCanvas>& canv,
426  const std::string& Title,
427  const std::string& outfilename)
428 {
429  canv->Clear();
430  gStyle->SetDrawBorder(0);
431  gStyle->SetTitleBorderSize(2);
432  gStyle->SetOptStat(0); //Set 0 to disable statistic box
433  canv->SetGrid();
434  canv->SetTopMargin(0.10);
435  canv->SetBottomMargin(0.10);
436  canv->SetLeftMargin(0.12);
437  canv->SetRightMargin(0.20);
438 
439  constexpr int NRGBs = 5;
440  TColor::InitializeColors();
441  Double_t stops[NRGBs] = { 0.00, 0.25, 0.50, 0.75, 1.00 };
442  Double_t red[NRGBs] = { 0.00, 0.25, 1.00, 1.00, 0.50 };
443  Double_t green[NRGBs] = { 0.00, 0.25, 1.00, 0.25, 0.00 };
444  Double_t blue[NRGBs] = { 0.50, 1.00, 1.00, 0.25, 0.00 };
445  TColor::CreateGradientColorTable(5, stops, red, green, blue, 255);
446  gStyle->SetNumberContours(255);
447 
448  for (int i = 0; i < static_cast<int>(Poly.size()); ++i) {
449  if (i == PriorKnot) continue; // Skip PriorKnot
450  std::unique_ptr<TH2> Ratio = M3::Clone(Poly[i].get());
451  Ratio->Divide(Poly[PriorKnot].get());
452  Ratio->SetTitle((Title + " " + std::to_string(static_cast<int>(sigmaArray[i])) + "sigma").c_str());
453 
454  const double maxz = Ratio->GetMaximum();
455  const double minz = Ratio->GetMinimum();
456  if (std::fabs(1-maxz) > std::fabs(1-minz))
457  Ratio->GetZaxis()->SetRangeUser(1-std::fabs(1-maxz),1+std::fabs(1-maxz));
458  else
459  Ratio->GetZaxis()->SetRangeUser(1-std::fabs(1-minz),1+std::fabs(1-minz));
460  Ratio->GetXaxis()->SetTitleOffset(1.1);
461  Ratio->GetYaxis()->SetTitleOffset(1.1);
462  Ratio->GetZaxis()->SetTitleOffset(1.5);
463  Ratio->GetZaxis()->SetTitle("Ratio to Prior");
464 
465  auto PrettyX = PlotMan->style().prettifyKinematicName(Ratio->GetXaxis()->GetTitle());
466  Ratio->GetXaxis()->SetTitle(PrettyX.c_str());
467  auto PrettyY = PlotMan->style().prettifyKinematicName(Ratio->GetYaxis()->GetTitle());
468  Ratio->GetYaxis()->SetTitle(PrettyY.c_str());
469 
470  Ratio->Draw("COLZ");
471  canv->Print((outfilename).c_str());
472  }
473 }
474 
475 void CompareSigVar2D(const std::string& filename, const YAML::Node& Settings)
476 {
477  //Get input file, make canvas and output file
478  auto canvas = std::make_unique<TCanvas>("canv", "canv", 1080, 1080);
479  TFile *infile = M3::Open(filename, "OPEN", __FILE__, __LINE__);
480  TDirectoryFile *SigmaDir = infile->Get<TDirectoryFile>("SigmaVar");
481 
482  std::string outfilename = filename.substr(0, filename.find(".root"));
483  outfilename = outfilename + "_RatioPlots2d.pdf";
484  gErrorIgnoreLevel = kWarning;
485  canvas->Print((outfilename+"[").c_str());
486 
487  auto IncludeString = GetFromManager<std::vector<std::string>>(Settings["IncludeString"], {}, __FILE__ , __LINE__);
488  auto ExcludeString = GetFromManager<std::vector<std::string>>(Settings["ExcludeString"], {}, __FILE__ , __LINE__);
489  TDirectory *dir = nullptr;
490 
491  for(size_t id = 0; id < DialNameVector.size(); id++)
492  {
493  for(size_t is = 0; is < SampleNameVector.size(); is++)
494  {
495  if(SkipDirectory(ExcludeString, IncludeString, (DialNameVector[id] + "/" + SampleNameVector[is]).c_str())) continue;
496  MACH3LOG_INFO("{} Entering {}/{}", __func__, DialNameVector[id], SampleNameVector[is]);
497  SigmaDir->cd((DialNameVector[id] + "/" + SampleNameVector[is]).c_str());
498 
499  //set dir to current directory
500  dir = gDirectory;
501 
502  int nDim = SampleMaxDim[is];
503 
504  TIter nextsub(dir->GetListOfKeys());
505  TKey *subsubkey = nullptr;
506 
507  // Loop over all unique dimension pairs
508  for (int iDim1 = 0; iDim1 <= nDim; ++iDim1) {
509  for (int iDim2 = iDim1 + 1; iDim2 <= nDim; ++iDim2) {
510  // Reset iterator for each dimension pair
511  nextsub.Reset();
512  //make -3,-1,0,1,3 polys
513  std::vector<std::unique_ptr<TH2>> Projection;
514 
515  //loop over items in directory, hard code which th2poly we want
516  while ((subsubkey = static_cast<TKey*>(nextsub())))
517  {
518  auto name = std::string(subsubkey->GetName());
519  auto classname = std::string(subsubkey->GetClassName());
520  // Looking
521  const std::string ProjectionName = "_2DProj_" + std::to_string(iDim1) + "_vs_" + std::to_string(iDim2);
522  const bool IsProjection = (name.find(ProjectionName) != std::string::npos);
523  if ((classname == "TH2D" || classname == "TH2Poly")&& IsProjection)
524  {
525  name = DialNameVector[id] + "/" + SampleNameVector[is] + "/" + name;
526  Projection.emplace_back(M3::Clone(SigmaDir->Get<TH2>(name.c_str())));
527  MACH3LOG_DEBUG("Adding hist {}", name);
528  }
529  }
530  std::string Title = PlotMan->style().prettifyParamName(DialNameVector[id]) + " "
532  if(Projection.size() == sigmaArray.size()) PlotRatio2D(Projection, canvas, Title, outfilename);
533  }
534  }
535  gDirectory->cd("..");
536  }
537  }
538  canvas->Print((outfilename+"]").c_str());
539  infile->Close();
540  delete infile;
541 }
542 
543 
544 void PlotEventRate(const std::vector<std::vector<std::unique_ptr<TH1D>>>& Poly,
545  const std::unique_ptr<TCanvas>& canv,
546  const std::string& Title,
547  const std::string& outfilename)
548 {
549  std::vector<std::unique_ptr<TH1D>> EvenRates(sigmaArray.size());
550  for(int ih = 0; ih < static_cast<int>(sigmaArray.size()); ih++)
551  {
552  EvenRates[ih] = std::make_unique<TH1D>(Title.c_str(), Title.c_str(), SampleNameVector.size(), 0, SampleNameVector.size());
553  EvenRates[ih]->SetDirectory(nullptr);
554  EvenRates[ih]->GetYaxis()->SetTitleOffset(1.4);
555  EvenRates[ih]->GetYaxis()->SetTitle("Events");
556  EvenRates[ih]->SetLineWidth(2.);
557  EvenRates[ih]->SetLineStyle(Style[ih]);
558  EvenRates[ih]->SetLineColor(Colours[ih]);
559 
560  for(size_t iSample = 0; iSample < SampleNameVector.size(); iSample ++) {
561  EvenRates[ih]->SetBinContent(iSample+1, Poly[iSample][ih]->Integral());
562 
563  std::string SamName = PlotMan->style().prettifySampleName(SampleNameVector[iSample]);
564  EvenRates[ih]->GetXaxis()->SetBinLabel(iSample+1, SamName.c_str());
565  }
566  }
567 
568  TPad* pad1 = nullptr;
569  TPad* pad2 = nullptr;
570  InitializePads(canv.get(), pad1, pad2, 0.50, 0.50);
571  pad2->SetBottomMargin(0.60);
572 
573  pad1->cd();
574  double max = 0;
575  for(int ik = 0; ik < static_cast<int>(sigmaArray.size()); ++ik) {
576  max = std::max(max, EvenRates[ik]->GetMaximum());
577  }
578  EvenRates[0]->SetTitle(Title.c_str());
579  EvenRates[0]->SetMaximum(max*1.2);
580  EvenRates[0]->Draw("HIST");
581  for(int ik = 1; ik < static_cast<int>(sigmaArray.size()); ++ik)
582  {
583  EvenRates[ik]->Draw("HIST SAME");
584  }
585 
586  auto DialValues = GetDialValues(Poly[0]);
587  auto leg = MakeLegend(0.55, 0.55, 0.8, 0.88, 0.04);
588  for (int j = 0; j < static_cast<int>(sigmaArray.size()); j++)
589  {
590  if(j == PriorKnot) {
591  leg->AddEntry(EvenRates[j].get(), Form("Prior (%.2f)", DialValues[j]), "l");
592  } else {
593  leg->AddEntry(EvenRates[j].get(), Form("%.0f#sigma (%.2f)", sigmaArray[j], DialValues[j]), "l");
594  }
595  }
596  leg->Draw("SAME");
597 
598  pad2->cd();
599  TLine line(EvenRates[0]->GetXaxis()->GetBinLowEdge(EvenRates[0]->GetXaxis()->GetFirst()),
600  1.0, EvenRates[0]->GetXaxis()->GetBinUpEdge(EvenRates[0]->GetXaxis()->GetLast()), 1.0);
601  std::vector<std::unique_ptr<TH1D>> Ratio(sigmaArray.size()-1);
602  MakeRatio(EvenRates, Ratio);
603  Ratio[0]->GetXaxis()->SetTitleSize(0.08);
604  Ratio[0]->GetYaxis()->SetTitleOffset(0.4);
605  Ratio[0]->GetYaxis()->SetTitleSize(0.06);
606 
607  Ratio[0]->GetXaxis()->SetLabelSize(0.08);
608  Ratio[0]->GetYaxis()->SetLabelSize(0.04);
609  Ratio[0]->GetXaxis()->LabelsOption("v");
610  Ratio[0]->Draw("HIST");
611 
612  for(int ik = 1; ik < static_cast<int>(sigmaArray.size())-1; ++ik)
613  {
614  Ratio[ik]->Draw("HIST SAME");
615  }
616 
617  line.SetLineWidth(2);
618  line.SetLineColor(kBlack);
619  line.Draw("SAME");
620 
621  canv->Print((outfilename).c_str());
622 
623  delete pad1;
624  delete pad2;
625 }
626 
627 void MakeEventRatePlot(const std::string& filename, const YAML::Node& Settings)
628 {
629  (void) Settings;
630  //Get input file, make canvas and output file
631  auto canvas = std::make_unique<TCanvas>("canv", "canv", 1080, 1080);
632  canvas->SetRightMargin(0.05);
633  TFile *infile = M3::Open(filename, "OPEN", __FILE__, __LINE__);
634  TDirectoryFile *SigmaDir = infile->Get<TDirectoryFile>("SigmaVar");
635 
636  std::string outfilename = filename.substr(0, filename.find(".root"));
637  outfilename = outfilename + "_EventRate.pdf";
638  gErrorIgnoreLevel = kWarning;
639  canvas->Print((outfilename+"[").c_str());
640 
641  TDirectory *dir = nullptr;
642  for(size_t id = 0; id < DialNameVector.size(); id++)
643  {
644  std::vector<std::vector<std::unique_ptr<TH1D>>> Projection(SampleNameVector.size());
645  for(size_t is = 0; is < SampleNameVector.size(); is++)
646  {
647  MACH3LOG_INFO("{} Entering {}/{}", __func__, DialNameVector[id], SampleNameVector[is]);
648  SigmaDir->cd((DialNameVector[id] + "/" + SampleNameVector[is]).c_str());
649 
650  //set dir to current directory
651  dir = gDirectory;
652 
653  //make -3,-1,0,1,3 polys
654  TIter nextsub(dir->GetListOfKeys());
655  TKey *subsubkey = nullptr;
656 
657  //loop over items in directory, hard code which th2poly we want
658  while ((subsubkey = static_cast<TKey*>(nextsub())))
659  {
660  auto name = std::string(subsubkey->GetName());
661  auto classname = std::string(subsubkey->GetClassName());
662  // Looking
663  const std::string ProjectionName = "_1DProj0";
664  const bool IsProjection = (name.find(ProjectionName) != std::string::npos);
665  if (classname == "TH1D" && IsProjection)
666  {
667  name = DialNameVector[id] + "/" + SampleNameVector[is] + "/" + name;
668  Projection[is].emplace_back(M3::Clone(SigmaDir->Get<TH1D>(name.c_str())));
669  MACH3LOG_DEBUG("Adding hist {}", name);
670  }
671  }
672  gDirectory->cd("..");
673  }
674  std::string Title = PlotMan->style().prettifyParamName(DialNameVector[id]);
675  PlotEventRate(Projection, canvas, Title, outfilename);
676  }
677 
678  canvas->Print((outfilename+"]").c_str());
679  infile->Close();
680  delete infile;
681 }
682 
683 void PlotSigVar1D(const std::vector<std::vector<std::unique_ptr<TH1D>>>& Projection,
684  const std::unique_ptr<TCanvas>& canv,
685  const std::string& Title,
686  const std::string& outfilename,
687  const std::vector<std::string>& ParamNames,
688  const std::vector<int>& ParamColour)
689 {
690  canv->Clear();
691  gStyle->SetDrawBorder(0);
692  gStyle->SetTitleBorderSize(2);
693  gStyle->SetOptStat(0); //Set 0 to disable statistic box
694  canv->SetGrid();
695  canv->SetTopMargin(0.10);
696  canv->SetBottomMargin(0.08);
697  canv->SetRightMargin(0.05);
698  canv->SetLeftMargin(0.12);
699 
700  auto PriorHist = Projection[0][PriorKnot].get();
701  PriorHist->SetTitle(Title.c_str());
702 
703  auto BinWidthScale = PlotMan->style().getBinWidthScale(PriorHist->GetXaxis()->GetTitle());
704  PriorHist->GetYaxis()->SetTitle(fmt::format("Events/{:.0f}", BinWidthScale).c_str());
705  PriorHist->Draw("HIST");
706  PriorHist->SetLineWidth(2.);
707  PriorHist->SetLineColor(kBlack);
708  M3::ScaleHistogram(PriorHist, BinWidthScale);
709 
710  auto PrettyX = PlotMan->style().prettifyKinematicName(PriorHist->GetXaxis()->GetTitle());
711  PlotMan->style().setTH1XRange(PriorHist);
712  PriorHist->GetXaxis()->SetTitle(PrettyX.c_str());
713  for(int ik = 0; ik < static_cast<int>(sigmaArray.size()); ++ik)
714  {
715  if(ik == PriorKnot) continue;
716 
717  double max = 0;
718  for(size_t nParam = 0; nParam < Projection.size(); nParam++) {
719  Projection[nParam][ik]->SetLineWidth(2.);
720  Projection[nParam][ik]->SetLineColor(ParamColour[nParam]);
721  Projection[nParam][ik]->SetLineStyle(kDotted);
722  Projection[nParam][ik]->GetYaxis()->SetTitle(fmt::format("Events/{:.0f}", BinWidthScale).c_str());
723  M3::ScaleHistogram(Projection[nParam][ik].get(), BinWidthScale);
724  max = std::max(max, Projection[nParam][ik]->GetMaximum());
725  }
726  PriorHist->SetMaximum(max*1.2);
727 
728  PriorHist->Draw("HIST");
729  for(size_t nParam = 0; nParam < Projection.size(); nParam++) {
730  Projection[nParam][ik]->Draw("HIST SAME");
731  }
732  auto leg = MakeLegend(0.50, 0.55, 0.70, 0.75, 0.035);
733  leg->AddEntry(PriorHist, "Prior", "l");
734  for(size_t nParam = 0; nParam < Projection.size(); nParam++) {
735  leg->AddEntry(Projection[nParam][ik].get(), Form("%s (%.0f#sigma)", ParamNames[nParam].c_str(), sigmaArray[ik]), "l");
736  }
737  leg->Draw("SAME");
738 
739  canv->Print((outfilename).c_str());
740  canv->cd();
741  }
742 }
743 
744 void OverlaySigVar1D(const std::string& filename, const YAML::Node& Settings)
745 {
746  auto ParamNames = GetFromManager<std::vector<std::string>>(Settings["ParamNames"], {}, __FILE__ , __LINE__);
747  auto SigColours = GetFromManager<std::vector<int>>(Settings["Coulour"], {}, __FILE__ , __LINE__);
748 
749  if(ParamNames.size() == 0) return;
750 
751  if(ParamNames.size() != SigColours.size()){
752  MACH3LOG_ERROR("Wrong Size");
753  throw MaCh3Exception(__FILE__, __LINE__);
754  }
755 
756  //Get input file, make canvas and output file
757  auto canvas = std::make_unique<TCanvas>("canv", "canv", 1080, 1080);
758  TFile *infile = M3::Open(filename, "OPEN", __FILE__, __LINE__);
759  TDirectoryFile *SigmaDir = infile->Get<TDirectoryFile>("SigmaVar");
760 
761  std::string outfilename = filename.substr(0, filename.find(".root"));
762  outfilename = outfilename + "_Overlay1d.pdf";
763  gErrorIgnoreLevel = kWarning;
764  canvas->Print((outfilename+"[").c_str());
765 
766  TDirectory *dir = nullptr;
767 
768  for(size_t is = 0; is < SampleNameVector.size(); is++)
769  {
770  // Loop over dimensions
771  for(int iDim = 0; iDim <= SampleMaxDim[is]; iDim++)
772  {
773  std::vector<std::vector<std::unique_ptr<TH1D>>> Projection(ParamNames.size());
774  for(size_t id = 0; id < ParamNames.size(); id++)
775  {
776  MACH3LOG_INFO("{} Entering {}/{}", __func__, ParamNames[id], SampleNameVector[is]);
777  SigmaDir->cd((ParamNames[id] + "/" + SampleNameVector[is]).c_str());
778 
779  //set dir to current directory
780  dir = gDirectory;
781  //make -3,-1,0,1,3 polys
782  TIter nextsub(dir->GetListOfKeys());
783  TKey *subsubkey = nullptr;
784 
785  //loop over items in directory, hard code which th2poly we want
786  while ((subsubkey = static_cast<TKey*>(nextsub())))
787  {
788  auto name = std::string(subsubkey->GetName());
789  auto classname = std::string(subsubkey->GetClassName());
790  // Looking
791  const std::string ProjectionName = "_1DProj" + std::to_string(iDim);
792  const bool IsProjection = (name.find(ProjectionName) != std::string::npos);
793  if (classname == "TH1D" && IsProjection)
794  {
795  name = ParamNames[id] + "/" + SampleNameVector[is] + "/" + name;
796  Projection[id].emplace_back(M3::Clone(SigmaDir->Get<TH1D>(name.c_str())));
797  MACH3LOG_DEBUG("Adding hist {}", name);
798  }
799  }
800  }
801  std::string Title = PlotMan->style().prettifySampleName(SampleNameVector[is]);
802  PlotSigVar1D(Projection, canvas, Title, outfilename, ParamNames, SigColours);
803  gDirectory->cd("..");
804  }
805  }
806 
807  canvas->Print((outfilename+"]").c_str());
808  infile->Close();
809  delete infile;
810 }
811 
812 int main(int argc, char **argv)
813 {
815  if (argc != 3)
816  {
817  MACH3LOG_ERROR("Need two inputs: output of sigma var and config");
818  throw MaCh3Exception(__FILE__, __LINE__);
819  }
820  std::string filename = argv[1];
821  std::string ConfigName = argv[2];
822  MACH3LOG_INFO("Running {} with {} {}", argv[0], filename, ConfigName);
823  // Load the YAML file
824  YAML::Node Config = M3OpenConfig(ConfigName);
825 
826  // Access the "MatrixPlotter" section
827  YAML::Node settings = Config["PlotSigmaVariation"];
828 
830 
832  PlotMan->initialise();
833 
834  CompareSigVar1D(filename, settings);
835  CompareSigVar2D(filename, settings);
836  MakeEventRatePlot(filename, settings);
837  OverlaySigVar1D(filename, settings);
838 
839  if(PlotMan) delete PlotMan;
840  return 0;
841 }
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:60
void PlotRatio(const std::vector< std::unique_ptr< TH1D >> &Poly, const std::unique_ptr< TCanvas > &canv, const std::string &Title, const std::string &outfilename)
void CompareSigVar2D(const std::string &filename, const YAML::Node &Settings)
constexpr ELineStyle Style[NVars]
int main(int argc, char **argv)
void PlotRatio2D(const std::vector< std::unique_ptr< TH2 >> &Poly, const std::unique_ptr< TCanvas > &canv, const std::string &Title, const std::string &outfilename)
void OverlaySigVar1D(const std::string &filename, const YAML::Node &Settings)
constexpr Color_t Colours[NVars]
std::vector< double > GetDialValues(const std::vector< std::unique_ptr< TH1D >> &Poly)
Extracts dial value for from histogram title.
void PlotEventRate(const std::vector< std::vector< std::unique_ptr< TH1D >>> &Poly, const std::unique_ptr< TCanvas > &canv, const std::string &Title, const std::string &outfilename)
void CompareSigVar1D(const std::string &filename, const YAML::Node &Settings)
void PlotSigVar1D(const std::vector< std::vector< std::unique_ptr< TH1D >>> &Projection, const std::unique_ptr< TCanvas > &canv, const std::string &Title, const std::string &outfilename, const std::vector< std::string > &ParamNames, const std::vector< int > &ParamColour)
std::unique_ptr< TLegend > MakeLegend(double x1, double y1, double x2, double y2, double textSize=0.04)
std::vector< int > SampleMaxDim
void ScanInput(std::vector< std::string > &DialNameVecr, std::vector< std::string > &SampleNameVec, std::vector< int > &SampleDimVec, std::vector< double > &SigmaValues, const std::string &filename)
Scan inputs to figure out dial name and used sample names.
std::vector< std::string > DialNameVector
void FindKnot(std::vector< double > &SigmaValues, const std::string &dirname, const std::string &subdirname, const std::string &ProjName, std::string histname)
Histograms have name like ND_CC0pi_1DProj0_Norm_Param_0_sig_n3.00_val_0.25. This code is trying to ex...
std::vector< std::string > SampleNameVector
int PriorKnot
std::vector< double > sigmaArray
void InitializePads(TCanvas *canv, TPad *&pad1, TPad *&pad2, double Pad1Bottom=0.25, double Pad2Top=0.25)
constexpr const int NVars
void MakeRatio(const std::vector< std::unique_ptr< TH1D >> &Poly, std::vector< std::unique_ptr< TH1D >> &Ratio)
void MakeEventRatePlot(const std::string &filename, const YAML::Node &Settings)
M3::Plotting::PlottingManager * PlotMan
bool SkipDirectory(const std::vector< std::string > &ExcludeString, const std::vector< std::string > &IncludeString, const std::string &dirname)
Check whether to skip directory or not based on defined strings.
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:589
The main class to be used in plotting scripts.
void initialise()
initalise this PlottingManager.
const StyleManager & style() const
Get the StyleManager contained within this PlottingManager, for doing style related things.
void setTH1XRange(TH1 *hist) const
Set plotting range for histogram.
double getBinWidthScale(const std::string &Name) const
Get bin-width scaling factor for a given kinematic variable.
std::string prettifySampleName(const std::string &origName) const
Convert hideous and vulgar internal sample name into a beautiful presentable name.
Definition: StyleManager.h:49
std::string prettifyKinematicName(const std::string &origName) const
Convert hideous and vulgar internal kinematics name into a beautiful presentable name.
Definition: StyleManager.h:58
std::string prettifyParamName(const std::string &origName) const
Convert hideous and vulgar internal parameter name into a beautiful presentable name.
Definition: StyleManager.h:40
Custom exception class used throughout MaCh3.
void SetSymmetricRatioRange(const std::vector< std::unique_ptr< TH1D >> &RatioPlot)
Set a symmetric Y-axis range around 1 for ratio plots.
std::unique_ptr< ObjectType > Clone(const ObjectType *obj, const std::string &name="")
KS: Creates a copy of a ROOT-like object and wraps it in a smart pointer.
void ScaleHistogram(TH1 *Sample_Hist, const double scale)
Scale histogram to get divided by bin width.
TFile * Open(const std::string &Name, const std::string &Type, const std::string &File, const int Line)
Opens a ROOT file with the given name and mode.
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Definition: Core.h:55