6 #include "TStopwatch.h"
8 #include "TGraphAsymmErrors.h"
11 #pragma GCC diagnostic ignored "-Wuseless-cast"
20 random = std::make_unique<TRandom3>(Get<int>(
fitMan->
raw()[
"General"][
"Seed"], __FILE__, __LINE__));
27 clock = std::make_unique<TStopwatch>();
28 stepClock = std::make_unique<TStopwatch>();
31 debug = GetFromManager<bool>(
fitMan->
raw()[
"General"][
"Debug"],
false, __FILE__ , __LINE__);
34 auto outfile = Get<std::string>(
fitMan->
raw()[
"General"][
"OutputFile"], __FILE__ , __LINE__);
37 auto_save = Get<int>(
fitMan->
raw()[
"General"][
"MCMC"][
"AutoSave"], __FILE__ , __LINE__);
43 outTree =
new TTree(
"posteriors",
"Posterior_Distributions");
59 if (debug) debugFile.open((outfile+
".log").c_str());
63 fTestLikelihood = GetFromManager<bool>(
fitMan->
raw()[
"General"][
"Fitter"][
"FitTestLikelihood"],
false, __FILE__ , __LINE__);
85 TDirectory* MaCh3Version =
outputFile->mkdir(
"MaCh3Engine");
88 if (std::getenv(
"MaCh3_ROOT") ==
nullptr) {
94 if (std::getenv(
"MACH3") ==
nullptr) {
99 std::string header_path = std::string(std::getenv(
"MACH3"));
100 header_path +=
"/version.h";
101 FILE* file = fopen(header_path.c_str(),
"r");
104 header_path = std::string(std::getenv(
"MaCh3_ROOT"));
105 header_path +=
"/version.h";
111 TMacro versionHeader(
"version_header",
"version_header");
112 versionHeader.ReadFile(header_path.c_str());
113 versionHeader.Write();
121 Engine.Write(
GetName().c_str());
123 MaCh3Version->Write();
135 for(
unsigned int i = 0; i <
systematics.size(); ++i)
138 for(
unsigned int i = 0; i <
samples.size(); ++i) {
140 for(
int iSam = 0; iSam <
samples[i]->GetNsamples(); ++iSam) {
141 MACH3LOG_INFO(
" {}: Sample name: {}, with {} osc channels",iSam ,
samples[i]->GetSampleTitle(iSam),
samples[i]->GetNOscChannels(iSam));
166 bool SaveProposal = GetFromManager<bool>(
fitMan->
raw()[
"General"][
"SaveProposal"],
false, __FILE__ , __LINE__);
168 if(SaveProposal)
MACH3LOG_INFO(
"Will save in the chain proposal parameters and LogL");
171 cov->SetBranches(*
outTree, SaveProposal);
185 for (
size_t i = 0; i <
samples.size(); ++i) {
186 std::stringstream oss, oss2;
187 oss <<
"LogL_sample_" << i;
188 oss2 << oss.str() <<
"/D";
193 std::stringstream oss, oss2;
194 oss <<
"LogL_systematic_" <<
systematics[i]->GetName();
195 oss2 << oss.str() <<
"/D";
207 MACH3LOG_INFO(
"-------------------- Starting MCMC --------------------");
210 debugFile <<
"----- Starting MCMC -----" << std::endl;
225 for (
size_t i = 0; i <
samples.size(); ++i) {
226 samples[i]->CleanMemoryBeforeFit();
238 int originalErrorLevel = gErrorIgnoreLevel;
239 gErrorIgnoreLevel = kFatal;
249 debugFile <<
"\n\n" <<
step <<
" steps took " <<
clock->RealTime() <<
" seconds to complete. (" <<
clock->RealTime() /
step <<
"s / step).\n" <<
accCount<<
" steps were accepted." << std::endl;
257 gErrorIgnoreLevel = originalErrorLevel;
265 for (
const auto &s :
samples) {
266 for (
int iExisting = 0; iExisting < s->GetNsamples(); ++iExisting) {
267 for (
int iNew = 0; iNew < sample->
GetNsamples(); ++iNew) {
268 if (s->GetSampleTitle(iExisting) == sample->
GetSampleTitle(iNew)) {
270 "Duplicate sample title '{}' in handler {} detected: "
272 sample->
GetName(), s->GetName());
279 for (
const auto &s :
samples) {
280 if (s->GetName() == sample->
GetName()) {
304 for (
int iPar = 0; iPar <
systematics[s]->GetNumParams(); ++iPar)
309 MACH3LOG_ERROR(
"ParameterHandler {} has param '{}' which already exists in in {}, with name {}",
315 MACH3LOG_ERROR(
"ParameterHandler {} has param '{}' which already exists in {}, with name {}",
333 CorrMatrix->Write((cov->
GetName() + std::string(
"_Corr")).c_str());
351 TFile *infile =
M3::Open(FitName,
"READ", __FILE__, __LINE__);
352 TTree *posts = infile->Get<TTree>(
"posteriors");
353 unsigned int step_val = 0;
355 posts->SetBranchAddress(
"step",&step_val);
356 posts->SetBranchAddress(
"LogL",&log_val);
360 TDirectory* CovarianceFolder = infile->Get<TDirectory>(
"CovarianceFolder");
362 std::string ConfigName =
"Config_" +
systematics[s]->GetName();
363 TMacro *ConfigCov = CovarianceFolder->Get<TMacro>(ConfigName.c_str());
365 if (ConfigCov !=
nullptr) {
369 YAML::Node ConfigCurrent =
systematics[s]->GetConfig();
373 MACH3LOG_ERROR(
"Yaml configs in previous chain (from path {}) and current one are different", FitName);
380 CovarianceFolder->Close();
381 delete CovarianceFolder;
383 std::vector<double> branch_vals;
384 std::vector<std::string> branch_name;
385 systematics[s]->MatchMaCh3OutputBranches(posts, branch_vals, branch_name);
386 posts->GetEntry(posts->GetEntries()-1);
395 for (
int i = 0; i <
systematics[s]->GetNumParams(); ++i) {
396 posts->SetBranchAddress(
systematics[s]->GetParName(i).c_str(),
nullptr);
416 if (
fitMan ==
nullptr)
return;
419 if (GetFromManager<bool>(
fitMan->
raw()[
"General"][
"ProcessMCMC"],
false, __FILE__ , __LINE__)){
425 TVectorD *Central =
nullptr;
426 TVectorD *Errors =
nullptr;
427 TVectorD *Central_Gauss =
nullptr;
428 TVectorD *Errors_Gauss =
nullptr;
429 TVectorD *Peaks =
nullptr;
432 Processor.
GetPostfit(Central, Errors, Central_Gauss, Errors_Gauss, Peaks);
436 TMatrixDSym *Covariance =
nullptr;
437 TMatrixDSym *Correlation =
nullptr;
447 MACH3LOG_INFO(
"Opening output again to update with means..");
448 outputFile =
new TFile(Get<std::string>(
fitMan->
raw()[
"General"][
"OutputFile"], __FILE__, __LINE__).c_str(),
"UPDATE");
450 Central->Write(
"PDF_Means");
451 Errors->Write(
"PDF_Errors");
452 Central_Gauss->Write(
"Gauss_Means");
453 Errors_Gauss->Write(
"Errors_Gauss");
454 Covariance->Write(
"Covariance");
455 Correlation->Write(
"Correlation");
467 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
469 TStopwatch clockRace;
471 for(
int Lap = 0; Lap < NLaps; ++Lap) {
475 MACH3LOG_INFO(
"It took {:.4f} s to reweights {} times sample: {}", clockRace.RealTime(), NLaps,
samples[ivs]->GetName());
476 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
479 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
481 TStopwatch clockRace;
483 for(
int Lap = 0; Lap < NLaps; ++Lap) {
487 MACH3LOG_INFO(
"It took {:.4f} s to calculate GetLikelihood {} times sample: {}", clockRace.RealTime(), NLaps,
samples[ivs]->GetName());
488 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
491 std::vector<std::vector<double>> StepsValuesBefore(
systematics.size());
493 StepsValuesBefore[s] =
systematics[s]->GetProposed();
496 TStopwatch clockRace;
498 for(
int Lap = 0; Lap < NLaps; ++Lap) {
502 MACH3LOG_INFO(
"It took {:.4f} s to propose step {} times cov: {}", clockRace.RealTime(), NLaps,
systematics[s]->GetName());
503 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
506 systematics[s]->SetParameters(StepsValuesBefore[s]);
510 TStopwatch clockRace;
512 for(
int Lap = 0; Lap < NLaps; ++Lap) {
516 MACH3LOG_INFO(
"It took {:.4f} s to calculate get likelihood {} times cov: {}", clockRace.RealTime(), NLaps,
systematics[s]->GetName());
517 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
525 bool isScanRanges =
false;
527 if(
fitMan->
raw()[
"LLHScan"][
"ScanRanges"]){
528 YAML::Node scanRangesList =
fitMan->
raw()[
"LLHScan"][
"ScanRanges"];
529 for (
auto it = scanRangesList.begin(); it != scanRangesList.end(); ++it) {
530 std::string itname = it->first.as<std::string>();
531 std::vector<double> itrange = it->second.as<std::vector<double>>();
533 scanRanges[itname] = itrange;
537 MACH3LOG_INFO(
"There are no user-defined parameter ranges, so I'll use default param bounds for LLH Scans");
546 for(
unsigned int is = 0; is < SkipVector.size(); ++is)
548 if(ParamName.substr(0, SkipVector[is].length()) == SkipVector[is])
560 double& lower,
double& upper,
const int n_points,
const std::string& suffix)
const {
563 std::map<std::string, std::vector<double>> scanRanges;
566 double nSigma = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSigma"], 1., __FILE__, __LINE__);
567 bool IsPCA = cov->
IsPCA();
571 if (IsPCA) name +=
"_PCA";
580 if (std::abs(CentralValue - prior) > 1e-10) {
581 MACH3LOG_INFO(
"For {} scanning around value {} rather than prior {}", name, CentralValue, prior);
604 auto it = scanRanges.find(name);
605 if (it != scanRanges.end() && it->second.size() == 2) {
606 lower = it->second[0];
607 upper = it->second[1];
608 MACH3LOG_INFO(
"Found matching param name for setting specified range for {}", name);
609 MACH3LOG_INFO(
"Range for {} = [{:.2f}, {:.2f}]", name, lower, upper);
617 MACH3LOG_INFO(
"Scanning {} {} with {} steps, from [{:.2f} , {:.2f}], CV = {:.2f}", suffix, name, n_points, lower, upper, CentralValue);
630 bool PlotLLHScanBySample = GetFromManager<bool>(
fitMan->
raw()[
"LLHScan"][
"LLHScanBySample"],
false, __FILE__ , __LINE__);
631 auto SkipVector = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSkipVector"], {}, __FILE__ , __LINE__);
635 std::vector<TDirectory *> Cov_LLH(
systematics.size());
636 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
638 std::string NameTemp =
systematics[ivc]->GetName();
639 NameTemp = NameTemp.substr(0, NameTemp.find(
"_cov")) +
"_LLH";
640 Cov_LLH[ivc] =
outputFile->mkdir(NameTemp.c_str());
643 std::vector<TDirectory *> SampleClass_LLH(
samples.size());
644 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
646 std::string NameTemp =
samples[ivs]->GetName();
647 SampleClass_LLH[ivs] =
outputFile->mkdir(NameTemp.c_str());
650 TDirectory *Sample_LLH =
outputFile->mkdir(
"Sample_LLH");
651 TDirectory *Total_LLH =
outputFile->mkdir(
"Total_LLH");
653 std::vector<TDirectory *>SampleSplit_LLH;
654 if(PlotLLHScanBySample)
657 int SampleIterator = 0;
658 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
660 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is )
662 SampleSplit_LLH[SampleIterator] =
outputFile->mkdir((
samples[ivs]->GetSampleTitle(is)+
"_LLH").c_str());
668 const int n_points = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanPoints"], 100, __FILE__ , __LINE__);
671 const int countwidth = int(
double(n_points)/
double(5));
678 int npars = cov->GetNumParams();
679 bool IsPCA = cov->IsPCA();
680 if (IsPCA) npars = cov->GetNParameters();
681 for (
int i = 0; i < npars; ++i)
684 std::string name = cov->GetParFancyName(i);
685 if (IsPCA) name +=
"_PCA";
689 double CentralValue, lower, upper;
692 auto hScan = std::make_unique<TH1D>((name +
"_full").c_str(), (name +
"_full").c_str(), n_points, lower, upper);
693 hScan->SetTitle((std::string(
"2LLH_full, ") + name +
";" + name +
"; -2(ln L_{sample} + ln L_{xsec+flux} + ln L_{det})").c_str());
694 hScan->SetDirectory(
nullptr);
696 auto hScanSam = std::make_unique<TH1D>((name +
"_sam").c_str(), (name +
"_sam").c_str(), n_points, lower, upper);
697 hScanSam->SetTitle((std::string(
"2LLH_sam, ") + name +
";" + name +
"; -2(ln L_{sample})").c_str());
698 hScanSam->SetDirectory(
nullptr);
700 std::vector<std::unique_ptr<TH1D>> hScanSample(
samples.size());
701 std::vector<double> nSamLLH(
samples.size(), 0.0);
702 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
704 std::string NameTemp =
samples[ivs]->GetName();
705 hScanSample[ivs] = std::make_unique<TH1D>((name+
"_"+NameTemp).c_str(), (name+
"_" + NameTemp).c_str(), n_points, lower, upper);
706 hScanSample[ivs]->SetDirectory(
nullptr);
707 hScanSample[ivs]->SetTitle((
"2LLH_" + NameTemp +
", " + name +
";" + name +
"; -2(ln L_{" + NameTemp +
"})").c_str());
710 std::vector<std::unique_ptr<TH1D>> hScanCov(
systematics.size());
711 std::vector<double> nCovLLH(
systematics.size(), 0.0);
712 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
714 std::string NameTemp =
systematics[ivc]->GetName();
715 NameTemp = NameTemp.substr(0, NameTemp.find(
"_cov"));
716 hScanCov[ivc] = std::make_unique<TH1D>((name +
"_" + NameTemp).c_str(), (name +
"_" + NameTemp).c_str(), n_points, lower, upper);
717 hScanCov[ivc]->SetDirectory(
nullptr);
718 hScanCov[ivc]->SetTitle((
"2LLH_" + NameTemp +
", " + name +
";" + name +
"; -2(ln L_{" + NameTemp +
"})").c_str());
721 std::vector<std::unique_ptr<TH1D>> hScanSamSplit;
722 std::vector<double> sampleSplitllh;
723 if(PlotLLHScanBySample)
725 int SampleIterator = 0;
728 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
730 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is )
732 auto histName = name +
samples[ivs]->GetSampleTitle(is);
733 auto histTitle = std::string(
"2LLH_sam, ") + name +
";" + name +
"; -2(ln L_{sample})";
734 hScanSamSplit[SampleIterator] = std::make_unique<TH1D>(histName.c_str(), histTitle.c_str(), n_points, lower, upper);
735 hScanSamSplit[SampleIterator]->SetDirectory(
nullptr);
742 for (
int j = 0; j < n_points; ++j)
744 if (j % countwidth == 0)
749 cov->GetPCAHandler()->SetParPropPCA(i, hScan->GetBinCenter(j+1));
752 cov->SetParProp(i, hScan->GetBinCenter(j+1));
756 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs ){
760 double totalllh = 0.;
763 double samplellh = 0.;
765 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs ) {
766 nSamLLH[ivs] =
samples[ivs]->GetLikelihood();
767 samplellh += nSamLLH[ivs];
770 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc ) {
772 totalllh += nCovLLH[ivc];
775 totalllh += samplellh;
777 if(PlotLLHScanBySample)
779 int SampleIterator = 0;
780 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
782 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is)
784 sampleSplitllh[SampleIterator] =
samples[ivs]->GetSampleLikelihood(is);
790 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs ) {
791 hScanSample[ivs]->SetBinContent(j+1, 2*nSamLLH[ivs]);
793 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc ) {
794 hScanCov[ivc]->SetBinContent(j+1, 2*nCovLLH[ivc]);
797 hScanSam->SetBinContent(j+1, 2*samplellh);
798 hScan->SetBinContent(j+1, 2*totalllh);
800 if(PlotLLHScanBySample)
802 int SampleIterator = 0;
803 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
805 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is)
807 hScanSamSplit[SampleIterator]->SetBinContent(j+1, 2*sampleSplitllh[SampleIterator]);
813 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
816 hScanCov[ivc]->Write();
819 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
821 SampleClass_LLH[ivs]->cd();
822 hScanSample[ivs]->Write();
829 if(PlotLLHScanBySample)
831 int SampleIterator = 0;
832 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
834 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is)
836 SampleSplit_LLH[SampleIterator]->cd();
837 hScanSamSplit[SampleIterator]->Write();
845 cov->GetPCAHandler()->SetParPropPCA(i, CentralValue);
847 cov->SetParProp(i, CentralValue);
852 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
854 Cov_LLH[ivc]->Write();
858 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
860 SampleClass_LLH[ivs]->Write();
861 delete SampleClass_LLH[ivs];
870 if(PlotLLHScanBySample)
872 int SampleIterator = 0;
873 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
875 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is )
877 SampleSplit_LLH[SampleIterator]->Write();
878 delete SampleSplit_LLH[SampleIterator];
889 TDirectory *Sample_LLH =
outputFile->Get<TDirectory>(
"Sample_LLH");
892 if(Sample_LLH->IsZombie())
894 MACH3LOG_WARN(
"Couldn't find Sample_LLH, it looks like LLH scan wasn't run, will do this now");
900 const int npars = cov->GetNumParams();
901 std::vector<double> StepScale(npars);
902 for (
int i = 0; i < npars; ++i)
904 std::string name = cov->GetParFancyName(i);
906 StepScale[i] = cov->GetIndivStepScale(i);
907 TH1D* LLHScan = Sample_LLH->Get<TH1D>((name+
"_sam").c_str());
908 if(LLHScan ==
nullptr)
910 MACH3LOG_WARN(
"Couldn't find LLH scan, for {}, skipping", name);
913 const double LLH_val = std::max(LLHScan->GetBinContent(1), LLHScan->GetBinContent(LLHScan->GetNbinsX()));
915 if(LLH_val < 0.001)
continue;
920 const double Var = 1.;
921 const double approxSigma = TMath::Abs(Var)/std::sqrt(LLH_val);
924 const double NewStepScale = approxSigma * 2.38/std::sqrt(npars);
925 StepScale[i] = NewStepScale;
929 cov->SetIndivStepScale(StepScale);
930 cov->SaveUpdatedMatrixConfig();
943 TDirectory *Sample_2DLLH =
outputFile->mkdir(
"Sample_2DLLH");
944 auto SkipVector = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSkipVector"], {}, __FILE__ , __LINE__);;
947 const int n_points = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"2DLLHScanPoints"], 20, __FILE__ , __LINE__);
949 const int countwidth = int(
double(n_points)/
double(5));
956 int npars = cov->GetNumParams();
957 bool IsPCA = cov->IsPCA();
958 if (IsPCA) npars = cov->GetNParameters();
960 for (
int i = 0; i < npars; ++i)
962 std::string name_x = cov->GetParFancyName(i);
963 if (IsPCA) name_x +=
"_PCA";
965 double central_x, lower_x, upper_x;
971 for (
int j = 0; j < i; ++j)
973 std::string name_y = cov->GetParFancyName(j);
974 if (IsPCA) name_y +=
"_PCA";
979 double central_y, lower_y, upper_y;
982 auto hScanSam = std::make_unique<TH2D>((name_x +
"_" + name_y +
"_sam").c_str(), (name_x +
"_" + name_y +
"_sam").c_str(),
983 n_points, lower_x, upper_x, n_points, lower_y, upper_y);
984 hScanSam->SetDirectory(
nullptr);
985 hScanSam->GetXaxis()->SetTitle(name_x.c_str());
986 hScanSam->GetYaxis()->SetTitle(name_y.c_str());
987 hScanSam->GetZaxis()->SetTitle(
"2LLH_sam");
990 for (
int x = 0; x < n_points; ++x)
992 if (x % countwidth == 0)
995 for (
int y = 0; y < n_points; ++y)
999 cov->GetPCAHandler()->SetParPropPCA(i, hScanSam->GetXaxis()->GetBinCenter(x+1));
1000 cov->GetPCAHandler()->SetParPropPCA(j, hScanSam->GetYaxis()->GetBinCenter(y+1));
1003 cov->SetParProp(i, hScanSam->GetXaxis()->GetBinCenter(x+1));
1004 cov->SetParProp(j, hScanSam->GetYaxis()->GetBinCenter(y+1));
1007 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs) {
1012 double samplellh = 0;
1013 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs) {
1014 samplellh +=
samples[ivs]->GetLikelihood();
1016 hScanSam->SetBinContent(x+1, y+1, 2*samplellh);
1024 cov->GetPCAHandler()->SetParPropPCA(i, central_x);
1025 cov->GetPCAHandler()->SetParPropPCA(j, central_y);
1027 cov->SetParProp(i, central_x);
1028 cov->SetParProp(j, central_y);
1033 Sample_2DLLH->Write();
1034 delete Sample_2DLLH;
1047 bool PlotLLHScanBySample = GetFromManager<bool>(
fitMan->
raw()[
"LLHScan"][
"LLHScanBySample"],
false, __FILE__ , __LINE__);
1048 auto ParamsOfInterest = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"LLHScan"][
"LLHParameters"], {}, __FILE__, __LINE__);
1050 if(ParamsOfInterest.empty()) {
1051 MACH3LOG_WARN(
"There were no LLH parameters of interest specified to run the LLHMap! LLHMap will not run at all ...");
1057 std::vector<std::tuple<std::string, ParameterHandlerBase*, int>> ParamsCovIDs;
1058 for(
auto& p : ParamsOfInterest) {
1061 for(
int c = 0; c < cov->GetNumParams(); ++c) {
1062 if(cov->GetParName(c) == p || cov->GetParFancyName(c) == p) {
1064 for(
auto& pc : ParamsCovIDs) {
1065 if(std::get<1>(pc) == cov && std::get<2>(pc) == c)
1067 MACH3LOG_WARN(
"Parameter {} as {}({}) listed multiple times for LLHMap, omitting and using only once!", p, cov->GetName(), c);
1074 ParamsCovIDs.push_back(std::make_tuple(p, cov, c));
1084 MACH3LOG_INFO(
"Parameter {} found in {} at an index {}.", p, std::get<1>(ParamsCovIDs.back())->GetName(), std::get<2>(ParamsCovIDs.back()));
1086 MACH3LOG_WARN(
"Parameter {} not found in any of the systematic covariance objects. Will not scan over this one!", p);
1090 std::map<std::string, std::pair<int, std::pair<double, double>>> ParamsRanges;
1092 MACH3LOG_INFO(
"======================================================================================");
1093 MACH3LOG_INFO(
"Performing a general multi-dimensional LogL map scan over following parameters ranges:");
1094 MACH3LOG_INFO(
"======================================================================================");
1095 unsigned long TotalPoints = 1;
1097 double nSigma = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSigma"], 1., __FILE__, __LINE__);
1102 for(
auto& p : ParamsCovIDs) {
1104 std::string name = std::get<0>(p);
1105 int i = std::get<2>(p);
1108 ParamsRanges[name].first = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanPoints"], 20, __FILE__, __LINE__);
1110 ParamsRanges[name].first = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"ScanPoints"][name], ParamsRanges[name].first, __FILE__, __LINE__);
1115 bool IsPCA = cov->
IsPCA();
1123 if (std::abs(CentralValue - prior) > 1e-10) {
1124 MACH3LOG_INFO(
"For {} scanning around value {} rather than prior {}", name, CentralValue, prior);
1142 ParamsRanges[name].second = {lower,upper};
1145 ParamsRanges[name].second = GetFromManager<std::pair<double,double>>(
fitMan->
raw()[
"LLHScan"][
"ScanRanges"][name], ParamsRanges[name].second, __FILE__, __LINE__);
1147 MACH3LOG_INFO(
"{} from {:.4f} to {:.4f} with a {:.5f} step ({} points total)",
1148 name, ParamsRanges[name].second.first, ParamsRanges[name].second.second,
1149 (ParamsRanges[name].second.second - ParamsRanges[name].second.first)/(ParamsRanges[name].first - 1.),
1150 ParamsRanges[name].first);
1152 TotalPoints *= ParamsRanges[name].first;
1156 MACH3LOG_INFO(
"In total, looping over {} points, from {} parameters. Estimates for run time:", TotalPoints, ParamsCovIDs.size());
1157 MACH3LOG_INFO(
" 1 s per point = {} hours",
double(TotalPoints)/3600.);
1158 MACH3LOG_INFO(
" 0.1 s per point = {} hours",
double(TotalPoints)/36000.);
1159 MACH3LOG_INFO(
"0.01 s per point = {} hours",
double(TotalPoints)/360000.);
1160 MACH3LOG_INFO(
"==================================================================================");
1162 const int countwidth = int(
double(TotalPoints)/
double(20));
1165 auto LLHMap =
new TTree(
"llhmap",
"LLH Map");
1168 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
1170 std::string NameTemp =
systematics[ivc]->GetName();
1171 NameTemp = NameTemp.substr(0, NameTemp.find(
"_cov")) +
"_LLH";
1172 LLHMap->Branch(NameTemp.c_str(), &CovLogL[ivc]);
1175 std::vector<double> SampleClassLogL(
samples.size());
1176 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
1178 std::string NameTemp =
samples[ivs]->GetName()+
"_LLH";
1179 LLHMap->Branch(NameTemp.c_str(), &SampleClassLogL[ivs]);
1182 double SampleLogL, TotalLogL;
1183 LLHMap->Branch(
"Sample_LLH", &SampleLogL);
1184 LLHMap->Branch(
"Total_LLH", &TotalLogL);
1186 std::vector<double>SampleSplitLogL;
1187 if(PlotLLHScanBySample)
1190 int SampleIterator = 0;
1191 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
1193 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is )
1195 std::string NameTemp =
samples[ivs]->GetSampleTitle(is)+
"_LLH";
1196 LLHMap->Branch(NameTemp.c_str(), &SampleSplitLogL[SampleIterator]);
1202 std::vector<double> ParamsValues(ParamsCovIDs.size());
1203 for(
unsigned int i=0; i < ParamsCovIDs.size(); ++i)
1204 LLHMap->Branch(std::get<0>(ParamsCovIDs[i]).c_str(), &ParamsValues[i]);
1208 std::vector<unsigned long> idx(ParamsCovIDs.size(), 0);
1211 for(
unsigned long sp = 0; sp < TotalPoints; ++sp)
1214 for(
unsigned int n = 0; n < ParamsCovIDs.size(); ++n)
1217 std::string name = std::get<0>(ParamsCovIDs[n]);
1218 int points = ParamsRanges[name].first;
1219 double low = ParamsRanges[name].second.first;
1220 double high = ParamsRanges[name].second.second;
1223 unsigned long dev = 1;
1224 for(
unsigned int m = 0; m <= n; ++m)
1225 dev *= ParamsRanges[std::get<0>(ParamsCovIDs[m])].first;
1229 idx[n] = idx[n] / ( dev / points );
1232 ParamsValues[n] = low + (high-low) *
double(idx[n])/double(points-1);
1237 int i = std::get<2>(ParamsCovIDs[n]);
1249 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
1252 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
1254 SampleClassLogL[ivs] = 2.*
samples[ivs]->GetLikelihood();
1255 SampleLogL += SampleClassLogL[ivs];
1257 TotalLogL += SampleLogL;
1260 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
1262 CovLogL[ivc] = 2.*
systematics[ivc]->GetLikelihood();
1263 TotalLogL += CovLogL[ivc];
1266 if(PlotLLHScanBySample)
1268 int SampleIterator = 0;
1269 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
1271 for(
int is = 0; is <
samples[ivs]->GetNsamples(); ++is)
1273 SampleSplitLogL[SampleIterator] = 2.*
samples[ivs]->GetSampleLikelihood(is);
1281 if (sp % countwidth == 0)
1293 if(!
fitMan->
raw()[
"SigmaVar"][
"CustomRange"])
return;
1295 auto Config =
fitMan->
raw()[
"SigmaVar"][
"CustomRange"];
1297 const auto sigmaStr = std::to_string(
static_cast<int>(std::round(sigma)));
1299 if (Config[ParName] && Config[ParName][sigmaStr]) {
1300 ParamShiftValue = Config[ParName][sigmaStr].as<
double>();
1301 MACH3LOG_INFO(
" ::: setting custom range from config ::: {} -> {}", ParName, ParamShiftValue);
1310 hist->SetTitle(baseName.c_str());
1312 TString className = hist->ClassName();
1315 if (className.Contains(
"TH1")) {
1316 hist->GetYaxis()->SetTitle(
"Events");
1317 }
else if (className.Contains(
"TH2")) {
1318 hist->GetZaxis()->SetTitle(
"Events");
1320 hist->SetDirectory(
nullptr);
1321 hist->Write(baseName.c_str());
1327 const std::string& suffix,
1329 const bool by_channel,
1330 const std::vector<TDirectory*>& SampleDir) {
1333 for (
int iSample = 0; iSample < sample->
GetNsamples(); ++iSample) {
1334 SampleDir[iSample]->cd();
1336 for(
int iDim1 = 0; iDim1 < sample->
GetNDim(iSample); iDim1++) {
1337 std::string ProjectionName = sample->
GetKinVarName(iSample, iDim1);
1338 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim1);
1342 for (
int iMode = 0; iMode < modes->
GetNModes(); ++iMode) {
1350 for (
int iChan = 0; iChan < sample->
GetNOscChannels(iSample); ++iChan) {
1357 if (by_mode && by_channel) {
1358 for (
int iMode = 0; iMode < modes->
GetNModes(); ++iMode) {
1359 for (
int iChan = 0; iChan < sample->
GetNOscChannels(iSample); ++iChan) {
1367 if (!by_mode && !by_channel) {
1368 auto hist = sample->
Get1DVarHist(iSample, ProjectionName);
1372 for (
int iDim2 = iDim1 + 1; iDim2 < sample->
GetNDim(iSample); ++iDim2) {
1374 std::string XVarName = sample->
GetKinVarName(iSample, iDim1);
1375 std::string YVarName = sample->
GetKinVarName(iSample, iDim2);
1378 auto hist2D = sample->
Get2DVarHist(iSample, XVarName, YVarName);
1381 std::string suffix2D =
"_2DProj_" + std::to_string(iDim1) +
"_vs_" + std::to_string(iDim2) + suffix;
1398 bool plot_by_mode = GetFromManager<bool>(
fitMan->
raw()[
"SigmaVar"][
"PlotByMode"],
false);
1399 bool plot_by_channel = GetFromManager<bool>(
fitMan->
raw()[
"SigmaVar"][
"PlotByChannel"],
false);
1400 auto SkipVector = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"SigmaVar"][
"SkipVector"], {}, __FILE__ , __LINE__);
1402 if (plot_by_mode)
MACH3LOG_INFO(
"Plotting by sample and mode");
1403 if (plot_by_channel)
MACH3LOG_INFO(
"Plotting by sample and channel");
1404 if (!plot_by_mode && !plot_by_channel)
MACH3LOG_INFO(
"Plotting by sample only");
1405 if (plot_by_mode && plot_by_channel)
MACH3LOG_INFO(
"Plotting by sample, mode and channel");
1407 auto SigmaArray = GetFromManager<std::vector<double>>(
fitMan->
raw()[
"SigmaVar"][
"SigmaArray"], {-3, -1, 0, 1, 3}, __FILE__ , __LINE__);
1408 if (std::find(SigmaArray.begin(), SigmaArray.end(), 0.0) == SigmaArray.end()) {
1409 MACH3LOG_ERROR(
":: SigmaArray does not contain 0! Current contents: {} ::", fmt::join(SigmaArray,
", "));
1413 TDirectory* SigmaDir =
outputFile->mkdir(
"SigmaVar");
1418 for(
int i = 0; i <
systematics[s]->GetNumParams(); i++)
1420 std::string ParName =
systematics[s]->GetParFancyName(i);
1426 TDirectory* ParamDir = SigmaDir->mkdir(ParName.c_str());
1429 const double ParamCentralValue =
systematics[s]->GetParProp(i);
1430 const double Prior =
systematics[s]->GetParInit(i);
1431 const double ParamLower =
systematics[s]->GetLowerBound(i);
1432 const double ParamUpper =
systematics[s]->GetUpperBound(i);
1434 if (std::abs(ParamCentralValue - Prior) > 1e-10) {
1435 MACH3LOG_INFO(
"For {} scanning around value {} rather than prior {}", ParName, ParamCentralValue, Prior);
1438 for(
unsigned int iSample = 0; iSample <
samples.size(); ++iSample)
1440 auto* MaCh3Sample =
samples[iSample];
1441 std::vector<TDirectory*> SampleDir(MaCh3Sample->GetNsamples());
1442 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNsamples(); ++SampleIndex) {
1443 SampleDir[SampleIndex] = ParamDir->mkdir(MaCh3Sample->GetSampleTitle(SampleIndex).c_str());
1446 for (
size_t j = 0; j < SigmaArray.size(); ++j) {
1447 double sigma = SigmaArray[j];
1449 double ParamShiftValue = ParamCentralValue + sigma * std::sqrt((*
systematics[s]->GetCovMatrix())(i,i));
1450 ParamShiftValue = std::max(std::min(ParamShiftValue, ParamUpper), ParamLower);
1455 MACH3LOG_INFO(
" - set to {:<5.2f} ({:<2} sigma shift)", ParamShiftValue, sigma);
1458 std::ostringstream valStream;
1459 valStream << std::fixed << std::setprecision(2) << ParamShiftValue;
1460 std::string valueStr = valStream.str();
1462 std::ostringstream sigmaStream;
1463 sigmaStream << std::fixed << std::setprecision(2) << std::abs(sigma);
1464 std::string sigmaStr = sigmaStream.str();
1468 suffix =
"_" + ParName +
"_nom_val_" + valueStr;
1470 std::string sign = (sigma > 0) ?
"p" :
"n";
1471 suffix =
"_" + ParName +
"_sig_" + sign + sigmaStr +
"_val_" + valueStr;
1475 MaCh3Sample->Reweight();
1479 for (
int subSampleIndex = 0; subSampleIndex < MaCh3Sample->GetNsamples(); ++subSampleIndex) {
1480 SampleDir[subSampleIndex]->Close();
1481 delete SampleDir[subSampleIndex];
1487 MACH3LOG_INFO(
" - set back to CV {:<5.2f}", ParamCentralValue);
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
#define _MaCh3_Safe_Include_End_
KS: Restore warning checking after including external headers.
void WriteHistogramsByMode(SampleHandlerBase *sample, const std::string &suffix, const bool by_mode, const bool by_channel, const std::vector< TDirectory * > &SampleDir)
Generic histogram writer - should make main code more palatable.
void WriteHistograms(TH1 *hist, const std::string &baseName)
Helper to write histograms.
#define MACH3LOG_CRITICAL
std::vector< TString > BranchNames
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
YAML::Node TMacroToYAML(const TMacro ¯o)
KS: Convert a ROOT TMacro object to a YAML node.
bool compareYAMLNodes(const YAML::Node &node1, const YAML::Node &node2, bool Mute=false)
Compare if yaml nodes are identical.
bool CheckNodeExists(const YAML::Node &node, Args... args)
KS: Wrapper function to call the recursive helper.
void RunLLHScan()
Perform a 1D likelihood scan.
FitterBase(Manager *const fitMan)
Constructor.
void AddSystObj(ParameterHandlerBase *cov)
This function adds a Covariance object to the analysis framework. The Covariance object will be utili...
std::string GetName() const
Get name of class.
void AddSampleHandler(SampleHandlerBase *sample)
This function adds a sample PDF object to the analysis framework. The sample PDF object will be utili...
std::unique_ptr< TRandom3 > random
Random number.
std::vector< SampleHandlerBase * > samples
Sample holder.
double logLProp
proposed likelihood
bool CheckSkipParameter(const std::vector< std::string > &SkipVector, const std::string &ParamName) const
KS: Check whether we want to skip parameter using skip vector.
void ProcessMCMC()
Process MCMC output.
int accCount
counts accepted steps
bool OutputPrepared
Checks if output prepared not repeat some operations.
void SaveOutput()
Save output and close files.
TFile * outputFile
Output.
void SaveSettings()
Save the settings that the MCMC was run with.
unsigned int step
current state
void PrepareOutput()
Prepare the output file.
bool SettingsSaved
Checks if setting saved not repeat some operations.
double accProb
current acceptance prob
void GetStepScaleBasedOnLLHScan()
LLH scan is good first estimate of step scale.
virtual void StartFromPreviousFit(const std::string &FitName)
Allow to start from previous fit/chain.
bool FileSaved
Checks if file saved not repeat some operations.
std::string AlgorithmName
Name of fitting algorithm that is being used.
std::vector< double > sample_llh
store the llh breakdowns
void RunSigmaVar()
Perform a 1D/2D sigma var for all samples.
void GetParameterScanRange(const ParameterHandlerBase *cov, const int i, double &CentralValue, double &lower, double &upper, const int n_points, const std::string &suffix="") const
Helper function to get parameter scan range, central value.
double stepTime
Time of single step.
std::unique_ptr< TStopwatch > clock
tells global time how long fit took
Manager * fitMan
The manager for configuration handling.
unsigned int stepStart
step start, by default 0 if we start from previous chain then it will be different
bool GetScanRange(std::map< std::string, std::vector< double >> &scanRanges) const
YSP: Set up a mapping to store parameters with user-specified ranges, suggested by D....
std::unique_ptr< TStopwatch > stepClock
tells how long single step/fit iteration took
TDirectory * CovFolder
Output cov folder.
void CustomRange(const std::string &ParName, const double sigma, double &ParamShiftValue) const
For comparison with other fitting frameworks (like P-Theta) we usually have to apply different parame...
TDirectory * SampleFolder
Output sample folder.
void DragRace(const int NLaps=100)
Calculates the required time for each sample or covariance object in a drag race simulation....
void Run2DLLHScan()
Perform a 2D likelihood scan.
unsigned int TotalNSamples
Total number of samples used, single SampleHandler can store more than one analysis sample!
double logLCurr
current likelihood
void RunLLHMap()
Perform a general multi-dimensional likelihood scan.
std::vector< double > syst_llh
systematic llh breakdowns
int auto_save
auto save every N steps
bool fTestLikelihood
Necessary for some fitting algorithms like PSO.
virtual ~FitterBase()
Destructor for the FitterBase class.
TTree * outTree
Output tree with posteriors.
void SanitiseInputs()
Remove obsolete memory and make other checks before fit starts.
std::vector< ParameterHandlerBase * > systematics
Systematic holder.
Class responsible for processing MCMC chains, performing diagnostics, generating plots,...
const std::vector< TString > & GetBranchNames() const
Get the vector of branch names from root file.
void Initialise()
Scan chain, what parameters we have and load information from covariance matrices.
void GetPostfit(TVectorD *&Central, TVectorD *&Errors, TVectorD *&Central_Gauss, TVectorD *&Errors_Gauss, TVectorD *&Peaks)
Get the post-fit results (arithmetic and Gaussian)
void DrawCovariance()
Draw the post-fit covariances.
void DrawPostfit()
Draw the post-fit comparisons.
void GetCovariance(TMatrixDSym *&Cov, TMatrixDSym *&Corr)
Get the post-fit covariances and correlations.
Custom exception class used throughout MaCh3.
KS: Class describing MaCh3 modes used in the analysis, it is being initialised from config.
int GetNModes() const
KS: Get number of modes, keep in mind actual number is +1 greater due to unknown category.
std::string GetMaCh3ModeName(const int Index) const
KS: Get normal name of mode, if mode not known you will get UNKNOWN_BAD.
The manager class is responsible for managing configurations and settings.
YAML::Node const & raw() const
Return config.
void SaveSettings(TFile *const OutputFile) const
Add manager useful information's to TFile, in most cases to Fitter.
double GetParPropPCA(const int i) const
Get current parameter value using PCA.
void SetParPropPCA(const int i, const double value)
Set proposed value for parameter in PCA base.
double GetPreFitValuePCA(const int i) const
Get current parameter value using PCA.
const TVectorD GetEigenValues() const
Get eigen values for all parameters, if you want for decomposed only parameters use GetEigenValuesMas...
Base class responsible for handling of systematic error parameters. Capable of using PCA or using ada...
int GetNumParams() const
Get total number of parameters.
std::string GetParName(const int i) const
Get name of parameter.
void SetParProp(const int i, const double val)
Set proposed parameter value.
double GetUpperBound(const int i) const
Get upper parameter bound in which it is physically valid.
TMatrixDSym * GetCovMatrix() const
Return covariance matrix.
std::string GetParFancyName(const int i) const
Get fancy name of the Parameter.
TH2D * GetCorrelationMatrix()
KS: Convert covariance matrix to correlation matrix and return TH2D which can be used for fancy plott...
PCAHandler * GetPCAHandler() const
Get pointer for PCAHandler.
double GetLowerBound(const int i) const
Get lower parameter bound in which it is physically valid.
bool IsPCA() const
is PCA, can use to query e.g. LLH scans
std::string GetName() const
Get name of covariance.
double GetParInit(const int i) const
Get prior parameter value.
double GetDiagonalError(const int i) const
Get diagonal error for ith parameter.
YAML::Node GetConfig() const
Getter to return a copy of the YAML node.
double GetParProp(const int i) const
Get proposed parameter value.
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
virtual std::string GetKinVarName(const int iSample, const int Dimension) const =0
Return Kinematic Variable name for specified sample and dimension for example "Reconstructed_Neutrino...
MaCh3Modes * GetMaCh3Modes() const
Return pointer to MaCh3 modes.
virtual std::string GetFlavourName(const int iSample, const int iChannel) const =0
virtual TH2 * Get2DVarHist(const int iSample, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, TAxis *AxisX=nullptr, TAxis *AxisY=nullptr, const std::vector< KinematicCut > &SubEventSelectionVec={})=0
virtual TH1 * Get1DVarHistByModeAndChannel(const int iSample, const std::string &ProjectionVar_Str, int kModeToFill=-1, int kChannelToFill=-1, int WeightStyle=0, TAxis *Axis=nullptr)=0
virtual TH1 * Get1DVarHist(const int iSample, const std::string &ProjectionVar, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, TAxis *Axis=nullptr, const std::vector< KinematicCut > &SubEventSelectionVec={})=0
virtual int GetNOscChannels(const int iSample) const =0
virtual void SaveAdditionalInfo(TDirectory *Dir)
Store additional info in a chan.
virtual M3::int_t GetNsamples()
virtual std::string GetSampleTitle(const int Sample) const =0
virtual std::string GetName() const =0
virtual int GetNDim(const int Sample) const =0
DB Function to differentiate 1D or 2D binning.
constexpr static const double _LARGE_LOGL_
Large Likelihood is used it parameter go out of physical boundary, this indicates in MCMC that such s...
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.
int GetNThreads()
number of threads which we need for example for TRandom3
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
int getValue(const std::string &Type)
CW: Get info like RAM.