MaCh3  2.4.2
Reference Guide
ReweightMCMC.cpp
Go to the documentation of this file.
1 //MaCh3 includes
2 #include "Manager/Manager.h"
4 
6 // ROOT includes
7 #include "TFile.h"
8 #include "TTree.h"
9 #include "TChain.h"
10 #include "TMath.h"
11 #include "TGraph2D.h"
12 #include "TGraph.h"
13 
14 // C++ includes
15 #include <memory>
16 #include <vector>
17 #include <string>
18 #include <cmath>
19 #include <fstream>
20 #include <map>
22 
29 
32  std::string key; // The YAML key for this reweight
33  std::string name;
34  std::string type; // "Gaussian", "TGraph2D"
35  int dimension; // 1 or 2
36  std::vector<std::string> paramNames;
37  std::vector<std::vector<double>> priorValues; // Changed to handle multiple [mean, sigma] pairs
38  std::string weightBranchName;
39  bool enabled;
40 
41  // For TGraph 1D or 2D
42  std::string fileName;
43  std::string graphName;
44 
45  // For TGraph1D
46  std::unique_ptr<TGraph> graph_1D;
47 
48  // For TGraph2D
49  std::string hierarchyType; // "NO", "IO", or "auto"
50  std::unique_ptr<TGraph2D> graph_NO;
51  std::unique_ptr<TGraph2D> graph_IO;
52 };
53 
59 void ReweightMCMC(const std::string& inputFile, const std::string& configFile);
60 
62 
64 double Graph_interpolateNO(TGraph2D* graph, double theta13, double dm32);
65 
67 double Graph_interpolateIO(TGraph2D* graph, double theta13, double dm32);
68 
70 double Graph_interpolate1D(TGraph* graph, double theta13);
71 
73 bool GetParameterInfo(MCMCProcessor* processor, const std::string& paramName,
74  double& mean, double& sigma);
75 
77 void LoadReweightingSettings(std::vector<ReweightConfig>& reweightConfigs, const YAML::Node& reweight_settings);
78 
80 int main(int argc, char *argv[])
81 {
83 
84  if (argc != 3) {
85  MACH3LOG_ERROR("How to use: {} <config.yaml> <input_file.root>", argv[0]);
86  throw MaCh3Exception(__FILE__, __LINE__);
87  }
88 
89  std::string configFile = argv[1];
90  std::string inputFile = argv[2];
91 
92  ReweightMCMC(configFile, inputFile);
93 
94  return 0;
95 }
96 
97 void LoadReweightingSettings(std::vector<ReweightConfig>& reweightConfigs, const YAML::Node& reweight_settings) {
98  // iterate through the keys in the reweighting yaml creating and storing the ReweightConfig as we go
99  for (const auto& reweight : reweight_settings) {
100  const std::string& reweightKey = reweight.first.as<std::string>();
101  const YAML::Node& reweightConfigNode = reweight.second;
102 
103  // Check if this particular reweight is enabled !!! Currently only support one reweight at a time so this defaults to enabled
104  if (!GetFromManager<bool>(reweightConfigNode["Enabled"], true)) {
105  MACH3LOG_INFO("Skipping disabled reweight: {}", reweightKey);
106  continue;
107  }
108 
109  ReweightConfig reweightConfig;
110  reweightConfig.key = reweightKey;
111  reweightConfig.name = GetFromManager<std::string>(reweightConfigNode["ReweightName"], reweightKey);
112  reweightConfig.type = GetFromManager<std::string>(reweightConfigNode["ReweightType"], "Gaussian");
113  reweightConfig.dimension = GetFromManager<int>(reweightConfigNode["ReweightDim"], 1);
114  // reweightConfig.weightBranchName = "Weight_" + reweightKey; // for now all weights will be stored in branches called Weight until multi weight support
115  reweightConfig.weightBranchName = "Weight";
116  reweightConfig.enabled = true;
117 
118  // Handle different reweight types as they fill different members
119  if (reweightConfig.dimension == 1) {
120  if (reweightConfig.type == "Gaussian") {
121  // For Gaussian reweights, we need the parameter name(s) and prior values (mean, sigma pairs)
122  auto paramNames = GetFromManager<std::vector<std::string>>(reweightConfigNode["ReweightVar"], {});
123 
124  // Get prior values - handle both single [mean, sigma] pair and list of pairs for safety
125  auto priorNode = reweightConfigNode["ReweightPrior"];
126  std::vector<std::vector<double>> allPriorValues;
127 
128  if (priorNode.IsSequence() && priorNode.size() > 0) {
129  // Check if first element is a number (single [mean, sigma] pair) or sequence (list of pairs)
130  if (priorNode[0].IsScalar()) {
131  // Single [mean, sigma] pair - convert to list format
132  auto priorValues = GetFromManager<std::vector<double>>(priorNode, {});
133  if (priorValues.size() == 2) {
134  allPriorValues.push_back(priorValues);
135  }
136  } else {
137  // List of [mean, sigma] pairs
138  for (const auto& priorPair : priorNode) {
139  auto priorValues = GetFromManager<std::vector<double>>(priorPair, {});
140  if (priorValues.size() == 2) {
141  allPriorValues.push_back(priorValues);
142  }
143  }
144  }
145  }
146 
147  reweightConfig.paramNames = paramNames;
148  reweightConfig.priorValues = allPriorValues;
149 
150  if (paramNames.empty() || allPriorValues.empty() || paramNames.size() != allPriorValues.size()) {
151  MACH3LOG_ERROR("Invalid Gaussian reweight configuration for {}: {} parameters, {} prior pairs",
152  reweightKey, paramNames.size(), allPriorValues.size());
153  continue;
154  }
155  } else if (reweightConfig.type == "TGraph") {
156  // For TGraph reweights, we need the parameter name and the TGraph file and name
157  auto paramNames = GetFromManager<std::vector<std::string>>(reweightConfigNode["ReweightVar"], {});
158  std::string fileName = GetFromManager<std::string>(reweightConfigNode["ReweightPrior"]["file"], "");
159  std::string graphName = GetFromManager<std::string>(reweightConfigNode["ReweightPrior"]["graph_name"], "");
160  reweightConfig.paramNames = paramNames;
161  reweightConfig.fileName = fileName;
162  reweightConfig.graphName = graphName;
163 
164  if (paramNames.empty() || paramNames.size() != 1 || fileName.empty() || graphName.empty()) {
165  MACH3LOG_ERROR("Invalid TGraph reweight configuration for {}", reweightKey);
166  continue;
167  }
168 
169  // Load the 1D graph
170  MACH3LOG_INFO("Loading 1D constraint from file: {} (graph: {})", reweightConfig.fileName, reweightConfig.graphName);
171  auto constraintFile = std::unique_ptr<TFile>(TFile::Open(reweightConfig.fileName.c_str(), "READ"));
172  if (!constraintFile || constraintFile->IsZombie()) {
173  MACH3LOG_ERROR("Failed to open constraint file: {}", reweightConfig.fileName);
174  continue;
175  }
176 
177  std::unique_ptr<TGraph> graph(constraintFile->Get<TGraph>(reweightConfig.graphName.c_str()));
178  if (graph) {
179  // Create a completely independent copy
180  auto cloned_graph = static_cast<TGraph*>(graph->Clone());
181  cloned_graph->SetBit(kCanDelete, true); // Allow ROOT to delete it when we're done
182  reweightConfig.graph_1D = std::unique_ptr<TGraph>(cloned_graph);
183  MACH3LOG_INFO("Loaded 1D graph: {}", reweightConfig.graphName);
184  } else {
185  MACH3LOG_ERROR("Failed to load graph: {}", reweightConfig.graphName);
186  continue;
187  }
188  } else {
189  MACH3LOG_ERROR("Unknown 1D reweight type: {} for {}", reweightConfig.type, reweightKey);
190  throw MaCh3Exception(__FILE__, __LINE__);
191  }
192 
193  } else if (reweightConfig.dimension == 2) {
194  auto paramNames = GetFromManager<std::vector<std::string>>(reweightConfigNode["ReweightVar"], {});
195 
196  // 2D reweights need 2 parameter names
197  if (paramNames.size() != 2) {
198  MACH3LOG_ERROR("2D reweighting requires exactly 2 parameter names for {}", reweightKey);
199  continue;
200  }
201 
202  reweightConfig.paramNames = paramNames;
203 
204  if (reweightConfig.type == "TGraph2D") {
205  auto priorConfig = reweightConfigNode["ReweightPrior"];
206  reweightConfig.fileName = GetFromManager<std::string>(priorConfig["file"], "");
207  reweightConfig.graphName = GetFromManager<std::string>(priorConfig["graph_name"], "");
208  reweightConfig.hierarchyType = GetFromManager<std::string>(priorConfig["hierarchy"], "auto");
209 
210  if (reweightConfig.fileName.empty() || reweightConfig.graphName.empty()) {
211  MACH3LOG_ERROR("Invalid TGraph2D configuration for {}", reweightKey);
212  continue;
213  }
214 
215  // Load the 2D graphs
216  MACH3LOG_INFO("Loading 2D constraint from file: {} (graph: {})", reweightConfig.fileName, reweightConfig.graphName);
217  auto constraintFile = std::unique_ptr<TFile>(TFile::Open(reweightConfig.fileName.c_str(), "READ"));
218  if (!constraintFile || constraintFile->IsZombie()) {
219  MACH3LOG_ERROR("Failed to open constraint file: {}", reweightConfig.fileName);
220  continue;
221  }
222 
223  // Load both NO and IO graphs if hierarchy is auto
224  if (reweightConfig.hierarchyType == "auto" || reweightConfig.hierarchyType == "NO") {
225  std::string graphName_NO = reweightConfig.graphName + "_NO";
226  MACH3LOG_INFO("Loading NO graph: {}", graphName_NO);
227 
228  std::unique_ptr<TGraph2D> graph_NO(constraintFile->Get<TGraph2D>(graphName_NO.c_str()));
229  if (graph_NO) {
230  // Create a completely independent copy
231  auto cloned_graph = static_cast<TGraph2D*>(graph_NO->Clone());
232  cloned_graph->SetDirectory(nullptr); // Detach from file
233  cloned_graph->SetBit(kCanDelete, true); // Allow ROOT to delete it when we're done
234  reweightConfig.graph_NO = std::unique_ptr<TGraph2D>(cloned_graph);
235  MACH3LOG_INFO("Loaded NO graph: {}", graphName_NO);
236  } else {
237  MACH3LOG_ERROR("Failed to load NO graph: {}", graphName_NO);
238  }
239  }
240 
241  if (reweightConfig.hierarchyType == "auto" || reweightConfig.hierarchyType == "IO") {
242  std::string graphName_IO = reweightConfig.graphName + "_IO";
243  MACH3LOG_INFO("Loading IO graph: {}", graphName_IO);
244  std::unique_ptr<TGraph2D> graph_IO(constraintFile->Get<TGraph2D>(graphName_IO.c_str()));
245  if (graph_IO) {
246  // Create a completely independent copy
247  auto cloned_graph = static_cast<TGraph2D*>(graph_IO->Clone());
248  cloned_graph->SetDirectory(nullptr); // Detach from file
249  cloned_graph->SetBit(kCanDelete, true); // Allow ROOT to delete it when we're done
250  reweightConfig.graph_IO = std::unique_ptr<TGraph2D>(cloned_graph);
251  MACH3LOG_INFO("Loaded IO graph: {}", graphName_IO);
252  } else {
253  MACH3LOG_ERROR("Failed to load IO graph: {}", graphName_IO);
254  }
255  }
256 
257  constraintFile->Close();
258  } else {
259  MACH3LOG_ERROR("Unknown 2D reweight type: {} for {}", reweightConfig.type, reweightKey);
260  continue;
261  }
262  } else {
263  MACH3LOG_ERROR("Unsupported reweight dimension: {} for {}", reweightConfig.dimension, reweightKey);
264  continue;
265  }
266 
267  reweightConfigs.push_back(std::move(reweightConfig));
268  MACH3LOG_INFO("Added reweight configuration: {} ({}D, type: {})", reweightConfigs.back().name, reweightConfigs.back().dimension, reweightConfigs.back().type);
269  }
270 
271  if (reweightConfigs.empty()) {
272  MACH3LOG_ERROR("No valid reweight configurations found in config file");
273  throw MaCh3Exception(__FILE__, __LINE__);
274  } else if (reweightConfigs.size() > 1) { // check number of ReweightConfigs, currently maximum supported is 1 due to structure of ProcessMCMC
275  MACH3LOG_ERROR("Currently only one reweight configuration is supported at a time, found {}", reweight_settings.size());
276  throw MaCh3Exception(__FILE__, __LINE__);
277  }
278 }
279 
280 void ReweightMCMC(const std::string& configFile, const std::string& inputFile)
281 {
282  MACH3LOG_INFO("File for reweighting: {} with config {}", inputFile, configFile);
283  // Load configuration
284  YAML::Node reweight_yaml = M3OpenConfig(configFile);
285  YAML::Node reweight_settings = reweight_yaml["ReweightMCMC"];
286 
287  // Parse all reweight configurations first
288  std::vector<ReweightConfig> reweightConfigs;
289 
290  LoadReweightingSettings(reweightConfigs, reweight_settings);
291 
292  // Create MCMCProcessor to get parameter information
293  auto processor = std::make_unique<MCMCProcessor>(inputFile);
294  processor->Initialise();
295 
296  // Validate that all required parameters exist in the chain
298  for (const auto& rwConfig : reweightConfigs) {
299  for (const auto& paramName : rwConfig.paramNames) {
300  int paramIndex = processor->GetParamIndexFromName(paramName);
301  if (paramIndex == M3::_BAD_INT_) {
302  MACH3LOG_ERROR("Parameter {} not found in MCMC chain", paramName);
303  throw MaCh3Exception(__FILE__, __LINE__);
304  }
305  MACH3LOG_INFO("Parameter {} found in chain", paramName);
306  }
307  }
308 
310  // Get the settings for the MCMC
311  auto TempFile = std::unique_ptr<TFile>(TFile::Open(inputFile.c_str(), "READ"));
312  if (!TempFile || TempFile->IsZombie()) {
313  MACH3LOG_ERROR("Cannot open MCMC file: {}", inputFile);
314  throw MaCh3Exception(__FILE__ , __LINE__ );
315  }
316  std::unique_ptr<TMacro> Config(TempFile->Get<TMacro>("MaCh3_Config"));
317  if (!Config) {
318  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", inputFile.c_str());
319  TempFile->ls();
320  throw MaCh3Exception(__FILE__ , __LINE__ );
321  }
322  MACH3LOG_INFO("Loading YAML config from MCMC chain");
323  YAML::Node Settings = TMacroToYAML(*Config);
324  bool asimovfit = GetFromManager<bool>(Settings["General"]["Asimov"], false);
325  if (asimovfit) {
326  MACH3LOG_WARN("MCMC chain was produced from an Asimov fit");
327  MACH3LOG_WARN("ReweightMCMC does not currently handle Asimov shifting, results may be incorrect!");
328  } else {
329  MACH3LOG_INFO("Not an Asimov fit, proceeding with reweighting");
330  }
331 
332  // Open input file and get tree
333  auto inFile = std::unique_ptr<TFile>(TFile::Open(inputFile.c_str(), "READ"));
334  if (!inFile || inFile->IsZombie()) {
335  MACH3LOG_ERROR("Cannot open input file: {}", inputFile);
336  throw MaCh3Exception(__FILE__, __LINE__);
337  }
338 
339  std::unique_ptr<TTree> inTree(inFile->Get<TTree>("posteriors"));
340  if (!inTree) {
341  MACH3LOG_ERROR("Cannot find 'posteriors' tree in input file");
342  throw MaCh3Exception(__FILE__, __LINE__);
343  }
344 
345  // Create output file
346  std::string configString = configFile.substr(configFile.find_last_of('/') + 1, configFile.find_last_of('.') - configFile.find_last_of('/') - 1);
347  std::string outputFile = inputFile.substr(0, inputFile.find_last_of('.')) + "_reweighted_" + configString + ".root";
348  auto outFile = std::unique_ptr<TFile>(TFile::Open(outputFile.c_str(), "RECREATE"));
349  if (!outFile || outFile->IsZombie()) {
350  MACH3LOG_ERROR("Cannot create output file: {}", outputFile);
351  throw MaCh3Exception(__FILE__, __LINE__);
352  }
353 
354  MACH3LOG_INFO("Output file will be: {}", outputFile);
355 
356  // Copy all the remaining objects into the out file (i.e. all but posteriors tree)
357  TIter next(inFile->GetListOfKeys());
358  while (TKey* key = dynamic_cast<TKey*>(next())) {
359  inFile->cd();
360  std::unique_ptr<TObject> obj(key->ReadObj());
361  if (obj->IsA()->InheritsFrom(TDirectory::Class())) {
362  // It's a folder, create and copy its contents
363  TDirectory* srcDir = static_cast<TDirectory*>(obj.get());
364  TDirectory* destDir = outFile->mkdir(srcDir->GetName());
365  TIter nextSubKey(srcDir->GetListOfKeys());
366  while (TKey* subKey = dynamic_cast<TKey*>(nextSubKey())) {
367  srcDir->cd();
368  std::unique_ptr<TObject> subObj(subKey->ReadObj());
369  destDir->cd();
370  subObj->Write();
371  }
372  } else if (std::string(key->GetName()) != "posteriors") {
373  // Regular object, skip "posteriors" tree
374  outFile->cd();
375  obj->Write();
376  }
377  }
378 
379  // Clone the tree structure
380  outFile->cd();
381  std::unique_ptr<TTree> outTree(inTree->CloneTree(0));
382 
383  // Set up parameter reading
384  std::map<std::string, double> paramValues;
385  for (const auto& rwConfig : reweightConfigs) {
386  for (const auto& paramName : rwConfig.paramNames) {
387  if (paramValues.find(paramName) == paramValues.end()) {
388  paramValues[paramName] = 0.0;
389  inTree->SetBranchAddress(paramName.c_str(), &paramValues[paramName]);
390  }
391  }
392  }
393 
394  // Add weight branches
395  std::map<std::string, double> weights;
396  std::map<std::string, TBranch*> weightBranches;
397 
398  for (const auto& rwConfig : reweightConfigs) {
399  weights[rwConfig.weightBranchName] = 1.0;
400  weightBranches[rwConfig.weightBranchName] = outTree->Branch(
401  rwConfig.weightBranchName.c_str(),
402  &weights[rwConfig.weightBranchName],
403  (rwConfig.weightBranchName + "/D").c_str()
404  );
405  MACH3LOG_INFO("Added weight branch: {}", rwConfig.weightBranchName);
406  }
407 
408  bool processMCMCreweighted=false;
409 
410  // If a given reweight is 1D Gaussian we can just let MCMCProcessor method do the reweight
411  for (const auto& rwConfig : reweightConfigs){
412  if (rwConfig.dimension == 1 && rwConfig.type == "Gaussian"){
413  // Extract the parameter names and convert priorValues to the format processor needs
414  const std::vector<std::string>& paramNames = rwConfig.paramNames;
415  std::vector<double> priorCentral;
416  std::vector<double> priorSigma;
417 
418  // Extract means and sigmas from the prior pairs
419  for (const auto& priorPair : rwConfig.priorValues) {
420  priorCentral.push_back(priorPair[0]); // mean
421  priorSigma.push_back(priorPair[1]); // sigma
422  }
423 
424  processor->ReweightPrior(paramNames, priorCentral, priorSigma);
425  MACH3LOG_INFO("Applied Gaussian reweighting for {} parameters", paramNames.size());
426  for (size_t i = 0; i < paramNames.size(); ++i) {
427  MACH3LOG_INFO(" {}: mean={}, sigma={}", paramNames[i], priorCentral[i], priorSigma[i]);
428  }
429  processMCMCreweighted=true;
430  }
431  }
432  // For 2D reweight and non-gaussian (ie TGraph) 1D reweight we need to do it ourselves
433  // Process all entries
434  Long64_t nEntries = inTree->GetEntries();
435  MACH3LOG_INFO("Processing {} entries", nEntries);
436 
437 
439 
440  if (processMCMCreweighted) {
441  MACH3LOG_INFO("MCMCProcessor has reweighted, skipping duplicate reweighting");
442  } else {
443  for (Long64_t i = 0; i < nEntries; ++i) {
444  if(i % (nEntries/20) == 0) MaCh3Utils::PrintProgressBar(i, nEntries);
445 
446  inTree->GetEntry(i);
447 
448  // Calculate weights for all configurations
449  for (const auto& rwConfig : reweightConfigs) {
450  double weight = 1.0;
451 
452  if (rwConfig.dimension == 1 && rwConfig.type != "Gaussian") {
453  if (rwConfig.type == "TGraph") {
454  double paramValue = paramValues[rwConfig.paramNames[0]];
455  weight = Graph_interpolate1D(rwConfig.graph_1D.get(), paramValue);
456  } else {
457  MACH3LOG_ERROR("Unsupported 1D reweight type: {} for {}", rwConfig.type, rwConfig.key);
458  }
459  } else if (rwConfig.dimension == 2) {
460  if (rwConfig.type == "TGraph2D") {
461  double dm32 = paramValues[rwConfig.paramNames[0]];
462  double theta13 = paramValues[rwConfig.paramNames[1]];
463  if (dm32 > 0) {
464  // Normal Ordering
465  if (rwConfig.graph_NO) {
466  weight = Graph_interpolateNO(rwConfig.graph_NO.get(), theta13, dm32);
467  } else {
468  MACH3LOG_ERROR("NO graph not available for {}", rwConfig.key);
469  weight = 0.0;
470  }
471  } else {
472  // Inverted Ordering
473  if (rwConfig.graph_IO) {
474  weight = Graph_interpolateIO(rwConfig.graph_IO.get(), theta13, dm32);
475  } else {
476  MACH3LOG_ERROR("IO graph not available for {}", rwConfig.key);
477  weight = 0.0;
478  }
479  }
480  }
481  }
482  weights[rwConfig.weightBranchName] = weight;
483  }
484  // Fill the output tree
485  outTree->Fill();
486  } // end loop over entries
487  }
488 
489  // Write and close
490  outFile->cd();
491  outTree->Write();
492 
493  // once we have finished the reweight save its configuration (reweightConfigNode) to the root file as a macro
494 
495  TMacro reweightMacro;
496  reweightMacro.SetName("Reweight_Config");
497  reweightMacro.SetTitle("ReweightMCMC configuration");
498  std::stringstream ss;
499  ss << reweight_settings;
500  reweightMacro.AddLine(ss.str().c_str());
501  reweightMacro.Write();
502 
503  if (processMCMCreweighted){
504  MACH3LOG_INFO("MCMCProcessor reweighting applied, Final reweighted file is: {}_reweighted.root", inputFile.substr(0, inputFile.find_last_of('.')));
505  // delete the file we just created since MCMCProcessor already did the reweighting and saved it to a file
506  outTree.reset(); // Release TTree before closing TFile
507  outFile->Close();
508  outFile.reset();
509 
510  if (std::remove(outputFile.c_str()) != 0) {
511  MACH3LOG_ERROR("Error deleting temporary file: {}", outputFile);
512  } else {
513  MACH3LOG_INFO("Deleted temporary file: {}", outputFile);
514  }
515  } else {
516  MACH3LOG_INFO("Reweighting completed successfully!");
517  MACH3LOG_INFO("Final reweighted file is: {}", outputFile);
518  }
519 }
520 
521 double Graph_interpolateNO(TGraph2D* graph, double theta13, double dm32)
522 {
523  if (!graph) {
524  MACH3LOG_ERROR("Graph pointer is null");
525  throw MaCh3Exception(__FILE__, __LINE__);
526  }
527 
528  double xmax = graph->GetXmax();
529  double xmin = graph->GetXmin();
530  double ymin = graph->GetYmin();
531  double ymax = graph->GetYmax();
532 
533  double chiSquared, prior;
534 
535  if (theta13 < xmax && theta13 > xmin && dm32 < ymax && dm32 > ymin) {
536  chiSquared = graph->Interpolate(theta13, dm32);
537  prior = std::exp(-0.5 * chiSquared);
538  } else {
539  prior = 0.0;
540  }
541 
542  return prior;
543 }
544 
545 double Graph_interpolateIO(TGraph2D* graph, double theta13, double dm32)
546 {
547  if (!graph) {
548  MACH3LOG_ERROR("Graph pointer is null");
549  throw MaCh3Exception(__FILE__, __LINE__);
550  }
551 
552  double xmax = graph->GetXmax();
553  double xmin = graph->GetXmin();
554  double ymax = graph->GetYmax();
555  double ymin = graph->GetYmin();
556 
557  // The dm32 value is positive for in the TGraph2D so we should compare the abs value of the -delM32 values to get the chisq
558  double mod_dm32 = std::abs(dm32);
559  double chiSquared, prior;
560 
561  if (theta13 < xmax && theta13 > xmin && mod_dm32 < ymax && mod_dm32 > ymin) {
562  chiSquared = graph->Interpolate(theta13, mod_dm32);
563  prior = std::exp(-0.5 * chiSquared);
564  } else {
565  prior = 0.0;
566  }
567 
568  return prior;
569 }
570 
571 double Graph_interpolate1D(TGraph* graph, double theta13)
572 {
574  if (!graph) {
575  MACH3LOG_ERROR("Graph pointer is null");
576  throw MaCh3Exception(__FILE__, __LINE__);
577  }
578 
579  double xmax = -999999999;
580  double xmin = 999999999;
581 
582  for (int i = 0; i < graph->GetN(); i++) {
583  double x = graph->GetX()[i];
584  if (x > xmax) xmax = x;
585  if (x < xmin) xmin = x;
586  }
587 
588  double chiSquared, prior;
589 
590  if (theta13 < xmax && theta13 > xmin) {
591  chiSquared = graph->Eval(theta13);
592  prior = std::exp(-0.5 * chiSquared);
593  } else {
594  prior = 0.0;
595  }
596 
597  return prior;
598 }
599 
600 bool GetParameterInfo(MCMCProcessor* processor, const std::string& paramName,
601  double& mean, double& sigma)
602 {
603  // Try to find the parameter index
604  int paramIndex = processor->GetParamIndexFromName(paramName);
605 
606  if (paramIndex == M3::_BAD_INT_) { // This indicate parameter not found
607  return false;
608  }
609 
610  // Get parameter information
611  TString title;
612  processor->GetNthParameter(paramIndex, mean, sigma, title);
613 
614  return true;
615 }
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
Definition: Core.h:126
#define _MaCh3_Safe_Include_End_
KS: Restore warning checking after including external headers.
Definition: Core.h:140
#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:61
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
int main(int argc, char *argv[])
Main function.
double Graph_interpolateNO(TGraph2D *graph, double theta13, double dm32)
Function to interpolate 2D graph for Normal Ordering.
void LoadReweightingSettings(std::vector< ReweightConfig > &reweightConfigs, const YAML::Node &reweight_settings)
Load reweighting setting like 1D or 2D from YAML config.
bool GetParameterInfo(MCMCProcessor *processor, const std::string &paramName, double &mean, double &sigma)
Get parameter information from MCMCProcessor.
double Graph_interpolateIO(TGraph2D *graph, double theta13, double dm32)
Function to interpolate 2D graph for Inverted Ordering
double Graph_interpolate1D(TGraph *graph, double theta13)
Function to interpolate 1D graph.
void ReweightMCMC(const std::string &inputFile, const std::string &configFile)
Main executable responsible for reweighting MCMC chains.
YAML::Node TMacroToYAML(const TMacro &macro)
KS: Convert a ROOT TMacro object to a YAML node.
Definition: YamlHelper.h:152
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:589
Class responsible for processing MCMC chains, performing diagnostics, generating plots,...
Definition: MCMCProcessor.h:58
void GetNthParameter(const int param, double &Prior, double &PriorError, TString &Title) const
Get properties of parameter by passing it number.
int GetParamIndexFromName(const std::string &Name) const
Get parameter number based on name.
Custom exception class used throughout MaCh3.
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
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:228
Structure to hold reweight configuration.
std::unique_ptr< TGraph2D > graph_NO
std::string key
std::string weightBranchName
std::string fileName
std::string graphName
std::unique_ptr< TGraph > graph_1D
std::string type
std::vector< std::string > paramNames
std::string name
std::vector< std::vector< double > > priorValues
std::string hierarchyType
std::unique_ptr< TGraph2D > graph_IO