MaCh3  2.2.3
Reference Guide
Functions | Variables
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 "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 ReadXSecFile (const std::string &inputFile)
 
void GetPenaltyTerm (const std::string &inputFile, const std::string &configFile)
 
int main (int argc, char *argv[])
 

Variables

std::vector< double > nominal
 
std::vector< bool > isFlat
 
std::vector< TString > BranchNames
 
std::vector< std::string > ParamNames
 
int size
 
double ** invCovMatrix
 

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

Definition in file GetPenaltyTerm.cpp.

Function Documentation

◆ GetPenaltyTerm()

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

Definition at line 128 of file GetPenaltyTerm.cpp.

129 {
130  auto canvas = std::make_unique<TCanvas>("canvas", "canvas", 0, 0, 1024, 1024);
131  canvas->SetGrid();
132  canvas->SetTickx();
133  canvas->SetTicky();
134 
135  canvas->SetBottomMargin(0.1f);
136  canvas->SetTopMargin(0.02f);
137  canvas->SetRightMargin(0.08f);
138  canvas->SetLeftMargin(0.15f);
139 
140  gStyle->SetOptTitle(0);
141  gStyle->SetOptStat(0);
142  gStyle->SetPalette(51);
143 
144  ReadXSecFile(inputFile);
145 
146  // Open the Chain
147  TChain* Chain = new TChain("posteriors","");
148  Chain->Add(inputFile.c_str());
149 
150  // Get the list of branches
151  TObjArray* brlis = Chain->GetListOfBranches();
152 
153  // Get the number of branches
154  int nBranches = brlis->GetEntries();
155  int RelevantBranches = 0;
156  for (int i = 0; i < nBranches; i++)
157  {
158  // Get the TBranch and its name
159  TBranch* br = static_cast<TBranch*>(brlis->At(i));
160  if(!br){
161  MACH3LOG_ERROR("Invalid branch at position {}", i);
162  throw MaCh3Exception(__FILE__,__LINE__);
163  }
164  TString bname = br->GetName();
165 
166  // If we're on beam systematics
167  if(bname.BeginsWith("xsec_"))
168  {
169  BranchNames.push_back(bname);
170  RelevantBranches++;
171  }
172  }
173 
174  // Set all the branches to off
175  Chain->SetBranchStatus("*", false);
176 
177  std::vector<double> fParProp(RelevantBranches);
178  // Turn on the branches which we want for parameters
179  for (int i = 0; i < RelevantBranches; ++i)
180  {
181  Chain->SetBranchStatus(BranchNames[i].Data(), true);
182  Chain->SetBranchAddress(BranchNames[i].Data(), &fParProp[i]);
183  }
184 
185  YAML::Node Settings = M3OpenConfig(configFile);
186  std::vector<std::string> SetsNames;
187  std::vector<std::vector<std::string>> RemoveNames;
188  std::vector<bool> Exclude;
189  std::vector<std::string> FancyTitle;
190 
191  std::vector<std::vector<bool>> isRelevantParam;
192  std::vector<std::string> node = Settings["GetPenaltyTerm"]["PenaltySets"].as<std::vector<std::string>>();
193  for (unsigned int i = 0; i < node.size(); i++)
194  {
195  std::string ParName = node[i];
196  SetsNames.push_back(ParName);
197 
198  const auto& Set = Settings["GetPenaltyTerm"][ParName];
199 
200  RemoveNames.push_back(Set[0].as<std::vector<std::string>>());
201  Exclude.push_back(Set[1].as<bool>());
202  FancyTitle.push_back(Set[2].as<std::string>());
203  }
204 
205  const int NSets = int(SetsNames.size());
206 
207  isRelevantParam.resize(NSets);
208  //Loop over sets in the config
209  for(int i = 0; i < NSets; i++)
210  {
211  isRelevantParam[i].resize(size);
212  int counter = 0;
213  //Loop over parameters in the Covariance object
214  for (int j = 0; j < size; j++)
215  {
216  isRelevantParam[i][j] = false;
217 
218  //KS: Here we loop over all names and if parameters wasn't matched then we set it is relevant. For xsec it is easier to do it like this
219  if(Exclude[i])
220  {
221  bool found = false;
222  for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
223  {
224  if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
225  {
226  found = true;
227  }
228  }
229  if(!found)
230  {
231  isRelevantParam[i][j] = true;
232  counter++;
233  }
234  }
235  //KS: Here is much simpler, if parameter matched then it is relevant
236  else
237  {
238  for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
239  {
240  if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
241  {
242  isRelevantParam[i][j] = true;
243  counter++;
244  break;
245  }
246  }
247  }
248  }
249  MACH3LOG_INFO(" Found {} params for set {}", counter, SetsNames[i]);
250  }
251 
252  int AllEvents = int(Chain->GetEntries());
253  std::vector<std::unique_ptr<TH1D>> hLogL(NSets);
254  for (int i = 0; i < NSets; i++) {
255  std::string NameTemp = "LogL_" + SetsNames[i];
256  hLogL[i] = std::make_unique<TH1D>(NameTemp.c_str(), NameTemp.c_str(), AllEvents, 0, AllEvents);
257  hLogL[i]->SetLineColor(kBlue);
258  }
259  std::vector<double> logL(NSets, 0.0);
260  for(int n = 0; n < AllEvents; ++n)
261  {
262  if(n%10000 == 0) MaCh3Utils::PrintProgressBar(n, AllEvents);
263 
264  Chain->GetEntry(n);
265 
266  for(int k = 0; k < NSets; ++k) logL[k] = 0.;
267 #ifdef MULTITHREAD
268  // The per-thread array
269  double *logL_private = nullptr;
270 
271  // Declare the omp parallel region
272  // The parallel region needs to stretch beyond the for loop!
273  #pragma omp parallel private(logL_private)
274  {
275  logL_private = new double[NSets]();
276  for(int k = 0; k < NSets; ++k) logL_private[k] = 0.;
277 
278  #pragma omp for
279  for (int i = 0; i < size; i++)
280  {
281  for (int j = 0; j <= i; ++j)
282  {
283  //check if flat prior
284  if (!isFlat[i] && !isFlat[j])
285  {
286  for(int k = 0; k < NSets; ++k)
287  {
288  //Check if parameter is relevant for this set
289  if (isRelevantParam[k][i] && isRelevantParam[k][j])
290  {
291  //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
292  int scale = 1;
293  if(i != j) scale = 2;
294  logL_private[k] += scale * 0.5*(fParProp[i] - nominal[i])*(fParProp[j] - nominal[j])*invCovMatrix[i][j];
295  }
296  }
297  }
298  }
299  }
300  // Now we can write the individual arrays from each thread to the main array
301  for(int k = 0; k < NSets; ++k)
302  {
303  #pragma omp atomic
304  logL[k] += logL_private[k];
305  }
306  //Delete private arrays
307  delete[] logL_private;
308  }//End omp range
309 
310 #else
311  for (int i = 0; i < size; i++)
312  {
313  for (int j = 0; j <= i; ++j)
314  {
315  //check if flat prior
316  if (!isFlat[i] && !isFlat[j])
317  {
318  for(int k = 0; k < NSets; ++k)
319  {
320  //Check if parameter is relevant for this set
321  if (isRelevantParam[k][i] && isRelevantParam[k][j])
322  {
323  //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
324  int scale = 1;
325  if(i != j) scale = 2;
326  logL[k] += scale * 0.5*(fParProp[i] - nominal[i])*(fParProp[j] - nominal[j])*invCovMatrix[i][j];
327  }
328  }
329  }
330  }
331  }
332 #endif
333  for(int k = 0; k < NSets; ++k)
334  {
335  hLogL[k]->SetBinContent(n, logL[k]);
336  }
337  }//End loop over steps
338 
339  // Directory for posteriors
340  std::string OutputName = inputFile + "_PenaltyTerm" +".root";
341  TFile* OutputFile = new TFile(OutputName.c_str(), "recreate");
342  TDirectory *PenaltyTermDir = OutputFile->mkdir("PenaltyTerm");
343 
344  canvas->Print(Form("%s_PenaltyTerm.pdf[",inputFile.c_str()), "pdf");
345  for(int i = 0; i < NSets; i++)
346  {
347  const double Maximum = hLogL[i]->GetMaximum();
348  hLogL[i]->GetYaxis()->SetRangeUser(0., Maximum*1.2);
349  hLogL[i]->SetTitle(FancyTitle[i].c_str());
350  hLogL[i]->GetXaxis()->SetTitle("Step");
351  hLogL[i]->GetYaxis()->SetTitle(FancyTitle[i].c_str());
352  hLogL[i]->GetYaxis()->SetTitleOffset(1.4f);
353 
354  hLogL[i]->Draw("");
355 
356  PenaltyTermDir->cd();
357  hLogL[i]->Write();
358 
359  canvas->Print(Form("%s_PenaltyTerm.pdf",inputFile.c_str()), "pdf");
360  }
361  canvas->Print(Form("%s_PenaltyTerm.pdf]",inputFile.c_str()), "pdf");
362  delete Chain;
363 
364  for (int i = 0; i < size; i++)
365  {
366  delete[] invCovMatrix[i];
367  }
368  delete[] invCovMatrix;
369  OutputFile->Close();
370  delete OutputFile;
371 }
std::vector< double > nominal
double ** invCovMatrix
int size
std::vector< std::string > ParamNames
void ReadXSecFile(const std::string &inputFile)
std::vector< TString > BranchNames
std::vector< bool > isFlat
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:27
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:25
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:561
Custom exception class for MaCh3 errors.
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:213

