MaCh3  2.6.1
Reference Guide
Public Member Functions | Private Member Functions | List of all members
M3::GetPenaltyTermModule Class Reference

Module for extracting specific penalty terms from MCMC chains. More...

#include <CLI/Modules/GetPenaltyTermModule.hpp>

Inheritance diagram for M3::GetPenaltyTermModule:
[legend]
Collaboration diagram for M3::GetPenaltyTermModule:
[legend]

Public Member Functions

virtual ~GetPenaltyTermModule ()
 Destructor. More...
 
MaCh3ArgumentParserget_parser () override
 Get the argument parser for this module. More...
 
int Run () override
 Execute the penalty term extraction. More...
 
- Public Member Functions inherited from M3::PluginBase
virtual ~PluginBase ()=default
 
- Public Member Functions inherited from M3::IPlugin
virtual ~IPlugin ()=default
 

Private Member Functions

void ReadCovFile (const std::string &inputFile, std::vector< double > &Prior, std::vector< bool > &isFlat, std::vector< std::string > &ParamNames, std::vector< std::vector< double >> &invCovMatrix, int &nParams)
 Read covariance matrix and parameter information from file. More...
 
void LoadSettings (YAML::Node &Settings, std::vector< std::string > &SetsNames, std::vector< std::string > &FancyTitle, std::vector< std::vector< bool >> &isRelevantParam, const std::vector< std::string > &ParamNames, const int nParams)
 Load penalty term sets from YAML configuration. More...
 
void GetPenaltyTerm (const std::string &inputFile, const std::string &configFile)
 Calculate and plot penalty terms for parameter sets. More...
 

Additional Inherited Members

- Protected Attributes inherited from M3::PluginBase
std::unique_ptr< MaCh3ArgumentParserm_parser
 Argument parser for this plugin. More...
 

Detailed Description

Module for extracting specific penalty terms from MCMC chains.

This module retrieves penalty terms from flux and cross-section systematic chains, since these systematic uncertainties are handled separately and the penalty term cannot be taken directly from the chain.

Definition at line 25 of file GetPenaltyTermModule.hpp.

Constructor & Destructor Documentation

◆ ~GetPenaltyTermModule()

M3::GetPenaltyTermModule::~GetPenaltyTermModule ( )
virtualdefault

Destructor.

Member Function Documentation

◆ get_parser()

MaCh3ArgumentParser * M3::GetPenaltyTermModule::get_parser ( )
overridevirtual

Get the argument parser for this module.

Returns
Pointer to the configured MaCh3ArgumentParser

Implements M3::IPlugin.

Definition at line 32 of file GetPenaltyTermModule.cpp.

32  {
33  m_parser = std::make_unique<MaCh3ArgumentParser>("penterm", "1.0", argparse::default_arguments::help);
34  m_parser->add_description("Calculate penalty term for selected parameters, for every step");
35  m_parser->add_argument("inputfile")
36  .help("Root file to analyse.")
37  .metavar("INPUTFILE")
38  .required();
39  m_parser->add_argument("config")
40  .help("Config file.")
41  .metavar("CONFIG")
42  .required();
43  return m_parser.get();
44  }
std::unique_ptr< MaCh3ArgumentParser > m_parser
Argument parser for this plugin.
Definition: plugin.hpp:44

◆ GetPenaltyTerm()

void M3::GetPenaltyTermModule::GetPenaltyTerm ( const std::string &  inputFile,
const std::string &  configFile 
)
private

Calculate and plot penalty terms for parameter sets.

Calculate and plot penalty terms for each parameter set.

Parameters
inputFilePath to the MCMC chain ROOT file
configFilePath to the YAML configuration file

Main function that reads the covariance, loads configuration, iterates through MCMC steps, and calculates penalty terms for each defined set. Results are saved to ROOT file and PDF plots.

Parameters
inputFilePath to the MCMC chain ROOT file
configFilePath to the YAML configuration file

Definition at line 242 of file GetPenaltyTermModule.cpp.

