MaCh3  2.6.0
Reference Guide
OscProcessor.cpp
Go to the documentation of this file.
1 #include "OscProcessor.h"
2 
4 // ROOT includes
5 #include "TArrow.h"
6 #include "TEllipse.h"
7 #include "TLatex.h"
8 #include "TVector2.h"
9 #include "TComplex.h"
11 
12 #pragma GCC diagnostic ignored "-Wfloat-conversion"
13 
14 // ****************************
15 OscProcessor::OscProcessor(const std::string &InputFile) : MCMCProcessor(InputFile) {
16 // ****************************
17  //KS: WARNING this only work when you project from Chain, will nor work when you try SetBranchAddress etc. Turn it on only if you know how to use it
18  PlotJarlskog = false;
19 
25 }
26 
27 // ****************************
28 // The destructor
30 // ****************************
31 }
32 
33 // ***************
34 // Read the Osc cov file and get the input central values and errors
36 // ***************
37  // KS: Check if OscParams were enabled, in future we will also get
38  for(size_t i = 0; i < ParameterGroup.size(); i++) {
39  if(ParameterGroup[i] == "Osc"){
40  OscEnabled = true;
41  break;
42  }
43  }
44 
45  if(OscEnabled)
46  {
47  for (int i = 0; i < nDraw; ++i)
48  {
49  //Those keep which parameter type we run currently and relative number
50  const int ParamEnum = ParamType[i];
51  const int ParamNo = i - ParamTypeStartPos[ParameterEnum(ParamEnum)];
52  const std::string CurrentName = ParamNames[ParamEnum][ParamNo].Data();
53 
55  if (CurrentName == "sin2th_13") {
56  Sin2Theta13Index = i;
57  Sin2Theta13Name = CurrentName;
58  } else if (CurrentName == "sin2th_12") {
59  Sin2Theta12Index = i;
60  Sin2Theta12Name = CurrentName;
61  } else if (CurrentName == "sin2th_23") {
62  Sin2Theta23Index = i;
63  Sin2Theta23Name = CurrentName;
64  } else if (CurrentName == "delta_cp") {
65  DeltaCPIndex = i;
66  DeltaCPName = CurrentName;
67  } else if (CurrentName == "delm2_23") {
68  DeltaM2_23Index = i;
69  DeltaM2_23Name = CurrentName;
70  }
71  }
72  } else{
73  MACH3LOG_WARN("Didn't find oscillation parameters");
74  }
75 
77  {
78  Chain->SetAlias("J_cp", "TMath::Sqrt(sin2th_13)*TMath::Sqrt(1.-sin2th_13)*TMath::Sqrt(1.-sin2th_13)*TMath::Sqrt(sin2th_12)*TMath::Sqrt(1.-sin2th_12)*TMath::Sqrt(sin2th_23)*TMath::Sqrt(1.-sin2th_23)*TMath::Sin(delta_cp)");
79  BranchNames.push_back("J_cp");
80  ParamType.push_back(kXSecPar);
81  nParam[kXSecPar]++;
82  nDraw++;
83 
85  ParamCentral[kXSecPar].push_back( 0. );
86  ParamErrors[kXSecPar].push_back( 1. );
87  // Push back the name
88  ParamNames[kXSecPar].push_back("J_cp");
89  ParamFlat[kXSecPar].push_back( false );
90  } else if(PlotJarlskog && !OscEnabled) {
91  MACH3LOG_ERROR("Trying to enable Jarlskog without oscillations");
92  throw MaCh3Exception(__FILE__,__LINE__);
93  }
94 }
95 
96 // ***************
97 // Calculate Jarlskog Invariant using oscillation parameters
98 double OscProcessor::CalcJarlskog(const double s2th13, const double s2th23, const double s2th12, const double dcp) const {
99 // ***************
100  const double s13 = std::sqrt(s2th13);
101  const double s23 = std::sqrt(s2th23);
102  const double s12 = std::sqrt(s2th12);
103  const double sdcp = std::sin(dcp);
104  const double c13 = std::sqrt(1.-s2th13);
105  const double c12 = std::sqrt(1.-s2th12);
106  const double c23 = std::sqrt(1.-s2th23);
107 
108  const double j = s13*c13*c13*s12*c12*s23*c23*sdcp;
109 
110  return j;
111 }
112 
113 // ***************
114 double OscProcessor::SamplePriorForParam(const int paramIndex, const std::unique_ptr<TRandom3>& randGen, const std::vector<double>& FlatBounds) const {
115 // ***************
116  TString Title = "";
117  double Prior = 1.0, PriorError = 1.0;
118  bool FlatPrior = false;
119 
120  // Get info for this parameter
121  GetNthParameter(paramIndex, Prior, PriorError, Title);
122 
123  ParameterEnum ParType = ParamType[paramIndex];
124  int ParamTemp = paramIndex - ParamTypeStartPos[ParType];
125  FlatPrior = ParamFlat[ParType][ParamTemp];
126 
127  if (FlatPrior) {
128  return randGen->Uniform(FlatBounds[0], FlatBounds[1]);
129  } else {
130  // Gaussian prior centered at Prior with width PriorError
131  return randGen->Gaus(Prior, PriorError);
132  }
133 }
134 
135 // ***************
136 void OscProcessor::Get1DReactorConstraintInfo(std::pair<double, double>& Sin13_NewPrior, bool& DoReweight) const {
137 // ***************
138  if(ReweightNames.size() != 1){
139  MACH3LOG_INFO("Found more than 1 weight for Jarlskog analysis");
140  return;
141  }
142  // Now read the MCMC file
143  TFile *TempFile = M3::Open((MCMCFile + ".root"), "open", __FILE__, __LINE__);
144 
145  // Get the settings for the MCMC
146  TMacro *Config = TempFile->Get<TMacro>("Reweight_Config");
147 
148  DoReweight = false;
149  if (Config != nullptr) {
150  MACH3LOG_INFO("Found Reweight_Config in chain");
151  // Print the reweight configuration for user info
152  YAML::Node Settings = TMacroToYAML(*Config);
153  // Simple check: only enable DoReweight if it's a 1D sin2th_13 Gaussian reweight since Savage Dickey process later on generates values from the Gaussian
154  if(CheckNodeExists(Settings, ReweightNames.back())) {
155  YAML::Node firstReweight = Settings[ReweightNames.back()];
156  int dimension = Get<int>(firstReweight["ReweightDim"], __FILE__ , __LINE__);
157  std::string reweightType = Get<std::string>(firstReweight["ReweightType"],__FILE__ , __LINE__);
158  auto paramNames = Get<std::vector<std::string>>(firstReweight["ReweightVar"], __FILE__ , __LINE__);
159  if (dimension == 1 && reweightType == "Gaussian" && paramNames.size() == 1){
160  auto Priors = Get<std::vector<std::pair<double, double>>>(firstReweight["ReweightPrior"], __FILE__,__LINE__);
161  Sin13_NewPrior = Priors[0];
162  DoReweight = true;
163  } else {
164  MACH3LOG_INFO("No valid reweighting configuration (1D Gaussian on sin2th_13 only) found for Jarlskog analysis");
165  }
166  } else {
167  MACH3LOG_INFO("No reweighting configuration found for Jarlskog analysis");
168  }
169  }
170 
171  TempFile->Close();
172  delete TempFile;
173 }
174 
175 // ***************
176 // Perform Several Jarlskog Plotting
178 // ***************
179  if(!OscEnabled ||
185  {
186  MACH3LOG_WARN("Will not {}, as oscillation parameters are missing", __func__);
187  return;
188  }
189  MACH3LOG_INFO("Starting {}", __func__);
190 
191  double s2th13, s2th23, s2th12, dcp, dm2 = M3::_BAD_DOUBLE_;
192  double weight = 1.0;
193 
194  bool DoReweight = false;
195  std::pair<double, double> Sin13_NewPrior;
196  Get1DReactorConstraintInfo(Sin13_NewPrior, DoReweight);
197 
198  TDirectory *JarlskogDir = OutputFile->mkdir("Jarlskog");
199  JarlskogDir->cd();
200 
201  unsigned int step = 0;
202  Chain->SetBranchStatus("*", false);
203 
204  Chain->SetBranchStatus(Sin2Theta13Name.c_str(), true);
205  Chain->SetBranchAddress(Sin2Theta13Name.c_str(), &s2th13);
206 
207  Chain->SetBranchStatus(Sin2Theta23Name.c_str(), true);
208  Chain->SetBranchAddress(Sin2Theta23Name.c_str(), &s2th23);
209 
210  Chain->SetBranchStatus(Sin2Theta12Name.c_str(), true);
211  Chain->SetBranchAddress(Sin2Theta12Name.c_str(), &s2th12);
212 
213  Chain->SetBranchStatus(DeltaCPName.c_str(), true);
214  Chain->SetBranchAddress(DeltaCPName.c_str(), &dcp);
215 
216  Chain->SetBranchStatus(DeltaM2_23Name.c_str(), true);
217  Chain->SetBranchAddress(DeltaM2_23Name.c_str(), &dm2);
218 
219  Chain->SetBranchStatus("step", true);
220  Chain->SetBranchAddress("step", &step);
221 
222  if(DoReweight) {
223  Chain->SetBranchStatus(ReweightNames.back().c_str(), true);
224  Chain->SetBranchAddress(ReweightNames.back().c_str(), &weight);
225  } else {
226  MACH3LOG_WARN("Not applying reweighting weight");
227  weight = 1.0;
228  }
229 
230  // Original histograms
231  auto jarl = std::make_unique<TH1D>("jarl", "jarl", 1000, -0.05, 0.05);
232  jarl->SetDirectory(nullptr);
233  auto jarl_th23 = std::make_unique<TH2D>("jarl_th23", "jarl_th23", 500, -0.05, 0.05, 500, 0.3, 0.7);
234  jarl_th23->SetDirectory(nullptr);
235  auto jarl_dcp = std::make_unique<TH2D>("jarl_dcp", "jarl_dcp", 500, -0.05, 0.05, 500, -1. * TMath::Pi(), TMath::Pi());
236  jarl_dcp->SetDirectory(nullptr);
237 
238  jarl->SetTitle("Jarlskog Invariant;J #equiv s_{13}c_{13}^{2}s_{12}c_{12}s_{23}c_{23}sin#delta;Posterior probability");
239  jarl_th23->SetTitle("Jarlskog Invariant;J #equiv s_{13}c_{13}^{2}s_{12}c_{12}s_{23}c_{23}sin#delta;Posterior probability");
240 
241  // Clones
242  auto jarl_IH = M3::Clone(jarl.get(), "jarl_IH");
243  auto jarl_NH = M3::Clone(jarl.get(), "jarl_NH");
244 
245  auto jarl_th23_IH = M3::Clone(jarl_th23.get(), "jarl_th23_IH");
246  auto jarl_th23_NH = M3::Clone(jarl_th23.get(), "jarl_th23_NH");
247 
248  auto jarl_dcp_IH = M3::Clone(jarl_dcp.get(), "jarl_dcp_IH");
249  auto jarl_dcp_NH = M3::Clone(jarl_dcp.get(), "jarl_dcp_NH");
250 
251  auto jarl_flatsindcp = M3::Clone(jarl.get(), "jarl_flatsindcp");
252  auto jarl_IH_flatsindcp = M3::Clone(jarl.get(), "jarl_IH_flatsindcp");
253  auto jarl_NH_flatsindcp = M3::Clone(jarl.get(), "jarl_NH_flatsindcp");
254 
255  auto jarl_th23_flatsindcp = M3::Clone(jarl_th23.get(), "jarl_th23_flatsindcp");
256  auto jarl_th23_IH_flatsindcp = M3::Clone(jarl_th23.get(), "jarl_th23_IH_flatsindcp");
257  auto jarl_th23_NH_flatsindcp = M3::Clone(jarl_th23.get(), "jarl_th23_NH_flatsindcp");
258 
259  auto jarl_prior = M3::Clone(jarl.get(), "jarl_prior");
260  auto jarl_prior_flatsindcp = M3::Clone(jarl.get(), "jarl_prior_flatsindcp");
261  std::unique_ptr<TH1D> jarl_wRC_prior, jarl_wRC_prior_flatsindcp, jarl_wRC_prior_t2kth23;
262  // Only use this if chain has reweigh weight [mostly coming from Reactor Constrains]
263  if(DoReweight){
264  jarl_wRC_prior = M3::Clone(jarl.get(), "jarl_wRC_prior");
265  jarl_wRC_prior_flatsindcp = M3::Clone(jarl.get(), "jarl_wRC_prior_flatsindcp");
266  jarl_wRC_prior_t2kth23 = M3::Clone(jarl.get(), "jarl_wRC_prior_flatsindcp");
267  }
268 
269  // to apply a prior that is flat in sin(dcp) intead of dcp
270  auto prior3 = std::make_unique<TF1>("prior3", "TMath::Abs(TMath::Cos(x))");
271 
272  // T2K prior is flat (and uncorrelated) in dcp, sin^2(th13), sin^2(th23)
273  auto randGen = std::make_unique<TRandom3>(0);
274  const Long64_t countwidth = nEntries/5;
275 
276  for(int i = 0; i < nEntries; ++i) {
277  if (i % countwidth == 0) {
280  } else {
281  Chain->GetEntry(i);
282  }
283 
284  if(step < BurnInCut) continue; // burn-in cut
285 
286  const double j = CalcJarlskog(s2th13, s2th23, s2th12, dcp);
287  const double prior_weight = prior3->Eval(dcp);
288 
289  jarl->Fill(j, weight);
290  jarl_th23->Fill(j, s2th23, weight);
291  jarl_dcp->Fill(j, dcp, weight);
292 
293  jarl_flatsindcp->Fill(j, prior_weight*weight);
294  jarl_th23_flatsindcp->Fill(j, s2th23, prior_weight*weight);
295 
296  const double prior_s2th13 = SamplePriorForParam(Sin2Theta13Index, randGen, {0.,1.});
297  const double prior_s2th23 = SamplePriorForParam(Sin2Theta23Index, randGen, {0.,1.});
298  const double prior_s2th12 = SamplePriorForParam(Sin2Theta12Index, randGen, {0.,1.});
299  const double prior_dcp = SamplePriorForParam(DeltaCPIndex, randGen, {-1.*TMath::Pi(),TMath::Pi()});
300  // KS: This is hardcoded but we always assume flat in delta CP so probably fine
301  const double prior_sindcp = randGen->Uniform(-1., 1.);
302 
303  const double prior_s13 = std::sqrt(prior_s2th13);
304  const double prior_s23 = std::sqrt(prior_s2th23);
305  const double prior_s12 = std::sqrt(prior_s2th12);
306  const double prior_sdcp = std::sin(prior_dcp);
307  const double prior_c13 = std::sqrt(1.-prior_s2th13);
308  const double prior_c12 = std::sqrt(1.-prior_s2th12);
309  const double prior_c23 = std::sqrt(1.-prior_s2th23);
310  const double prior_j = prior_s13*prior_c13*prior_c13*prior_s12*prior_c12*prior_s23*prior_c23*prior_sdcp;
311  const double prior_flatsindcp_j = prior_s13*prior_c13*prior_c13*prior_s12*prior_c12*prior_s23*prior_c23*prior_sindcp;
312 
313  jarl_prior->Fill(prior_j);
314  jarl_prior_flatsindcp->Fill(prior_flatsindcp_j);
315 
316  if(DoReweight) {
317  const double prior_wRC_s2th13 = randGen->Gaus(Sin13_NewPrior.first, Sin13_NewPrior.second);
318  const double prior_wRC_s13 = std::sqrt(prior_wRC_s2th13);
319  const double prior_wRC_c13 = std::sqrt(1.-prior_wRC_s2th13);
320  const double prior_wRC_j = prior_wRC_s13*prior_wRC_c13*prior_wRC_c13*prior_s12*prior_c12*prior_s23*prior_c23*prior_sdcp;
321  const double prior_wRC_flatsindcp_j = prior_wRC_s13*prior_wRC_c13*prior_wRC_c13*prior_s12*prior_c12*prior_s23*prior_c23*prior_sindcp;
322  const double s23 = std::sqrt(s2th23);
323  const double c23 = std::sqrt(1.-s2th23);
324 
325  jarl_wRC_prior->Fill(prior_wRC_j);
326  jarl_wRC_prior_flatsindcp->Fill(prior_wRC_flatsindcp_j);
327  jarl_wRC_prior_t2kth23->Fill(prior_wRC_s13*prior_wRC_c13*prior_wRC_c13*prior_s12*prior_c12*s23*c23*prior_sdcp);
328  }
329 
330  if(dm2 > 0.) {
331  jarl_NH->Fill(j, weight);
332  jarl_th23_NH->Fill(j, s2th23, weight);
333  jarl_dcp_NH->Fill(j, dcp, weight);
334  jarl_NH_flatsindcp->Fill(j, prior_weight*weight);
335  jarl_th23_NH_flatsindcp->Fill(j, s2th23, prior_weight*weight);
336  }
337  else if(dm2 < 0.) {
338  jarl_IH->Fill(j, weight);
339  jarl_th23_IH->Fill(j, s2th23, weight);
340  jarl_dcp_IH->Fill(j, dcp, weight);
341  jarl_IH_flatsindcp->Fill(j, prior_weight*weight);
342  jarl_th23_IH_flatsindcp->Fill(j, s2th23, prior_weight*weight);
343  }
344  }
345 
346  jarl->Write("jarlskog_both");
347  jarl_NH->Write("jarlskog_NH");
348  jarl_IH->Write("jarlskog_IH");
349  jarl_th23->Write("jarlskog_th23_both");
350  jarl_th23_NH->Write("jarlskog_th23_NH");
351  jarl_th23_IH->Write("jarlskog_th23_IH");
352 
353  jarl_dcp->Write("jarlskog_dcp_both");
354  jarl_dcp_NH->Write("jarlskog_dcp_NH");
355  jarl_dcp_IH->Write("jarlskog_dcp_IH");
356 
357 
358  jarl_flatsindcp->Write("jarlskog_both_flatsindcp");
359  jarl_NH_flatsindcp->Write("jarlskog_NH_flatsindcp");
360  jarl_IH_flatsindcp->Write("jarlskog_IH_flatsindcp");
361  jarl_th23_flatsindcp->Write("jarlskog_th23_both_flatsindcp");
362  jarl_th23_NH_flatsindcp->Write("jarlskog_th23_NH_flatsindcp");
363  jarl_th23_IH_flatsindcp->Write("jarlskog_th23_IH_flatsindcp");
364 
365  jarl_prior->Write("jarl_prior");
366  jarl_prior_flatsindcp->Write("jarl_prior_flatsindcp");
367  if(DoReweight) {
368  jarl_wRC_prior->Write("jarl_wRC_prior");
369  jarl_wRC_prior_flatsindcp->Write("jarl_wRC_prior_flatsindcp");
370  jarl_wRC_prior_t2kth23->Write("jarl_wRC_prior_t2kth23");
371  }
372 
373  MakeJarlskogPlot(jarl, jarl_flatsindcp,
374  jarl_NH, jarl_NH_flatsindcp,
375  jarl_IH, jarl_IH_flatsindcp);
376 
377  // Perform Savage Dickey analysis
378  if(DoReweight) {
379  SavageDickeyPlot(jarl, jarl_wRC_prior, "Jarlskog flat #delta_{CP}", 0);
380  SavageDickeyPlot(jarl_flatsindcp, jarl_wRC_prior_flatsindcp, "Jarlskog flat sin#delta_{CP}", 0);
381  } else {
382  SavageDickeyPlot(jarl, jarl_prior, "Jarlskog flat #delta_{CP}", 0);
383  SavageDickeyPlot(jarl_flatsindcp, jarl_prior_flatsindcp, "Jarlskog flat sin#delta_{CP}", 0);
384  }
385 
386  JarlskogDir->Close();
387  delete JarlskogDir;
388 
389  Chain->SetBranchStatus("*", true);
390  OutputFile->cd();
391 }
392 
393 
394 // ***************
395 void OscProcessor::MakeJarlskogPlot(const std::unique_ptr<TH1D>& jarl,
396  const std::unique_ptr<TH1D>& jarl_flatsindcp,
397  const std::unique_ptr<TH1D>& jarl_NH,
398  const std::unique_ptr<TH1D>& jarl_NH_flatsindcp,
399  const std::unique_ptr<TH1D>& jarl_IH,
400  const std::unique_ptr<TH1D>& jarl_IH_flatsindcp) {
401 // ***************
402  MACH3LOG_INFO("Starting {}", __func__);
403  int originalErrorLevel = gErrorIgnoreLevel;
404  gErrorIgnoreLevel = kFatal;
405 
406  // 1-->NH, 0-->both, -1-->IH
407  for(int hierarchy = -1; hierarchy <= 1; hierarchy++)
408  {
409  std::unique_ptr<TH1D> j_hist;
410  std::unique_ptr<TH1D> j_hist_sdcp;
411  if(hierarchy == 1) {
412  j_hist = M3::Clone(jarl_NH.get(), "");
413  j_hist_sdcp = M3::Clone(jarl_NH_flatsindcp.get(), "");
414  j_hist->SetTitle(";J_{CP} #equiv s_{13}c^{2}_{13}s_{12}c_{12}s_{23}c_{23}sin#delta_{CP};Posterior probability");
415  } else if(hierarchy == 0) {
416  j_hist = M3::Clone(jarl.get(), "");
417  j_hist_sdcp = M3::Clone(jarl_flatsindcp.get(), "");
418  j_hist->SetTitle(";J_{CP} #equiv s_{13}c^{2}_{13}s_{12}c_{12}s_{23}c_{23}sin#delta_{CP};Posterior probability");
419  } else if(hierarchy == -1) {
420  j_hist = M3::Clone(jarl_IH.get(), "");
421  j_hist_sdcp = M3::Clone(jarl_IH_flatsindcp.get(), "");
422  j_hist->SetTitle(";J_{CP} #equiv s_{13}c^{2}_{13}s_{12}c_{12}s_{23}c_{23}sin#delta_{CP};Posterior probability");
423  } else {
424  MACH3LOG_ERROR("Invalid hierarchy option. 1 for NH, 0 for both, -1 for IH");
425  throw MaCh3Exception(__FILE__ , __LINE__ );
426  }
427 
428  j_hist->Rebin(7);
429  j_hist_sdcp->Rebin(7);
430 
431  j_hist->SetLineColor(kAzure-2);
432  j_hist_sdcp->SetLineColor(kOrange+1);
433  j_hist->SetLineWidth(2);
434  j_hist_sdcp->SetLineWidth(2);
435 
436  auto StyleAxis = [](TH1* h) {
437  auto xAxis = h->GetXaxis();
438  auto yAxis = h->GetYaxis();
439 
440  xAxis->SetLabelSize(0.04);
441  xAxis->SetLabelFont(132);
442  xAxis->SetTitleSize(0.04);
443  xAxis->SetTitleOffset(0.80);
444  xAxis->SetTitleFont(132);
445  xAxis->SetNdivisions(505);
446  xAxis->SetTickSize(0.04);
447 
448  yAxis->SetLabelSize(0.04);
449  yAxis->SetLabelFont(132);
450  yAxis->SetTitleSize(0.04);
451  yAxis->SetTitleOffset(1.2);
452  yAxis->SetTitleFont(132);
453  yAxis->SetNdivisions(505);
454  yAxis->SetTickSize(0.04);
455  };
456 
457  StyleAxis(j_hist.get());
458 
459  j_hist->GetXaxis()->SetRangeUser(-0.04,0.04);
460  j_hist->Scale(1./j_hist->Integral());
461  j_hist_sdcp->Scale(1./j_hist_sdcp->Integral());
462 
463  std::unique_ptr<TH1D> j_hist_copy = M3::Clone(j_hist.get(), "j_hist_copy");
464  std::unique_ptr<TH1D> j_hist_1sig = M3::Clone(j_hist.get(), "j_hist_1sig");
465  std::unique_ptr<TH1D> j_hist_2sig = M3::Clone(j_hist.get(), "j_hist_2sig");
466  std::unique_ptr<TH1D> j_hist_3sig = M3::Clone(j_hist.get(), "j_hist_3sig");
467 
468  //upper and lower edges
469  double j_bf = j_hist_copy->GetXaxis()->GetBinCenter(j_hist_copy->GetMaximumBin());
470  double j_1sig_low = 9999999.;
471  double j_1sig_up = -9999999.;
472  double j_2sig_low = 9999999.;;
473  double j_2sig_up = -9999999.;
474  double j_3sig_low = 9999999.;;
475  double j_3sig_up = -9999999.;
476 
477 
478  std::unique_ptr<TH1D> j_hist_sdcp_copy = M3::Clone(j_hist_sdcp.get(), "j_hist_sdcp_copy");
479  std::unique_ptr<TH1D> j_hist_sdcp_1sig = M3::Clone(j_hist_sdcp.get(), "j_hist_sdcp_1sig");
480  std::unique_ptr<TH1D> j_hist_sdcp_2sig = M3::Clone(j_hist_sdcp.get(), "j_hist_sdcp_2sig");
481  std::unique_ptr<TH1D> j_hist_sdcp_3sig = M3::Clone(j_hist_sdcp.get(), "j_hist_sdcp_3sig");
482 
483  //upper and lower edges
484  double j_sdcp_1sig_low = 9999999.;
485  double j_sdcp_1sig_up = -9999999.;
486  double j_sdcp_2sig_low = 9999999.;;
487  double j_sdcp_2sig_up = -9999999.;
488  double j_sdcp_3sig_low = 9999999.;;
489  double j_sdcp_3sig_up = -9999999.;
490 
491  double contlevel1 = 0.68;
492  double contlevel2 = 0.90;
493  double contlevel4 = 0.99;
494  double contlevel5 = 0.9973;
495  double integral, tsum = 0.;
496 
497  integral = j_hist_copy->Integral();
498 
499  while((tsum/integral)<contlevel5) {
500  double tmax = j_hist_copy->GetMaximum();
501  int bin = j_hist_copy->GetMaximumBin();
502  double xval = j_hist_copy->GetXaxis()->GetBinCenter(bin);
503  double xwidth = j_hist_copy->GetXaxis()->GetBinWidth(bin);
504  if((tsum/integral)<contlevel1) {
505  j_hist_copy->SetBinContent(bin,-1.0);
506  j_hist_1sig->SetBinContent(bin,0.);
507  j_hist_2sig->SetBinContent(bin,0.);
508  j_hist_3sig->SetBinContent(bin,0.);
509  if(xval<j_1sig_low && xval<j_bf) j_1sig_low = xval - xwidth/2.;
510  if(xval>j_1sig_up && xval>j_bf) j_1sig_up = xval + xwidth/2.;
511  }
512  if((tsum/integral)<contlevel2 && (tsum / integral > contlevel1) ) {
513  j_hist_copy->SetBinContent(bin,-5.0);
514  j_hist_2sig->SetBinContent(bin,0.);
515  j_hist_3sig->SetBinContent(bin,0.);
516  if(xval<j_2sig_low && xval<j_bf) j_2sig_low = xval - xwidth/2.;
517  if(xval>j_2sig_up && xval>j_bf) j_2sig_up = xval + xwidth/2.;
518  }
519  if((tsum/integral)<contlevel4 && (tsum / integral > contlevel1) ) {
520  j_hist_copy->SetBinContent(bin,-9.0);
521  j_hist_3sig->SetBinContent(bin,0.);
522  if(xval < j_3sig_low && xval <j_bf) j_3sig_low = xval - xwidth/2.;
523  if(xval > j_3sig_up && xval > j_bf) j_3sig_up = xval + xwidth/2.;
524  }
525  tsum+=tmax;
526  }
527 
528  integral = j_hist_sdcp_copy->Integral();
529  tsum = 0.;
530 
531  while((tsum/integral)<contlevel5) {
532  double tmax = j_hist_sdcp_copy->GetMaximum();
533  int bin = j_hist_sdcp_copy->GetMaximumBin();
534  double xval = j_hist_sdcp_copy->GetXaxis()->GetBinCenter(bin);
535  double xwidth = j_hist_sdcp_copy->GetXaxis()->GetBinWidth(bin);
536  if((tsum/integral)<contlevel1) {
537  j_hist_sdcp_copy->SetBinContent(bin,-1.0);
538  j_hist_sdcp_1sig->SetBinContent(bin,0.);
539  j_hist_sdcp_2sig->SetBinContent(bin,0.);
540  j_hist_sdcp_3sig->SetBinContent(bin,0.);
541  if(xval<j_sdcp_1sig_low && xval<j_bf) j_sdcp_1sig_low = xval - xwidth/2.;
542  if(xval>j_sdcp_1sig_up && xval>j_bf) j_sdcp_1sig_up = xval + xwidth/2.;
543  }
544  if((tsum/integral)<contlevel2 && (tsum / integral > contlevel1) ) {
545  j_hist_sdcp_copy->SetBinContent(bin,-5.0);
546  j_hist_sdcp_2sig->SetBinContent(bin,0.);
547  j_hist_sdcp_3sig->SetBinContent(bin,0.);
548  if(xval<j_sdcp_2sig_low && xval<j_bf) j_sdcp_2sig_low = xval - xwidth/2.;
549  if(xval>j_sdcp_2sig_up && xval>j_bf) j_sdcp_2sig_up = xval + xwidth/2.;
550  }
551  if((tsum/integral)<contlevel4 && (tsum / integral > contlevel1) ) {
552  j_hist_sdcp_copy->SetBinContent(bin,-9.0);
553  j_hist_sdcp_3sig->SetBinContent(bin,0.);
554  if(xval<j_sdcp_3sig_low && xval<j_bf) j_sdcp_3sig_low = xval - xwidth/2.;
555  if(xval>j_sdcp_3sig_up && xval>j_bf) j_sdcp_3sig_up = xval + xwidth/2.;
556  }
557  tsum+=tmax;
558  }
559 
560  j_hist_1sig->SetLineStyle(9);
561  j_hist_sdcp_1sig->SetLineStyle(9);
562  j_hist_2sig->SetLineStyle(7);
563  j_hist_sdcp_2sig->SetLineStyle(7);
564  j_hist_3sig->SetLineStyle(2);
565  j_hist_sdcp_3sig->SetLineStyle(2);
566 
567  auto ldash = std::make_unique<TH1D>("ldash", "solid", 10, -0.04, 0.04);
568  auto sdash = std::make_unique<TH1D>("sdash", "dashed", 10, -0.04, 0.04);
569  auto fdash = std::make_unique<TH1D>("fdash", "fdashed",10, -0.04, 0.04);
570  ldash->SetLineColor(kBlack);
571  sdash->SetLineColor(kBlack);
572  fdash->SetLineColor(kBlack);
573  ldash->SetLineWidth(2);
574  sdash->SetLineWidth(2);
575  fdash->SetLineWidth(2);
576  ldash->SetLineStyle(9);
577  sdash->SetLineStyle(7);
578  fdash->SetLineStyle(2);
579 
580  double vertUp = 0.5 * j_hist->GetMaximum();
581  auto jline_1sig_low = std::make_unique<TLine>(j_1sig_low, 0., j_1sig_low, vertUp);
582  auto jline_2sig_low = std::make_unique<TLine>(j_2sig_low, 0., j_2sig_low, vertUp);
583  auto jline_3sig_low = std::make_unique<TLine>(j_3sig_low, 0., j_3sig_low, vertUp);
584 
585  auto jline_1sig_up = std::make_unique<TLine>(j_1sig_up, 0., j_1sig_up,vertUp);
586  auto jline_2sig_up = std::make_unique<TLine>(j_2sig_up, 0., j_2sig_up,vertUp);
587  auto jline_3sig_up = std::make_unique<TLine>(j_3sig_up, 0., j_3sig_up,vertUp);
588 
589  auto jline_sdcp_1sig_low = std::make_unique<TLine>(j_sdcp_1sig_low, 0., j_sdcp_1sig_low, vertUp);
590  auto jline_sdcp_2sig_low = std::make_unique<TLine>(j_sdcp_2sig_low, 0., j_sdcp_2sig_low, vertUp);
591  auto jline_sdcp_3sig_low = std::make_unique<TLine>(j_sdcp_3sig_low, 0., j_sdcp_3sig_low, vertUp);
592 
593  auto jline_sdcp_1sig_up = std::make_unique<TLine>(j_sdcp_1sig_up, 0., j_sdcp_1sig_up, vertUp);
594  auto jline_sdcp_2sig_up = std::make_unique<TLine>(j_sdcp_2sig_up, 0., j_sdcp_2sig_up, vertUp);
595  auto jline_sdcp_3sig_up = std::make_unique<TLine>(j_sdcp_3sig_up, 0., j_sdcp_3sig_up, vertUp);
596 
597  double arrowLength = 0.003;
598  double arrowHeight = vertUp;
599 
600  auto MakeArrow = [&](double x, Color_t color, Width_t width) -> std::unique_ptr<TArrow> {
601  auto arrow = std::make_unique<TArrow>(x, arrowHeight, x - arrowLength, arrowHeight, 0.02, ">");
602  arrow->SetLineColor(color);
603  arrow->SetLineWidth(width);
604  return arrow;
605  };
606 
607  auto j_arrow_1sig_up = MakeArrow(j_1sig_up, j_hist_1sig->GetLineColor(), j_hist_1sig->GetLineWidth());
608  auto j_arrow_2sig_up = MakeArrow(j_2sig_up, j_hist_2sig->GetLineColor(), j_hist_2sig->GetLineWidth());
609  auto j_arrow_3sig_up = MakeArrow(j_3sig_up, j_hist_3sig->GetLineColor(), j_hist_3sig->GetLineWidth());
610 
611  auto j_sdcp_arrow_1sig_up = MakeArrow(j_sdcp_1sig_up, j_hist_sdcp_1sig->GetLineColor(), j_hist_sdcp_1sig->GetLineWidth());
612  auto j_sdcp_arrow_2sig_up = MakeArrow(j_sdcp_2sig_up, j_hist_sdcp_2sig->GetLineColor(), j_hist_sdcp_2sig->GetLineWidth());
613  auto j_sdcp_arrow_3sig_up = MakeArrow(j_sdcp_3sig_up, j_hist_sdcp_3sig->GetLineColor(), j_hist_sdcp_3sig->GetLineWidth());
614 
615  MACH3LOG_DEBUG("j_1sig_low = {:.4f}, j_2sig_low = {:.4f}, j_3sig_low = {:.4f}", j_1sig_low, j_2sig_low, j_3sig_low);
616  MACH3LOG_DEBUG("j_1sig_up = {:.4f}, j_2sig_up = {:.4f}, j_3sig_up = {:.4f}", j_1sig_up, j_2sig_up, j_3sig_up);
617 
618  auto CopyLineStyle = [](const TH1D* src, TLine* dst) {
619  dst->SetLineColor(src->GetLineColor());
620  dst->SetLineStyle(src->GetLineStyle());
621  dst->SetLineWidth(src->GetLineWidth());
622  };
623 
624  CopyLineStyle(j_hist_1sig.get(), jline_1sig_low.get());
625  CopyLineStyle(j_hist_1sig.get(), jline_1sig_up.get());
626  CopyLineStyle(j_hist_2sig.get(), jline_2sig_low.get());
627  CopyLineStyle(j_hist_2sig.get(), jline_2sig_up.get());
628  CopyLineStyle(j_hist_3sig.get(), jline_3sig_low.get());
629  CopyLineStyle(j_hist_3sig.get(), jline_3sig_up.get());
630 
631  CopyLineStyle(j_hist_sdcp_1sig.get(), jline_sdcp_1sig_low.get());
632  CopyLineStyle(j_hist_sdcp_1sig.get(), jline_sdcp_1sig_up.get());
633  CopyLineStyle(j_hist_sdcp_2sig.get(), jline_sdcp_2sig_low.get());
634  CopyLineStyle(j_hist_sdcp_2sig.get(), jline_sdcp_2sig_up.get());
635  CopyLineStyle(j_hist_sdcp_3sig.get(), jline_sdcp_3sig_low.get());
636  CopyLineStyle(j_hist_sdcp_3sig.get(), jline_sdcp_3sig_up.get());
637 
638  auto leg = std::make_unique<TLegend>(0.45, 0.60, 0.75, 0.90);
639  leg->SetTextSize(0.05);
640  leg->SetFillStyle(0);
641  leg->SetNColumns(1);
642  leg->SetTextFont(132);
643  leg->SetBorderSize(0);
644 
645  leg->AddEntry(j_hist.get(), "Prior flat in #delta_{CP}", "l");
646  leg->AddEntry(j_hist_sdcp.get(), "Prior flat in sin#delta_{CP}", "l");
647  leg->AddEntry(ldash.get(), "68% CI", "l");
648  leg->AddEntry(sdash.get(), "90% CI", "l");
649  leg->AddEntry(fdash.get(), "99% CI", "l");
650 
651  j_hist->GetYaxis()->SetRangeUser(0., j_hist->GetMaximum()*1.15);
652  j_hist->Draw("h");
653  j_hist_sdcp->Draw("same h");
654 
655  jline_sdcp_1sig_up->Draw("same");
656  jline_sdcp_2sig_up->Draw("same");
657  jline_sdcp_3sig_up->Draw("same");
658  jline_1sig_up->Draw("same");
659  jline_2sig_up->Draw("same");
660  jline_3sig_up->Draw("same");
661 
662  j_arrow_1sig_up->Draw();
663  j_arrow_2sig_up->Draw();
664  j_arrow_3sig_up->Draw();
665  j_sdcp_arrow_1sig_up->Draw();
666  j_sdcp_arrow_2sig_up->Draw();
667  j_sdcp_arrow_3sig_up->Draw();
668  leg->Draw("same");
669 
670  auto ttext = std::make_unique<TText>();
671  ttext->SetNDC(); // Use normalized device coordinates
672  ttext->SetTextSize(0.03); // Adjust size as needed
673  ttext->SetTextAlign(13); // Align left-top
674 
675  if (hierarchy == 1) ttext->DrawText(0.15, 0.85, "Normal Ordering");
676  else if (hierarchy == 0) ttext->DrawText(0.15, 0.85, "Both Orderings");
677  else if (hierarchy == -1) ttext->DrawText(0.15, 0.85, "Inverted Ordering");
678 
679  gPad->RedrawAxis();
680  Posterior->Update();
681  gPad->Update();
682 
683  Posterior->Print(CanvasName);
684 
685  if(hierarchy == 1) Posterior->Write("jarl1D_NH_comp");
686  else if(hierarchy == 0) Posterior->Write("jarl1D_both_comp");
687  else if(hierarchy == -1) Posterior->Write("jarl1D_IH_comp");
688  }
689 
690  gErrorIgnoreLevel = originalErrorLevel;
691 }
692 
693 // ***************
695 // ***************
697  {
698  MACH3LOG_WARN("Will not {}, as oscillation parameters are missing", __func__);
699  return;
700  }
701  MACH3LOG_INFO("Starting {}", __func__);
702 
703  // get best fit for delta CP
704  const double best_fit = (*Means_HPD)(DeltaCPIndex);
705 
706  const double sigma_p = (*Errors_HPD_Positive)(DeltaCPIndex);
707  const double sigma_n = (*Errors_HPD_Negative)(DeltaCPIndex);
708  // make sure result is between -pi and pi
709  auto wrap_pi = [](double x) {
710  while (x > TMath::Pi()) x -= 2*TMath::Pi();
711  while (x < -TMath::Pi()) x += 2*TMath::Pi();
712  return x;
713  };
714 
715  std::array<double, 6> bds;
716  bds[0] = wrap_pi(best_fit - 3.0 * sigma_n); // -3σ
717  bds[1] = wrap_pi(best_fit - 2.0 * sigma_n); // -2σ
718  bds[2] = wrap_pi(best_fit - 1.0 * sigma_n); // -1σ
719  bds[3] = wrap_pi(best_fit + 1.0 * sigma_p); // +1σ
720  bds[4] = wrap_pi(best_fit + 2.0 * sigma_p); // +2σ
721  bds[5] = wrap_pi(best_fit + 3.0 * sigma_p); // +3σ
722 
723  constexpr double radius = 0.4;
724  constexpr double rad_to_deg = 180.0 / TMath::Pi();
725 
726  // ROOT expects TEllipse angles in degrees, counterclockwise from the x-axis.
727  // If phimax < phimin, ROOT draws counterclockwise across the full circle, causing overlaps.
728  // This ensures threesigA slice stays within the intended range.
729  auto normalize_angle = [](double rad) {
730  // If rad is negative, add 2*pi to wrap into [0, 2*pi)
731  if (rad < 0) rad += 2.0 * TMath::Pi();
732  return rad;
733  };
734 
735  TEllipse onesig (0.5, 0.5, radius, radius, bds[2] * rad_to_deg, bds[4] * rad_to_deg);
736  TEllipse twosigA (0.5, 0.5, radius, radius, bds[1] * rad_to_deg, bds[2] * rad_to_deg);
737  TEllipse twosigB (0.5, 0.5, radius, radius, bds[3] * rad_to_deg, bds[4] * rad_to_deg);
738 
739  // three sigma slices
740  TEllipse threesigA(0.5, 0.5, radius, radius, bds[0] * rad_to_deg, normalize_angle(bds[1]) * rad_to_deg);
741  TEllipse threesigB(0.5, 0.5, radius, radius, bds[4] * rad_to_deg, bds[5] * rad_to_deg);
742 
743  // Remaining slices
744  TEllipse rest(0.5, 0.5, radius, radius, bds[5]*rad_to_deg, bds[0]*rad_to_deg);
745  TEllipse restA(0.5, 0.5, radius, radius, bds[5]*rad_to_deg, 180.0);
746  TEllipse restB(0.5, 0.5, radius, radius, -180.0, bds[0]*rad_to_deg);
747 
748  onesig.SetFillColor(13);
749  twosigA.SetFillColor(12);
750  twosigB.SetFillColor(12);
751  threesigA.SetFillColor(11);
752  threesigB.SetFillColor(11);
753  TLine line1(0.5 - radius, 0.5, 0.5 + radius, 0.5);
754  line1.SetLineWidth(3);
755 
756  TLine line2(0.5, 0.5 - radius, 0.5, 0.5 + radius);
757  line2.SetLineWidth(3);
758 
759  TArrow bf(0.5, 0.5, 0.5 + radius * cos(best_fit),0.5 + radius * sin(best_fit),0.04, "|>");
760  bf.SetLineWidth(3);
761  bf.SetLineColor(kRed);
762  bf.SetFillColor(kRed);
763 
764  TCanvas canvas("canvas", "canvas", 0, 0, 1000, 1000);
765  onesig.Draw();
766  twosigA.Draw();
767  twosigB.Draw();
768  threesigA.Draw();
769  threesigB.Draw();
770 
771  // Check if the rest wraps around the circle
772  if (bds[5] > 0) {
773  // Single rest slice
774  rest.Draw();
775  } else {
776  // Split rest into two slices
777  restA.Draw();
778  restB.Draw();
779  }
780 
781  line1.Draw();
782  line2.Draw();
783  bf.Draw();
784 
785  TLegend leg(0.0, 0.8, 0.23, 0.95);
786  leg.AddEntry(&bf, "Best Fit", "L");
787  leg.AddEntry(&onesig, "1#sigma", "F");
788  leg.AddEntry(&twosigA, "2#sigma", "F");
789  leg.AddEntry(&threesigA, "3#sigma", "F");
790  leg.Draw();
791 
792  // KS: Simple lambda to avoid copy-pasting
793  auto draw_text = [](auto& txt, Color_t color = kBlack) {
794  txt.SetTextAlign(22);
795  txt.SetTextColor(color);
796  txt.SetTextFont(43);
797  txt.SetTextSize(40);
798  txt.SetTextAngle(0);
799  txt.Draw();
800  };
801 
802  //KS: If best fit point is somehow very close text we simply not plot it
803  // Define a threshold for "too close"
804  constexpr double too_close_threshold = 0.1;
805 
806  // Position of tbf
807  const double tbf_x = 0.5 + (radius + 0.02) * cos(best_fit);
808  const double tbf_y = 0.5 + (radius + 0.02) * sin(best_fit);
809 
810  // Function to calculate distance between two points
811  auto distance = [](double x1, double y1, double x2, double y2) {
812  return std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
813  };
814 
815  // Check and draw right 0
816  constexpr double t0_x = 0.5 + radius + 0.02;
817  constexpr double t0_y = 0.5;
818  TText t0(t0_x, t0_y, "0");
819  if (distance(tbf_x, tbf_y, t0_x, t0_y) > too_close_threshold) {
820  draw_text(t0);
821  }
822 
823  // Check and draw left pi
824  constexpr double tp_x = 0.5 - radius - 0.02;
825  constexpr double tp_y = 0.5;
826  TLatex tp(tp_x, tp_y, "#pi");
827  if (distance(tbf_x, tbf_y, tp_x, tp_y) > too_close_threshold) {
828  draw_text(tp);
829  }
830 
831  // Check and draw top pi/2
832  constexpr double tp2_x = 0.5;
833  constexpr double tp2_y = 0.5 + radius + 0.04;
834  TLatex tp2(tp2_x, tp2_y, "#frac{#pi}{2}");
835  if (distance(tbf_x, tbf_y, tp2_x, tp2_y) > too_close_threshold) {
836  draw_text(tp2);
837  }
838 
839  // Check and draw bottom -pi/2
840  constexpr double tmp2_x = 0.5;
841  constexpr double tmp2_y = 0.5 - radius - 0.04;
842  TLatex tmp2(tmp2_x, tmp2_y, "-#frac{#pi}{2}");
843  if (distance(tbf_x, tbf_y, tmp2_x, tmp2_y) > too_close_threshold) {
844  draw_text(tmp2);
845  }
846 
847  TLatex tbf(0.5 + (radius + 0.02) * cos(best_fit),
848  0.5 + (radius + 0.02) * sin(best_fit),
849  fmt::format("{:.2f}", best_fit).c_str());
850  draw_text(tbf, kRed);
851 
852  canvas.Print(CanvasName);
853 }
854 
855 // ***************
856 // MP: Calculate PMNS matrix elements
857 std::array<std::array<TComplex, 3>, 3> OscProcessor::CalculatePMNSElements(const double s2th13, const double s2th23, const double s2th12, const double dcp) const {
858 // ***************
859  const double s13 = std::sqrt(s2th13);
860  const double s23 = std::sqrt(s2th23);
861  const double s12 = std::sqrt(s2th12);
862 
863  const double sdcp = std::sin(dcp);
864  const double cdcp = std::cos(dcp);
865 
866  const double c13 = std::sqrt(1.-s2th13);
867  const double c12 = std::sqrt(1.-s2th12);
868  const double c23 = std::sqrt(1.-s2th23);
869 
870  double real_ue[3];
871  double imag_ue[3];
872  real_ue[0] = c12*c13;
873  imag_ue[0] = 0.;
874  real_ue[1] = s12*c13;
875  imag_ue[1] = 0.;
876  real_ue[2] = s13*cdcp;
877  imag_ue[2] = -s13*sdcp;
878 
879  double real_umu[3];
880  double imag_umu[3];
881  real_umu[0] = -s12*c23 - c12*s23*s13*cdcp;
882  imag_umu[0] = -c12*s23*s13*sdcp;
883  real_umu[1] = c12*c23 - s12*s23*s13*cdcp;
884  imag_umu[1] = -s12*s23*s13*sdcp;
885  real_umu[2] = s23*c13;
886  imag_umu[2] = 0.;
887 
888  double real_utau[3];
889  double imag_utau[3];
890  real_utau[0] = s12*s23 - c12*c23*s13*cdcp;
891  imag_utau[0] = -c12*c23*s13*sdcp;
892  real_utau[1] = -c12*s23 - s12*c23*s13*cdcp;
893  imag_utau[1] = -s12*c23*s13*sdcp;
894  real_utau[2] = c23*c13;
895  imag_utau[2] = 0.;
896 
897  TComplex U[3][3];
898  for (int i = 0; i < 3; i++) {
899  U[0][i] = TComplex(real_ue[i], imag_ue[i]);
900  U[1][i] = TComplex(real_umu[i], imag_umu[i]);
901  U[2][i] = TComplex(real_utau[i], imag_utau[i]);
902  }
903 
904  return {{{U[0][0], U[0][1], U[0][2]}, {U[1][0], U[1][1], U[1][2]}, {U[2][0], U[2][1], U[2][2]}}};
905 }
906 
907 // ***************
908 // MP: Produce PMNS matrix elements
910 // ***************
911  if(!OscEnabled ||
916  {
917  MACH3LOG_WARN("Will not {}, as oscillation parameters are missing", __func__);
918  return;
919  }
920  MACH3LOG_INFO("Starting {}", __func__);
921 
922  double s2th13, s2th23, s2th12, dcp = M3::_BAD_DOUBLE_;
923 
924 
925  TDirectory *PMNSElementsDir = OutputFile->mkdir("PMNSElements");
926  PMNSElementsDir->cd();
927 
928  unsigned int step = 0;
929  Chain->SetBranchStatus("*", false);
930 
931  Chain->SetBranchStatus(Sin2Theta13Name.c_str(), true);
932  Chain->SetBranchAddress(Sin2Theta13Name.c_str(), &s2th13);
933 
934  Chain->SetBranchStatus(Sin2Theta23Name.c_str(), true);
935  Chain->SetBranchAddress(Sin2Theta23Name.c_str(), &s2th23);
936 
937  Chain->SetBranchStatus(Sin2Theta12Name.c_str(), true);
938  Chain->SetBranchAddress(Sin2Theta12Name.c_str(), &s2th12);
939 
940  Chain->SetBranchStatus(DeltaCPName.c_str(), true);
941  Chain->SetBranchAddress(DeltaCPName.c_str(), &dcp);
942 
943  Chain->SetBranchStatus("step", true);
944  Chain->SetBranchAddress("step", &step);
945 
946  double weight = 1.0;
947  std::vector<double> reweights(ReweightNames.size(), 1.0);
948  bool anyMissing = false;
949  for (size_t i = 0; i < ReweightNames.size(); ++i) {
950  const auto& name = ReweightNames[i];
951  if (Chain->GetBranch(name.c_str())) {
952  Chain->SetBranchStatus(name.c_str(), true);
953  Chain->SetBranchAddress(name.c_str(), &reweights[i]);
954  } else {
955  anyMissing = true;
956  }
957  }
958  if (anyMissing) {
959  MACH3LOG_WARN("Some reweight branches were missing — using partial weight");
960  reweights.clear();
961  }
962  constexpr int n_bins = 1000;
963 
964  std::unique_ptr<TH1D> h_ue[3];
965  std::unique_ptr<TH1D> h_umu[3];
966  std::unique_ptr<TH1D> h_utau[3];
967 
968  std::unique_ptr<TH1D> h_ue_real[3];
969  std::unique_ptr<TH1D> h_umu_real[3];
970  std::unique_ptr<TH1D> h_utau_real[3];
971 
972  std::unique_ptr<TH1D> h_ue_imag[3];
973  std::unique_ptr<TH1D> h_umu_imag[3];
974  std::unique_ptr<TH1D> h_utau_imag[3];
975 
976  std::unique_ptr<TH2D> h_ue_s2th12[3];
977  std::unique_ptr<TH2D> h_umu_s2th12[3];
978  std::unique_ptr<TH2D> h_utau_s2th12[3];
979 
980  std::unique_ptr<TH2D> h_ue_s2th13[3];
981  std::unique_ptr<TH2D> h_umu_s2th13[3];
982  std::unique_ptr<TH2D> h_utau_s2th13[3];
983 
984  std::unique_ptr<TH2D> h_ue_s2th23[3];
985  std::unique_ptr<TH2D> h_umu_s2th23[3];
986  std::unique_ptr<TH2D> h_utau_s2th23[3];
987 
988  std::unique_ptr<TH2D> h_ue_dcp[3];
989  std::unique_ptr<TH2D> h_umu_dcp[3];
990  std::unique_ptr<TH2D> h_utau_dcp[3];
991 
992  for (int iU = 0; iU < 3; iU++) {
993  h_ue[iU] = std::make_unique<TH1D>(Form("h_ue%d", iU+1), Form(";|U_{e%d}|", iU+1), n_bins, 0., 1.);
994  h_ue[iU]->SetDirectory(nullptr);
995  h_umu[iU] = std::make_unique<TH1D>(Form("h_umu%d", iU+1), Form(";|U_{#mu%d}|", iU+1), n_bins, 0., 1.);
996  h_umu[iU]->SetDirectory(nullptr);
997  h_utau[iU] = std::make_unique<TH1D>(Form("h_utau%d", iU+1), Form(";|U_{#tau%d}|", iU+1), n_bins, 0., 1.);
998  h_utau[iU]->SetDirectory(nullptr);
999 
1000  h_ue_real[iU] = std::make_unique<TH1D>(Form("h_ue%d_real", iU+1), Form(";Re(U_{e%d})", iU+1), n_bins, -1., 1.);
1001  h_ue_real[iU]->SetDirectory(nullptr);
1002  h_umu_real[iU] = std::make_unique<TH1D>(Form("h_umu%d_real", iU+1), Form(";Re(U_{#mu%d})", iU+1), n_bins, -1., 1.);
1003  h_umu_real[iU]->SetDirectory(nullptr);
1004  h_utau_real[iU] = std::make_unique<TH1D>(Form("h_utau%d_real", iU+1), Form(";Re(U_{#tau%d})", iU+1), n_bins, -1., 1.);
1005  h_utau_real[iU]->SetDirectory(nullptr);
1006 
1007  h_ue_imag[iU] = std::make_unique<TH1D>(Form("h_ue%d_imag", iU+1), Form(";Im(U_{e%d})", iU+1), n_bins, -1., 1.);
1008  h_ue_imag[iU]->SetDirectory(nullptr);
1009  h_umu_imag[iU] = std::make_unique<TH1D>(Form("h_umu%d_imag", iU+1), Form(";Im(U_{#mu%d})", iU+1), n_bins, -1., 1.);
1010  h_umu_imag[iU]->SetDirectory(nullptr);
1011  h_utau_imag[iU] = std::make_unique<TH1D>(Form("h_utau%d_imag", iU+1), Form(";Im(U_{#tau%d})", iU+1), n_bins, -1., 1.);
1012  h_utau_imag[iU]->SetDirectory(nullptr);
1013 
1014  h_ue_s2th12[iU] = std::make_unique<TH2D>(Form("h_ue%d_s2th12", iU+1), Form(";|U_{e%d}|;sin^{2}(#theta_{12})", iU+1),
1015  n_bins, 0., 1., n_bins, 0.15, 0.5);
1016  h_ue_s2th12[iU]->SetDirectory(nullptr);
1017  h_umu_s2th12[iU] = std::make_unique<TH2D>(Form("h_umu%d_s2th12", iU+1), Form(";|U_{#mu%d}|;sin^{2}(#theta_{12})", iU+1),
1018  n_bins, 0., 1., n_bins, 0.15, 0.5);
1019  h_umu_s2th12[iU]->SetDirectory(nullptr);
1020  h_utau_s2th12[iU] = std::make_unique<TH2D>(Form("h_utau%d_s2th12", iU+1), Form(";|U_{#tau%d}|;sin^{2}(#theta_{12})", iU+1),
1021  n_bins, 0., 1., n_bins, 0.15, 0.5);
1022  h_utau_s2th12[iU]->SetDirectory(nullptr);
1023 
1024 
1025  h_ue_s2th13[iU] = std::make_unique<TH2D>(Form("h_ue%d_s2th13", iU+1), Form(";|U_{e%d}|;sin^{2}(#theta_{13})", iU+1),
1026  n_bins, 0., 1., n_bins, 0., 0.1);
1027  h_ue_s2th13[iU]->SetDirectory(nullptr);
1028  h_umu_s2th13[iU] = std::make_unique<TH2D>(Form("h_umu%d_s2th13", iU+1), Form(";|U_{#mu%d}|;sin^{2}(#theta_{13})", iU+1),
1029  n_bins, 0., 1., n_bins, 0., 0.1);
1030  h_umu_s2th13[iU]->SetDirectory(nullptr);
1031  h_utau_s2th13[iU] = std::make_unique<TH2D>(Form("h_utau%d_s2th13", iU+1), Form(";|U_{#tau%d}|;sin^{2}(#theta_{13})", iU+1),
1032  n_bins, 0., 1., n_bins, 0., 0.1);
1033  h_utau_s2th13[iU]->SetDirectory(nullptr);
1034 
1035 
1036  h_ue_s2th23[iU] = std::make_unique<TH2D>(Form("h_ue%d_s2th23", iU+1), Form(";|U_{e%d}|;sin^{2}(#theta_{23})", iU+1),
1037  n_bins, 0., 1., n_bins, 0.3, 0.8);
1038  h_ue_s2th23[iU]->SetDirectory(nullptr);
1039  h_umu_s2th23[iU] = std::make_unique<TH2D>(Form("h_umu%d_s2th23", iU+1), Form(";|U_{#mu%d}|;sin^{2}(#theta_{23})", iU+1),
1040  n_bins, 0., 1., n_bins, 0.3, 0.8);
1041  h_umu_s2th23[iU]->SetDirectory(nullptr);
1042  h_utau_s2th23[iU] = std::make_unique<TH2D>(Form("h_utau%d_s2th23", iU+1), Form(";|U_{#tau%d}|;sin^{2}(#theta_{23})", iU+1),
1043  n_bins, 0., 1., n_bins, 0.3, 0.8);
1044  h_utau_s2th23[iU]->SetDirectory(nullptr);
1045 
1046 
1047  h_ue_dcp[iU] = std::make_unique<TH2D>(Form("h_ue%d_dcp", iU+1), Form(";|U_{e%d}|;#delta_{CP}", iU+1),
1048  n_bins, 0., 1., n_bins, -TMath::Pi(), TMath::Pi());
1049  h_ue_dcp[iU]->SetDirectory(nullptr);
1050  h_umu_dcp[iU] = std::make_unique<TH2D>(Form("h_umu%d_dcp", iU+1), Form(";|U_{#mu%d}|;#delta_{CP}", iU+1),
1051  n_bins, 0., 1., n_bins, -TMath::Pi(), TMath::Pi());
1052  h_umu_dcp[iU]->SetDirectory(nullptr);
1053  h_utau_dcp[iU] = std::make_unique<TH2D>(Form("h_utau%d_dcp", iU+1), Form(";|U_{#tau%d}|;#delta_{CP}", iU+1),
1054  n_bins, 0., 1., n_bins, -TMath::Pi(), TMath::Pi());
1055  h_utau_dcp[iU]->SetDirectory(nullptr);
1056  }
1057 
1058  // MP: 2D histograms for all unique pairs of |U_{alpha i}| vs |U_{beta j}| (no self-pairs)
1059  std::vector<std::unique_ptr<TH2D>> h_UU;
1060  std::string U_names[9] = {"ue1", "ue2", "ue3", "umu1", "umu2", "umu3", "utau1", "utau2", "utau3"};
1061  std::string U_tex[9] = {"|U_{e1}|", "|U_{e2}|", "|U_{e3}|", "|U_{#mu1}|", "|U_{#mu2}|", "|U_{#mu3}|", "|U_{#tau1}|", "|U_{#tau2}|", "|U_{#tau3}|"};
1062  for(int i=0; i < 9; ++i){
1063  for(int j = i+1; j < 9; ++j){
1064  std::string name = "h_" + U_names[i] + "_" + U_names[j];
1065  std::string title = ";" + U_tex[i] + ";" + U_tex[j];
1066  h_UU.push_back(std::make_unique<TH2D>(name.c_str(), title.c_str(), n_bins, 0., 1., n_bins, 0., 1.));
1067  h_UU.back()->SetDirectory(nullptr);
1068  }
1069  }
1070  const Long64_t countwidth = nEntries/5;
1071  for(int i = 0; i < nEntries; i++) {
1072  if (i % countwidth == 0) {
1075  } else {
1076  Chain->GetEntry(i);
1077  }
1078 
1079  if(step < BurnInCut) continue; // burn-in cut
1080 
1081  const std::array<std::array<TComplex, 3>, 3> U = CalculatePMNSElements(s2th13, s2th23, s2th12, dcp);
1082  // KS: Calculate total weight
1083  weight = 1.0;
1084  for (const auto& w : reweights) {
1085  weight *= w;
1086  }
1087  for(int iU = 0; iU < 3; iU++){
1088  h_ue[iU]->Fill(TComplex::Abs(U[0][iU]), weight);
1089  h_umu[iU]->Fill(TComplex::Abs(U[1][iU]), weight);
1090  h_utau[iU]->Fill(TComplex::Abs(U[2][iU]), weight);
1091 
1092  h_ue_real[iU]->Fill(U[0][iU].Re(), weight);
1093  h_umu_real[iU]->Fill(U[1][iU].Re(), weight);
1094  h_utau_real[iU]->Fill(U[2][iU].Re(), weight);
1095 
1096  h_ue_imag[iU]->Fill(U[0][iU].Im(), weight);
1097  h_umu_imag[iU]->Fill(U[1][iU].Im(), weight);
1098  h_utau_imag[iU]->Fill(U[2][iU].Im(), weight);
1099 
1100  h_ue_s2th12[iU]->Fill(TComplex::Abs(U[0][iU]), s2th12, weight);
1101  h_umu_s2th12[iU]->Fill(TComplex::Abs(U[1][iU]), s2th12, weight);
1102  h_utau_s2th12[iU]->Fill(TComplex::Abs(U[2][iU]), s2th12, weight);
1103 
1104  h_ue_s2th13[iU]->Fill(TComplex::Abs(U[0][iU]), s2th13, weight);
1105  h_umu_s2th13[iU]->Fill(TComplex::Abs(U[1][iU]), s2th13, weight);
1106  h_utau_s2th13[iU]->Fill(TComplex::Abs(U[2][iU]), s2th13, weight);
1107 
1108  h_ue_s2th23[iU]->Fill(TComplex::Abs(U[0][iU]), s2th23, weight);
1109  h_umu_s2th23[iU]->Fill(TComplex::Abs(U[1][iU]), s2th23, weight);
1110  h_utau_s2th23[iU]->Fill(TComplex::Abs(U[2][iU]), s2th23, weight);
1111 
1112  h_ue_dcp[iU]->Fill(TComplex::Abs(U[0][iU]), dcp, weight);
1113  h_umu_dcp[iU]->Fill(TComplex::Abs(U[1][iU]), dcp, weight);
1114  h_utau_dcp[iU]->Fill(TComplex::Abs(U[2][iU]), dcp, weight);
1115  }
1116 
1117  // MP: Store in an array for easy access
1118  double U_mod[9] = {TComplex::Abs(U[0][0]), TComplex::Abs(U[0][1]), TComplex::Abs(U[0][2]), TComplex::Abs(U[1][0]), TComplex::Abs(U[1][1]), TComplex::Abs(U[1][2]), TComplex::Abs(U[2][0]), TComplex::Abs(U[2][1]), TComplex::Abs(U[2][2])};
1119  int idx = 0;
1120  for(int ix = 0; ix < 9; ++ix){
1121  for(int iy = ix+1; iy<9; ++iy){
1122  h_UU[idx]->Fill(U_mod[ix], U_mod[iy], weight);
1123  ++idx;
1124  }
1125  }
1126  } // end loop over steps
1127 
1128  // Now we save
1129  PMNSElementsDir->cd();
1130 
1131  for (int iU = 0; iU < 3; iU++) {
1132  h_ue[iU]->Write(Form("h_ue%d", iU+1));
1133  h_umu[iU]->Write(Form("h_umu%d", iU+1));
1134  h_utau[iU]->Write(Form("h_utau%d", iU+1));
1135 
1136  h_ue_real[iU]->Write(Form("h_ue%d_real", iU+1));
1137  h_umu_real[iU]->Write(Form("h_umu%d_real", iU+1));
1138  h_utau_real[iU]->Write(Form("h_utau%d_real", iU+1));
1139 
1140  h_ue_imag[iU]->Write(Form("h_ue%d_imag", iU+1));
1141  h_umu_imag[iU]->Write(Form("h_umu%d_imag", iU+1));
1142  h_utau_imag[iU]->Write(Form("h_utau%d_imag", iU+1));
1143 
1144  h_ue_s2th12[iU]->Write(Form("h_ue%d_s2th12", iU+1));
1145  h_umu_s2th12[iU]->Write(Form("h_umu%d_s2th12", iU+1));
1146  h_utau_s2th12[iU]->Write(Form("h_utau%d_s2th12", iU+1));
1147 
1148  h_ue_s2th13[iU]->Write(Form("h_ue%d_s2th13", iU+1));
1149  h_umu_s2th13[iU]->Write(Form("h_umu%d_s2th13", iU+1));
1150  h_utau_s2th13[iU]->Write(Form("h_utau%d_s2th13", iU+1));
1151 
1152  h_ue_s2th23[iU]->Write(Form("h_ue%d_s2th23", iU+1));
1153  h_umu_s2th23[iU]->Write(Form("h_umu%d_s2th23", iU+1));
1154  h_utau_s2th23[iU]->Write(Form("h_utau%d_s2th23", iU+1));
1155 
1156  h_ue_dcp[iU]->Write(Form("h_ue%d_dcp", iU+1));
1157  h_umu_dcp[iU]->Write(Form("h_umu%d_dcp", iU+1));
1158  h_utau_dcp[iU]->Write(Form("h_utau%d_dcp", iU+1));
1159  }
1160 
1161  // MP: Write all |U_{alpha i}| vs |U_{beta j}| 2D histograms (no self-pairs)
1162  for(size_t iPlot = 0; iPlot < h_UU.size(); ++iPlot){
1163  h_UU[iPlot]->Write();
1164  }
1165 
1166  PMNSElementsDir->Close();
1167  delete PMNSElementsDir;
1168 
1169  Chain->SetBranchStatus("*", true);
1170  OutputFile->cd();
1171 }
1172 
1173 // ***************
1174 // MP: Produce unitarity triangles from PMNS matrix elements
1176 // ***************
1177  if(!OscEnabled ||
1182  {
1183  MACH3LOG_WARN("Will not {}, as oscillation parameters are missing", __func__);
1184  return;
1185  }
1186  MACH3LOG_INFO("Starting {}", __func__);
1187 
1188  double s2th13, s2th23, s2th12, dcp = M3::_BAD_DOUBLE_;
1189 
1190  TComplex tr_emu_num, tr_etau_num, tr_mutau_num, tr_12_num, tr_13_num, tr_23_num;
1191  TComplex tr_emu_denom, tr_etau_denom, tr_mutau_denom, tr_12_denom, tr_13_denom, tr_23_denom;
1192  TComplex tr_emu, tr_etau, tr_mutau, tr_12, tr_13, tr_23;
1193 
1194  TDirectory *UnitarityTrianglesDir = OutputFile->mkdir("UnitarityTriangles");
1195  UnitarityTrianglesDir->cd();
1196 
1197  unsigned int step = 0;
1198  Chain->SetBranchStatus("*", false);
1199 
1200  Chain->SetBranchStatus(Sin2Theta13Name.c_str(), true);
1201  Chain->SetBranchAddress(Sin2Theta13Name.c_str(), &s2th13);
1202 
1203  Chain->SetBranchStatus(Sin2Theta23Name.c_str(), true);
1204  Chain->SetBranchAddress(Sin2Theta23Name.c_str(), &s2th23);
1205 
1206  Chain->SetBranchStatus(Sin2Theta12Name.c_str(), true);
1207  Chain->SetBranchAddress(Sin2Theta12Name.c_str(), &s2th12);
1208 
1209  Chain->SetBranchStatus(DeltaCPName.c_str(), true);
1210  Chain->SetBranchAddress(DeltaCPName.c_str(), &dcp);
1211 
1212  Chain->SetBranchStatus("step", true);
1213  Chain->SetBranchAddress("step", &step);
1214 
1215  double weight = 1.0;
1216  std::vector<double> reweights(ReweightNames.size(), 1.0);
1217  bool anyMissing = false;
1218  for (size_t i = 0; i < ReweightNames.size(); ++i) {
1219  const auto& name = ReweightNames[i];
1220  if (Chain->GetBranch(name.c_str())) {
1221  Chain->SetBranchStatus(name.c_str(), true);
1222  Chain->SetBranchAddress(name.c_str(), &reweights[i]);
1223  } else {
1224  anyMissing = true;
1225  }
1226  }
1227  if (anyMissing) {
1228  MACH3LOG_WARN("Some reweight branches were missing — using partial weight");
1229  reweights.clear();
1230  }
1231  constexpr int n_bins = 1000;
1232 
1233  std::unique_ptr<TH2D> h_tr_emu;
1234  std::unique_ptr<TH2D> h_tr_etau;
1235  std::unique_ptr<TH2D> h_tr_mutau;
1236 
1237  std::unique_ptr<TH2D> h_tr_12;
1238  std::unique_ptr<TH2D> h_tr_13;
1239  std::unique_ptr<TH2D> h_tr_23;
1240 
1241  h_tr_emu = std::make_unique<TH2D>("h_tr_emu",";#rho_{e#mu};#eta_{e#mu}",n_bins,-5,5,n_bins,-5,5);
1242  h_tr_emu->SetDirectory(nullptr);
1243  h_tr_etau = std::make_unique<TH2D>("h_tr_etau",";#rho_{e#tau};#eta_{e#tau}",n_bins,0,2,n_bins,-1,1);
1244  h_tr_etau->SetDirectory(nullptr);
1245  h_tr_mutau = std::make_unique<TH2D>("h_tr_mutau",";#rho_{#mu#tau};#eta_{#mu#tau}",n_bins,0,2,n_bins,-1,1);
1246  h_tr_mutau->SetDirectory(nullptr);
1247 
1248  h_tr_12 = std::make_unique<TH2D>("h_tr_12",";#rho_{12};#eta_{12}",n_bins,0,3.2,n_bins,-1.5,1.5);
1249  h_tr_12->SetDirectory(nullptr);
1250  h_tr_13 = std::make_unique<TH2D>("h_tr_13",";#rho_{13};#eta_{13}",n_bins,0,2,n_bins,-1,1);
1251  h_tr_13->SetDirectory(nullptr);
1252  h_tr_23 = std::make_unique<TH2D>("h_tr_23",";#rho_{23};#eta_{23}",n_bins,-8,8,n_bins,-8,8);
1253  h_tr_23->SetDirectory(nullptr);
1254 
1255  const Long64_t countwidth = nEntries/5;
1256  for(int i = 0; i < nEntries; i++) {
1257  if (i % countwidth == 0) {
1260  } else {
1261  Chain->GetEntry(i);
1262  }
1263 
1264  if(step < BurnInCut) continue; // burn-in cut
1265 
1266  // KS: Calculate total weight
1267  weight = 1.0;
1268  for (const auto& w : reweights) {
1269  weight *= w;
1270  }
1271 
1272  const std::array<std::array<TComplex, 3>, 3> U = CalculatePMNSElements(s2th13, s2th23, s2th12, dcp);
1273 
1274  // Calculate the sides of the unitarity triangles
1275  tr_emu_num = U[0][0].operator*(TComplex::Conjugate(U[1][0]));
1276  tr_emu_denom = U[0][2].operator*(TComplex::Conjugate(U[1][2]));
1277  tr_emu = - tr_emu_num.operator/(tr_emu_denom);
1278 
1279  tr_etau_num = U[0][1].operator*(TComplex::Conjugate(U[2][1]));
1280  tr_etau_denom = U[0][0].operator*(TComplex::Conjugate(U[2][0]));
1281  tr_etau = - tr_etau_num.operator/(tr_etau_denom);
1282 
1283  tr_mutau_num = U[1][2].operator*(TComplex::Conjugate(U[2][2]));
1284  tr_mutau_denom = U[1][1].operator*(TComplex::Conjugate(U[2][1]));
1285  tr_mutau = - tr_mutau_num.operator/(tr_mutau_denom);
1286 
1287  tr_12_num = U[0][0].operator*(TComplex::Conjugate(U[0][1]));
1288  tr_12_denom = U[1][0].operator*(TComplex::Conjugate(U[1][1]));
1289  tr_12 = - tr_12_num.operator/(tr_12_denom);
1290 
1291  tr_13_num = U[1][0].operator*(TComplex::Conjugate(U[1][2]));
1292  tr_13_denom = U[2][0].operator*(TComplex::Conjugate(U[2][2]));
1293  tr_13 = - tr_13_num.operator/(tr_13_denom);
1294 
1295  tr_23_num = U[2][1].operator*(TComplex::Conjugate(U[2][2]));
1296  tr_23_denom = U[0][1].operator*(TComplex::Conjugate(U[0][2]));
1297  tr_23 = - tr_23_num.operator/(tr_23_denom);
1298 
1299  h_tr_emu->Fill(tr_emu.Re(), tr_emu.Im(), weight);
1300  h_tr_etau->Fill(tr_etau.Re(), tr_etau.Im(), weight);
1301  h_tr_mutau->Fill(tr_mutau.Re(), tr_mutau.Im(), weight);
1302 
1303  h_tr_12->Fill(tr_12.Re(), tr_12.Im(), weight);
1304  h_tr_13->Fill(tr_13.Re(), tr_13.Im(), weight);
1305  h_tr_23->Fill(tr_23.Re(), tr_23.Im(), weight);
1306  } // end loop over steps
1307 
1308  // Now we save
1309  UnitarityTrianglesDir->cd();
1310 
1311  h_tr_emu->Write("h_tr_emu");
1312  h_tr_etau->Write("h_tr_etau");
1313  h_tr_mutau->Write("h_tr_mutau");
1314 
1315  h_tr_12->Write("h_tr_12");
1316  h_tr_13->Write("h_tr_13");
1317  h_tr_23->Write("h_tr_23");
1318 
1319  UnitarityTrianglesDir->Close();
1320  delete UnitarityTrianglesDir;
1321 
1322  Chain->SetBranchStatus("*", true);
1323  OutputFile->cd();
1324 }
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
Definition: Core.h:126
#define _MaCh3_Safe_Include_End_
ParameterEnum
Definition: MCMCProcessor.h:45
@ kXSecPar
Definition: MCMCProcessor.h:46
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
YAML::Node TMacroToYAML(const TMacro &macro)
KS: Convert a ROOT TMacro object to a YAML node.
Definition: YamlHelper.h:152
bool CheckNodeExists(const YAML::Node &node, Args... args)
KS: Wrapper function to call the recursive helper.
Definition: YamlHelper.h:60
Class responsible for processing MCMC chains, performing diagnostics, generating plots,...
Definition: MCMCProcessor.h:61
void GetNthParameter(const int param, double &Prior, double &PriorError, TString &Title) const
Get properties of parameter by passing it number.
std::vector< std::string > ReweightNames
Name of branch used for chain reweighting.
std::vector< std::vector< double > > ParamCentral
Parameters central values which we are going to analyse.
std::vector< std::vector< double > > ParamErrors
Uncertainty on a single parameter.
std::vector< int > nParam
Number of parameters per type.
std::vector< std::vector< bool > > ParamFlat
Whether Param has flat prior or not.
std::unique_ptr< TCanvas > Posterior
Fancy canvas used for our beautiful plots.
TFile * OutputFile
The output file.
TChain * Chain
Main chain storing all steps etc.
std::string MCMCFile
Name of MCMC file.
int nDraw
Number of all parameters used in the analysis.
std::vector< ParameterEnum > ParamType
Make an enum for which class this parameter belongs to so we don't have to keep string comparing.
TString CanvasName
Name of canvas which help to save to the sample pdf.
std::vector< std::string > ParameterGroup
std::vector< TString > BranchNames
std::vector< std::vector< TString > > ParamNames
Name of parameters which we are going to analyse.
std::vector< int > ParamTypeStartPos
int nEntries
KS: For merged chains number of entries will be different from nSteps.
void SavageDickeyPlot(std::unique_ptr< TH1D > &PriorHist, std::unique_ptr< TH1D > &PosteriorHist, const std::string &Title, const double EvaluationPoint) const
Produce Savage Dickey plot.
unsigned int BurnInCut
Value of burn in cut.
Custom exception class used throughout MaCh3.
double SamplePriorForParam(const int paramIndex, const std::unique_ptr< TRandom3 > &randGen, const std::vector< double > &FlatBounds) const
Draw Prior value.
void ProduceUnitarityTriangles()
MP: Produce unitarity triangles from PMNS matrix elements.
int DeltaCPIndex
Index of in the parameter list.
Definition: OscProcessor.h:102
double CalcJarlskog(const double s2th13, const double s2th23, const double s2th12, const double dcp) const
Calculate Jarlskog Invariant using oscillation parameters.
std::string Sin2Theta13Name
Name of the parameter representing .
Definition: OscProcessor.h:85
std::string Sin2Theta12Name
Name of the parameter representing .
Definition: OscProcessor.h:87
int Sin2Theta12Index
Index of in the parameter list.
Definition: OscProcessor.h:98
OscProcessor(const std::string &InputFile)
Constructs an OscProcessor object with the specified input file and options.
int DeltaM2_23Index
Index of in the parameter list.
Definition: OscProcessor.h:104
std::string DeltaCPName
Name of the parameter representing (the CP-violating phase).
Definition: OscProcessor.h:91
bool PlotJarlskog
Will plot Jarlskog Invariant using information in the chain.
Definition: OscProcessor.h:79
void ProducePMNSElements()
MP: Produce PMNS matrix elements.
int Sin2Theta13Index
Index of in the parameter list.
Definition: OscProcessor.h:96
std::string Sin2Theta23Name
Name of the parameter representing .
Definition: OscProcessor.h:89
std::array< std::array< TComplex, 3 >, 3 > CalculatePMNSElements(const double s2th13, const double s2th23, const double s2th12, const double dcp) const
MP: Calculate PMNS matrix elements.
void Get1DReactorConstraintInfo(std::pair< double, double > &Sin13_NewPrior, bool &DoReweight) const
Extract 1D reactor constraint information from an MCMC file.
void MakeJarlskogPlot(const std::unique_ptr< TH1D > &jarl, const std::unique_ptr< TH1D > &jarl_flatsindcp, const std::unique_ptr< TH1D > &jarl_NH, const std::unique_ptr< TH1D > &jarl_NH_flatsindcp, const std::unique_ptr< TH1D > &jarl_IH, const std::unique_ptr< TH1D > &jarl_IH_flatsindcp)
Perform Jarlskog Plotting.
int Sin2Theta23Index
Index of in the parameter list.
Definition: OscProcessor.h:100
virtual ~OscProcessor()
Destroys the OscProcessor object.
std::string DeltaM2_23Name
Name of the parameter representing (mass-squared difference).
Definition: OscProcessor.h:93
void LoadAdditionalInfo() final
Read the Osc cov file and get the input central values and errors Here we allow Jarlskog Shenanigans.
bool OscEnabled
Will plot Jarlskog Invariant using information in the chain.
Definition: OscProcessor.h:82
void MakePiePlot()
Make fancy Pie plot for delta CP.
void PerformJarlskogAnalysis()
Perform Several Jarlskog Plotting.
void EstimateDataTransferRate(TChain *chain, const Long64_t entry)
KS: Check what CPU you are using.
Definition: Monitor.cpp:212
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:229
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.
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:53
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