MaCh3  2.4.2
Reference Guide
Functions
GetPenaltyTerm.cpp File Reference

KS: This file contains the implementation of the function to extract specific penalty terms from systematic chains. More...

#include "Manager/Manager.h"
#include "Samples/SampleStructs.h"
#include "Samples/HistogramUtils.h"
#include "Parameters/ParameterHandlerUtils.h"
#include "TFile.h"
#include "TBranch.h"
#include "TCanvas.h"
#include "TLine.h"
#include "TLegend.h"
#include "TString.h"
#include "TStyle.h"
#include "TMatrixT.h"
#include "TMatrixDSym.h"
#include "TVectorD.h"
#include "TObject.h"
#include "TChain.h"
#include "TH1.h"
#include "TColor.h"
#include "TObjString.h"
#include "TROOT.h"
Include dependency graph for GetPenaltyTerm.cpp:

Go to the source code of this file.

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)
 
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)
 
void GetPenaltyTerm (const std::string &inputFile, const std::string &configFile)
 
int main (int argc, char *argv[])
 

Detailed Description

KS: This file contains the implementation of the function to extract specific penalty terms from systematic chains.

This script is designed to retrieve penalty terms from various sources, such as flux and cross-section systematic chains. Since flux and cross-section uncertainties are handled systematically, the penalty term cannot be taken directly from the chain.

Todo:
KS: This should really be moved to MCMC Processor
Author
Kamil Skwarczynski

Definition in file GetPenaltyTerm.cpp.

Function Documentation

◆ GetPenaltyTerm()

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

Definition at line 193 of file GetPenaltyTerm.cpp.

