MaCh3  2.2.3
Reference Guide
Typedefs | Enumerations | Functions | Variables
M3 Namespace Reference

Typedefs

using float_t = double
 
using int_t = int
 
using uint_t = unsigned
 

Enumerations

enum  kInfCrit { kBIC , kDIC , kWAIC , kInfCrits }
 KS: Different Information Criterion tests mostly based Gelman paper. More...
 

Functions

template<typename T >
constexpr T fmaf_t (T x, T y, T z)
 Function template for fused multiply-add. More...
 
int GetNThreads ()
 number of threads which we need for example for TRandom3 More...
 
void AddPath (std::string &FilePath)
 Prepends the MACH3 environment path to FilePath if it is not already present. More...
 
int GetThreadIndex ()
 thread index inside parallel loop More...
 
TFile * Open (const std::string &Name, const std::string &Type, const std::string &File, const int Line)
 Opens a ROOT file with the given name and mode. More...
 
template<typename ObjectType >
std::unique_ptr< ObjectType > Clone (const ObjectType *obj, const std::string &name="")
 KS: Creates a copy of a ROOT-like object and wraps it in a smart pointer. More...
 
double * MatrixMult (double *A, double *B, int n)
 CW: Multi-threaded matrix multiplication. More...
 
double ** MatrixMult (double **A, double **B, int n)
 CW: Multi-threaded matrix multiplication. More...
 
TMatrixD MatrixMult (TMatrixD A, TMatrixD B)
 CW: Multi-threaded matrix multiplication. More...
 
void MatrixVectorMulti (double *_restrict_ VecMulti, double **_restrict_ matrix, const double *_restrict_ vector, const int n)
 KS: Custom function to perform multiplication of matrix and vector with multithreading. More...
 
double MatrixVectorMultiSingle (double **_restrict_ matrix, const double *_restrict_ vector, const int Length, const int i)
 KS: Custom function to perform multiplication of matrix and single element which is thread safe. More...
 
void FixSampleNamesQuotes (std::string &yamlStr)
 KS: Yaml emitter has problem and drops "", if you have special signs in you like * then there is problem. This bit hacky code adds these "". More...
 
void AddTuneValues (YAML::Node &root, const std::vector< double > &Values, const std::string &Tune, const std::vector< std::string > &FancyNames={})
 KS: Add Tune values to YAML covariance matrix. More...
 
void MakeCorrelationMatrix (YAML::Node &root, const std::vector< double > &Values, const std::vector< double > &Errors, const std::vector< std::vector< double >> &Correlation, const std::string &OutYAMLName, const std::vector< std::string > &FancyNames={})
 KS: Replace correlation matrix and tune values in YAML covariance matrix. More...
 
TMacro * GetConfigMacroFromChain (TDirectory *CovarianceFolder)
 KS: We store configuration macros inside the chain. In the past, multiple configs were stored, which required error-prone hardcoding like "Config_xsec_cov". Therefore, this code maintains backward compatibility by checking the number of macros present and using a hardcoded name only if necessary. More...
 
TMatrixDSym * GetCovMatrixFromChain (TDirectory *TempFile)
 KS: Retrieve the cross-section covariance matrix from the given TDirectory. Historically, multiple covariance matrices could be stored, requiring fragile hardcoded paths like "CovarianceFolder/xsec_cov". This function maintains backward compatibility by: More...
 
std::vector< std::vector< double > > GetCholeskyDecomposedMatrix (const TMatrixDSym &matrix, const std::string &matrixName)
 Computes Cholesky decomposition of a symmetric positive definite matrix using custom function which can be even 20 times faster. More...
 
bool CanDecomposeMatrix (const TMatrixDSym &matrix)
 Checks if a matrix can be Cholesky decomposed. More...
 
void MakeMatrixPosDef (TMatrixDSym *cov)
 Makes sure that matrix is positive-definite by adding a small number to on-diagonal elements. More...
 

Variables

constexpr static const char * float_t_str_repr = "D"
 
constexpr static const double _BAD_DOUBLE_ = -999.99
 Default value used for double initialisation. More...
 
constexpr static const int _BAD_INT_ = -999
 Default value used for int initialisation. More...
 
constexpr static const double _DEFAULT_RETURN_VAL_ = -999999.123456
 
constexpr static const double Unity_D = 1.
 Some commonly used variables to which we set pointers to. More...
 
constexpr static const float Unity_F = 1.
 
constexpr static const float_t Unity = Unity_D
 
constexpr static const double Zero_D = 0.
 
constexpr static const float Zero_F = 0.
 
constexpr static const float_t Zero = Zero_D
 
constexpr static const double KinematicLowBound = std::numeric_limits<double>::lowest()
 When parameter has no bound this serves as it. Lowest possible value the system. More...
 
