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__);
43 std::unordered_set<int>& ParameterOnlyToVary) {
46 auto DoNotThrowLegacyCov = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"DoNotThrowLegacyCov"], {}, __FILE__, __LINE__);
48 for (
size_t i = 0; i < DoNotThrowLegacyCov.size(); ++i) {
66 if (ParameterOnlyToVary.find(i) == ParameterOnlyToVary.end()) {
77 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
95 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
96 for (
int SampleIndex = 0; SampleIndex <
samples[iPDF]->GetNSamples(); ++SampleIndex) {
110 std::unordered_set<int>& ParameterOnlyToVary,
111 std::vector<const M3::float_t*>& BoundValuePointer,
112 std::vector<std::pair<double, double>>& ParamBounds) {
126 MACH3LOG_INFO(
"You've chosen to run Prior Predictive Distribution");
128 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
134 auto AllowDifferentConfigs = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"AllowDifferentConfigs"],
false, __FILE__, __LINE__);
142 if(AllowDifferentConfigs){
143 MACH3LOG_WARN(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
145 MACH3LOG_ERROR(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
152 MACH3LOG_ERROR(
"Found {} ParmaterHandler inheriting from ParameterHandlerGeneric, I can accept at most 1", counter);
161 auto ThrowParamGroupOnly = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowParamGroupOnly"], {}, __FILE__, __LINE__);
163 auto ParameterOnlyToVaryString = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowSinlgeParams"], {}, __FILE__, __LINE__);
165 if (!ThrowParamGroupOnly.empty() && !ParameterOnlyToVaryString.empty()) {
166 MACH3LOG_ERROR(
"Can't use ThrowParamGroupOnly and ThrowSinlgeParams at the same time");
170 if (!ParameterOnlyToVaryString.empty()) {
171 MACH3LOG_INFO(
"I will throw only: {}", fmt::join(ParameterOnlyToVaryString,
", "));
172 std::vector<int> ParameterVary(ParameterOnlyToVaryString.size());
174 for (
size_t i = 0; i < ParameterOnlyToVaryString.size(); ++i) {
177 MACH3LOG_ERROR(
"Can't proceed if param {} is missing", ParameterOnlyToVaryString[i]);
181 ParameterOnlyToVary = std::unordered_set<int>(ParameterVary.begin(), ParameterVary.end());
183 MACH3LOG_INFO(
"I have following parameter groups: {}", fmt::join(UniqueParamGroup,
", "));
184 if (ThrowParamGroupOnly.empty()) {
187 std::unordered_set<std::string> throwOnlySet(ThrowParamGroupOnly.begin(), ThrowParamGroupOnly.end());
188 ParameterGroupsNotVaried.clear();
190 for (
const auto& group : UniqueParamGroup) {
191 if (throwOnlySet.find(group) == throwOnlySet.end()) {
192 ParameterGroupsNotVaried.push_back(group);
196 MACH3LOG_INFO(
"I will vary: {}", fmt::join(ThrowParamGroupOnly,
", "));
197 MACH3LOG_INFO(
"Exclude: {}", fmt::join(ParameterGroupsNotVaried,
", "));
202 auto paramNode =
fitMan->
raw()[
"Predictive"][
"ParameterBounds"];
203 for (
const auto& p : paramNode) {
205 std::string name = p[0].as<std::string>();
208 double minVal = p[1][0].as<
double>();
209 double maxVal = p[1][1].as<
double>();
210 ParamBounds.emplace_back(minVal, maxVal);
213 for(
int iPar = 0; iPar <
systematics[s]->GetNParameters(); iPar++){
215 BoundValuePointer.push_back(
systematics[s]->RetPointer(iPar));
220 if(ParamBounds.size() != BoundValuePointer.size()){
224 MACH3LOG_INFO(
"Parameter: {} with : [{}, {}]", name, minVal, maxVal);
227 MACH3LOG_ERROR(
"Additional bounds not supported by prior predictive right now");
236 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
238 int originalErrorWarning = gErrorIgnoreLevel;
239 gErrorIgnoreLevel = kFatal;
240 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
242 gErrorIgnoreLevel = originalErrorWarning;
243 TDirectory* ToyDir =
nullptr;
244 if (!file || file->IsZombie()) {
248 if ((ToyDir = file->GetDirectory(
"Toys"))) {
249 MACH3LOG_INFO(
"Found toys in Posterior file will attempt toy reading");
258 TTree* PenaltyTree =
static_cast<TTree*
>(file->Get(
"ToySummary"));
266 Ntoys =
static_cast<int>(PenaltyTree->GetEntries());
267 int ConfigNtoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);;
268 if (
Ntoys != ConfigNtoys) {
269 MACH3LOG_WARN(
"Found different number of toys in saved file than asked to run!");
278 double Penalty = 0, Weight = 1;
279 PenaltyTree->SetBranchAddress(
"Penalty", &Penalty);
280 PenaltyTree->SetBranchAddress(
"Weight", &Weight);
281 PenaltyTree->SetBranchAddress(
"NModelParams", &
NModelParams);
283 for (
int i = 0; i <
Ntoys; ++i) {
284 PenaltyTree->GetEntry(i);
297 TH1* DataHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_data").c_str()));
300 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc").c_str()));
303 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2").c_str()));
308 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
313 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc_" + std::to_string(iToy)).c_str()));
314 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2_" + std::to_string(iToy)).c_str()));
329 TDirectory * ogdir = gDirectory;
331 std::vector<std::string> FancyNames;
332 std::string Name = std::string(
"Config_") + Systematics->
GetName();
333 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
335 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
336 TDirectory* CovarianceFolder = file->GetDirectory(
"CovarianceFolder");
338 TMacro* FoundMacro =
static_cast<TMacro*
>(CovarianceFolder->Get(Name.c_str()));
339 if(FoundMacro ==
nullptr) {
342 if(ogdir){ ogdir->cd(); }
349 int params = int(Settings[
"Systematics"].size());
350 FancyNames.resize(params);
352 for (
auto const ¶m : Settings[
"Systematics"]) {
353 FancyNames[iPar] = Get<std::string>(param[
"Systematic"][
"Names"][
"FancyName"], __FILE__ , __LINE__);
358 if(ogdir){ ogdir->cd(); }
365 TDirectory* Toy_1DDirectory,
366 TDirectory* Toy_2DDirectory,
369 int SampleCounter = 0;
370 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
372 auto* SampleHandler =
samples[iPDF];
373 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
377 auto SampleName = SampleHandler->GetSampleTitle(iSample);
378 const TH1* MCHist = SampleHandler->GetMCHist(iSample);
379 MC_Hist_Toy[SampleCounter][iToy] =
M3::Clone(MCHist, SampleName +
"_mc_" + std::to_string(iToy));
382 const TH1* W2Hist = SampleHandler->GetW2Hist(iSample);
383 W2_Hist_Toy[SampleCounter][iToy] =
M3::Clone(W2Hist, SampleName +
"_w2_" + std::to_string(iToy));
387 Toy_1DDirectory->cd();
388 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
389 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
390 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
392 auto hist = SampleHandler->Get1DVarHist(iSample, ProjectionName);
393 hist->SetTitle((SampleName + ProjectionSuffix).c_str());
394 hist->SetName((SampleName + ProjectionSuffix).c_str());
398 Toy_2DDirectory->cd();
400 for(
int iDim1 = 0; iDim1 < SampleHandler->GetNDim(iSample); iDim1++) {
401 for (
int iDim2 = iDim1 + 1; iDim2 < SampleHandler->GetNDim(iSample); ++iDim2) {
403 std::string XVarName = SampleHandler->GetKinVarName(iSample, iDim1);
404 std::string YVarName = SampleHandler->GetKinVarName(iSample, iDim2);
407 auto hist2D = SampleHandler->Get2DVarHist(iSample, XVarName, YVarName);
410 std::string suffix2D =
"_2DProj_" + std::to_string(iDim1) +
"_vs_" + std::to_string(iDim2) +
"_" + std::to_string(iToy);
411 hist2D->SetTitle((SampleName + suffix2D).c_str());
412 hist2D->SetName((SampleName + suffix2D).c_str());
425 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
427 auto* SampleHandler =
samples[iPDF];
428 auto* modes = SampleHandler->GetMaCh3Modes();
429 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
431 ByModeDirectory->cd();
433 auto SampleName = SampleHandler->GetSampleTitle(iSample);
434 for (
int iMode = 0; iMode < modes->GetNModes()+1; ++iMode) {
435 auto ModeName = modes->GetMaCh3ModeName(iMode);
436 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
437 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
438 std::string PlotSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + ModeName +
"_" + std::to_string(iToy);
440 auto hist = SampleHandler->Get1DVarHistByModeAndChannel(iSample, ProjectionName, iMode);
441 hist->SetTitle((SampleName + PlotSuffix).c_str());
442 hist->SetName((SampleName + PlotSuffix).c_str());
451 bool CheckBounds(
const std::vector<const M3::float_t*>& BoundValuePointer,
452 const std::vector<std::pair<double,double>>& ParamBounds) {
454 for (
size_t i = 0; i < BoundValuePointer.size(); ++i) {
455 const double val = *(BoundValuePointer[i]);
456 const double minVal = ParamBounds[i].first;
457 const double maxVal = ParamBounds[i].second;
459 if (val < minVal || val > maxVal)
473 std::vector<std::string> ParameterGroupsNotVaried;
475 std::unordered_set<int> ParameterOnlyToVary;
477 std::vector<const M3::float_t*> BoundValuePointer;
478 std::vector<std::pair<double, double>> ParamBounds;
482 BoundValuePointer, ParamBounds);
484 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
489 double Penalty = 0, Weight = 1.;
492 TTree *ToyTree =
new TTree(
"ToySummary",
"ToySummary");
493 ToyTree->Branch(
"Penalty", &Penalty,
"Penalty/D");
494 ToyTree->Branch(
"Weight", &Weight,
"Weight/D");
495 ToyTree->Branch(
"Draw", &Draw,
"Draw/I");
496 ToyTree->Branch(
"NModelParams", &
NModelParams,
"NModelParams/I");
500 std::vector<const M3::float_t*> ParampPointers(
NModelParams);
501 int ParamCounter = 0;
502 for (
size_t iSys = 0; iSys <
systematics.size(); iSys++)
504 for (
int iPar = 0; iPar <
systematics[iSys]->GetNumParams(); iPar++)
506 ParampPointers[ParamCounter] =
systematics[iSys]->RetPointer(iPar);
507 std::string Name =
systematics[iSys]->GetParFancyName(iPar);
509 while (Name.find(
"-") != std::string::npos) {
510 Name.replace(Name.find(
"-"), 1, std::string(
"_"));
512 ToyTree->Branch(Name.c_str(), &ParamValues[ParamCounter], (Name +
"/D").c_str());
516 TDirectory* ToyDirectory =
outputFile->mkdir(
"Toys");
518 int SampleCounter = 0;
519 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
521 auto* MaCh3Sample =
samples[iPDF];
522 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNSamples(); ++SampleIndex)
525 const TH1* DataHist = MaCh3Sample->GetDataHist(SampleIndex);
526 Data_Hist[SampleCounter] =
M3::Clone(DataHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data");
527 Data_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data").c_str());
529 const TH1* MCHist = MaCh3Sample->GetMCHist(SampleIndex);
530 MC_Nom_Hist[SampleCounter] =
M3::Clone(MCHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc");
531 MC_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc").c_str());
533 const TH1* W2Hist = MaCh3Sample->GetW2Hist(SampleIndex);
534 W2_Nom_Hist[SampleCounter] =
M3::Clone(W2Hist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2");
535 W2_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2").c_str());
540 TDirectory* Toy_1DDirectory =
outputFile->mkdir(
"Toys_1DHistVar");
541 TDirectory* Toy_2DDirectory =
outputFile->mkdir(
"Toys_2DHistVar");
542 auto doByMode = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"ByMode"],
false, __FILE__, __LINE__);
543 TDirectory* ByModeDirectory =
nullptr;
544 if(doByMode) ByModeDirectory =
outputFile->mkdir(
"Toys_ByMode");
545 auto ReweightNames = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ReweightNames"],
546 {
"Weight"}, __FILE__, __LINE__);
547 bool doReweight =
false;
548 std::vector<double> reweight_weight(ReweightNames.size(), 1.0);
551 std::vector<std::vector<double>> branch_vals(
systematics.size());
552 std::vector<std::vector<std::string>> branch_name(
systematics.size());
554 TChain* PosteriorFile =
nullptr;
555 unsigned int burn_in = 0;
556 unsigned int maxNsteps = 0;
557 unsigned int Step = 0;
560 PosteriorFile =
new TChain(
"posteriors");
561 PosteriorFile->Add(PosteriorFileName.c_str());
563 PosteriorFile->SetBranchAddress(
"step", &Step);
565 for (
size_t i = 0; i < ReweightNames.size(); ++i) {
566 const auto& name = ReweightNames[i];
567 if (PosteriorFile->GetBranch(name.c_str())) {
568 PosteriorFile->SetBranchStatus(name.c_str(),
true);
569 PosteriorFile->SetBranchAddress(name.c_str(), &reweight_weight[i]);
571 MACH3LOG_WARN(
"Missing reweight branch '{}' -> disabling ALL reweighting", name);
578 systematics[s]->MatchMaCh3OutputBranches(PosteriorFile, branch_vals[s], branch_name[s], fancy_names);
582 burn_in = Get<unsigned int>(
fitMan->
raw()[
"Predictive"][
"BurnInSteps"], __FILE__, __LINE__);
585 maxNsteps =
static_cast<unsigned int>(PosteriorFile->GetMaximum(
"step"));
586 if(burn_in >= maxNsteps)
588 MACH3LOG_ERROR(
"You are running on a chain shorter than burn in cut");
589 MACH3LOG_ERROR(
"Maximal value of nSteps: {}, burn in cut {}", maxNsteps, burn_in);
596 TStopwatch TempClock;
598 for(
int i = 0; i <
Ntoys; i++)
607 bool WithinBounds =
false;
612 while(Step < burn_in || !WithinBounds) {
613 entry =
random->Integer(
static_cast<unsigned int>(PosteriorFile->GetEntries()));
614 PosteriorFile->GetEntry(entry);
617 if(BoundValuePointer.size() > 0) {
622 WithinBounds =
CheckBounds(BoundValuePointer, ParamBounds);
638 SetParamters(ParameterGroupsNotVaried, ParameterOnlyToVary);
651 for (
size_t iWeight = 0; iWeight < reweight_weight.size(); ++iWeight) {
652 Weight *= reweight_weight[iWeight];
657 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
661 WriteToy(ToyDirectory, Toy_1DDirectory, Toy_2DDirectory, i);
665 for (
size_t iPar = 0; iPar < ParamValues.size(); iPar++) {
666 ParamValues[iPar] = *ParampPointers[iPar];
673 if(PosteriorFile)
delete PosteriorFile;
674 ToyDirectory->Close();
delete ToyDirectory;
675 Toy_1DDirectory->Close();
delete Toy_1DDirectory;
676 Toy_2DDirectory->Close();
delete Toy_2DDirectory;
678 ByModeDirectory->Close();
679 delete ByModeDirectory;
683 ToyTree->Write();
delete ToyTree;
685 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
693 TDirectory * ogdir = gDirectory;
694 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
696 int originalErrorWarning = gErrorIgnoreLevel;
697 gErrorIgnoreLevel = kFatal;
699 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
701 gErrorIgnoreLevel = originalErrorWarning;
702 TDirectory* ToyDir = file->GetDirectory(
"Toys_1DHistVar");
704 if(ToyDir ==
nullptr) {
705 ToyDir =
outputFile->GetDirectory(
"Toys_1DHistVar");
708 std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>> ProjectionToys(
TotalNumberOfSamples);
710 ProjectionToys[sample].resize(
Ntoys);
711 const int nDims =
SampleInfo[sample].Dimenstion;
712 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
713 ProjectionToys[sample][iToy].resize(nDims);
717 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
718 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
720 const int nDims =
SampleInfo[sample].Dimenstion;
721 for(
int iDim = 0; iDim < nDims; iDim ++){
722 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
723 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
724 ProjectionToys[sample][iToy][iDim] =
M3::Clone(MCHist1D);
728 file->Close();
delete file;
729 if(ogdir){ ogdir->cd(); }
733 const int nDims =
SampleInfo[sample].Dimenstion;
737 SampleDirectories[sample]->cd();
739 std::string nameX =
"Data_" +
SampleInfo[sample].Name +
"_Dim0";
740 std::string nameY =
"Data_" +
SampleInfo[sample].Name +
"_Dim1";
742 if(std::string(hist->ClassName()) ==
"TH2Poly") {
743 TAxis* xax = ProjectionToys[sample][0][0]->GetXaxis();
744 TAxis* yax = ProjectionToys[sample][0][1]->GetXaxis();
746 std::vector<double> XBinning(xax->GetNbins()+1);
747 std::vector<double> YBinning(yax->GetNbins()+1);
749 for(
int i=0;i<=xax->GetNbins();++i)
750 XBinning[i] = xax->GetBinLowEdge(i+1);
752 for(
int i=0;i<=yax->GetNbins();++i)
753 YBinning[i] = yax->GetBinLowEdge(i+1);
755 TH1D* ProjectionX =
PolyProjectionX(
static_cast<TH2Poly*
>(hist), nameX.c_str(), XBinning,
false);
756 TH1D* ProjectionY =
PolyProjectionY(
static_cast<TH2Poly*
>(hist), nameY.c_str(), YBinning,
false);
758 ProjectionX->SetDirectory(
nullptr);
759 ProjectionY->SetDirectory(
nullptr);
761 ProjectionX->Write(nameX.c_str());
762 ProjectionY->Write(nameY.c_str());
767 TH1D* ProjectionX =
static_cast<TH2D*
>(hist)->ProjectionX(nameX.c_str());
768 TH1D* ProjectionY =
static_cast<TH2D*
>(hist)->ProjectionY(nameY.c_str());
770 ProjectionX->SetDirectory(
nullptr);
771 ProjectionY->SetDirectory(
nullptr);
773 ProjectionX->Write(nameX.c_str());
774 ProjectionY->Write(nameY.c_str());
787 TDirectory * ogdir = gDirectory;
788 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
790 int originalErrorWarning = gErrorIgnoreLevel;
791 gErrorIgnoreLevel = kFatal;
793 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
795 gErrorIgnoreLevel = originalErrorWarning;
796 TDirectory* ToyDir = file->GetDirectory(
"Toys_ByMode");
798 if(ToyDir ==
nullptr) {
799 ToyDir =
outputFile->GetDirectory(
"Toys_ByMode");
804 auto* mode =
SampleInfo[0].SamHandler->GetMaCh3Modes();
805 auto NModes = mode->GetNModes()+1;
807 std::vector<std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>>> ProjectionToys(NModes);
808 for(
int iMode = 0; iMode < NModes; iMode++) {
811 ProjectionToys[iMode][sample].resize(
Ntoys);
812 const int nDims =
SampleInfo[sample].Dimenstion;
813 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
814 ProjectionToys[iMode][sample][iToy].resize(nDims);
819 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
820 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
821 for(
int iMode = 0; iMode < NModes; iMode++) {
822 auto ModeName = mode->GetMaCh3ModeName(iMode);
824 const int nDims =
SampleInfo[sample].Dimenstion;
825 for(
int iDim = 0; iDim < nDims; iDim ++) {
826 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + ModeName +
"_" + std::to_string(iToy);
827 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
828 ProjectionToys[iMode][sample][iToy][iDim] =
M3::Clone(MCHist1D);
837 ModeDirectory[iSample] = SampleDirectories[iSample]->mkdir(
"ByMode");
840 for(
int iMode = 0; iMode < NModes; iMode++) {
841 auto ModeName = mode->GetMaCh3ModeName(iMode);
842 ProduceSpectra(ProjectionToys[iMode], ModeDirectory, ModeName,
false);
845 ModeDirectory[iSample]->Close();
846 delete ModeDirectory[iSample];
848 file->Close();
delete file;
849 if(ogdir){ ogdir->cd(); }
854 const std::vector<TDirectory*>& SampleDirectories,
855 const std::string suffix,
856 const bool DoSummary)
const {
862 const int nDims =
SampleInfo[sample].Dimenstion;
863 MaxValue[sample].assign(nDims, 0);
868 #pragma omp parallel for
871 for (
int toy = 0; toy <
Ntoys; ++toy) {
872 const int nDims =
SampleInfo[sample].Dimenstion;
873 for (
int dim = 0; dim < nDims; dim++) {
874 double max_val = Toys[sample][toy][dim]->GetMaximum();
875 MaxValue[sample][dim] = std::max(MaxValue[sample][dim], max_val);
884 const int nDims =
SampleInfo[sample].Dimenstion;
885 Spectra[sample].resize(nDims);
886 for (
int dim = 0; dim < nDims; dim++) {
888 TH1D* refHist = Toys[sample][0][dim].get();
890 const int n_bins_x = refHist->GetNbinsX();
891 std::vector<double> x_bin_edges(n_bins_x + 1);
892 for (
int b = 0; b < n_bins_x; ++b) {
893 x_bin_edges[b] = refHist->GetXaxis()->GetBinLowEdge(b + 1);
895 x_bin_edges[n_bins_x] = refHist->GetXaxis()->GetBinUpEdge(n_bins_x);
897 constexpr
int n_bins_y = 400;
898 constexpr
double y_min = 0.0;
899 const double y_max = MaxValue[sample][dim] * 1.05;
902 Spectra[sample][dim] = std::make_unique<TH2D>(
903 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
904 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
905 n_bins_x, x_bin_edges.data(),
906 n_bins_y, y_min, y_max
909 Spectra[sample][dim]->GetXaxis()->SetTitle(refHist->GetXaxis()->GetTitle());
910 Spectra[sample][dim]->GetYaxis()->SetTitle(
"Events");
912 Spectra[sample][dim]->SetDirectory(
nullptr);
913 Spectra[sample][dim]->Sumw2(
true);
919 #pragma omp parallel for collapse(2)
922 for (
int toy = 0; toy <
Ntoys; ++toy) {
923 const int nDims =
SampleInfo[sample].Dimenstion;
924 for (
int dim = 0; dim < nDims; dim++) {
925 FastViolinFill(Spectra[sample][dim].get(), Toys[sample][toy][dim].get());
932 SampleDirectories[sample]->cd();
933 const int nDims =
SampleInfo[sample].Dimenstion;
934 for (
long unsigned int dim = 0; dim < Spectra[sample].size(); dim++) {
935 Spectra[sample][dim]->Write();
937 if(nDims == 2 && DoSummary) {
938 const std::string name =
SampleInfo[sample].Name +
"_" + suffix+
"_PostPred_dim" + std::to_string(dim);
950 const std::vector<int>& bins)
const {
952 std::string BinName =
"";
954 const int b = bins[0];
955 const TAxis* ax = hist->GetXaxis();
956 const double low = ax->GetBinLowEdge(b);
957 const double up = ax->GetBinUpEdge(b);
959 BinName = fmt::format(
"Dim0 ({:g}, {:g})", low, up);
960 }
else if (Dim == 2) {
961 if(uniform ==
true) {
962 const int bx = bins[0];
963 const int by = bins[1];
964 const TAxis* ax = hist->GetXaxis();
965 const TAxis* ay = hist->GetYaxis();
966 BinName = fmt::format(
"Dim0 ({:g}, {:g}), ", ax->GetBinLowEdge(bx), ax->GetBinUpEdge(bx));
967 BinName += fmt::format(
"Dim1 ({:g}, {:g})", ay->GetBinLowEdge(by), ay->GetBinUpEdge(by));
969 TH2PolyBin* bin =
static_cast<TH2PolyBin*
>(
static_cast<TH2Poly*
>(hist)->GetBins()->At(bins[0]-1));
971 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 0, bin->GetXMin(), bin->GetXMax());
972 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 1, bin->GetYMin(), bin->GetYMax());
975 BinName = hist->GetXaxis()->GetBinLabel(bins[0]);
984 const std::string& suffix)
const {
986 std::vector<std::unique_ptr<TH1D>> PosteriorHistVec;
987 constexpr
int nBins = 100;
988 const std::string Sample_Name =
SampleInfo[SampleId].Name;
990 if(std::string(hist->ClassName()) ==
"TH2Poly") {
991 for (
int i = 1; i <= static_cast<TH2Poly*>(hist)->GetNumberOfBins(); ++i) {
992 std::string ProjName = fmt::format(
"{} {} Bin: {}",
997 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
998 PosteriorHist->SetDirectory(
nullptr);
999 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1000 PosteriorHistVec.push_back(std::move(PosteriorHist));
1003 int nbinsx = hist->GetNbinsX();
1004 int nbinsy = hist->GetNbinsY();
1005 for (
int iy = 1; iy <= nbinsy; ++iy) {
1006 for (
int ix = 1; ix <= nbinsx; ++ix) {
1007 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1008 Sample_Name, suffix,
1012 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1013 PosteriorHist->SetDirectory(
nullptr);
1014 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1015 PosteriorHistVec.push_back(std::move(PosteriorHist));
1020 int nbinsx = hist->GetNbinsX();
1021 PosteriorHistVec.reserve(nbinsx);
1022 for (
int i = 1; i <= nbinsx; ++i) {
1023 std::string ProjName = fmt::format(
"{} {} Bin: {}",
1024 Sample_Name, suffix,
1028 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
1029 PosteriorHist->SetDirectory(
nullptr);
1030 PosteriorHist->GetXaxis()->SetTitle(
"Events");
1031 PosteriorHistVec.push_back(std::move(PosteriorHist));
1034 return PosteriorHistVec;
1039 const std::vector<TDirectory*>& Directory,
1040 const std::string& suffix,
1041 const bool DebugHistograms,
1042 const bool WriteHist) {
1048 const int nDims =
SampleInfo[sample].Dimenstion;
1049 const std::string Sample_Name =
SampleInfo[sample].Name;
1050 Posterior_hist[sample] =
PerBinHistogram(Toys[sample][0].get(), sample, nDims, suffix);
1051 auto PredictiveHist =
M3::Clone(Toys[sample][0].get());
1053 PredictiveHist->Reset();
1054 PredictiveHist->SetName((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
1055 PredictiveHist->SetTitle((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
1056 PredictiveHist->SetDirectory(
nullptr);
1057 PostPred[sample] = std::move(PredictiveHist);
1062 #pragma omp parallel for
1065 const int nDims =
SampleInfo[sample].Dimenstion;
1066 auto& hist = Toys[sample][0];
1067 for (
size_t iToy = 0; iToy < Toys[sample].size(); ++iToy) {
1069 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1070 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
1071 double content = Toys[sample][iToy]->GetBinContent(i);
1072 Posterior_hist[sample][i-1]->Fill(content,
ReweightWeight[iToy]);
1075 int nbinsx = hist->GetNbinsX();
1076 int nbinsy = hist->GetNbinsY();
1077 for (
int iy = 1; iy <= nbinsy; ++iy) {
1078 for (
int ix = 1; ix <= nbinsx; ++ix) {
1079 int Bin = (iy-1) * nbinsx + (ix-1);
1080 double content = Toys[sample][iToy]->GetBinContent(ix, iy);
1081 Posterior_hist[sample][Bin]->Fill(content,
ReweightWeight[iToy]);
1086 int nbinsx = hist->GetNbinsX();
1087 for (
int i = 1; i <= nbinsx; ++i) {
1088 double content = Toys[sample][iToy]->GetBinContent(i);
1089 Posterior_hist[sample][i-1]->Fill(content,
ReweightWeight[iToy]);
1097 const int nDims =
SampleInfo[sample].Dimenstion;
1098 auto& hist = Toys[sample][0];
1099 Directory[sample]->cd();
1101 if(std::string(hist->ClassName()) ==
"TH2Poly") {
1102 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
1103 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1105 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1106 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1109 int nbinsx = hist->GetNbinsX();
1110 int nbinsy = hist->GetNbinsY();
1111 for (
int iy = 1; iy <= nbinsy; ++iy) {
1112 for (
int ix = 1; ix <= nbinsx; ++ix) {
1113 int Bin = (iy-1) * nbinsx + (ix-1);
1114 if (DebugHistograms) Posterior_hist[sample][Bin]->Write();
1115 PostPred[sample]->SetBinContent(ix, iy, Posterior_hist[sample][Bin]->GetMean());
1116 PostPred[sample]->SetBinError(ix, iy, Posterior_hist[sample][Bin]->GetRMS());
1121 int nbinsx = hist->GetNbinsX();
1122 for (
int i = 1; i <= nbinsx; ++i) {
1123 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1124 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1125 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1128 if(WriteHist) PostPred[sample]->Write();
1144 TStopwatch TempClock;
1147 auto DebugHistograms = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"DebugHistograms"],
false, __FILE__, __LINE__);
1148 auto doByMode = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"ByMode"],
false, __FILE__, __LINE__);
1150 TDirectory* PredictiveDir =
outputFile->mkdir(
"Predictive");
1151 std::vector<TDirectory*> SampleDirectories;
1156 SampleDirectories[sample] = PredictiveDir->mkdir(
SampleInfo[sample].Name.c_str());
1176 SampleDirectories[sample]->Close();
1177 delete SampleDirectories[sample];
1180 auto StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__);
1181 auto StudyInfoCriterion = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyInformationCriterion"],
true, __FILE__, __LINE__);
1182 auto StudyCorr = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyCorrelations"],
true, __FILE__, __LINE__);
1191 PredictiveDir->Close();
1192 delete PredictiveDir;
1197 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
1218 if (
auto h1 =
dynamic_cast<const TH1D*
>(DatHist)) {
1220 static_cast<const TH1D*
>(MCHist),
1221 static_cast<const TH1D*
>(W2Hist),
1226 if (
auto h2 =
dynamic_cast<const TH2D*
>(DatHist)) {
1228 static_cast<const TH2D*
>(MCHist),
1229 static_cast<const TH2D*
>(W2Hist),
1234 if (
auto h2p =
dynamic_cast<const TH2Poly*
>(DatHist)) {
1236 static_cast<const TH2Poly*
>(MCHist),
1237 static_cast<const TH2Poly*
>(W2Hist),
1252 for (
int i = 1; i <= DatHist->GetXaxis()->GetNbins(); ++i)
1254 const double data = DatHist->GetBinContent(i);
1255 const double mc = MCHist->GetBinContent(i);
1256 const double w2 = W2Hist->GetBinContent(i);
1265 const TH2Poly* MCHist,
1266 const TH2Poly* W2Hist,
1270 for (
int i = 1; i <= DatHist->GetNumberOfBins(); ++i)
1272 const double data = DatHist->GetBinContent(i);
1273 const double mc = MCHist->GetBinContent(i);
1274 const double w2 = W2Hist->GetBinContent(i);
1289 const int nBinsX = DatHist->GetXaxis()->GetNbins();
1290 const int nBinsY = DatHist->GetYaxis()->GetNbins();
1292 for (
int i = 1; i <= nBinsX; ++i)
1294 for (
int j = 1; j <= nBinsY; ++j)
1296 const double data = DatHist->GetBinContent(i, j);
1297 const double mc = MCHist->GetBinContent(i, j);
1298 const double w2 = W2Hist->GetBinContent(i, j);
1313 auto applyFluctuation = [&](
auto* f,
auto* h) {
1321 if (Hist->InheritsFrom(TH2Poly::Class())) {
1322 applyFluctuation(
static_cast<TH2Poly*
>(FluctHist),
static_cast<TH2Poly*
>(Hist));
1324 else if (Hist->InheritsFrom(TH2D::Class())) {
1325 applyFluctuation(
static_cast<TH2D*
>(FluctHist),
static_cast<TH2D*
>(Hist));
1327 else if (Hist->InheritsFrom(TH1D::Class())) {
1328 applyFluctuation(
static_cast<TH1D*
>(FluctHist),
static_cast<TH1D*
>(Hist));
1338 const std::vector<TDirectory*>& SampleDir) {
1342 auto make_matrix = [&](
double init = 0.0) {
1343 return std::vector<std::vector<double>>(
1345 std::vector<double>(
Ntoys, init));
1347 auto chi2_dat = make_matrix();
1348 auto chi2_mc = make_matrix();
1349 auto chi2_pred = make_matrix();
1350 auto chi2_rate_dat = make_matrix();
1351 auto chi2_rate_mc = make_matrix();
1352 auto chi2_rate_pred = make_matrix();
1355 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1367 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1368 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1371 auto PredFluctHist =
M3::Clone(PostPred_mc[iSample].get());
1384 chi2_rate_mc[iSample][iToy] =
CalcLLH(DrawFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1385 chi2_rate_pred[iSample][iToy] =
CalcLLH(PredFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1400 MakeChi2Plots(chi2_mc,
"-2LLH (Draw Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_drawfluc_draw");
1401 MakeChi2Plots(chi2_pred,
"-2LLH (Pred Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_predfluc_draw");
1404 MakeChi2Plots(chi2_rate_mc,
"-2LLH (Rate Draw Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_drawfluc_draw");
1405 MakeChi2Plots(chi2_rate_pred,
"-2LLH (Rate Pred Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_predfluc_draw");
1410 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1411 const std::vector<std::unique_ptr<TH1>>& PostPred_w,
1412 const std::vector<TDirectory*>& SampleDir) {
1414 MACH3LOG_INFO(
"{:<55} {:<10} {:<10} {:<10}",
"Sample",
"DataInt",
"MCInt",
"-2LLH");
1415 MACH3LOG_INFO(
"{:-<55} {:-<10} {:-<10} {:-<10}",
"",
"",
"",
"");
1417 SampleDir[iSample]->cd();
1418 ExtractLLH(Data_histogram[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(),
SampleInfo[iSample].SamHandler);
1419 PostPred_mc[iSample]->Write();
1426 const std::string& Chi2_x_title,
1427 const std::vector<std::vector<double>>& Chi2_y,
1428 const std::string& Chi2_y_title,
1429 const std::vector<TDirectory*>& SampleDir,
1430 const std::string Title) {
1433 SampleDir[iSample]->cd();
1436 std::vector<double> chi2_y_sample(
Ntoys);
1437 std::vector<double> chi2_x_per_sample(
Ntoys);
1439 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1440 chi2_y_sample[iToy] = Chi2_y[iSample][iToy];
1441 chi2_x_per_sample[iToy] = Chi2_x[iSample][iToy];
1444 const double min_val = std::min(*std::min_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1445 *std::min_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1446 const double max_val = std::max(*std::max_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1447 *std::max_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1449 auto chi2_hist = std::make_unique<TH2D>((
SampleInfo[iSample].Name+ Title).c_str(),
1451 50, min_val, max_val, 50, min_val, max_val);
1452 chi2_hist->SetDirectory(
nullptr);
1453 chi2_hist->GetXaxis()->SetTitle(Chi2_x_title.c_str());
1454 chi2_hist->GetYaxis()->SetTitle(Chi2_y_title.c_str());
1456 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1457 chi2_hist->Fill(chi2_x_per_sample[iToy], chi2_y_sample[iToy]);
1469 bool StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__ );
1470 if (StudyBeta ==
false)
return;
1473 TDirectory* BetaDir = PredictiveDir->mkdir(
"BetaParameters");
1479 DirBeta[sample] = BetaDir->mkdir(
SampleInfo[sample].Name.c_str());
1484 const int nDims =
SampleInfo[iSample].Dimenstion;
1486 TH1* RefHist =
Data_Hist[iSample].get();
1487 BetaHist[iSample] =
PerBinHistogram(RefHist, iSample, nDims,
"Beta_Parameter");
1489 for (
size_t i = 0; i < BetaHist[iSample].size(); ++i) {
1490 BetaHist[iSample][i]->GetXaxis()->SetTitle(
"beta parameter");
1496 #pragma omp parallel for
1499 const int nDims =
SampleInfo[iSample].Dimenstion;
1500 const auto likelihood =
SampleInfo[iSample].SamHandler->GetTestStatistic();
1501 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1503 if(std::string(
Data_Hist[iSample]->ClassName()) ==
"TH2Poly") {
1504 for (
int i = 1; i <= static_cast<TH2Poly*>(
Data_Hist[iSample].get())->GetNumberOfBins(); ++i) {
1505 const double Data =
Data_Hist[iSample]->GetBinContent(i);
1506 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1507 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1513 const int nX =
Data_Hist[iSample]->GetNbinsX();
1514 const int nY =
Data_Hist[iSample]->GetNbinsY();
1515 for (
int iy = 1; iy <= nY; ++iy) {
1516 for (
int ix = 1; ix <= nX; ++ix) {
1517 const int FlatBin = (iy-1) * nX + (ix-1);
1519 const double Data =
Data_Hist[iSample]->GetBinContent(ix, iy);
1520 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1521 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1524 BetaHist[iSample][FlatBin]->Fill(BetaParam,
ReweightWeight[iToy]);
1529 int nbinsx =
Data_Hist[iSample]->GetNbinsX();
1530 for (
int ix = 1; ix <= nbinsx; ++ix) {
1532 const double Data =
Data_Hist[iSample]->GetBinContent(ix);
1533 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1534 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1545 for (
size_t iBin = 0; iBin < BetaHist[iSample].size(); iBin++) {
1546 DirBeta[iSample]->cd();
1547 BetaHist[iSample][iBin]->Write();
1549 DirBeta[iSample]->Close();
1550 delete DirBeta[iSample];
1555 PredictiveDir->cd();
1561 const std::vector<std::vector<std::unique_ptr<TH1>>>& Toys,
1562 const bool DebugHistograms)
const {
1567 TDirectory *CorrDir = PredictiveDir->mkdir(
"Correlations");
1573 #pragma omp parallel for
1577 for (
const auto& toyHist : Toys[i])
1579 const double val = toyHist->Integral();
1580 if (val < minVals[i]) minVals[i] = val;
1581 if (val > maxVals[i]) maxVals[i] = val;
1584 auto hSamCorr = std::make_unique<TH2D>(
"Sample Correlation",
"Sample Correlation",
TotalNumberOfSamples, 0,
1586 hSamCorr->SetDirectory(
nullptr);
1587 hSamCorr->GetZaxis()->SetTitle(
"Correlation");
1588 hSamCorr->SetMinimum(-1);
1589 hSamCorr->SetMaximum(1);
1590 hSamCorr->GetXaxis()->SetLabelSize(0.015);
1591 hSamCorr->GetYaxis()->SetLabelSize(0.015);
1594 hSamCorr->SetBinContent(i+1, i+1, 1.0);
1595 hSamCorr->GetXaxis()->SetBinLabel(i+1,
SampleInfo[i].Name.c_str());
1597 hSamCorr->GetYaxis()->SetBinLabel(j+1,
SampleInfo[j].Name.c_str());
1605 const double Min_i = minVals[i];
1606 const double Max_i = maxVals[i];
1609 const double Min_j = minVals[j];
1610 const double Max_j = maxVals[j];
1612 std::string name =
"SamCorr_" + std::to_string(i) +
"_" + std::to_string(j);
1613 SamCorr[i][j] = std::make_unique<TH2D>(name.c_str(), name.c_str(), 70, Min_i, Max_i, 70, Min_j, Max_j);
1614 SamCorr[i][j]->SetDirectory(
nullptr);
1615 SamCorr[i][j]->SetMinimum(0);
1616 SamCorr[i][j]->GetXaxis()->SetTitle(
SampleInfo[i].Name.c_str());
1617 SamCorr[i][j]->GetYaxis()->SetTitle(
SampleInfo[j].Name.c_str());
1618 SamCorr[i][j]->GetZaxis()->SetTitle(
"Events");
1624 #pragma omp parallel for
1628 for (
int j = 0; j <= i; ++j)
1631 if (j == i)
continue;
1633 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1635 SamCorr[i][j]->Fill(Toys[i][iToy]->Integral(), Toys[j][iToy]->Integral());
1637 SamCorr[i][j]->Smooth();
1640 const double corr = SamCorr[i][j]->GetCorrelationFactor();
1641 hSamCorr->SetBinContent(i+1, j+1, corr);
1642 hSamCorr->SetBinContent(j+1, i+1, corr);
1646 hSamCorr->Draw(
"colz");
1647 hSamCorr->Write(
"Sample_Corr");
1649 if(DebugHistograms) {
1651 for (
int j = 0; j <= i; ++j) {
1653 if (j == i)
continue;
1654 SamCorr[i][j]->Write();
1659 PredictiveDir->cd();
1666 const double llh =
CalcLLH(DatHist, MCHist, W2Hist, SampleHandler);
1667 std::stringstream ss;
1668 ss <<
"_2LLH=" << llh;
1669 MCHist->SetTitle((std::string(MCHist->GetTitle())+ss.str()).c_str());
1670 MACH3LOG_INFO(
"{:<55} {:<10.2f} {:<10.2f} {:<10.2f}", MCHist->GetName(), DatHist->Integral(), MCHist->Integral(), llh);
1678 int originalErrorWarning = gErrorIgnoreLevel;
1679 gErrorIgnoreLevel = kFatal;
1682 auto TempLine = std::make_unique<TLine>(DataRate, Histogram->GetMinimum(), DataRate, Histogram->GetMaximum());
1683 TempLine->SetLineColor(kRed);
1684 TempLine->SetLineWidth(2);
1686 auto Fitter = std::make_unique<TF1>(
"Fit",
"gaus", Histogram->GetBinLowEdge(1), Histogram->GetBinLowEdge(Histogram->GetNbinsX()+1));
1687 Histogram->Fit(Fitter.get(),
"RQ");
1688 Fitter->SetLineColor(kRed-5);
1691 for (
int z = 0; z < Histogram->GetNbinsX(); ++z) {
1692 const double xvalue = Histogram->GetBinCenter(z+1);
1693 if (xvalue >= DataRate) {
1694 Above += Histogram->GetBinContent(z+1);
1697 const double pvalue = Above/Histogram->Integral();
1698 TLegend Legend(0.4, 0.75, 0.98, 0.90);
1699 Legend.SetFillColor(0);
1700 Legend.SetFillStyle(0);
1701 Legend.SetLineWidth(0);
1702 Legend.SetLineColor(0);
1703 Legend.AddEntry(TempLine.get(), Form(
"Data, %.0f, p-value=%.2f", DataRate, pvalue),
"l");
1704 Legend.AddEntry(Histogram, Form(
"MC, #mu=%.1f#pm%.1f", Histogram->GetMean(), Histogram->GetRMS()),
"l");
1705 Legend.AddEntry(Fitter.get(), Form(
"Gauss, #mu=%.1f#pm%.1f", Fitter->GetParameter(1), Fitter->GetParameter(2)),
"l");
1706 std::string TempTitle = std::string(Histogram->GetName());
1707 TempTitle +=
"_canv";
1708 TCanvas TempCanvas(TempTitle.c_str(), TempTitle.c_str(), 1024, 1024);
1709 TempCanvas.SetGridx();
1710 TempCanvas.SetGridy();
1711 TempCanvas.SetRightMargin(0.03);
1712 TempCanvas.SetBottomMargin(0.08);
1713 TempCanvas.SetLeftMargin(0.10);
1714 TempCanvas.SetTopMargin(0.06);
1717 TempLine->Draw(
"same");
1718 Fitter->Draw(
"same");
1719 Legend.Draw(
"same");
1722 gErrorIgnoreLevel = originalErrorWarning;
1727 const std::vector<TDirectory*>& SampleDirectories)
const {
1731 std::string Title =
"EventHist: ";
1740 EventHist[iSample] = std::make_unique<TH1D>(Title.c_str(), Title.c_str(), 100, 1, -1);
1741 EventHist[iSample]->SetDirectory(
nullptr);
1742 EventHist[iSample]->GetXaxis()->SetTitle(
"Total event rate");
1743 EventHist[iSample]->GetYaxis()->SetTitle(
"Counts");
1744 EventHist[iSample]->SetLineWidth(2);
1749 #pragma omp parallel for
1752 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1753 double Count = Toys[iSample][iToy]->Integral();
1754 EventHist[iSample]->Fill(Count);
1759 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1760 double TotalCount = 0.0;
1762 TotalCount += Toys[iSample][iToy]->Integral();
1767 double DataRate = 0.0;
1770 #pragma omp parallel for reduction(+:DataRate)
1773 DataRates[i] =
Data_Hist[i]->Integral();
1774 DataRate += DataRates[i];
1779 SampleDirectories[SampleNum]->cd();
1788 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1789 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1818 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1821 double DataRate = 0.0;
1822 double BinsRate = 0.0;
1823 double TotalLLH = 0.0;
1825 #pragma omp parallel for reduction(+:DataRate, BinsRate, TotalLLH)
1829 auto SampleHandler =
SampleInfo[i].SamHandler;
1831 DataRate += h->Integral();
1832 if (
auto h1 =
dynamic_cast<TH1D*
>(h)) {
1833 BinsRate += h1->GetNbinsX();
1834 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(h)) {
1835 BinsRate += h2->GetNbinsX() * h2->GetNbinsY();
1836 }
else if (
auto h2poly =
dynamic_cast<TH2Poly*
>(h)) {
1837 BinsRate += h2poly->GetNumberOfBins();
1841 TotalLLH +=
CalcLLH(
Data_Hist[i].get(), PostPred_mc[i].get(), PostPred_w[i].get(), SampleHandler);
1846 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of events: {:.2f}", EventRateBIC);
1847 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of bins: {:.2f}", BinBasedBIC);
1848 MACH3LOG_INFO(
"Additional info: NModelParams: {}, DataRate: {:.2f}, BinsRate: {:.2f}",
NModelParams, DataRate, BinsRate);
1854 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1858 double TotalLLH = 0.0;
1861 #pragma omp parallel for reduction(+:Dbar)
1865 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1866 TotalLLH +=
CalcLLH(
Data_Hist[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(), SampleHandler);
1867 double LLH_temp = 0.;
1868 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1874 Dbar = Dbar /
Ntoys;
1877 const double Dhat = TotalLLH;
1880 const double p_D = std::fabs(Dbar - Dhat);
1883 const double DIC_stat = Dhat + 2 * p_D;
1884 MACH3LOG_INFO(
"Effective number of parameters following DIC formalism is equal to: {:.2f}", p_D);
1893 double& mean_llh_squared,
1894 double& sum_exp_llh) {
1897 double LLH_temp = -neg_LLH_temp;
1899 mean_llh += LLH_temp;
1900 mean_llh_squared += LLH_temp * LLH_temp;
1901 sum_exp_llh += std::exp(LLH_temp);
1907 const unsigned int Ntoys,
double& lppd,
double& p_WAIC) {
1911 mean_llh_squared /=
Ntoys;
1912 sum_exp_llh /=
Ntoys;
1913 sum_exp_llh = std::log(sum_exp_llh);
1916 lppd += sum_exp_llh;
1919 p_WAIC += mean_llh_squared - (mean_llh * mean_llh);
1932 #pragma omp parallel for reduction(+:lppd, p_WAIC)
1935 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1938 if (
auto h2poly =
dynamic_cast<TH2Poly*
>(hData)) {
1940 for (
int i = 1; i <= h2poly->GetNumberOfBins(); ++i) {
1941 const double data =
Data_Hist[iSample]->GetBinContent(i);
1942 double mean_llh = 0.;
1943 double sum_exp_llh = 0;
1944 double mean_llh_squared = 0.;
1946 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1947 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1948 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1950 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1955 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(hData)) {
1957 for (
int ix = 1; ix <= h2->GetNbinsX(); ++ix) {
1958 for (
int iy = 1; iy <= h2->GetNbinsY(); ++iy) {
1959 const double data = hData->GetBinContent(ix, iy);
1960 double mean_llh = 0.;
1961 double mean_llh_squared = 0.;
1962 double sum_exp_llh = 0.;
1963 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1964 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1965 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1967 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1973 }
else if (
auto h1 =
dynamic_cast<TH1D*
>(hData)) {
1975 for (
int iBin = 1; iBin <= h1->GetNbinsX(); ++iBin) {
1976 const double data = hData->GetBinContent(iBin);
1977 double mean_llh = 0.;
1978 double mean_llh_squared = 0.;
1979 double sum_exp_llh = 0.;
1980 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1981 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
1982 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
1985 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1994 double WAIC = -2 * (lppd - p_WAIC);
1995 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.