194 {
195  auto canvas = std::make_unique<TCanvas>("canvas", "canvas", 0, 0, 1024, 1024);
196  canvas->SetGrid();
197  canvas->SetTickx();
198  canvas->SetTicky();
199 
200  canvas->SetBottomMargin(0.1f);
201  canvas->SetTopMargin(0.02f);
202  canvas->SetRightMargin(0.08f);
203  canvas->SetLeftMargin(0.15f);
204 
205  gStyle->SetOptTitle(0);
206  gStyle->SetOptStat(0);
207  gStyle->SetPalette(51);
208 
209  std::vector <double> Prior;
210  std::vector <bool> isFlat;
211  std::vector<std::string> ParamNames;
212  std::vector<std::vector<double>> invCovMatrix;
213  int nParams;
214  ReadCovFile(inputFile, Prior, isFlat, ParamNames, invCovMatrix, nParams);
215 
216  std::vector<TString> BranchNames;
217 
218  // Open the Chain
219  TChain* Chain = new TChain("posteriors","");
220  Chain->Add(inputFile.c_str());
221 
222  // Get the list of branches
223  TObjArray* brlis = Chain->GetListOfBranches();
224 
225  // Get the number of branches
226  int nBranches = brlis->GetEntries();
227  int RelevantBranches = 0;
228  for (int i = 0; i < nBranches; i++)
229  {
230  // Get the TBranch and its name
231  TBranch* br = static_cast<TBranch*>(brlis->At(i));
232  if(!br){
233  MACH3LOG_ERROR("Invalid branch at position {}", i);
234  throw MaCh3Exception(__FILE__,__LINE__);
235  }
236  TString bname = br->GetName();
237 
238  // If we're on beam systematics
239  if(bname.BeginsWith("param_"))
240  {
241  BranchNames.push_back(bname);
242  RelevantBranches++;
243  }
244  }
245 
246  // Set all the branches to off
247  Chain->SetBranchStatus("*", false);
248 
249  std::vector<double> fParProp(RelevantBranches);
250  // Turn on the branches which we want for parameters
251  for (int i = 0; i < RelevantBranches; ++i)
252  {
253  Chain->SetBranchStatus(BranchNames[i].Data(), true);
254  Chain->SetBranchAddress(BranchNames[i].Data(), &fParProp[i]);
255  }
256 
257  YAML::Node Settings = M3OpenConfig(configFile);
258  std::vector<std::string> SetsNames;
259  std::vector<std::string> FancyTitle;
260  std::vector<std::vector<bool>> isRelevantParam;
261 
262  LoadSettings(Settings, SetsNames, FancyTitle, isRelevantParam, ParamNames, nParams);
263 
264  const int NSets = int(SetsNames.size());
265  int AllEvents = int(Chain->GetEntries());
266  std::vector<std::unique_ptr<TH1D>> hLogL(NSets);
267  for (int i = 0; i < NSets; i++) {
268  std::string NameTemp = "LogL_" + SetsNames[i];
269  hLogL[i] = std::make_unique<TH1D>(NameTemp.c_str(), NameTemp.c_str(), AllEvents, 0, AllEvents);
270  hLogL[i]->SetLineColor(kBlue);
271  }
272  std::vector<double> logL(NSets, 0.0);
273  for(int n = 0; n < AllEvents; ++n)
274  {
275  if(n%10000 == 0) MaCh3Utils::PrintProgressBar(n, AllEvents);
276 
277  Chain->GetEntry(n);
278 
279  for(int k = 0; k < NSets; ++k) logL[k] = 0.;
280 #ifdef MULTITHREAD
281  // The per-thread array
282  double *logL_private = nullptr;
283 
284  // Declare the omp parallel region
285  // The parallel region needs to stretch beyond the for loop!
286  #pragma omp parallel private(logL_private)
287  {
288  logL_private = new double[NSets];
289  for(int k = 0; k < NSets; ++k) logL_private[k] = 0.;
290 
291  #pragma omp for
292  for (int i = 0; i < nParams; i++)
293  {
294  for (int j = 0; j <= i; ++j)
295  {
296  //check if flat prior
297  if (!isFlat[i] && !isFlat[j])
298  {
299  for(int k = 0; k < NSets; ++k)
300  {
301  //Check if parameter is relevant for this set
302  if (isRelevantParam[k][i] && isRelevantParam[k][j])
303  {
304  //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
305  int scale = 1;
306  if(i != j) scale = 2;
307  logL_private[k] += scale * 0.5*(fParProp[i] - Prior[i])*(fParProp[j] - Prior[j])*invCovMatrix[i][j];
308  }
309  }
310  }
311  }
312  }
313  // Now we can write the individual arrays from each thread to the main array
314  for(int k = 0; k < NSets; ++k)
315  {
316  #pragma omp atomic
317  logL[k] += logL_private[k];
318  }
319  //Delete private arrays
320  delete[] logL_private;
321  }//End omp range
322 
323 #else
324  for (int i = 0; i < nParams; i++)
325  {
326  for (int j = 0; j <= i; ++j)
327  {
328  //check if flat prior
329  if (!isFlat[i] && !isFlat[j])
330  {
331  for(int k = 0; k < NSets; ++k)
332  {
333  //Check if parameter is relevant for this set
334  if (isRelevantParam[k][i] && isRelevantParam[k][j])
335  {
336  //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
337  int scale = 1;
338  if(i != j) scale = 2;
339  logL[k] += scale * 0.5*(fParProp[i] - Prior[i])*(fParProp[j] - Prior[j])*invCovMatrix[i][j];
340  }
341  }
342  }
343  }
344  }
345 #endif // end MULTITHREAD
346  for(int k = 0; k < NSets; ++k)
347  {
348  hLogL[k]->SetBinContent(n, logL[k]);
349  }
350  }//End loop over steps
351 
352  // Directory for posteriors
353  std::string OutputName = inputFile + "_PenaltyTerm" +".root";
354  TFile *OutputFile = M3::Open(OutputName, "recreate", __FILE__, __LINE__);
355  TDirectory *PenaltyTermDir = OutputFile->mkdir("PenaltyTerm");
356 
357  canvas->Print(Form("%s_PenaltyTerm.pdf[",inputFile.c_str()), "pdf");
358  for(int i = 0; i < NSets; i++)
359  {
360  const double Maximum = hLogL[i]->GetMaximum();
361  hLogL[i]->GetYaxis()->SetRangeUser(0., Maximum*1.2);
362  hLogL[i]->SetTitle(FancyTitle[i].c_str());
363  hLogL[i]->GetXaxis()->SetTitle("Step");
364  hLogL[i]->GetYaxis()->SetTitle(FancyTitle[i].c_str());
365  hLogL[i]->GetYaxis()->SetTitleOffset(1.4f);
366 
367  hLogL[i]->Draw("");
368 
369  PenaltyTermDir->cd();
370  hLogL[i]->Write();
371 
372  canvas->Print(Form("%s_PenaltyTerm.pdf",inputFile.c_str()), "pdf");
373  }
374  canvas->Print(Form("%s_PenaltyTerm.pdf]",inputFile.c_str()), "pdf");
375  delete Chain;
376 
377  OutputFile->Close();
378  delete OutputFile;
379 }
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)
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)
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
std::vector< TString > BranchNames
Definition: RHat.cpp:54
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:589
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.
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:228