constexpr static const double KinematicUpBound = std::numeric_limits<double>::max()
 When parameter has no bound this serves as it. Highest possible value the system. More...
 
constexpr static const double _LARGE_LOGL_ = 1234567890.0
 Large Likelihood is used it parameter go out of physical boundary, this indicates in MCMC that such step should be removed. More...
 
constexpr static const double _LOW_MC_BOUND_ = .00001
 MC prediction lower bound in bin to identify problematic binning definitions and handle LogL calculation. More...
 
constexpr static const double DefSplineKnotUpBound = 9999
 Default value for spline knot capping, default mean not capping is being applied. More...
 
constexpr static const double DefSplineKnotLowBound = -9999
 Default value for spline knot capping, default mean not capping is being applied. More...
 

Detailed Description

Run low or high memory versions of structs N.B. for 64 bit systems sizeof(float) == sizeof(double) so not a huge effect

Typedef Documentation

◆ float_t

using M3::float_t = typedef double

Definition at line 30 of file Core.h.

◆ int_t

using M3::int_t = typedef int

Definition at line 31 of file Core.h.

◆ uint_t

using M3::uint_t = typedef unsigned

Definition at line 32 of file Core.h.

Enumeration Type Documentation

◆ kInfCrit

KS: Different Information Criterion tests mostly based Gelman paper.

Enumerator
kBIC 

Bayesian Information Criterion.

kDIC 

Deviance Information Criterion.

kWAIC 

Watanabe-Akaike information criterion.

kInfCrits 

This only enumerates.

Definition at line 10 of file SampleSummary.h.

10  {
11  kBIC,
12  kDIC,
13  kWAIC,
14  kInfCrits
15  };
@ kWAIC
Watanabe-Akaike information criterion.
Definition: SampleSummary.h:13
@ kInfCrits
This only enumerates.
Definition: SampleSummary.h:14
@ kBIC
Bayesian Information Criterion.
Definition: SampleSummary.h:11
@ kDIC
Deviance Information Criterion.
Definition: SampleSummary.h:12

Function Documentation

◆ AddPath()

void M3::AddPath ( std::string &  FilePath)

Prepends the MACH3 environment path to FilePath if it is not already present.

Parameters
FilePathReference to the file path string to be modified.

Definition at line 367 of file Monitor.cpp.

