6 #pragma GCC diagnostic ignored "-Wfloat-conversion"
7 #pragma GCC diagnostic ignored "-Wuseless-cast"
21 else MACH3LOG_INFO(
"Using alternative method of statistical fluctuation, which is much slower");
25 FullLLH = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"FullLLH"],
false, __FILE__, __LINE__ );
29 Ntoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);
32 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
33 auto outfile = Get<std::string>(
fitMan->
raw()[
"General"][
"OutputFile"], __FILE__ , __LINE__);
34 if(PosteriorFileName == outfile){
35 MACH3LOG_ERROR(
"Output file ({}) and posterior files ({}) have same name", outfile, PosteriorFileName);
52 std::unordered_set<int>& ParameterOnlyToVary) {
55 auto DoNotThrowLegacyCov = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"DoNotThrowLegacyCov"], {}, __FILE__, __LINE__);
57 for (
size_t i = 0; i < DoNotThrowLegacyCov.size(); ++i) {
75 if (ParameterOnlyToVary.find(i) == ParameterOnlyToVary.end()) {
86 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
104 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
105 for (
int SampleIndex = 0; SampleIndex <
samples[iPDF]->GetNSamples(); ++SampleIndex) {
119 std::unordered_set<int>& ParameterOnlyToVary,
120 std::vector<const M3::float_t*>& BoundValuePointer,
121 std::vector<std::pair<double, double>>& ParamBounds) {
135 MACH3LOG_INFO(
"You've chosen to run Prior Predictive Distribution");
137 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
143 auto AllowDifferentConfigs = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"AllowDifferentConfigs"],
false, __FILE__, __LINE__);
151 if(AllowDifferentConfigs){
152 MACH3LOG_WARN(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
154 MACH3LOG_ERROR(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
161 MACH3LOG_ERROR(
"Found {} ParmaterHandler inheriting from ParameterHandlerGeneric, I can accept at most 1", counter);
170 auto ThrowParamGroupOnly = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowParamGroupOnly"], {}, __FILE__, __LINE__);
172 auto ParameterOnlyToVaryString = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowSingleParams"], {}, __FILE__, __LINE__);
174 if (!ThrowParamGroupOnly.empty() && !ParameterOnlyToVaryString.empty()) {
175 MACH3LOG_ERROR(
"Can't use ThrowParamGroupOnly and ThrowSingleParams at the same time");
179 if (!ParameterOnlyToVaryString.empty()) {
180 MACH3LOG_INFO(
"I will throw only: {}", fmt::join(ParameterOnlyToVaryString,
", "));
181 std::vector<int> ParameterVary(ParameterOnlyToVaryString.size());
183 for (
size_t i = 0; i < ParameterOnlyToVaryString.size(); ++i) {
186 MACH3LOG_ERROR(
"Can't proceed if param {} is missing", ParameterOnlyToVaryString[i]);
190 ParameterOnlyToVary = std::unordered_set<int>(ParameterVary.begin(), ParameterVary.end());
192 MACH3LOG_INFO(
"I have following parameter groups: {}", fmt::join(UniqueParamGroup,
", "));
193 if (ThrowParamGroupOnly.empty()) {
196 std::unordered_set<std::string> throwOnlySet(ThrowParamGroupOnly.begin(), ThrowParamGroupOnly.end());
197 ParameterGroupsNotVaried.clear();
199 for (
const auto& group : UniqueParamGroup) {
200 if (throwOnlySet.find(group) == throwOnlySet.end()) {
201 ParameterGroupsNotVaried.push_back(group);
205 MACH3LOG_INFO(
"I will vary: {}", fmt::join(ThrowParamGroupOnly,
", "));
206 MACH3LOG_INFO(
"Exclude: {}", fmt::join(ParameterGroupsNotVaried,
", "));
211 auto paramNode =
fitMan->
raw()[
"Predictive"][
"ParameterBounds"];
212 for (
const auto& p : paramNode) {
214 std::string name = p[0].as<std::string>();
217 double minVal = p[1][0].as<
double>();
218 double maxVal = p[1][1].as<
double>();
219 ParamBounds.emplace_back(minVal, maxVal);
222 for(
int iPar = 0; iPar <
systematics[s]->GetNParameters(); iPar++){
224 BoundValuePointer.push_back(
systematics[s]->RetPointer(iPar));
229 if(ParamBounds.size() != BoundValuePointer.size()){
233 MACH3LOG_INFO(
"Parameter: {} with : [{}, {}]", name, minVal, maxVal);
236 MACH3LOG_ERROR(
"Additional bounds not supported by prior predictive right now");
245 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
247 int originalErrorWarning = gErrorIgnoreLevel;
248 gErrorIgnoreLevel = kFatal;
249 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
251 gErrorIgnoreLevel = originalErrorWarning;
252 TDirectory* ToyDir =
nullptr;
253 if (!file || file->IsZombie()) {
257 if ((ToyDir = file->GetDirectory(
"Toys"))) {
258 MACH3LOG_INFO(
"Found toys in Posterior file will attempt toy reading");
267 TTree* PenaltyTree =
static_cast<TTree*
>(file->Get(
"ToySummary"));
275 Ntoys =
static_cast<int>(PenaltyTree->GetEntries());
276 int ConfigNtoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);;
277 if (
Ntoys != ConfigNtoys) {
278 MACH3LOG_WARN(
"Found different number of toys in saved file than asked to run!");
287 double Penalty = 0, Weight = 1;
288 PenaltyTree->SetBranchAddress(
"Penalty", &Penalty);
289 PenaltyTree->SetBranchAddress(
"Weight", &Weight);
290 PenaltyTree->SetBranchAddress(
"NModelParams", &
NModelParams);
292 for (
int i = 0; i <
Ntoys; ++i) {
293 PenaltyTree->GetEntry(i);
306 TH1* DataHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_data").c_str()));
309 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc").c_str()));
312 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2").c_str()));
317 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
322 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc_" + std::to_string(iToy)).c_str()));
323 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2_" + std::to_string(iToy)).c_str()));
338 TDirectory * ogdir = gDirectory;
340 std::vector<std::string> FancyNames;
341 std::string Name = std::string(
"Config_") + Systematics->
GetName();
342 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
344 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
345 TDirectory* CovarianceFolder = file->GetDirectory(
"CovarianceFolder");
347 TMacro* FoundMacro =
static_cast<TMacro*
>(CovarianceFolder->Get(Name.c_str()));
348 if(FoundMacro ==
nullptr) {
351 if(ogdir){ ogdir->cd(); }
358 int params = int(Settings[
"Systematics"].size());
359 FancyNames.resize(params);
361 for (
auto const ¶m : Settings[
"Systematics"]) {
362 FancyNames[iPar] = Get<std::string>(param[
"Systematic"][
"Names"][
"FancyName"], __FILE__ , __LINE__);
367 if(ogdir){ ogdir->cd(); }
374 TDirectory* Toy_1DDirectory,
375 TDirectory* Toy_2DDirectory,
378 int SampleCounter = 0;
379 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
381 auto* SampleHandler =
samples[iPDF];
382 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
386 auto SampleName = SampleHandler->GetSampleTitle(iSample);
387 const TH1* MCHist = SampleHandler->GetMCHist(iSample);
388 MC_Hist_Toy[SampleCounter][iToy] =
M3::Clone(MCHist, SampleName +
"_mc_" + std::to_string(iToy));
391 const TH1* W2Hist = SampleHandler->GetW2Hist(iSample);
392 W2_Hist_Toy[SampleCounter][iToy] =
M3::Clone(W2Hist, SampleName +
"_w2_" + std::to_string(iToy));
396 Toy_1DDirectory->cd();
397 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
398 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
399 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
401 auto hist = SampleHandler->Get1DVarHist(iSample, ProjectionName);
402 hist->SetTitle((SampleName + ProjectionSuffix).c_str());
403 hist->SetName((SampleName + ProjectionSuffix).c_str());
407 Toy_2DDirectory->cd();
409 for(
int iDim1 = 0; iDim1 < SampleHandler->GetNDim(iSample); iDim1++) {
410 for (
int iDim2 = iDim1 + 1; iDim2 < SampleHandler->GetNDim(iSample); ++iDim2) {
412 std::string XVarName = SampleHandler->GetKinVarName(iSample, iDim1);
413 std::string YVarName = SampleHandler->GetKinVarName(iSample, iDim2);
416 auto hist2D = SampleHandler->Get2DVarHist(iSample, XVarName, YVarName);
419 std::string suffix2D =
"_2DProj_" + std::to_string(iDim1) +
"_vs_" + std::to_string(iDim2) +
"_" + std::to_string(iToy);
420 hist2D->SetTitle((SampleName + suffix2D).c_str());
421 hist2D->SetName((SampleName + suffix2D).c_str());
434 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
436 auto* SampleHandler =
samples[iPDF];
437 auto* modes = SampleHandler->GetMaCh3Modes();
438 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
440 ByModeDirectory->cd();
442 auto SampleName = SampleHandler->GetSampleTitle(iSample);
443 for (
int iMode = 0; iMode < modes->GetNModes()+1; ++iMode) {
444 auto ModeName = modes->GetMaCh3ModeName(iMode);
445 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
446 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
447 std::string PlotSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + ModeName +
"_" + std::to_string(iToy);
449 auto hist = SampleHandler->Get1DVarHistByModeAndChannel(iSample, ProjectionName, iMode);
450 hist->SetTitle((SampleName + PlotSuffix).c_str());
451 hist->SetName((SampleName + PlotSuffix).c_str());
460 bool CheckBounds(
const std::vector<const M3::float_t*>& BoundValuePointer,
461 const std::vector<std::pair<double,double>>& ParamBounds) {
463 for (
size_t i = 0; i < BoundValuePointer.size(); ++i) {
464 const double val = *(BoundValuePointer[i]);
465 const double minVal = ParamBounds[i].first;
466 const double maxVal = ParamBounds[i].second;
468 if (val < minVal || val > maxVal)
482 std::vector<std::string> ParameterGroupsNotVaried;
484 std::unordered_set<int> ParameterOnlyToVary;
486 std::vector<const M3::float_t*> BoundValuePointer;
487 std::vector<std::pair<double, double>> ParamBounds;
491 BoundValuePointer, ParamBounds);
493 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
498 double Penalty = 0, Weight = 1.;
501 TTree *ToyTree =
new TTree(
"ToySummary",
"ToySummary");
502 ToyTree->Branch(
"Penalty", &Penalty,
"Penalty/D");
503 ToyTree->Branch(
"Weight", &Weight,
"Weight/D");
504 ToyTree->Branch(
"Draw", &Draw,
"Draw/I");
505 ToyTree->Branch(
"NModelParams", &
NModelParams,
"NModelParams/I");
509 std::vector<const M3::float_t*> ParampPointers(
NModelParams);
510 int ParamCounter = 0;
511 for (
size_t iSys = 0; iSys <
systematics.size(); iSys++)
513 for (
int iPar = 0; iPar <
systematics[iSys]->GetNumParams(); iPar++)
515 ParampPointers[ParamCounter] =
systematics[iSys]->RetPointer(iPar);
516 std::string Name =
systematics[iSys]->GetParFancyName(iPar);
518 while (Name.find(
"-") != std::string::npos) {
519 Name.replace(Name.find(
"-"), 1, std::string(
"_"));
521 ToyTree->Branch(Name.c_str(), &ParamValues[ParamCounter], (Name +
"/D").c_str());
525 TDirectory* ToyDirectory =
outputFile->mkdir(
"Toys");
527 int SampleCounter = 0;
528 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
530 auto* MaCh3Sample =
samples[iPDF];
531 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNSamples(); ++SampleIndex)
534 const TH1* DataHist = MaCh3Sample->GetDataHist(SampleIndex);
535 Data_Hist[SampleCounter] =
M3::Clone(DataHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data");
536 Data_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data").c_str());
538 const TH1* MCHist = MaCh3Sample->GetMCHist(SampleIndex);
539 MC_Nom_Hist[SampleCounter] =
M3::Clone(MCHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc");
540 MC_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc").c_str());
542 const TH1* W2Hist = MaCh3Sample->GetW2Hist(SampleIndex);
543 W2_Nom_Hist[SampleCounter] =
M3::Clone(W2Hist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2");
544 W2_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2").c_str());
549 TDirectory* Toy_1DDirectory =
outputFile->mkdir(
"Toys_1DHistVar");
550 TDirectory* Toy_2DDirectory =
outputFile->mkdir(
"Toys_2DHistVar");
551 auto doByMode = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"ByMode"],
false, __FILE__, __LINE__);
552 TDirectory* ByModeDirectory =
nullptr;
553 if(doByMode) ByModeDirectory =
outputFile->mkdir(
"Toys_ByMode");
554 auto ReweightNames = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ReweightNames"],
555 {
"Weight"}, __FILE__, __LINE__);
556 bool doReweight =
false;
557 std::vector<double> reweight_weight(ReweightNames.size(), 1.0);
560 std::vector<std::vector<double>> branch_vals(
systematics.size());
561 std::vector<std::vector<std::string>> branch_name(
systematics.size());
563 TChain* PosteriorFile =
nullptr;
564 unsigned int burn_in = 0;
565 unsigned int maxNsteps = 0;
566 unsigned int Step = 0;
569 PosteriorFile =
new TChain(
"posteriors");
570 PosteriorFile->Add(PosteriorFileName.c_str());
572 PosteriorFile->SetBranchAddress(
"step", &Step);
574 for (
size_t i = 0; i < ReweightNames.size(); ++i) {
575 const auto& name = ReweightNames[i];
576 if (PosteriorFile->GetBranch(name.c_str())) {
577 PosteriorFile->SetBranchStatus(name.c_str(),
true);
578 PosteriorFile->SetBranchAddress(name.c_str(), &reweight_weight[i]);
580 MACH3LOG_WARN(
"Missing reweight branch '{}' -> disabling ALL reweighting", name);
587 systematics[s]->MatchMaCh3OutputBranches(PosteriorFile, branch_vals[s], branch_name[s], fancy_names);
591 burn_in = Get<unsigned int>(
fitMan->
raw()[
"Predictive"][
"BurnInSteps"], __FILE__, __LINE__);
594 maxNsteps =
static_cast<unsigned int>(PosteriorFile->GetMaximum(
"step"));
595 if(burn_in >= maxNsteps)
597 MACH3LOG_ERROR(
"You are running on a chain shorter than burn in cut");
598 MACH3LOG_ERROR(
"Maximal value of nSteps: {}, burn in cut {}", maxNsteps, burn_in);
605 TStopwatch TempClock;
607 for(
int i = 0; i <
Ntoys; i++)
616 bool WithinBounds =
false;
621 while(Step < burn_in || !WithinBounds) {
622 entry =
random->Integer(
static_cast<unsigned int>(PosteriorFile->GetEntries()));
623 PosteriorFile->GetEntry(entry);
626 if(BoundValuePointer.size() > 0) {
631 WithinBounds =
CheckBounds(BoundValuePointer, ParamBounds);
647 SetParamters(ParameterGroupsNotVaried, ParameterOnlyToVary);
660 for (
size_t iWeight = 0; iWeight < reweight_weight.size(); ++iWeight) {
661 Weight *= reweight_weight[iWeight];
666 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
670 WriteToy(ToyDirectory, Toy_1DDirectory, Toy_2DDirectory, i);
674 for (
size_t iPar = 0; iPar < ParamValues.size(); iPar++) {
675 ParamValues[iPar] = *ParampPointers[iPar];
682 if(PosteriorFile)
delete PosteriorFile;
683 ToyDirectory->Close();
delete ToyDirectory;
684 Toy_1DDirectory->Close();
delete Toy_1DDirectory;
685 Toy_2DDirectory->Close();
delete Toy_2DDirectory;
687 ByModeDirectory->Close();
688 delete ByModeDirectory;
692 ToyTree->Write();
delete ToyTree;
694 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
702 TDirectory * ogdir = gDirectory;
703 TDirectory* ToyDir =
nullptr;
705 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
707 int originalErrorWarning = gErrorIgnoreLevel;
708 gErrorIgnoreLevel = kFatal;
709 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
710 gErrorIgnoreLevel = originalErrorWarning;
712 if (file ==
nullptr || file->IsZombie()) {
713 ToyDir =
outputFile->GetDirectory(
"Toys_1DHistVar");
715 ToyDir = file->GetDirectory(
"Toys_1DHistVar");
717 if(ToyDir ==
nullptr) {
718 ToyDir =
outputFile->GetDirectory(
"Toys_1DHistVar");
723 std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>> ProjectionToys(
TotalNumberOfSamples);
725 ProjectionToys[sample].resize(
Ntoys);
726 const int nDims =
SampleInfo[sample].Dimenstion;
727 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
728 ProjectionToys[sample][iToy].resize(nDims);
732 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
733 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
735 const int nDims =
SampleInfo[sample].Dimenstion;
736 for(
int iDim = 0; iDim < nDims; iDim ++){
737 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
738 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
739 ProjectionToys[sample][iToy][iDim] =
M3::Clone(MCHist1D);
743 if(file) { file->Close();
delete file; }
744 if(ogdir){ ogdir->cd(); }
748 const int nDims =
SampleInfo[sample].Dimenstion;
752 SampleDirectories[sample]->cd();
754 std::string nameX =
"Data_" +
SampleInfo[sample].Name +
"_Dim0";
755 std::string nameY =
"Data_" +
SampleInfo[sample].Name +
"_Dim1";
757 if(std::string(hist->ClassName()) ==
"TH2Poly") {
758 TAxis* xax = ProjectionToys[sample][0][0]->GetXaxis();
759 TAxis* yax = ProjectionToys[sample][0][1]->GetXaxis();
761 std::vector<double> XBinning(xax->GetNbins()+1);
762 std::vector<double> YBinning(yax->GetNbins()+1);
764 for(
int i=0;i<=xax->GetNbins();++i)
765 XBinning[i] = xax->GetBinLowEdge(i+1);
767 for(
int i=0;i<=yax->GetNbins();++i)
768 YBinning[i] = yax->GetBinLowEdge(i+1);
770 TH1D* ProjectionX =
PolyProjectionX(
static_cast<TH2Poly*
>(hist), nameX.c_str(), XBinning,
false);
771 TH1D* ProjectionY =
PolyProjectionY(
static_cast<TH2Poly*
>(hist), nameY.c_str(), YBinning,
false);
775 ProjectionX->GetXaxis()->SetTitle(x_var.c_str());
776 ProjectionY->GetXaxis()->SetTitle(y_var.c_str());
778 ProjectionX->SetDirectory(
nullptr);
779 ProjectionY->SetDirectory(
nullptr);
781 ProjectionX->Write(nameX.c_str());
782 ProjectionY->Write(nameY.c_str());
787 TH1D* ProjectionX =
static_cast<TH2D*
>(hist)->ProjectionX(nameX.c_str());
788 TH1D* ProjectionY =
static_cast<TH2D*
>(hist)->ProjectionY(nameY.c_str());
790 ProjectionX->SetDirectory(
nullptr);
791 ProjectionY->SetDirectory(
nullptr);
793 ProjectionX->Write(nameX.c_str());
794 ProjectionY->Write(nameY.c_str());
807 TDirectory* ogdir = gDirectory;
808 TDirectory* ToyDir =
nullptr;
810 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
812 int originalErrorWarning = gErrorIgnoreLevel;
813 gErrorIgnoreLevel = kFatal;
814 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
815 gErrorIgnoreLevel = originalErrorWarning;
817 if (file ==
nullptr || file->IsZombie()) {
818 ToyDir =
outputFile->GetDirectory(
"Toys_ByMode");
820 ToyDir = file->GetDirectory(
"Toys_ByMode");
822 if(ToyDir ==
nullptr) {
823 ToyDir =
outputFile->GetDirectory(
"Toys_ByMode");
830 auto* mode =
SampleInfo[0].SamHandler->GetMaCh3Modes();
831 auto NModes = mode->GetNModes()+1;
833 std::vector<std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>>> ProjectionToys(NModes);
834 for(
int iMode = 0; iMode < NModes; iMode++) {
837 ProjectionToys[iMode][sample].resize(
Ntoys);
838 const int nDims =
SampleInfo[sample].Dimenstion;
839 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
840 ProjectionToys[iMode][sample][iToy].resize(nDims);
845 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
846 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
847 for(
int iMode = 0; iMode < NModes; iMode++) {
848 auto ModeName = mode->GetMaCh3ModeName(iMode);
850 const int nDims =
SampleInfo[sample].Dimenstion;
851 for(
int iDim = 0; iDim < nDims; iDim ++) {
852 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + ModeName +
"_" + std::to_string(iToy);
853 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
854 ProjectionToys[iMode][sample][iToy][iDim] =
M3::Clone(MCHist1D);
863 ModeDirectory[iSample] = SampleDirectories[iSample]->mkdir(
"ByMode");
866 for(
int iMode = 0; iMode < NModes; iMode++) {
867 auto ModeName = mode->GetMaCh3ModeName(iMode);
868 ProduceSpectra(ProjectionToys[iMode], ModeDirectory, ModeName,
false);
871 ModeDirectory[iSample]->Close();
872 delete ModeDirectory[iSample];
874 if(file){file->Close();
delete file;}
875 if(ogdir){ ogdir->cd(); }
880 const std::vector<TDirectory*>& SampleDirectories,
881 const std::string suffix,
882 const bool DoSummary)
const {
888 const int nDims =
SampleInfo[sample].Dimenstion;
889 MaxValue[sample].assign(nDims, 0);
894 #pragma omp parallel for
897 for (
int toy = 0; toy <
Ntoys; ++toy) {
898 const int nDims =
SampleInfo[sample].Dimenstion;
899 for (
int dim = 0; dim < nDims; dim++) {
900 double max_val = Toys[sample][toy][dim]->GetMaximum();
901 MaxValue[sample][dim] = std::max(MaxValue[sample][dim], max_val);
910 const int nDims =
SampleInfo[sample].Dimenstion;
911 Spectra[sample].resize(nDims);
912 for (
int dim = 0; dim < nDims; dim++) {
914 TH1D* refHist = Toys[sample][0][dim].get();
916 const int n_bins_x = refHist->GetNbinsX();
917 std::vector<double> x_bin_edges(n_bins_x + 1);
918 for (
int b = 0; b < n_bins_x; ++b) {
919 x_bin_edges[b] = refHist->GetXaxis()->GetBinLowEdge(b + 1);
921 x_bin_edges[n_bins_x] = refHist->GetXaxis()->GetBinUpEdge(n_bins_x);
923 constexpr
int n_bins_y = 400;
924 constexpr
double y_min = 0.0;
925 const double y_max = MaxValue[sample][dim] * 1.05;
928 Spectra[sample][dim] = std::make_unique<TH2D>(
929 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
930 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
931 n_bins_x, x_bin_edges.data(),
932 n_bins_y, y_min, y_max
935 Spectra[sample][dim]->GetXaxis()->SetTitle(refHist->GetXaxis()->GetTitle());
936 Spectra[sample][dim]->GetYaxis()->SetTitle(
"Events");
938 Spectra[sample][dim]->SetDirectory(
nullptr);
939 Spectra[sample][dim]->Sumw2(
true);
945 #pragma omp parallel for collapse(2)
948 for (
int toy = 0; toy <
Ntoys; ++toy) {
949 const int nDims =
SampleInfo[sample].Dimenstion;
950 for (
int dim = 0; dim < nDims; dim++) {
951 FastViolinFill(Spectra[sample][dim].get(), Toys[sample][toy][dim].get());
958 SampleDirectories[sample]->cd();
959 const int nDims =
SampleInfo[sample].Dimenstion;
960 for (
long unsigned int dim = 0; dim < Spectra[sample].size(); dim++) {
961 Spectra[sample][dim]->Write();
963 if(nDims == 2 && DoSummary) {
964 const std::string name =
SampleInfo[sample].Name +
"_" + suffix+
"_PostPred_dim" + std::to_string(dim);
976 const std::vector<int>& bins)
const {
978 std::string BinName =
"";
980 const int b = bins[0];
981 const TAxis* ax = hist->GetXaxis();
982 const double low = ax->GetBinLowEdge(b);
983 const double up = ax->GetBinUpEdge(b);
985 BinName = fmt::format(
"Dim0 ({:g}, {:g})", low, up);
986 }
else if (Dim == 2) {
987 if(uniform ==
true) {
988 const int bx = bins[0];
989 const int by = bins[1];
990 const TAxis* ax = hist->GetXaxis();
991 const TAxis* ay = hist->GetYaxis();
992 BinName = fmt::format(
"Dim0 ({:g}, {:g}), ", ax->GetBinLowEdge(bx), ax->GetBinUpEdge(bx));
993 BinName += fmt::format(
"Dim1 ({:g}, {:g})", ay->GetBinLowEdge(by), ay->GetBinUpEdge(by));
995 TH2PolyBin* bin =
static_cast<TH2PolyBin*
>(
static_cast<TH2Poly*
>(hist)->GetBins()->At(bins[0]-1));
997 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 0, bin->GetXMin(), bin->GetXMax());
998 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 1, bin->GetYMin(), bin->GetYMax());
1001 BinName = hist->GetXaxis()->GetBinLabel(bins[0]);
1010 const std::string& suffix)
const {
1012 std::vector<std::unique_ptr<TH1D>> PosteriorHistVec;
1013 constexpr
int nBins = 100;
1014 const std::string Sample_Name =
SampleInfo[SampleId].Name;
1016 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1017 for (
int i = 1; i <= static_cast<TH2Poly*>(hist)->GetNumberOfBins(); ++i) {
1018 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1019 Sample_Name, suffix,
1023 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1024 PosteriorHist->SetDirectory(
nullptr);
1025 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1026 PosteriorHistVec.push_back(std::move(PosteriorHist));
1029 int nbinsx = hist->GetNbinsX();
1030 int nbinsy = hist->GetNbinsY();
1031 for (
int iy = 1; iy <= nbinsy; ++iy) {
1032 for (
int ix = 1; ix <= nbinsx; ++ix) {
1033 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1034 Sample_Name, suffix,
1038 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1039 PosteriorHist->SetDirectory(
nullptr);
1040 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1041 PosteriorHistVec.push_back(std::move(PosteriorHist));
1046 int nbinsx = hist->GetNbinsX();
1047 PosteriorHistVec.reserve(nbinsx);
1048 for (
int i = 1; i <= nbinsx; ++i) {
1049 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1050 Sample_Name, suffix,
1054 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1055 PosteriorHist->SetDirectory(
nullptr);
1056 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1057 PosteriorHistVec.push_back(std::move(PosteriorHist));
1060 return PosteriorHistVec;
1065 const std::vector<TDirectory*>& Directory,
1066 const std::string& suffix,
1067 const bool DebugHistograms,
1068 const bool WriteHist) {
1074 const int nDims =
SampleInfo[sample].Dimenstion;
1075 const std::string Sample_Name =
SampleInfo[sample].Name;
1076 Posterior_hist[sample] =
PerBinHistogram(Toys[sample][0].get(), sample, nDims, suffix);
1077 auto PredictiveHist =
M3::Clone(Toys[sample][0].get());
1079 PredictiveHist->Reset();
1080 PredictiveHist->SetName((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
1081 PredictiveHist->SetTitle((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
1082 PredictiveHist->SetDirectory(
nullptr);
1083 PostPred[sample] = std::move(PredictiveHist);
1088 #pragma omp parallel for
1091 const int nDims =
SampleInfo[sample].Dimenstion;
1092 auto& hist = Toys[sample][0];
1093 for (
size_t iToy = 0; iToy < Toys[sample].size(); ++iToy) {
1095 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1096 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
1097 double content = Toys[sample][iToy]->GetBinContent(i);
1098 Posterior_hist[sample][i-1]->Fill(content,
ReweightWeight[iToy]);
1101 int nbinsx = hist->GetNbinsX();
1102 int nbinsy = hist->GetNbinsY();
1103 for (
int iy = 1; iy <= nbinsy; ++iy) {
1104 for (
int ix = 1; ix <= nbinsx; ++ix) {
1105 int Bin = (iy-1) * nbinsx + (ix-1);
1106 double content = Toys[sample][iToy]->GetBinContent(ix, iy);
1107 Posterior_hist[sample][Bin]->Fill(content,
ReweightWeight[iToy]);
1112 int nbinsx = hist->GetNbinsX();
1113 for (
int i = 1; i <= nbinsx; ++i) {
1114 double content = Toys[sample][iToy]->GetBinContent(i);
1115 Posterior_hist[sample][i-1]->Fill(content,
ReweightWeight[iToy]);
1123 const int nDims =
SampleInfo[sample].Dimenstion;
1124 auto& hist = Toys[sample][0];
1125 Directory[sample]->cd();
1127 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1128 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
1129 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1131 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1132 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1135 int nbinsx = hist->GetNbinsX();
1136 int nbinsy = hist->GetNbinsY();
1137 for (
int iy = 1; iy <= nbinsy; ++iy) {
1138 for (
int ix = 1; ix <= nbinsx; ++ix) {
1139 int Bin = (iy-1) * nbinsx + (ix-1);
1140 if (DebugHistograms) Posterior_hist[sample][Bin]->Write();
1141 PostPred[sample]->SetBinContent(ix, iy, Posterior_hist[sample][Bin]->GetMean());
1142 PostPred[sample]->SetBinError(ix, iy, Posterior_hist[sample][Bin]->GetRMS());
1147 int nbinsx = hist->GetNbinsX();
1148 for (
int i = 1; i <= nbinsx; ++i) {
1149 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1150 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1151 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1154 if(WriteHist) PostPred[sample]->Write();
1170 TStopwatch TempClock;
1173 auto DebugHistograms = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"DebugHistograms"],
false, __FILE__, __LINE__);
1174 auto doByMode = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"ByMode"],
false, __FILE__, __LINE__);
1176 TDirectory* PredictiveDir =
outputFile->mkdir(
"Predictive");
1177 std::vector<TDirectory*> SampleDirectories;
1182 SampleDirectories[sample] = PredictiveDir->mkdir(
SampleInfo[sample].Name.c_str());
1202 SampleDirectories[sample]->Close();
1203 delete SampleDirectories[sample];
1206 auto StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__);
1207 auto StudyInfoCriterion = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyInformationCriterion"],
true, __FILE__, __LINE__);
1208 auto StudyCorr = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyCorrelations"],
true, __FILE__, __LINE__);
1217 PredictiveDir->Close();
1218 delete PredictiveDir;
1223 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
1244 if (
auto h1 =
dynamic_cast<const TH1D*
>(DatHist)) {
1246 static_cast<const TH1D*
>(MCHist),
1247 static_cast<const TH1D*
>(W2Hist),
1252 if (
auto h2 =
dynamic_cast<const TH2D*
>(DatHist)) {
1254 static_cast<const TH2D*
>(MCHist),
1255 static_cast<const TH2D*
>(W2Hist),
1260 if (
auto h2p =
dynamic_cast<const TH2Poly*
>(DatHist)) {
1262 static_cast<const TH2Poly*
>(MCHist),
1263 static_cast<const TH2Poly*
>(W2Hist),
1278 for (
int i = 1; i <= DatHist->GetXaxis()->GetNbins(); ++i)
1280 const double data = DatHist->GetBinContent(i);
1281 const double mc = MCHist->GetBinContent(i);
1282 const double w2 = W2Hist->GetBinContent(i);
1291 const TH2Poly* MCHist,
1292 const TH2Poly* W2Hist,
1296 for (
int i = 1; i <= DatHist->GetNumberOfBins(); ++i)
1298 const double data = DatHist->GetBinContent(i);
1299 const double mc = MCHist->GetBinContent(i);
1300 const double w2 = W2Hist->GetBinContent(i);
1315 const int nBinsX = DatHist->GetXaxis()->GetNbins();
1316 const int nBinsY = DatHist->GetYaxis()->GetNbins();
1318 for (
int i = 1; i <= nBinsX; ++i)
1320 for (
int j = 1; j <= nBinsY; ++j)
1322 const double data = DatHist->GetBinContent(i, j);
1323 const double mc = MCHist->GetBinContent(i, j);
1324 const double w2 = W2Hist->GetBinContent(i, j);
1339 auto applyFluctuation = [&](
auto* f,
auto* h) {
1347 if (Hist->InheritsFrom(TH2Poly::Class())) {
1348 applyFluctuation(
static_cast<TH2Poly*
>(FluctHist),
static_cast<TH2Poly*
>(Hist));
1350 else if (Hist->InheritsFrom(TH2D::Class())) {
1351 applyFluctuation(
static_cast<TH2D*
>(FluctHist),
static_cast<TH2D*
>(Hist));
1353 else if (Hist->InheritsFrom(TH1D::Class())) {
1354 applyFluctuation(
static_cast<TH1D*
>(FluctHist),
static_cast<TH1D*
>(Hist));
1364 const std::vector<TDirectory*>& SampleDir) {
1368 auto make_matrix = [&](
double init = 0.0) {
1369 return std::vector<std::vector<double>>(
1371 std::vector<double>(
Ntoys, init));
1373 auto chi2_dat = make_matrix();
1374 auto chi2_mc = make_matrix();
1375 auto chi2_pred = make_matrix();
1376 auto chi2_rate_dat = make_matrix();
1377 auto chi2_rate_mc = make_matrix();
1378 auto chi2_rate_pred = make_matrix();
1381 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1393 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1394 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1397 auto PredFluctHist =
M3::Clone(PostPred_mc[iSample].get());
1410 chi2_rate_mc[iSample][iToy] =
CalcLLH(DrawFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1411 chi2_rate_pred[iSample][iToy] =
CalcLLH(PredFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1426 MakeChi2Plots(chi2_mc,
"-2LLH (Draw Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_drawfluc_draw");
1427 MakeChi2Plots(chi2_pred,
"-2LLH (Pred Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_predfluc_draw");
1430 MakeChi2Plots(chi2_rate_mc,
"-2LLH (Rate Draw Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_drawfluc_draw");
1431 MakeChi2Plots(chi2_rate_pred,
"-2LLH (Rate Pred Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_predfluc_draw");
1436 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1437 const std::vector<std::unique_ptr<TH1>>& PostPred_w,
1438 const std::vector<TDirectory*>& SampleDir) {
1440 MACH3LOG_INFO(
"{:<55} {:<10} {:<10} {:<10}",
"Sample",
"DataInt",
"MCInt",
"-2LLH");
1441 MACH3LOG_INFO(
"{:-<55} {:-<10} {:-<10} {:-<10}",
"",
"",
"",
"");
1443 SampleDir[iSample]->cd();
1444 ExtractLLH(Data_histogram[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(),
SampleInfo[iSample].SamHandler);
1445 PostPred_mc[iSample]->Write();
1452 const std::string& Chi2_x_title,
1453 const std::vector<std::vector<double>>& Chi2_y,
1454 const std::string& Chi2_y_title,
1455 const std::vector<TDirectory*>& SampleDir,
1456 const std::string Title) {
1459 SampleDir[iSample]->cd();
1462 std::vector<double> chi2_y_sample(
Ntoys);
1463 std::vector<double> chi2_x_per_sample(
Ntoys);
1465 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1466 chi2_y_sample[iToy] = Chi2_y[iSample][iToy];
1467 chi2_x_per_sample[iToy] = Chi2_x[iSample][iToy];
1470 const double min_val = std::min(*std::min_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1471 *std::min_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1472 const double max_val = std::max(*std::max_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1473 *std::max_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1475 auto chi2_hist = std::make_unique<TH2D>((
SampleInfo[iSample].Name+ Title).c_str(),
1477 50, min_val, max_val, 50, min_val, max_val);
1478 chi2_hist->SetDirectory(
nullptr);
1479 chi2_hist->GetXaxis()->SetTitle(Chi2_x_title.c_str());
1480 chi2_hist->GetYaxis()->SetTitle(Chi2_y_title.c_str());
1482 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1483 chi2_hist->Fill(chi2_x_per_sample[iToy], chi2_y_sample[iToy]);
1495 bool StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__ );
1496 if (StudyBeta ==
false)
return;
1499 TDirectory* BetaDir = PredictiveDir->mkdir(
"BetaParameters");
1505 DirBeta[sample] = BetaDir->mkdir(
SampleInfo[sample].Name.c_str());
1510 const int nDims =
SampleInfo[iSample].Dimenstion;
1512 TH1* RefHist =
Data_Hist[iSample].get();
1513 BetaHist[iSample] =
PerBinHistogram(RefHist, iSample, nDims,
"Beta_Parameter");
1515 for (
size_t i = 0; i < BetaHist[iSample].size(); ++i) {
1516 BetaHist[iSample][i]->GetXaxis()->SetTitle(
"beta parameter");
1522 #pragma omp parallel for
1525 const int nDims =
SampleInfo[iSample].Dimenstion;
1526 const auto likelihood =
SampleInfo[iSample].SamHandler->GetTestStatistic();
1527 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1529 if(std::string(
Data_Hist[iSample]->ClassName()) ==
"TH2Poly") {
1530 for (
int i = 1; i <= static_cast<TH2Poly*>(
Data_Hist[iSample].get())->GetNumberOfBins(); ++i) {
1531 const double Data =
Data_Hist[iSample]->GetBinContent(i);
1532 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1533 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1539 const int nX =
Data_Hist[iSample]->GetNbinsX();
1540 const int nY =
Data_Hist[iSample]->GetNbinsY();
1541 for (
int iy = 1; iy <= nY; ++iy) {
1542 for (
int ix = 1; ix <= nX; ++ix) {
1543 const int FlatBin = (iy-1) * nX + (ix-1);
1545 const double Data =
Data_Hist[iSample]->GetBinContent(ix, iy);
1546 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1547 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1550 BetaHist[iSample][FlatBin]->Fill(BetaParam,
ReweightWeight[iToy]);
1555 int nbinsx =
Data_Hist[iSample]->GetNbinsX();
1556 for (
int ix = 1; ix <= nbinsx; ++ix) {
1558 const double Data =
Data_Hist[iSample]->GetBinContent(ix);
1559 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1560 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1571 for (
size_t iBin = 0; iBin < BetaHist[iSample].size(); iBin++) {
1572 DirBeta[iSample]->cd();
1573 BetaHist[iSample][iBin]->Write();
1575 DirBeta[iSample]->Close();
1576 delete DirBeta[iSample];
1581 PredictiveDir->cd();
1587 const std::vector<std::vector<std::unique_ptr<TH1>>>& Toys,
1588 const bool DebugHistograms)
const {
1593 TDirectory *CorrDir = PredictiveDir->mkdir(
"Correlations");
1599 #pragma omp parallel for
1603 for (
const auto& toyHist : Toys[i])
1605 const double val = toyHist->Integral();
1606 if (val < minVals[i]) minVals[i] = val;
1607 if (val > maxVals[i]) maxVals[i] = val;
1610 auto hSamCorr = std::make_unique<TH2D>(
"Sample Correlation",
"Sample Correlation",
TotalNumberOfSamples, 0,
1612 hSamCorr->SetDirectory(
nullptr);
1613 hSamCorr->GetZaxis()->SetTitle(
"Correlation");
1614 hSamCorr->SetMinimum(-1);
1615 hSamCorr->SetMaximum(1);
1616 hSamCorr->GetXaxis()->SetLabelSize(0.015);
1617 hSamCorr->GetYaxis()->SetLabelSize(0.015);
1620 hSamCorr->SetBinContent(i+1, i+1, 1.0);
1621 hSamCorr->GetXaxis()->SetBinLabel(i+1,
SampleInfo[i].Name.c_str());
1623 hSamCorr->GetYaxis()->SetBinLabel(j+1,
SampleInfo[j].Name.c_str());
1631 const double Min_i = minVals[i];
1632 const double Max_i = maxVals[i];
1635 const double Min_j = minVals[j];
1636 const double Max_j = maxVals[j];
1638 std::string name =
"SamCorr_" + std::to_string(i) +
"_" + std::to_string(j);
1639 SamCorr[i][j] = std::make_unique<TH2D>(name.c_str(), name.c_str(), 70, Min_i, Max_i, 70, Min_j, Max_j);
1640 SamCorr[i][j]->SetDirectory(
nullptr);
1641 SamCorr[i][j]->SetMinimum(0);
1642 SamCorr[i][j]->GetXaxis()->SetTitle(
SampleInfo[i].Name.c_str());
1643 SamCorr[i][j]->GetYaxis()->SetTitle(
SampleInfo[j].Name.c_str());
1644 SamCorr[i][j]->GetZaxis()->SetTitle(
"Events");
1650 #pragma omp parallel for
1654 for (
int j = 0; j <= i; ++j)
1657 if (j == i)
continue;
1659 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1661 SamCorr[i][j]->Fill(Toys[i][iToy]->Integral(), Toys[j][iToy]->Integral());
1663 SamCorr[i][j]->Smooth();
1666 const double corr = SamCorr[i][j]->GetCorrelationFactor();
1667 hSamCorr->SetBinContent(i+1, j+1, corr);
1668 hSamCorr->SetBinContent(j+1, i+1, corr);
1672 hSamCorr->Draw(
"colz");
1673 hSamCorr->Write(
"Sample_Corr");
1675 if(DebugHistograms) {
1677 for (
int j = 0; j <= i; ++j) {
1679 if (j == i)
continue;
1680 SamCorr[i][j]->Write();
1685 PredictiveDir->cd();
1692 const double llh =
CalcLLH(DatHist, MCHist, W2Hist, SampleHandler);
1693 std::stringstream ss;
1694 ss <<
"_2LLH=" << llh;
1695 MCHist->SetTitle((std::string(MCHist->GetTitle())+ss.str()).c_str());
1696 MACH3LOG_INFO(
"{:<55} {:<10.2f} {:<10.2f} {:<10.2f}", MCHist->GetName(), DatHist->Integral(), MCHist->Integral(), llh);
1704 int originalErrorWarning = gErrorIgnoreLevel;
1705 gErrorIgnoreLevel = kFatal;
1708 auto TempLine = std::make_unique<TLine>(DataRate, Histogram->GetMinimum(), DataRate, Histogram->GetMaximum());
1709 TempLine->SetLineColor(kRed);
1710 TempLine->SetLineWidth(2);
1712 auto Fitter = std::make_unique<TF1>(
"Fit",
"gaus", Histogram->GetBinLowEdge(1), Histogram->GetBinLowEdge(Histogram->GetNbinsX()+1));
1713 Histogram->Fit(Fitter.get(),
"RQ");
1714 Fitter->SetLineColor(kRed-5);
1717 for (
int z = 0; z < Histogram->GetNbinsX(); ++z) {
1718 const double xvalue = Histogram->GetBinCenter(z+1);
1719 if (xvalue >= DataRate) {
1720 Above += Histogram->GetBinContent(z+1);
1723 const double pvalue = Above/Histogram->Integral();
1724 TLegend Legend(0.4, 0.75, 0.98, 0.90);
1725 Legend.SetFillColor(0);
1726 Legend.SetFillStyle(0);
1727 Legend.SetLineWidth(0);
1728 Legend.SetLineColor(0);
1729 Legend.AddEntry(TempLine.get(), Form(
"Data, %.0f, p-value=%.2f", DataRate, pvalue),
"l");
1730 Legend.AddEntry(Histogram, Form(
"MC, #mu=%.1f#pm%.1f", Histogram->GetMean(), Histogram->GetRMS()),
"l");
1731 Legend.AddEntry(Fitter.get(), Form(
"Gauss, #mu=%.1f#pm%.1f", Fitter->GetParameter(1), Fitter->GetParameter(2)),
"l");
1732 std::string TempTitle = std::string(Histogram->GetName());
1733 TempTitle +=
"_canv";
1734 TCanvas TempCanvas(TempTitle.c_str(), TempTitle.c_str(), 1024, 1024);
1735 TempCanvas.SetGridx();
1736 TempCanvas.SetGridy();
1737 TempCanvas.SetRightMargin(0.03);
1738 TempCanvas.SetBottomMargin(0.08);
1739 TempCanvas.SetLeftMargin(0.10);
1740 TempCanvas.SetTopMargin(0.06);
1743 TempLine->Draw(
"same");
1744 Fitter->Draw(
"same");
1745 Legend.Draw(
"same");
1748 gErrorIgnoreLevel = originalErrorWarning;
1753 const std::vector<TDirectory*>& SampleDirectories)
const {
1757 std::string Title =
"EventHist: ";
1766 EventHist[iSample] = std::make_unique<TH1D>(Title.c_str(), Title.c_str(), 100, 1, -1);
1767 EventHist[iSample]->SetDirectory(
nullptr);
1768 EventHist[iSample]->GetXaxis()->SetTitle(
"Total event rate");
1769 EventHist[iSample]->GetYaxis()->SetTitle(
"Counts");
1770 EventHist[iSample]->SetLineWidth(2);
1775 #pragma omp parallel for
1778 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1779 double Count = Toys[iSample][iToy]->Integral();
1780 EventHist[iSample]->Fill(Count);
1785 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1786 double TotalCount = 0.0;
1788 TotalCount += Toys[iSample][iToy]->Integral();
1793 double DataRate = 0.0;
1796 #pragma omp parallel for reduction(+:DataRate)
1799 DataRates[i] =
Data_Hist[i]->Integral();
1800 DataRate += DataRates[i];
1805 SampleDirectories[SampleNum]->cd();
1814 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1815 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1844 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1847 double DataRate = 0.0;
1848 double BinsRate = 0.0;
1849 double TotalLLH = 0.0;
1851 #pragma omp parallel for reduction(+:DataRate, BinsRate, TotalLLH)
1855 auto SampleHandler =
SampleInfo[i].SamHandler;
1857 DataRate += h->Integral();
1858 if (
auto h1 =
dynamic_cast<TH1D*
>(h)) {
1859 BinsRate += h1->GetNbinsX();
1860 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(h)) {
1861 BinsRate += h2->GetNbinsX() * h2->GetNbinsY();
1862 }
else if (
auto h2poly =
dynamic_cast<TH2Poly*
>(h)) {
1863 BinsRate += h2poly->GetNumberOfBins();
1867 TotalLLH +=
CalcLLH(
Data_Hist[i].get(), PostPred_mc[i].get(), PostPred_w[i].get(), SampleHandler);
1872 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of events: {:.2f}", EventRateBIC);
1873 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of bins: {:.2f}", BinBasedBIC);
1874 MACH3LOG_INFO(
"Additional info: NModelParams: {}, DataRate: {:.2f}, BinsRate: {:.2f}",
NModelParams, DataRate, BinsRate);
1880 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1884 double TotalLLH = 0.0;
1887 #pragma omp parallel for reduction(+:Dbar)
1891 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1892 TotalLLH +=
CalcLLH(
Data_Hist[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(), SampleHandler);
1893 double LLH_temp = 0.;
1894 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1900 Dbar = Dbar /
Ntoys;
1903 const double Dhat = TotalLLH;
1906 const double p_D = std::fabs(Dbar - Dhat);
1909 const double DIC_stat = Dhat + 2 * p_D;
1910 MACH3LOG_INFO(
"Effective number of parameters following DIC formalism is equal to: {:.2f}", p_D);
1919 double& mean_llh_squared,
1920 double& sum_exp_llh) {
1923 double LLH_temp = -neg_LLH_temp;
1925 mean_llh += LLH_temp;
1926 mean_llh_squared += LLH_temp * LLH_temp;
1927 sum_exp_llh += std::exp(LLH_temp);
1933 const unsigned int Ntoys,
double& lppd,
double& p_WAIC) {
1937 mean_llh_squared /= Ntoys;
1938 sum_exp_llh /= Ntoys;
1939 sum_exp_llh = std::log(sum_exp_llh);
1942 lppd += sum_exp_llh;
1945 p_WAIC += mean_llh_squared - (mean_llh * mean_llh);
1958 #pragma omp parallel for reduction(+:lppd, p_WAIC)
1961 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1964 if (
auto h2poly =
dynamic_cast<TH2Poly*
>(hData)) {
1966 for (
int i = 1; i <= h2poly->GetNumberOfBins(); ++i) {
1967 const double data =
Data_Hist[iSample]->GetBinContent(i);
1968 double mean_llh = 0.;
1969 double sum_exp_llh = 0;
1970 double mean_llh_squared = 0.;
1972 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1973 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1974 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1976 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1981 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(hData)) {
1983 for (
int ix = 1; ix <= h2->GetNbinsX(); ++ix) {
1984 for (
int iy = 1; iy <= h2->GetNbinsY(); ++iy) {
1985 const double data = hData->GetBinContent(ix, iy);
1986 double mean_llh = 0.;
1987 double mean_llh_squared = 0.;
1988 double sum_exp_llh = 0.;
1989 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1990 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1991 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1993 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1999 }
else if (
auto h1 =
dynamic_cast<TH1D*
>(hData)) {
2001 for (
int iBin = 1; iBin <= h1->GetNbinsX(); ++iBin) {
2002 const double data = hData->GetBinContent(iBin);
2003 double mean_llh = 0.;
2004 double mean_llh_squared = 0.;
2005 double sum_exp_llh = 0.;
2006 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
2007 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
2008 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
2011 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
2020 double WAIC = -2 * (lppd - p_WAIC);
2021 MACH3LOG_INFO(
"Effective number of parameters following WAIC formalism is equal to: {:.2f}", p_WAIC);
void MakeFluctuatedHistogramAlternative(TH1D *FluctHist, TH1D *PolyHist, TRandom3 *rand)
Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check.
void MakeFluctuatedHistogramStandard(TH1D *FluctHist, TH1D *PolyHist, TRandom3 *rand)
Make Poisson fluctuation of TH1D hist using default fast method.
TH1D * PolyProjectionX(TObject *poly, const std::string &TempName, const std::vector< double > &xbins, const bool computeErrors)
WP: Poly Projectors.
void FastViolinFill(TH2D *violin, TH1D *hist_1d)
KS: Fill Violin histogram with entry from a toy.
TH1D * PolyProjectionY(TObject *poly, const std::string &TempName, const std::vector< double > &ybins, const bool computeErrors)
WP: Poly Projectors.
std::unique_ptr< TH1D > MakeSummaryFromSpectra(const TH2D *Spectra, const std::string &name)
Build a 1D posterior-predictive summary from a violin spectrum.
void AccumulateWAICToy(const double neg_LLH_temp, double &mean_llh, double &mean_llh_squared, double &sum_exp_llh)
bool CheckBounds(const std::vector< const M3::float_t * > &BoundValuePointer, const std::vector< std::pair< double, double >> &ParamBounds)
void AccumulateWAICBin(double &mean_llh, double &mean_llh_squared, double &sum_exp_llh, const unsigned int Ntoys, double &lppd, double &p_WAIC)
double GetBetaParameter(const double data, const double mc, const double w2, const TestStatistic TestStat)
KS: Calculate Beta parameter which will be different based on specified test statistic.
double GetBIC(const double llh, const int data, const int nPars)
Get the Bayesian Information Criterion (BIC) or Schwarz information criterion (also SIC,...
void Get2DBayesianpValue(TH2D *Histogram)
Calculates the 2D Bayesian p-value and generates a visualization.
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.
Base class for implementing fitting algorithms.
std::string GetName() const
Get name of class.
std::unique_ptr< TRandom3 > random
Random number.
TFile * outputFile
Output.
std::string AlgorithmName
Name of fitting algorithm that is being used.
std::vector< SampleHandlerInterface * > samples
Sample holder.
Manager * fitMan
The manager for configuration handling.
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,...
void Initialise()
Scan chain, what parameters we have and load information from covariance matrices.
YAML::Node GetCovConfig(const int i) const
Get Yaml config obtained from a Chain.
Custom exception class used throughout MaCh3.
The manager class is responsible for managing configurations and settings.
YAML::Node const & raw() const
Return config.
Base class for handling systematic uncertainty parameters.
int GetNumParams() const
Get total number of parameters.
void SetParProp(const int i, const double val)
Set proposed parameter value.
int GetParIndex(const std::string &name) const
Get index based on name.
std::string GetName() const
Get name of covariance.
double GetParPreFit(const int i) const
Get prior parameter value.
YAML::Node GetConfig() const
Getter to return a copy of the YAML node.
Class responsible for handling of systematic error parameters with different types defined in the con...
std::vector< std::string > GetUniqueParameterGroups() const
KS: Get names of all unique parameter groups.
void SetGroupOnlyParameters(const std::string &Group, const std::vector< double > &Pars={})
KS Function to set to prior parameters of a given group or values from vector.
std::vector< double > PenaltyTerm
Penalty term values for each toy by default 0.
virtual ~PredictiveThrower()
Destructor.
void ExtractLLH(TH1 *DatHist, TH1 *MCHist, TH1 *W2Hist, const SampleHandlerInterface *SampleHandler) const
Calculate the LLH for TH1, set the LLH to title of MCHist.
bool FullLLH
KS: Use Full LLH or only sample contribution based on discussion with Asher we almost always only wan...
void WriteToy(TDirectory *ToyDirectory, TDirectory *Toy_1DDirectory, TDirectory *Toy_2DDirectory, const int iToy)
Save histograms for a single MCMC Throw/Toy.
void StudyCorrelations(TDirectory *PredictiveDir, const std::vector< std::vector< std::unique_ptr< TH1 >>> &Toys, const bool DebugHistograms) const
Study Prior/Posterior correlations between samples etc.
void RunPredictiveAnalysis()
Main routine responsible for producing posterior predictive distributions and $p$-value.
bool LoadToys()
Load existing toys.
void PosteriorPredictivepValue(const std::vector< std::unique_ptr< TH1 >> &PostPred_mc, const std::vector< TDirectory * > &SampleDir)
Calculate Posterior Predictive $p$-value Compares observed data to toy datasets generated from:
void WriteByModeToys(TDirectory *ByModeDirectory, const int iToy)
Save mode histograms for a single MCMC Throw/Toy.
void StudyBIC(const std::vector< std::unique_ptr< TH1 >> &PostPred_mc, const std::vector< std::unique_ptr< TH1 >> &PostPred_w)
Study Bayesian Information Criterion (BIC) The BIC is defined as:
void SetupToyGeneration(std::vector< std::string > &ParameterGroupsNotVaried, std::unordered_set< int > &ParameterOnlyToVary, std::vector< const M3::float_t * > &BoundValuePointer, std::vector< std::pair< double, double >> &ParamBounds)
Setup useful variables etc before stating toy generation.
std::string GetBinName(TH1 *hist, const bool uniform, const int Dim, const std::vector< int > &bins) const
Construct a human-readable label describing a specific analysis bin.
std::vector< std::string > GetStoredFancyName(ParameterHandlerBase *Systematics) const
Get Fancy parameters stored in mcmc chains for passed ParameterHandler.
std::vector< std::unique_ptr< TH1 > > W2_Nom_Hist
Vector of W2 histograms.
std::vector< std::vector< std::unique_ptr< TH1 > > > W2_Hist_Toy
bool Is_PriorPredictive
Whether it is Prior or Posterior predictive.
int NModelParams
KS: Count total number of model parameters which can be used for stuff like BIC.
void MakeCutEventRate(TH1D *Histogram, const double DataRate) const
Make the 1D Event Rate Hist.
void StudyInformationCriterion(M3::kInfCrit Criterion, const std::vector< std::unique_ptr< TH1 >> &PostPred_mc, const std::vector< std::unique_ptr< TH1 >> &PostPred_w)
Information Criterion.
int Ntoys
Number of toys we are generating analysing.
void StudyByMode1DProjections(const std::vector< TDirectory * > &SampleDirectories) const
Load 1D projections by mode and produce post pred for each.
void PredictiveLLH(const std::vector< std::unique_ptr< TH1 >> &Data_histogram, const std::vector< std::unique_ptr< TH1 >> &PostPred_mc, const std::vector< std::unique_ptr< TH1 >> &PostPred_w, const std::vector< TDirectory * > &SampleDir)
Calculate Posterior Predictive LLH.
void RateAnalysis(const std::vector< std::vector< std::unique_ptr< TH1 >>> &Toys, const std::vector< TDirectory * > &SampleDirectories) const
Produce distribution of number of events for each sample.
void MakeChi2Plots(const std::vector< std::vector< double >> &Chi2_x, const std::string &Chi2_x_title, const std::vector< std::vector< double >> &Chi2_y, const std::string &Chi2_y_title, const std::vector< TDirectory * > &SampleDir, const std::string Title)
Produce Chi2 plot for a single sample based on which $p$-value is calculated.
void SetParamters(std::vector< std::string > &ParameterGroupsNotVaried, std::unordered_set< int > &ParameterOnlyToVary)
This set some params to prior value this way you can evaluate errors from subset of errors.
void StudyWAIC()
KS: Get the Watanabe-Akaike information criterion (WAIC)
void Study1DProjections(const std::vector< TDirectory * > &SampleDirectories) const
Load 1D projections and later produce violin plots for each.
void SetupSampleInformation()
Setup sample information.
std::vector< std::unique_ptr< TH1 > > MC_Nom_Hist
Vector of MC histograms.
int TotalNumberOfSamples
Number of toys we are generating analysing.
void ProduceToys()
Produce toys by throwing from MCMC.
void StudyBetaParameters(TDirectory *PredictiveDir)
Evaluate prior/post predictive distribution for beta parameters (used for evaluating impact MC statis...
double CalcLLH(const double data, const double mc, const double w2, const SampleHandlerInterface *SampleHandler) const
Calculates the -2LLH (likelihood) for a single sample.
std::vector< std::unique_ptr< TH1 > > Data_Hist
Vector of Data histograms.
bool StandardFluctuation
KS: We have two methods for Poissonian fluctuation.
ParameterHandlerGeneric * ModelSystematic
Pointer to El Generico.
std::vector< double > ReweightWeight
Reweighting factors applied for each toy, by default 1.
std::vector< std::unique_ptr< TH1 > > MakePredictive(const std::vector< std::vector< std::unique_ptr< TH1 >>> &Toys, const std::vector< TDirectory * > &Director, const std::string &suffix, const bool DebugHistograms, const bool WriteHist)
Produce posterior predictive distribution.
PredictiveThrower(Manager *const fitMan)
Constructor.
void MakeFluctuatedHistogram(TH1 *FluctHist, TH1 *PolyHist)
Make Poisson fluctuation of TH1D hist.
std::vector< std::vector< std::unique_ptr< TH1 > > > MC_Hist_Toy
void StudyDIC(const std::vector< std::unique_ptr< TH1 >> &PostPred_mc, const std::vector< std::unique_ptr< TH1 >> &PostPred_w)
KS: Get the Deviance Information Criterion (DIC) The deviance is defined as:
double GetLLH(const TH1D *DatHist, const TH1D *MCHist, const TH1D *W2Hist, const SampleHandlerInterface *SampleHandler) const
Helper functions to calculate likelihoods using TH1D.
void ProduceSpectra(const std::vector< std::vector< std::vector< std::unique_ptr< TH1D >>>> &Toys, const std::vector< TDirectory * > &Director, const std::string suffix, const bool DoSummary=true) const
Produce Violin style spectra.
std::vector< std::unique_ptr< TH1D > > PerBinHistogram(TH1 *hist, const int SampleId, const int Dim, const std::string &suffix) const
Create per-bin posterior histograms for a given sample.
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
double GetTestStatLLH(const double data, const double mc, const double w2) const
Calculate test statistic for a single bin. Calculation depends on setting of fTestStatistic....
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.
kInfCrit
KS: Different Information Criterion tests mostly based Gelman paper.
@ kWAIC
Watanabe-Akaike information criterion.
@ kInfCrits
This only enumerates.
@ kBIC
Bayesian Information Criterion.
@ kDIC
Deviance Information Criterion.
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.
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.
constexpr static const int _BAD_INT_
Default value used for int initialisation.
KS: Store info about MC sample.