◆ LoadSettings()

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 
)

Definition at line 122 of file GetPenaltyTerm.cpp.

128 {
129  std::vector<std::string> node = Settings["GetPenaltyTerm"]["PenaltySets"].as<std::vector<std::string>>();
130  std::vector<std::vector<std::string>> RemoveNames;
131  std::vector<bool> Exclude;
132 
133  for (unsigned int i = 0; i < node.size(); i++)
134  {
135  std::string ParName = node[i];
136  SetsNames.push_back(ParName);
137 
138  const auto& Set = Settings["GetPenaltyTerm"][ParName];
139 
140  RemoveNames.push_back(Set[0].as<std::vector<std::string>>());
141  Exclude.push_back(Set[1].as<bool>());
142  FancyTitle.push_back(Set[2].as<std::string>());
143  }
144 
145  const int NSets = int(SetsNames.size());
146 
147  isRelevantParam.resize(NSets);
148  //Loop over sets in the config
149  for(int i = 0; i < NSets; i++)
150  {
151  isRelevantParam[i].resize(nParams);
152  int counter = 0;
153  //Loop over parameters in the Covariance object
154  for (int j = 0; j < nParams; j++)
155  {
156  isRelevantParam[i][j] = false;
157 
158  //KS: Here we loop over all names and if parameters wasn't matched then we set it is relevant.
159  if(Exclude[i])
160  {
161  bool found = false;
162  for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
163  {
164  if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
165  {
166  found = true;
167  }
168  }
169  if(!found)
170  {
171  isRelevantParam[i][j] = true;
172  counter++;
173  }
174  }
175  //KS: Here is much simpler, if parameter matched then it is relevant
176  else
177  {
178  for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
179  {
180  if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
181  {
182  isRelevantParam[i][j] = true;
183  counter++;
184  break;
185  }
186  }
187  }
188  }
189  MACH3LOG_INFO(" Found {} params for set {}", counter, SetsNames[i]);
190  }
191 }
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 381 of file GetPenaltyTerm.cpp.

382 {
385  if (argc != 3 )
386  {
387  MACH3LOG_WARN("Something went wrong ");
388  MACH3LOG_WARN("{} root_file_to_analyse.root", argv[1]);
389  throw MaCh3Exception(__FILE__ , __LINE__ );
390  }
391  std::string filename = argv[1];
392  std::string config = argv[2];
393  GetPenaltyTerm(filename, config);
394 
395  return 0;
396 }
void GetPenaltyTerm(const std::string &inputFile, const std::string &configFile)
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:61
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
std::string config
Definition: ProcessMCMC.cpp:30
void MaCh3Welcome()
KS: Prints welcome message with MaCh3 logo.
Definition: Monitor.cpp:12

