8 #pragma GCC diagnostic ignored "-Wfloat-conversion"
9 #pragma GCC diagnostic ignored "-Wuseless-cast"
23 else MACH3LOG_INFO(
"Using alternative method of statistical fluctuation, which is much slower");
27 FullLLH = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"FullLLH"],
false, __FILE__, __LINE__ );
31 Ntoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);
34 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
35 auto outfile = Get<std::string>(
fitMan->
raw()[
"General"][
"OutputFile"], __FILE__ , __LINE__);
36 if(PosteriorFileName == outfile){
37 MACH3LOG_ERROR(
"Output file ({}) and posterior files ({}) have same name", outfile, PosteriorFileName);
54 std::unordered_set<int>& ParameterOnlyToVary) {
57 auto DoNotThrowLegacyCov = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"DoNotThrowLegacyCov"], {}, __FILE__, __LINE__);
59 for (
size_t i = 0; i < DoNotThrowLegacyCov.size(); ++i) {
77 if (ParameterOnlyToVary.find(i) == ParameterOnlyToVary.end()) {
88 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
106 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
107 for (
int SampleIndex = 0; SampleIndex <
samples[iPDF]->GetNSamples(); ++SampleIndex) {
121 std::unordered_set<int>& ParameterOnlyToVary,
122 std::vector<const M3::float_t*>& BoundValuePointer,
123 std::vector<std::pair<double, double>>& ParamBounds) {
137 MACH3LOG_INFO(
"You've chosen to run Prior Predictive Distribution");
139 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
145 auto AllowDifferentConfigs = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"AllowDifferentConfigs"],
false, __FILE__, __LINE__);
153 if(AllowDifferentConfigs){
154 MACH3LOG_WARN(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
156 MACH3LOG_ERROR(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
163 MACH3LOG_ERROR(
"Found {} ParmaterHandler inheriting from ParameterHandlerGeneric, I can accept at most 1", counter);
172 auto ThrowParamGroupOnly = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowParamGroupOnly"], {}, __FILE__, __LINE__);
174 auto ParameterOnlyToVaryString = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowSingleParams"], {}, __FILE__, __LINE__);
176 if (!ThrowParamGroupOnly.empty() && !ParameterOnlyToVaryString.empty()) {
177 MACH3LOG_ERROR(
"Can't use ThrowParamGroupOnly and ThrowSingleParams at the same time");
181 if (!ParameterOnlyToVaryString.empty()) {
183 std::vector<int> ParameterVary(ParameterOnlyToVaryString.size());
185 for (
size_t i = 0; i < ParameterOnlyToVaryString.size(); ++i) {
188 MACH3LOG_ERROR(
"Can't proceed if param {} is missing", ParameterOnlyToVaryString[i]);
192 ParameterOnlyToVary = std::unordered_set<int>(ParameterVary.begin(), ParameterVary.end());
195 if (ThrowParamGroupOnly.empty()) {
198 std::unordered_set<std::string> throwOnlySet(ThrowParamGroupOnly.begin(), ThrowParamGroupOnly.end());
199 ParameterGroupsNotVaried.clear();
201 for (
const auto& group : UniqueParamGroup) {
202 if (throwOnlySet.find(group) == throwOnlySet.end()) {
203 ParameterGroupsNotVaried.push_back(group);
213 auto paramNode =
fitMan->
raw()[
"Predictive"][
"ParameterBounds"];
214 for (
const auto& p : paramNode) {
216 std::string name = p[0].as<std::string>();
219 double minVal = p[1][0].as<
double>();
220 double maxVal = p[1][1].as<
double>();
221 ParamBounds.emplace_back(minVal, maxVal);
224 for(
int iPar = 0; iPar <
systematics[s]->GetNParameters(); iPar++){
226 BoundValuePointer.push_back(
systematics[s]->RetPointer(iPar));
231 if(ParamBounds.size() != BoundValuePointer.size()){
235 MACH3LOG_INFO(
"Parameter: {} with : [{}, {}]", name, minVal, maxVal);
238 MACH3LOG_ERROR(
"Additional bounds not supported by prior predictive right now");
247 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
249 int originalErrorWarning = gErrorIgnoreLevel;
250 gErrorIgnoreLevel = kFatal;
251 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
253 gErrorIgnoreLevel = originalErrorWarning;
254 TDirectory* ToyDir =
nullptr;
255 if (!file || file->IsZombie()) {
259 if ((ToyDir = file->GetDirectory(
"Toys"))) {
260 MACH3LOG_INFO(
"Found toys in Posterior file will attempt toy reading");
269 TTree* PenaltyTree =
static_cast<TTree*
>(file->Get(
"ToySummary"));
277 Ntoys =
static_cast<int>(PenaltyTree->GetEntries());
278 int ConfigNtoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);;
279 if (
Ntoys != ConfigNtoys) {
280 MACH3LOG_WARN(
"Found different number of toys in saved file than asked to run!");
289 double Penalty = 0, Weight = 1;
290 PenaltyTree->SetBranchAddress(
"Penalty", &Penalty);
291 PenaltyTree->SetBranchAddress(
"Weight", &Weight);
292 PenaltyTree->SetBranchAddress(
"NModelParams", &
NModelParams);
294 for (
int i = 0; i <
Ntoys; ++i) {
295 PenaltyTree->GetEntry(i);
308 TH1* DataHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_data").c_str()));
311 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc").c_str()));
314 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2").c_str()));
319 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
324 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc_" + std::to_string(iToy)).c_str()));
325 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2_" + std::to_string(iToy)).c_str()));
340 TDirectory * ogdir = gDirectory;
342 std::vector<std::string> FancyNames;
343 std::string Name = std::string(
"Config_") + Systematics->
GetName();
344 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
346 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
347 TDirectory* CovarianceFolder = file->GetDirectory(
"CovarianceFolder");
349 TMacro* FoundMacro =
static_cast<TMacro*
>(CovarianceFolder->Get(Name.c_str()));
350 if(FoundMacro ==
nullptr) {
353 if(ogdir){ ogdir->cd(); }
360 int params = int(Settings[
"Systematics"].size());
361 FancyNames.resize(params);
363 for (
auto const ¶m : Settings[
"Systematics"]) {
364 FancyNames[iPar] = Get<std::string>(param[
"Systematic"][
"Names"][
"FancyName"], __FILE__ , __LINE__);
369 if(ogdir){ ogdir->cd(); }
376 TDirectory* Toy_1DDirectory,
377 TDirectory* Toy_2DDirectory,
380 int SampleCounter = 0;
381 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
383 auto* SampleHandler =
samples[iPDF];
384 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
388 auto SampleName = SampleHandler->GetSampleTitle(iSample);
389 const TH1* MCHist = SampleHandler->GetMCHist(iSample);
390 MC_Hist_Toy[SampleCounter][iToy] =
M3::Clone(MCHist, SampleName +
"_mc_" + std::to_string(iToy));
393 const TH1* W2Hist = SampleHandler->GetW2Hist(iSample);
394 W2_Hist_Toy[SampleCounter][iToy] =
M3::Clone(W2Hist, SampleName +
"_w2_" + std::to_string(iToy));
398 Toy_1DDirectory->cd();
399 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
400 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
401 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
403 auto hist = SampleHandler->Get1DVarHist(iSample, ProjectionName);
404 hist->SetTitle((SampleName + ProjectionSuffix).c_str());
405 hist->SetName((SampleName + ProjectionSuffix).c_str());
409 Toy_2DDirectory->cd();
411 for(
int iDim1 = 0; iDim1 < SampleHandler->GetNDim(iSample); iDim1++) {
412 for (
int iDim2 = iDim1 + 1; iDim2 < SampleHandler->GetNDim(iSample); ++iDim2) {
414 std::string XVarName = SampleHandler->GetKinVarName(iSample, iDim1);
415 std::string YVarName = SampleHandler->GetKinVarName(iSample, iDim2);
418 auto hist2D = SampleHandler->Get2DVarHist(iSample, XVarName, YVarName);
421 std::string suffix2D =
"_2DProj_" + std::to_string(iDim1) +
"_vs_" + std::to_string(iDim2) +
"_" + std::to_string(iToy);
422 hist2D->SetTitle((SampleName + suffix2D).c_str());
423 hist2D->SetName((SampleName + suffix2D).c_str());
436 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
438 auto* SampleHandler =
samples[iPDF];
439 auto* modes = SampleHandler->GetMaCh3Modes();
440 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
442 ByModeDirectory->cd();
444 auto SampleName = SampleHandler->GetSampleTitle(iSample);
445 for (
int iMode = 0; iMode < modes->GetNModes()+1; ++iMode) {
446 auto ModeName = modes->GetMaCh3ModeName(iMode);
447 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
448 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
449 std::string PlotSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + ModeName +
"_" + std::to_string(iToy);
451 auto hist = SampleHandler->Get1DVarHistByModeAndChannel(iSample, ProjectionName, iMode);
452 hist->SetTitle((SampleName + PlotSuffix).c_str());
453 hist->SetName((SampleName + PlotSuffix).c_str());
462 bool CheckBounds(
const std::vector<const M3::float_t*>& BoundValuePointer,
463 const std::vector<std::pair<double,double>>& ParamBounds) {
465 for (
size_t i = 0; i < BoundValuePointer.size(); ++i) {
466 const double val = *(BoundValuePointer[i]);
467 const double minVal = ParamBounds[i].first;
468 const double maxVal = ParamBounds[i].second;
470 if (val < minVal || val > maxVal)
484 std::vector<std::string> ParameterGroupsNotVaried;
486 std::unordered_set<int> ParameterOnlyToVary;
488 std::vector<const M3::float_t*> BoundValuePointer;
489 std::vector<std::pair<double, double>> ParamBounds;
493 BoundValuePointer, ParamBounds);
495 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
500 double Penalty = 0, Weight = 1.;
503 TTree *ToyTree =
new TTree(
"ToySummary",
"ToySummary");
504 ToyTree->Branch(
"Penalty", &Penalty,
"Penalty/D");
505 ToyTree->Branch(
"Weight", &Weight,
"Weight/D");
506 ToyTree->Branch(
"Draw", &Draw,
"Draw/I");
507 ToyTree->Branch(
"NModelParams", &
NModelParams,
"NModelParams/I");
511 std::vector<const M3::float_t*> ParampPointers(
NModelParams);
512 int ParamCounter = 0;
513 for (
size_t iSys = 0; iSys <
systematics.size(); iSys++)
515 for (
int iPar = 0; iPar <
systematics[iSys]->GetNumParams(); iPar++)
517 ParampPointers[ParamCounter] =
systematics[iSys]->RetPointer(iPar);
518 std::string Name =
systematics[iSys]->GetParFancyName(iPar);
520 while (Name.find(
"-") != std::string::npos) {
521 Name.replace(Name.find(
"-"), 1, std::string(
"_"));
523 ToyTree->Branch(Name.c_str(), &ParamValues[ParamCounter], (Name +
"/D").c_str());
527 TDirectory* ToyDirectory =
outputFile->mkdir(
"Toys");
529 int SampleCounter = 0;
530 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
532 auto* MaCh3Sample =
samples[iPDF];
533 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNSamples(); ++SampleIndex)
536 const TH1* DataHist = MaCh3Sample->GetDataHist(SampleIndex);
537 Data_Hist[SampleCounter] =
M3::Clone(DataHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data");
538 Data_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data").c_str());
540 const TH1* MCHist = MaCh3Sample->GetMCHist(SampleIndex);
541 MC_Nom_Hist[SampleCounter] =
M3::Clone(MCHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc");
542 MC_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc").c_str());
544 const TH1* W2Hist = MaCh3Sample->GetW2Hist(SampleIndex);
545 W2_Nom_Hist[SampleCounter] =
M3::Clone(W2Hist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2");
546 W2_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2").c_str());
551 TDirectory* Toy_1DDirectory =
outputFile->mkdir(
"Toys_1DHistVar");
552 TDirectory* Toy_2DDirectory =
outputFile->mkdir(
"Toys_2DHistVar");
553 auto doByMode = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"ByMode"],
false, __FILE__, __LINE__);
554 TDirectory* ByModeDirectory =
nullptr;
555 if(doByMode) ByModeDirectory =
outputFile->mkdir(
"Toys_ByMode");
556 auto ReweightNames = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ReweightNames"],
557 {
"Weight"}, __FILE__, __LINE__);
558 bool doReweight =
false;
559 std::vector<double> reweight_weight(ReweightNames.size(), 1.0);
562 std::vector<std::vector<double>> branch_vals(
systematics.size());
563 std::vector<std::vector<std::string>> branch_name(
systematics.size());
565 TChain* PosteriorFile =
nullptr;
566 unsigned int burn_in = 0;
567 unsigned int maxNsteps = 0;
568 unsigned int Step = 0;
571 PosteriorFile =
new TChain(
"posteriors");
572 PosteriorFile->Add(PosteriorFileName.c_str());
574 PosteriorFile->SetBranchAddress(
"step", &Step);
576 for (
size_t i = 0; i < ReweightNames.size(); ++i) {
577 const auto& name = ReweightNames[i];
578 if (PosteriorFile->GetBranch(name.c_str())) {
579 PosteriorFile->SetBranchStatus(name.c_str(),
true);
580 PosteriorFile->SetBranchAddress(name.c_str(), &reweight_weight[i]);
582 MACH3LOG_WARN(
"Missing reweight branch '{}' -> disabling ALL reweighting", name);
589 systematics[s]->MatchMaCh3OutputBranches(PosteriorFile, branch_vals[s], branch_name[s], fancy_names);
593 burn_in = Get<unsigned int>(
fitMan->
raw()[
"Predictive"][
"BurnInSteps"], __FILE__, __LINE__);
596 maxNsteps =
static_cast<unsigned int>(PosteriorFile->GetMaximum(
"step"));
597 if(burn_in >= maxNsteps)
599 MACH3LOG_ERROR(
"You are running on a chain shorter than burn in cut");
600 MACH3LOG_ERROR(
"Maximal value of nSteps: {}, burn in cut {}", maxNsteps, burn_in);
607 TStopwatch TempClock;
609 for(
int i = 0; i <
Ntoys; i++)
618 bool WithinBounds =
false;
623 while(Step < burn_in || !WithinBounds) {
625 PosteriorFile->GetEntry(entry);
628 if(BoundValuePointer.size() > 0) {
633 WithinBounds =
CheckBounds(BoundValuePointer, ParamBounds);
649 SetParamters(ParameterGroupsNotVaried, ParameterOnlyToVary);
662 for (
size_t iWeight = 0; iWeight < reweight_weight.size(); ++iWeight) {
663 Weight *= reweight_weight[iWeight];
668 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
672 WriteToy(ToyDirectory, Toy_1DDirectory, Toy_2DDirectory, i);
676 for (
size_t iPar = 0; iPar < ParamValues.size(); iPar++) {
677 ParamValues[iPar] = *ParampPointers[iPar];
684 if(PosteriorFile)
delete PosteriorFile;
685 ToyDirectory->Close();
delete ToyDirectory;
686 Toy_1DDirectory->Close();
delete Toy_1DDirectory;
687 Toy_2DDirectory->Close();
delete Toy_2DDirectory;
689 ByModeDirectory->Close();
690 delete ByModeDirectory;
694 ToyTree->Write();
delete ToyTree;
696 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
704 TDirectory * ogdir = gDirectory;
705 TDirectory* ToyDir =
nullptr;
707 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
709 int originalErrorWarning = gErrorIgnoreLevel;
710 gErrorIgnoreLevel = kFatal;
711 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
712 gErrorIgnoreLevel = originalErrorWarning;
714 if (file ==
nullptr || file->IsZombie()) {
715 ToyDir =
outputFile->GetDirectory(
"Toys_1DHistVar");
717 ToyDir = file->GetDirectory(
"Toys_1DHistVar");
719 if(ToyDir ==
nullptr) {
720 ToyDir =
outputFile->GetDirectory(
"Toys_1DHistVar");
725 std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>> ProjectionToys(
TotalNumberOfSamples);
727 ProjectionToys[sample].resize(
Ntoys);
728 const int nDims =
SampleInfo[sample].Dimenstion;
729 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
730 ProjectionToys[sample][iToy].resize(nDims);
734 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
735 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
737 const int nDims =
SampleInfo[sample].Dimenstion;
738 for(
int iDim = 0; iDim < nDims; iDim ++){
739 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
740 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
741 ProjectionToys[sample][iToy][iDim] =
M3::Clone(MCHist1D);
745 if(file) { file->Close();
delete file; }
746 if(ogdir){ ogdir->cd(); }
750 const int nDims =
SampleInfo[sample].Dimenstion;
754 SampleDirectories[sample]->cd();
756 std::string nameX =
"Data_" +
SampleInfo[sample].Name +
"_Dim0";
757 std::string nameY =
"Data_" +
SampleInfo[sample].Name +
"_Dim1";
759 if(std::string(hist->ClassName()) ==
"TH2Poly") {
760 TAxis* xax = ProjectionToys[sample][0][0]->GetXaxis();
761 TAxis* yax = ProjectionToys[sample][0][1]->GetXaxis();
763 std::vector<double> XBinning(xax->GetNbins()+1);
764 std::vector<double> YBinning(yax->GetNbins()+1);
766 for(
int i=0;i<=xax->GetNbins();++i)
767 XBinning[i] = xax->GetBinLowEdge(i+1);
769 for(
int i=0;i<=yax->GetNbins();++i)
770 YBinning[i] = yax->GetBinLowEdge(i+1);
772 TH1D* ProjectionX =
PolyProjectionX(
static_cast<TH2Poly*
>(hist), nameX.c_str(), XBinning,
false);
773 TH1D* ProjectionY =
PolyProjectionY(
static_cast<TH2Poly*
>(hist), nameY.c_str(), YBinning,
false);
777 ProjectionX->GetXaxis()->SetTitle(x_var.c_str());
778 ProjectionY->GetXaxis()->SetTitle(y_var.c_str());
780 ProjectionX->SetDirectory(
nullptr);
781 ProjectionY->SetDirectory(
nullptr);
783 ProjectionX->Write(nameX.c_str());
784 ProjectionY->Write(nameY.c_str());
789 TH1D* ProjectionX =
static_cast<TH2D*
>(hist)->ProjectionX(nameX.c_str());
790 TH1D* ProjectionY =
static_cast<TH2D*
>(hist)->ProjectionY(nameY.c_str());
792 ProjectionX->SetDirectory(
nullptr);
793 ProjectionY->SetDirectory(
nullptr);
795 ProjectionX->Write(nameX.c_str());
796 ProjectionY->Write(nameY.c_str());
809 TDirectory* ogdir = gDirectory;
810 TDirectory* ToyDir =
nullptr;
812 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
814 int originalErrorWarning = gErrorIgnoreLevel;
815 gErrorIgnoreLevel = kFatal;
816 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
817 gErrorIgnoreLevel = originalErrorWarning;
819 if (file ==
nullptr || file->IsZombie()) {
820 ToyDir =
outputFile->GetDirectory(
"Toys_ByMode");
822 ToyDir = file->GetDirectory(
"Toys_ByMode");
824 if(ToyDir ==
nullptr) {
825 ToyDir =
outputFile->GetDirectory(
"Toys_ByMode");
832 auto* mode =
SampleInfo[0].SamHandler->GetMaCh3Modes();
833 auto NModes = mode->GetNModes()+1;
835 std::vector<std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>>> ProjectionToys(NModes);
836 for(
int iMode = 0; iMode < NModes; iMode++) {
839 ProjectionToys[iMode][sample].resize(
Ntoys);
840 const int nDims =
SampleInfo[sample].Dimenstion;
841 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
842 ProjectionToys[iMode][sample][iToy].resize(nDims);
847 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
848 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
849 for(
int iMode = 0; iMode < NModes; iMode++) {
850 auto ModeName = mode->GetMaCh3ModeName(iMode);
852 const int nDims =
SampleInfo[sample].Dimenstion;
853 for(
int iDim = 0; iDim < nDims; iDim ++) {
854 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + ModeName +
"_" + std::to_string(iToy);
855 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
856 ProjectionToys[iMode][sample][iToy][iDim] =
M3::Clone(MCHist1D);
865 ModeDirectory[iSample] = SampleDirectories[iSample]->mkdir(
"ByMode");
868 for(
int iMode = 0; iMode < NModes; iMode++) {
869 auto ModeName = mode->GetMaCh3ModeName(iMode);
870 ProduceSpectra(ProjectionToys[iMode], ModeDirectory, ModeName,
false);
873 ModeDirectory[iSample]->Close();
874 delete ModeDirectory[iSample];
876 if(file){file->Close();
delete file;}
877 if(ogdir){ ogdir->cd(); }
882 const std::vector<TDirectory*>& SampleDirectories,
883 const std::string suffix,
884 const bool DoSummary)
const {
890 const int nDims =
SampleInfo[sample].Dimenstion;
891 MaxValue[sample].assign(nDims, 0);
896 #pragma omp parallel for
899 for (
int toy = 0; toy <
Ntoys; ++toy) {
900 const int nDims =
SampleInfo[sample].Dimenstion;
901 for (
int dim = 0; dim < nDims; dim++) {
902 double max_val = Toys[sample][toy][dim]->GetMaximum();
903 MaxValue[sample][dim] = std::max(MaxValue[sample][dim], max_val);
912 const int nDims =
SampleInfo[sample].Dimenstion;
913 Spectra[sample].resize(nDims);
914 for (
int dim = 0; dim < nDims; dim++) {
916 TH1D* refHist = Toys[sample][0][dim].get();
918 const int n_bins_x = refHist->GetNbinsX();
919 std::vector<double> x_bin_edges(n_bins_x + 1);
920 for (
int b = 0; b < n_bins_x; ++b) {
921 x_bin_edges[b] = refHist->GetXaxis()->GetBinLowEdge(b + 1);
923 x_bin_edges[n_bins_x] = refHist->GetXaxis()->GetBinUpEdge(n_bins_x);
925 constexpr
int n_bins_y = 400;
926 constexpr
double y_min = 0.0;
927 const double y_max = MaxValue[sample][dim] * 1.05;
930 Spectra[sample][dim] = std::make_unique<TH2D>(
931 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
932 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
933 n_bins_x, x_bin_edges.data(),
934 n_bins_y, y_min, y_max
937 Spectra[sample][dim]->GetXaxis()->SetTitle(refHist->GetXaxis()->GetTitle());
938 Spectra[sample][dim]->GetYaxis()->SetTitle(
"Events");
940 Spectra[sample][dim]->SetDirectory(
nullptr);
941 Spectra[sample][dim]->Sumw2(
true);
947 #pragma omp parallel for collapse(2)
950 for (
int toy = 0; toy <
Ntoys; ++toy) {
951 const int nDims =
SampleInfo[sample].Dimenstion;
952 for (
int dim = 0; dim < nDims; dim++) {
953 FastViolinFill(Spectra[sample][dim].get(), Toys[sample][toy][dim].get());
960 SampleDirectories[sample]->cd();
961 const int nDims =
SampleInfo[sample].Dimenstion;
962 for (
long unsigned int dim = 0; dim < Spectra[sample].size(); dim++) {
963 Spectra[sample][dim]->Write();
965 if(nDims == 2 && DoSummary) {
966 const std::string name =
SampleInfo[sample].Name +
"_" + suffix+
"_PostPred_dim" + std::to_string(dim);
978 const std::vector<int>& bins)
const {
980 std::string BinName =
"";
982 const int b = bins[0];
983 const TAxis* ax = hist->GetXaxis();
984 const double low = ax->GetBinLowEdge(b);
985 const double up = ax->GetBinUpEdge(b);
987 BinName = fmt::format(
"Dim0 ({:g}, {:g})", low, up);
988 }
else if (Dim == 2) {
989 if(uniform ==
true) {
990 const int bx = bins[0];
991 const int by = bins[1];
992 const TAxis* ax = hist->GetXaxis();
993 const TAxis* ay = hist->GetYaxis();
994 BinName = fmt::format(
"Dim0 ({:g}, {:g}), ", ax->GetBinLowEdge(bx), ax->GetBinUpEdge(bx));
995 BinName += fmt::format(
"Dim1 ({:g}, {:g})", ay->GetBinLowEdge(by), ay->GetBinUpEdge(by));
997 TH2PolyBin* bin =
static_cast<TH2PolyBin*
>(
static_cast<TH2Poly*
>(hist)->GetBins()->At(bins[0]-1));
999 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 0, bin->GetXMin(), bin->GetXMax());
1000 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 1, bin->GetYMin(), bin->GetYMax());
1003 BinName = hist->GetXaxis()->GetBinLabel(bins[0]);
1012 const std::string& suffix)
const {
1014 std::vector<std::unique_ptr<TH1D>> PosteriorHistVec;
1015 constexpr
int nBins = 100;
1016 const std::string Sample_Name =
SampleInfo[SampleId].Name;
1018 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1019 for (
int i = 1; i <= static_cast<TH2Poly*>(hist)->GetNumberOfBins(); ++i) {
1020 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1021 Sample_Name, suffix,
1025 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1026 PosteriorHist->SetDirectory(
nullptr);
1027 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1028 PosteriorHistVec.push_back(std::move(PosteriorHist));
1031 int nbinsx = hist->GetNbinsX();
1032 int nbinsy = hist->GetNbinsY();
1033 for (
int iy = 1; iy <= nbinsy; ++iy) {
1034 for (
int ix = 1; ix <= nbinsx; ++ix) {
1035 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1036 Sample_Name, suffix,
1040 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1041 PosteriorHist->SetDirectory(
nullptr);
1042 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1043 PosteriorHistVec.push_back(std::move(PosteriorHist));
1048 int nbinsx = hist->GetNbinsX();
1049 PosteriorHistVec.reserve(nbinsx);
1050 for (
int i = 1; i <= nbinsx; ++i) {
1051 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1052 Sample_Name, suffix,
1056 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1057 PosteriorHist->SetDirectory(
nullptr);
1058 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1059 PosteriorHistVec.push_back(std::move(PosteriorHist));
1062 return PosteriorHistVec;
1067 const std::vector<TDirectory*>& Directory,
1068 const std::string& suffix,
1069 const bool DebugHistograms,
1070 const bool WriteHist) {
1076 const int nDims =
SampleInfo[sample].Dimenstion;
1077 const std::string Sample_Name =
SampleInfo[sample].Name;
1078 Posterior_hist[sample] =
PerBinHistogram(Toys[sample][0].get(), sample, nDims, suffix);
1079 auto PredictiveHist =
M3::Clone(Toys[sample][0].get());
1081 PredictiveHist->Reset();
1082 PredictiveHist->SetName((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
1083 PredictiveHist->SetTitle((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
1084 PredictiveHist->SetDirectory(
nullptr);
1085 PostPred[sample] = std::move(PredictiveHist);
1090 #pragma omp parallel for
1093 const int nDims =
SampleInfo[sample].Dimenstion;
1094 auto& hist = Toys[sample][0];
1095 for (
size_t iToy = 0; iToy < Toys[sample].size(); ++iToy) {
1097 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1098 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
1099 double content = Toys[sample][iToy]->GetBinContent(i);
1100 Posterior_hist[sample][i-1]->Fill(content,
ReweightWeight[iToy]);
1103 int nbinsx = hist->GetNbinsX();
1104 int nbinsy = hist->GetNbinsY();
1105 for (
int iy = 1; iy <= nbinsy; ++iy) {
1106 for (
int ix = 1; ix <= nbinsx; ++ix) {
1107 int Bin = (iy-1) * nbinsx + (ix-1);
1108 double content = Toys[sample][iToy]->GetBinContent(ix, iy);
1109 Posterior_hist[sample][Bin]->Fill(content,
ReweightWeight[iToy]);
1114 int nbinsx = hist->GetNbinsX();
1115 for (
int i = 1; i <= nbinsx; ++i) {
1116 double content = Toys[sample][iToy]->GetBinContent(i);
1117 Posterior_hist[sample][i-1]->Fill(content,
ReweightWeight[iToy]);
1125 const int nDims =
SampleInfo[sample].Dimenstion;
1126 auto& hist = Toys[sample][0];
1127 Directory[sample]->cd();
1129 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1130 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
1131 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1133 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1134 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1137 int nbinsx = hist->GetNbinsX();
1138 int nbinsy = hist->GetNbinsY();
1139 for (
int iy = 1; iy <= nbinsy; ++iy) {
1140 for (
int ix = 1; ix <= nbinsx; ++ix) {
1141 int Bin = (iy-1) * nbinsx + (ix-1);
1142 if (DebugHistograms) Posterior_hist[sample][Bin]->Write();
1143 PostPred[sample]->SetBinContent(ix, iy, Posterior_hist[sample][Bin]->GetMean());
1144 PostPred[sample]->SetBinError(ix, iy, Posterior_hist[sample][Bin]->GetRMS());
1149 int nbinsx = hist->GetNbinsX();
1150 for (
int i = 1; i <= nbinsx; ++i) {
1151 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1152 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1153 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1156 if(WriteHist) PostPred[sample]->Write();
1172 TStopwatch TempClock;
1175 auto DebugHistograms = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"DebugHistograms"],
false, __FILE__, __LINE__);
1176 auto doByMode = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"ByMode"],
false, __FILE__, __LINE__);
1178 TDirectory* PredictiveDir =
outputFile->mkdir(
"Predictive");
1179 std::vector<TDirectory*> SampleDirectories;
1184 SampleDirectories[sample] = PredictiveDir->mkdir(
SampleInfo[sample].Name.c_str());
1204 SampleDirectories[sample]->Close();
1205 delete SampleDirectories[sample];
1208 auto StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__);
1209 auto StudyInfoCriterion = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyInformationCriterion"],
true, __FILE__, __LINE__);
1210 auto StudyCorr = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyCorrelations"],
true, __FILE__, __LINE__);
1219 PredictiveDir->Close();
1220 delete PredictiveDir;
1225 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
1246 if (
auto h1 =
dynamic_cast<const TH1D*
>(DatHist)) {
1248 static_cast<const TH1D*
>(MCHist),
1249 static_cast<const TH1D*
>(W2Hist),
1254 if (
auto h2 =
dynamic_cast<const TH2D*
>(DatHist)) {
1256 static_cast<const TH2D*
>(MCHist),
1257 static_cast<const TH2D*
>(W2Hist),
1262 if (
auto h2p =
dynamic_cast<const TH2Poly*
>(DatHist)) {
1264 static_cast<const TH2Poly*
>(MCHist),
1265 static_cast<const TH2Poly*
>(W2Hist),
1280 for (
int i = 1; i <= DatHist->GetXaxis()->GetNbins(); ++i)
1282 const double data = DatHist->GetBinContent(i);
1283 const double mc = MCHist->GetBinContent(i);
1284 const double w2 = W2Hist->GetBinContent(i);
1293 const TH2Poly* MCHist,
1294 const TH2Poly* W2Hist,
1298 for (
int i = 1; i <= DatHist->GetNumberOfBins(); ++i)
1300 const double data = DatHist->GetBinContent(i);
1301 const double mc = MCHist->GetBinContent(i);
1302 const double w2 = W2Hist->GetBinContent(i);
1317 const int nBinsX = DatHist->GetXaxis()->GetNbins();
1318 const int nBinsY = DatHist->GetYaxis()->GetNbins();
1320 for (
int i = 1; i <= nBinsX; ++i)
1322 for (
int j = 1; j <= nBinsY; ++j)
1324 const double data = DatHist->GetBinContent(i, j);
1325 const double mc = MCHist->GetBinContent(i, j);
1326 const double w2 = W2Hist->GetBinContent(i, j);
1341 auto applyFluctuation = [&](
auto* f,
auto* h) {
1349 if (Hist->InheritsFrom(TH2Poly::Class())) {
1350 applyFluctuation(
static_cast<TH2Poly*
>(FluctHist),
static_cast<TH2Poly*
>(Hist));
1352 else if (Hist->InheritsFrom(TH2D::Class())) {
1353 applyFluctuation(
static_cast<TH2D*
>(FluctHist),
static_cast<TH2D*
>(Hist));
1355 else if (Hist->InheritsFrom(TH1D::Class())) {
1356 applyFluctuation(
static_cast<TH1D*
>(FluctHist),
static_cast<TH1D*
>(Hist));
1366 const std::vector<TDirectory*>& SampleDir) {
1370 auto make_matrix = [&](
double init = 0.0) {
1371 return std::vector<std::vector<double>>(
1373 std::vector<double>(
Ntoys, init));
1375 auto chi2_dat = make_matrix();
1376 auto chi2_mc = make_matrix();
1377 auto chi2_pred = make_matrix();
1378 auto chi2_rate_dat = make_matrix();
1379 auto chi2_rate_mc = make_matrix();
1380 auto chi2_rate_pred = make_matrix();
1383 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1395 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1396 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1399 auto PredFluctHist =
M3::Clone(PostPred_mc[iSample].get());
1412 chi2_rate_mc[iSample][iToy] =
CalcLLH(DrawFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1413 chi2_rate_pred[iSample][iToy] =
CalcLLH(PredFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1428 MakeChi2Plots(chi2_mc,
"-2LLH (Draw Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_drawfluc_draw");
1429 MakeChi2Plots(chi2_pred,
"-2LLH (Pred Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_predfluc_draw");
1432 MakeChi2Plots(chi2_rate_mc,
"-2LLH (Rate Draw Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_drawfluc_draw");
1433 MakeChi2Plots(chi2_rate_pred,
"-2LLH (Rate Pred Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_predfluc_draw");
1438 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1439 const std::vector<std::unique_ptr<TH1>>& PostPred_w,
1440 const std::vector<TDirectory*>& SampleDir) {
1442 MACH3LOG_INFO(
"{:<55} {:<10} {:<10} {:<10}",
"Sample",
"DataInt",
"MCInt",
"-2LLH");
1443 MACH3LOG_INFO(
"{:-<55} {:-<10} {:-<10} {:-<10}",
"",
"",
"",
"");
1445 SampleDir[iSample]->cd();
1446 ExtractLLH(Data_histogram[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(),
SampleInfo[iSample].SamHandler);
1447 PostPred_mc[iSample]->Write();
1454 const std::string& Chi2_x_title,
1455 const std::vector<std::vector<double>>& Chi2_y,
1456 const std::string& Chi2_y_title,
1457 const std::vector<TDirectory*>& SampleDir,
1458 const std::string Title) {
1461 SampleDir[iSample]->cd();
1464 std::vector<double> chi2_y_sample(
Ntoys);
1465 std::vector<double> chi2_x_per_sample(
Ntoys);
1467 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1468 chi2_y_sample[iToy] = Chi2_y[iSample][iToy];
1469 chi2_x_per_sample[iToy] = Chi2_x[iSample][iToy];
1472 const double min_val = std::min(*std::min_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1473 *std::min_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1474 const double max_val = std::max(*std::max_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1475 *std::max_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1477 auto chi2_hist = std::make_unique<TH2D>((
SampleInfo[iSample].Name+ Title).c_str(),
1479 50, min_val, max_val, 50, min_val, max_val);
1480 chi2_hist->SetDirectory(
nullptr);
1481 chi2_hist->GetXaxis()->SetTitle(Chi2_x_title.c_str());
1482 chi2_hist->GetYaxis()->SetTitle(Chi2_y_title.c_str());
1484 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1485 chi2_hist->Fill(chi2_x_per_sample[iToy], chi2_y_sample[iToy]);
1497 bool StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__ );
1498 if (StudyBeta ==
false)
return;
1501 TDirectory* BetaDir = PredictiveDir->mkdir(
"BetaParameters");
1507 DirBeta[sample] = BetaDir->mkdir(
SampleInfo[sample].Name.c_str());
1512 const int nDims =
SampleInfo[iSample].Dimenstion;
1514 TH1* RefHist =
Data_Hist[iSample].get();
1515 BetaHist[iSample] =
PerBinHistogram(RefHist, iSample, nDims,
"Beta_Parameter");
1517 for (
size_t i = 0; i < BetaHist[iSample].size(); ++i) {
1518 BetaHist[iSample][i]->GetXaxis()->SetTitle(
"beta parameter");
1524 #pragma omp parallel for
1527 const int nDims =
SampleInfo[iSample].Dimenstion;
1528 const auto likelihood =
SampleInfo[iSample].SamHandler->GetTestStatistic();
1529 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1531 if(std::string(
Data_Hist[iSample]->ClassName()) ==
"TH2Poly") {
1532 for (
int i = 1; i <= static_cast<TH2Poly*>(
Data_Hist[iSample].get())->GetNumberOfBins(); ++i) {
1533 const double Data =
Data_Hist[iSample]->GetBinContent(i);
1534 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1535 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1541 const int nX =
Data_Hist[iSample]->GetNbinsX();
1542 const int nY =
Data_Hist[iSample]->GetNbinsY();
1543 for (
int iy = 1; iy <= nY; ++iy) {
1544 for (
int ix = 1; ix <= nX; ++ix) {
1545 const int FlatBin = (iy-1) * nX + (ix-1);
1547 const double Data =
Data_Hist[iSample]->GetBinContent(ix, iy);
1548 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1549 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1552 BetaHist[iSample][FlatBin]->Fill(BetaParam,
ReweightWeight[iToy]);
1557 int nbinsx =
Data_Hist[iSample]->GetNbinsX();
1558 for (
int ix = 1; ix <= nbinsx; ++ix) {
1560 const double Data =
Data_Hist[iSample]->GetBinContent(ix);
1561 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1562 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1573 for (
size_t iBin = 0; iBin < BetaHist[iSample].size(); iBin++) {
1574 DirBeta[iSample]->cd();
1575 BetaHist[iSample][iBin]->Write();
1577 DirBeta[iSample]->Close();
1578 delete DirBeta[iSample];
1583 PredictiveDir->cd();
1589 const std::vector<std::vector<std::unique_ptr<TH1>>>& Toys,
1590 const bool DebugHistograms)
const {
1595 TDirectory *CorrDir = PredictiveDir->mkdir(
"Correlations");
1601 #pragma omp parallel for
1605 for (
const auto& toyHist : Toys[i])
1607 const double val = toyHist->Integral();
1608 if (val < minVals[i]) minVals[i] = val;
1609 if (val > maxVals[i]) maxVals[i] = val;
1612 auto hSamCorr = std::make_unique<TH2D>(
"Sample Correlation",
"Sample Correlation",
TotalNumberOfSamples, 0,
1614 hSamCorr->SetDirectory(
nullptr);
1615 hSamCorr->GetZaxis()->SetTitle(
"Correlation");
1616 hSamCorr->SetMinimum(-1);
1617 hSamCorr->SetMaximum(1);
1618 hSamCorr->GetXaxis()->SetLabelSize(0.015);
1619 hSamCorr->GetYaxis()->SetLabelSize(0.015);
1622 hSamCorr->SetBinContent(i+1, i+1, 1.0);
1623 hSamCorr->GetXaxis()->SetBinLabel(i+1,
SampleInfo[i].Name.c_str());
1625 hSamCorr->GetYaxis()->SetBinLabel(j+1,
SampleInfo[j].Name.c_str());
1633 const double Min_i = minVals[i];
1634 const double Max_i = maxVals[i];
1637 const double Min_j = minVals[j];
1638 const double Max_j = maxVals[j];
1640 std::string name =
"SamCorr_" + std::to_string(i) +
"_" + std::to_string(j);
1641 SamCorr[i][j] = std::make_unique<TH2D>(name.c_str(), name.c_str(), 70, Min_i, Max_i, 70, Min_j, Max_j);
1642 SamCorr[i][j]->SetDirectory(
nullptr);
1643 SamCorr[i][j]->SetMinimum(0);
1644 SamCorr[i][j]->GetXaxis()->SetTitle(
SampleInfo[i].Name.c_str());
1645 SamCorr[i][j]->GetYaxis()->SetTitle(
SampleInfo[j].Name.c_str());
1646 SamCorr[i][j]->GetZaxis()->SetTitle(
"Events");
1652 #pragma omp parallel for
1656 for (
int j = 0; j <= i; ++j)
1659 if (j == i)
continue;
1661 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1663 SamCorr[i][j]->Fill(Toys[i][iToy]->Integral(), Toys[j][iToy]->Integral());
1665 SamCorr[i][j]->Smooth();
1668 const double corr = SamCorr[i][j]->GetCorrelationFactor();
1669 hSamCorr->SetBinContent(i+1, j+1, corr);
1670 hSamCorr->SetBinContent(j+1, i+1, corr);
1674 hSamCorr->Draw(
"colz");
1675 hSamCorr->Write(
"Sample_Corr");
1677 if(DebugHistograms) {
1679 for (
int j = 0; j <= i; ++j) {
1681 if (j == i)
continue;
1682 SamCorr[i][j]->Write();
1687 PredictiveDir->cd();
1694 const double llh =
CalcLLH(DatHist, MCHist, W2Hist, SampleHandler);
1695 std::stringstream ss;
1696 ss <<
"_2LLH=" << llh;
1697 MCHist->SetTitle((std::string(MCHist->GetTitle())+ss.str()).c_str());
1698 MACH3LOG_INFO(
"{:<55} {:<10.2f} {:<10.2f} {:<10.2f}", MCHist->GetName(), DatHist->Integral(), MCHist->Integral(), llh);
1706 int originalErrorWarning = gErrorIgnoreLevel;
1707 gErrorIgnoreLevel = kFatal;
1710 auto TempLine = std::make_unique<TLine>(DataRate, Histogram->GetMinimum(), DataRate, Histogram->GetMaximum());
1711 TempLine->SetLineColor(kRed);
1712 TempLine->SetLineWidth(2);
1714 auto Fitter = std::make_unique<TF1>(
"Fit",
"gaus", Histogram->GetBinLowEdge(1), Histogram->GetBinLowEdge(Histogram->GetNbinsX()+1));
1715 Histogram->Fit(Fitter.get(),
"RQ");
1716 Fitter->SetLineColor(kRed-5);
1719 for (
int z = 0; z < Histogram->GetNbinsX(); ++z) {
1720 const double xvalue = Histogram->GetBinCenter(z+1);
1721 if (xvalue >= DataRate) {
1722 Above += Histogram->GetBinContent(z+1);
1725 const double pvalue = Above/Histogram->Integral();
1726 TLegend Legend(0.4, 0.75, 0.98, 0.90);
1727 Legend.SetFillColor(0);
1728 Legend.SetFillStyle(0);
1729 Legend.SetLineWidth(0);
1730 Legend.SetLineColor(0);
1731 Legend.AddEntry(TempLine.get(), Form(
"Data, %.0f, p-value=%.2f", DataRate, pvalue),
"l");
1732 Legend.AddEntry(Histogram, Form(
"MC, #mu=%.1f#pm%.1f", Histogram->GetMean(), Histogram->GetRMS()),
"l");
1733 Legend.AddEntry(Fitter.get(), Form(
"Gauss, #mu=%.1f#pm%.1f", Fitter->GetParameter(1), Fitter->GetParameter(2)),
"l");
1734 std::string TempTitle = std::string(Histogram->GetName());
1735 TempTitle +=
"_canv";
1736 TCanvas TempCanvas(TempTitle.c_str(), TempTitle.c_str(), 1024, 1024);
1737 TempCanvas.SetGridx();
1738 TempCanvas.SetGridy();
1739 TempCanvas.SetRightMargin(0.03);
1740 TempCanvas.SetBottomMargin(0.08);
1741 TempCanvas.SetLeftMargin(0.10);
1742 TempCanvas.SetTopMargin(0.06);
1745 TempLine->Draw(
"same");
1746 Fitter->Draw(
"same");
1747 Legend.Draw(
"same");
1750 gErrorIgnoreLevel = originalErrorWarning;
1755 const std::vector<TDirectory*>& SampleDirectories)
const {
1759 std::string Title =
"EventHist: ";
1768 EventHist[iSample] = std::make_unique<TH1D>(Title.c_str(), Title.c_str(), 100, 1, -1);
1769 EventHist[iSample]->SetDirectory(
nullptr);
1770 EventHist[iSample]->GetXaxis()->SetTitle(
"Total event rate");
1771 EventHist[iSample]->GetYaxis()->SetTitle(
"Counts");
1772 EventHist[iSample]->SetLineWidth(2);
1777 #pragma omp parallel for
1780 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1781 double Count = Toys[iSample][iToy]->Integral();
1782 EventHist[iSample]->Fill(Count);
1787 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1788 double TotalCount = 0.0;
1790 TotalCount += Toys[iSample][iToy]->Integral();
1795 double DataRate = 0.0;
1798 #pragma omp parallel for reduction(+:DataRate)
1801 DataRates[i] =
Data_Hist[i]->Integral();
1802 DataRate += DataRates[i];
1807 SampleDirectories[SampleNum]->cd();
1816 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1817 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1846 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1849 double DataRate = 0.0;
1850 double BinsRate = 0.0;
1851 double TotalLLH = 0.0;
1853 #pragma omp parallel for reduction(+:DataRate, BinsRate, TotalLLH)
1857 auto SampleHandler =
SampleInfo[i].SamHandler;
1859 DataRate += h->Integral();
1860 if (
auto h1 =
dynamic_cast<TH1D*
>(h)) {
1861 BinsRate += h1->GetNbinsX();
1862 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(h)) {
1863 BinsRate += h2->GetNbinsX() * h2->GetNbinsY();
1864 }
else if (
auto h2poly =
dynamic_cast<TH2Poly*
>(h)) {
1865 BinsRate += h2poly->GetNumberOfBins();
1869 TotalLLH +=
CalcLLH(
Data_Hist[i].get(), PostPred_mc[i].get(), PostPred_w[i].get(), SampleHandler);
1874 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of events: {:.2f}", EventRateBIC);
1875 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of bins: {:.2f}", BinBasedBIC);
1876 MACH3LOG_INFO(
"Additional info: NModelParams: {}, DataRate: {:.2f}, BinsRate: {:.2f}",
NModelParams, DataRate, BinsRate);
1882 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1886 double TotalLLH = 0.0;
1889 #pragma omp parallel for reduction(+:Dbar)
1893 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1894 TotalLLH +=
CalcLLH(
Data_Hist[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(), SampleHandler);
1895 double LLH_temp = 0.;
1896 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1902 Dbar = Dbar /
Ntoys;
1905 const double Dhat = TotalLLH;
1908 const double p_D = std::fabs(Dbar - Dhat);
1911 const double DIC_stat = Dhat + 2 * p_D;
1912 MACH3LOG_INFO(
"Effective number of parameters following DIC formalism is equal to: {:.2f}", p_D);
1921 double& mean_llh_squared,
1922 double& sum_exp_llh) {
1925 double LLH_temp = -neg_LLH_temp;
1927 mean_llh += LLH_temp;
1928 mean_llh_squared += LLH_temp * LLH_temp;
1929 sum_exp_llh += std::exp(LLH_temp);
1935 const unsigned int Ntoys,
double& lppd,
double& p_WAIC) {
1939 mean_llh_squared /= Ntoys;
1940 sum_exp_llh /= Ntoys;
1941 sum_exp_llh = std::log(sum_exp_llh);
1944 lppd += sum_exp_llh;
1947 p_WAIC += mean_llh_squared - (mean_llh * mean_llh);
1960 #pragma omp parallel for reduction(+:lppd, p_WAIC)
1963 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1966 if (
auto h2poly =
dynamic_cast<TH2Poly*
>(hData)) {
1968 for (
int i = 1; i <= h2poly->GetNumberOfBins(); ++i) {
1969 const double data =
Data_Hist[iSample]->GetBinContent(i);
1970 double mean_llh = 0.;
1971 double sum_exp_llh = 0;
1972 double mean_llh_squared = 0.;
1974 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1975 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1976 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1978 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1983 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(hData)) {
1985 for (
int ix = 1; ix <= h2->GetNbinsX(); ++ix) {
1986 for (
int iy = 1; iy <= h2->GetNbinsY(); ++iy) {
1987 const double data = hData->GetBinContent(ix, iy);
1988 double mean_llh = 0.;
1989 double mean_llh_squared = 0.;
1990 double sum_exp_llh = 0.;
1991 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1992 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1993 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1995 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
2001 }
else if (
auto h1 =
dynamic_cast<TH1D*
>(hData)) {
2003 for (
int iBin = 1; iBin <= h1->GetNbinsX(); ++iBin) {
2004 const double data = hData->GetBinContent(iBin);
2005 double mean_llh = 0.;
2006 double mean_llh_squared = 0.;
2007 double sum_exp_llh = 0.;
2008 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
2009 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
2010 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
2013 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
2022 double WAIC = -2 * (lppd - p_WAIC);
2023 MACH3LOG_INFO(
"Effective number of parameters following WAIC formalism is equal to: {:.2f}", p_WAIC);
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
#define _MaCh3_Safe_Include_End_
void MakeFluctuatedHistogramStandard(TH1D *FluctHist, TH1D *PolyHist)
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 MakeFluctuatedHistogramAlternative(TH1D *FluctHist, TH1D *PolyHist)
Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check.
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.
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.
void MakeFluctuatedHistogram(TH1 *FluctHist, TH1 *Hist)
Make Poisson fluctuation of TH1D hist.
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.
PredictiveThrower(Manager *const fitMan)
Constructor.
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.
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.
std::string join(const Container &values, std::string_view separator=" ")
Join all values in a container into a single string.
int UniformInt(const int min, const int max)
Generate a uniform random integer in [min, max].
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.