367  {
368 // ***************************************************************************
369  //KS:Most inputs are in ${MACH3}/inputs/blarb.root
370  if (std::getenv("MACH3") == nullptr) {
371  MACH3LOG_ERROR("MACH3 is not defined");
372  MACH3LOG_ERROR("Please source your setup script");
373  MACH3LOG_ERROR("Read more: https://github.com/mach3-software/MaCh3/wiki/0.-FAQ#error-need-mach3-environment-variable");
374  throw MaCh3Exception(__FILE__, __LINE__);
375  }
376 
377  std::string MaCh3Path = std::string(std::getenv("MACH3")) + "/";
378  // Check if FilePath does NOT start with MaCh3Path
379  if (FilePath.find(MaCh3Path) != 0) {
380  FilePath.insert(0, MaCh3Path);
381  }
382 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:27
Custom exception class for MaCh3 errors.

◆ AddTuneValues()

void M3::AddTuneValues ( YAML::Node &  root,
const std::vector< double > &  Values,
const std::string &  Tune,
const std::vector< std::string > &  FancyNames = {} 
)
inline

KS: Add Tune values to YAML covariance matrix.

Parameters
rootThe root YAML node to be updated.
ValuesThe values to add for the specified tune.
TuneThe name of the tune (e.g., "PostFit").
FancyNamesOptional list of fancy names to match systematics (must match Values size if provided).

Definition at line 187 of file ParameterHandlerUtils.h.

190  {}) {
191 // *************************************
192  YAML::Node NodeCopy = YAML::Clone(root);
193  YAML::Node systematics = NodeCopy["Systematics"];
194 
195  if (!systematics || !systematics.IsSequence()) {
196  MACH3LOG_ERROR("'Systematics' node is missing or not a sequence in the YAML copy");
197  throw MaCh3Exception(__FILE__, __LINE__);
198  }
199 
200  if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
201  MACH3LOG_ERROR("Mismatch in sizes: FancyNames has {}, but Values has {}", FancyNames.size(), Values.size());
202  throw MaCh3Exception(__FILE__, __LINE__);
203  }
204 
205  if (FancyNames.empty() && systematics.size() != Values.size()) {
206  MACH3LOG_ERROR("Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
207  Values.size(), systematics.size());
208  throw MaCh3Exception(__FILE__, __LINE__);
209  }
210 
211  if (!FancyNames.empty()) {
212  for (std::size_t i = 0; i < FancyNames.size(); ++i) {
213  bool matched = false;
214  for (std::size_t j = 0; j < systematics.size(); ++j) {
215  YAML::Node systematicNode = systematics[j]["Systematic"];
216  if (!systematicNode) continue;
217  auto nameNode = systematicNode["Names"];
218  if (!nameNode || !nameNode["FancyName"]) continue;
219  if (nameNode["FancyName"].as<std::string>() == FancyNames[i]) {
220  if (!systematicNode["ParameterValues"]) {
221  MACH3LOG_ERROR("Missing 'ParameterValues' for matched FancyName '{}'", FancyNames[i]);
222  throw MaCh3Exception(__FILE__, __LINE__);
223  }
224  systematicNode["ParameterValues"][Tune] = MaCh3Utils::FormatDouble(Values[i], 4);
225  matched = true;
226  break;
227  }
228  }
229  if (!matched) {
230  MACH3LOG_ERROR("Could not find a matching FancyName '{}' in the systematics", FancyNames[i]);
231  throw MaCh3Exception(__FILE__, __LINE__);
232  }
233  }
234  } else {
235  for (std::size_t i = 0; i < systematics.size(); ++i) {
236  YAML::Node systematicNode = systematics[i]["Systematic"];
237  if (!systematicNode || !systematicNode["ParameterValues"]) {
238  MACH3LOG_ERROR("Missing 'Systematic' or 'ParameterValues' entry at index {}", i);
239  throw MaCh3Exception(__FILE__, __LINE__);
240  }
241  systematicNode["ParameterValues"][Tune] = MaCh3Utils::FormatDouble(Values[i], 4);
242  }
243  }
244 
245  // Convert updated copy to string
246  std::string YAMLString = YAMLtoSTRING(NodeCopy);
247  FixSampleNamesQuotes(YAMLString);
248  // Write to output file
249  std::string OutName = "UpdatedMatrixWithTune" + Tune + ".yaml";
250  std::ofstream outFile(OutName);
251  if (!outFile) {
252  MACH3LOG_ERROR("Failed to open file for writing: {}", OutName);
253  throw MaCh3Exception(__FILE__, __LINE__);
254  }
255 
256  outFile << YAMLString;
257  outFile.close();
258 }
std::string YAMLtoSTRING(const YAML::Node &node)
KS: Convert a YAML node to a string representation.
Definition: YamlHelper.h:107
std::unique_ptr< ObjectType > Clone(const ObjectType *obj, const std::string &name="")
KS: Creates a copy of a ROOT-like object and wraps it in a smart pointer.
void FixSampleNamesQuotes(std::string &yamlStr)
KS: Yaml emitter has problem and drops "", if you have special signs in you like * then there is prob...
std::string FormatDouble(const double value, const int precision)
Convert double into string for precision, useful for playing with yaml if you don't want to have in c...

◆ CanDecomposeMatrix()

bool M3::CanDecomposeMatrix ( const TMatrixDSym &  matrix)
inline

Checks if a matrix can be Cholesky decomposed.

Parameters
matrixInput symmetric matrix to test

Definition at line 498 of file ParameterHandlerUtils.h.

498  {
499 // *************************************
500  TDecompChol chdcmp(matrix);
501  return chdcmp.Decompose();
502 }

◆ Clone()

template<typename ObjectType >
std::unique_ptr<ObjectType> M3::Clone ( const ObjectType *  obj,
const std::string &  name = "" 
)

KS: Creates a copy of a ROOT-like object and wraps it in a smart pointer.

Template Parameters
ObjectTypeThe type of the object to clone for example TH1D or TH2Poly.
Parameters
objPointer to the object to clone.
nameOptional argument allowing to set new name of cloned object
Returns
std::unique_ptr<ObjectType> Owning pointer to the cloned object.

Definition at line 139 of file HistogramUtils.h.

139  {
140  std::string cloneName = name.empty() ? obj->GetName() : name;
141 
142  std::unique_ptr<ObjectType> Hist(static_cast<ObjectType*>(obj->Clone(cloneName.c_str())));
143  // Disable ROOT memory management because it causes lot of headache especially as smart pointers are much smarter
144  Hist->SetDirectory(nullptr);
145 
146  return Hist;
147 }

◆ FixSampleNamesQuotes()

void M3::FixSampleNamesQuotes ( std::string &  yamlStr)
inline

KS: Yaml emitter has problem and drops "", if you have special signs in you like * then there is problem. This bit hacky code adds these "".

Parameters
yamlStrThe YAML string to be processed (modified in-place).

Definition at line 152 of file ParameterHandlerUtils.h.

