MaCh3  2.2.3
Reference Guide
inputManager.cpp
Go to the documentation of this file.
1 #include "inputManager.h"
2 
3 
4 namespace MaCh3Plotting {
5 // this is the constructor with user specified translation config file
6 InputManager::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
13  _fitterSpecConfig = _translatorConfig["FitterSpec"];
14  _parametersConfig = _translatorConfig["Parameters"];
15  _samplesConfig = _translatorConfig["Samples"];
16 
17  // check the config file and get which parameters, samples, and fitters we've been told about
18  _knownFitters = Get<std::vector<std::string>>(_fitterSpecConfig["fitters"], __FILE__, __LINE__);
19  _knownParameters = Get<std::vector<std::string>>(_parametersConfig["Parameters"], __FILE__, __LINE__);
20  _knownSamples = Get<std::vector<std::string>>(_samplesConfig["Samples"], __FILE__, __LINE__);
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 = Get<std::vector<std::string>>(_parametersConfig[param]["tags"], __FILE__, __LINE__);
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 = Get<std::vector<std::string>>(_samplesConfig[samp]["tags"], __FILE__, __LINE__);
54  MACH3LOG_DEBUG(" - Found {}!", tags.size());
55  }
56  }
57  _sampleToTagsMap[samp] = tags;
58  }
59 }
60 
69 void 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 
82 void 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 
109 double InputManager::getPostFitError(const 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 find {} post fit error for {}. Returning {}", errorType, paramName, M3::_BAD_DOUBLE_);
133 
134  return M3::_BAD_DOUBLE_;
135 }
136 
137 double InputManager::getPostFitValue(const 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 find {} 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 
170 std::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 == "exact" )
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 
229 std::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 
287 std::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 
343 bool 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  auto testLLHRawLocations = Get<std::vector<std::string>>(testLLHConfig["location"], __FILE__, __LINE__);
350 
351  auto LLHObjType = Get<std::string>(thisFitterSpec_config["LLHObjectType"], __FILE__, __LINE__);
352  // EM: Now look for the parameter in this folder
353  std::shared_ptr<TObject> LLHObj = nullptr;
354  for (std::string rawLocation : testLLHRawLocations)
355  {
356  LLHObj =
357  findRootObject(inputFileDef, parseLocation(rawLocation, fitter, kLLH, parameter, sample));
358  if (LLHObj != nullptr)
359  {
360  break;
361  }
362  }
363 
364  // EM: If it's not in there we can return here
365  if (LLHObj == nullptr)
366  return false;
367 
368  // EM: If specified, we set the object in the InputFile object
369  if (setInputFileScan)
370  {
371  std::shared_ptr<TGraph> LLHGraph = std::make_shared<TGraph>();
372 
373  if (LLHObjType == "TH1D")
374  {
375  LLHGraph = std::make_shared<TGraph>(static_cast<TH1D*>(LLHObj.get()));
376  } else if (LLHObjType == "TGraph")
377  {
378  LLHGraph = std::shared_ptr<TGraph>(static_cast<TGraph*>(LLHObj->Clone()));
379  } else
380  {
381  throw MaCh3Exception(__FILE__ , __LINE__, "uknown type of LLH object specified: " + LLHObjType);
382  }
383 
384  inputFileDef.LLHScansBySample_map[sample][parameter] = LLHGraph;
385  }
386  return true;
387 }
388 
389 // check the input file for raw MCMC step values for a particular parameter
390 bool InputManager::findRawChainSteps(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, bool setInputBranch) const {
391  // we'll assume for now that the chain is in the form of a TTree and the branch names are parameter names
392  bool wasFound = false;
393 
394  // make sure that the filedef object has all the necessary stuff to read from the posterior tree
395  if ( (inputFileDef.mcmcProc != nullptr) && (inputFileDef.posteriorTree != nullptr) )
396  {
397  const std::vector<TString> branchNames = inputFileDef.mcmcProc->GetBranchNames();
398 
399  std::string specificName = getFitterSpecificParamName(fitter, kMCMC, parameter);
400 
401  // loop over possible parameters and compare names
402  for ( int paramIdx = 0; paramIdx < inputFileDef.mcmcProc->GetNParams() -1 ; paramIdx ++ )
403  {
404  TString title;
405  double prior, priorError; // <- will be discarded
406  inputFileDef.mcmcProc->GetNthParameter(paramIdx, prior, priorError, title);
407 
408  if ( strEndsWith(title.Data(), specificName) )
409  {
410  wasFound = true;
411  if ( setInputBranch )
412  {
413  // EM: should probably use MCMCProcessor for this so we can use caching, gpu etc.
414  inputFileDef.MCMCstepParamsMap[parameter] = new double( M3::_BAD_DOUBLE_ ); // <- initialise the parameter step values
415  inputFileDef.posteriorTree->SetBranchAddress( branchNames[paramIdx], inputFileDef.MCMCstepParamsMap.at(parameter) );
416  }
417  break;
418  }
419  }
420  }
421  return wasFound;
422 }
423 
424 // check the input file for processed 1d posteriors for a particular parameter
425 bool InputManager::find1dPosterior(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, bool setFileData) const {
426  bool wasFound = false;
427 
428  YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
429 
430  if ( thisFitterSpec_config["1dPosteriors"] ) {
431  auto rawLocations = Get<std::vector<std::string>>(thisFitterSpec_config["1dPosteriors"]["location"],
432  __FILE__, __LINE__);
433  for ( const std::string &rawLoc : rawLocations)
434  {
435  std::shared_ptr<TH1D> posterior1d = std::static_pointer_cast<TH1D>(findRootObject(inputFileDef, parseLocation(rawLoc, fitter, kMCMC, parameter)));
436 
437  if ( posterior1d != nullptr )
438  {
439  wasFound = true;
440 
441  if ( setFileData )
442  {
443  inputFileDef.posteriors1d_map[parameter] = std::make_shared<TGraph>(posterior1d.get());
444  }
445  break;
446  }
447  }
448  }
449  return wasFound;
450 }
451 
452 bool InputManager::findPostFitParamError(InputFile &inputFileDef, const std::string &parameter,
453  std::string &fitter, const std::string &errorType,
454  const bool setInputFileError) {
455  std::string specificName = getFitterSpecificParamName(fitter, kPostFit, parameter);
456  YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
457 
458  // EM: Get which hist this parameter lives in from the config
459  YAML::Node postFitErrorTypes = thisFitterSpec_config["postFitErrorTypes"];
460  YAML::Node specificErrorType = postFitErrorTypes[errorType];
461  auto postFitLocations = Get<std::vector<std::string>>(specificErrorType["location"], __FILE__, __LINE__);
462 
463  // EM: If the parameter has a specified list of locations then override the default one
464  std::vector<std::string> postFitLocations_override;
465  if (getFitterSpecificParamOption<std::vector<std::string>>(fitter, "postFitLoc",
466  postFitLocations_override, parameter))
467  {
468  postFitLocations = postFitLocations_override;
469  }
470 
471  for (std::string postFitLoc : postFitLocations)
472  {
473  std::shared_ptr<TH1D> postFitErrors = std::static_pointer_cast<TH1D>(findRootObject(inputFileDef, parseLocation(postFitLoc, fitter, kPostFit, parameter)));
474 
475  // EM: the postfit hist for this parameter isn't in this file
476  if (postFitErrors == nullptr)
477  continue;
478 
479  // EM: Loop through the hist to see if it contains the parameter we're looking for
480  for (int binIdx = 0; binIdx <= postFitErrors->GetNbinsX(); binIdx++)
481  {
482  std::string binLabel = std::string(postFitErrors->GetXaxis()->GetBinLabel(binIdx));
483  if (strEndsWith(binLabel, specificName))
484  {
485  if (setInputFileError)
486  {
487  // EM: if specified, we fill the postfit error TH1D in the provided InputFile object
488  inputFileDef.postFitErrors[errorType][parameter] = postFitErrors->GetBinError(binIdx);
489  inputFileDef.postFitValues[errorType][parameter] = postFitErrors->GetBinContent(binIdx);
490  }
491 
492  return true;
493  }
494  }
495  }
496  // EM: Didn't find the parameter in any of the specified locations
497  return false;
498 }
499 
500 // EM: Lots of room for improvement in fillFileInfo and fillFileData, should be split up into more
501 // methods, currently a lot of copy pasting
502 void InputManager::fillFileInfo(InputFile &inputFileDef, const bool printThoughts) {
507 
508  // use the contents of the file to decide which fitter it came from and what type of file it is
509  if (printThoughts)
510  MACH3LOG_INFO("Checking contents of file {}", inputFileDef.fileName);
511 
512  for (std::string fitter: _knownFitters)
513  {
514  // flag for whether or not the current fitter is the correct one
515  bool foundFitter = false;
516  if (printThoughts)
517  MACH3LOG_INFO("Checking if this is a {} file", fitter);
518 
519  // EM: get the configuration specifying what the output of this fitter looks like
520  if (!_fitterSpecConfig[fitter])
521  {
522  throw MaCh3Exception(__FILE__ , __LINE__, "translation config doesnt contain a definition for fitter " + fitter);
523  }
524 
525  YAML::Node thisFitterSpec_config = _fitterSpecConfig[fitter];
526 
527  size_t numLLHParams;
528 
529  // ##### Look for LLH scans in the input #####
530  // check for all 3 LLH directory types
531  for (std::string LLHType : {"sample", "penalty", "total"})
532  {
533  if (printThoughts)
534  MACH3LOG_INFO(".... searching for {} LLH scans... ", LLHType);
535 
536  // vector of all the possible locations that we might find LLH scans for this type of LLH
537  YAML::Node testLLHConfig = thisFitterSpec_config[LLHType + "_LLH"];
538  auto testLLHRawLocations = Get<std::vector<std::string>>(testLLHConfig["location"], __FILE__, __LINE__);
539 
540  // counter for the total number of parameters we find scans for
541  numLLHParams = 0;
542 
543  std::vector<std::string> enabledLLHParams;
544 
545  for (const std::string &parameter : _knownParameters)
546  {
547  MACH3LOG_DEBUG(" - for {}", parameter);
548  inputFileDef.availableParams_map_LLH[LLHType][parameter] = false;
549 
550  // check if we find the parameter at any of the locations we think it should be at
551  for (const std::string &rawLocation : testLLHRawLocations)
552  {
553  if (findRootObject(inputFileDef, parseLocation(rawLocation, fitter, kLLH, parameter)) !=
554  nullptr)
555  {
556  numLLHParams++;
557  enabledLLHParams.push_back(parameter);
558  inputFileDef.availableParams_map_LLH[LLHType][parameter] = true;
559  MACH3LOG_DEBUG(" FOUND!");
560  break; // <- we've found it, no point checking the rest of the locations
561  }
562  }
563  }
564 
565  if (printThoughts)
566  MACH3LOG_INFO(".... Found {}", numLLHParams);
567 
568  if (numLLHParams > 0)
569  {
570  foundFitter = true;
571  inputFileDef.hasLLHScans = true;
572  inputFileDef.availableParams_LLH = enabledLLHParams;
573  inputFileDef.hasLLHScans_map[LLHType] = true;
574  }
575 
578  }
579 
580  if (printThoughts)
581  MACH3LOG_INFO("");
582 
583  // ##### now look for processed post fit errors #####
584  if (printThoughts)
585  {
586  MACH3LOG_INFO("....searching for Post Fit Parameters");
587 
588  if (thisFitterSpec_config["defaultPostFitErrorType"])
589  {
590  MACH3LOG_DEBUG(" Default type specified with possible locations: ");
591  YAML::Node postFitErrorSpec = thisFitterSpec_config["postFitErrorTypes"];
592  YAML::Node defaultErrorType =
593  postFitErrorSpec[thisFitterSpec_config["defaultPostFitErrorType"].as<std::string>()];
594  auto locations = Get<std::vector<std::string>>(defaultErrorType["location"], __FILE__, __LINE__);
595  for (std::string loc : locations)
596  MACH3LOG_DEBUG(loc);
597  }
598  else
599  {
600  MACH3LOG_DEBUG(" No default location specified");
601  }
602  }
603 
604  int numPostFitParams = 0;
605  std::vector<std::string> enabledPostFitParams;
606 
607  auto defaultErrorType =
608  Get<std::string>(thisFitterSpec_config["defaultPostFitErrorType"], __FILE__, __LINE__);
609  for (std::string parameter : _knownParameters)
610  {
611  if (findPostFitParamError(inputFileDef, parameter, fitter, defaultErrorType))
612  {
613  numPostFitParams++;
614  enabledPostFitParams.push_back(parameter);
615  }
616  }
617 
618  if (printThoughts)
619  MACH3LOG_INFO(".... Found {}", numPostFitParams);
620 
621  if (numPostFitParams > 0)
622  {
623  foundFitter = true;
624  inputFileDef.hasPostFitErrors = true;
625  inputFileDef.availableParams_postFitErrors = enabledPostFitParams;
626  }
627 
628  // ######### Now look for LLH scans broken down by sample #########
629  // This is really just a check to see if the number of by sample LLH scans is the same as normal
630  // LLH scans
631  if (printThoughts)
632  MACH3LOG_INFO("....Searching for LLH scans broken down by sample");
633 
634  for (const std::string &sample : _knownSamples)
635  {
636  size_t numLLHBySampleParams = 0;
637  for (const std::string &parameter : _knownParameters)
638  {
639  inputFileDef.availableParams_map_LLHBySample[sample][parameter] = false;
640  if (findBySampleLLH(inputFileDef, parameter, fitter, sample))
641  {
642  inputFileDef.availableParams_map_LLHBySample[sample][parameter] = true;
643  numLLHBySampleParams++;
644  }
645  }
646 
647  if (numLLHBySampleParams != 0)
648  {
649  inputFileDef.availableSamples_LLH.push_back(sample);
650 
651  if (printThoughts)
652  MACH3LOG_INFO("........ Found {} LLH scans for sample {}", numLLHBySampleParams, sample);
653 
654  if ((numLLHParams != numLLHBySampleParams))
655  {
656  MACH3LOG_ERROR("hmmmmm something weird is happening here");
657  MACH3LOG_ERROR(" I have {} LLH scans for sample {}", numLLHBySampleParams, sample);
658  MACH3LOG_ERROR(" But {} parameters with Total_LLH scals", numLLHParams);
659  }
660  }
661  }
662 
663  // ######### Now for the main event: Look for MCMC chains and processed posteriors ###########
664 
665  // EM: if "MCMCsteps" was defined for this fitter, we assume that it is a MaCh3 raw MCMC file
666  // thus it needs an MCMCProcessor to read from it. This isn't super general and it would probably
667  // be good to have some additional "isMaCh3" option that can decide whether or not to use MCMCProcessor
668  // but hey ho it's good enough for now
669  if ( thisFitterSpec_config["MCMCsteps"] )
670  {
671  MACH3LOG_DEBUG("Initialising MCMCProcessor for the input file");
672  auto posteriorTreeRawLocations =
673  Get<std::vector<std::string>>(thisFitterSpec_config["MCMCsteps"]["location"], __FILE__, __LINE__);
674 
675  TTree *postTree = nullptr;
676  for ( const std::string &rawLoc: posteriorTreeRawLocations )
677  {
678  MACH3LOG_DEBUG(" - Looking for MCMC chain parameter values at: {}", rawLoc);
679 
680  postTree = inputFileDef.file->Get<TTree>(rawLoc.c_str());
681 
682  if ( postTree != nullptr )
683  {
684  inputFileDef.mcmcProc = new MCMCProcessor(inputFileDef.fileName);
685  inputFileDef.mcmcProc->Initialise();
686 
687  MACH3LOG_DEBUG(" - FOUND!");
688  break;
689  }
690  }
691 
692  if ( postTree != nullptr )
693  {
694  inputFileDef.posteriorTree = postTree;
695  inputFileDef.nMCMCentries = int(postTree->GetEntries());
696  }
697  }
698 
699  if (printThoughts)
700  {
701  MACH3LOG_INFO("....Searching for MCMC related things");
702  }
703 
704  size_t num1dPosteriors = 0;
705  std::vector<std::string> enabled1dPosteriorParams;
706 
707  size_t numMCMCchainParams = 0;
708  std::vector<std::string> enabledMCMCchainParams;
709 
710  for ( const std::string &parameter : _knownParameters )
711  {
712  MACH3LOG_DEBUG(" - for {}", parameter);
713  // check for 1d post processing posterior.q
714  inputFileDef.availableParams_map_1dPosteriors[parameter] = false;
715  if ( thisFitterSpec_config["1dPosteriors"] && find1dPosterior(inputFileDef, parameter, fitter) )
716  {
717  MACH3LOG_DEBUG(" Found 1d processed posterior!");
718  enabled1dPosteriorParams.push_back(parameter);
719  num1dPosteriors++;
720  inputFileDef.availableParams_map_1dPosteriors[parameter] = true;
721  }
722  // now check for parameters in chain
723  inputFileDef.availableParams_map_MCMCchain[parameter] = false;
724  if ( thisFitterSpec_config["MCMCsteps"] && findRawChainSteps(inputFileDef, parameter, fitter) )
725  {
726  MACH3LOG_DEBUG(" Found raw MCMC steps!");
727  enabledMCMCchainParams.push_back(parameter);
728  numMCMCchainParams++;
729  inputFileDef.availableParams_map_MCMCchain[parameter] = true;
730  }
731  }
732 
733  if (num1dPosteriors > 0 )
734  {
735  foundFitter = true;
736  inputFileDef.has1dPosteriors = true;
737  inputFileDef.availableParams_1dPosteriors = enabled1dPosteriorParams;
738 
739  if (printThoughts)
740  MACH3LOG_INFO("........ Found {} 1d processed posteriors", num1dPosteriors);
741  }
742  if ( numMCMCchainParams > 0 )
743  {
744  foundFitter = true;
745  inputFileDef.hasMCMCchain = true;
746  inputFileDef.availableParams_MCMCchain = enabledMCMCchainParams;
747 
748  if (printThoughts)
749  MACH3LOG_INFO("........ Found {} parameters in MCMC chain", numMCMCchainParams);
750  }
751 
752  /*
753  switch (i) {
754  // any other weird fitter specific conditions/ edge cases should go in here
755  }
756  */
757 
758  if (foundFitter)
759  {
760  if (printThoughts)
761  {
762  MACH3LOG_INFO("This is a {} file!", fitter);
763  }
764  inputFileDef.fitter = fitter;
765  return;
766  }
767  }
768 
769  // if we didn't return above then the fitter type wasn't found
770  if (printThoughts)
771  MACH3LOG_WARN("I don't know what kinda fitter this came from, will proceed with caution");
772  inputFileDef.fitter = "UNKNOWN_FITTER";
773 }
774 
775 void InputManager::fillFileData(InputFile &inputFileDef, const bool printThoughts) {
776  // load in the data in the file using the info gotten above
777  // EM: a lot of this is copy paste from above, could be better organised
778  if (printThoughts)
779  MACH3LOG_INFO("....getting data from file {}", inputFileDef.fileName);
780 
781  YAML::Node thisFitterSpec_config = _fitterSpecConfig[inputFileDef.fitter];
782 
783  // set the default post fit error type so we can read it as default later
784  inputFileDef.defaultErrorType =
785  Get<std::string>(thisFitterSpec_config["defaultPostFitErrorType"], __FILE__, __LINE__);
786 
787  // ########### First fill up the LLH vectors ############
788  for (const std::string LLHType : {"sample", "penalty", "total"})
789  {
790  if (!inputFileDef.hasLLHScans_map.at(LLHType))
791  continue;
792 
793  // vector of all the possible locations that we might find LLH scans for this type of LLH
794  YAML::Node testLLHConfig = thisFitterSpec_config[LLHType + "_LLH"];
795  const std::vector<std::string> testLLHRawLocations =
796  Get<std::vector<std::string>>(testLLHConfig["location"], __FILE__, __LINE__);
797 
798  // get the expected root object type of the llh scans
799  auto LLHObjType = Get<std::string>(thisFitterSpec_config["LLHObjectType"], __FILE__, __LINE__);
800  // EM: now get the objects from the file
801  for (const std::string &parameter : inputFileDef.availableParams_LLH)
802  {
803  std::shared_ptr<TObject> LLHObj = nullptr;
804 
805  // check the locations for the object
806  for (const std::string &rawLocation : testLLHRawLocations)
807  {
808  LLHObj = findRootObject(inputFileDef,
809  parseLocation(rawLocation, inputFileDef.fitter, kLLH, parameter));
810  // if we found it then break out of the loop
811  if (LLHObj != nullptr)
812  break;
813  }
814 
815  // double check that we actually found it.. just in case
816  if (LLHObj == nullptr)
817  {
818  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);
819  MACH3LOG_ERROR("This will very likely cause segfaults and sadness");
820  }
821 
822  // now convert it to a TGraph
823  std::shared_ptr<TGraph> LLHGraph = std::make_shared<TGraph>();
824 
825  // EM: maybe have the type of the LLH object specified in the config to know what to downcast
826  // it to??
827  if (LLHObjType == "TH1D")
828  {
829  LLHGraph = std::make_shared<TGraph>(static_cast<TH1D*>(LLHObj.get()));
830  }
831 
832  else if (LLHObjType == "TGraph")
833  {
834  LLHGraph = std::shared_ptr<TGraph>(static_cast<TGraph*>(LLHObj->Clone()));
835  }
836 
837  else
838  {
839  MACH3LOG_CRITICAL("ERROR: uknown type of LLH object specified: {}", LLHObjType);
840  throw MaCh3Exception(__FILE__ , __LINE__ );
841  }
842 
843  inputFileDef.LLHScans_map[LLHType][parameter] = LLHGraph;
844  }
845  }
846 
847  // ####### Get the by sample LLH scans #######
848  for (const std::string &parameter : inputFileDef.availableParams_LLH)
849  {
850  for (const std::string &sample : _knownSamples)
851  {
852  findBySampleLLH(inputFileDef, parameter, inputFileDef.fitter, sample, true);
853  }
854  }
855 
856  // ####### Get the processed post fit errors #######
857  for (const std::string &parameter : inputFileDef.availableParams_postFitErrors)
858  {
859  auto availableErrorTypes = Get<std::vector<std::string>>(thisFitterSpec_config["AvailablePostFitErrorTypes"],
860  __FILE__, __LINE__);
861 
862  for (const std::string &errorType : availableErrorTypes)
863  {
864  findPostFitParamError(inputFileDef, parameter, inputFileDef.fitter, errorType, true);
865  }
866  }
867 
868  // ########## Get the MCMC related posteriors ###########
869  for (const std::string &parameter : inputFileDef.availableParams_MCMCchain)
870  {
871  findRawChainSteps(inputFileDef, parameter, inputFileDef.fitter, true);
872  }
873  for (const std::string &parameter : inputFileDef.availableParams_1dPosteriors)
874  {
875  find1dPosterior(inputFileDef, parameter, inputFileDef.fitter, true);
876  }
877 }
878 } // namespace MaCh3Plotting
#define MACH3LOG_CRITICAL
Definition: MaCh3Logger.h:28
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:24
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:27
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:25
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:26
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:561
Class responsible for processing MCMC chains, performing diagnostics, generating plots,...
Definition: MCMCProcessor.h:61
void GetNthParameter(const int param, double &Prior, double &PriorError, TString &Title) const
Get properties of parameter by passing it number.
const std::vector< TString > & GetBranchNames() const
Get the vector of branch names from root file.
void Initialise()
Scan chain, what parameters we have and load information from covariance matrices.
int GetNParams() const
Get total number of used parameters.
Custom exception class for MaCh3 errors.
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::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::unordered_map< std::string, std::vector< std::string > > _paramToTagsMap
Definition: inputManager.h:656
double getPostFitError(const int fileNum, const std::string &paramName, std::string errorType="") const
Get the post fit error for a particular parameter from a particular input file.
InputFile const & getFile(int fileId) const
Definition: inputManager.h:500
double getPostFitValue(const 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::vector< InputFile > _fileVec
Definition: inputManager.h:668
std::vector< std::string > _knownParameters
Definition: inputManager.h:646
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::shared_ptr< TObject > findRootObject(const InputFile &fileDef, const std::vector< std::string > &locationVec) const
std::vector< std::string > _knownFitters
Definition: inputManager.h:653
void fillFileInfo(InputFile &inputFileDef, const bool printThoughts=true)
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:595
bool strEndsWith(const std::string &str, const std::string &ending) const
Definition: inputManager.h:636
std::string getFitterSpecificParamName(const std::string &fitter, fileTypeEnum fileType, const std::string &parameter) const
Definition: inputManager.h:609
void fillFileData(InputFile &inputFileDef, const bool printThoughts=true)
bool findPostFitParamError(InputFile &inputFileDef, const std::string &parameter, std::string &fitter, const std::string &errorType, const 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:650
std::string getFitterSpecificSampleName(const std::string &fitter, fileTypeEnum fileType, const std::string &sample) const
Definition: inputManager.h:623
std::unordered_map< std::string, std::vector< std::string > > _sampleToTagsMap
Definition: inputManager.h:658
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.
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:46
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:116
std::shared_ptr< TFile > file
Pointer to the underlying file for this InputFile instance.
Definition: inputManager.h:115
std::unordered_map< std::string, bool > hasLLHScans_map
Definition: inputManager.h:132
std::unordered_map< std::string, std::unordered_map< std::string, bool > > availableParams_map_LLH
Definition: inputManager.h:138
std::vector< std::string > availableParams_LLH
The parameters that this file contains likelihood scans for.
Definition: inputManager.h:130
std::unordered_map< std::string, bool > availableParams_map_MCMCchain
whether or not specific parameters exist in the MCMC posterior chain
Definition: inputManager.h:180
std::string defaultErrorType
Definition: inputManager.h:168
std::unordered_map< std::string, std::unordered_map< std::string, std::shared_ptr< TGraph > > > LLHScans_map
Definition: inputManager.h:135
std::string fitter
Which fitter this file came from, detected by InputManager::fillFileInfo().
Definition: inputManager.h:118
bool hasLLHScans
Whether or not this file contains any log likelihood scans.
Definition: inputManager.h:128
bool has1dPosteriors
Whether or not the file has processed 1d posteriors.
Definition: inputManager.h:172
MCMCProcessor * mcmcProc
ptr to an MCMCProcessor instance to be used if this is a MaCh3 input file
Definition: inputManager.h:112
std::unordered_map< std::string, std::shared_ptr< TGraph > > posteriors1d_map
Definition: inputManager.h:189
std::unordered_map< std::string, std::unordered_map< std::string, double > > postFitErrors
Definition: inputManager.h:163
std::vector< std::string > availableParams_MCMCchain
Definition: inputManager.h:184
std::unordered_map< std::string, bool > availableParams_map_1dPosteriors
Definition: inputManager.h:181
std::unordered_map< std::string, std::unordered_map< std::string, double > > postFitValues
Definition: inputManager.h:166
std::unordered_map< std::string, std::unordered_map< std::string, std::shared_ptr< TGraph > > > LLHScansBySample_map
Definition: inputManager.h:151
bool hasPostFitErrors
Whether or not this file contains any processed post fit errors.
Definition: inputManager.h:159
std::vector< std::string > availableParams_postFitErrors
The parameters that this file has post fit errors for.
Definition: inputManager.h:161
std::unordered_map< std::string, std::unordered_map< std::string, bool > > availableParams_map_LLHBySample
Definition: inputManager.h:154
std::unordered_map< std::string, double * > MCMCstepParamsMap
Definition: inputManager.h:186
bool hasMCMCchain
Whether or not the file has unprocessed MCMC chain steps.
Definition: inputManager.h:174
int nMCMCentries
The number of steps in the MCMC chain.
Definition: inputManager.h:177
std::vector< std::string > availableSamples_LLH
Definition: inputManager.h:148
std::vector< std::string > availableParams_1dPosteriors
Definition: inputManager.h:183