MaCh3 2.2.1
Reference Guide
Loading...
Searching...
No Matches
inputManager.cpp
Go to the documentation of this file.
1#include "inputManager.h"
2
3
4namespace MaCh3Plotting {
5// this is the constructor with user specified translation config file
6InputManager::InputManager(const std::string &translationConfigName) {
7 // read the config file
8 _translatorConfig = M3OpenConfig(translationConfigName);
9
10 MACH3LOG_DEBUG("InputManager: have loaded translation config file");
11
12 // split up the parts of the config for easier access later
16
17 // check the config file and get which parameters, samples, and fitters we've been told about
18 _knownFitters = _fitterSpecConfig["fitters"].as<std::vector<std::string>>();
19 _knownParameters = _parametersConfig["Parameters"].as<std::vector<std::string>>();
20 _knownSamples = _samplesConfig["Samples"].as<std::vector<std::string>>();
21
22 MACH3LOG_DEBUG("Will now check the specified parameters for tags");
23
24 // loop through all parameters and get their tags
25 for ( const std::string &param: _knownParameters )
26 {
27 std::vector<std::string> tags;
28
29 MACH3LOG_DEBUG("Looking for tags for parameter {}", param);
30 if ( _parametersConfig[param] )
31 {
32 if ( _parametersConfig[param]["tags"] )
33 {
34 tags = _parametersConfig[param]["tags"].as<std::vector<std::string>>();
35 MACH3LOG_DEBUG(" - Found {}!", tags.size());
36 }
37 }
38 _paramToTagsMap[param] = tags;
39 }
40
41 MACH3LOG_DEBUG("Will now check the specified samples for tags");
42
43 // same again for samples
44 for ( const std::string &samp: _knownSamples )
45 {
46 std::vector<std::string> tags;
47
48 MACH3LOG_DEBUG("Looking for tags for sample {}", samp);
49 if ( _samplesConfig[samp])
50 {
51 if ( _samplesConfig[samp]["tags"] )
52 {
53 tags = _samplesConfig[samp]["tags"].as<std::vector<std::string>>();
54 MACH3LOG_DEBUG(" - Found {}!", tags.size());
55 }
56 }
57 _sampleToTagsMap[samp] = tags;
58 }
59}
60
69void InputManager::addFile(const std::string &fileName) {
70 _fileVec.emplace_back(fileName);
71
72 // EM: need to be done in this order since fillFileData needs to know info about the file, e.g.
73 // fitter and what things are in it
74 InputFile &fileInfo = _fileVec.back();
75 fillFileInfo(fileInfo);
76 fillFileData(fileInfo);
77}
78
82void InputManager::print(const std::string &printLevel) const {
83 MACH3LOG_INFO("Printing contents of InputManager instance:");
84
85 if (printLevel == "dump")
86 {
87 MACH3LOG_INFO("parameters known to this manager: ");
88 for (std::string param : _knownParameters)
89 {
90 MACH3LOG_INFO(" ");
91 }
92 }
93
94 int fileCount = 0;
95 for (const InputFile &file : _fileVec)
96 {
97 MACH3LOG_INFO(" For file {}", fileCount);
98 if (printLevel == "summary")
99 {
100 file.Summarise();
101 } else if (printLevel == "dump")
102 { file.Dump(); }
103 fileCount++;
104 }
105
106 MACH3LOG_INFO("");
107}
108
109double InputManager::getPostFitError(int fileNum, const std::string &paramName,
110 std::string errorType) const {
111 const InputFile &inputFileDef = getFile(fileNum);
112
113 // set default type if not specified
114 if (errorType == "")
115 errorType = inputFileDef.defaultErrorType;
116
117 if (inputFileDef.postFitErrors.find(errorType) == inputFileDef.postFitErrors.end())
118 {
119 MACH3LOG_CRITICAL("Requested error type, {} does not exist in the specified file: ", errorType);
120 MACH3LOG_CRITICAL(" {}", inputFileDef.fileName);
121 MACH3LOG_CRITICAL(" at index {}", fileNum);
122
123 throw MaCh3Exception(__FILE__ , __LINE__ );
124 }
125
126 if (inputFileDef.postFitErrors.at(errorType).find(paramName) !=
127 inputFileDef.postFitErrors.at(errorType).end())
128 {
129 return inputFileDef.postFitErrors.at(errorType).at(paramName);
130 }
131
132 MACH3LOG_WARN("Didn't fnd {} post fit error for {}. Returning {}", errorType, paramName, M3::_BAD_DOUBLE_);
133
134 return M3::_BAD_DOUBLE_;
135}
136
137double InputManager::getPostFitValue(int fileNum, const std::string &paramName,
138 std::string errorType) const {
139 const InputFile &inputFileDef = getFile(fileNum);
140
141 // set default type if not specified
142 if (errorType == "")
143 errorType = inputFileDef.defaultErrorType;
144
145 if (inputFileDef.postFitErrors.find(errorType) == inputFileDef.postFitErrors.end())
146 {
147 MACH3LOG_CRITICAL("Requested error type, {} does not exist in the specified file: ", errorType);
148 MACH3LOG_CRITICAL(" {}", inputFileDef.fileName);
149 MACH3LOG_CRITICAL(" at index {}", fileNum);
150
151 throw MaCh3Exception(__FILE__ , __LINE__ );
152 }
153
154 if (inputFileDef.postFitValues.at(errorType).find(paramName) !=
155 inputFileDef.postFitValues.at(errorType).end())
156 {
157 return inputFileDef.postFitValues.at(errorType).at(paramName);
158 }
159
160 MACH3LOG_WARN("Didn't fnd {} post fit value for {}. Returning {}", errorType, paramName, M3::_BAD_DOUBLE_);
161
162 return M3::_BAD_DOUBLE_;
163}
164
165
166// ##################################################################
167// ################## End of public interface #######################
168// ##################################################################
169
170std::vector<std::string> InputManager::getTaggedValues(const std::vector<std::string> &values,
171 const std::unordered_map<std::string, std::vector<std::string>> &tagMap,
172 const std::vector<std::string> &tags, std::string checkType) const {
173 // check that checkType is valid
174 if(
175 checkType != "all" &&
176 checkType != "any" &&
177 checkType != "exact"
178 )
179 {
180 MACH3LOG_ERROR("Invalid tag check type specified: {}. Will instead use the default type: 'all'", checkType);
181 checkType = "all";
182 }
183
184 // If no tags were specified, take this to mean that anything should be a match
185 if (tags.size() == 0) return values;
186
187 std::vector<std::string> retVec;
188
189 MACH3LOG_DEBUG("Getting tagged values using checkType {}", checkType);
190 for ( std::string val: values )
191 {
192 MACH3LOG_DEBUG("Checking tags of {}", val);
193 // get the tags that this value has
194 const std::vector<std::string> &valTags = tagMap.at(val);
195
196 // we can skip it if it has no tags
197 if (valTags.size() == 0) continue;
198
199 // count how many of the specified tags match the tags of the current value
200 unsigned int tagCount = 0;
201 for ( const std::string &tag: tags )
202 {
203 if ( std::find( valTags.begin(), valTags.end(), tag ) != valTags.end() )
204 {
205 MACH3LOG_DEBUG(" - Matched tag {} !", tag);
206 tagCount ++;
207 }
208 }
209
210 // now decide if we include the current value based on the check type
211 if ( checkType == "all" )
212 {
213 if ( tagCount == tags.size() ) retVec.push_back(val);
214 }
215 else if ( checkType == "any" )
216 {
217 if ( tagCount > 0 ) retVec.push_back(val);
218 }
219 else if ( checkType == "exect" )
220 {
221 // EM: note that this will break if duplicate tags are specified in either vector... so please don't do that
222 if ( tagCount == valTags.size() ) retVec.push_back(val);
223 }
224 }
225 MACH3LOG_DEBUG("Found {} values matching the specified tags", retVec.size());
226 return retVec;
227}
228
229std::vector<std::string> InputManager::parseLocation(const std::string &rawLocationString, std::string &fitter,
230 fileTypeEnum fileType, const std::string &parameter,
231 const std::string &sample, const std::string &parameter2) const {
232 std::string locationString(rawLocationString);
233 std::vector<std::string> tokens;
234
235 std::size_t pos = 0;
236 std::string toReplace = "";
237
238 // loop through the raw location string and replace any instance of {PARAMETER} with the name of
239 // the parameter
240 toReplace = "{PARAMETER}";
241 while ((pos = locationString.find(toReplace)) != std::string::npos)
242 {
243 locationString.replace(pos, toReplace.length(),
244 getFitterSpecificParamName(fitter, fileType, parameter));
245 }
246
247 // same again with {SAMPLE}
248 toReplace = "{SAMPLE}";
249 while ((pos = locationString.find(toReplace)) != std::string::npos)
250 {
251 locationString.replace(pos, toReplace.length(),
252 getFitterSpecificSampleName(fitter, fileType, sample));
253 }
254
255 // loop through the raw location string and replace any instance of {PARAMETER2} with the name of
256 // the second specified parameter
257 toReplace = "{PARAMETER2}";
258 while ((pos = locationString.find(toReplace)) != std::string::npos)
259 {
260 locationString.replace(pos, toReplace.length(),
261 getFitterSpecificParamName(fitter, fileType, parameter2));
262 }
263
264 // Now we go through and look for ":" and split the location into two parts
265 // first part should be the directory to look for the parameter
266 // lats part should be the end of the name of the object to look for
267 std::string token;
268 std::string delimiter = ":";
269 while ((pos = locationString.find(delimiter)) != std::string::npos)
270 {
271 token = locationString.substr(0, pos);
272 tokens.push_back(token);
273 locationString.erase(0, pos + delimiter.length());
274 }
275 tokens.push_back(locationString);
276
277 // should only have found 2 parts, anything more means there was too many
278 // ":" in the location string
279 if (tokens.size() > 2)
280 {
281 throw MaCh3Exception(__FILE__ , __LINE__, "Too many : tokens in location string: " + rawLocationString);
282 }
283
284 return tokens;
285}
286
287std::shared_ptr<TObject> InputManager::findRootObject(const InputFile &fileDef,
288 const std::vector<std::string> &locationVec) const {
289 std::shared_ptr<TObject> object = nullptr;
290
291 // if vector only has one element, just interpret it as the absolute path to the object
292 if (locationVec.size() == 1)
293 {
294 object = std::shared_ptr<TObject>(fileDef.file->Get(locationVec[0].c_str()));
295 }
296
297 // if vector has two elements, interpret the first as the directory and the second as a string to
298 // match with the end of the objects in the file
299 else if (locationVec.size() == 2)
300 {
301 TDirectoryFile *directory = fileDef.file->Get<TDirectoryFile>(locationVec[0].c_str());
302 size_t nMatchingObjects = 0;
303
304 // let's make sure that the directory itself exists
305 if (directory == nullptr)
306 {
307 object = nullptr;
308 }
309 else
310 {
311 // loop through the keys in the directory and find objects whose name matches the specified
312 // pattern
313 TIter next(directory->GetListOfKeys());
314 while (TKey *key = static_cast<TKey*>(next()))
315 {
316 if (strEndsWith(std::string(key->GetName()), locationVec[1]))
317 {
318 object = std::shared_ptr<TObject>(directory->Get(key->GetName()));
319 nMatchingObjects++;
320 }
321 }
322 }
323 // check that only one object matched the pattern
324 if (nMatchingObjects > 1)
325 {
326 MACH3LOG_CRITICAL("Too many objects match the pattern specified by {} {}", locationVec[0], locationVec.size()==2 ? locationVec[1] : "");
327 MACH3LOG_CRITICAL("Found {} matching objects, should just be one", nMatchingObjects);
328
329 throw MaCh3Exception(__FILE__ , __LINE__ );
330 }
331 }
332 else // Vector too big!!
333 {
334 MACH3LOG_CRITICAL("Invalid object location vector");
335 MACH3LOG_CRITICAL("Should have two elements: [ (directory to look in), (end of the name of the object) ]");
336 MACH3LOG_CRITICAL("Or one element that is just the absolute path to the object");
337
338 throw MaCh3Exception(__FILE__ , __LINE__ );
339 }
340 return object;
341}
342
343bool InputManager::findBySampleLLH(InputFile &inputFileDef, const std::string &parameter,
344 std::string &fitter, const std::string &sample, bool setInputFileScan) {
345 YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
346
347 // EM: Get where the by sample LLH scan for this parameter *should* live if it exists
348 YAML::Node testLLHConfig = thisFitterSpec_config["bySample_LLH"];
349 std::vector<std::string> testLLHRawLocations =
350 testLLHConfig["location"].as<std::vector<std::string>>();
351
352 std::string LLHObjType = thisFitterSpec_config["LLHObjectType"].as<std::string>();
353
354 // EM: Now look for the parameter in this folder
355 std::shared_ptr<TObject> LLHObj = nullptr;
356 for (std::string rawLocation : testLLHRawLocations)
357 {
358 LLHObj =
359 findRootObject(inputFileDef, parseLocation(rawLocation, fitter, kLLH, parameter, sample));
360 if (LLHObj != nullptr)
361 {
362 break;
363 }
364 }
365
366 // EM: If it's not in there we can return here
367 if (LLHObj == nullptr)
368 return false;
369
370 // EM: If specified, we set the object in the InputFile object
371 if (setInputFileScan)
372 {
373 std::shared_ptr<TGraph> LLHGraph = std::make_shared<TGraph>();
374
375 if (LLHObjType == "TH1D")
376 {
377 LLHGraph = std::make_shared<TGraph>(static_cast<TH1D*>(LLHObj.get()));
378 } else if (LLHObjType == "TGraph")
379 {
380 LLHGraph = std::shared_ptr<TGraph>(static_cast<TGraph*>(LLHObj->Clone()));
381 } else
382 {
383 throw MaCh3Exception(__FILE__ , __LINE__, "uknown type of LLH object specified: " + LLHObjType);
384 }
385
386 inputFileDef.LLHScansBySample_map[sample][parameter] = LLHGraph;
387 }
388 return true;
389}
390
391// check the input file for raw MCMC step values for a particular parameter
392bool InputManager::findRawChainSteps(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, bool setInputBranch) const {
393 // we'll assume for now that the chain is in the form of a TTree and the branch names are parameter names
394 bool wasFound = false;
395
396 // make sure that the filedef object has all the necessary stuff to read from the posterior tree
397 if ( (inputFileDef.mcmcProc != nullptr) && (inputFileDef.posteriorTree != nullptr) )
398 {
399 const std::vector<TString> branchNames = inputFileDef.mcmcProc->GetBranchNames();
400
401 std::string specificName = getFitterSpecificParamName(fitter, kMCMC, parameter);
402
403 // loop over possible parameters and compare names
404 for ( int paramIdx = 0; paramIdx < inputFileDef.mcmcProc->GetNParams() -1 ; paramIdx ++ )
405 {
406 TString title;
407 double prior, priorError; // <- will be discarded
408 inputFileDef.mcmcProc->GetNthParameter(paramIdx, prior, priorError, title);
409
410 if ( strEndsWith(title.Data(), specificName) )
411 {
412 wasFound = true;
413 if ( setInputBranch )
414 {
415 // EM: should probably use MCMCProcessor for this so we can use caching, gpu etc.
416 inputFileDef.MCMCstepParamsMap[parameter] = new double( M3::_BAD_DOUBLE_ ); // <- initialise the parameter step values
417 inputFileDef.posteriorTree->SetBranchAddress( branchNames[paramIdx], inputFileDef.MCMCstepParamsMap.at(parameter) );
418 }
419 break;
420 }
421 }
422 }
423 return wasFound;
424}
425
426// check the input file for processed 1d posteriors for a particular parameter
427bool InputManager::find1dPosterior(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, bool setFileData) const {
428 bool wasFound = false;
429
430 YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
431
432 if ( thisFitterSpec_config["1dPosteriors"] ) {
433 std::vector<std::string> rawLocations = thisFitterSpec_config["1dPosteriors"]["location"].as<std::vector<std::string>>();
434
435 for ( const std::string &rawLoc : rawLocations)
436 {
437 std::shared_ptr<TH1D> posterior1d = std::static_pointer_cast<TH1D>(findRootObject(inputFileDef, parseLocation(rawLoc, fitter, kMCMC, parameter)));
438
439 if ( posterior1d != nullptr )
440 {
441 wasFound = true;
442
443 if ( setFileData )
444 {
445 inputFileDef.posteriors1d_map[parameter] = std::make_shared<TGraph>(posterior1d.get());
446 }
447 break;
448 }
449 }
450 }
451 return wasFound;
452}
453
454bool InputManager::findPostFitParamError(InputFile &inputFileDef, const std::string &parameter,
455 std::string &fitter, const std::string &errorType,
456 bool setInputFileError) {
457 std::string specificName = getFitterSpecificParamName(fitter, kPostFit, parameter);
458 YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
459
460 // EM: Get which hist this parameter lives in from the config
461 YAML::Node postFitErrorTypes = thisFitterSpec_config["postFitErrorTypes"];
462 YAML::Node specificErrorType = postFitErrorTypes[errorType];
463 std::vector<std::string> postFitLocations =
464 specificErrorType["location"].as<std::vector<std::string>>();
465
466 // EM: If the parameter has a specified list of locations then override the default one
467 std::vector<std::string> postFitLocations_override;
468 if (getFitterSpecificParamOption<std::vector<std::string>>(fitter, "postFitLoc",
469 postFitLocations_override, parameter))
470 {
471 postFitLocations = postFitLocations_override;
472 }
473
474 for (std::string postFitLoc : postFitLocations)
475 {
476 std::shared_ptr<TH1D> postFitErrors = std::static_pointer_cast<TH1D>(findRootObject(inputFileDef, parseLocation(postFitLoc, fitter, kPostFit, parameter)));
477
478 // EM: the postfit hist for this parameter isn't in this file
479 if (postFitErrors == nullptr)
480 continue;
481
482 // EM: Loop through the hist to see if it contains the parameter we're looking for
483 for (int binIdx = 0; binIdx <= postFitErrors->GetNbinsX(); binIdx++)
484 {
485 std::string binLabel = std::string(postFitErrors->GetXaxis()->GetBinLabel(binIdx));
486 if (strEndsWith(binLabel, specificName))
487 {
488 if (setInputFileError)
489 {
490 // EM: if specified, we fill the postfit error TH1D in the provided InputFile object
491 inputFileDef.postFitErrors[errorType][parameter] = postFitErrors->GetBinError(binIdx);
492 inputFileDef.postFitValues[errorType][parameter] = postFitErrors->GetBinContent(binIdx);
493 }
494
495 return true;
496 }
497 }
498 }
499 // EM: Didn't find the parameter in any of the specified locations
500 return false;
501}
502
503// EM: Lots of room for improvement in fillFileInfo and fillFileData, should be split up into more
504// methods, currently a lot of copy pasting
505void InputManager::fillFileInfo(InputFile &inputFileDef, bool printThoughts) {
510
511 // use the contents of the file to decide which fitter it came from and what type of file it is
512 if (printThoughts)
513 MACH3LOG_INFO("Checking contents of file {}", inputFileDef.fileName);
514
515 for (std::string fitter: _knownFitters)
516 {
517 // flag for whether or not the current fitter is the correct one
518 bool foundFitter = false;
519 if (printThoughts)
520 MACH3LOG_INFO("Checking if this is a {} file", fitter);
521
522 // EM: get the configuration specifying what the output of this fitter looks like
523 if (!_fitterSpecConfig[fitter])
524 {
525 throw MaCh3Exception(__FILE__ , __LINE__, "translation config doesnt contain a definition for fitter " + fitter);
526 }
527
528 YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
529
530 size_t numLLHParams;
531
532 // ##### Look for LLH scans in the input #####
533 // check for all 3 LLH directory types
534 for (std::string LLHType : {"sample", "penalty", "total"})
535 {
536 if (printThoughts)
537 MACH3LOG_INFO(".... searching for {} LLH scans... ", LLHType);
538
539 // vector of all the possible locations that we might find LLH scans for this type of LLH
540 YAML::Node testLLHConfig = thisFitterSpec_config[LLHType + "_LLH"];
541 std::vector<std::string> testLLHRawLocations =
542 testLLHConfig["location"].as<std::vector<std::string>>();
543
544 // counter for the total number of parameters we find scans for
545 numLLHParams = 0;
546
547 std::vector<std::string> enabledLLHParams;
548
549 for (const std::string &parameter : _knownParameters)
550 {
551 MACH3LOG_DEBUG(" - for {}", parameter);
552 inputFileDef.availableParams_map_LLH[LLHType][parameter] = false;
553
554 // check if we find the parameter at any of the locations we think it should be at
555 for (const std::string &rawLocation : testLLHRawLocations)
556 {
557 if (findRootObject(inputFileDef, parseLocation(rawLocation, fitter, kLLH, parameter)) !=
558 nullptr)
559 {
560 numLLHParams++;
561 enabledLLHParams.push_back(parameter);
562 inputFileDef.availableParams_map_LLH[LLHType][parameter] = true;
563 MACH3LOG_DEBUG(" FOUND!");
564 break; // <- we've found it, no point checking the rest of the locations
565 }
566 }
567 }
568
569 if (printThoughts)
570 MACH3LOG_INFO(".... Found {}\n", numLLHParams);
571
572 if (numLLHParams > 0)
573 {
574 foundFitter = true;
575 inputFileDef.hasLLHScans = true;
576 inputFileDef.availableParams_LLH = enabledLLHParams;
577 inputFileDef.hasLLHScans_map[LLHType] = true;
578 }
579
582 }
583
584 if (printThoughts)
585 MACH3LOG_INFO("");
586
587 // ##### now look for processed post fit errors #####
588 if (printThoughts)
589 {
590 MACH3LOG_INFO("....searching for Post Fit Parameters");
591
592 if (thisFitterSpec_config["defaultPostFitErrorType"])
593 {
594 MACH3LOG_DEBUG(" Default type specified with possible locations: ");
595 YAML::Node postFitErrorSpec = thisFitterSpec_config["postFitErrorTypes"];
596 YAML::Node defaultErrorType =
597 postFitErrorSpec[thisFitterSpec_config["defaultPostFitErrorType"].as<std::string>()];
598 std::vector<std::string> locations = defaultErrorType["location"].as<std::vector<std::string>>();
599 for (std::string loc : locations)
600 MACH3LOG_DEBUG(loc);
601 }
602 else
603 {
604 MACH3LOG_DEBUG(" No default location specified");
605 }
606 }
607
608 int numPostFitParams = 0;
609 std::vector<std::string> enabledPostFitParams;
610
611 std::string defaultErrorType =
612 thisFitterSpec_config["defaultPostFitErrorType"].as<std::string>();
613 for (std::string parameter : _knownParameters)
614 {
615 if (findPostFitParamError(inputFileDef, parameter, fitter, defaultErrorType))
616 {
617 numPostFitParams++;
618 enabledPostFitParams.push_back(parameter);
619 }
620 }
621
622 if (printThoughts)
623 MACH3LOG_INFO(".... Found {}\n", numPostFitParams);
624
625 if (numPostFitParams > 0)
626 {
627 foundFitter = true;
628 inputFileDef.hasPostFitErrors = true;
629 inputFileDef.availableParams_postFitErrors = enabledPostFitParams;
630 }
631
632 // ######### Now look for LLH scans broken down by sample #########
633 // This is really just a check to see if the number of by sample LLH scans is the same as normal
634 // LLH scans
635 if (printThoughts)
636 MACH3LOG_INFO("....Searching for LLH scans broken down by sample");
637
638 for (const std::string &sample : _knownSamples)
639 {
640 size_t numLLHBySampleParams = 0;
641 for (const std::string &parameter : _knownParameters)
642 {
643 inputFileDef.availableParams_map_LLHBySample[sample][parameter] = false;
644 if (findBySampleLLH(inputFileDef, parameter, fitter, sample))
645 {
646 inputFileDef.availableParams_map_LLHBySample[sample][parameter] = true;
647 numLLHBySampleParams++;
648 }
649 }
650
651 if (numLLHBySampleParams != 0)
652 {
653 inputFileDef.availableSamples_LLH.push_back(sample);
654
655 if (printThoughts)
656 MACH3LOG_INFO("........ Found {} LLH scans for sample {}", numLLHBySampleParams, sample);
657
658 if ((numLLHParams != numLLHBySampleParams))
659 {
660 MACH3LOG_ERROR("hmmmmm something weird is happening here");
661 MACH3LOG_ERROR(" I have {} LLH scans for sample {}", numLLHBySampleParams, sample);
662 MACH3LOG_ERROR(" But {} parameters with Total_LLH scals", numLLHParams);
663 }
664 }
665 }
666
667 // ######### Now for the main event: Look for MCMC chains and processed posteriors ###########
668
669 // EM: if "MCMCsteps" was defined for this fitter, we assume that it is a MaCh3 raw MCMC file
670 // thus it needs an MCMCProcessor to read from it. This isn't super general and it would probably
671 // be good to have some additional "isMaCh3" option that can decide whether or not to use MCMCProcessor
672 // but hey ho it's good enough for now
673 if ( thisFitterSpec_config["MCMCsteps"] )
674 {
675 MACH3LOG_DEBUG("Initialising MCMCProcessor for the input file");
676 std::vector<std::string> posteriorTreeRawLocations = thisFitterSpec_config["MCMCsteps"]["location"].as<std::vector<std::string>>();
677
678 TTree *postTree = nullptr;
679 for ( const std::string &rawLoc: posteriorTreeRawLocations )
680 {
681 MACH3LOG_DEBUG(" - Looking for MCMC chain parameter values at: {}", rawLoc);
682
683 postTree = inputFileDef.file->Get<TTree>(rawLoc.c_str());
684
685 if ( postTree != nullptr )
686 {
687 inputFileDef.mcmcProc = new MCMCProcessor(inputFileDef.fileName);
688 inputFileDef.mcmcProc->Initialise();
689
690 MACH3LOG_DEBUG(" - FOUND!");
691 break;
692 }
693 }
694
695 if ( postTree != nullptr )
696 {
697 inputFileDef.posteriorTree = postTree;
698 inputFileDef.nMCMCentries = int(postTree->GetEntries());
699 }
700 }
701
702 if (printThoughts)
703 {
704 MACH3LOG_INFO("....Searching for MCMC related things");
705 }
706
707 size_t num1dPosteriors = 0;
708 std::vector<std::string> enabled1dPosteriorParams;
709
710 size_t numMCMCchainParams = 0;
711 std::vector<std::string> enabledMCMCchainParams;
712
713 for ( const std::string &parameter : _knownParameters )
714 {
715 MACH3LOG_DEBUG(" - for {}", parameter);
716 // check for 1d post processing posterior.q
717 inputFileDef.availableParams_map_1dPosteriors[parameter] = false;
718 if ( thisFitterSpec_config["1dPosteriors"] && find1dPosterior(inputFileDef, parameter, fitter) )
719 {
720 MACH3LOG_DEBUG(" Found 1d processed posterior!");
721 enabled1dPosteriorParams.push_back(parameter);
722 num1dPosteriors++;
723 inputFileDef.availableParams_map_1dPosteriors[parameter] = true;
724 }
725 // now check for parameters in chain
726 inputFileDef.availableParams_map_MCMCchain[parameter] = false;
727 if ( thisFitterSpec_config["MCMCsteps"] && findRawChainSteps(inputFileDef, parameter, fitter) )
728 {
729 MACH3LOG_DEBUG(" Found raw MCMC steps!");
730 enabledMCMCchainParams.push_back(parameter);
731 numMCMCchainParams++;
732 inputFileDef.availableParams_map_MCMCchain[parameter] = true;
733 }
734 }
735
736 if (num1dPosteriors > 0 )
737 {
738 foundFitter = true;
739 inputFileDef.has1dPosteriors = true;
740 inputFileDef.availableParams_1dPosteriors = enabled1dPosteriorParams;
741
742 if (printThoughts)
743 MACH3LOG_INFO("........ Found {} 1d processed posteriors", num1dPosteriors);
744 }
745 if ( numMCMCchainParams > 0 )
746 {
747 foundFitter = true;
748 inputFileDef.hasMCMCchain = true;
749 inputFileDef.availableParams_MCMCchain = enabledMCMCchainParams;
750
751 if (printThoughts)
752 MACH3LOG_INFO("........ Found {} parameters in MCMC chain", numMCMCchainParams);
753 }
754
755 /*
756 switch (i) {
757 // any other weird fitter specific conditions/ edge cases should go in here
758 }
759 */
760
761 if (foundFitter)
762 {
763 if (printThoughts)
764 {
765 MACH3LOG_INFO("This is a {} file!\n", fitter);
766 }
767 inputFileDef.fitter = fitter;
768 return;
769 }
770 }
771
772 // if we didn't return above then the fitter type wasn't found
773 if (printThoughts)
774 MACH3LOG_WARN("I don't know what kinda fitter this came from, will proceed with caution");
775 inputFileDef.fitter = "UNKNOWN_FITTER";
776}
777
778void InputManager::fillFileData(InputFile &inputFileDef, bool printThoughts) {
779 // load in the data in the file using the info gotten above
780 // EM: a lot of this is copy paste from above, could be better organised
781 if (printThoughts)
782 MACH3LOG_INFO("....getting data from file {}", inputFileDef.fileName);
783
784 YAML::Node thisFitterSpec_config = _fitterSpecConfig[inputFileDef.fitter];
785
786 // set the default post fit error type so we can read it as default later
787 inputFileDef.defaultErrorType =
788 thisFitterSpec_config["defaultPostFitErrorType"].as<std::string>();
789
790 // ########### First fill up the LLH vectors ############
791 for (const std::string LLHType : {"sample", "penalty", "total"})
792 {
793 if (!inputFileDef.hasLLHScans_map.at(LLHType))
794 continue;
795
796 // vector of all the possible locations that we might find LLH scans for this type of LLH
797 YAML::Node testLLHConfig = thisFitterSpec_config[LLHType + "_LLH"];
798 const std::vector<std::string> testLLHRawLocations =
799 testLLHConfig["location"].as<std::vector<std::string>>();
800
801 // get the expected root object type of the llh scans
802 std::string LLHObjType = thisFitterSpec_config["LLHObjectType"].as<std::string>();
803
804 // EM: now get the objects from the file
805 for (const std::string &parameter : inputFileDef.availableParams_LLH)
806 {
807 std::shared_ptr<TObject> LLHObj = nullptr;
808
809 // check the locations for the object
810 for (const std::string &rawLocation : testLLHRawLocations)
811 {
812 LLHObj = findRootObject(inputFileDef,
813 parseLocation(rawLocation, inputFileDef.fitter, kLLH, parameter));
814 // if we found it then break out of the loop
815 if (LLHObj != nullptr)
816 break;
817 }
818
819 // double check that we actually found it.. just in case
820 if (LLHObj == nullptr)
821 {
822 MACH3LOG_ERROR("Hmmm, something seems to have gone wrong and I couldnt find the {} LLH scan for {} when attempting to read the data for it", LLHType, parameter);
823 MACH3LOG_ERROR("This will very likely cause segfaults and sadness");
824 }
825
826 // now convert it to a TGraph
827 std::shared_ptr<TGraph> LLHGraph = std::make_shared<TGraph>();
828
829 // EM: maybe have the type of the LLH object specified in the config to know what to downcast
830 // it to??
831 if (LLHObjType == "TH1D")
832 {
833 LLHGraph = std::make_shared<TGraph>(static_cast<TH1D*>(LLHObj.get()));
834 }
835
836 else if (LLHObjType == "TGraph")
837 {
838 LLHGraph = std::shared_ptr<TGraph>(static_cast<TGraph*>(LLHObj->Clone()));
839 }
840
841 else
842 {
843 MACH3LOG_CRITICAL("ERROR: uknown type of LLH object specified: {}", LLHObjType);
844 throw MaCh3Exception(__FILE__ , __LINE__ );
845 }
846
847 inputFileDef.LLHScans_map[LLHType][parameter] = LLHGraph;
848 }
849 }
850
851 // ####### Get the by sample LLH scans #######
852 for (const std::string &parameter : inputFileDef.availableParams_LLH)
853 {
854 for (const std::string &sample : _knownSamples)
855 {
856 findBySampleLLH(inputFileDef, parameter, inputFileDef.fitter, sample, true);
857 }
858 }
859
860 // ####### Get the processed post fit errors #######
861 for (const std::string &parameter : inputFileDef.availableParams_postFitErrors)
862 {
863 std::vector<std::string> availableErrorTypes =
864 thisFitterSpec_config["AvailablePostFitErrorTypes"].as<std::vector<std::string>>();
865 for (const std::string &errorType : availableErrorTypes)
866 {
867 findPostFitParamError(inputFileDef, parameter, inputFileDef.fitter, errorType, true);
868 }
869 }
870
871 // ########## Get the MCMC related posteriors ###########
872 for (const std::string &parameter : inputFileDef.availableParams_MCMCchain)
873 {
874 findRawChainSteps(inputFileDef, parameter, inputFileDef.fitter, true);
875 }
876 for (const std::string &parameter : inputFileDef.availableParams_1dPosteriors)
877 {
878 find1dPosterior(inputFileDef, parameter, inputFileDef.fitter, true);
879 }
880}
881} // namespace MaCh3Plotting
#define MACH3LOG_CRITICAL
Definition: MaCh3Logger.h:26
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:22
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:25
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:23
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:24
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:560
Class responsible for processing MCMC chains, performing diagnostics, generating plots,...
Definition: MCMCProcessor.h:65
void GetNthParameter(const int param, double &Prior, double &PriorError, TString &Title) const
Get properties of parameter by passing it number.
void Initialise()
Scan chain, what parameters we have and load information from covariance matrices.
const std::vector< TString > & GetBranchNames() const
Get the vector of branch names from root file.
int GetNParams()
Get total number of used parameters.
Custom exception class for MaCh3 errors.
double getPostFitError(int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit error for a particular parameter from a particular input file.
std::vector< std::string > parseLocation(const std::string &locationString, std::string &fitter, fileTypeEnum fileType, const std::string &parameter="", const std::string &sample="", const std::string &parameter2="") const
std::unordered_map< std::string, std::vector< std::string > > _paramToTagsMap
Definition: inputManager.h:654
std::vector< InputFile > _fileVec
Definition: inputManager.h:666
InputFile const & getFile(int fileId) const
Definition: inputManager.h:498
void fillFileData(InputFile &inputFileDef, bool printThoughts=true)
std::vector< std::string > _knownParameters
Definition: inputManager.h:644
InputManager(const std::string &translationConfigName)
Construct a new InputManager using specified fitter translation config file.
Definition: inputManager.cpp:6
bool find1dPosterior(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, bool setFileData=false) const
std::vector< std::string > getTaggedValues(const std::vector< std::string > &values, const std::unordered_map< std::string, std::vector< std::string > > &tagMap, const std::vector< std::string > &tags, std::string checkType) const
std::shared_ptr< TObject > findRootObject(const InputFile &fileDef, const std::vector< std::string > &locationVec) const
std::vector< std::string > _knownFitters
Definition: inputManager.h:651
void addFile(const std::string &fileName)
Add a new InputFile object to this input manager.
bool getFitterSpecificParamOption(const std::string &fitter, const std::string &option, T &ret, const std::string &parameter) const
Definition: inputManager.h:593
bool strEndsWith(const std::string &str, const std::string &ending) const
Definition: inputManager.h:634
std::string getFitterSpecificParamName(const std::string &fitter, fileTypeEnum fileType, const std::string &parameter) const
Definition: inputManager.h:607
void fillFileInfo(InputFile &inputFileDef, bool printThoughts=true)
bool findPostFitParamError(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, const std::string &errorType, bool setInputFileError=false)
bool findRawChainSteps(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, bool setInputBranch=false) const
std::vector< std::string > _knownSamples
Definition: inputManager.h:648
std::string getFitterSpecificSampleName(const std::string &fitter, fileTypeEnum fileType, const std::string &sample) const
Definition: inputManager.h:621
double getPostFitValue(int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit value for a particular parameter from a particular input file.
std::unordered_map< std::string, std::vector< std::string > > _sampleToTagsMap
Definition: inputManager.h:656
bool findBySampleLLH(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, const std::string &sample, bool setInputFileScan=false)
void print(const std::string &printLevel="summary") const
Print out what this Inputmanager instance knows about.
static constexpr const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:43
fileTypeEnum
Types of possible file that can be read.
Definition: inputManager.h:16
@ kPostFit
Processed post fit errors.
Definition: inputManager.h:18
@ kLLH
Log Likelihood scan.
Definition: inputManager.h:17
@ kMCMC
MCMC chain.
Definition: inputManager.h:19
Struct which wraps around the actual input file and also holds general information,...
Definition: inputManager.h:35
std::string fileName
The location of the underlying file.
Definition: inputManager.h:112
std::shared_ptr< TFile > file
Pointer to the underlying file for this InputFile instance.
Definition: inputManager.h:111
std::unordered_map< std::string, bool > hasLLHScans_map
Definition: inputManager.h:128
std::unordered_map< std::string, std::unordered_map< std::string, bool > > availableParams_map_LLH
Definition: inputManager.h:134
std::vector< std::string > availableParams_LLH
The parameters that this file contains likelihood scans for.
Definition: inputManager.h:126
std::unordered_map< std::string, bool > availableParams_map_MCMCchain
whether or not specific parameters exist in the MCMC posterior chain
Definition: inputManager.h:176
std::string defaultErrorType
Definition: inputManager.h:164
std::unordered_map< std::string, std::unordered_map< std::string, std::shared_ptr< TGraph > > > LLHScans_map
Definition: inputManager.h:131
std::string fitter
Which fitter this file came from, detected by InputManager::fillFileInfo().
Definition: inputManager.h:114
bool hasLLHScans
Whether or not this file contains any log likelihood scans.
Definition: inputManager.h:124
bool has1dPosteriors
Whether or not the file has processed 1d posteriors.
Definition: inputManager.h:168
MCMCProcessor * mcmcProc
ptr to an MCMCProcessor instance to be used if this is a MaCh3 input file
Definition: inputManager.h:108
std::unordered_map< std::string, std::shared_ptr< TGraph > > posteriors1d_map
Definition: inputManager.h:185
std::unordered_map< std::string, std::unordered_map< std::string, double > > postFitErrors
Definition: inputManager.h:159
std::vector< std::string > availableParams_MCMCchain
Definition: inputManager.h:180
std::unordered_map< std::string, bool > availableParams_map_1dPosteriors
Definition: inputManager.h:177
std::unordered_map< std::string, std::unordered_map< std::string, double > > postFitValues
Definition: inputManager.h:162
std::unordered_map< std::string, std::unordered_map< std::string, std::shared_ptr< TGraph > > > LLHScansBySample_map
Definition: inputManager.h:147
bool hasPostFitErrors
Whether or not this file contains any processed post fit errors.
Definition: inputManager.h:155
std::vector< std::string > availableParams_postFitErrors
The parameters that this file has post fit errors for.
Definition: inputManager.h:157
std::unordered_map< std::string, std::unordered_map< std::string, bool > > availableParams_map_LLHBySample
Definition: inputManager.h:150
std::unordered_map< std::string, double * > MCMCstepParamsMap
Definition: inputManager.h:182
bool hasMCMCchain
Whether or not the file has unprocessed MCMC chain steps.
Definition: inputManager.h:170
int nMCMCentries
The number of steps in the MCMC chain.
Definition: inputManager.h:173
std::vector< std::string > availableSamples_LLH
Definition: inputManager.h:144
std::vector< std::string > availableParams_1dPosteriors
Definition: inputManager.h:179