9 #include "TMatrixDSym.h"
18 #include "TDecompChol.h"
19 #include "TStopwatch.h"
21 #include "TMatrixDSymEigen.h"
22 #include "TMatrixDEigen.h"
23 #include "TDecompSVD.h"
45 double *BT =
new double[n*n];
47 #pragma omp parallel for
49 for (
int i = 0; i < n; i++) {
50 for (
int j = 0; j < n; j++) {
56 double *C =
new double[n*n];
58 #pragma omp parallel for
60 for (
int i = 0; i < n; i++) {
61 for (
int j = 0; j < n; j++) {
63 for (
int k = 0; k < n; k++) {
64 sum += A[i*n+k]*BT[j*n+k];
75 inline double**
MatrixMult(
double **A,
double **B,
int n) {
77 double *A_mon =
new double[n*n];
78 double *B_mon =
new double[n*n];
81 #pragma omp parallel for
83 for (
int i = 0; i < n; ++i) {
84 for (
int j = 0; j < n; ++j) {
85 A_mon[i*n+j] = A[i][j];
86 B_mon[i*n+j] = B[i][j];
95 double **C =
new double*[n];
97 #pragma omp parallel for
99 for (
int i = 0; i < n; ++i) {
100 C[i] =
new double[n];
101 for (
int j = 0; j < n; ++j) {
102 C[i][j] = C_mon[i*n+j];
113 double *C_mon =
MatrixMult(A.GetMatrixArray(), B.GetMatrixArray(), A.GetNcols());
115 C.Use(A.GetNcols(), A.GetNrows(), C_mon);
128 #pragma omp parallel for
130 for (
int i = 0; i < n; ++i)
136 for (
int j = 0; j < n; ++j)
138 result += matrix[i][j]*vector[j];
140 VecMulti[i] = result;
152 double Element = 0.0;
156 for (
int j = 0; j < Length; ++j) {
157 Element += matrix[i][j]*vector[j];
167 std::stringstream input(yamlStr);
169 std::string fixedYaml;
170 std::regex sampleNamesRegex(R
"(SampleNames:\s*\[([^\]]+)\])");
172 while (std::getline(input, line)) {
174 if (std::regex_search(line, match, sampleNamesRegex)) {
175 std::string contents = match[1];
176 std::stringstream ss(contents);
178 std::vector<std::string> quotedItems;
180 while (std::getline(ss, item,
',')) {
181 item = std::regex_replace(item, std::regex(R
"(^\s+|\s+$)"), "");
182 quotedItems.push_back(
"\"" + item +
"\"");
185 std::string replacement =
"SampleNames: [" + fmt::format(
"{}", fmt::join(quotedItems,
", ")) +
"]";
186 line = std::regex_replace(line, sampleNamesRegex, replacement);
188 fixedYaml += line +
"\n";
201 const std::vector<double>& Values,
202 const std::string& Tune,
203 const std::vector<std::string>& FancyNames = {}) {
206 YAML::Node systematics = NodeCopy[
"Systematics"];
208 if (!systematics || !systematics.IsSequence()) {
209 MACH3LOG_ERROR(
"'Systematics' node is missing or not a sequence in the YAML copy");
213 if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
214 MACH3LOG_ERROR(
"Mismatch in sizes: FancyNames has {}, but Values has {}", FancyNames.size(), Values.size());
218 if (FancyNames.empty() && systematics.size() != Values.size()) {
219 MACH3LOG_ERROR(
"Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
220 Values.size(), systematics.size());
224 if (!FancyNames.empty()) {
225 for (std::size_t i = 0; i < FancyNames.size(); ++i) {
226 bool matched =
false;
227 for (std::size_t j = 0; j < systematics.size(); ++j) {
228 YAML::Node systematicNode = systematics[j][
"Systematic"];
229 if (!systematicNode)
continue;
230 auto nameNode = systematicNode[
"Names"];
231 if (!nameNode || !nameNode[
"FancyName"])
continue;
232 if (nameNode[
"FancyName"].as<std::string>() == FancyNames[i]) {
233 if (!systematicNode[
"ParameterValues"]) {
234 MACH3LOG_ERROR(
"Missing 'ParameterValues' for matched FancyName '{}'", FancyNames[i]);
243 MACH3LOG_ERROR(
"Could not find a matching FancyName '{}' in the systematics", FancyNames[i]);
248 for (std::size_t i = 0; i < systematics.size(); ++i) {
249 YAML::Node systematicNode = systematics[i][
"Systematic"];
250 if (!systematicNode || !systematicNode[
"ParameterValues"]) {
251 MACH3LOG_ERROR(
"Missing 'Systematic' or 'ParameterValues' entry at index {}", i);
262 std::string OutName =
"UpdatedMatrixWithTune" + Tune +
".yaml";
263 std::ofstream outFile(OutName);
269 outFile << YAMLString;
282 const std::vector<double>& Values,
283 const std::vector<double>& Errors,
284 const std::vector<std::vector<double>>& Correlation,
285 const std::string& OutYAMLName,
286 const std::vector<std::string>& FancyNames = {}) {
288 if (Values.size() != Errors.size() || Values.size() != Correlation.size()) {
289 MACH3LOG_ERROR(
"Size mismatch between Values, Errors, and Correlation matrix");
293 for (
const auto& row : Correlation) {
294 if (row.size() != Correlation.size()) {
301 YAML::Node systematics = NodeCopy[
"Systematics"];
303 if (!systematics || !systematics.IsSequence()) {
304 MACH3LOG_ERROR(
"'Systematics' node is missing or not a sequence");
308 if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
309 MACH3LOG_ERROR(
"FancyNames size ({}) does not match Values size ({})", FancyNames.size(), Values.size());
314 std::unordered_map<std::string, YAML::Node> nameToNode;
315 for (std::size_t i = 0; i < systematics.size(); ++i) {
316 YAML::Node syst = systematics[i][
"Systematic"];
317 if (!syst || !syst[
"Names"] || !syst[
"Names"][
"FancyName"])
continue;
318 std::string name = syst[
"Names"][
"FancyName"].as<std::string>();
319 nameToNode[name] = syst;
322 if (!FancyNames.empty()) {
323 for (std::size_t i = 0; i < FancyNames.size(); ++i) {
324 const std::string& name_i = FancyNames[i];
325 auto it_i = nameToNode.find(name_i);
326 if (it_i == nameToNode.end()) {
330 YAML::Node& syst_i = it_i->second;
333 syst_i[
"Error"] = std::round(Errors[i] * 100.0) / 100.0;
335 YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
336 for (std::size_t j = 0; j < FancyNames.size(); ++j) {
337 if (i == j)
continue;
339 if (std::abs(Correlation[i][j]) < 1e-8)
continue;
340 YAML::Node singleEntry;
342 correlationsNode.push_back(singleEntry);
344 syst_i[
"Correlations"] = correlationsNode;
347 if (systematics.size() != Values.size()) {
348 MACH3LOG_ERROR(
"Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
349 Values.size(), systematics.size());
353 for (std::size_t i = 0; i < systematics.size(); ++i) {
354 YAML::Node syst = systematics[i][
"Systematic"];
361 syst[
"Error"] = std::round(Errors[i] * 100.0) / 100.0;
363 YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
364 for (std::size_t j = 0; j < Correlation[i].size(); ++j) {
365 if (i == j)
continue;
367 if (std::abs(Correlation[i][j]) < 1e-8)
continue;
368 YAML::Node singleEntry;
369 const std::string& otherName = systematics[j][
"Systematic"][
"Names"][
"FancyName"].as<std::string>();
371 correlationsNode.push_back(singleEntry);
373 syst[
"Correlations"] = correlationsNode;
380 std::ofstream outFile(OutYAMLName);
382 MACH3LOG_ERROR(
"Failed to open file for writing: {}", OutYAMLName);
386 outFile << YAMLString;
397 if (!CovarianceFolder) {
402 TMacro* foundMacro =
nullptr;
405 TIter next(CovarianceFolder->GetListOfKeys());
407 while ((key =
dynamic_cast<TKey*
>(next()))) {
408 if (std::string(key->GetClassName()) ==
"TMacro") {
410 if (macroCount == 1) {
411 foundMacro =
dynamic_cast<TMacro*
>(key->ReadObj());
416 if (macroCount == 1 && foundMacro) {
417 MACH3LOG_INFO(
"Found single TMacro in directory: using it.");
420 MACH3LOG_WARN(
"Found {} TMacro objects. Using hardcoded macro name: Config_xsec_cov.", macroCount);
421 TMacro* fallback = CovarianceFolder->Get<TMacro>(
"Config_xsec_cov");
423 MACH3LOG_WARN(
"Fallback macro 'Config_xsec_cov' not found in directory.");
443 TMatrixDSym* foundMatrix =
nullptr;
446 TIter next(TempFile->GetListOfKeys());
448 while ((key =
dynamic_cast<TKey*
>(next()))) {
449 std::string className = key->GetClassName();
450 if (className.find(
"TMatrix") != std::string::npos) {
452 if (matrixCount == 1) {
453 foundMatrix =
dynamic_cast<TMatrixDSym*
>(key->ReadObj());
458 if (matrixCount == 1 && foundMatrix) {
459 MACH3LOG_INFO(
"Found single TMatrixDSym in directory: using it.");
462 MACH3LOG_WARN(
"Found {} TMatrixDSym objects. Using hardcoded path: xsec_cov.", matrixCount);
463 TMatrixDSym* fallback = TempFile->Get<TMatrixDSym>(
"xsec_cov");
477 const Int_t n = matrix.GetNrows();
478 std::vector<std::vector<double>> L(n, std::vector<double>(n, 0.0));
480 for (Int_t j = 0; j < n; ++j) {
482 double sum_diag = matrix(j, j);
483 for (Int_t k = 0; k < j; ++k) {
484 sum_diag -= L[j][k] * L[j][k];
486 const double tol = 1e-15;
487 if (sum_diag <= tol) {
488 MACH3LOG_ERROR(
"Cholesky decomposition failed for {} (non-positive diagonal)", matrixName);
491 L[j][j] = std::sqrt(sum_diag);
495 #pragma omp parallel for
497 for (Int_t i = j + 1; i < n; ++i) {
498 double sum = matrix(i, j);
499 for (Int_t k = 0; k < j; ++k) {
500 sum -= L[i][k] * L[j][k];
502 L[i][j] = sum / L[j][j];
513 TDecompChol chdcmp(matrix);
514 return chdcmp.Decompose();
523 int originalErrorWarning = gErrorIgnoreLevel;
524 gErrorIgnoreLevel = kFatal;
527 constexpr
int MaxAttempts = 1e5;
528 const int matrixSize = cov->GetNrows();
530 bool CanDecomp =
false;
532 for (iAttempt = 0; iAttempt < MaxAttempts; iAttempt++) {
538 #pragma omp parallel for
540 for (
int iVar = 0 ; iVar < matrixSize; iVar++) {
541 (*cov)(iVar, iVar) += 1e-9;
547 MACH3LOG_ERROR(
"Tried {} times to shift diagonal but still can not decompose the matrix", MaxAttempts);
548 MACH3LOG_ERROR(
"This indicates that something is wrong with the input matrix");
553 gErrorIgnoreLevel = originalErrorWarning;
562 const std::vector<double>& _fPreFitValue,
563 const std::vector<double>& _fError,
564 const std::vector<double>& _fLowBound,
565 const std::vector<double>& _fUpBound,
566 const std::vector<double>& _fIndivStepScale,
567 const std::vector<std::string>& _fFancyNames,
568 const std::vector<bool>& _fFlatPrior,
569 const std::vector<SplineParameter>& SplineParams,
570 TMatrixDSym* covMatrix,
572 const std::string& Name) {
574 TFile* outputFile =
new TFile(Name.c_str(),
"RECREATE");
576 TObjArray* param_names =
new TObjArray();
577 TObjArray* spline_interpolation =
new TObjArray();
578 TObjArray* spline_names =
new TObjArray();
580 TVectorD* param_prior =
new TVectorD(_fNumPar);
581 TVectorD* flat_prior =
new TVectorD(_fNumPar);
582 TVectorD* stepscale =
new TVectorD(_fNumPar);
583 TVectorD* param_lb =
new TVectorD(_fNumPar);
584 TVectorD* param_ub =
new TVectorD(_fNumPar);
586 TVectorD* param_knot_weight_lb =
new TVectorD(_fNumPar);
587 TVectorD* param_knot_weight_ub =
new TVectorD(_fNumPar);
588 TVectorD* error =
new TVectorD(_fNumPar);
590 for(
int i = 0; i < _fNumPar; ++i)
592 TObjString* nameObj =
new TObjString(_fFancyNames[i].c_str());
593 param_names->AddLast(nameObj);
595 TObjString* splineType =
new TObjString(
"TSpline3");
596 spline_interpolation->AddLast(splineType);
598 TObjString* splineName =
new TObjString(
"");
599 spline_names->AddLast(splineName);
601 (*param_prior)[i] = _fPreFitValue[i];
602 (*flat_prior)[i] = _fFlatPrior[i];
603 (*stepscale)[i] = _fIndivStepScale[i];
604 (*error)[i] = _fError[i];
606 (*param_lb)[i] = _fLowBound[i];
607 (*param_ub)[i] = _fUpBound[i];
610 (*param_knot_weight_lb)[i] = -9999;
611 (*param_knot_weight_ub)[i] = +9999;
617 (*param_knot_weight_lb)[SystIndex] = SplineParams.at(
SplineIndex)._SplineKnotLowBound;
618 (*param_knot_weight_ub)[SystIndex] = SplineParams.at(
SplineIndex)._SplineKnotUpBound;
621 spline_interpolation->AddAt(splineType, SystIndex);
623 TObjString* splineName =
new TObjString(SplineParams[
SplineIndex]._fSplineNames.c_str());
624 spline_names->AddAt(splineName, SystIndex);
626 param_names->Write(
"xsec_param_names", TObject::kSingleKey);
628 spline_interpolation->Write(
"xsec_spline_interpolation", TObject::kSingleKey);
629 delete spline_interpolation;
630 spline_names->Write(
"xsec_spline_names", TObject::kSingleKey);
633 param_prior->Write(
"xsec_param_prior");
635 flat_prior->Write(
"xsec_flat_prior");
637 stepscale->Write(
"xsec_stepscale");
639 param_lb->Write(
"xsec_param_lb");
641 param_ub->Write(
"xsec_param_ub");
644 param_knot_weight_lb->Write(
"xsec_param_knot_weight_lb");
645 delete param_knot_weight_lb;
646 param_knot_weight_ub->Write(
"xsec_param_knot_weight_ub");
647 delete param_knot_weight_ub;
648 error->Write(
"xsec_error");
651 covMatrix->Write(
"xsec_cov");
652 CorrMatrix->Write(
"hcov");
662 const TMatrixD& temp,
663 const TMatrixD& eigen_vectors,
664 const TVectorD& eigen_values,
665 const TMatrixD& TransferMat,
666 const TMatrixD& TransferMatT,
668 const int FirstPCAdpar,
669 const int LastPCAdpar,
670 const int nKeptPCApars,
671 const double eigen_threshold) {
673 #pragma GCC diagnostic push
674 #pragma GCC diagnostic ignored "-Wfloat-conversion"
675 int originalErrorWarning = gErrorIgnoreLevel;
676 gErrorIgnoreLevel = kFatal;
678 TDirectory *ogdir = gDirectory;
680 TFile *PCA_Debug =
new TFile(
"Debug_PCA.root",
"RECREATE");
683 bool PlotText =
true;
685 if(NumPar > 200) PlotText =
false;
687 auto heigen_values = std::make_unique<TH1D>(
"eigen_values",
"Eigen Values", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
688 heigen_values->SetDirectory(
nullptr);
689 auto heigen_cumulative = std::make_unique<TH1D>(
"heigen_cumulative",
"heigen_cumulative", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
690 heigen_cumulative->SetDirectory(
nullptr);
691 auto heigen_frac = std::make_unique<TH1D>(
"heigen_fractional",
"heigen_fractional", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
692 heigen_frac->SetDirectory(
nullptr);
693 heigen_values->GetXaxis()->SetTitle(
"Eigen Vector");
694 heigen_values->GetYaxis()->SetTitle(
"Eigen Value");
696 double Cumulative = 0;
697 for(
int i = 0; i < eigen_values.GetNrows(); i++)
699 heigen_values->SetBinContent(i+1, (eigen_values)(i));
700 heigen_cumulative->SetBinContent(i+1, (eigen_values)(i)/sum + Cumulative);
701 heigen_frac->SetBinContent(i+1, (eigen_values)(i)/sum);
702 Cumulative += (eigen_values)(i)/sum;
704 heigen_values->Write(
"heigen_values");
705 eigen_values.Write(
"eigen_values");
706 heigen_cumulative->Write(
"heigen_values_cumulative");
707 heigen_frac->Write(
"heigen_values_frac");
709 TH2D* heigen_vectors =
new TH2D(eigen_vectors);
710 heigen_vectors->GetXaxis()->SetTitle(
"Parameter in Normal Base");
711 heigen_vectors->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
712 heigen_vectors->Write(
"heigen_vectors");
713 eigen_vectors.Write(
"eigen_vectors");
715 TH2D* SubsetPCA =
new TH2D(temp);
716 SubsetPCA->GetXaxis()->SetTitle(
"Parameter in Normal Base");
717 SubsetPCA->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
719 SubsetPCA->Write(
"hSubsetPCA");
720 temp.Write(
"SubsetPCA");
721 TH2D* hTransferMat =
new TH2D(TransferMat);
722 hTransferMat->GetXaxis()->SetTitle(
"Parameter in Normal Base");
723 hTransferMat->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
724 TH2D* hTransferMatT =
new TH2D(TransferMatT);
726 hTransferMatT->GetXaxis()->SetTitle(
"Parameter in Decomposed Base");
727 hTransferMatT->GetYaxis()->SetTitle(
"Parameter in Normal Base");
729 hTransferMat->Write(
"hTransferMat");
730 TransferMat.Write(
"TransferMat");
731 hTransferMatT->Write(
"hTransferMatT");
732 TransferMatT.Write(
"TransferMatT");
734 auto c1 = std::make_unique<TCanvas>(
"c1",
" ", 0, 0, 1024, 1024);
735 c1->SetBottomMargin(0.1);
736 c1->SetTopMargin(0.05);
737 c1->SetRightMargin(0.05);
738 c1->SetLeftMargin(0.12);
741 gStyle->SetPaintTextFormat(
"4.1f");
742 gStyle->SetOptFit(0);
743 gStyle->SetOptStat(0);
745 constexpr
int NRGBs = 5;
746 TColor::InitializeColors();
747 Double_t stops[NRGBs] = { 0.00, 0.25, 0.50, 0.75, 1.00 };
748 Double_t red[NRGBs] = { 0.00, 0.25, 1.00, 1.00, 0.50 };
749 Double_t green[NRGBs] = { 0.00, 0.25, 1.00, 0.25, 0.00 };
750 Double_t blue[NRGBs] = { 0.50, 1.00, 1.00, 0.25, 0.00 };
751 TColor::CreateGradientColorTable(5, stops, red, green, blue, 255);
752 gStyle->SetNumberContours(255);
757 c1->Print(
"Debug_PCA.pdf[");
758 auto EigenLine = std::make_unique<TLine>(nKeptPCApars, 0, nKeptPCApars, heigen_cumulative->GetMaximum());
759 EigenLine->SetLineColor(kPink);
760 EigenLine->SetLineWidth(2);
761 EigenLine->SetLineStyle(kSolid);
763 auto text = std::make_unique<TText>(0.5, 0.5, Form(
"Threshold = %g", eigen_threshold));
764 text->SetTextFont (43);
765 text->SetTextSize (40);
767 heigen_values->SetLineColor(kRed);
768 heigen_values->SetLineWidth(2);
769 heigen_cumulative->SetLineColor(kGreen);
770 heigen_cumulative->SetLineWidth(2);
771 heigen_frac->SetLineColor(kBlue);
772 heigen_frac->SetLineWidth(2);
775 heigen_values->SetMaximum(heigen_cumulative->GetMaximum()+heigen_cumulative->GetMaximum()*0.4);
776 heigen_values->Draw();
777 heigen_frac->Draw(
"SAME");
778 heigen_cumulative->Draw(
"SAME");
779 EigenLine->Draw(
"Same");
780 text->DrawTextNDC(0.42, 0.84,Form(
"Threshold = %g", eigen_threshold));
782 auto leg = std::make_unique<TLegend>(0.2, 0.2, 0.6, 0.5);
783 leg->SetTextSize(0.04);
784 leg->AddEntry(heigen_values.get(),
"Absolute",
"l");
785 leg->AddEntry(heigen_frac.get(),
"Fractional",
"l");
786 leg->AddEntry(heigen_cumulative.get(),
"Cumulative",
"l");
788 leg->SetLineColor(0);
789 leg->SetLineStyle(0);
790 leg->SetFillColor(0);
791 leg->SetFillStyle(0);
794 c1->Print(
"Debug_PCA.pdf");
795 c1->SetRightMargin(0.15);
798 heigen_vectors->SetMarkerSize(0.2);
799 minz = heigen_vectors->GetMinimum();
800 if (fabs(0-maxz)>fabs(0-minz)) heigen_vectors->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
801 else heigen_vectors->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
802 if(PlotText) heigen_vectors->Draw(
"COLZ TEXT");
803 else heigen_vectors->Draw(
"COLZ");
805 auto Eigen_Line = std::make_unique<TLine>(0, nKeptPCApars, LastPCAdpar - FirstPCAdpar, nKeptPCApars);
806 Eigen_Line->SetLineColor(kGreen);
807 Eigen_Line->SetLineWidth(2);
808 Eigen_Line->SetLineStyle(kDotted);
809 Eigen_Line->Draw(
"SAME");
810 c1->Print(
"Debug_PCA.pdf");
812 SubsetPCA->SetMarkerSize(0.2);
813 minz = SubsetPCA->GetMinimum();
814 if (fabs(0-maxz)>fabs(0-minz)) SubsetPCA->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
815 else SubsetPCA->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
816 if(PlotText) SubsetPCA->Draw(
"COLZ TEXT");
817 else SubsetPCA->Draw(
"COLZ");
818 c1->Print(
"Debug_PCA.pdf");
821 hTransferMat->SetMarkerSize(0.15);
822 minz = hTransferMat->GetMinimum();
823 if (fabs(0-maxz)>fabs(0-minz)) hTransferMat->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
824 else hTransferMat->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
825 if(PlotText) hTransferMat->Draw(
"COLZ TEXT");
826 else hTransferMat->Draw(
"COLZ");
827 c1->Print(
"Debug_PCA.pdf");
830 hTransferMatT->SetMarkerSize(0.15);
831 minz = hTransferMatT->GetMinimum();
832 if (fabs(0-maxz)>fabs(0-minz)) hTransferMatT->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
833 else hTransferMatT->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
834 if(PlotText) hTransferMatT->Draw(
"COLZ TEXT");
835 else hTransferMatT->Draw(
"COLZ");
836 c1->Print(
"Debug_PCA.pdf");
837 delete hTransferMatT;
839 delete heigen_vectors;
841 c1->Print(
"Debug_PCA.pdf]");
844 gErrorIgnoreLevel = originalErrorWarning;
846 #pragma GCC diagnostic pop
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
#define _MaCh3_Safe_Include_End_
#define _restrict_
KS: Using restrict limits the effects of pointer aliasing, aiding optimizations. While reading I foun...
Definitions of generic parameter structs and utility templates for MaCh3.
std::string SplineInterpolation_ToString(const SplineInterpolation i)
Convert a LLH type to a string.
std::string YAMLtoSTRING(const YAML::Node &node)
KS: Convert a YAML node to a string representation.
Custom exception class used throughout MaCh3.
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...
Main namespace for MaCh3 software.
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 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.
double * MatrixMult(double *A, double *B, int n)
CW: Multi-threaded matrix multiplication.
void FixSampleNamesQuotes(std::string &yamlStr)
KS: Yaml emitter has problem and drops "", if you have special signs in you like * then there is prob...
void DumpParamHandlerToFile(const int _fNumPar, const std::vector< double > &_fPreFitValue, const std::vector< double > &_fError, const std::vector< double > &_fLowBound, const std::vector< double > &_fUpBound, const std::vector< double > &_fIndivStepScale, const std::vector< std::string > &_fFancyNames, const std::vector< bool > &_fFlatPrior, const std::vector< SplineParameter > &SplineParams, TMatrixDSym *covMatrix, TH2D *CorrMatrix, const std::string &Name)
Dump Matrix to ROOT file, useful when we need to pass matrix info to another fitting group.
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.
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.
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.
void MakeMatrixPosDef(TMatrixDSym *cov)
Makes sure that matrix is positive-definite by adding a small number to on-diagonal elements.
TMatrixDSym * GetCovMatrixFromChain(TDirectory *TempFile)
KS: Retrieve the cross-section covariance matrix from the given TDirectory. Historically,...
bool CanDecomposeMatrix(const TMatrixDSym &matrix)
Checks if a matrix can be Cholesky decomposed.
TMacro * GetConfigMacroFromChain(TDirectory *CovarianceFolder)
KS: We store configuration macros inside the chain. In the past, multiple configs were stored,...
void DebugPCA(const double sum, const TMatrixD &temp, const TMatrixD &eigen_vectors, const TVectorD &eigen_values, const TMatrixD &TransferMat, const TMatrixD &TransferMatT, const int NumPar, const int FirstPCAdpar, const int LastPCAdpar, const int nKeptPCApars, const double eigen_threshold)
KS: Let's dump all useful matrices to properly validate PCA.
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 c...
Flat representation of a spline index entry.