243  {
244  auto canvas = std::make_unique<TCanvas>("canvas", "canvas", 0, 0, 1024, 1024);
245  canvas->SetGrid();
246  canvas->SetTickx();
247  canvas->SetTicky();
248 
249  canvas->SetBottomMargin(0.1f);
250  canvas->SetTopMargin(0.02f);
251  canvas->SetRightMargin(0.08f);
252  canvas->SetLeftMargin(0.15f);
253 
254  gStyle->SetOptTitle(0);
255  gStyle->SetOptStat(0);
256  gStyle->SetPalette(51);
257 
258  std::vector <double> Prior;
259  std::vector <bool> isFlat;
260  std::vector<std::string> ParamNames;
261  std::vector<std::vector<double>> invCovMatrix;
262  int nParams;
263  this->ReadCovFile(inputFile, Prior, isFlat, ParamNames, invCovMatrix, nParams);
264 
265  std::vector<TString> BranchNames;
266 
267  // Open the Chain
268  TChain* Chain = new TChain("posteriors","");
269  Chain->Add(inputFile.c_str());
270 
271  // Get the list of branches
272  TObjArray* brlis = Chain->GetListOfBranches();
273 
274  // Get the number of branches
275  int nBranches = brlis->GetEntries();
276  int RelevantBranches = 0;
277  for (int i = 0; i < nBranches; i++)
278  {
279  // Get the TBranch and its name
280  TBranch* br = static_cast<TBranch*>(brlis->At(i));
281  if(!br){
282  MACH3LOG_ERROR("Invalid branch at position {}", i);
283  throw MaCh3Exception(__FILE__,__LINE__);
284  }
285  TString bname = br->GetName();
286 
287  // If we're on beam systematics
288  if(bname.BeginsWith("param_"))
289  {
290  BranchNames.push_back(bname);
291  RelevantBranches++;
292  }
293  }
294 
295  // Set all the branches to off
296  Chain->SetBranchStatus("*", false);
297 
298  std::vector<double> fParProp(RelevantBranches);
299  // Turn on the branches which we want for parameters
300  for (int i = 0; i < RelevantBranches; ++i)
301  {
302  Chain->SetBranchStatus(BranchNames[i].Data(), true);
303  Chain->SetBranchAddress(BranchNames[i].Data(), &fParProp[i]);
304  }
305 
306  YAML::Node Settings = M3OpenConfig(configFile);
307  std::vector<std::string> SetsNames;
308  std::vector<std::string> FancyTitle;
309  std::vector<std::vector<bool>> isRelevantParam;
310 
311  this->LoadSettings(Settings, SetsNames, FancyTitle, isRelevantParam, ParamNames, nParams);
312 
313  const int NSets = int(SetsNames.size());
314  int AllEvents = int(Chain->GetEntries());
315  std::vector<std::unique_ptr<TH1D>> hLogL(NSets);
316  for (int i = 0; i < NSets; i++) {
317  std::string NameTemp = "LogL_" + SetsNames[i];
318  hLogL[i] = std::make_unique<TH1D>(NameTemp.c_str(), NameTemp.c_str(), AllEvents, 0, AllEvents);
319  hLogL[i]->SetLineColor(kBlue);
320  }
321  std::vector<double> logL(NSets, 0.0);
322  for(int n = 0; n < AllEvents; ++n)
323  {
324  if(n%10000 == 0) M3::Utils::PrintProgressBar(n, AllEvents);
325 
326  Chain->GetEntry(n);
327 
328  for(int k = 0; k < NSets; ++k) logL[k] = 0.;
329  #ifdef MULTITHREAD
330  // The per-thread array
331  double *logL_private = nullptr;
332 
333  // Declare the omp parallel region
334  // The parallel region needs to stretch beyond the for loop!
335  #pragma omp parallel private(logL_private)
336  {
337  logL_private = new double[NSets];
338  for(int k = 0; k < NSets; ++k) logL_private[k] = 0.;
339 
340  #pragma omp for
341  for (int i = 0; i < nParams; i++)
342  {
343  for (int j = 0; j <= i; ++j)
344  {
345  //check if flat prior
346  if (!isFlat[i] && !isFlat[j])
347  {
348  for(int k = 0; k < NSets; ++k)
349  {
350  //Check if parameter is relevant for this set
351  if (isRelevantParam[k][i] && isRelevantParam[k][j])
352  {
353  //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
354  int scale = 1;
355  if(i != j) scale = 2;
356  logL_private[k] += scale * 0.5*(fParProp[i] - Prior[i])*(fParProp[j] - Prior[j])*invCovMatrix[i][j];
357  }
358  }
359  }
360  }
361  }
362  // Now we can write the individual arrays from each thread to the main array
363  for(int k = 0; k < NSets; ++k)
364  {
365  #pragma omp atomic
366  logL[k] += logL_private[k];
367  }
368  //Delete private arrays
369  delete[] logL_private;
370  }//End omp range
371 
372  #else
373  for (int i = 0; i < nParams; i++)
374  {
375  for (int j = 0; j <= i; ++j)
376  {
377  //check if flat prior
378  if (!isFlat[i] && !isFlat[j])
379  {
380  for(int k = 0; k < NSets; ++k)
381  {
382  //Check if parameter is relevant for this set
383  if (isRelevantParam[k][i] && isRelevantParam[k][j])
384  {
385  //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
386  int scale = 1;
387  if(i != j) scale = 2;
388  logL[k] += scale * 0.5*(fParProp[i] - Prior[i])*(fParProp[j] - Prior[j])*invCovMatrix[i][j];
389  }
390  }
391  }
392  }
393  }
394  #endif // end MULTITHREAD
395  for(int k = 0; k < NSets; ++k)
396  {
397  hLogL[k]->SetBinContent(n, logL[k]);
398  }
399  }//End loop over steps
400 
401  // Directory for posteriors
402  std::string OutputName = inputFile + "_PenaltyTerm" +".root";
403  TFile *OutputFile = M3::Open(OutputName, "recreate", __FILE__, __LINE__);
404  TDirectory *PenaltyTermDir = OutputFile->mkdir("PenaltyTerm");
405 
406  canvas->Print(Form("%s_PenaltyTerm.pdf[",inputFile.c_str()), "pdf");
407  for(int i = 0; i < NSets; i++)
408  {
409  const double Maximum = hLogL[i]->GetMaximum();
410  hLogL[i]->GetYaxis()->SetRangeUser(0., Maximum*1.2);
411  hLogL[i]->SetTitle(FancyTitle[i].c_str());
412  hLogL[i]->GetXaxis()->SetTitle("Step");
413  hLogL[i]->GetYaxis()->SetTitle(FancyTitle[i].c_str());
414  hLogL[i]->GetYaxis()->SetTitleOffset(1.4f);
415 
416  hLogL[i]->Draw("");
417 
418  PenaltyTermDir->cd();
419  hLogL[i]->Write();
420 
421  canvas->Print(Form("%s_PenaltyTerm.pdf",inputFile.c_str()), "pdf");
422  }
423  canvas->Print(Form("%s_PenaltyTerm.pdf]",inputFile.c_str()), "pdf");
424  delete Chain;
425 
426  OutputFile->Close();
427  delete OutputFile;
428  }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
bool isFlat(TSpline3_red *&spl)
CW: Helper function used in the constructor, tests to see if the spline is flat.
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:590
void LoadSettings(YAML::Node &Settings, std::vector< std::string > &SetsNames, std::vector< std::string > &FancyTitle, std::vector< std::vector< bool >> &isRelevantParam, const std::vector< std::string > &ParamNames, const int nParams)
Load penalty term sets from YAML configuration.
void ReadCovFile(const std::string &inputFile, std::vector< double > &Prior, std::vector< bool > &isFlat, std::vector< std::string > &ParamNames, std::vector< std::vector< double >> &invCovMatrix, int &nParams)
Read covariance matrix and parameter information from file.
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
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.

