9 #include "TMatrixDSym.h"
17 #include "TDecompChol.h"
18 #include "TStopwatch.h"
20 #include "TMatrixDSymEigen.h"
21 #include "TMatrixDEigen.h"
22 #include "TDecompSVD.h"
46 std::transform(Text.begin(), Text.end(), Text.begin(), ::tolower);
49 std::transform(Pattern.begin(), Pattern.end(), Pattern.begin(), ::tolower);
52 std::string RegexPattern =
"^" + std::regex_replace(Pattern, std::regex(
"\\*"),
".*") +
"$";
53 std::regex Regex(RegexPattern);
54 return std::regex_match(Text, Regex);
56 catch (
const std::regex_error& e) {
66 for (
size_t i = 0; i < Patterns.size(); i++) {
77 double *BT =
new double[n*n];
79 #pragma omp parallel for
81 for (
int i = 0; i < n; i++) {
82 for (
int j = 0; j < n; j++) {
88 double *C =
new double[n*n];
90 #pragma omp parallel for
92 for (
int i = 0; i < n; i++) {
93 for (
int j = 0; j < n; j++) {
95 for (
int k = 0; k < n; k++) {
96 sum += A[i*n+k]*BT[j*n+k];
109 double *A_mon =
new double[n*n];
110 double *B_mon =
new double[n*n];
113 #pragma omp parallel for
115 for (
int i = 0; i < n; ++i) {
116 for (
int j = 0; j < n; ++j) {
117 A_mon[i*n+j] = A[i][j];
118 B_mon[i*n+j] = B[i][j];
127 double **C =
new double*[n];
129 #pragma omp parallel for
131 for (
int i = 0; i < n; ++i) {
132 C[i] =
new double[n];
133 for (
int j = 0; j < n; ++j) {
134 C[i][j] = C_mon[i*n+j];
145 double *C_mon =
MatrixMult(A.GetMatrixArray(), B.GetMatrixArray(), A.GetNcols());
147 C.Use(A.GetNcols(), A.GetNrows(), C_mon);
160 #pragma omp parallel for
162 for (
int i = 0; i < n; ++i)
168 for (
int j = 0; j < n; ++j)
170 result += matrix[i][j]*vector[j];
172 VecMulti[i] = result;
184 double Element = 0.0;
188 for (
int j = 0; j < Length; ++j) {
189 Element += matrix[i][j]*vector[j];
199 std::stringstream input(yamlStr);
201 std::string fixedYaml;
202 std::regex sampleNamesRegex(R
"(SampleNames:\s*\[([^\]]+)\])");
204 while (std::getline(input, line)) {
206 if (std::regex_search(line, match, sampleNamesRegex)) {
207 std::string contents = match[1];
208 std::stringstream ss(contents);
210 std::vector<std::string> quotedItems;
212 while (std::getline(ss, item,
',')) {
213 item = std::regex_replace(item, std::regex(R
"(^\s+|\s+$)"), "");
214 quotedItems.push_back(
"\"" + item +
"\"");
217 std::string replacement =
"SampleNames: [" + fmt::format(
"{}",
fmt::join(quotedItems,
", ")) +
"]";
218 line = std::regex_replace(line, sampleNamesRegex, replacement);
220 fixedYaml += line +
"\n";
233 const std::vector<double>& Values,
234 const std::string& Tune,
235 const std::vector<std::string>& FancyNames = {}) {
238 YAML::Node systematics = NodeCopy[
"Systematics"];
240 if (!systematics || !systematics.IsSequence()) {
241 MACH3LOG_ERROR(
"'Systematics' node is missing or not a sequence in the YAML copy");
245 if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
246 MACH3LOG_ERROR(
"Mismatch in sizes: FancyNames has {}, but Values has {}", FancyNames.size(), Values.size());
250 if (FancyNames.empty() && systematics.size() != Values.size()) {
251 MACH3LOG_ERROR(
"Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
252 Values.size(), systematics.size());
256 if (!FancyNames.empty()) {
257 for (std::size_t i = 0; i < FancyNames.size(); ++i) {
258 bool matched =
false;
259 for (std::size_t j = 0; j < systematics.size(); ++j) {
260 YAML::Node systematicNode = systematics[j][
"Systematic"];
261 if (!systematicNode)
continue;
262 auto nameNode = systematicNode[
"Names"];
263 if (!nameNode || !nameNode[
"FancyName"])
continue;
264 if (nameNode[
"FancyName"].as<std::string>() == FancyNames[i]) {
265 if (!systematicNode[
"ParameterValues"]) {
266 MACH3LOG_ERROR(
"Missing 'ParameterValues' for matched FancyName '{}'", FancyNames[i]);
275 MACH3LOG_ERROR(
"Could not find a matching FancyName '{}' in the systematics", FancyNames[i]);
280 for (std::size_t i = 0; i < systematics.size(); ++i) {
281 YAML::Node systematicNode = systematics[i][
"Systematic"];
282 if (!systematicNode || !systematicNode[
"ParameterValues"]) {
283 MACH3LOG_ERROR(
"Missing 'Systematic' or 'ParameterValues' entry at index {}", i);
294 std::string OutName =
"UpdatedMatrixWithTune" + Tune +
".yaml";
295 std::ofstream outFile(OutName);
301 outFile << YAMLString;
314 const std::vector<double>& Values,
315 const std::vector<double>& Errors,
316 const std::vector<std::vector<double>>& Correlation,
317 const std::string& OutYAMLName,
318 const std::vector<std::string>& FancyNames = {}) {
320 if (Values.size() != Errors.size() || Values.size() != Correlation.size()) {
321 MACH3LOG_ERROR(
"Size mismatch between Values, Errors, and Correlation matrix");
325 for (
const auto& row : Correlation) {
326 if (row.size() != Correlation.size()) {
333 YAML::Node systematics = NodeCopy[
"Systematics"];
335 if (!systematics || !systematics.IsSequence()) {
336 MACH3LOG_ERROR(
"'Systematics' node is missing or not a sequence");
340 if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
341 MACH3LOG_ERROR(
"FancyNames size ({}) does not match Values size ({})", FancyNames.size(), Values.size());
346 std::unordered_map<std::string, YAML::Node> nameToNode;
347 for (std::size_t i = 0; i < systematics.size(); ++i) {
348 YAML::Node syst = systematics[i][
"Systematic"];
349 if (!syst || !syst[
"Names"] || !syst[
"Names"][
"FancyName"])
continue;
350 std::string name = syst[
"Names"][
"FancyName"].as<std::string>();
351 nameToNode[name] = syst;
354 if (!FancyNames.empty()) {
355 for (std::size_t i = 0; i < FancyNames.size(); ++i) {
356 const std::string& name_i = FancyNames[i];
357 auto it_i = nameToNode.find(name_i);
358 if (it_i == nameToNode.end()) {
362 YAML::Node& syst_i = it_i->second;
367 YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
368 for (std::size_t j = 0; j < FancyNames.size(); ++j) {
369 if (i == j)
continue;
371 if (std::abs(Correlation[i][j]) < 1e-8)
continue;
372 YAML::Node singleEntry;
374 correlationsNode.push_back(singleEntry);
376 syst_i[
"Correlations"] = correlationsNode;
379 if (systematics.size() != Values.size()) {
380 MACH3LOG_ERROR(
"Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
381 Values.size(), systematics.size());
385 for (std::size_t i = 0; i < systematics.size(); ++i) {
386 YAML::Node syst = systematics[i][
"Systematic"];
395 YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
396 for (std::size_t j = 0; j < Correlation[i].size(); ++j) {
397 if (i == j)
continue;
399 if (std::abs(Correlation[i][j]) < 1e-8)
continue;
400 YAML::Node singleEntry;
401 const std::string& otherName = systematics[j][
"Systematic"][
"Names"][
"FancyName"].as<std::string>();
403 correlationsNode.push_back(singleEntry);
405 syst[
"Correlations"] = correlationsNode;
412 std::ofstream outFile(OutYAMLName);
414 MACH3LOG_ERROR(
"Failed to open file for writing: {}", OutYAMLName);
418 outFile << YAMLString;
429 if (!CovarianceFolder) {
434 TMacro* foundMacro =
nullptr;
437 TIter next(CovarianceFolder->GetListOfKeys());
439 while ((key =
dynamic_cast<TKey*
>(next()))) {
440 if (std::string(key->GetClassName()) ==
"TMacro") {
442 if (macroCount == 1) {
443 foundMacro =
dynamic_cast<TMacro*
>(key->ReadObj());
448 if (macroCount == 1 && foundMacro) {
449 MACH3LOG_INFO(
"Found single TMacro in directory: using it.");
452 MACH3LOG_WARN(
"Found {} TMacro objects. Using hardcoded macro name: Config_xsec_cov.", macroCount);
453 TMacro* fallback = CovarianceFolder->Get<TMacro>(
"Config_xsec_cov");
455 MACH3LOG_WARN(
"Fallback macro 'Config_xsec_cov' not found in directory.");
475 TMatrixDSym* foundMatrix =
nullptr;
478 TIter next(TempFile->GetListOfKeys());
480 while ((key =
dynamic_cast<TKey*
>(next()))) {
481 std::string className = key->GetClassName();
482 if (className.find(
"TMatrix") != std::string::npos) {
484 if (matrixCount == 1) {
485 foundMatrix =
dynamic_cast<TMatrixDSym*
>(key->ReadObj());
490 if (matrixCount == 1 && foundMatrix) {
491 MACH3LOG_INFO(
"Found single TMatrixDSym in directory: using it.");
494 MACH3LOG_WARN(
"Found {} TMatrixDSym objects. Using hardcoded path: xsec_cov.", matrixCount);
495 TMatrixDSym* fallback = TempFile->Get<TMatrixDSym>(
"xsec_cov");
509 const Int_t n = matrix.GetNrows();
510 std::vector<std::vector<double>> L(n, std::vector<double>(n, 0.0));
512 for (Int_t j = 0; j < n; ++j) {
514 double sum_diag = matrix(j, j);
515 for (Int_t k = 0; k < j; ++k) {
516 sum_diag -= L[j][k] * L[j][k];
518 const double tol = 1e-15;
519 if (sum_diag <= tol) {
520 MACH3LOG_ERROR(
"Cholesky decomposition failed for {} (non-positive diagonal)", matrixName);
523 L[j][j] = std::sqrt(sum_diag);
527 #pragma omp parallel for
529 for (Int_t i = j + 1; i < n; ++i) {
530 double sum = matrix(i, j);
531 for (Int_t k = 0; k < j; ++k) {
532 sum -= L[i][k] * L[j][k];
534 L[i][j] = sum / L[j][j];
545 TDecompChol chdcmp(matrix);
546 return chdcmp.Decompose();
555 int originalErrorWarning = gErrorIgnoreLevel;
556 gErrorIgnoreLevel = kFatal;
559 constexpr
int MaxAttempts = 1e5;
560 const int matrixSize = cov->GetNrows();
562 bool CanDecomp =
false;
565 std::vector<double> original_diagonal(matrixSize, 0.0);
566 for (
int iVar = 0 ; iVar < matrixSize; iVar++) {
567 original_diagonal[iVar] = (*cov)(iVar, iVar);
572 for (iAttempt = 0; iAttempt < MaxAttempts; iAttempt++) {
580 #pragma omp parallel for
582 for (
int iVar = 0 ; iVar < matrixSize; iVar++) {
583 if( (*cov)(iVar, iVar)/10 > original_diagonal[iVar]) {
584 MACH3LOG_DEBUG(
"Diagonal element {} has been shifted too much (> original value/10). Stopping further shifts.", iVar);
585 original_diagonal[iVar] = 0;
588 (*cov)(iVar, iVar) += 1e-9;
594 MACH3LOG_ERROR(
"Tried {} times to shift diagonal but still can not decompose the matrix", MaxAttempts);
595 MACH3LOG_ERROR(
"This indicates that something is wrong with the input matrix");
600 gErrorIgnoreLevel = originalErrorWarning;
610 const std::vector<double>& _fPreFitValue,
611 const std::vector<double>& _fError,
612 const std::vector<double>& _fLowBound,
613 const std::vector<double>& _fUpBound,
614 const std::vector<double>& _fIndivStepScale,
615 const std::vector<std::string>& _fFancyNames,
616 const std::vector<bool>& _fFlatPrior,
617 const std::vector<SplineParameter>& SplineParams,
618 TMatrixDSym* covMatrix,
620 const std::string& Name) {
622 TFile* outputFile =
new TFile(Name.c_str(),
"RECREATE");
624 TObjArray* param_names =
new TObjArray();
625 TObjArray* spline_interpolation =
new TObjArray();
626 TObjArray* spline_names =
new TObjArray();
628 TVectorD* param_prior =
new TVectorD(_fNumPar);
629 TVectorD* flat_prior =
new TVectorD(_fNumPar);
630 TVectorD* stepscale =
new TVectorD(_fNumPar);
631 TVectorD* param_lb =
new TVectorD(_fNumPar);
632 TVectorD* param_ub =
new TVectorD(_fNumPar);
634 TVectorD* param_knot_weight_lb =
new TVectorD(_fNumPar);
635 TVectorD* param_knot_weight_ub =
new TVectorD(_fNumPar);
636 TVectorD* error =
new TVectorD(_fNumPar);
638 for(
int i = 0; i < _fNumPar; ++i)
640 TObjString* nameObj =
new TObjString(_fFancyNames[i].c_str());
641 param_names->AddLast(nameObj);
643 TObjString* splineType =
new TObjString(
"TSpline3");
644 spline_interpolation->AddLast(splineType);
646 TObjString* splineName =
new TObjString(
"");
647 spline_names->AddLast(splineName);
649 (*param_prior)[i] = _fPreFitValue[i];
650 (*flat_prior)[i] = _fFlatPrior[i];
651 (*stepscale)[i] = _fIndivStepScale[i];
652 (*error)[i] = _fError[i];
654 (*param_lb)[i] = _fLowBound[i];
655 (*param_ub)[i] = _fUpBound[i];
658 (*param_knot_weight_lb)[i] = -9999;
659 (*param_knot_weight_ub)[i] = +9999;
665 (*param_knot_weight_lb)[SystIndex] = SplineParams.at(
SplineIndex)._SplineKnotLowBound;
666 (*param_knot_weight_ub)[SystIndex] = SplineParams.at(
SplineIndex)._SplineKnotUpBound;
669 spline_interpolation->AddAt(splineType, SystIndex);
671 TObjString* splineName =
new TObjString(SplineParams[
SplineIndex]._fSplineNames.c_str());
672 spline_names->AddAt(splineName, SystIndex);
674 param_names->Write(
"xsec_param_names", TObject::kSingleKey);
676 spline_interpolation->Write(
"xsec_spline_interpolation", TObject::kSingleKey);
677 delete spline_interpolation;
678 spline_names->Write(
"xsec_spline_names", TObject::kSingleKey);
681 param_prior->Write(
"xsec_param_prior");
683 flat_prior->Write(
"xsec_flat_prior");
685 stepscale->Write(
"xsec_stepscale");
687 param_lb->Write(
"xsec_param_lb");
689 param_ub->Write(
"xsec_param_ub");
692 param_knot_weight_lb->Write(
"xsec_param_knot_weight_lb");
693 delete param_knot_weight_lb;
694 param_knot_weight_ub->Write(
"xsec_param_knot_weight_ub");
695 delete param_knot_weight_ub;
696 error->Write(
"xsec_error");
699 covMatrix->Write(
"xsec_cov");
700 CorrMatrix->Write(
"hcov");
710 const TMatrixD& temp,
711 const TMatrixD& eigen_vectors,
712 const TVectorD& eigen_values,
713 const TMatrixD& TransferMat,
714 const TMatrixD& TransferMatT,
716 const int FirstPCAdpar,
717 const int LastPCAdpar,
718 const int nKeptPCApars,
719 const double eigen_threshold) {
721 #pragma GCC diagnostic push
722 #pragma GCC diagnostic ignored "-Wfloat-conversion"
723 int originalErrorWarning = gErrorIgnoreLevel;
724 gErrorIgnoreLevel = kFatal;
726 TDirectory *ogdir = gDirectory;
728 TFile *PCA_Debug =
new TFile(
"Debug_PCA.root",
"RECREATE");
731 bool PlotText =
true;
733 if(NumPar > 200) PlotText =
false;
735 auto heigen_values = std::make_unique<TH1D>(
"eigen_values",
"Eigen Values", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
736 heigen_values->SetDirectory(
nullptr);
737 auto heigen_cumulative = std::make_unique<TH1D>(
"heigen_cumulative",
"heigen_cumulative", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
738 heigen_cumulative->SetDirectory(
nullptr);
739 auto heigen_frac = std::make_unique<TH1D>(
"heigen_fractional",
"heigen_fractional", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
740 heigen_frac->SetDirectory(
nullptr);
741 heigen_values->GetXaxis()->SetTitle(
"Eigen Vector");
742 heigen_values->GetYaxis()->SetTitle(
"Eigen Value");
744 double Cumulative = 0;
745 for(
int i = 0; i < eigen_values.GetNrows(); i++)
747 heigen_values->SetBinContent(i+1, (eigen_values)(i));
748 heigen_cumulative->SetBinContent(i+1, (eigen_values)(i)/sum + Cumulative);
749 heigen_frac->SetBinContent(i+1, (eigen_values)(i)/sum);
750 Cumulative += (eigen_values)(i)/sum;
752 heigen_values->Write(
"heigen_values");
753 eigen_values.Write(
"eigen_values");
754 heigen_cumulative->Write(
"heigen_values_cumulative");
755 heigen_frac->Write(
"heigen_values_frac");
757 TH2D* heigen_vectors =
new TH2D(eigen_vectors);
758 heigen_vectors->GetXaxis()->SetTitle(
"Parameter in Normal Base");
759 heigen_vectors->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
760 heigen_vectors->Write(
"heigen_vectors");
761 eigen_vectors.Write(
"eigen_vectors");
763 TH2D* SubsetPCA =
new TH2D(temp);
764 SubsetPCA->GetXaxis()->SetTitle(
"Parameter in Normal Base");
765 SubsetPCA->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
767 SubsetPCA->Write(
"hSubsetPCA");
768 temp.Write(
"SubsetPCA");
769 TH2D* hTransferMat =
new TH2D(TransferMat);
770 hTransferMat->GetXaxis()->SetTitle(
"Parameter in Normal Base");
771 hTransferMat->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
772 TH2D* hTransferMatT =
new TH2D(TransferMatT);
774 hTransferMatT->GetXaxis()->SetTitle(
"Parameter in Decomposed Base");
775 hTransferMatT->GetYaxis()->SetTitle(
"Parameter in Normal Base");
777 hTransferMat->Write(
"hTransferMat");
778 TransferMat.Write(
"TransferMat");
779 hTransferMatT->Write(
"hTransferMatT");
780 TransferMatT.Write(
"TransferMatT");
782 auto c1 = std::make_unique<TCanvas>(
"c1",
" ", 0, 0, 1024, 1024);
783 c1->SetBottomMargin(0.1);
784 c1->SetTopMargin(0.05);
785 c1->SetRightMargin(0.05);
786 c1->SetLeftMargin(0.12);
789 gStyle->SetPaintTextFormat(
"4.1f");
790 gStyle->SetOptFit(0);
791 gStyle->SetOptStat(0);
793 constexpr
int NRGBs = 5;
794 TColor::InitializeColors();
795 Double_t stops[NRGBs] = { 0.00, 0.25, 0.50, 0.75, 1.00 };
796 Double_t red[NRGBs] = { 0.00, 0.25, 1.00, 1.00, 0.50 };
797 Double_t green[NRGBs] = { 0.00, 0.25, 1.00, 0.25, 0.00 };
798 Double_t blue[NRGBs] = { 0.50, 1.00, 1.00, 0.25, 0.00 };
799 TColor::CreateGradientColorTable(5, stops, red, green, blue, 255);
800 gStyle->SetNumberContours(255);
805 c1->Print(
"Debug_PCA.pdf[");
806 auto EigenLine = std::make_unique<TLine>(nKeptPCApars, 0, nKeptPCApars, heigen_cumulative->GetMaximum());
807 EigenLine->SetLineColor(kPink);
808 EigenLine->SetLineWidth(2);
809 EigenLine->SetLineStyle(kSolid);
811 auto text = std::make_unique<TText>(0.5, 0.5, Form(
"Threshold = %g", eigen_threshold));
812 text->SetTextFont (43);
813 text->SetTextSize (40);
815 heigen_values->SetLineColor(kRed);
816 heigen_values->SetLineWidth(2);
817 heigen_cumulative->SetLineColor(kGreen);
818 heigen_cumulative->SetLineWidth(2);
819 heigen_frac->SetLineColor(kBlue);
820 heigen_frac->SetLineWidth(2);
823 heigen_values->SetMaximum(heigen_cumulative->GetMaximum()+heigen_cumulative->GetMaximum()*0.4);
824 heigen_values->Draw();
825 heigen_frac->Draw(
"SAME");
826 heigen_cumulative->Draw(
"SAME");
827 EigenLine->Draw(
"Same");
828 text->DrawTextNDC(0.42, 0.84,Form(
"Threshold = %g", eigen_threshold));
830 auto leg = std::make_unique<TLegend>(0.2, 0.2, 0.6, 0.5);
831 leg->SetTextSize(0.04);
832 leg->AddEntry(heigen_values.get(),
"Absolute",
"l");
833 leg->AddEntry(heigen_frac.get(),
"Fractional",
"l");
834 leg->AddEntry(heigen_cumulative.get(),
"Cumulative",
"l");
836 leg->SetLineColor(0);
837 leg->SetLineStyle(0);
838 leg->SetFillColor(0);
839 leg->SetFillStyle(0);
842 c1->Print(
"Debug_PCA.pdf");
843 c1->SetRightMargin(0.15);
846 heigen_vectors->SetMarkerSize(0.2);
847 minz = heigen_vectors->GetMinimum();
848 if (fabs(0-maxz)>fabs(0-minz)) heigen_vectors->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
849 else heigen_vectors->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
850 if(PlotText) heigen_vectors->Draw(
"COLZ TEXT");
851 else heigen_vectors->Draw(
"COLZ");
853 auto Eigen_Line = std::make_unique<TLine>(0, nKeptPCApars, LastPCAdpar - FirstPCAdpar, nKeptPCApars);
854 Eigen_Line->SetLineColor(kGreen);
855 Eigen_Line->SetLineWidth(2);
856 Eigen_Line->SetLineStyle(kDotted);
857 Eigen_Line->Draw(
"SAME");
858 c1->Print(
"Debug_PCA.pdf");
860 SubsetPCA->SetMarkerSize(0.2);
861 minz = SubsetPCA->GetMinimum();
862 if (fabs(0-maxz)>fabs(0-minz)) SubsetPCA->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
863 else SubsetPCA->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
864 if(PlotText) SubsetPCA->Draw(
"COLZ TEXT");
865 else SubsetPCA->Draw(
"COLZ");
866 c1->Print(
"Debug_PCA.pdf");
869 hTransferMat->SetMarkerSize(0.15);
870 minz = hTransferMat->GetMinimum();
871 if (fabs(0-maxz)>fabs(0-minz)) hTransferMat->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
872 else hTransferMat->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
873 if(PlotText) hTransferMat->Draw(
"COLZ TEXT");
874 else hTransferMat->Draw(
"COLZ");
875 c1->Print(
"Debug_PCA.pdf");
878 hTransferMatT->SetMarkerSize(0.15);
879 minz = hTransferMatT->GetMinimum();
880 if (fabs(0-maxz)>fabs(0-minz)) hTransferMatT->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
881 else hTransferMatT->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
882 if(PlotText) hTransferMatT->Draw(
"COLZ TEXT");
883 else hTransferMatT->Draw(
"COLZ");
884 c1->Print(
"Debug_PCA.pdf");
885 delete hTransferMatT;
887 delete heigen_vectors;
889 c1->Print(
"Debug_PCA.pdf]");
892 gErrorIgnoreLevel = originalErrorWarning;
894 #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...
std::string join(const Container &values, std::string_view separator=" ")
Join all values in a container into a single string.
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...
bool CaseInsentiveMatch(std::string Text, std::string Pattern)
Matches a string against a simple wildcard Pattern using regex. Is not case sensitive.
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.
int 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.
bool CaseInsensitiveMatchAny(std::string Text, const std::vector< std::string > &Patterns)
Matches a string against a simple wildcard Pattern using regex. Is not case sensitive.
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.