152  {
153 // *************************************
154  std::stringstream input(yamlStr);
155  std::string line;
156  std::string fixedYaml;
157  std::regex sampleNamesRegex(R"(SampleNames:\s*\[([^\]]+)\])");
158 
159  while (std::getline(input, line)) {
160  std::smatch match;
161  if (std::regex_search(line, match, sampleNamesRegex)) {
162  std::string contents = match[1]; // inside the brackets
163  std::stringstream ss(contents);
164  std::string item;
165  std::vector<std::string> quotedItems;
166 
167  while (std::getline(ss, item, ',')) {
168  item = std::regex_replace(item, std::regex(R"(^\s+|\s+$)"), ""); // trim
169  quotedItems.push_back("\"" + item + "\"");
170  }
171 
172  std::string replacement = "SampleNames: [" + fmt::format("{}", fmt::join(quotedItems, ", ")) + "]";
173  line = std::regex_replace(line, sampleNamesRegex, replacement);
174  }
175  fixedYaml += line + "\n";
176  }
177 
178  yamlStr = fixedYaml;
179 }

◆ fmaf_t()

template<typename T >
constexpr T M3::fmaf_t ( x,
y,
z 
)
constexpr

Function template for fused multiply-add.

Definition at line 38 of file Core.h.

38  {
39  #ifdef _LOW_MEMORY_STRUCTS_
40  return std::fmaf(x, y, z);
41  #else
42  return std::fma(x, y, z);
43  #endif
44  }

◆ GetCholeskyDecomposedMatrix()

std::vector<std::vector<double> > M3::GetCholeskyDecomposedMatrix ( const TMatrixDSym &  matrix,
const std::string &  matrixName 
)
inline

Computes Cholesky decomposition of a symmetric positive definite matrix using custom function which can be even 20 times faster.

Parameters
matrixInput symmetric positive definite matrix
matrixNameIdentifier for error reporting

Definition at line 462 of file ParameterHandlerUtils.h.

462  {
463 // *************************************
464  const Int_t n = matrix.GetNrows();
465  std::vector<std::vector<double>> L(n, std::vector<double>(n, 0.0));
466 
467  for (Int_t j = 0; j < n; ++j) {
468  // Compute diagonal element (must be serial)
469  double sum_diag = matrix(j, j);
470  for (Int_t k = 0; k < j; ++k) {
471  sum_diag -= L[j][k] * L[j][k];
472  }
473  const double tol = 1e-15;
474  if (sum_diag <= tol) {
475  MACH3LOG_ERROR("Cholesky decomposition failed for {} (non-positive diagonal)", matrixName);
476  throw MaCh3Exception(__FILE__, __LINE__);
477  }
478  L[j][j] = std::sqrt(sum_diag);
479 
480  // Compute the rest of the column in parallel
481  #ifdef MULTITHREAD
482  #pragma omp parallel for
483  #endif
484  for (Int_t i = j + 1; i < n; ++i) {
485  double sum = matrix(i, j);
486  for (Int_t k = 0; k < j; ++k) {
487  sum -= L[i][k] * L[j][k];
488  }
489  L[i][j] = sum / L[j][j];
490  }
491  }
492  return L;
493 }

◆ GetConfigMacroFromChain()

TMacro* M3::GetConfigMacroFromChain ( TDirectory *  CovarianceFolder)
inline

KS: We store configuration macros inside the chain. In the past, multiple configs were stored, which required error-prone hardcoding like "Config_xsec_cov". Therefore, this code maintains backward compatibility by checking the number of macros present and using a hardcoded name only if necessary.

Definition at line 382 of file ParameterHandlerUtils.h.

382  {
383 // *************************************
384  if (!CovarianceFolder) {
385  MACH3LOG_ERROR("Null TDirectory passed to {}", __func__);
386  throw MaCh3Exception(__FILE__, __LINE__);
387  }
388 
389  TMacro* foundMacro = nullptr;
390  int macroCount = 0;
391 
392  TIter next(CovarianceFolder->GetListOfKeys());
393  TKey* key;
394  while ((key = dynamic_cast<TKey*>(next()))) {
395  if (std::string(key->GetClassName()) == "TMacro") {
396  ++macroCount;
397  if (macroCount == 1) {
398  foundMacro = dynamic_cast<TMacro*>(key->ReadObj());
399  }
400  }
401  }
402 
403  if (macroCount == 1 && foundMacro) {
404  MACH3LOG_INFO("Found single TMacro in directory: using it.");
405  return foundMacro;
406  } else {
407  MACH3LOG_WARN("Found {} TMacro objects. Using hardcoded macro name: Config_xsec_cov.", macroCount);
408  TMacro* fallback = CovarianceFolder->Get<TMacro>("Config_xsec_cov");
409  if (!fallback) {
410  MACH3LOG_WARN("Fallback macro 'Config_xsec_cov' not found in directory.");
411  }
412  return fallback;
413  }
414 }
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:25
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:26

