9 #include "TMatrixDSym.h"
18 #include "TDecompChol.h"
19 #include "TStopwatch.h"
21 #include "TMatrixDSymEigen.h"
22 #include "TMatrixDEigen.h"
23 #include "TDecompSVD.h"
47 std::transform(Text.begin(), Text.end(), Text.begin(), ::tolower);
50 std::transform(Pattern.begin(), Pattern.end(), Pattern.begin(), ::tolower);
53 std::string RegexPattern =
"^" + std::regex_replace(Pattern, std::regex(
"\\*"),
".*") +
"$";
54 std::regex Regex(RegexPattern);
55 return std::regex_match(Text, Regex);
57 catch (
const std::regex_error& e) {
67 for (
size_t i = 0; i < Patterns.size(); i++) {
78 double *BT =
new double[n*n];
80 #pragma omp parallel for
82 for (
int i = 0; i < n; i++) {
83 for (
int j = 0; j < n; j++) {
89 double *C =
new double[n*n];
91 #pragma omp parallel for
93 for (
int i = 0; i < n; i++) {
94 for (
int j = 0; j < n; j++) {
96 for (
int k = 0; k < n; k++) {
97 sum += A[i*n+k]*BT[j*n+k];
110 double *A_mon =
new double[n*n];
111 double *B_mon =
new double[n*n];
114 #pragma omp parallel for
116 for (
int i = 0; i < n; ++i) {
117 for (
int j = 0; j < n; ++j) {
118 A_mon[i*n+j] = A[i][j];
119 B_mon[i*n+j] = B[i][j];
128 double **C =
new double*[n];
130 #pragma omp parallel for
132 for (
int i = 0; i < n; ++i) {
133 C[i] =
new double[n];
134 for (
int j = 0; j < n; ++j) {
135 C[i][j] = C_mon[i*n+j];
146 double *C_mon =
MatrixMult(A.GetMatrixArray(), B.GetMatrixArray(), A.GetNcols());
148 C.Use(A.GetNcols(), A.GetNrows(), C_mon);
161 #pragma omp parallel for
163 for (
int i = 0; i < n; ++i)
169 for (
int j = 0; j < n; ++j)
171 result += matrix[i][j]*vector[j];
173 VecMulti[i] = result;
185 double Element = 0.0;
189 for (
int j = 0; j < Length; ++j) {
190 Element += matrix[i][j]*vector[j];
200 std::stringstream input(yamlStr);
202 std::string fixedYaml;
203 std::regex sampleNamesRegex(R
"(SampleNames:\s*\[([^\]]+)\])");
205 while (std::getline(input, line)) {
207 if (std::regex_search(line, match, sampleNamesRegex)) {
208 std::string contents = match[1];
209 std::stringstream ss(contents);
211 std::vector<std::string> quotedItems;
213 while (std::getline(ss, item,
',')) {
214 item = std::regex_replace(item, std::regex(R
"(^\s+|\s+$)"), "");
215 quotedItems.push_back(
"\"" + item +
"\"");
218 std::string replacement =
"SampleNames: [" + fmt::format(
"{}", fmt::join(quotedItems,
", ")) +
"]";
219 line = std::regex_replace(line, sampleNamesRegex, replacement);
221 fixedYaml += line +
"\n";
234 const std::vector<double>& Values,
235 const std::string& Tune,
236 const std::vector<std::string>& FancyNames = {}) {
239 YAML::Node systematics = NodeCopy[
"Systematics"];
241 if (!systematics || !systematics.IsSequence()) {
242 MACH3LOG_ERROR(
"'Systematics' node is missing or not a sequence in the YAML copy");
246 if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
247 MACH3LOG_ERROR(
"Mismatch in sizes: FancyNames has {}, but Values has {}", FancyNames.size(), Values.size());
251 if (FancyNames.empty() && systematics.size() != Values.size()) {
252 MACH3LOG_ERROR(
"Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
253 Values.size(), systematics.size());
257 if (!FancyNames.empty()) {
258 for (std::size_t i = 0; i < FancyNames.size(); ++i) {
259 bool matched =
false;
260 for (std::size_t j = 0; j < systematics.size(); ++j) {
261 YAML::Node systematicNode = systematics[j][
"Systematic"];
262 if (!systematicNode)
continue;
263 auto nameNode = systematicNode[
"Names"];
264 if (!nameNode || !nameNode[
"FancyName"])
continue;
265 if (nameNode[
"FancyName"].as<std::string>() == FancyNames[i]) {
266 if (!systematicNode[
"ParameterValues"]) {
267 MACH3LOG_ERROR(
"Missing 'ParameterValues' for matched FancyName '{}'", FancyNames[i]);
276 MACH3LOG_ERROR(
"Could not find a matching FancyName '{}' in the systematics", FancyNames[i]);
281 for (std::size_t i = 0; i < systematics.size(); ++i) {
282 YAML::Node systematicNode = systematics[i][
"Systematic"];
283 if (!systematicNode || !systematicNode[
"ParameterValues"]) {
284 MACH3LOG_ERROR(
"Missing 'Systematic' or 'ParameterValues' entry at index {}", i);
295 std::string OutName =
"UpdatedMatrixWithTune" + Tune +
".yaml";
296 std::ofstream outFile(OutName);
302 outFile << YAMLString;
315 const std::vector<double>& Values,
316 const std::vector<double>& Errors,
317 const std::vector<std::vector<double>>& Correlation,
318 const std::string& OutYAMLName,
319 const std::vector<std::string>& FancyNames = {}) {
321 if (Values.size() != Errors.size() || Values.size() != Correlation.size()) {
322 MACH3LOG_ERROR(
"Size mismatch between Values, Errors, and Correlation matrix");
326 for (
const auto& row : Correlation) {
327 if (row.size() != Correlation.size()) {
334 YAML::Node systematics = NodeCopy[
"Systematics"];
336 if (!systematics || !systematics.IsSequence()) {
337 MACH3LOG_ERROR(
"'Systematics' node is missing or not a sequence");
341 if (!FancyNames.empty() && FancyNames.size() != Values.size()) {
342 MACH3LOG_ERROR(
"FancyNames size ({}) does not match Values size ({})", FancyNames.size(), Values.size());
347 std::unordered_map<std::string, YAML::Node> nameToNode;
348 for (std::size_t i = 0; i < systematics.size(); ++i) {
349 YAML::Node syst = systematics[i][
"Systematic"];
350 if (!syst || !syst[
"Names"] || !syst[
"Names"][
"FancyName"])
continue;
351 std::string name = syst[
"Names"][
"FancyName"].as<std::string>();
352 nameToNode[name] = syst;
355 if (!FancyNames.empty()) {
356 for (std::size_t i = 0; i < FancyNames.size(); ++i) {
357 const std::string& name_i = FancyNames[i];
358 auto it_i = nameToNode.find(name_i);
359 if (it_i == nameToNode.end()) {
363 YAML::Node& syst_i = it_i->second;
368 YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
369 for (std::size_t j = 0; j < FancyNames.size(); ++j) {
370 if (i == j)
continue;
372 if (std::abs(Correlation[i][j]) < 1e-8)
continue;
373 YAML::Node singleEntry;
375 correlationsNode.push_back(singleEntry);
377 syst_i[
"Correlations"] = correlationsNode;
380 if (systematics.size() != Values.size()) {
381 MACH3LOG_ERROR(
"Mismatch in sizes: Values has {}, but YAML 'Systematics' has {} entries",
382 Values.size(), systematics.size());
386 for (std::size_t i = 0; i < systematics.size(); ++i) {
387 YAML::Node syst = systematics[i][
"Systematic"];
396 YAML::Node correlationsNode = YAML::Node(YAML::NodeType::Sequence);
397 for (std::size_t j = 0; j < Correlation[i].size(); ++j) {
398 if (i == j)
continue;
400 if (std::abs(Correlation[i][j]) < 1e-8)
continue;
401 YAML::Node singleEntry;
402 const std::string& otherName = systematics[j][
"Systematic"][
"Names"][
"FancyName"].as<std::string>();
404 correlationsNode.push_back(singleEntry);
406 syst[
"Correlations"] = correlationsNode;
413 std::ofstream outFile(OutYAMLName);
415 MACH3LOG_ERROR(
"Failed to open file for writing: {}", OutYAMLName);
419 outFile << YAMLString;
430 if (!CovarianceFolder) {
435 TMacro* foundMacro =
nullptr;
438 TIter next(CovarianceFolder->GetListOfKeys());
440 while ((key =
dynamic_cast<TKey*
>(next()))) {
441 if (std::string(key->GetClassName()) ==
"TMacro") {
443 if (macroCount == 1) {
444 foundMacro =
dynamic_cast<TMacro*
>(key->ReadObj());
449 if (macroCount == 1 && foundMacro) {
450 MACH3LOG_INFO(
"Found single TMacro in directory: using it.");
453 MACH3LOG_WARN(
"Found {} TMacro objects. Using hardcoded macro name: Config_xsec_cov.", macroCount);
454 TMacro* fallback = CovarianceFolder->Get<TMacro>(
"Config_xsec_cov");
456 MACH3LOG_WARN(
"Fallback macro 'Config_xsec_cov' not found in directory.");
476 TMatrixDSym* foundMatrix =
nullptr;
479 TIter next(TempFile->GetListOfKeys());
481 while ((key =
dynamic_cast<TKey*
>(next()))) {
482 std::string className = key->GetClassName();
483 if (className.find(
"TMatrix") != std::string::npos) {
485 if (matrixCount == 1) {
486 foundMatrix =
dynamic_cast<TMatrixDSym*
>(key->ReadObj());
491 if (matrixCount == 1 && foundMatrix) {
492 MACH3LOG_INFO(
"Found single TMatrixDSym in directory: using it.");
495 MACH3LOG_WARN(
"Found {} TMatrixDSym objects. Using hardcoded path: xsec_cov.", matrixCount);
496 TMatrixDSym* fallback = TempFile->Get<TMatrixDSym>(
"xsec_cov");
510 const Int_t n = matrix.GetNrows();
511 std::vector<std::vector<double>> L(n, std::vector<double>(n, 0.0));
513 for (Int_t j = 0; j < n; ++j) {
515 double sum_diag = matrix(j, j);
516 for (Int_t k = 0; k < j; ++k) {
517 sum_diag -= L[j][k] * L[j][k];
519 const double tol = 1e-15;
520 if (sum_diag <= tol) {
521 MACH3LOG_ERROR(
"Cholesky decomposition failed for {} (non-positive diagonal)", matrixName);
524 L[j][j] = std::sqrt(sum_diag);
528 #pragma omp parallel for
530 for (Int_t i = j + 1; i < n; ++i) {
531 double sum = matrix(i, j);
532 for (Int_t k = 0; k < j; ++k) {
533 sum -= L[i][k] * L[j][k];
535 L[i][j] = sum / L[j][j];
546 TDecompChol chdcmp(matrix);
547 return chdcmp.Decompose();
556 int originalErrorWarning = gErrorIgnoreLevel;
557 gErrorIgnoreLevel = kFatal;
560 constexpr
int MaxAttempts = 1e5;
561 const int matrixSize = cov->GetNrows();
563 bool CanDecomp =
false;
566 std::vector<double> original_diagonal(matrixSize, 0.0);
567 for (
int iVar = 0 ; iVar < matrixSize; iVar++) {
568 original_diagonal[iVar] = (*cov)(iVar, iVar);
573 for (iAttempt = 0; iAttempt < MaxAttempts; iAttempt++) {
581 #pragma omp parallel for
583 for (
int iVar = 0 ; iVar < matrixSize; iVar++) {
584 if( (*cov)(iVar, iVar)/10 > original_diagonal[iVar]) {
585 MACH3LOG_DEBUG(
"Diagonal element {} has been shifted too much (> original value/10). Stopping further shifts.", iVar);
586 original_diagonal[iVar] = 0;
589 (*cov)(iVar, iVar) += 1e-9;
595 MACH3LOG_ERROR(
"Tried {} times to shift diagonal but still can not decompose the matrix", MaxAttempts);
596 MACH3LOG_ERROR(
"This indicates that something is wrong with the input matrix");
601 gErrorIgnoreLevel = originalErrorWarning;
611 const std::vector<double>& _fPreFitValue,
612 const std::vector<double>& _fError,
613 const std::vector<double>& _fLowBound,
614 const std::vector<double>& _fUpBound,
615 const std::vector<double>& _fIndivStepScale,
616 const std::vector<std::string>& _fFancyNames,
617 const std::vector<bool>& _fFlatPrior,
618 const std::vector<SplineParameter>& SplineParams,
619 TMatrixDSym* covMatrix,
621 const std::string& Name) {
623 TFile* outputFile =
new TFile(Name.c_str(),
"RECREATE");
625 TObjArray* param_names =
new TObjArray();
626 TObjArray* spline_interpolation =
new TObjArray();
627 TObjArray* spline_names =
new TObjArray();
629 TVectorD* param_prior =
new TVectorD(_fNumPar);
630 TVectorD* flat_prior =
new TVectorD(_fNumPar);
631 TVectorD* stepscale =
new TVectorD(_fNumPar);
632 TVectorD* param_lb =
new TVectorD(_fNumPar);
633 TVectorD* param_ub =
new TVectorD(_fNumPar);
635 TVectorD* param_knot_weight_lb =
new TVectorD(_fNumPar);
636 TVectorD* param_knot_weight_ub =
new TVectorD(_fNumPar);
637 TVectorD* error =
new TVectorD(_fNumPar);
639 for(
int i = 0; i < _fNumPar; ++i)
641 TObjString* nameObj =
new TObjString(_fFancyNames[i].c_str());
642 param_names->AddLast(nameObj);
644 TObjString* splineType =
new TObjString(
"TSpline3");
645 spline_interpolation->AddLast(splineType);
647 TObjString* splineName =
new TObjString(
"");
648 spline_names->AddLast(splineName);
650 (*param_prior)[i] = _fPreFitValue[i];
651 (*flat_prior)[i] = _fFlatPrior[i];
652 (*stepscale)[i] = _fIndivStepScale[i];
653 (*error)[i] = _fError[i];
655 (*param_lb)[i] = _fLowBound[i];
656 (*param_ub)[i] = _fUpBound[i];
659 (*param_knot_weight_lb)[i] = -9999;
660 (*param_knot_weight_ub)[i] = +9999;
666 (*param_knot_weight_lb)[SystIndex] = SplineParams.at(
SplineIndex)._SplineKnotLowBound;
667 (*param_knot_weight_ub)[SystIndex] = SplineParams.at(
SplineIndex)._SplineKnotUpBound;
670 spline_interpolation->AddAt(splineType, SystIndex);
672 TObjString* splineName =
new TObjString(SplineParams[
SplineIndex]._fSplineNames.c_str());
673 spline_names->AddAt(splineName, SystIndex);
675 param_names->Write(
"xsec_param_names", TObject::kSingleKey);
677 spline_interpolation->Write(
"xsec_spline_interpolation", TObject::kSingleKey);
678 delete spline_interpolation;
679 spline_names->Write(
"xsec_spline_names", TObject::kSingleKey);
682 param_prior->Write(
"xsec_param_prior");
684 flat_prior->Write(
"xsec_flat_prior");
686 stepscale->Write(
"xsec_stepscale");
688 param_lb->Write(
"xsec_param_lb");
690 param_ub->Write(
"xsec_param_ub");
693 param_knot_weight_lb->Write(
"xsec_param_knot_weight_lb");
694 delete param_knot_weight_lb;
695 param_knot_weight_ub->Write(
"xsec_param_knot_weight_ub");
696 delete param_knot_weight_ub;
697 error->Write(
"xsec_error");
700 covMatrix->Write(
"xsec_cov");
701 CorrMatrix->Write(
"hcov");
711 const TMatrixD& temp,
712 const TMatrixD& eigen_vectors,
713 const TVectorD& eigen_values,
714 const TMatrixD& TransferMat,
715 const TMatrixD& TransferMatT,
717 const int FirstPCAdpar,
718 const int LastPCAdpar,
719 const int nKeptPCApars,
720 const double eigen_threshold) {
722 #pragma GCC diagnostic push
723 #pragma GCC diagnostic ignored "-Wfloat-conversion"
724 int originalErrorWarning = gErrorIgnoreLevel;
725 gErrorIgnoreLevel = kFatal;
727 TDirectory *ogdir = gDirectory;
729 TFile *PCA_Debug =
new TFile(
"Debug_PCA.root",
"RECREATE");
732 bool PlotText =
true;
734 if(NumPar > 200) PlotText =
false;
736 auto heigen_values = std::make_unique<TH1D>(
"eigen_values",
"Eigen Values", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
737 heigen_values->SetDirectory(
nullptr);
738 auto heigen_cumulative = std::make_unique<TH1D>(
"heigen_cumulative",
"heigen_cumulative", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
739 heigen_cumulative->SetDirectory(
nullptr);
740 auto heigen_frac = std::make_unique<TH1D>(
"heigen_fractional",
"heigen_fractional", eigen_values.GetNrows(), 0.0, eigen_values.GetNrows());
741 heigen_frac->SetDirectory(
nullptr);
742 heigen_values->GetXaxis()->SetTitle(
"Eigen Vector");
743 heigen_values->GetYaxis()->SetTitle(
"Eigen Value");
745 double Cumulative = 0;
746 for(
int i = 0; i < eigen_values.GetNrows(); i++)
748 heigen_values->SetBinContent(i+1, (eigen_values)(i));
749 heigen_cumulative->SetBinContent(i+1, (eigen_values)(i)/sum + Cumulative);
750 heigen_frac->SetBinContent(i+1, (eigen_values)(i)/sum);
751 Cumulative += (eigen_values)(i)/sum;
753 heigen_values->Write(
"heigen_values");
754 eigen_values.Write(
"eigen_values");
755 heigen_cumulative->Write(
"heigen_values_cumulative");
756 heigen_frac->Write(
"heigen_values_frac");
758 TH2D* heigen_vectors =
new TH2D(eigen_vectors);
759 heigen_vectors->GetXaxis()->SetTitle(
"Parameter in Normal Base");
760 heigen_vectors->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
761 heigen_vectors->Write(
"heigen_vectors");
762 eigen_vectors.Write(
"eigen_vectors");
764 TH2D* SubsetPCA =
new TH2D(temp);
765 SubsetPCA->GetXaxis()->SetTitle(
"Parameter in Normal Base");
766 SubsetPCA->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
768 SubsetPCA->Write(
"hSubsetPCA");
769 temp.Write(
"SubsetPCA");
770 TH2D* hTransferMat =
new TH2D(TransferMat);
771 hTransferMat->GetXaxis()->SetTitle(
"Parameter in Normal Base");
772 hTransferMat->GetYaxis()->SetTitle(
"Parameter in Decomposed Base");
773 TH2D* hTransferMatT =
new TH2D(TransferMatT);
775 hTransferMatT->GetXaxis()->SetTitle(
"Parameter in Decomposed Base");
776 hTransferMatT->GetYaxis()->SetTitle(
"Parameter in Normal Base");
778 hTransferMat->Write(
"hTransferMat");
779 TransferMat.Write(
"TransferMat");
780 hTransferMatT->Write(
"hTransferMatT");
781 TransferMatT.Write(
"TransferMatT");
783 auto c1 = std::make_unique<TCanvas>(
"c1",
" ", 0, 0, 1024, 1024);
784 c1->SetBottomMargin(0.1);
785 c1->SetTopMargin(0.05);
786 c1->SetRightMargin(0.05);
787 c1->SetLeftMargin(0.12);
790 gStyle->SetPaintTextFormat(
"4.1f");
791 gStyle->SetOptFit(0);
792 gStyle->SetOptStat(0);
794 constexpr
int NRGBs = 5;
795 TColor::InitializeColors();
796 Double_t stops[NRGBs] = { 0.00, 0.25, 0.50, 0.75, 1.00 };
797 Double_t red[NRGBs] = { 0.00, 0.25, 1.00, 1.00, 0.50 };
798 Double_t green[NRGBs] = { 0.00, 0.25, 1.00, 0.25, 0.00 };
799 Double_t blue[NRGBs] = { 0.50, 1.00, 1.00, 0.25, 0.00 };
800 TColor::CreateGradientColorTable(5, stops, red, green, blue, 255);
801 gStyle->SetNumberContours(255);
806 c1->Print(
"Debug_PCA.pdf[");
807 auto EigenLine = std::make_unique<TLine>(nKeptPCApars, 0, nKeptPCApars, heigen_cumulative->GetMaximum());
808 EigenLine->SetLineColor(kPink);
809 EigenLine->SetLineWidth(2);
810 EigenLine->SetLineStyle(kSolid);
812 auto text = std::make_unique<TText>(0.5, 0.5, Form(
"Threshold = %g", eigen_threshold));
813 text->SetTextFont (43);
814 text->SetTextSize (40);
816 heigen_values->SetLineColor(kRed);
817 heigen_values->SetLineWidth(2);
818 heigen_cumulative->SetLineColor(kGreen);
819 heigen_cumulative->SetLineWidth(2);
820 heigen_frac->SetLineColor(kBlue);
821 heigen_frac->SetLineWidth(2);
824 heigen_values->SetMaximum(heigen_cumulative->GetMaximum()+heigen_cumulative->GetMaximum()*0.4);
825 heigen_values->Draw();
826 heigen_frac->Draw(
"SAME");
827 heigen_cumulative->Draw(
"SAME");
828 EigenLine->Draw(
"Same");
829 text->DrawTextNDC(0.42, 0.84,Form(
"Threshold = %g", eigen_threshold));
831 auto leg = std::make_unique<TLegend>(0.2, 0.2, 0.6, 0.5);
832 leg->SetTextSize(0.04);
833 leg->AddEntry(heigen_values.get(),
"Absolute",
"l");
834 leg->AddEntry(heigen_frac.get(),
"Fractional",
"l");
835 leg->AddEntry(heigen_cumulative.get(),
"Cumulative",
"l");
837 leg->SetLineColor(0);
838 leg->SetLineStyle(0);
839 leg->SetFillColor(0);
840 leg->SetFillStyle(0);
843 c1->Print(
"Debug_PCA.pdf");
844 c1->SetRightMargin(0.15);
847 heigen_vectors->SetMarkerSize(0.2);
848 minz = heigen_vectors->GetMinimum();
849 if (fabs(0-maxz)>fabs(0-minz)) heigen_vectors->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
850 else heigen_vectors->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
851 if(PlotText) heigen_vectors->Draw(
"COLZ TEXT");
852 else heigen_vectors->Draw(
"COLZ");
854 auto Eigen_Line = std::make_unique<TLine>(0, nKeptPCApars, LastPCAdpar - FirstPCAdpar, nKeptPCApars);
855 Eigen_Line->SetLineColor(kGreen);
856 Eigen_Line->SetLineWidth(2);
857 Eigen_Line->SetLineStyle(kDotted);
858 Eigen_Line->Draw(
"SAME");
859 c1->Print(
"Debug_PCA.pdf");
861 SubsetPCA->SetMarkerSize(0.2);
862 minz = SubsetPCA->GetMinimum();
863 if (fabs(0-maxz)>fabs(0-minz)) SubsetPCA->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
864 else SubsetPCA->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
865 if(PlotText) SubsetPCA->Draw(
"COLZ TEXT");
866 else SubsetPCA->Draw(
"COLZ");
867 c1->Print(
"Debug_PCA.pdf");
870 hTransferMat->SetMarkerSize(0.15);
871 minz = hTransferMat->GetMinimum();
872 if (fabs(0-maxz)>fabs(0-minz)) hTransferMat->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
873 else hTransferMat->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
874 if(PlotText) hTransferMat->Draw(
"COLZ TEXT");
875 else hTransferMat->Draw(
"COLZ");
876 c1->Print(
"Debug_PCA.pdf");
879 hTransferMatT->SetMarkerSize(0.15);
880 minz = hTransferMatT->GetMinimum();
881 if (fabs(0-maxz)>fabs(0-minz)) hTransferMatT->GetZaxis()->SetRangeUser(0-fabs(0-maxz),0+fabs(0-maxz));
882 else hTransferMatT->GetZaxis()->SetRangeUser(0-fabs(0-minz),0+fabs(0-minz));
883 if(PlotText) hTransferMatT->Draw(
"COLZ TEXT");
884 else hTransferMatT->Draw(
"COLZ");
885 c1->Print(
"Debug_PCA.pdf");
886 delete hTransferMatT;
888 delete heigen_vectors;
890 c1->Print(
"Debug_PCA.pdf]");
893 gErrorIgnoreLevel = originalErrorWarning;
895 #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...
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.