MaCh3 2.2.1
Reference Guide
Loading...
Searching...
No Matches
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 = YAML::LoadFile(configFile.c_str());
186
187 std::vector<std::string> SetsNames;
188 std::vector<std::vector<std::string>> RemoveNames;
189 std::vector<bool> Exclude;
190 std::vector<std::string> FancyTittle;
191
192 std::vector<std::vector<bool>> isRelevantParam;
193 std::vector<std::string> node = Settings["GetPenaltyTerm"]["PenaltySets"].as<std::vector<std::string>>();
194 for (unsigned int i = 0; i < node.size(); i++)
195 {
196 std::string ParName = node[i];
197 SetsNames.push_back(ParName);
198
199 const auto& Set = Settings["GetPenaltyTerm"][ParName];
200
201 RemoveNames.push_back(Set[0].as<std::vector<std::string>>());
202 Exclude.push_back(Set[1].as<bool>());
203 FancyTittle.push_back(Set[2].as<std::string>());
204 }
205
206 const int NSets = int(SetsNames.size());
207
208 isRelevantParam.resize(NSets);
209 //Loop over sets in the config
210 for(int i = 0; i < NSets; i++)
211 {
212 isRelevantParam[i].resize(size);
213 int counter = 0;
214 //Loop over parameters in the Covariance object
215 for (int j = 0; j < size; j++)
216 {
217 isRelevantParam[i][j] = false;
218
219 //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
220 if(Exclude[i])
221 {
222 bool found = false;
223 for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
224 {
225 if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
226 {
227 found = true;
228 }
229 }
230 if(!found)
231 {
232 isRelevantParam[i][j] = true;
233 counter++;
234 }
235 }
236 //KS: Here is much simpler, if parameter matched then it is relevant
237 else
238 {
239 for (unsigned int k = 0; k < RemoveNames[i].size(); k++)
240 {
241 if (ParamNames[j].rfind(RemoveNames[i][k], 0) == 0)
242 {
243 isRelevantParam[i][j] = true;
244 counter++;
245 break;
246 }
247 }
248 }
249 }
250 MACH3LOG_INFO(" Found {} params for set {}", counter, SetsNames[i]);
251 }
252
253 int AllEvents = int(Chain->GetEntries());
254 std::vector<std::unique_ptr<TH1D>> hLogL(NSets);
255 for (int i = 0; i < NSets; i++) {
256 std::string NameTemp = "LogL_" + SetsNames[i];
257 hLogL[i] = std::make_unique<TH1D>(NameTemp.c_str(), NameTemp.c_str(), AllEvents, 0, AllEvents);
258 hLogL[i]->SetLineColor(kBlue);
259 }
260 std::vector<double> logL(NSets, 0.0);
261 for(int n = 0; n < AllEvents; ++n)
262 {
263 if(n%10000 == 0) MaCh3Utils::PrintProgressBar(n, AllEvents);
264
265 Chain->GetEntry(n);
266
267 for(int k = 0; k < NSets; ++k) logL[k] = 0.;
268#ifdef MULTITHREAD
269 // The per-thread array
270 double *logL_private = nullptr;
271
272 // Declare the omp parallel region
273 // The parallel region needs to stretch beyond the for loop!
274 #pragma omp parallel private(logL_private)
275 {
276 logL_private = new double[NSets]();
277 for(int k = 0; k < NSets; ++k) logL_private[k] = 0.;
278
279 #pragma omp for
280 for (int i = 0; i < size; i++)
281 {
282 for (int j = 0; j <= i; ++j)
283 {
284 //check if flat prior
285 if (!isFlat[i] && !isFlat[j])
286 {
287 for(int k = 0; k < NSets; ++k)
288 {
289 //Check if parameter is relevant for this set
290 if (isRelevantParam[k][i] && isRelevantParam[k][j])
291 {
292 //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
293 int scale = 1;
294 if(i != j) scale = 2;
295 logL_private[k] += scale * 0.5*(fParProp[i] - nominal[i])*(fParProp[j] - nominal[j])*invCovMatrix[i][j];
296 }
297 }
298 }
299 }
300 }
301 // Now we can write the individual arrays from each thread to the main array
302 for(int k = 0; k < NSets; ++k)
303 {
304 #pragma omp atomic
305 logL[k] += logL_private[k];
306 }
307 //Delete private arrays
308 delete[] logL_private;
309 }//End omp range
310
311#else
312 for (int i = 0; i < size; i++)
313 {
314 for (int j = 0; j <= i; ++j)
315 {
316 //check if flat prior
317 if (!isFlat[i] && !isFlat[j])
318 {
319 for(int k = 0; k < NSets; ++k)
320 {
321 //Check if parameter is relevant for this set
322 if (isRelevantParam[k][i] && isRelevantParam[k][j])
323 {
324 //KS: Since matrix is symmetric we can calculate non diagonal elements only once and multiply by 2, can bring up to factor speed decrease.
325 int scale = 1;
326 if(i != j) scale = 2;
327 logL[k] += scale * 0.5*(fParProp[i] - nominal[i])*(fParProp[j] - nominal[j])*invCovMatrix[i][j];
328 }
329 }
330 }
331 }
332 }
333#endif
334 for(int k = 0; k < NSets; ++k)
335 {
336 hLogL[k]->SetBinContent(n, logL[k]);
337 }
338 }//End loop over steps
339
340 // Directory for posteriors
341 std::string OutputName = inputFile + "_PenaltyTerm" +".root";
342 TFile* OutputFile = new TFile(OutputName.c_str(), "recreate");
343 TDirectory *PenaltyTermDir = OutputFile->mkdir("PenaltyTerm");
344
345 canvas->Print(Form("%s_PenaltyTerm.pdf[",inputFile.c_str()), "pdf");
346 for(int i = 0; i < NSets; i++)
347 {
348 const double Maximum = hLogL[i]->GetMaximum();
349 hLogL[i]->GetYaxis()->SetRangeUser(0., Maximum*1.2);
350 hLogL[i]->SetTitle(FancyTittle[i].c_str());
351 hLogL[i]->GetXaxis()->SetTitle("Step");
352 hLogL[i]->GetYaxis()->SetTitle(FancyTittle[i].c_str());
353 hLogL[i]->GetYaxis()->SetTitleOffset(1.4f);
354
355 hLogL[i]->Draw("");
356
357 PenaltyTermDir->cd();
358 hLogL[i]->Write();
359
360 canvas->Print(Form("%s_PenaltyTerm.pdf",inputFile.c_str()), "pdf");
361 }
362 canvas->Print(Form("%s_PenaltyTerm.pdf]",inputFile.c_str()), "pdf");
363 delete Chain;
364
365 for (int i = 0; i < size; i++)
366 {
367 delete[] invCovMatrix[i];
368 }
369 delete[] invCovMatrix;
370 OutputFile->Close();
371 delete OutputFile;
372}
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:25
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:23
Custom exception class for MaCh3 errors.
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:212

◆ main()

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

Definition at line 374 of file GetPenaltyTerm.cpp.

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

◆ 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");
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:146
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:560
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:294

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.