◆ GetCovMatrixFromChain()

TMatrixDSym* M3::GetCovMatrixFromChain ( TDirectory *  TempFile)
inline

KS: Retrieve the cross-section covariance matrix from the given TDirectory. Historically, multiple covariance matrices could be stored, requiring fragile hardcoded paths like "CovarianceFolder/xsec_cov". This function maintains backward compatibility by:

  • Using the single matrix present if only one exists,
  • Otherwise falling back to the hardcoded path. This avoids error-prone assumptions while supporting both old and new formats.

Definition at line 423 of file ParameterHandlerUtils.h.

423  {
424 // *************************************
425  if (!TempFile) {
426  MACH3LOG_ERROR("Null TDirectory passed to {}.", __func__);
427  throw MaCh3Exception(__FILE__, __LINE__);
428  }
429 
430  TMatrixDSym* foundMatrix = nullptr;
431  int matrixCount = 0;
432 
433  TIter next(TempFile->GetListOfKeys());
434  TKey* key;
435  while ((key = dynamic_cast<TKey*>(next()))) {
436  std::string className = key->GetClassName();
437  if (className.find("TMatrix") != std::string::npos) {
438  ++matrixCount;
439  if (matrixCount == 1) {
440  foundMatrix = dynamic_cast<TMatrixDSym*>(key->ReadObj());
441  }
442  }
443  }
444 
445  if (matrixCount == 1 && foundMatrix) {
446  MACH3LOG_INFO("Found single TMatrixDSym in directory: using it.");
447  return foundMatrix;
448  } else {
449  MACH3LOG_WARN("Found {} TMatrixDSym objects. Using hardcoded path: xsec_cov.", matrixCount);
450  TMatrixDSym* fallback = TempFile->Get<TMatrixDSym>("xsec_cov");
451  if (!fallback) {
452  MACH3LOG_WARN("Fallback matrix 'xsec_cov' not found.");
453  }
454  return fallback;
455  }
456 }

◆ GetNThreads()

int M3::GetNThreads ( )

number of threads which we need for example for TRandom3

Definition at line 357 of file Monitor.cpp.

357  {
358 // ***************************************************************************
359  #ifdef MULTITHREAD
360  return omp_get_max_threads();
361  #else
362  return 1;
363  #endif
364 }

◆ GetThreadIndex()

int M3::GetThreadIndex ( )
inline

thread index inside parallel loop

Definition at line 86 of file Monitor.h.

86  {
87  #ifdef MULTITHREAD
88  return omp_get_thread_num();
89  #else
90  return 0;
91  #endif
92  }

◆ MakeCorrelationMatrix()

void M3::MakeCorrelationMatrix ( YAML::Node &  root,
const std::vector< double > &  Values,
const std::vector< double > &  Errors,
const std::vector< std::vector< double >> &  Correlation,
const std::string &  OutYAMLName,
const std::vector< std::string > &  FancyNames = {} 
)
inline

KS: Replace correlation matrix and tune values in YAML covariance matrix.

Parameters
rootThe root YAML node to be updated.
ValuesThe new values for each systematic.
ErrorsThe new errors for each systematic.
CorrelationThe new correlation matrix (must be square and match Values size).
OutYAMLNameThe output filename for the updated YAML.
FancyNamesOptional list of fancy names to match systematics (must match Values size if provided).

Definition at line 268 of file ParameterHandlerUtils.h.