◆ LoadSettings()

void M3::GetPenaltyTermModule::LoadSettings ( YAML::Node &  Settings,
std::vector< std::string > &  SetsNames,
std::vector< std::string > &  FancyTitle,
std::vector< std::vector< bool >> &  isRelevantParam,
const std::vector< std::string > &  ParamNames,
const int  nParams 
)
private

Load penalty term sets from YAML configuration.

Load penalty term set definitions from YAML configuration.

Parameters
SettingsYAML configuration node
SetsNamesVector to store set names
FancyTitleVector to store fancy titles for each set
isRelevantParam2D vector indicating which parameters belong to each set
ParamNamesVector of all parameter names
nParamsTotal number of parameters

Parses the configuration to determine which parameters belong to each penalty term set, based on either inclusion or exclusion patterns.

Parameters
SettingsYAML configuration node
SetsNamesVector to be filled with set names
FancyTitleVector to be filled with fancy titles for plotting
isRelevantParam2D vector to be filled with parameter relevance flags
ParamNamesVector of all parameter names from the covariance
nParamsTotal number of parameters

Definition at line 163 of file GetPenaltyTermModule.cpp.

169  {
170  std::vector<std::string> node = Settings["GetPenaltyTerm"]["PenaltySets"].as<std::vector<std::string>>();
171  std::vector<std::vector<std::string>> RemoveNames;
172  std::vector<bool> Exclude;
173 
174  for (unsigned int i = 0; i < node.size(); i++)
175  {
176  std::string ParName = node[i];
177  SetsNames.push_back(ParName);
178 
179  const auto& Set = Settings["GetPenaltyTerm"][ParName];
180 
181  RemoveNames.push_back(Set[0].as<std::vector<std::string>>());
182  Exclude.push_back(Set[1].as<bool>());
183  FancyTitle.push_back(Set[2].as<std::string>());
184  }
185 
186  const int NSets = int(SetsNames.size());
187 
188  isRelevantParam.resize(NSets);
189  //Loop over sets in the config
190  for(int i = 0; i < NSets; i++)
191  {
192  isRelevantParam[i].resize(nParams);
193  int counter = 0;
194  //Loop over parameters in the Covariance object
195  for (int j = 0; j < nParams; j++)
196  {
197  isRelevantParam[i][j] = false;
198 
199  //KS: Here we loop over all names and if parameters wasn't matched then we set it is relevant.
200  if(Exclude[i])
201  {
202  bool found = false;
203  for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
204  {
205  if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
206  {
207  found = true;
208  }
209  }
210  if(!found)
211  {
212  isRelevantParam[i][j] = true;
213  counter++;
214  }
215  }
216  //KS: Here is much simpler, if parameter matched then it is relevant
217  else
218  {
219  for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
220  {
221  if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
222  {
223  isRelevantParam[i][j] = true;
224  counter++;
225  break;
226  }
227  }
228  }
229  }
230  MACH3LOG_INFO(" Found {} params for set {}", counter, SetsNames[i]);
231  }
232  }
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35

