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__);
44 std::unordered_set<int>& ParameterOnlyToVary) {
47 auto DoNotThrowLegacyCov = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"DoNotThrowLegacyCov"], {}, __FILE__, __LINE__);
49 for (
size_t i = 0; i < DoNotThrowLegacyCov.size(); ++i) {
67 if (ParameterOnlyToVary.find(i) == ParameterOnlyToVary.end()) {
78 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
96 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
97 for (
int SampleIndex = 0; SampleIndex <
samples[iPDF]->GetNSamples(); ++SampleIndex) {
111 std::unordered_set<int>& ParameterOnlyToVary,
112 std::vector<const M3::float_t*>& BoundValuePointer,
113 std::vector<std::pair<double, double>>& ParamBounds) {
127 MACH3LOG_INFO(
"You've chosen to run Prior Predictive Distribution");
129 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
135 auto AllowDifferentConfigs = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"AllowDifferentConfigs"],
false, __FILE__, __LINE__);
143 if(AllowDifferentConfigs){
144 MACH3LOG_WARN(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
146 MACH3LOG_ERROR(
"Yaml configs used for your ParameterHandler for chain you want sample from ({}) and one currently initialised are different", PosteriorFileName);
153 MACH3LOG_ERROR(
"Found {} ParmaterHandler inheriting from ParameterHandlerGeneric, I can accept at most 1", counter);
162 auto ThrowParamGroupOnly = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowParamGroupOnly"], {}, __FILE__, __LINE__);
164 auto ParameterOnlyToVaryString = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowSinlgeParams"], {}, __FILE__, __LINE__);
166 if (!ThrowParamGroupOnly.empty() && !ParameterOnlyToVaryString.empty()) {
167 MACH3LOG_ERROR(
"Can't use ThrowParamGroupOnly and ThrowSinlgeParams at the same time");
171 if (!ParameterOnlyToVaryString.empty()) {
172 MACH3LOG_INFO(
"I will throw only: {}", fmt::join(ParameterOnlyToVaryString,
", "));
173 std::vector<int> ParameterVary(ParameterOnlyToVaryString.size());
175 for (
size_t i = 0; i < ParameterOnlyToVaryString.size(); ++i) {
178 MACH3LOG_ERROR(
"Can't proceed if param {} is missing", ParameterOnlyToVaryString[i]);
182 ParameterOnlyToVary = std::unordered_set<int>(ParameterVary.begin(), ParameterVary.end());
184 MACH3LOG_INFO(
"I have following parameter groups: {}", fmt::join(UniqueParamGroup,
", "));
185 if (ThrowParamGroupOnly.empty()) {
188 std::unordered_set<std::string> throwOnlySet(ThrowParamGroupOnly.begin(), ThrowParamGroupOnly.end());
189 ParameterGroupsNotVaried.clear();
191 for (
const auto& group : UniqueParamGroup) {
192 if (throwOnlySet.find(group) == throwOnlySet.end()) {
193 ParameterGroupsNotVaried.push_back(group);
197 MACH3LOG_INFO(
"I will vary: {}", fmt::join(ThrowParamGroupOnly,
", "));
198 MACH3LOG_INFO(
"Exclude: {}", fmt::join(ParameterGroupsNotVaried,
", "));
203 auto paramNode =
fitMan->
raw()[
"Predictive"][
"ParameterBounds"];
204 for (
const auto& p : paramNode) {
206 std::string name = p[0].as<std::string>();
209 double minVal = p[1][0].as<
double>();
210 double maxVal = p[1][1].as<
double>();
211 ParamBounds.emplace_back(minVal, maxVal);
214 for(
int iPar = 0; iPar <
systematics[s]->GetNParameters(); iPar++){
216 BoundValuePointer.push_back(
systematics[s]->RetPointer(iPar));
221 if(ParamBounds.size() != BoundValuePointer.size()){
225 MACH3LOG_INFO(
"Parameter: {} with : [{}, {}]", name, minVal, maxVal);
228 MACH3LOG_ERROR(
"Additional bounds not supported by prior predictive right now");
237 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
239 int originalErrorWarning = gErrorIgnoreLevel;
240 gErrorIgnoreLevel = kFatal;
241 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
243 gErrorIgnoreLevel = originalErrorWarning;
244 TDirectory* ToyDir =
nullptr;
245 if (!file || file->IsZombie()) {
249 if ((ToyDir = file->GetDirectory(
"Toys"))) {
250 MACH3LOG_INFO(
"Found toys in Posterior file will attempt toy reading");
259 TTree* PenaltyTree =
static_cast<TTree*
>(file->Get(
"ToySummary"));
267 Ntoys =
static_cast<int>(PenaltyTree->GetEntries());
268 int ConfigNtoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);;
269 if (
Ntoys != ConfigNtoys) {
270 MACH3LOG_WARN(
"Found different number of toys in saved file than asked to run!");
279 double Penalty = 0, Weight = 1;
280 PenaltyTree->SetBranchAddress(
"Penalty", &Penalty);
281 PenaltyTree->SetBranchAddress(
"Weight", &Weight);
282 PenaltyTree->SetBranchAddress(
"NModelParams", &
NModelParams);
284 for (
int i = 0; i <
Ntoys; ++i) {
285 PenaltyTree->GetEntry(i);
298 TH1* DataHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_data").c_str()));
301 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc").c_str()));
304 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2").c_str()));
309 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
314 TH1* MCHist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_mc_" + std::to_string(iToy)).c_str()));
315 TH1* W2Hist1D =
static_cast<TH1*
>(ToyDir->Get((
SampleInfo[sample].Name +
"_w2_" + std::to_string(iToy)).c_str()));
330 TDirectory * ogdir = gDirectory;
332 std::vector<std::string> FancyNames;
333 std::string Name = std::string(
"Config_") + Systematics->
GetName();
334 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
336 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
337 TDirectory* CovarianceFolder = file->GetDirectory(
"CovarianceFolder");
339 TMacro* FoundMacro =
static_cast<TMacro*
>(CovarianceFolder->Get(Name.c_str()));
340 if(FoundMacro ==
nullptr) {
343 if(ogdir){ ogdir->cd(); }
350 int params = int(Settings[
"Systematics"].size());
351 FancyNames.resize(params);
353 for (
auto const ¶m : Settings[
"Systematics"]) {
354 FancyNames[iPar] = Get<std::string>(param[
"Systematic"][
"Names"][
"FancyName"], __FILE__ , __LINE__);
359 if(ogdir){ ogdir->cd(); }
366 TDirectory* Toy_1DDirectory,
367 TDirectory* Toy_2DDirectory,
370 int SampleCounter = 0;
371 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
373 auto* SampleHandler =
samples[iPDF];
374 for (
int iSample = 0; iSample < SampleHandler->GetNSamples(); ++iSample)
378 auto SampleName = SampleHandler->GetSampleTitle(iSample);
379 const TH1* MCHist = SampleHandler->GetMCHist(iSample);
380 MC_Hist_Toy[SampleCounter][iToy] =
M3::Clone(MCHist, SampleName +
"_mc_" + std::to_string(iToy));
383 const TH1* W2Hist = SampleHandler->GetW2Hist(iSample);
384 W2_Hist_Toy[SampleCounter][iToy] =
M3::Clone(W2Hist, SampleName +
"_w2_" + std::to_string(iToy));
388 Toy_1DDirectory->cd();
389 for(
int iDim = 0; iDim < SampleHandler->GetNDim(iSample); iDim++) {
390 std::string ProjectionName = SampleHandler->GetKinVarName(iSample, iDim);
391 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
393 auto hist = SampleHandler->Get1DVarHist(iSample, ProjectionName);
394 hist->SetTitle((SampleName + ProjectionSuffix).c_str());
395 hist->SetName((SampleName + ProjectionSuffix).c_str());
399 Toy_2DDirectory->cd();
401 for(
int iDim1 = 0; iDim1 < SampleHandler->GetNDim(iSample); iDim1++) {
402 for (
int iDim2 = iDim1 + 1; iDim2 < SampleHandler->GetNDim(iSample); ++iDim2) {
404 std::string XVarName = SampleHandler->GetKinVarName(iSample, iDim1);
405 std::string YVarName = SampleHandler->GetKinVarName(iSample, iDim2);
408 auto hist2D = SampleHandler->Get2DVarHist(iSample, XVarName, YVarName);
411 std::string suffix2D =
"_2DProj_" + std::to_string(iDim1) +
"_vs_" + std::to_string(iDim2) +
"_" + std::to_string(iToy);
412 hist2D->SetTitle((SampleName + suffix2D).c_str());
413 hist2D->SetName((SampleName + suffix2D).c_str());
423 bool CheckBounds(
const std::vector<const M3::float_t*>& BoundValuePointer,
424 const std::vector<std::pair<double,double>>& ParamBounds) {
426 for (
size_t i = 0; i < BoundValuePointer.size(); ++i) {
427 const double val = *(BoundValuePointer[i]);
428 const double minVal = ParamBounds[i].first;
429 const double maxVal = ParamBounds[i].second;
431 if (val < minVal || val > maxVal)
445 std::vector<std::string> ParameterGroupsNotVaried;
447 std::unordered_set<int> ParameterOnlyToVary;
449 std::vector<const M3::float_t*> BoundValuePointer;
450 std::vector<std::pair<double, double>> ParamBounds;
454 BoundValuePointer, ParamBounds);
456 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
461 double Penalty = 0, Weight = 1;
464 TTree *ToyTree =
new TTree(
"ToySummary",
"ToySummary");
465 ToyTree->Branch(
"Penalty", &Penalty,
"Penalty/D");
466 ToyTree->Branch(
"Weight", &Weight,
"Weight/D");
467 ToyTree->Branch(
"Draw", &Draw,
"Draw/I");
468 ToyTree->Branch(
"NModelParams", &
NModelParams,
"NModelParams/I");
472 std::vector<const M3::float_t*> ParampPointers(
NModelParams);
473 int ParamCounter = 0;
474 for (
size_t iSys = 0; iSys <
systematics.size(); iSys++)
476 for (
int iPar = 0; iPar <
systematics[iSys]->GetNumParams(); iPar++)
478 ParampPointers[ParamCounter] =
systematics[iSys]->RetPointer(iPar);
479 std::string Name =
systematics[iSys]->GetParFancyName(iPar);
481 while (Name.find(
"-") != std::string::npos) {
482 Name.replace(Name.find(
"-"), 1, std::string(
"_"));
484 ToyTree->Branch(Name.c_str(), &ParamValues[ParamCounter], (Name +
"/D").c_str());
488 TDirectory* ToyDirectory =
outputFile->mkdir(
"Toys");
490 int SampleCounter = 0;
491 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
493 auto* MaCh3Sample =
samples[iPDF];
494 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNSamples(); ++SampleIndex)
497 const TH1* DataHist = MaCh3Sample->GetDataHist(SampleIndex);
498 Data_Hist[SampleCounter] =
M3::Clone(DataHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data");
499 Data_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_data").c_str());
501 const TH1* MCHist = MaCh3Sample->GetMCHist(SampleIndex);
502 MC_Nom_Hist[SampleCounter] =
M3::Clone(MCHist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc");
503 MC_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_mc").c_str());
505 const TH1* W2Hist = MaCh3Sample->GetW2Hist(SampleIndex);
506 W2_Nom_Hist[SampleCounter] =
M3::Clone(W2Hist, MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2");
507 W2_Nom_Hist[SampleCounter]->Write((MaCh3Sample->GetSampleTitle(SampleIndex) +
"_w2").c_str());
512 TDirectory* Toy_1DDirectory =
outputFile->mkdir(
"Toys_1DHistVar");
513 TDirectory* Toy_2DDirectory =
outputFile->mkdir(
"Toys_2DHistVar");
515 std::vector<std::vector<double>> branch_vals(
systematics.size());
516 std::vector<std::vector<std::string>> branch_name(
systematics.size());
518 TChain* PosteriorFile =
nullptr;
519 unsigned int burn_in = 0;
520 unsigned int maxNsteps = 0;
521 unsigned int Step = 0;
524 PosteriorFile =
new TChain(
"posteriors");
525 PosteriorFile->Add(PosteriorFileName.c_str());
527 PosteriorFile->SetBranchAddress(
"step", &Step);
528 if (PosteriorFile->GetBranch(
"Weight")) {
529 PosteriorFile->SetBranchStatus(
"Weight",
true);
530 PosteriorFile->SetBranchAddress(
"Weight", &Weight);
538 systematics[s]->MatchMaCh3OutputBranches(PosteriorFile, branch_vals[s], branch_name[s], fancy_names);
542 burn_in = Get<unsigned int>(
fitMan->
raw()[
"Predictive"][
"BurnInSteps"], __FILE__, __LINE__);
545 maxNsteps =
static_cast<unsigned int>(PosteriorFile->GetMaximum(
"step"));
546 if(burn_in >= maxNsteps)
548 MACH3LOG_ERROR(
"You are running on a chain shorter than burn in cut");
549 MACH3LOG_ERROR(
"Maximal value of nSteps: {}, burn in cut {}", maxNsteps, burn_in);
556 TStopwatch TempClock;
558 for(
int i = 0; i <
Ntoys; i++)
567 bool WithinBounds =
false;
572 while(Step < burn_in || !WithinBounds) {
573 entry =
random->Integer(
static_cast<unsigned int>(PosteriorFile->GetEntries()));
574 PosteriorFile->GetEntry(entry);
577 if(BoundValuePointer.size() > 0) {
582 WithinBounds =
CheckBounds(BoundValuePointer, ParamBounds);
598 SetParamters(ParameterGroupsNotVaried, ParameterOnlyToVary);
611 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
615 WriteToy(ToyDirectory, Toy_1DDirectory, Toy_2DDirectory, i);
618 for (
size_t iPar = 0; iPar < ParamValues.size(); iPar++) {
619 ParamValues[iPar] = *ParampPointers[iPar];
626 if(PosteriorFile)
delete PosteriorFile;
627 ToyDirectory->Close();
delete ToyDirectory;
628 Toy_1DDirectory->Close();
delete Toy_1DDirectory;
629 Toy_2DDirectory->Close();
delete Toy_2DDirectory;
632 ToyTree->Write();
delete ToyTree;
634 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
642 TDirectory * ogdir = gDirectory;
643 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
645 int originalErrorWarning = gErrorIgnoreLevel;
646 gErrorIgnoreLevel = kFatal;
648 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
650 gErrorIgnoreLevel = originalErrorWarning;
651 TDirectory* ToyDir = file->GetDirectory(
"Toys_1DHistVar");
653 if(ToyDir ==
nullptr) {
654 ToyDir =
outputFile->GetDirectory(
"Toys_1DHistVar");
657 std::vector<std::vector<std::vector<std::unique_ptr<TH1D>>>> ProjectionToys(
TotalNumberOfSamples);
659 ProjectionToys[sample].resize(
Ntoys);
660 const int nDims =
SampleInfo[sample].Dimenstion;
661 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
662 ProjectionToys[sample][iToy].resize(nDims);
666 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
667 if (iToy % 100 == 0)
MACH3LOG_INFO(
" Loaded Projection toys {}", iToy);
669 const int nDims =
SampleInfo[sample].Dimenstion;
670 for(
int iDim = 0; iDim < nDims; iDim ++){
671 std::string ProjectionSuffix =
"_1DProj" + std::to_string(iDim) +
"_" + std::to_string(iToy);
672 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleInfo[sample].Name + ProjectionSuffix).c_str()));
673 ProjectionToys[sample][iToy][iDim] =
M3::Clone(MCHist1D);
677 file->Close();
delete file;
678 if(ogdir){ ogdir->cd(); }
682 const int nDims =
SampleInfo[sample].Dimenstion;
686 SampleDirectories[sample]->cd();
688 std::string nameX =
"Data_" +
SampleInfo[sample].Name +
"_Dim0";
689 std::string nameY =
"Data_" +
SampleInfo[sample].Name +
"_Dim1";
691 if(std::string(hist->ClassName()) ==
"TH2Poly") {
692 TAxis* xax = ProjectionToys[sample][0][0]->GetXaxis();
693 TAxis* yax = ProjectionToys[sample][0][1]->GetXaxis();
695 std::vector<double> XBinning(xax->GetNbins()+1);
696 std::vector<double> YBinning(yax->GetNbins()+1);
698 for(
int i=0;i<=xax->GetNbins();++i)
699 XBinning[i] = xax->GetBinLowEdge(i+1);
701 for(
int i=0;i<=yax->GetNbins();++i)
702 YBinning[i] = yax->GetBinLowEdge(i+1);
704 TH1D* ProjectionX =
PolyProjectionX(
static_cast<TH2Poly*
>(hist), nameX.c_str(), XBinning,
false);
705 TH1D* ProjectionY =
PolyProjectionY(
static_cast<TH2Poly*
>(hist), nameY.c_str(), YBinning,
false);
707 ProjectionX->SetDirectory(
nullptr);
708 ProjectionY->SetDirectory(
nullptr);
710 ProjectionX->Write(nameX.c_str());
711 ProjectionY->Write(nameY.c_str());
716 TH1D* ProjectionX =
static_cast<TH2D*
>(hist)->ProjectionX(nameX.c_str());
717 TH1D* ProjectionY =
static_cast<TH2D*
>(hist)->ProjectionY(nameY.c_str());
719 ProjectionX->SetDirectory(
nullptr);
720 ProjectionY->SetDirectory(
nullptr);
722 ProjectionX->Write(nameX.c_str());
723 ProjectionY->Write(nameY.c_str());
733 const std::vector<TDirectory*>& SampleDirectories,
734 const std::string suffix)
const {
740 const int nDims =
SampleInfo[sample].Dimenstion;
741 MaxValue[sample].assign(nDims, 0);
746 #pragma omp parallel for
749 for (
int toy = 0; toy <
Ntoys; ++toy) {
750 const int nDims =
SampleInfo[sample].Dimenstion;
751 for (
int dim = 0; dim < nDims; dim++) {
752 double max_val = Toys[sample][toy][dim]->GetMaximum();
753 MaxValue[sample][dim] = std::max(MaxValue[sample][dim], max_val);
762 const int nDims =
SampleInfo[sample].Dimenstion;
763 Spectra[sample].resize(nDims);
764 for (
int dim = 0; dim < nDims; dim++) {
766 TH1D* refHist = Toys[sample][0][dim].get();
768 const int n_bins_x = refHist->GetNbinsX();
769 std::vector<double> x_bin_edges(n_bins_x + 1);
770 for (
int b = 0; b < n_bins_x; ++b) {
771 x_bin_edges[b] = refHist->GetXaxis()->GetBinLowEdge(b + 1);
773 x_bin_edges[n_bins_x] = refHist->GetXaxis()->GetBinUpEdge(n_bins_x);
775 constexpr
int n_bins_y = 400;
776 constexpr
double y_min = 0.0;
777 const double y_max = MaxValue[sample][dim] * 1.05;
780 Spectra[sample][dim] = std::make_unique<TH2D>(
781 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
782 (
SampleInfo[sample].Name +
"_" + suffix +
"_dim" + std::to_string(dim)).c_str(),
783 n_bins_x, x_bin_edges.data(),
784 n_bins_y, y_min, y_max
787 Spectra[sample][dim]->GetXaxis()->SetTitle(refHist->GetXaxis()->GetTitle());
788 Spectra[sample][dim]->GetYaxis()->SetTitle(
"Events");
790 Spectra[sample][dim]->SetDirectory(
nullptr);
791 Spectra[sample][dim]->Sumw2(
true);
797 #pragma omp parallel for collapse(2)
800 for (
int toy = 0; toy <
Ntoys; ++toy) {
801 const int nDims =
SampleInfo[sample].Dimenstion;
802 for (
int dim = 0; dim < nDims; dim++) {
803 FastViolinFill(Spectra[sample][dim].get(), Toys[sample][toy][dim].get());
810 SampleDirectories[sample]->cd();
811 const int nDims =
SampleInfo[sample].Dimenstion;
812 for (
long unsigned int dim = 0; dim < Spectra[sample].size(); dim++) {
813 Spectra[sample][dim]->Write();
816 const std::string name =
SampleInfo[sample].Name +
"_" + suffix+
"_PostPred_dim" + std::to_string(dim);
828 const std::vector<int>& bins)
const {
830 std::string BinName =
"";
832 const int b = bins[0];
833 const TAxis* ax = hist->GetXaxis();
834 const double low = ax->GetBinLowEdge(b);
835 const double up = ax->GetBinUpEdge(b);
837 BinName = fmt::format(
"Dim0 ({:g}, {:g})", low, up);
838 }
else if (Dim == 2) {
839 if(uniform ==
true) {
840 const int bx = bins[0];
841 const int by = bins[1];
842 const TAxis* ax = hist->GetXaxis();
843 const TAxis* ay = hist->GetYaxis();
844 BinName = fmt::format(
"Dim0 ({:g}, {:g}), ", ax->GetBinLowEdge(bx), ax->GetBinUpEdge(bx));
845 BinName += fmt::format(
"Dim1 ({:g}, {:g})", ay->GetBinLowEdge(by), ay->GetBinUpEdge(by));
847 TH2PolyBin* bin =
static_cast<TH2PolyBin*
>(
static_cast<TH2Poly*
>(hist)->GetBins()->At(bins[0]-1));
849 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 0, bin->GetXMin(), bin->GetXMax());
850 BinName += fmt::format(
"Dim{} ({:g}, {:g})", 1, bin->GetYMin(), bin->GetYMax());
853 BinName = hist->GetXaxis()->GetBinLabel(bins[0]);
862 const std::string& suffix)
const {
864 std::vector<std::unique_ptr<TH1D>> PosteriorHistVec;
865 constexpr
int nBins = 100;
866 const std::string Sample_Name =
SampleInfo[SampleId].Name;
868 if(std::string(hist->ClassName()) ==
"TH2Poly") {
869 for (
int i = 1; i <= static_cast<TH2Poly*>(hist)->GetNumberOfBins(); ++i) {
870 std::string ProjName = fmt::format(
"{} {} Bin: {}",
875 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
876 PosteriorHist->SetDirectory(
nullptr);
877 PosteriorHist->GetXaxis()->SetTitle(
"Events");
878 PosteriorHistVec.push_back(std::move(PosteriorHist));
881 int nbinsx = hist->GetNbinsX();
882 int nbinsy = hist->GetNbinsY();
883 for (
int iy = 1; iy <= nbinsy; ++iy) {
884 for (
int ix = 1; ix <= nbinsx; ++ix) {
885 std::string ProjName = fmt::format(
"{} {} Bin: {}",
890 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
891 PosteriorHist->SetDirectory(
nullptr);
892 PosteriorHist->GetXaxis()->SetTitle(
"Events");
893 PosteriorHistVec.push_back(std::move(PosteriorHist));
898 int nbinsx = hist->GetNbinsX();
899 PosteriorHistVec.reserve(nbinsx);
900 for (
int i = 1; i <= nbinsx; ++i) {
901 std::string ProjName = fmt::format(
"{} {} Bin: {}",
906 auto PosteriorHist = std::make_unique<TH1D>(ProjName.c_str(), ProjName.c_str(), nBins, 1, -1);
907 PosteriorHist->SetDirectory(
nullptr);
908 PosteriorHist->GetXaxis()->SetTitle(
"Events");
909 PosteriorHistVec.push_back(std::move(PosteriorHist));
912 return PosteriorHistVec;
917 const std::vector<TDirectory*>& Directory,
918 const std::string& suffix,
919 const bool DebugHistograms,
920 const bool WriteHist) {
926 const int nDims =
SampleInfo[sample].Dimenstion;
927 const std::string Sample_Name =
SampleInfo[sample].Name;
928 Posterior_hist[sample] =
PerBinHistogram(Toys[sample][0].get(), sample, nDims, suffix);
929 auto PredictiveHist =
M3::Clone(Toys[sample][0].get());
931 PredictiveHist->Reset();
932 PredictiveHist->SetName((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
933 PredictiveHist->SetTitle((Sample_Name +
"_" + suffix +
"_PostPred").c_str());
934 PredictiveHist->SetDirectory(
nullptr);
935 PostPred[sample] = std::move(PredictiveHist);
940 #pragma omp parallel for
943 const int nDims =
SampleInfo[sample].Dimenstion;
944 auto& hist = Toys[sample][0];
945 for (
size_t iToy = 0; iToy < Toys[sample].size(); ++iToy) {
947 if(std::string(hist->ClassName()) ==
"TH2Poly") {
948 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
949 double content = Toys[sample][iToy]->GetBinContent(i);
953 int nbinsx = hist->GetNbinsX();
954 int nbinsy = hist->GetNbinsY();
955 for (
int iy = 1; iy <= nbinsy; ++iy) {
956 for (
int ix = 1; ix <= nbinsx; ++ix) {
957 int Bin = (iy-1) * nbinsx + (ix-1);
958 double content = Toys[sample][iToy]->GetBinContent(ix, iy);
964 int nbinsx = hist->GetNbinsX();
965 for (
int i = 1; i <= nbinsx; ++i) {
966 double content = Toys[sample][iToy]->GetBinContent(i);
975 const int nDims =
SampleInfo[sample].Dimenstion;
976 auto& hist = Toys[sample][0];
977 Directory[sample]->cd();
979 if(std::string(hist->ClassName()) ==
"TH2Poly") {
980 for (
int i = 1; i <= static_cast<TH2Poly*>(hist.get())->GetNumberOfBins(); ++i) {
981 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
983 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
984 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
987 int nbinsx = hist->GetNbinsX();
988 int nbinsy = hist->GetNbinsY();
989 for (
int iy = 1; iy <= nbinsy; ++iy) {
990 for (
int ix = 1; ix <= nbinsx; ++ix) {
991 int Bin = (iy-1) * nbinsx + (ix-1);
992 if (DebugHistograms) Posterior_hist[sample][Bin]->Write();
993 PostPred[sample]->SetBinContent(ix, iy, Posterior_hist[sample][Bin]->GetMean());
994 PostPred[sample]->SetBinError(ix, iy, Posterior_hist[sample][Bin]->GetRMS());
999 int nbinsx = hist->GetNbinsX();
1000 for (
int i = 1; i <= nbinsx; ++i) {
1001 PostPred[sample]->SetBinContent(i, Posterior_hist[sample][i-1]->GetMean());
1002 PostPred[sample]->SetBinError(i, Posterior_hist[sample][i-1]->GetRMS());
1003 if (DebugHistograms) Posterior_hist[sample][i-1]->Write();
1006 if(WriteHist) PostPred[sample]->Write();
1022 TStopwatch TempClock;
1025 auto DebugHistograms = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"DebugHistograms"],
false, __FILE__, __LINE__);
1026 auto StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__);
1028 TDirectory* PredictiveDir =
outputFile->mkdir(
"Predictive");
1029 std::vector<TDirectory*> SampleDirectories;
1034 SampleDirectories[sample] = PredictiveDir->mkdir(
SampleInfo[sample].Name.c_str());
1055 SampleDirectories[sample]->Close();
1056 delete SampleDirectories[sample];
1061 PredictiveDir->Close();
1062 delete PredictiveDir;
1067 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
1088 if (
auto h1 =
dynamic_cast<const TH1D*
>(DatHist)) {
1090 static_cast<const TH1D*
>(MCHist),
1091 static_cast<const TH1D*
>(W2Hist),
1096 if (
auto h2 =
dynamic_cast<const TH2D*
>(DatHist)) {
1098 static_cast<const TH2D*
>(MCHist),
1099 static_cast<const TH2D*
>(W2Hist),
1104 if (
auto h2p =
dynamic_cast<const TH2Poly*
>(DatHist)) {
1106 static_cast<const TH2Poly*
>(MCHist),
1107 static_cast<const TH2Poly*
>(W2Hist),
1122 for (
int i = 1; i <= DatHist->GetXaxis()->GetNbins(); ++i)
1124 const double data = DatHist->GetBinContent(i);
1125 const double mc = MCHist->GetBinContent(i);
1126 const double w2 = W2Hist->GetBinContent(i);
1135 const TH2Poly* MCHist,
1136 const TH2Poly* W2Hist,
1140 for (
int i = 1; i <= DatHist->GetNumberOfBins(); ++i)
1142 const double data = DatHist->GetBinContent(i);
1143 const double mc = MCHist->GetBinContent(i);
1144 const double w2 = W2Hist->GetBinContent(i);
1159 const int nBinsX = DatHist->GetXaxis()->GetNbins();
1160 const int nBinsY = DatHist->GetYaxis()->GetNbins();
1162 for (
int i = 1; i <= nBinsX; ++i)
1164 for (
int j = 1; j <= nBinsY; ++j)
1166 const double data = DatHist->GetBinContent(i, j);
1167 const double mc = MCHist->GetBinContent(i, j);
1168 const double w2 = W2Hist->GetBinContent(i, j);
1183 auto applyFluctuation = [&](
auto* f,
auto* h) {
1191 if (Hist->InheritsFrom(TH2Poly::Class())) {
1192 applyFluctuation(
static_cast<TH2Poly*
>(FluctHist),
static_cast<TH2Poly*
>(Hist));
1194 else if (Hist->InheritsFrom(TH2D::Class())) {
1195 applyFluctuation(
static_cast<TH2D*
>(FluctHist),
static_cast<TH2D*
>(Hist));
1197 else if (Hist->InheritsFrom(TH1D::Class())) {
1198 applyFluctuation(
static_cast<TH1D*
>(FluctHist),
static_cast<TH1D*
>(Hist));
1208 const std::vector<TDirectory*>& SampleDir) {
1212 auto make_matrix = [&](
double init = 0.0) {
1213 return std::vector<std::vector<double>>(
1215 std::vector<double>(
Ntoys, init));
1217 auto chi2_dat = make_matrix();
1218 auto chi2_mc = make_matrix();
1219 auto chi2_pred = make_matrix();
1220 auto chi2_rate_dat = make_matrix();
1221 auto chi2_rate_mc = make_matrix();
1222 auto chi2_rate_pred = make_matrix();
1225 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1237 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1238 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1241 auto PredFluctHist =
M3::Clone(PostPred_mc[iSample].get());
1254 chi2_rate_mc[iSample][iToy] =
CalcLLH(DrawFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1255 chi2_rate_pred[iSample][iToy] =
CalcLLH(PredFluctHist->Integral(),
MC_Hist_Toy[iSample][iToy]->Integral(),
W2_Hist_Toy[iSample][iToy]->Integral(), SampleHandler);
1270 MakeChi2Plots(chi2_mc,
"-2LLH (Draw Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_drawfluc_draw");
1271 MakeChi2Plots(chi2_pred,
"-2LLH (Pred Fluc, Draw)", chi2_dat,
"-2LLH (Data, Draw)", SampleDir,
"_predfluc_draw");
1274 MakeChi2Plots(chi2_rate_mc,
"-2LLH (Rate Draw Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_drawfluc_draw");
1275 MakeChi2Plots(chi2_rate_pred,
"-2LLH (Rate Pred Fluc, Draw)", chi2_rate_dat,
"-2LLH (Rate Data, Draw)", SampleDir,
"_rate_predfluc_draw");
1280 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1281 const std::vector<std::unique_ptr<TH1>>& PostPred_w,
1282 const std::vector<TDirectory*>& SampleDir) {
1284 MACH3LOG_INFO(
"{:<55} {:<10} {:<10} {:<10}",
"Sample",
"DataInt",
"MCInt",
"-2LLH");
1285 MACH3LOG_INFO(
"{:-<55} {:-<10} {:-<10} {:-<10}",
"",
"",
"",
"");
1287 SampleDir[iSample]->cd();
1288 ExtractLLH(Data_histogram[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(),
SampleInfo[iSample].SamHandler);
1289 PostPred_mc[iSample]->Write();
1296 const std::string& Chi2_x_title,
1297 const std::vector<std::vector<double>>& Chi2_y,
1298 const std::string& Chi2_y_title,
1299 const std::vector<TDirectory*>& SampleDir,
1300 const std::string Title) {
1303 SampleDir[iSample]->cd();
1306 std::vector<double> chi2_y_sample(
Ntoys);
1307 std::vector<double> chi2_x_per_sample(
Ntoys);
1309 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1310 chi2_y_sample[iToy] = Chi2_y[iSample][iToy];
1311 chi2_x_per_sample[iToy] = Chi2_x[iSample][iToy];
1314 const double min_val = std::min(*std::min_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1315 *std::min_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1316 const double max_val = std::max(*std::max_element(chi2_y_sample.begin(), chi2_y_sample.end()),
1317 *std::max_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
1319 auto chi2_hist = std::make_unique<TH2D>((
SampleInfo[iSample].Name+ Title).c_str(),
1321 50, min_val, max_val, 50, min_val, max_val);
1322 chi2_hist->SetDirectory(
nullptr);
1323 chi2_hist->GetXaxis()->SetTitle(Chi2_x_title.c_str());
1324 chi2_hist->GetYaxis()->SetTitle(Chi2_y_title.c_str());
1326 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1327 chi2_hist->Fill(chi2_x_per_sample[iToy], chi2_y_sample[iToy]);
1339 bool StudyBeta = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"StudyBetaParameters"],
true, __FILE__, __LINE__ );
1340 if (StudyBeta ==
false)
return;
1343 TDirectory* BetaDir = PredictiveDir->mkdir(
"BetaParameters");
1349 DirBeta[sample] = BetaDir->mkdir(
SampleInfo[sample].Name.c_str());
1354 const int nDims =
SampleInfo[iSample].Dimenstion;
1356 TH1* RefHist =
Data_Hist[iSample].get();
1357 BetaHist[iSample] =
PerBinHistogram(RefHist, iSample, nDims,
"Beta_Parameter");
1359 for (
size_t i = 0; i < BetaHist[iSample].size(); ++i) {
1360 BetaHist[iSample][i]->GetXaxis()->SetTitle(
"beta parameter");
1366 #pragma omp parallel for
1369 const int nDims =
SampleInfo[iSample].Dimenstion;
1370 const auto likelihood =
SampleInfo[iSample].SamHandler->GetTestStatistic();
1371 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1373 if(std::string(
Data_Hist[iSample]->ClassName()) ==
"TH2Poly") {
1374 for (
int i = 1; i <= static_cast<TH2Poly*>(
Data_Hist[iSample].get())->GetNumberOfBins(); ++i) {
1375 const double Data =
Data_Hist[iSample]->GetBinContent(i);
1376 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1377 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1383 const int nX =
Data_Hist[iSample]->GetNbinsX();
1384 const int nY =
Data_Hist[iSample]->GetNbinsY();
1385 for (
int iy = 1; iy <= nY; ++iy) {
1386 for (
int ix = 1; ix <= nX; ++ix) {
1387 const int FlatBin = (iy-1) * nX + (ix-1);
1389 const double Data =
Data_Hist[iSample]->GetBinContent(ix, iy);
1390 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1391 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1394 BetaHist[iSample][FlatBin]->Fill(BetaParam,
ReweightWeight[iToy]);
1399 int nbinsx =
Data_Hist[iSample]->GetNbinsX();
1400 for (
int ix = 1; ix <= nbinsx; ++ix) {
1402 const double Data =
Data_Hist[iSample]->GetBinContent(ix);
1403 const double MC =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1404 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix);
1415 for (
size_t iBin = 0; iBin < BetaHist[iSample].size(); iBin++) {
1416 DirBeta[iSample]->cd();
1417 BetaHist[iSample][iBin]->Write();
1419 DirBeta[iSample]->Close();
1420 delete DirBeta[iSample];
1425 PredictiveDir->cd();
1433 const double llh =
CalcLLH(DatHist, MCHist, W2Hist, SampleHandler);
1434 std::stringstream ss;
1435 ss <<
"_2LLH=" << llh;
1436 MCHist->SetTitle((std::string(MCHist->GetTitle())+ss.str()).c_str());
1437 MACH3LOG_INFO(
"{:<55} {:<10.2f} {:<10.2f} {:<10.2f}", MCHist->GetName(), DatHist->Integral(), MCHist->Integral(), llh);
1445 int originalErrorWarning = gErrorIgnoreLevel;
1446 gErrorIgnoreLevel = kFatal;
1449 auto TempLine = std::make_unique<TLine>(DataRate, Histogram->GetMinimum(), DataRate, Histogram->GetMaximum());
1450 TempLine->SetLineColor(kRed);
1451 TempLine->SetLineWidth(2);
1453 auto Fitter = std::make_unique<TF1>(
"Fit",
"gaus", Histogram->GetBinLowEdge(1), Histogram->GetBinLowEdge(Histogram->GetNbinsX()+1));
1454 Histogram->Fit(Fitter.get(),
"RQ");
1455 Fitter->SetLineColor(kRed-5);
1458 for (
int z = 0; z < Histogram->GetNbinsX(); ++z) {
1459 const double xvalue = Histogram->GetBinCenter(z+1);
1460 if (xvalue >= DataRate) {
1461 Above += Histogram->GetBinContent(z+1);
1464 const double pvalue = Above/Histogram->Integral();
1465 TLegend Legend(0.4, 0.75, 0.98, 0.90);
1466 Legend.SetFillColor(0);
1467 Legend.SetFillStyle(0);
1468 Legend.SetLineWidth(0);
1469 Legend.SetLineColor(0);
1470 Legend.AddEntry(TempLine.get(), Form(
"Data, %.0f, p-value=%.2f", DataRate, pvalue),
"l");
1471 Legend.AddEntry(Histogram, Form(
"MC, #mu=%.1f#pm%.1f", Histogram->GetMean(), Histogram->GetRMS()),
"l");
1472 Legend.AddEntry(Fitter.get(), Form(
"Gauss, #mu=%.1f#pm%.1f", Fitter->GetParameter(1), Fitter->GetParameter(2)),
"l");
1473 std::string TempTitle = std::string(Histogram->GetName());
1474 TempTitle +=
"_canv";
1475 TCanvas TempCanvas(TempTitle.c_str(), TempTitle.c_str(), 1024, 1024);
1476 TempCanvas.SetGridx();
1477 TempCanvas.SetGridy();
1478 TempCanvas.SetRightMargin(0.03);
1479 TempCanvas.SetBottomMargin(0.08);
1480 TempCanvas.SetLeftMargin(0.10);
1481 TempCanvas.SetTopMargin(0.06);
1484 TempLine->Draw(
"same");
1485 Fitter->Draw(
"same");
1486 Legend.Draw(
"same");
1489 gErrorIgnoreLevel = originalErrorWarning;
1494 const std::vector<TDirectory*>& SampleDirectories)
const {
1498 std::string Title =
"EventHist: ";
1507 EventHist[iSample] = std::make_unique<TH1D>(Title.c_str(), Title.c_str(), 100, 1, -1);
1508 EventHist[iSample]->SetDirectory(
nullptr);
1509 EventHist[iSample]->GetXaxis()->SetTitle(
"Total event rate");
1510 EventHist[iSample]->GetYaxis()->SetTitle(
"Counts");
1511 EventHist[iSample]->SetLineWidth(2);
1516 #pragma omp parallel for
1519 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1520 double Count = Toys[iSample][iToy]->Integral();
1521 EventHist[iSample]->Fill(Count);
1526 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1527 double TotalCount = 0.0;
1529 TotalCount += Toys[iSample][iToy]->Integral();
1534 double DataRate = 0.0;
1537 #pragma omp parallel for reduction(+:DataRate)
1540 DataRates[i] =
Data_Hist[i]->Integral();
1541 DataRate += DataRates[i];
1546 SampleDirectories[SampleNum]->cd();
1555 const std::vector<std::unique_ptr<TH1>>& PostPred_mc,
1556 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1585 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1588 double DataRate = 0.0;
1589 double BinsRate = 0.0;
1590 double TotalLLH = 0.0;
1592 #pragma omp parallel for reduction(+:DataRate, BinsRate, TotalLLH)
1596 auto SampleHandler =
SampleInfo[i].SamHandler;
1598 DataRate += h->Integral();
1599 if (
auto h1 =
dynamic_cast<TH1D*
>(h)) {
1600 BinsRate += h1->GetNbinsX();
1601 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(h)) {
1602 BinsRate += h2->GetNbinsX() * h2->GetNbinsY();
1603 }
else if (
auto h2poly =
dynamic_cast<TH2Poly*
>(h)) {
1604 BinsRate += h2poly->GetNumberOfBins();
1608 TotalLLH +=
CalcLLH(
Data_Hist[i].get(), PostPred_mc[i].get(), PostPred_w[i].get(), SampleHandler);
1613 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of events: {:.2f}", EventRateBIC);
1614 MACH3LOG_INFO(
"Calculated Bayesian Information Criterion using global number of bins: {:.2f}", BinBasedBIC);
1615 MACH3LOG_INFO(
"Additional info: NModelParams: {}, DataRate: {:.2f}, BinsRate: {:.2f}",
NModelParams, DataRate, BinsRate);
1621 const std::vector<std::unique_ptr<TH1>>& PostPred_w) {
1625 double TotalLLH = 0.0;
1628 #pragma omp parallel for reduction(+:Dbar)
1632 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1633 TotalLLH +=
CalcLLH(
Data_Hist[iSample].get(), PostPred_mc[iSample].get(), PostPred_w[iSample].get(), SampleHandler);
1634 double LLH_temp = 0.;
1635 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
1641 Dbar = Dbar /
Ntoys;
1644 const double Dhat = TotalLLH;
1647 const double p_D = std::fabs(Dbar - Dhat);
1650 const double DIC_stat = Dhat + 2 * p_D;
1651 MACH3LOG_INFO(
"Effective number of parameters following DIC formalism is equal to: {:.2f}", p_D);
1660 double& mean_llh_squared,
1661 double& sum_exp_llh) {
1664 double LLH_temp = -neg_LLH_temp;
1666 mean_llh += LLH_temp;
1667 mean_llh_squared += LLH_temp * LLH_temp;
1668 sum_exp_llh += std::exp(LLH_temp);
1674 const unsigned int Ntoys,
double& lppd,
double& p_WAIC) {
1678 mean_llh_squared /=
Ntoys;
1679 sum_exp_llh /=
Ntoys;
1680 sum_exp_llh = std::log(sum_exp_llh);
1683 lppd += sum_exp_llh;
1686 p_WAIC += mean_llh_squared - (mean_llh * mean_llh);
1699 #pragma omp parallel for reduction(+:lppd, p_WAIC)
1702 auto SampleHandler =
SampleInfo[iSample].SamHandler;
1705 if (
auto h2poly =
dynamic_cast<TH2Poly*
>(hData)) {
1707 for (
int i = 1; i <= h2poly->GetNumberOfBins(); ++i) {
1708 const double data =
Data_Hist[iSample]->GetBinContent(i);
1709 double mean_llh = 0.;
1710 double sum_exp_llh = 0;
1711 double mean_llh_squared = 0.;
1713 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1714 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(i);
1715 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(i);
1717 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1722 }
else if (
auto h2 =
dynamic_cast<TH2D*
>(hData)) {
1724 for (
int ix = 1; ix <= h2->GetNbinsX(); ++ix) {
1725 for (
int iy = 1; iy <= h2->GetNbinsY(); ++iy) {
1726 const double data = hData->GetBinContent(ix, iy);
1727 double mean_llh = 0.;
1728 double mean_llh_squared = 0.;
1729 double sum_exp_llh = 0.;
1730 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1731 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1732 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(ix, iy);
1734 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1740 }
else if (
auto h1 =
dynamic_cast<TH1D*
>(hData)) {
1742 for (
int iBin = 1; iBin <= h1->GetNbinsX(); ++iBin) {
1743 const double data = hData->GetBinContent(iBin);
1744 double mean_llh = 0.;
1745 double mean_llh_squared = 0.;
1746 double sum_exp_llh = 0.;
1747 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
1748 const double mc =
MC_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
1749 const double w2 =
W2_Hist_Toy[iSample][iToy]->GetBinContent(iBin);
1752 double neg_LLH_temp = SampleHandler->GetTestStatLLH(data, mc, w2);
1761 double WAIC = -2 * (lppd - p_WAIC);
1762 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, 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, 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 responsible for handling of systematic error parameters. Capable of using PCA or using ada...
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 GetParInit(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 RunPredictiveAnalysis()
Main routine responsible for producing posterior predictive distributions and $p$-value.
bool LoadToys()
Load existing toys.
void ProduceSpectra(const std::vector< std::vector< std::vector< std::unique_ptr< TH1D >>>> &Toys, const std::vector< TDirectory * > &Director, const std::string suffix) const
Produce Violin style spectra.
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 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 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.
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.