273  {}) {
274 // *************************************
275  if (Values.size() != Errors.size() || Values.size() != Correlation.size()) {
276  MACH3LOG_ERROR("Size mismatch between Values, Errors, and Correlation matrix");
277  throw MaCh3Exception(__FILE__, __LINE__);
278  }
279 
280  for (const auto& row : Correlation) {
281  if (row.size() != Correlation.size()) {
282  MACH3LOG_ERROR("Correlation matrix is not square");
283  throw MaCh3Exception(__FILE__, __LINE__);
284  }
285  }
286 
287  YAML::Node NodeCopy = YAML::Clone(root);
288  YAML::Node systematics = NodeCopy["Systematics"];
289 
290  if (!systematics || !systematics.IsSequence()) {
291  MACH3LOG_ERROR("'Systematics' node is missing or not a sequence");
292  throw MaCh3Exception(__FILE__, __LINE__);
293  }
294 
295  if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
296  MACH3LOG_ERROR("FancyNames size ({}) does not match Values size ({})", FancyNames.size(), Values.size());
297  throw MaCh3Exception(__FILE__, __LINE__);
298  }
299 
300  // Map from FancyName to Systematic node
301  std::unordered_map<std::string, YAML::Node> nameToNode;
302  for (std::size_t i = 0; i < systematics.size(); ++i) {
303  YAML::Node syst = systematics[i]["Systematic"];
304  if (!syst || !syst["Names"] || !syst["Names"]["FancyName"]) continue;
305  std::string name = syst["Names"]["FancyName"].as<std::string>();
306  nameToNode[name] = syst;
307  }
308 
309  if (!FancyNames.empty()) {
310  for (std::size_t i = 0; i < FancyNames.size(); ++i) {
311  const std::string& name_i = FancyNames[i];
312  auto it_i = nameToNode.find(name_i);
313  if (it_i == nameToNode.end()) {
314  MACH3LOG_ERROR("Could not find FancyName '{}' in YAML", name_i);
315  throw MaCh3Exception(__FILE__, __LINE__);
316  }
317  YAML::Node& syst_i = it_i->second;
318 
319  syst_i["ParameterValues"]["PreFitValue"] = MaCh3Utils::FormatDouble(Values[i], 4);
320  syst_i["Error"] = std::round(Errors[i] * 100.0) / 100.0;
321 
322  YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
323  for (std::size_t j = 0; j < FancyNames.size(); ++j) {
324  if (i == j) continue;
325  // KS: Skip if value close to 0
326  if (std::abs(Correlation[i][j]) < 1e-8) continue;
327  YAML::Node singleEntry;
328  singleEntry[FancyNames[j]] = MaCh3Utils::FormatDouble(Correlation[i][j], 4);
329  correlationsNode.push_back(singleEntry);
330  }
331  syst_i["Correlations"] = correlationsNode;
332  }
333  } else {
334  if (systematics.size() != Values.size()) {
335  MACH3LOG_ERROR("Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
336  Values.size(), systematics.size());
337  throw MaCh3Exception(__FILE__, __LINE__);
338  }
339 
340  for (std::size_t i = 0; i < systematics.size(); ++i) {
341  YAML::Node syst = systematics[i]["Systematic"];
342  if (!syst) {
343  MACH3LOG_ERROR("Missing 'Systematic' node at index {}", i);
344  throw MaCh3Exception(__FILE__, __LINE__);
345  }
346 
347  syst["ParameterValues"]["PreFitValue"] = MaCh3Utils::FormatDouble(Values[i], 4);
348  syst["Error"] = std::round(Errors[i] * 100.0) / 100.0;
349 
350  YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
351  for (std::size_t j = 0; j < Correlation[i].size(); ++j) {
352  if (i == j) continue;
353  // KS: Skip if value close to 0
354  if (std::abs(Correlation[i][j]) < 1e-8) continue;
355  YAML::Node singleEntry;
356  const std::string& otherName = systematics[j]["Systematic"]["Names"]["FancyName"].as<std::string>();
357  singleEntry[otherName] = MaCh3Utils::FormatDouble(Correlation[i][j], 4);
358  correlationsNode.push_back(singleEntry);
359  }
360  syst["Correlations"] = correlationsNode;
361  }
362  }
363 
364  // Convert and write
365  std::string YAMLString = YAMLtoSTRING(NodeCopy);
366  FixSampleNamesQuotes(YAMLString);
367  std::ofstream outFile(OutYAMLName);
368  if (!outFile) {
369  MACH3LOG_ERROR("Failed to open file for writing: {}", OutYAMLName);
370  throw MaCh3Exception(__FILE__, __LINE__);
371  }
372 
373  outFile << YAMLString;
374  outFile.close();
375 }

◆ MakeMatrixPosDef()

void M3::MakeMatrixPosDef ( TMatrixDSym *  cov)
inline

Makes sure that matrix is positive-definite by adding a small number to on-diagonal elements.

Definition at line 506 of file ParameterHandlerUtils.h.

506  {
507 // *************************************
508  //DB Save original warning state and then increase it in this function to suppress 'matrix not positive definite' messages
509  //Means we no longer need to overload
510  int originalErrorWarning = gErrorIgnoreLevel;
511  gErrorIgnoreLevel = kFatal;
512 
513  //DB Loop 1000 times adding 1e-9 which tops out at 1e-6 shift on the diagonal before throwing error
514  constexpr int MaxAttempts = 1e5;
515  const int matrixSize = cov->GetNrows();
516  int iAttempt = 0;
517  bool CanDecomp = false;
518 
519  for (iAttempt = 0; iAttempt < MaxAttempts; iAttempt++) {
520  if (CanDecomposeMatrix(*cov)) {
521  CanDecomp = true;
522  break;
523  } else {
524  #ifdef MULTITHREAD
525  #pragma omp parallel for
526  #endif
527  for (int iVar = 0 ; iVar < matrixSize; iVar++) {
528  (*cov)(iVar,iVar) += pow(10, -9);
529  }
530  }
531  }
532 
533  if (!CanDecomp) {
534  MACH3LOG_ERROR("Tried {} times to shift diagonal but still can not decompose the matrix", MaxAttempts);
535  MACH3LOG_ERROR("This indicates that something is wrong with the input matrix");
536  throw MaCh3Exception(__FILE__ , __LINE__ );
537  }
538 
539  //DB Resetting warning level
540  gErrorIgnoreLevel = originalErrorWarning;
541 }
bool CanDecomposeMatrix(const TMatrixDSym &matrix)
Checks if a matrix can be Cholesky decomposed.

