16 FullLLH = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"FullLLH"],
false, __FILE__, __LINE__ );
20 Ntoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);
37 auto DoNotThrowLegacyCov = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"DoNotThrowLegacyCov"], {}, __FILE__, __LINE__);
39 for (
size_t i = 0; i < DoNotThrowLegacyCov.size(); ++i) {
64 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
68 MACH3LOG_ERROR(
"Sample {} do not inherit from SampleHandlerFD this is not implemented",
samples[iPDF]->GetTitle());
72 if(
samples[iPDF]->GetNsamples() > 1){
88 for (
size_t iPDF = 0; iPDF <
samples.size(); ++iPDF) {
89 for (
int subSampleIndex = 0; subSampleIndex <
samples[iPDF]->GetNsamples(); ++subSampleIndex) {
119 MACH3LOG_INFO(
"You've chosen to run Prior Predictive Distribution");
121 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
132 MACH3LOG_ERROR(
"Yaml configs in previous chain and current one are different", PosteriorFileName);
138 MACH3LOG_ERROR(
"Found {} ParmaterHandler inheriting from ParameterHandlerGeneric, I can accept at most 1", counter);
147 auto ThrowParamGroupOnly = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowParamGroupOnly"], {}, __FILE__, __LINE__);
149 auto ParameterOnlyToVaryString = GetFromManager<std::vector<std::string>>(
fitMan->
raw()[
"Predictive"][
"ThrowSinlgeParams"], {}, __FILE__, __LINE__);
151 if (!ThrowParamGroupOnly.empty() && !ParameterOnlyToVaryString.empty()) {
152 MACH3LOG_ERROR(
"Can't use ThrowParamGroupOnly and ThrowSinlgeParams at the same time");
156 if (!ParameterOnlyToVaryString.empty()) {
157 MACH3LOG_INFO(
"I will throw only: {}", fmt::join(ParameterOnlyToVaryString,
", "));
158 std::vector<int> ParameterVary(ParameterOnlyToVaryString.size());
160 for (
size_t i = 0; i < ParameterOnlyToVaryString.size(); ++i) {
163 MACH3LOG_ERROR(
"Can't proceed if param {} is missing", ParameterOnlyToVaryString[i]);
169 MACH3LOG_INFO(
"I have following parameter groups: {}", fmt::join(UniqueParamGroup,
", "));
170 if (ThrowParamGroupOnly.empty()) {
173 std::unordered_set<std::string> throwOnlySet(ThrowParamGroupOnly.begin(), ThrowParamGroupOnly.end());
176 for (
const auto& group : UniqueParamGroup) {
177 if (throwOnlySet.find(group) == throwOnlySet.end()) {
182 MACH3LOG_INFO(
"I will vary: {}", fmt::join(ThrowParamGroupOnly,
", "));
193 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
195 TFile* file =
TFile::Open(PosteriorFileName.c_str(),
"READ");
196 TDirectory* ToyDir =
nullptr;
197 if (!file || file->IsZombie()) {
201 if ((ToyDir = file->GetDirectory(
"Toys"))) {
202 MACH3LOG_INFO(
"Found toys in Posterior file will attempt toy reading");
211 TTree* PenaltyTree =
static_cast<TTree*
>(file->Get(
"ToySummary"));
219 Ntoys =
static_cast<int>(PenaltyTree->GetEntries());
220 int ConfigNtoys = Get<int>(
fitMan->
raw()[
"Predictive"][
"Ntoy"], __FILE__, __LINE__);;
221 if (
Ntoys != ConfigNtoys) {
222 MACH3LOG_WARN(
"Found different number of toys in saved file than asked to run!");
231 double Penalty = 0, Weight = 1;
232 PenaltyTree->SetBranchAddress(
"Penalty", &Penalty);
233 PenaltyTree->SetBranchAddress(
"Weight", &Weight);
234 PenaltyTree->SetBranchAddress(
"NModelParams", &
NModelParams);
236 for (
int i = 0; i <
Ntoys; ++i) {
237 PenaltyTree->GetEntry(i);
250 TH1D* DataHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleNames[sample] +
"_data").c_str()));
253 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleNames[sample] +
"_mc").c_str()));
256 TH1D* W2Hist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleNames[sample] +
"_w2").c_str()));
261 for (
int iToy = 0; iToy <
Ntoys; ++iToy)
266 TH1D* MCHist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleNames[sample] +
"_mc_" + std::to_string(iToy)).c_str()));
267 TH1D* W2Hist1D =
static_cast<TH1D*
>(ToyDir->Get((
SampleNames[sample] +
"_w2_" + std::to_string(iToy)).c_str()));
289 auto PosteriorFileName = Get<std::string>(
fitMan->
raw()[
"Predictive"][
"PosteriorFile"], __FILE__, __LINE__);
294 double Penalty = 0, Weight = 1;
297 TTree *ToyTree =
new TTree(
"ToySummary",
"ToySummary");
298 ToyTree->Branch(
"Penalty", &Penalty,
"Penalty/D");
299 ToyTree->Branch(
"Weight", &Weight,
"Weight/D");
300 ToyTree->Branch(
"Draw", &Draw,
"Draw/I");
301 ToyTree->Branch(
"NModelParams", &
NModelParams,
"NModelParams/I");
303 TDirectory* ToyDirectory =
outputFile->mkdir(
"Toys");
306 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
309 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNsamples(); ++SampleIndex)
312 TH1D* DataHist1D =
static_cast<TH1D*
>(MaCh3Sample->GetDataHist(1));
314 Data_Hist[iPDF]->Write((MaCh3Sample->GetTitle() +
"_data").c_str());
316 TH1D* MCHist1D =
static_cast<TH1D*
>(MaCh3Sample->GetMCHist(1));
318 MCHist1D->Write((MaCh3Sample->GetTitle() +
"_mc").c_str());
320 TH1D* W2Hist1D =
static_cast<TH1D*
>(MaCh3Sample->GetW2Hist(1));
322 W2Hist1D->Write((MaCh3Sample->GetTitle() +
"_w2").c_str());
328 std::vector<std::vector<double>> branch_vals(
systematics.size());
329 std::vector<std::vector<std::string>> branch_name(
systematics.size());
331 TChain* PosteriorFile =
new TChain(
"posteriors");
332 PosteriorFile->Add(PosteriorFileName.c_str());
333 unsigned int Step = 0;
334 PosteriorFile->SetBranchAddress(
"step", &Step);
336 if (PosteriorFile->GetBranch(
"Weight")) {
337 PosteriorFile->SetBranchStatus(
"Weight",
true);
338 PosteriorFile->SetBranchAddress(
"Weight", &Weight);
345 systematics[s]->MatchMaCh3OutputBranches(PosteriorFile, branch_vals[s], branch_name[s]);
348 auto burn_in = Get<unsigned int>(
fitMan->
raw()[
"Predictive"][
"BurnInSteps"], __FILE__, __LINE__);
351 const unsigned int maxNsteps =
static_cast<unsigned int>(PosteriorFile->GetMaximum(
"step"));
352 if(burn_in >= maxNsteps)
354 MACH3LOG_ERROR(
"You are running on a chain shorter than burn in cut");
355 MACH3LOG_ERROR(
"Maximal value of nSteps: {}, burn in cut {}", maxNsteps, burn_in);
361 TStopwatch TempClock;
363 for(
int i = 0; i <
Ntoys; i++)
365 if( i % (
Ntoys/10) == 0) {
375 while(Step < burn_in){
376 entry =
random->Integer(
static_cast<unsigned int>(PosteriorFile->GetEntries()));
377 PosteriorFile->GetEntry(entry);
403 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++) {
407 for (
size_t iPDF = 0; iPDF <
samples.size(); iPDF++)
410 for (
int SampleIndex = 0; SampleIndex < MaCh3Sample->GetNsamples(); ++SampleIndex)
412 TH1D* MCHist1D =
static_cast<TH1D*
>(MaCh3Sample->GetMCHist(1));
413 MC_Hist_Toy[iPDF][i] =
M3::Clone(MCHist1D, MaCh3Sample->GetTitle() +
"_mc_" + std::to_string(i));
416 TH1D* W2Hist1D =
static_cast<TH1D*
>(MaCh3Sample->GetW2Hist(1));
417 W2_Hist_Toy[iPDF][i] =
M3::Clone(W2Hist1D, MaCh3Sample->GetTitle() +
"_w2_" + std::to_string(i));
426 delete PosteriorFile;
427 ToyDirectory->Close();
434 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
439 const std::string suffix) {
443 #pragma omp parallel for collapse(2)
446 for (
int toy = 0; toy <
Ntoys; ++toy) {
447 double max_val = Toys[sample][toy]->GetMaximum();
448 MaxValue[sample] = std::max(MaxValue[sample], max_val);
455 TH1D* refHist = Toys[sample][0].get();
457 const int n_bins_x = refHist->GetNbinsX();
458 std::vector<double> x_bin_edges(n_bins_x + 1);
459 for (
int b = 0; b <= n_bins_x; ++b) {
460 x_bin_edges[b] = refHist->GetXaxis()->GetBinLowEdge(b + 1);
463 x_bin_edges[n_bins_x] = refHist->GetXaxis()->GetBinUpEdge(n_bins_x);
465 constexpr
int n_bins_y = 400;
466 constexpr
double y_min = 0.0;
467 const double y_max = MaxValue[sample] * 1.05;
470 Spectra[sample] = std::make_unique<TH2D>(
473 n_bins_x, x_bin_edges.data(),
474 n_bins_y, y_min, y_max
477 Spectra[sample]->SetDirectory(
nullptr);
478 Spectra[sample]->Sumw2(
true);
482 #pragma omp parallel for
485 for (
int toy = 0; toy <
Ntoys; ++toy) {
495 const std::string& Sample_Name,
496 const std::string& suffix,
497 const bool DebugHistograms) {
499 constexpr
int nXBins = 100;
500 int nbinsx = Toys[0]->GetNbinsX();
502 auto PredictiveHist = std::make_unique<TH1D>((Sample_Name +
"_" + suffix +
"_PostPred").c_str(),
503 (Sample_Name +
"_" + suffix +
"_PostPred").c_str(),
504 nbinsx, Toys[0]->GetXaxis()->GetXbins()->GetArray());
505 PredictiveHist->SetDirectory(
nullptr);
507 for (
int i = 1; i <= nbinsx; ++i) {
508 double x_low = Toys[0]->GetXaxis()->GetBinLowEdge(i);
509 double x_high = Toys[0]->GetXaxis()->GetBinUpEdge(i);
510 TString projName = TString::Format(
"%s %s X: [%.3f, %.3f]", Sample_Name.c_str(), suffix.c_str(), x_low, x_high);
511 auto PosteriorHist = std::make_unique<TH1D>(projName, projName, nXBins, 1, -1);
512 PosteriorHist->SetDirectory(
nullptr);
514 for (
size_t iToy = 0; iToy < Toys.size(); ++iToy) {
515 const double Content = Toys[iToy]->GetBinContent(i);
519 if(DebugHistograms) PosteriorHist->Write();
521 const double nMean = PosteriorHist->GetMean();
522 const double nMeanError = PosteriorHist->GetRMS();
524 PredictiveHist->SetBinContent(i, nMean);
525 PredictiveHist->SetBinError(i, nMeanError);
528 PredictiveHist->Write();
529 return PredictiveHist;
537 TStopwatch TempClock;
540 auto DebugHistograms = GetFromManager<bool>(
fitMan->
raw()[
"Predictive"][
"DebugHistograms"],
false, __FILE__, __LINE__);
542 TDirectory* PredictiveDir =
outputFile->mkdir(
"Predictive");
543 std::vector<TDirectory*> SampleDirectories;
547 SampleDirectories[sample] = PredictiveDir->mkdir(
SampleNames[sample].c_str());
555 SampleDirectories[sample]->cd();
556 Spectra_mc[sample]->Write();
569 SampleDirectories[sample]->Close();
570 delete SampleDirectories[sample];
573 PredictiveDir->Close();
574 delete PredictiveDir;
579 MACH3LOG_INFO(
"{} took {:.2f}s to finish for {} toys", __func__, TempClock.RealTime(),
Ntoys);
584 const std::unique_ptr<TH1D>& MCHist,
585 const std::unique_ptr<TH1D>& W2Hist,
589 for (
int i = 1; i <= DatHist->GetXaxis()->GetNbins(); ++i)
591 const double data = DatHist->GetBinContent(i);
592 const double mc = MCHist->GetBinContent(i);
593 const double w2 = W2Hist->GetBinContent(i);
603 const std::vector<TDirectory*>& SampleDir) {
607 std::vector<std::vector<double>> chi2_dat_vec(
Ntoys);
608 std::vector<std::vector<double>> chi2_mc_vec(
Ntoys);
609 std::vector<std::vector<double>> chi2_pred_vec(
Ntoys);
611 for(
int iToy = 0; iToy <
Ntoys; iToy++) {
625 auto PredFluctHist =
M3::Clone(PostPred_mc[iSample].get());
633 chi2_dat_vec[iToy].back() += chi2_dat_vec[iToy][iSample];
634 chi2_mc_vec[iToy].back() += chi2_mc_vec[iToy][iSample];
635 chi2_pred_vec[iToy].back() += chi2_pred_vec[iToy][iSample];
639 MakeChi2Plots(chi2_mc_vec,
"-2LLH (Draw Fluc, Draw)", chi2_dat_vec,
"-2LLH (Data, Draw)", SampleDir,
"_drawfluc_draw");
640 MakeChi2Plots(chi2_pred_vec,
"-2LLH (Pred Fluc, Draw)", chi2_dat_vec,
"-2LLH (Data, Draw)", SampleDir,
"_predfluc_draw");
645 const std::string& Chi2_x_title,
646 const std::vector<std::vector<double>>& Chi2_y,
647 const std::string& Chi2_y_title,
648 const std::vector<TDirectory*>& SampleDir,
649 const std::string Title) {
652 SampleDir[iSample]->cd();
655 std::vector<double> chi2_y_sample(
Ntoys);
656 std::vector<double> chi2_x_per_sample(
Ntoys);
658 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
659 chi2_y_sample[iToy] = Chi2_y[iToy][iSample];
660 chi2_x_per_sample[iToy] = Chi2_x[iToy][iSample];
663 const double min_val = std::min(*std::min_element(chi2_y_sample.begin(), chi2_y_sample.end()),
664 *std::min_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
665 const double max_val = std::max(*std::max_element(chi2_y_sample.begin(), chi2_y_sample.end()),
666 *std::max_element(chi2_x_per_sample.begin(), chi2_x_per_sample.end()));
668 auto chi2_hist = std::make_unique<TH2D>((
SampleNames[iSample] + Title).c_str(),
670 100, min_val, max_val, 100, min_val, max_val);
671 chi2_hist->SetDirectory(
nullptr);
672 chi2_hist->GetXaxis()->SetTitle(Chi2_x_title.c_str());
673 chi2_hist->GetYaxis()->SetTitle(Chi2_y_title.c_str());
675 for (
int iToy = 0; iToy <
Ntoys; ++iToy) {
676 chi2_hist->Fill(chi2_x_per_sample[iToy], chi2_y_sample[iToy]);
MaCh3Plotting::PlottingManager * man
void MakeFluctuatedHistogramAlternative(TH1D *FluctHist, TH1D *PolyHist, TRandom3 *rand)
Make Poisson fluctuation of TH1D hist using slow method which is only for cross-check.
void FastViolinFill(TH2D *violin, TH1D *hist_1d)
KS: Fill Violin histogram with entry from a toy.
void Get2DBayesianpValue(TH2D *Histogram)
Calculates the 2D Bayesian p-value and generates a visualization.
bool compareYAMLNodes(const YAML::Node &node1, const YAML::Node &node2)
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.
std::vector< SampleHandlerBase * > samples
Sample holder.
TFile * outputFile
Output.
manager * fitMan
The manager.
std::string AlgorithmName
Name of fitting algorithm that is being used.
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 for MaCh3 errors.
Class responsible for handling of systematic error parameters with different types defined in the con...
void SetParamters()
This set some params to prior value this way you can evaluate errors from subset of errors.
std::vector< double > PenaltyTerm
Penalty term values for each toy by default 0.
std::vector< std::string > SampleNames
Name of a single sample.
std::vector< std::unique_ptr< TH1D > > MC_Nom_Hist
Vector of MC histograms.
virtual ~PredictiveThrower()
Destructor.
bool FullLLH
KS: Use Full LLH or only sample contribution based on discussion with Asher we almost always only wan...
std::unique_ptr< TH1D > MakePredictive(const std::vector< std::unique_ptr< TH1D >> &Toys, const std::string &Sample_Name, const std::string &suffix, const bool DebugHistograms)
Produce posterior predictive distribution.
void RunPredictiveAnalysis()
Main routine responsible for producing posterior predictive distributions and $p$-value.
bool LoadToys()
Load existing toys.
PredictiveThrower(manager *const fitMan)
Constructor.
std::vector< std::vector< std::unique_ptr< TH1D > > > W2_Hist_Toy
std::unordered_set< int > ParameterOnlyToVary
KS: Index of parameters groups that will be varied.
bool Is_PriorPredictive
Whether it is Prior or Posterior predictive.
std::vector< std::string > ParameterGroupsNotVaried
KS: Names of parameter groups that will not be varied.
std::vector< std::unique_ptr< TH1D > > W2_Nom_Hist
Vector of W2 histograms.
int NModelParams
KS: Count total number of model parameters which can be used for stuff like BIC.
int Ntoys
Number of toys we are generating analysing.
void SetupToyGeneration()
Setup useful variables etc before stating toy generation.
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.
std::vector< int > SampleObjectMap
Maps if sample with given SampleHandler, useful if we have more than one sample in single object.
void SetupSampleInformation()
Setup sample information.
void PosteriorPredictivepValue(const std::vector< std::unique_ptr< TH1D >> &PostPred_mc, const std::vector< TDirectory * > &SampleDir)
Calculate Posterior Predictive $p$-value.
int TotalNumberOfSamples
Number of toys we are generating analysing.
void ProduceToys()
Produce toys by throwing from MCMC.
std::vector< std::unique_ptr< TH2D > > ProduceSpectra(const std::vector< std::vector< std::unique_ptr< TH1D >>> &Toys, const std::string suffix)
Produce Violin style spectra.
ParameterHandlerGeneric * ModelSystematic
Pointer to El Generico.
std::vector< double > ReweightWeight
Reweighting factors applied for each toy, by default 1.
double GetLLH(const std::unique_ptr< TH1D > &DatHist, const std::unique_ptr< TH1D > &MCHist, const std::unique_ptr< TH1D > &W2Hist, SampleHandlerBase *SampleHandler)
Helper functions to calculate likelihoods using TH1D.
std::vector< std::unique_ptr< TH1D > > Data_Hist
Vector of Data histograms.
std::vector< std::vector< std::unique_ptr< TH1D > > > MC_Hist_Toy
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
The manager class is responsible for managing configurations and settings.
YAML::Node const & raw()
Return config.
int GetNumParams() const
Get total number of parameters.
int GetParIndex(const std::string &name) const
Get index based on name.
double GetParInit(const int i) const
Get prior parameter value.
std::vector< std::string > GetUniqueParameterGroups()
KS: Get names of all unique parameter groups.
YAML::Node GetConfig() const
Getter to return a copy of the YAML node.
void SetParProp(const int i, const double val)
Set proposed parameter value.
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.
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....
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.
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.