76 double xmax = graph->GetXmax();
77 double xmin = graph->GetXmin();
78 double ymin = graph->GetYmin();
79 double ymax = graph->GetYmax();
81 double chiSquared, prior;
83 if (theta13 < xmax && theta13 > xmin && dm32 < ymax && dm32 > ymin) {
84 chiSquared = graph->Interpolate(theta13, dm32);
85 prior = std::exp(-0.5 * chiSquared);
101 double xmax = graph->GetXmax();
102 double xmin = graph->GetXmin();
103 double ymax = graph->GetYmax();
104 double ymin = graph->GetYmin();
107 double mod_dm32 = std::abs(dm32);
108 double chiSquared, prior;
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);
129 double xmax = -999999999;
130 double xmin = 999999999;
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;
138 double chiSquared, prior;
140 if (theta13 < xmax && theta13 > xmin) {
141 chiSquared = graph->Eval(theta13);
142 prior = std::exp(-0.5 * chiSquared);
152 double& mean,
double& sigma,
bool&
isFlat)
172 for (
const auto& reweight : reweight_settings) {
173 const std::string& reweightKey = reweight.first.as<std::string>();
174 const YAML::Node& reweightConfigNode = reweight.second;
177 if (!GetFromManager<bool>(reweightConfigNode[
"Enabled"],
true, __FILE__ , __LINE__)) {
178 MACH3LOG_INFO(
"Skipping disabled reweight: {}", reweightKey);
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__);
191 auto paramNames = Get<std::vector<std::string>>(reweightConfigNode[
"ReweightVar"], __FILE__ , __LINE__);
194 reweightConfig.
flatPrior.resize(paramNames.size());
198 if (ReweightType ==
"Gaussian") {
202 auto priorNode = reweightConfigNode[
"ReweightPrior"];
203 std::vector<std::vector<double>> allPriorValues;
205 if (priorNode.IsSequence() && priorNode.size() > 0) {
207 if (priorNode[0].IsScalar()) {
209 auto newPriorValues = Get<std::vector<double>>(priorNode, __FILE__ , __LINE__);
210 if (newPriorValues.size() == 2) {
211 allPriorValues.push_back(newPriorValues);
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);
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());
231 }
else if (ReweightType ==
"TGraph") {
234 auto fileName = Get<std::string>(reweightConfigNode[
"ReweightPrior"][
"file"], __FILE__ , __LINE__);
235 auto graphName = Get<std::string>(reweightConfigNode[
"ReweightPrior"][
"graph_name"], __FILE__ , __LINE__);
239 if (paramNames.empty() || paramNames.size() != 1 || fileName.empty() || graphName.empty()) {
240 MACH3LOG_ERROR(
"Invalid TGraph reweight configuration for {}", reweightKey);
246 auto constraintFile = std::unique_ptr<TFile>(
TFile::Open(reweightConfig.
fileName.c_str(),
"READ"));
247 if (!constraintFile || constraintFile->IsZombie()) {
252 std::unique_ptr<TGraph> graph(constraintFile->Get<TGraph>(reweightConfig.
graphName.c_str()));
255 auto cloned_graph =
static_cast<TGraph*
>(graph->Clone());
256 cloned_graph->SetBit(kCanDelete,
true);
257 reweightConfig.
graph_1D = std::unique_ptr<TGraph>(cloned_graph);
264 MACH3LOG_ERROR(
"Unknown 1D reweight type: {} for {}", ReweightType, reweightKey);
267 }
else if (reweightConfig.
dimension == 2) {
269 if (paramNames.size() != 2) {
270 MACH3LOG_ERROR(
"2D reweighting requires exactly 2 parameter names for {}", reweightKey);
274 if (ReweightType ==
"TGraph2D") {
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__);
282 MACH3LOG_ERROR(
"Invalid TGraph2D configuration for {}", reweightKey);
288 auto constraintFile = std::unique_ptr<TFile>(
TFile::Open(reweightConfig.
fileName.c_str(),
"READ"));
289 if (!constraintFile || constraintFile->IsZombie()) {
296 std::string graphName_NO = reweightConfig.
graphName +
"_NO";
299 std::unique_ptr<TGraph2D> graph_NO(constraintFile->Get<TGraph2D>(graphName_NO.c_str()));
302 auto cloned_graph =
static_cast<TGraph2D*
>(graph_NO->Clone());
303 cloned_graph->SetDirectory(
nullptr);
304 cloned_graph->SetBit(kCanDelete,
true);
305 reweightConfig.
graph_NO = std::unique_ptr<TGraph2D>(cloned_graph);
313 std::string graphName_IO = reweightConfig.
graphName +
"_IO";
315 std::unique_ptr<TGraph2D> graph_IO(constraintFile->Get<TGraph2D>(graphName_IO.c_str()));
318 auto cloned_graph =
static_cast<TGraph2D*
>(graph_IO->Clone());
319 cloned_graph->SetDirectory(
nullptr);
320 cloned_graph->SetBit(kCanDelete,
true);
321 reweightConfig.
graph_IO = std::unique_ptr<TGraph2D>(cloned_graph);
328 constraintFile->Close();
330 MACH3LOG_ERROR(
"Unknown 2D reweight type: {} for {}", ReweightType, reweightKey);
338 reweightConfigs.push_back(std::move(reweightConfig));
339 MACH3LOG_INFO(
"Added reweight configuration: {} ({}D, type: {})", reweightConfigs.back().name, reweightConfigs.back().dimension, ReweightType);
342 if (reweightConfigs.empty()) {
343 MACH3LOG_ERROR(
"No valid reweight configurations found in config file");
350 const std::map<std::string, double>& paramValues) {
356 for (
unsigned int j = 0; j < paramNames.size(); ++j)
361 double NewCentral = newPriorPair[0];
362 double NewError = newPriorPair[1];
364 double new_chi = (paramValues.at(name) - NewCentral)/NewError;
365 double new_prior = std::exp(-0.5 * new_chi * new_chi);
368 double old_prior = -1;
373 double OldCentral = newPriorPair[0];
374 double OldError = newPriorPair[1];
376 old_chi = (paramValues.at(name) - OldCentral)/OldError;
377 old_prior = std::exp(-0.5 * old_chi * old_chi);
379 weight *= new_prior/old_prior;
382 double paramValue = paramValues.at(rwConfig.
paramNames.at(0));
390 const std::map<std::string, double>& paramValues) {
393 double dm32 = paramValues.at(rwConfig.
paramNames.at(0));
394 double theta13 = paramValues.at(rwConfig.
paramNames.at(1));
422 void ReweightMCMC(
const std::string& configFile,
const std::string& inputFile)
424 MACH3LOG_INFO(
"File for reweighting: {} with config {}", inputFile, configFile);
427 YAML::Node reweight_settings = reweight_yaml[
"ReweightMCMC"];
430 std::vector<ReweightConfig> reweightConfigs;
435 auto processor = std::make_unique<MCMCProcessor>(inputFile);
436 processor->Initialise();
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);
445 MACH3LOG_ERROR(
"Parameter {} not found in MCMC chain", paramName);
454 rwConfig.oldPriorValues[i] = {mean, sigma};
455 rwConfig.flatPrior[i] =
isFlat;
461 auto TempFile = std::unique_ptr<TFile>(
TFile::Open(inputFile.c_str(),
"READ"));
462 if (!TempFile || TempFile->IsZombie()) {
466 std::unique_ptr<TMacro> Config(TempFile->Get<TMacro>(
"MaCh3_Config"));
468 MACH3LOG_ERROR(
"Didn't find MaCh3_Config tree in MCMC file! {}", inputFile.c_str());
474 bool asimovfit = GetFromManager<bool>(Settings[
"General"][
"Asimov"],
false, __FILE__ , __LINE__);
477 MACH3LOG_WARN(
"ReweightMCMC does not currently handle Asimov shifting, results may be incorrect!");
479 MACH3LOG_INFO(
"Not an Asimov fit, proceeding with reweighting");
483 auto inFile = std::unique_ptr<TFile>(
TFile::Open(inputFile.c_str(),
"READ"));
484 if (!inFile || inFile->IsZombie()) {
489 std::unique_ptr<TTree> inTree(inFile->Get<TTree>(
"posteriors"));
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()) {
507 TIter next(inFile->GetListOfKeys());
508 while (TKey* key =
dynamic_cast<TKey*
>(next())) {
510 std::unique_ptr<TObject> obj(key->ReadObj());
511 if (obj->IsA()->InheritsFrom(TDirectory::Class())) {
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())) {
518 std::unique_ptr<TObject> subObj(subKey->ReadObj());
522 }
else if (std::string(key->GetName()) !=
"posteriors") {
531 std::unique_ptr<TTree> outTree(inTree->CloneTree(0));
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;
540 auto idx = processor->GetParamIndexFromName(paramName);
541 auto BranchName = processor->GetBranchNames()[idx];
542 inTree->SetBranchAddress(BranchName, ¶mValues[paramName]);
548 std::map<std::string, double> weights;
549 std::map<std::string, TBranch*> weightBranches;
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);
562 Long64_t nEntries = inTree->GetEntries();
566 for (Long64_t i = 0; i < nEntries; ++i) {
572 for (
const auto& rwConfig : reweightConfigs) {
574 if (rwConfig.dimension == 1) {
576 }
else if (rwConfig.dimension == 2) {
579 weights[rwConfig.weightBranchName] = weight;
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();
603 int main(
int argc,
char *argv[])
608 MACH3LOG_ERROR(
"How to use: {} <config.yaml> <input_file.root>", argv[0]);
612 std::string configFile = argv[1];
613 std::string inputFile = argv[2];
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
#define _MaCh3_Safe_Include_End_
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
double Get1DWeight(const ReweightConfig &rwConfig, const std::map< std::string, double > ¶mValues)
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 > ¶mValues)
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 ¶mName, 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 ¯o)
KS: Convert a ROOT TMacro object to a YAML node.
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Class responsible for processing MCMC chains, performing diagnostics, generating plots,...
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.
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.
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::vector< bool > flatPrior
std::string hierarchyType
"NO", "IO", or "auto"
std::unique_ptr< TGraph2D > graph_IO
Inverted Ordering graph.