◆ MatrixMult() [1/3]

double** M3::MatrixMult ( double **  A,
double **  B,
int  n 
)
inline

CW: Multi-threaded matrix multiplication.

Definition at line 62 of file ParameterHandlerUtils.h.

62  {
63  // First make into monolithic array
64  double *A_mon = new double[n*n];
65  double *B_mon = new double[n*n];
66 
67  #ifdef MULTITHREAD
68  #pragma omp parallel for
69  #endif
70  for (int i = 0; i < n; ++i) {
71  for (int j = 0; j < n; ++j) {
72  A_mon[i*n+j] = A[i][j];
73  B_mon[i*n+j] = B[i][j];
74  }
75  }
76  //CW: Now call the monolithic calculator
77  double *C_mon = MatrixMult(A_mon, B_mon, n);
78  delete A_mon;
79  delete B_mon;
80 
81  // Return the double pointer
82  double **C = new double*[n];
83  #ifdef MULTITHREAD
84  #pragma omp parallel for
85  #endif
86  for (int i = 0; i < n; ++i) {
87  C[i] = new double[n];
88  for (int j = 0; j < n; ++j) {
89  C[i][j] = C_mon[i*n+j];
90  }
91  }
92  delete C_mon;
93 
94  return C;
95 }
TMatrixD MatrixMult(TMatrixD A, TMatrixD B)
CW: Multi-threaded matrix multiplication.

◆ MatrixMult() [2/3]

double* M3::MatrixMult ( double *  A,
double *  B,
int  n 
)
inline

CW: Multi-threaded matrix multiplication.

Definition at line 30 of file ParameterHandlerUtils.h.

30  {
31  //CW: First transpose to increse cache hits
32  double *BT = new double[n*n];
33  #ifdef MULTITHREAD
34  #pragma omp parallel for
35  #endif
36  for (int i = 0; i < n; i++) {
37  for (int j = 0; j < n; j++) {
38  BT[j*n+i] = B[i*n+j];
39  }
40  }
41 
42  // Now multiply
43  double *C = new double[n*n];
44  #ifdef MULTITHREAD
45  #pragma omp parallel for
46  #endif
47  for (int i = 0; i < n; i++) {
48  for (int j = 0; j < n; j++) {
49  double sum = 0;
50  for (int k = 0; k < n; k++) {
51  sum += A[i*n+k]*BT[j*n+k];
52  }
53  C[i*n+j] = sum;
54  }
55  }
56  delete BT;
57 
58  return C;
59 }

◆ MatrixMult() [3/3]

TMatrixD M3::MatrixMult ( TMatrixD  A,
TMatrixD  B 
)
inline

CW: Multi-threaded matrix multiplication.

Definition at line 98 of file ParameterHandlerUtils.h.

99 {
100  double *C_mon = MatrixMult(A.GetMatrixArray(), B.GetMatrixArray(), A.GetNcols());
101  TMatrixD C;
102  C.Use(A.GetNcols(), A.GetNrows(), C_mon);
103  return C;
104 }

◆ MatrixVectorMulti()

void M3::MatrixVectorMulti ( double *_restrict_  VecMulti,
double **_restrict_  matrix,
const double *_restrict_  vector,
const int  n 
)
inline

KS: Custom function to perform multiplication of matrix and vector with multithreading.

Parameters
VecMultiOutput Vector, VecMulti = matrix x vector
matrixThis matrix is used for multiplication VecMulti = matrix x vector
vectorThis vector is used for multiplication VecMulti = matrix x vector
nthis is size of matrix and vector, we assume matrix is symmetric

Definition at line 112 of file ParameterHandlerUtils.h.

112  {
113 // ********************************************
114  #ifdef MULTITHREAD
115  #pragma omp parallel for
116  #endif
117  for (int i = 0; i < n; ++i)
118  {
119  double result = 0.0;
120  #ifdef MULTITHREAD
121  #pragma omp simd
122  #endif
123  for (int j = 0; j < n; ++j)
124  {
125  result += matrix[i][j]*vector[j];
126  }
127  VecMulti[i] = result;
128  }
129 }

◆ MatrixVectorMultiSingle()

double M3::MatrixVectorMultiSingle ( double **_restrict_  matrix,
const double *_restrict_  vector,
const int  Length,
const int  i 
)
inline

