5 #include "TStopwatch.h"
7 #include "TGraphAsymmErrors.h"
10 #pragma GCC diagnostic ignored "-Wuseless-cast"
19 random = std::make_unique<TRandom3>(Get<int>(
fitMan->
raw()[
"General"][
"Seed"], __FILE__, __LINE__));
26 clock = std::make_unique<TStopwatch>();
27 stepClock = std::make_unique<TStopwatch>();
30 debug = GetFromManager<bool>(
fitMan->
raw()[
"General"][
"Debug"],
false, __FILE__ , __LINE__);
33 auto outfile = Get<std::string>(
fitMan->
raw()[
"General"][
"OutputFile"], __FILE__ , __LINE__);
36 auto_save = Get<int>(
fitMan->
raw()[
"General"][
"MCMC"][
"AutoSave"], __FILE__ , __LINE__);
42 outTree =
new TTree(
"posteriors",
"Posterior_Distributions");
58 if (debug) debugFile.open((outfile+
".log").c_str());
62 fTestLikelihood = GetFromManager<bool>(
fitMan->
raw()[
"General"][
"Fitter"][
"FitTestLikelihood"],
false, __FILE__ , __LINE__);
83 TDirectory* MaCh3Version =
outputFile->mkdir(
"MaCh3Engine");
86 if (std::getenv(
"MaCh3_ROOT") ==
nullptr) {
92 if (std::getenv(
"MACH3") ==
nullptr) {
97 std::string header_path = std::string(std::getenv(
"MACH3"));
98 header_path +=
"/version.h";
99 FILE* file = fopen(header_path.c_str(),
"r");
102 header_path = std::string(std::getenv(
"MaCh3_ROOT"));
103 header_path +=
"/version.h";
109 TMacro versionHeader(
"version_header",
"version_header");
110 versionHeader.ReadFile(header_path.c_str());
111 versionHeader.Write();
119 Engine.Write(
GetName().c_str());
121 MaCh3Version->Write();
133 for(
unsigned int i = 0; i <
systematics.size(); ++i)
136 for(
unsigned int i = 0; i <
samples.size(); ++i) {
138 for(
int iSam = 0; iSam <
samples[i]->GetNSamples(); ++iSam) {
139 MACH3LOG_INFO(
" {}: Sample name: {}, with {} osc channels",iSam ,
samples[i]->GetSampleTitle(iSam),
samples[i]->GetNOscChannels(iSam));
164 bool SaveProposal = GetFromManager<bool>(
fitMan->
raw()[
"General"][
"SaveProposal"],
false, __FILE__ , __LINE__);
166 if(SaveProposal)
MACH3LOG_INFO(
"Will save in the chain proposal parameters and LogL");
169 cov->SetBranches(*
outTree, SaveProposal);
183 for (
size_t i = 0; i <
samples.size(); ++i) {
184 std::stringstream oss, oss2;
185 oss <<
"LogL_sample_" << i;
186 oss2 << oss.str() <<
"/D";
191 std::stringstream oss, oss2;
192 oss <<
"LogL_systematic_" <<
systematics[i]->GetName();
193 oss2 << oss.str() <<
"/D";
205 MACH3LOG_INFO(
"-------------------- Starting MCMC --------------------");
208 debugFile <<
"----- Starting MCMC -----" << std::endl;
223 for (
size_t i = 0; i <
samples.size(); ++i) {
224 samples[i]->CleanMemoryBeforeFit();
236 int originalErrorLevel = gErrorIgnoreLevel;
237 gErrorIgnoreLevel = kFatal;
247 debugFile <<
"\n\n" <<
step <<
" steps took " <<
clock->RealTime() <<
" seconds to complete. (" <<
clock->RealTime() /
step <<
"s / step).\n" <<
accCount<<
" steps were accepted." << std::endl;
255 gErrorIgnoreLevel = originalErrorLevel;
263 for (
const auto &s :
samples) {
264 for (
int iExisting = 0; iExisting < s->GetNSamples(); ++iExisting) {
265 for (
int iNew = 0; iNew < sample->
GetNSamples(); ++iNew) {
266 if (s->GetSampleTitle(iExisting) == sample->
GetSampleTitle(iNew)) {
268 "Duplicate sample title '{}' in handler {} detected: "
270 sample->
GetName(), s->GetName());
277 for (
const auto &s :
samples) {
278 if (s->GetName() == sample->
GetName()) {
302 for (
int iPar = 0; iPar <
systematics[s]->GetNumParams(); ++iPar)
307 MACH3LOG_ERROR(
"ParameterHandler {} has param '{}' which already exists in in {}, with name {}",
313 MACH3LOG_ERROR(
"ParameterHandler {} has param '{}' which already exists in {}, with name {}",
331 CorrMatrix->Write((cov->
GetName() + std::string(
"_Corr")).c_str());
349 TFile *infile =
M3::Open(FitName,
"READ", __FILE__, __LINE__);
350 TTree *posts = infile->Get<TTree>(
"posteriors");
351 unsigned int step_val = 0;
353 posts->SetBranchAddress(
"step",&step_val);
354 posts->SetBranchAddress(
"LogL",&log_val);
358 TDirectory* CovarianceFolder = infile->Get<TDirectory>(
"CovarianceFolder");
360 std::string ConfigName =
"Config_" +
systematics[s]->GetName();
361 TMacro *ConfigCov = CovarianceFolder->Get<TMacro>(ConfigName.c_str());
363 if (ConfigCov !=
nullptr) {
367 YAML::Node ConfigCurrent =
systematics[s]->GetConfig();
371 MACH3LOG_ERROR(
"Yaml configs in previous chain (from path {}) and current one are different", FitName);
378 CovarianceFolder->Close();
379 delete CovarianceFolder;
381 std::vector<double> branch_vals;
382 std::vector<std::string> branch_name;
383 systematics[s]->MatchMaCh3OutputBranches(posts, branch_vals, branch_name);
384 posts->GetEntry(posts->GetEntries()-1);
393 for (
int i = 0; i <
systematics[s]->GetNumParams(); ++i) {
394 posts->SetBranchAddress(
systematics[s]->GetParName(i).c_str(),
nullptr);
414 if (
fitMan ==
nullptr)
return;
417 if (GetFromManager<bool>(
fitMan->
raw()[
"General"][
"ProcessMCMC"],
false, __FILE__ , __LINE__)){
423 TVectorD *Central =
nullptr;
424 TVectorD *Errors =
nullptr;
425 TVectorD *Central_Gauss =
nullptr;
426 TVectorD *Errors_Gauss =
nullptr;
427 TVectorD *Peaks =
nullptr;
430 Processor.
GetPostfit(Central, Errors, Central_Gauss, Errors_Gauss, Peaks);
434 TMatrixDSym *Covariance =
nullptr;
435 TMatrixDSym *Correlation =
nullptr;
445 MACH3LOG_INFO(
"Opening output again to update with means..");
446 outputFile =
new TFile(Get<std::string>(
fitMan->
raw()[
"General"][
"OutputFile"], __FILE__, __LINE__).c_str(),
"UPDATE");
448 Central->Write(
"PDF_Means");
449 Errors->Write(
"PDF_Errors");
450 Central_Gauss->Write(
"Gauss_Means");
451 Errors_Gauss->Write(
"Errors_Gauss");
452 Covariance->Write(
"Covariance");
453 Correlation->Write(
"Correlation");
465 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
467 TStopwatch clockRace;
469 for(
int Lap = 0; Lap < NLaps; ++Lap) {
473 MACH3LOG_INFO(
"It took {:.4f} s to reweights {} times sample: {}", clockRace.RealTime(), NLaps,
samples[ivs]->GetName());
474 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
477 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
479 TStopwatch clockRace;
481 for(
int Lap = 0; Lap < NLaps; ++Lap) {
485 MACH3LOG_INFO(
"It took {:.4f} s to calculate GetLikelihood {} times sample: {}", clockRace.RealTime(), NLaps,
samples[ivs]->GetName());
486 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
489 std::vector<std::vector<double>> StepsValuesBefore(
systematics.size());
491 StepsValuesBefore[s] =
systematics[s]->GetProposed();
494 TStopwatch clockRace;
496 for(
int Lap = 0; Lap < NLaps; ++Lap) {
500 MACH3LOG_INFO(
"It took {:.4f} s to propose step {} times cov: {}", clockRace.RealTime(), NLaps,
systematics[s]->GetName());
501 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
504 systematics[s]->SetParameters(StepsValuesBefore[s]);
508 TStopwatch clockRace;
510 for(
int Lap = 0; Lap < NLaps; ++Lap) {
514 MACH3LOG_INFO(
"It took {:.4f} s to calculate get likelihood {} times cov: {}", clockRace.RealTime(), NLaps,
systematics[s]->GetName());
515 MACH3LOG_INFO(
"On average {:.6f}", clockRace.RealTime()/NLaps);
523 bool isScanRanges =
false;
525 if(
fitMan->
raw()[
"LLHScan"][
"ScanRanges"]){
526 YAML::Node scanRangesList =
fitMan->
raw()[
"LLHScan"][
"ScanRanges"];
527 for (
auto it = scanRangesList.begin(); it != scanRangesList.end(); ++it) {
528 std::string itname = it->first.as<std::string>();
529 std::vector<double> itrange = it->second.as<std::vector<double>>();
531 scanRanges[itname] = itrange;
535 MACH3LOG_INFO(
"There are no user-defined parameter ranges, so I'll use default param bounds for LLH Scans");
544 for(
unsigned int is = 0; is < SkipVector.size(); ++is)
546 if(ParamName.substr(0, SkipVector[is].length()) == SkipVector[is])
558 double& lower,
double& upper,
const int n_points,
const std::string& suffix)
const {
561 std::map<std::string, std::vector<double>> scanRanges;
564 double nSigma = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSigma"], 1., __FILE__, __LINE__);
565 bool IsPCA = cov->
IsPCA();
569 if (IsPCA) name +=
"_PCA";
578 if (std::abs(CentralValue - prior) > 1e-10) {
579 MACH3LOG_INFO(
"For {} scanning around value {} rather than prior {}", name, CentralValue, prior);
602 auto it = scanRanges.find(name);
603 if (it != scanRanges.end() && it->second.size() == 2) {
604 lower = it->second[0];
605 upper = it->second[1];
606 MACH3LOG_INFO(
"Found matching param name for setting specified range for {}", name);
607 MACH3LOG_INFO(
"Range for {} = [{:.2f}, {:.2f}]", name, lower, upper);
615 MACH3LOG_INFO(
"Scanning {} {} with {} steps, from [{:.2f} , {:.2f}], CV = {:.2f}", suffix, name, n_points, lower, upper, CentralValue);
628 bool PlotLLHScanBySample = GetFromManager<bool>(
fitMan->
raw()[
"LLHScan"][
"LLHScanBySample"],
false, __FILE__ , __LINE__);
629 auto SkipVector = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSkipVector"], {}, __FILE__ , __LINE__);
633 std::vector<TDirectory *> Cov_LLH(
systematics.size());
634 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
636 std::string NameTemp =
systematics[ivc]->GetName();
637 NameTemp = NameTemp.substr(0, NameTemp.find(
"_cov")) +
"_LLH";
638 Cov_LLH[ivc] =
outputFile->mkdir(NameTemp.c_str());
641 std::vector<TDirectory *> SampleClass_LLH(
samples.size());
642 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
644 std::string NameTemp =
samples[ivs]->GetName();
645 SampleClass_LLH[ivs] =
outputFile->mkdir(NameTemp.c_str());
648 TDirectory *Sample_LLH =
outputFile->mkdir(
"Sample_LLH");
649 TDirectory *Total_LLH =
outputFile->mkdir(
"Total_LLH");
651 std::vector<TDirectory *>SampleSplit_LLH;
652 if(PlotLLHScanBySample)
655 int SampleIterator = 0;
656 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
658 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is )
660 SampleSplit_LLH[SampleIterator] =
outputFile->mkdir((
samples[ivs]->GetSampleTitle(is)+
"_LLH").c_str());
666 const int n_points = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanPoints"], 100, __FILE__ , __LINE__);
669 const int countwidth = int(
double(n_points)/
double(5));
676 int npars = cov->GetNumParams();
677 bool IsPCA = cov->IsPCA();
678 if (IsPCA) npars = cov->GetNParameters();
679 for (
int i = 0; i < npars; ++i)
682 std::string name = cov->GetParFancyName(i);
683 if (IsPCA) name +=
"_PCA";
687 double CentralValue, lower, upper;
690 auto hScan = std::make_unique<TH1D>((name +
"_full").c_str(), (name +
"_full").c_str(), n_points, lower, upper);
691 hScan->SetTitle((std::string(
"2LLH_full, ") + name +
";" + name +
"; -2(ln L_{sample} + ln L_{xsec+flux} + ln L_{det})").c_str());
692 hScan->SetDirectory(
nullptr);
694 auto hScanSam = std::make_unique<TH1D>((name +
"_sam").c_str(), (name +
"_sam").c_str(), n_points, lower, upper);
695 hScanSam->SetTitle((std::string(
"2LLH_sam, ") + name +
";" + name +
"; -2(ln L_{sample})").c_str());
696 hScanSam->SetDirectory(
nullptr);
698 std::vector<std::unique_ptr<TH1D>> hScanSample(
samples.size());
699 std::vector<double> nSamLLH(
samples.size(), 0.0);
700 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
702 std::string NameTemp =
samples[ivs]->GetName();
703 hScanSample[ivs] = std::make_unique<TH1D>((name+
"_"+NameTemp).c_str(), (name+
"_" + NameTemp).c_str(), n_points, lower, upper);
704 hScanSample[ivs]->SetDirectory(
nullptr);
705 hScanSample[ivs]->SetTitle((
"2LLH_" + NameTemp +
", " + name +
";" + name +
"; -2(ln L_{" + NameTemp +
"})").c_str());
708 std::vector<std::unique_ptr<TH1D>> hScanCov(
systematics.size());
709 std::vector<double> nCovLLH(
systematics.size(), 0.0);
710 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
712 std::string NameTemp =
systematics[ivc]->GetName();
713 NameTemp = NameTemp.substr(0, NameTemp.find(
"_cov"));
714 hScanCov[ivc] = std::make_unique<TH1D>((name +
"_" + NameTemp).c_str(), (name +
"_" + NameTemp).c_str(), n_points, lower, upper);
715 hScanCov[ivc]->SetDirectory(
nullptr);
716 hScanCov[ivc]->SetTitle((
"2LLH_" + NameTemp +
", " + name +
";" + name +
"; -2(ln L_{" + NameTemp +
"})").c_str());
719 std::vector<std::unique_ptr<TH1D>> hScanSamSplit;
720 std::vector<double> sampleSplitllh;
721 if(PlotLLHScanBySample)
723 int SampleIterator = 0;
726 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
728 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is )
730 auto histName = name +
samples[ivs]->GetSampleTitle(is);
731 auto histTitle = std::string(
"2LLH_sam, ") + name +
";" + name +
"; -2(ln L_{sample})";
732 hScanSamSplit[SampleIterator] = std::make_unique<TH1D>(histName.c_str(), histTitle.c_str(), n_points, lower, upper);
733 hScanSamSplit[SampleIterator]->SetDirectory(
nullptr);
740 for (
int j = 0; j < n_points; ++j)
742 if (j % countwidth == 0)
747 cov->GetPCAHandler()->SetParPropPCA(i, hScan->GetBinCenter(j+1));
750 cov->SetParProp(i, hScan->GetBinCenter(j+1));
754 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs ){
758 double totalllh = 0.;
761 double samplellh = 0.;
763 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs ) {
764 nSamLLH[ivs] =
samples[ivs]->GetLikelihood();
765 samplellh += nSamLLH[ivs];
768 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc ) {
770 totalllh += nCovLLH[ivc];
773 totalllh += samplellh;
775 if(PlotLLHScanBySample)
777 int SampleIterator = 0;
778 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
780 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is)
782 sampleSplitllh[SampleIterator] =
samples[ivs]->GetSampleLikelihood(is);
788 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs ) {
789 hScanSample[ivs]->SetBinContent(j+1, 2*nSamLLH[ivs]);
791 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc ) {
792 hScanCov[ivc]->SetBinContent(j+1, 2*nCovLLH[ivc]);
795 hScanSam->SetBinContent(j+1, 2*samplellh);
796 hScan->SetBinContent(j+1, 2*totalllh);
798 if(PlotLLHScanBySample)
800 int SampleIterator = 0;
801 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
803 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is)
805 hScanSamSplit[SampleIterator]->SetBinContent(j+1, 2*sampleSplitllh[SampleIterator]);
811 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
814 hScanCov[ivc]->Write();
817 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
819 SampleClass_LLH[ivs]->cd();
820 hScanSample[ivs]->Write();
827 if(PlotLLHScanBySample)
829 int SampleIterator = 0;
830 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
832 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is)
834 SampleSplit_LLH[SampleIterator]->cd();
835 hScanSamSplit[SampleIterator]->Write();
843 cov->GetPCAHandler()->SetParPropPCA(i, CentralValue);
845 cov->SetParProp(i, CentralValue);
850 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
852 Cov_LLH[ivc]->Write();
856 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
858 SampleClass_LLH[ivs]->Write();
859 delete SampleClass_LLH[ivs];
868 if(PlotLLHScanBySample)
870 int SampleIterator = 0;
871 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
873 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is )
875 SampleSplit_LLH[SampleIterator]->Write();
876 delete SampleSplit_LLH[SampleIterator];
887 TFile* outputFileLLH =
nullptr;
888 bool ownsfile =
false;
889 if(outputFileName !=
""){
890 outputFileLLH =
M3::Open(outputFileName,
"READ", __FILE__, __LINE__);
896 TDirectory *Sample_LLH = outputFileLLH->Get<TDirectory>(
"Sample_LLH");
899 if(!Sample_LLH || Sample_LLH->IsZombie())
901 MACH3LOG_WARN(
"Couldn't find Sample_LLH, it looks like LLH scan wasn't run, will do this now");
903 Sample_LLH = outputFileLLH->Get<TDirectory>(
"Sample_LLH");
908 const int npars = cov->GetNumParams();
909 std::vector<double> StepScale(npars);
910 for (
int i = 0; i < npars; ++i)
912 std::string name = cov->GetParFancyName(i);
913 StepScale[i] = cov->GetIndivStepScale(i);
914 TH1D* LLHScan = Sample_LLH->Get<TH1D>((name+
"_sam").c_str());
915 if(LLHScan ==
nullptr)
917 MACH3LOG_WARN(
"Couldn't find LLH scan, for {}, skipping", name);
920 const double LLH_val = std::max(LLHScan->GetBinContent(1), LLHScan->GetBinContent(LLHScan->GetNbinsX()));
922 if(LLH_val < 0.001)
continue;
927 const double Var = 1.;
928 const double approxSigma = TMath::Abs(Var)/std::sqrt(LLH_val);
931 const double NewStepScale = approxSigma * 2.38/std::sqrt(npars);
932 StepScale[i] = NewStepScale;
936 cov->SetIndivStepScale(StepScale);
937 cov->SaveUpdatedMatrixConfig();
939 if(ownsfile && outputFileLLH !=
nullptr)
delete outputFileLLH;
951 TDirectory *Sample_2DLLH =
outputFile->mkdir(
"Sample_2DLLH");
952 auto SkipVector = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSkipVector"], {}, __FILE__ , __LINE__);;
955 const int n_points = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"2DLLHScanPoints"], 20, __FILE__ , __LINE__);
957 const int countwidth = int(
double(n_points)/
double(5));
964 int npars = cov->GetNumParams();
965 bool IsPCA = cov->IsPCA();
966 if (IsPCA) npars = cov->GetNParameters();
968 for (
int i = 0; i < npars; ++i)
970 std::string name_x = cov->GetParFancyName(i);
971 if (IsPCA) name_x +=
"_PCA";
973 double central_x, lower_x, upper_x;
979 for (
int j = 0; j < i; ++j)
981 std::string name_y = cov->GetParFancyName(j);
982 if (IsPCA) name_y +=
"_PCA";
987 double central_y, lower_y, upper_y;
990 auto hScanSam = std::make_unique<TH2D>((name_x +
"_" + name_y +
"_sam").c_str(), (name_x +
"_" + name_y +
"_sam").c_str(),
991 n_points, lower_x, upper_x, n_points, lower_y, upper_y);
992 hScanSam->SetDirectory(
nullptr);
993 hScanSam->GetXaxis()->SetTitle(name_x.c_str());
994 hScanSam->GetYaxis()->SetTitle(name_y.c_str());
995 hScanSam->GetZaxis()->SetTitle(
"2LLH_sam");
998 for (
int x = 0; x < n_points; ++x)
1000 if (x % countwidth == 0)
1003 for (
int y = 0; y < n_points; ++y)
1007 cov->GetPCAHandler()->SetParPropPCA(i, hScanSam->GetXaxis()->GetBinCenter(x+1));
1008 cov->GetPCAHandler()->SetParPropPCA(j, hScanSam->GetYaxis()->GetBinCenter(y+1));
1011 cov->SetParProp(i, hScanSam->GetXaxis()->GetBinCenter(x+1));
1012 cov->SetParProp(j, hScanSam->GetYaxis()->GetBinCenter(y+1));
1015 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs) {
1020 double samplellh = 0;
1021 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs) {
1022 samplellh +=
samples[ivs]->GetLikelihood();
1024 hScanSam->SetBinContent(x+1, y+1, 2*samplellh);
1032 cov->GetPCAHandler()->SetParPropPCA(i, central_x);
1033 cov->GetPCAHandler()->SetParPropPCA(j, central_y);
1035 cov->SetParProp(i, central_x);
1036 cov->SetParProp(j, central_y);
1041 Sample_2DLLH->Write();
1042 delete Sample_2DLLH;
1055 bool PlotLLHScanBySample = GetFromManager<bool>(
fitMan->
raw()[
"LLHScan"][
"LLHScanBySample"],
false, __FILE__ , __LINE__);
1056 auto ParamsOfInterest = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"LLHScan"][
"LLHParameters"], {}, __FILE__, __LINE__);
1058 if(ParamsOfInterest.empty()) {
1059 MACH3LOG_WARN(
"There were no LLH parameters of interest specified to run the LLHMap! LLHMap will not run at all ...");
1065 std::vector<std::tuple<std::string, ParameterHandlerBase*, int>> ParamsCovIDs;
1066 for(
auto& p : ParamsOfInterest) {
1069 for(
int c = 0; c < cov->GetNumParams(); ++c) {
1070 if(cov->GetParName(c) == p || cov->GetParFancyName(c) == p) {
1072 for(
auto& pc : ParamsCovIDs) {
1073 if(std::get<1>(pc) == cov && std::get<2>(pc) == c)
1075 MACH3LOG_WARN(
"Parameter {} as {}({}) listed multiple times for LLHMap, omitting and using only once!", p, cov->GetName(), c);
1082 ParamsCovIDs.push_back(std::make_tuple(p, cov, c));
1092 MACH3LOG_INFO(
"Parameter {} found in {} at an index {}.", p, std::get<1>(ParamsCovIDs.back())->GetName(), std::get<2>(ParamsCovIDs.back()));
1094 MACH3LOG_WARN(
"Parameter {} not found in any of the systematic covariance objects. Will not scan over this one!", p);
1098 std::map<std::string, std::pair<int, std::pair<double, double>>> ParamsRanges;
1100 MACH3LOG_INFO(
"======================================================================================");
1101 MACH3LOG_INFO(
"Performing a general multi-dimensional LogL map scan over following parameters ranges:");
1102 MACH3LOG_INFO(
"======================================================================================");
1103 unsigned long TotalPoints = 1;
1105 double nSigma = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanSigma"], 1., __FILE__, __LINE__);
1110 for(
auto& p : ParamsCovIDs) {
1112 std::string name = std::get<0>(p);
1113 int i = std::get<2>(p);
1116 ParamsRanges[name].first = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"LLHScanPoints"], 20, __FILE__, __LINE__);
1118 ParamsRanges[name].first = GetFromManager<int>(
fitMan->
raw()[
"LLHScan"][
"ScanPoints"][name], ParamsRanges[name].first, __FILE__, __LINE__);
1123 bool IsPCA = cov->
IsPCA();
1131 if (std::abs(CentralValue - prior) > 1e-10) {
1132 MACH3LOG_INFO(
"For {} scanning around value {} rather than prior {}", name, CentralValue, prior);
1150 ParamsRanges[name].second = {lower,upper};
1153 ParamsRanges[name].second = GetFromManager<std::pair<double,double>>(
fitMan->
raw()[
"LLHScan"][
"ScanRanges"][name], ParamsRanges[name].second, __FILE__, __LINE__);
1155 MACH3LOG_INFO(
"{} from {:.4f} to {:.4f} with a {:.5f} step ({} points total)",
1156 name, ParamsRanges[name].second.first, ParamsRanges[name].second.second,
1157 (ParamsRanges[name].second.second - ParamsRanges[name].second.first)/(ParamsRanges[name].first - 1.),
1158 ParamsRanges[name].first);
1160 TotalPoints *= ParamsRanges[name].first;
1164 MACH3LOG_INFO(
"In total, looping over {} points, from {} parameters. Estimates for run time:", TotalPoints, ParamsCovIDs.size());
1165 MACH3LOG_INFO(
" 1 s per point = {} hours",
double(TotalPoints)/3600.);
1166 MACH3LOG_INFO(
" 0.1 s per point = {} hours",
double(TotalPoints)/36000.);
1167 MACH3LOG_INFO(
"0.01 s per point = {} hours",
double(TotalPoints)/360000.);
1168 MACH3LOG_INFO(
"==================================================================================");
1170 const int countwidth = int(
double(TotalPoints)/
double(20));
1173 auto LLHMap =
new TTree(
"llhmap",
"LLH Map");
1176 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
1178 std::string NameTemp =
systematics[ivc]->GetName();
1179 NameTemp = NameTemp.substr(0, NameTemp.find(
"_cov")) +
"_LLH";
1180 LLHMap->Branch(NameTemp.c_str(), &CovLogL[ivc]);
1183 std::vector<double> SampleClassLogL(
samples.size());
1184 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
1186 std::string NameTemp =
samples[ivs]->GetName()+
"_LLH";
1187 LLHMap->Branch(NameTemp.c_str(), &SampleClassLogL[ivs]);
1190 double SampleLogL, TotalLogL;
1191 LLHMap->Branch(
"Sample_LLH", &SampleLogL);
1192 LLHMap->Branch(
"Total_LLH", &TotalLogL);
1194 std::vector<double>SampleSplitLogL;
1195 if(PlotLLHScanBySample)
1198 int SampleIterator = 0;
1199 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
1201 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is )
1203 std::string NameTemp =
samples[ivs]->GetSampleTitle(is)+
"_LLH";
1204 LLHMap->Branch(NameTemp.c_str(), &SampleSplitLogL[SampleIterator]);
1210 std::vector<double> ParamsValues(ParamsCovIDs.size());
1211 for(
unsigned int i=0; i < ParamsCovIDs.size(); ++i)
1212 LLHMap->Branch(std::get<0>(ParamsCovIDs[i]).c_str(), &ParamsValues[i]);
1216 std::vector<unsigned long> idx(ParamsCovIDs.size(), 0);
1219 for(
unsigned long sp = 0; sp < TotalPoints; ++sp)
1222 for(
unsigned int n = 0; n < ParamsCovIDs.size(); ++n)
1225 std::string name = std::get<0>(ParamsCovIDs[n]);
1226 int points = ParamsRanges[name].first;
1227 double low = ParamsRanges[name].second.first;
1228 double high = ParamsRanges[name].second.second;
1231 unsigned long dev = 1;
1232 for(
unsigned int m = 0; m <= n; ++m)
1233 dev *= ParamsRanges[std::get<0>(ParamsCovIDs[m])].first;
1237 idx[n] = idx[n] / ( dev / points );
1240 ParamsValues[n] = low + (high-low) *
double(idx[n])/double(points-1);
1245 int i = std::get<2>(ParamsCovIDs[n]);
1257 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
1260 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs)
1262 SampleClassLogL[ivs] = 2.*
samples[ivs]->GetLikelihood();
1263 SampleLogL += SampleClassLogL[ivs];
1265 TotalLogL += SampleLogL;
1268 for(
unsigned int ivc = 0; ivc <
systematics.size(); ++ivc )
1270 CovLogL[ivc] = 2.*
systematics[ivc]->GetLikelihood();
1271 TotalLogL += CovLogL[ivc];
1274 if(PlotLLHScanBySample)
1276 int SampleIterator = 0;
1277 for(
unsigned int ivs = 0; ivs <
samples.size(); ++ivs )
1279 for(
int is = 0; is <
samples[ivs]->GetNSamples(); ++is)
1281 SampleSplitLogL[SampleIterator] = 2.*
samples[ivs]->GetSampleLikelihood(is);
1289 if (sp % countwidth == 0)
1301 if(!
fitMan->
raw()[
"SigmaVar"][
"CustomRange"])
return;
1303 auto Config =
fitMan->
raw()[
"SigmaVar"][
"CustomRange"];
1305 const auto sigmaStr = std::to_string(
static_cast<int>(std::round(sigma)));
1307 if (Config[ParName] && Config[ParName][sigmaStr]) {
1308 ParamShiftValue = Config[ParName][sigmaStr].as<
double>();
1309 MACH3LOG_INFO(
" ::: setting custom range from config ::: {} -> {}", ParName, ParamShiftValue);
1318 hist->SetTitle(baseName.c_str());
1320 TString className = hist->ClassName();
1323 if (className.Contains(
"TH1")) {
1324 hist->GetYaxis()->SetTitle(
"Events");
1325 }
else if (className.Contains(
"TH2")) {
1326 hist->GetZaxis()->SetTitle(
"Events");
1328 hist->Write(baseName.c_str());
1334 const std::string& suffix,
1336 const bool by_channel,
1337 const std::vector<TDirectory*>& SampleDir) {
1340 for (
int iSample = 0; iSample < sample->
GetNSamples(); ++iSample) {
1341 SampleDir[iSample]->cd();
1343 for(
int iDim1 = 0; iDim1 < sample->
GetNDim(iSample); iDim1++) {
1344 std::string ProjectionName = sample->
GetKinVarName(iSample, iDim1);
1345 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim1);
1349 for (
int iMode = 0; iMode < modes->
GetNModes(); ++iMode) {
1356 for (
int iChan = 0; iChan < sample->
GetNOscChannels(iSample); ++iChan) {
1362 if (by_mode && by_channel) {
1363 for (
int iMode = 0; iMode < modes->
GetNModes(); ++iMode) {
1364 for (
int iChan = 0; iChan < sample->
GetNOscChannels(iSample); ++iChan) {
1371 if (!by_mode && !by_channel) {
1372 auto hist = sample->
Get1DVarHist(iSample, ProjectionName);
1375 for (
int iDim2 = iDim1 + 1; iDim2 < sample->
GetNDim(iSample); ++iDim2) {
1377 std::string XVarName = sample->
GetKinVarName(iSample, iDim1);
1378 std::string YVarName = sample->
GetKinVarName(iSample, iDim2);
1381 auto hist2D = sample->
Get2DVarHist(iSample, XVarName, YVarName);
1384 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(SampleHandlerInterface *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.
std::unique_ptr< TRandom3 > random
Random number.
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
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.
std::vector< SampleHandlerInterface * > samples
Sample holder.
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.
void GetStepScaleBasedOnLLHScan(const std::string &filename="")
LLH scan is good first estimate of step scale.
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.
void AddSampleHandler(SampleHandlerInterface *sample)
This function adds a sample PDF object to the analysis framework. The sample PDF object will be utili...
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.
M3::float_t GetParProp(const int i) const
Get proposed parameter value.
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.
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
virtual std::unique_ptr< TH1 > Get1DVarHistByModeAndChannel(const int iSample, const std::string &ProjectionVar_Str, const int kModeToFill=-1, const int kChannelToFill=-1, const int WeightStyle=0)=0
virtual std::string GetName() const =0
virtual void SaveAdditionalInfo(TDirectory *Dir)
Store additional info in a chan.
virtual std::unique_ptr< TH1 > Get1DVarHist(const int iSample, const std::string &ProjectionVar, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, const std::vector< KinematicCut > &SubEventSelectionVec={})=0
virtual std::string GetFlavourName(const int iSample, const int iChannel) const =0
MaCh3Modes * GetMaCh3Modes() const
Return pointer to MaCh3 modes.
virtual int GetNOscChannels(const int iSample) const =0
virtual M3::int_t GetNSamples()
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...
virtual std::string GetSampleTitle(const int Sample) const =0
virtual std::unique_ptr< TH2 > Get2DVarHist(const int iSample, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &EventSelectionVec={}, const int WeightStyle=0, const std::vector< KinematicCut > &SubEventSelectionVec={})=0
virtual int GetNDim(const int Sample) const =0
DB Function to differentiate 1D or 2D binning.
int getValue(const std::string &Type)
CW: Get info like RAM.
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
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