◆ ReadCovFile()

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 
)

Definition at line 38 of file GetPenaltyTerm.cpp.

44 {
45  // Now read the MCMC file
46  TFile *TempFile = M3::Open(inputFile, "open", __FILE__, __LINE__);
47 
48  // Get the matrix
49  TDirectory* CovarianceFolder = TempFile->Get<TDirectory>("CovarianceFolder");
50  TMatrixDSym *CovMatrix = M3::GetCovMatrixFromChain(CovarianceFolder);
51 
52  // Get the settings for the MCMC
53  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
54  if (Config == nullptr) {
55  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", inputFile);
56  TempFile->ls();
57  throw MaCh3Exception(__FILE__ , __LINE__ );
58  }
59 
60  YAML::Node Settings = TMacroToYAML(*Config);
61 
62  //CW: Get the Covariance matrix
63  std::vector<std::string> CovPos = GetFromManager<std::vector<std::string>>(Settings["General"]["Systematics"]["XsecCovFile"], {"none"});
64  if(CovPos.back() == "none")
65  {
66  MACH3LOG_WARN("Couldn't find Cov branch in output");
67  MaCh3Utils::PrintConfig(Settings);
68  throw MaCh3Exception(__FILE__ , __LINE__ );
69  }
70 
71  //KS:Most inputs are in ${MACH3}/inputs/blarb.root
72  if (std::getenv("MACH3") != nullptr) {
73  MACH3LOG_INFO("Found MACH3 environment variable: {}", std::getenv("MACH3"));
74  for(unsigned int i = 0; i < CovPos.size(); i++)
75  CovPos[i].insert(0, std::string(std::getenv("MACH3"))+"/");
76  }
77 
78  YAML::Node CovFile;
79  CovFile["Systematics"] = YAML::Node(YAML::NodeType::Sequence);
80  for(unsigned int i = 0; i < CovPos.size(); i++)
81  {
82  YAML::Node YAMLDocTemp = M3OpenConfig(CovPos[i]);
83  for (const auto& item : YAMLDocTemp["Systematics"]) {
84  CovFile["Systematics"].push_back(item);
85  }
86  }
87 
88  nParams = CovMatrix->GetNrows();
89 
90  auto systematics = CovFile["Systematics"];
91  for (auto it = systematics.begin(); it != systematics.end(); ++it)
92  {
93  auto const &param = *it;
94 
95  ParamNames.push_back(param["Systematic"]["Names"]["FancyName"].as<std::string>());
96  Prior.push_back( param["Systematic"]["ParameterValues"]["PreFitValue"].as<double>() );
97 
98  bool flat = false;
99  if (param["Systematic"]["FlatPrior"]) { flat = param["Systematic"]["FlatPrior"].as<bool>(); }
100  isFlat.push_back( flat );
101  }
102 
103  CovMatrix->Invert();
104  //KS: Let's use double as it is faster than TMatrix
105  invCovMatrix.resize(nParams, std::vector<double>(nParams, -999));
106 
107  #ifdef MULTITHREAD
108  #pragma omp parallel for collapse(2)
109  #endif
110  for (int i = 0; i < nParams; i++)
111  {
112  for (int j = 0; j < nParams; ++j)
113  {
114  invCovMatrix[i][j] = (*CovMatrix)(i,j);
115  }
116  }
117 
118  TempFile->Close();
119  delete TempFile;
120 }
YAML::Node TMacroToYAML(const TMacro &macro)
KS: Convert a ROOT TMacro object to a YAML node.
Definition: YamlHelper.h:152
TMatrixDSym * GetCovMatrixFromChain(TDirectory *TempFile)
KS: Retrieve the cross-section covariance matrix from the given TDirectory. Historically,...
void PrintConfig(const YAML::Node &node)
KS: Print Yaml config using logger.
Definition: Monitor.cpp:310