KS: Custom function to perform multiplication of matrix and single element which is thread safe.

Parameters
matrixThis matrix is used for multiplication VecMulti = matrix x vector
vectorThis vector is used for multiplication VecMulti = matrix x vector
Lengththis is size of matrix and vector, we assume matrix is symmetric
iElement of matrix that we want to multiply

Definition at line 137 of file ParameterHandlerUtils.h.

137  {
138 // ********************************************
139  double Element = 0.0;
140  #ifdef MULTITHREAD
141  #pragma omp simd
142  #endif
143  for (int j = 0; j < Length; ++j) {
144  Element += matrix[i][j]*vector[j];
145  }
146  return Element;
147 }

◆ Open()

TFile * M3::Open ( const std::string &  Name,
const std::string &  Type,
const std::string &  File,
const int  Line 
)

Opens a ROOT file with the given name and mode.

This function wraps ROOT’s TFile constructor and checks whether the file was opened successfully and give some useful debugging information

Parameters
NameThe name or path of the file to open.
TypeThe file open mode (e.g., "READ", "RECREATE", "UPDATE").
Returns
Pointer to the opened ROOT file.

Definition at line 610 of file HistogramUtils.cpp.

610  {
611 // **************************************************************************
612  TFile* OutFile = new TFile(Name.c_str(), Type.c_str());
613 
614  // Check if the file is successfully opened and usable
615  if (OutFile->IsZombie()) {
616  MACH3LOG_ERROR("Failed to open file: {}", Name);
617  if (Type == "RECREATE") {
618  MACH3LOG_ERROR("Check if directory exist");
619  }
620  delete OutFile;
621  throw MaCh3Exception(File, Line);
622  }
623  return OutFile;
624 }

Variable Documentation

◆ _BAD_DOUBLE_

constexpr static const double M3::_BAD_DOUBLE_ = -999.99
staticconstexpr

Default value used for double initialisation.

Definition at line 46 of file Core.h.

◆ _BAD_INT_

constexpr static const int M3::_BAD_INT_ = -999
staticconstexpr

Default value used for int initialisation.

Definition at line 48 of file Core.h.

◆ _DEFAULT_RETURN_VAL_

constexpr static const double M3::_DEFAULT_RETURN_VAL_ = -999999.123456
staticconstexpr

Definition at line 49 of file Core.h.

◆ _LARGE_LOGL_

constexpr static const double M3::_LARGE_LOGL_ = 1234567890.0
staticconstexpr

Large Likelihood is used it parameter go out of physical boundary, this indicates in MCMC that such step should be removed.

Definition at line 73 of file Core.h.

◆ _LOW_MC_BOUND_

constexpr static const double M3::_LOW_MC_BOUND_ = .00001
staticconstexpr

MC prediction lower bound in bin to identify problematic binning definitions and handle LogL calculation.

Definition at line 76 of file Core.h.

◆ DefSplineKnotLowBound

constexpr static const double M3::DefSplineKnotLowBound = -9999
staticconstexpr

Default value for spline knot capping, default mean not capping is being applied.

Definition at line 81 of file Core.h.

◆ DefSplineKnotUpBound

constexpr static const double M3::DefSplineKnotUpBound = 9999
staticconstexpr

Default value for spline knot capping, default mean not capping is being applied.

Definition at line 79 of file Core.h.

◆ float_t_str_repr

constexpr static const char* M3::float_t_str_repr = "D"
staticconstexpr

Definition at line 33 of file Core.h.

◆ KinematicLowBound

constexpr static const double M3::KinematicLowBound = std::numeric_limits<double>::lowest()
staticconstexpr

When parameter has no bound this serves as it. Lowest possible value the system.

Definition at line 68 of file Core.h.

◆ KinematicUpBound

constexpr static const double M3::KinematicUpBound = std::numeric_limits<double>::max()
staticconstexpr

When parameter has no bound this serves as it. Highest possible value the system.

Definition at line 70 of file Core.h.

◆ Unity

constexpr static const float_t M3::Unity = Unity_D
staticconstexpr

Definition at line 57 of file Core.h.

◆ Unity_D

constexpr static const double M3::Unity_D = 1.
staticconstexpr

Some commonly used variables to which we set pointers to.

Definition at line 52 of file Core.h.

◆ Unity_F

constexpr static const float M3::Unity_F = 1.
staticconstexpr

Definition at line 53 of file Core.h.

◆ Zero

constexpr static const float_t M3::Zero = Zero_D
staticconstexpr

Definition at line 64 of file Core.h.

◆ Zero_D

constexpr static const double M3::Zero_D = 0.
staticconstexpr

Definition at line 59 of file Core.h.

◆ Zero_F

constexpr static const float M3::Zero_F = 0.
staticconstexpr

Definition at line 60 of file Core.h.