◆ main()

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

Definition at line 373 of file GetPenaltyTerm.cpp.

374 {
377  if (argc != 3 )
378  {
379  MACH3LOG_WARN("Something went wrong ");
380  MACH3LOG_WARN("./GetPenaltyTerm root_file_to_analyse.root ");
381  throw MaCh3Exception(__FILE__ , __LINE__ );
382  }
383  std::string filename = argv[1];
384  std::string config = argv[2];
385  GetPenaltyTerm(filename, config);
386 
387  return 0;
388 }
void GetPenaltyTerm(const std::string &inputFile, const std::string &configFile)
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:51
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:26
std::string config
Definition: ProcessMCMC.cpp:29
void MaCh3Welcome()
KS: Prints welcome message with MaCh3 logo.
Definition: Monitor.cpp:12

◆ ReadXSecFile()

void ReadXSecFile ( const std::string &  inputFile)

Definition at line 42 of file GetPenaltyTerm.cpp.

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

Variable Documentation

◆ BranchNames

std::vector<TString> BranchNames

Definition at line 36 of file GetPenaltyTerm.cpp.

◆ invCovMatrix

double** invCovMatrix

Definition at line 40 of file GetPenaltyTerm.cpp.

◆ isFlat

std::vector<bool> isFlat

Definition at line 35 of file GetPenaltyTerm.cpp.

◆ nominal

std::vector<double> nominal

Definition at line 34 of file GetPenaltyTerm.cpp.

◆ ParamNames

std::vector<std::string> ParamNames

Definition at line 37 of file GetPenaltyTerm.cpp.

◆ size

int size

Definition at line 38 of file GetPenaltyTerm.cpp.