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