16 #include "TStopwatch.h"
48 std::sort(arr, arr+size);
51 return (arr[(size-1)/2] + arr[size/2])/2.0;
58 if(std::isnan(var) || !std::isfinite(var)) var = cap;
90 std::vector<unsigned int> BurnIn(
Nchains);
91 std::vector<unsigned int> nEntries(
Nchains);
92 std::vector<int> nBranches(
Nchains);
93 std::vector<unsigned int> step(
Nchains);
98 std::unique_ptr<MCMCProcessor> Processor;
102 for (
int m = 0; m <
Nchains; m++)
105 if (!std::filesystem::exists(
MCMCFile[m])) {
109 TChain* Chain =
new TChain(
"posteriors");
111 nEntries[m] =
static_cast<unsigned int>(Chain->GetEntries());
114 BurnIn[m] = nEntries[m]/5;
117 TObjArray* brlis = Chain->GetListOfBranches();
120 nBranches[m] = brlis->GetEntries();
123 Chain->SetBranchStatus(
"*",
false);
125 std::vector<TString> SampleLLH;
126 std::vector<TString> SystLLH;
129 Processor = std::make_unique<MCMCProcessor>(
MCMCFile[m]);
130 Processor->Initialise();
131 nDraw = Processor->GetNParams();
132 SampleLLH = Processor->GetSampleBranchNames();
133 SystLLH = Processor->GetSystBranchNames();
134 nDraw =
nDraw +
static_cast<int>(SampleLLH.size()) +
static_cast<int>(SystLLH.size());
139 Chain->SetBranchStatus(
"*",
false);
143 for (
int i = 0; i < Processor->GetNParams(); i++)
145 TString bname = Processor->GetBranchNames()[i];
152 Chain->SetBranchStatus(bname,
true);
154 if (!Chain->GetBranch(bname)) {
155 MACH3LOG_ERROR(
"Branch '{}' does not exist in the TChain", bname.Data());
161 for (
size_t i = 0; i < SampleLLH.size(); ++i) {
162 TString bname = SampleLLH[i];
163 Chain->SetBranchStatus(bname,
true);
170 for (
size_t i = 0; i < SystLLH.size(); ++i) {
171 TString bname = SystLLH[i];
172 Chain->SetBranchStatus(bname,
true);
180 Chain->SetBranchStatus(
"step",
true);
181 Chain->SetBranchAddress(
"step", &step[m]);
185 if(nBranches[m] != nBranches[0])
187 MACH3LOG_ERROR(
"Ups, something went wrong, chain {} called {} has {} branches, while 0 called {} has {} branches", m,
MCMCFile[m], nBranches[m],
MCMCFile[0], nBranches[0]);
188 MACH3LOG_ERROR(
"All chains should have the same number of branches");
196 for(
int i = 0; i <
Ntoys; i++)
204 std::vector<double> branch_values(
nDraw, 0.0);
205 for (
int j = 0; j <
nDraw; ++j) {
206 Chain->SetBranchAddress(
BranchNames[j].Data(), &branch_values[j]);
210 if(BurnIn[m] >= nEntries[m])
212 MACH3LOG_ERROR(
"You are running on a chain shorter than BurnIn cut");
213 MACH3LOG_ERROR(
"Number of entries {} BurnIn cut {}", nEntries[m], BurnIn[m]);
219 for (
int i = 0; i <
Ntoys; i++)
224 Chain->GetEntry(entry);
228 if (step[m] < BurnIn[m]) {
240 for (
int j = 0; j <
nDraw; ++j) {
241 Draws[m][i][j] = branch_values[j];
253 #pragma omp parallel for
255 for(
int j = 0; j <
nDraw; j++)
258 std::vector<double> TempDraws(
static_cast<size_t>(
Ntoys) *
Nchains);
259 for(
int m = 0; m <
Nchains; m++)
261 for(
int i = 0; i <
Ntoys; i++)
264 TempDraws[im] =
Draws[m][i][j];
271 #pragma omp parallel for collapse(3)
273 for(
int m = 0; m <
Nchains; m++)
275 for(
int i = 0; i <
Ntoys; i++)
277 for(
int j = 0; j <
nDraw; j++)
284 MACH3LOG_INFO(
"Finished calculating Toys, it took {:.2f}s to finish", clock.RealTime());
298 std::vector<unsigned int> BurnIn(
Nchains);
299 std::vector<unsigned int> nEntries(
Nchains);
300 std::vector<int> nBranches(
Nchains);
301 std::vector<unsigned int> step(
Nchains);
306 std::unique_ptr<MCMCProcessor> Processor;
310 for (
int m = 0; m <
Nchains; m++)
313 if (!std::filesystem::exists(
MCMCFile[m])) {
317 TChain* Chain =
new TChain(
"posteriors");
320 nEntries[m] =
static_cast<unsigned int>(Chain->GetEntries());
328 BurnIn[m] = nEntries[m]/5;
331 TObjArray* brlis = Chain->GetListOfBranches();
334 nBranches[m] = brlis->GetEntries();
337 Chain->SetBranchStatus(
"*",
false);
339 std::vector<TString> SampleLLH;
340 std::vector<TString> SystLLH;
343 Processor = std::make_unique<MCMCProcessor>(
MCMCFile[m]);
344 Processor->Initialise();
345 nDraw = Processor->GetNParams();
346 SampleLLH = Processor->GetSampleBranchNames();
347 SystLLH = Processor->GetSystBranchNames();
348 nDraw =
nDraw +
static_cast<int>(SampleLLH.size()) +
static_cast<int>(SystLLH.size());
353 Chain->SetBranchStatus(
"*",
false);
357 for (
int i = 0; i < Processor->GetNParams(); i++)
359 TString bname = Processor->GetBranchNames()[i];
366 Chain->SetBranchStatus(bname,
true);
369 if (!Chain->GetBranch(bname)) {
370 MACH3LOG_ERROR(
"Branch '{}' does not exist in the TChain", bname.Data());
376 for (
size_t i = 0; i < SampleLLH.size(); ++i) {
377 TString bname = SampleLLH[i];
378 Chain->SetBranchStatus(bname,
true);
385 for (
size_t i = 0; i < SystLLH.size(); ++i) {
386 TString bname = SystLLH[i];
387 Chain->SetBranchStatus(bname,
true);
395 Chain->SetBranchStatus(
"step",
true);
396 Chain->SetBranchAddress(
"step", &step[m]);
409 if(nBranches[m] != nBranches[0])
411 MACH3LOG_ERROR(
"Ups, something went wrong, chain {} called {} has {} branches, while 0 called {} has {} branches", m,
MCMCFile[m], nBranches[m],
MCMCFile[0], nBranches[0]);
412 MACH3LOG_ERROR(
"All chains should have the same number of branches");
419 std::vector<double> branch_values(
nDraw, 0.0);
420 for (
int id = 0;
id <
nDraw; ++id) {
421 Chain->SetBranchAddress(
BranchNames[
id].Data(), &branch_values[
id]);
425 if(BurnIn[m] >= nEntries[m])
427 MACH3LOG_ERROR(
"You are running on a chain shorter than BurnIn cut");
428 MACH3LOG_ERROR(
"Number of entries {} BurnIn cut {}", nEntries[m], BurnIn[m]);
440 Chain->GetEntry(entry);
444 if (step[m] < BurnIn[m])
458 for (
int j = 0; j <
nDraw; ++j)
461 S2_global[j] += branch_values[j]*branch_values[j];
463 S2_chain[m][j] += branch_values[j]*branch_values[j];
477 MACH3LOG_INFO(
"Finished calculating Toys, it took {:.2f}s to finish", clock.RealTime());
488 for (
int m = 0; m <
Nchains; ++m) {
505 for (
int m = 0; m <
Nchains; ++m) {
540 for (
int m = 0; m <
Nchains; ++m)
542 for (
int j = 0; j <
nDraw; ++j)
553 for (
int j = 0; j <
nDraw; ++j)
555 for (
int m = 0; m <
Nchains; ++m)
566 for (
int j = 0; j <
nDraw; ++j)
575 for (
int m = 0; m <
Nchains; ++m)
587 for (
int j = 0; j <
nDraw; ++j)
596 for (
int j = 0; j <
nDraw; ++j)
608 for (
int j = 0; j <
nDraw; ++j)
620 MACH3LOG_INFO(
"Finished calculating RHat, it took {:.2f}s to finish", clock.RealTime());
639 #pragma omp for collapse(2)
643 for (
int m = 0; m <
Nchains; ++m)
645 for (
int j = 0; j <
nDraw; ++j)
647 for(
int i = 0; i <
Ntoys; i++)
661 for (
int j = 0; j <
nDraw; ++j)
663 for (
int m = 0; m <
Nchains; ++m)
674 #pragma omp for collapse(2)
677 for (
int m = 0; m <
Nchains; ++m)
679 for (
int j = 0; j <
nDraw; ++j)
681 for(
int i = 0; i <
Ntoys; i++)
695 for (
int j = 0; j <
nDraw; ++j)
697 for (
int m = 0; m <
Nchains; ++m)
709 for (
int j = 0; j <
nDraw; ++j)
719 for (
int m = 0; m <
Nchains; ++m)
732 for (
int j = 0; j <
nDraw; ++j)
742 for (
int j = 0; j <
nDraw; ++j)
756 for (
int j = 0; j <
nDraw; ++j)
770 MACH3LOG_INFO(
"Finished calculating RHat, it took {:.2f}s to finish", clock.RealTime());
776 #pragma GCC diagnostic push
777 #pragma GCC diagnostic ignored "-Wfloat-conversion"
779 std::string NameTemp =
"";
783 for (
int i = 0; i <
Nchains; i++)
787 while (temp.find(
".root") != std::string::npos) {
788 temp = temp.substr(0, temp.find(
".root"));
791 const auto slash = temp.find_last_of(
"/\\");
792 if (slash != std::string::npos) {
793 temp = temp.substr(slash + 1);
796 NameTemp = NameTemp + temp +
"_";
800 NameTemp = std::to_string(
Nchains) +
"Chains" +
"_";
802 NameTemp +=
"diag.root";
804 TFile *DiagFile =
M3::Open(NameTemp,
"recreate", __FILE__, __LINE__);
807 TH1D *StandardDeviationGlobalPlot =
new TH1D(
"StandardDeviationGlobalPlot",
"StandardDeviationGlobalPlot",
nDraw, 0,
nDraw);
808 TH1D *BetweenChainVariancePlot =
new TH1D(
"BetweenChainVariancePlot",
"BetweenChainVariancePlot",
nDraw, 0,
nDraw);
809 TH1D *MarginalPosteriorVariancePlot =
new TH1D(
"MarginalPosteriorVariancePlot",
"MarginalPosteriorVariancePlot",
nDraw, 0,
nDraw);
810 TH1D *RhatPlot =
new TH1D(
"RhatPlot",
"RhatPlot", 200, 0, 2);
811 TH1D *EffectiveSampleSizePlot =
new TH1D(
"EffectiveSampleSizePlot",
"EffectiveSampleSizePlot", 400, 0, 10000);
813 TH1D *RhatLogPlot =
new TH1D(
"RhatLogPlot",
"RhatLogPlot", 200, 0, 2);
815 TH1D *StandardDeviationGlobalFoldedPlot =
nullptr;
816 TH1D *BetweenChainVarianceFoldedPlot =
nullptr;
817 TH1D *MarginalPosteriorVarianceFoldedPlot =
nullptr;
818 TH1D *RhatFoldedPlot =
nullptr;
819 TH1D *EffectiveSampleSizeFoldedPlot =
nullptr;
820 TH1D *RhatFoldedLogPlot =
nullptr;
824 StandardDeviationGlobalFoldedPlot =
new TH1D(
"StandardDeviationGlobalFoldedPlot",
"StandardDeviationGlobalFoldedPlot",
nDraw, 0,
nDraw);
825 BetweenChainVarianceFoldedPlot =
new TH1D(
"BetweenChainVarianceFoldedPlot",
"BetweenChainVarianceFoldedPlot",
nDraw, 0,
nDraw);
826 MarginalPosteriorVarianceFoldedPlot =
new TH1D(
"MarginalPosteriorVarianceFoldedPlot",
"MarginalPosteriorVarianceFoldedPlot",
nDraw, 0,
nDraw);
827 RhatFoldedPlot =
new TH1D(
"RhatFoldedPlot",
"RhatFoldedPlot", 200, 0, 2);
828 EffectiveSampleSizeFoldedPlot =
new TH1D(
"EffectiveSampleSizeFoldedPlot",
"EffectiveSampleSizeFoldedPlot", 400, 0, 10000);
829 RhatFoldedLogPlot =
new TH1D(
"RhatFoldedLogPlot",
"RhatFoldedLogPlot", 200, 0, 2);
833 int CiteriumFolded = 0;
834 for(
int j = 0; j <
nDraw; j++)
842 RhatPlot->Fill(
RHat[j]);
844 if(
RHat[j] > 1.1) Criterium++;
856 RhatLogPlot->Fill(
RHat[j]);
864 MACH3LOG_WARN(
"Number of parameters which has R hat greater than 1.1 is {}({:.2f}%) while for R hat folded {}({:.2f}%)",
865 Criterium, 100*
double(Criterium)/
double(
nDraw), CiteriumFolded, 100*
double(CiteriumFolded)/
double(
nDraw));
866 for(
int j = 0; j <
nDraw; j++)
877 MACH3LOG_WARN(
"Number of parameters which has R hat greater than 1.1 is {}({:.2f}%)", Criterium, 100*
double(Criterium)/
double(
nDraw));
878 for(
int j = 0; j <
nDraw; j++)
887 StandardDeviationGlobalPlot->Write();
888 BetweenChainVariancePlot->Write();
889 MarginalPosteriorVariancePlot->Write();
891 EffectiveSampleSizePlot->Write();
893 RhatLogPlot->Write();
897 StandardDeviationGlobalFoldedPlot->Write();
898 BetweenChainVarianceFoldedPlot->Write();
899 MarginalPosteriorVarianceFoldedPlot->Write();
900 RhatFoldedPlot->Write();
901 EffectiveSampleSizeFoldedPlot->Write();
903 RhatFoldedLogPlot->Write();
907 auto TempCanvas = std::make_unique<TCanvas>(
"Canvas",
"Canvas", 1024, 1024);
908 gStyle->SetOptStat(0);
909 TempCanvas->SetGridx();
910 TempCanvas->SetGridy();
913 auto TempLine = std::make_unique<TLine>(0, 0, 0, 0);
914 TempLine->SetLineColor(kBlack);
916 RhatPlot->GetXaxis()->SetTitle(
"R hat");
917 RhatPlot->SetLineColor(kRed);
918 RhatPlot->SetFillColor(kRed);
921 RhatFoldedPlot->SetLineColor(kBlue);
922 RhatFoldedPlot->SetFillColor(kBlue);
925 TLegend Legend(0.55, 0.6, 0.9, 0.9);
926 Legend.SetTextSize(0.04);
927 Legend.SetFillColor(0);
928 Legend.SetFillStyle(0);
929 Legend.SetLineWidth(0);
930 Legend.SetLineColor(0);
932 Legend.AddEntry(TempLine.get(), Form(
"Number of throws=%.0i, Number of chains=%.1i",
TotToys,
Nchains),
"");
933 Legend.AddEntry(RhatPlot,
"Rhat Gelman 2013",
"l");
934 if(
HighMemoryMode) Legend.AddEntry(RhatFoldedPlot,
"Rhat-Folded Gelman 2021",
"l");
939 TempCanvas->Write(
"Rhat");
942 RhatLogPlot->GetXaxis()->SetTitle(
"R hat for LogL");
943 RhatLogPlot->SetLineColor(kRed);
944 RhatLogPlot->SetFillColor(kRed);
948 TLegend LegendFolded(0.55, 0.6, 0.9, 0.9);
950 LegendFolded.SetTextSize(0.04);
951 LegendFolded.SetFillColor(0);
952 LegendFolded.SetFillStyle(0);
953 LegendFolded.SetLineWidth(0);
954 LegendFolded.SetLineColor(0);
956 LegendFolded.AddEntry(TempLine.get(), Form(
"Number of throws=%.0i, Number of chains=%.1i",
TotToys,
Nchains),
"");
957 LegendFolded.AddEntry(RhatLogPlot,
"Rhat Gelman 2013",
"l");
958 if(
HighMemoryMode) LegendFolded.AddEntry(RhatFoldedLogPlot,
"Rhat-Folded Gelman 2021",
"l");
961 LegendFolded.Draw(
"same");
962 TempCanvas->Write(
"RhatLog");
965 EffectiveSampleSizePlot->GetXaxis()->SetTitle(
"S_{eff, BDA2}");
966 EffectiveSampleSizePlot->SetLineColor(kRed);
967 if(
HighMemoryMode) EffectiveSampleSizeFoldedPlot->SetLineColor(kBlue);
969 TLegend LegendESS(0.45, 0.6, 0.9, 0.9);
970 LegendESS.SetTextSize(0.03);
971 LegendESS.SetFillColor(0);
972 LegendESS.SetFillStyle(0);
973 LegendESS.SetLineWidth(0);
974 LegendESS.SetLineColor(0);
976 const double Mean1 = EffectiveSampleSizePlot->GetMean();
977 const double RMS1 = EffectiveSampleSizePlot->GetRMS();
979 LegendESS.AddEntry(TempLine.get(), Form(
"Number of throws=%.0i, Number of chains=%.1i",
TotToys,
Nchains),
"");
980 LegendESS.AddEntry(EffectiveSampleSizePlot, Form(
"S_{eff, BDA2} #mu = %.2f, #sigma = %.2f",Mean1 ,RMS1),
"l");
983 const double Mean2 = EffectiveSampleSizeFoldedPlot->GetMean();
984 const double RMS2 = EffectiveSampleSizeFoldedPlot->GetRMS();
985 LegendESS.AddEntry(EffectiveSampleSizeFoldedPlot, Form(
"S_{eff, BDA2} Folded, #mu = %.2f, #sigma = %.2f", Mean2, RMS2),
"l");
987 EffectiveSampleSizePlot->Draw();
988 LegendESS.Draw(
"same");
990 TempCanvas->Write(
"EffectiveSampleSize");
994 delete StandardDeviationGlobalPlot;
995 delete BetweenChainVariancePlot;
996 delete MarginalPosteriorVariancePlot;
998 delete EffectiveSampleSizePlot;
1004 delete StandardDeviationGlobalFoldedPlot;
1005 delete BetweenChainVarianceFoldedPlot;
1006 delete MarginalPosteriorVarianceFoldedPlot;
1007 delete RhatFoldedPlot;
1008 delete EffectiveSampleSizeFoldedPlot;
1010 delete RhatFoldedLogPlot;
1016 MACH3LOG_INFO(
"Finished and wrote results to {}", NameTemp);
1017 #pragma GCC diagnostic pop
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
#define _MaCh3_Safe_Include_End_
#define MACH3LOG_CRITICAL
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
double CalcMedian(double arr[], const int size)
void CapVariable(double var, const double cap)
Custom exception class used throughout MaCh3.
std::vector< double > EffectiveSampleSizeFolded
std::vector< std::vector< std::vector< double > > > DrawsFolded
std::vector< std::vector< double > > StandardDeviationFolded
std::vector< double > BetweenChainVarianceFolded
std::vector< double > S2_global
Sum_i^N x_i^2 | total.
std::vector< double > MarginalPosteriorVarianceFolded
std::vector< double > MedianArr
std::vector< std::vector< double > > StandardDeviation
std::vector< double > BetweenChainVariance
std::vector< double > MeanGlobal
std::vector< bool > ValidPar
std::vector< std::vector< double > > S1_chain
Sum_i^N x_i | for each chain.
std::vector< TString > BranchNames
virtual ~RHatCalculator()
Destroys the RHatCalculator object.
std::vector< double > StandardDeviationGlobal
std::vector< double > MeanGlobalFolded
std::vector< int > Ntoys_requested
std::vector< double > EffectiveSampleSize
std::vector< double > StandardDeviationGlobalFolded
std::vector< std::vector< double > > Mean
void PrepareChains()
Load chain and prepare toys.
std::vector< std::string > MCMCFile
void PrepareChains_HighMem()
Load chain and prepare toys.
std::vector< std::vector< std::vector< double > > > Draws
std::vector< std::vector< double > > MeanFolded
void CalcRhat_HighMem()
KS: Based on Gelman et. al. arXiv:1903.08008v5.
void CalcRhat()
KS: Based on Gelman et. al. arXiv:1903.08008v5.
std::vector< double > MarginalPosteriorVariance
std::vector< int > Ntoys_filled
RHatCalculator(bool HighMemory, std::vector< std::string > &Inputs, int entries)
Constructor.
std::vector< double > S1_global
Sum_i^N x_i | total.
std::vector< double > RHatFolded
void InitialiseArrays()
Create all arrays we are going to use later.
std::vector< std::vector< double > > S2_chain
Sum_i^N x_i^2 | for each chain.
std::vector< double > RHat
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
double Uniform(const double min=0.0, const double max=1.0)
Generate a uniform random number in [min, max).
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.