◆ ReadCovFile()

void M3::GetPenaltyTermModule::ReadCovFile ( const std::string &  inputFile,
std::vector< double > &  Prior,
std::vector< bool > &  isFlat,
std::vector< std::string > &  ParamNames,
std::vector< std::vector< double >> &  invCovMatrix,
int &  nParams 
)
private

Read covariance matrix and parameter information from file.

Read covariance matrix and prior information from ROOT file.

Parameters
inputFilePath to the ROOT file containing the covariance
PriorVector to store prior parameter values
isFlatVector to store flat prior flags
ParamNamesVector to store parameter names
invCovMatrix2D vector to store inverted covariance matrix
nParamsReference to store the number of parameters

Loads the covariance matrix, inverts it, and extracts parameter priors and flat prior flags from the MCMC output file.

Parameters
inputFilePath to the ROOT file containing MCMC output
PriorVector to be filled with prior parameter values
isFlatVector to be filled with flat prior flags
ParamNamesVector to be filled with parameter names
invCovMatrix2D vector to be filled with inverted covariance matrix
nParamsReference to store the number of parameters

Definition at line 68 of file GetPenaltyTermModule.cpp.

74  {
75  // Now read the MCMC file
76  TFile *TempFile = M3::Open(inputFile, "open", __FILE__, __LINE__);
77 
78  // Get the matrix
79  TDirectory* CovarianceFolder = TempFile->Get<TDirectory>("CovarianceFolder");
80  TMatrixDSym *CovMatrix = M3::GetCovMatrixFromChain(CovarianceFolder);
81 
82  // Get the settings for the MCMC
83  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
84  if (Config == nullptr) {
85  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", inputFile);
86  TempFile->ls();
87  throw MaCh3Exception(__FILE__ , __LINE__ );
88  }
89 
90  YAML::Node Settings = TMacroToYAML(*Config);
91 
92  //CW: Get the Covariance matrix
93  std::vector<std::string> CovPos = GetFromManager<std::vector<std::string>>(Settings["General"]["Systematics"]["XsecCovFile"], {"none"}, __FILE__, __LINE__);
94  if(CovPos.back() == "none")
95  {
96  MACH3LOG_WARN("Couldn't find Cov branch in output");
97  M3::Utils::PrintConfig(Settings);
98  throw MaCh3Exception(__FILE__ , __LINE__ );
99  }
100 
101  //KS:Most inputs are in ${MACH3}/inputs/blarb.root
102  if (std::getenv("MACH3") != nullptr) {
103  MACH3LOG_INFO("Found MACH3 environment variable: {}", std::getenv("MACH3"));
104  for(unsigned int i = 0; i < CovPos.size(); i++)
105  CovPos[i].insert(0, std::string(std::getenv("MACH3"))+"/");
106  }
107 
108  YAML::Node CovFile;
109  CovFile["Systematics"] = YAML::Node(YAML::NodeType::Sequence);
110  for(unsigned int i = 0; i < CovPos.size(); i++)
111  {
112  YAML::Node YAMLDocTemp = M3OpenConfig(CovPos[i]);
113  for (const auto& item : YAMLDocTemp["Systematics"]) {
114  CovFile["Systematics"].push_back(item);
115  }
116  }
117 
118  nParams = CovMatrix->GetNrows();
119 
120  auto systematics = CovFile["Systematics"];
121  for (auto it = systematics.begin(); it != systematics.end(); ++it)
122  {
123  auto const &param = *it;
124 
125  ParamNames.push_back(param["Systematic"]["Names"]["FancyName"].as<std::string>());
126  Prior.push_back( param["Systematic"]["ParameterValues"]["PreFitValue"].as<double>() );
127 
128  bool flat = false;
129  if (param["Systematic"]["FlatPrior"]) { flat = param["Systematic"]["FlatPrior"].as<bool>(); }
130  isFlat.push_back( flat );
131  }
132 
133  CovMatrix->Invert();
134  //KS: Let's use double as it is faster than TMatrix
135  invCovMatrix.resize(nParams, std::vector<double>(nParams, -999));
136 
137  #ifdef MULTITHREAD
138  #pragma omp parallel for collapse(2)
139  #endif
140  for (int i = 0; i < nParams; i++)
141  {
142  for (int j = 0; j < nParams; ++j)
143  {
144  invCovMatrix[i][j] = (*CovMatrix)(i,j);
145  }
146  }
147 
148  TempFile->Close();
149  delete TempFile;
150  }
#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
void PrintConfig(const YAML::Node &node)
KS: Print Yaml config using logger.
Definition: Monitor.cpp:311
TMatrixDSym * GetCovMatrixFromChain(TDirectory *TempFile)
KS: Retrieve the cross-section covariance matrix from the given TDirectory. Historically,...

◆ Run()

int M3::GetPenaltyTermModule::Run ( )
overridevirtual

Execute the penalty term extraction.

Returns
Exit code (0 on success)

Implements M3::IPlugin.

Definition at line 46 of file GetPenaltyTermModule.cpp.

47  {
50  std::string inputFile = m_parser->get<std::string>("inputfile");
51  std::string config = m_parser->get<std::string>("config");
52  this->GetPenaltyTerm(inputFile, config);
53 
54  return 0;
55  }
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:60
void GetPenaltyTerm(const std::string &inputFile, const std::string &configFile)
Calculate and plot penalty terms for parameter sets.
void MaCh3Welcome()
KS: Prints welcome message with MaCh3 logo.
Definition: Monitor.cpp:13

The documentation for this class was generated from the following files: