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;
85 auto rnd = std::make_unique<TRandom3>(0);
92 std::vector<unsigned int> BurnIn(
Nchains);
93 std::vector<unsigned int> nEntries(
Nchains);
94 std::vector<int> nBranches(
Nchains);
95 std::vector<unsigned int> step(
Nchains);
100 std::unique_ptr<MCMCProcessor> Processor;
104 for (
int m = 0; m <
Nchains; m++)
107 if (!std::filesystem::exists(
MCMCFile[m])) {
111 TChain* Chain =
new TChain(
"posteriors");
113 nEntries[m] =
static_cast<unsigned int>(Chain->GetEntries());
116 BurnIn[m] = nEntries[m]/5;
119 TObjArray* brlis = Chain->GetListOfBranches();
122 nBranches[m] = brlis->GetEntries();
125 Chain->SetBranchStatus(
"*",
false);
127 std::vector<TString> SampleLLH;
128 std::vector<TString> SystLLH;
131 Processor = std::make_unique<MCMCProcessor>(
MCMCFile[m]);
132 Processor->Initialise();
133 nDraw = Processor->GetNParams();
134 SampleLLH = Processor->GetSampleBranchNames();
135 SystLLH = Processor->GetSystBranchNames();
136 nDraw =
nDraw +
static_cast<int>(SampleLLH.size()) +
static_cast<int>(SystLLH.size());
141 Chain->SetBranchStatus(
"*",
false);
145 for (
int i = 0; i < Processor->GetNParams(); i++)
147 TString bname = Processor->GetBranchNames()[i];
154 Chain->SetBranchStatus(bname,
true);
156 if (!Chain->GetBranch(bname)) {
157 MACH3LOG_ERROR(
"Branch '{}' does not exist in the TChain", bname.Data());
163 for (
size_t i = 0; i < SampleLLH.size(); ++i) {
164 TString bname = SampleLLH[i];
165 Chain->SetBranchStatus(bname,
true);
172 for (
size_t i = 0; i < SystLLH.size(); ++i) {
173 TString bname = SystLLH[i];
174 Chain->SetBranchStatus(bname,
true);
182 Chain->SetBranchStatus(
"step",
true);
183 Chain->SetBranchAddress(
"step", &step[m]);
187 if(nBranches[m] != nBranches[0])
189 MACH3LOG_ERROR(
"Ups, something went wrong, chain {} called {} has {} branches, while 0 called {} has {} branches", m,
MCMCFile[m], nBranches[m],
MCMCFile[0], nBranches[0]);
190 MACH3LOG_ERROR(
"All chains should have the same number of branches");
198 for(
int i = 0; i <
Ntoys; i++)
206 std::vector<double> branch_values(
nDraw, 0.0);
207 for (
int j = 0; j <
nDraw; ++j) {
208 Chain->SetBranchAddress(
BranchNames[j].Data(), &branch_values[j]);
212 if(BurnIn[m] >= nEntries[m])
214 MACH3LOG_ERROR(
"You are running on a chain shorter than BurnIn cut");
215 MACH3LOG_ERROR(
"Number of entries {} BurnIn cut {}", nEntries[m], BurnIn[m]);
221 for (
int i = 0; i <
Ntoys; i++)
224 int entry = int(nEntries[m]*rnd->Rndm());
226 Chain->GetEntry(entry);
230 if (step[m] < BurnIn[m]) {
242 for (
int j = 0; j <
nDraw; ++j) {
243 Draws[m][i][j] = branch_values[j];
255 #pragma omp parallel for
257 for(
int j = 0; j <
nDraw; j++)
260 std::vector<double> TempDraws(
static_cast<size_t>(
Ntoys) *
Nchains);
261 for(
int m = 0; m <
Nchains; m++)
263 for(
int i = 0; i <
Ntoys; i++)
266 TempDraws[im] =
Draws[m][i][j];
273 #pragma omp parallel for collapse(3)
275 for(
int m = 0; m <
Nchains; m++)
277 for(
int i = 0; i <
Ntoys; i++)
279 for(
int j = 0; j <
nDraw; j++)
286 MACH3LOG_INFO(
"Finished calculating Toys, it took {:.2f}s to finish", clock.RealTime());
300 std::vector<unsigned int> BurnIn(
Nchains);
301 std::vector<unsigned int> nEntries(
Nchains);
302 std::vector<int> nBranches(
Nchains);
303 std::vector<unsigned int> step(
Nchains);
308 std::unique_ptr<MCMCProcessor> Processor;
312 for (
int m = 0; m <
Nchains; m++)
315 if (!std::filesystem::exists(
MCMCFile[m])) {
319 TChain* Chain =
new TChain(
"posteriors");
322 nEntries[m] =
static_cast<unsigned int>(Chain->GetEntries());
330 BurnIn[m] = nEntries[m]/5;
333 TObjArray* brlis = Chain->GetListOfBranches();
336 nBranches[m] = brlis->GetEntries();
339 Chain->SetBranchStatus(
"*",
false);
341 std::vector<TString> SampleLLH;
342 std::vector<TString> SystLLH;
345 Processor = std::make_unique<MCMCProcessor>(
MCMCFile[m]);
346 Processor->Initialise();
347 nDraw = Processor->GetNParams();
348 SampleLLH = Processor->GetSampleBranchNames();
349 SystLLH = Processor->GetSystBranchNames();
350 nDraw =
nDraw +
static_cast<int>(SampleLLH.size()) +
static_cast<int>(SystLLH.size());
355 Chain->SetBranchStatus(
"*",
false);
359 for (
int i = 0; i < Processor->GetNParams(); i++)
361 TString bname = Processor->GetBranchNames()[i];
368 Chain->SetBranchStatus(bname,
true);
371 if (!Chain->GetBranch(bname)) {
372 MACH3LOG_ERROR(
"Branch '{}' does not exist in the TChain", bname.Data());
378 for (
size_t i = 0; i < SampleLLH.size(); ++i) {
379 TString bname = SampleLLH[i];
380 Chain->SetBranchStatus(bname,
true);
387 for (
size_t i = 0; i < SystLLH.size(); ++i) {
388 TString bname = SystLLH[i];
389 Chain->SetBranchStatus(bname,
true);
397 Chain->SetBranchStatus(
"step",
true);
398 Chain->SetBranchAddress(
"step", &step[m]);
411 if(nBranches[m] != nBranches[0])
413 MACH3LOG_ERROR(
"Ups, something went wrong, chain {} called {} has {} branches, while 0 called {} has {} branches", m,
MCMCFile[m], nBranches[m],
MCMCFile[0], nBranches[0]);
414 MACH3LOG_ERROR(
"All chains should have the same number of branches");
421 std::vector<double> branch_values(
nDraw, 0.0);
422 for (
int id = 0;
id <
nDraw; ++id) {
423 Chain->SetBranchAddress(
BranchNames[
id].Data(), &branch_values[
id]);
427 if(BurnIn[m] >= nEntries[m])
429 MACH3LOG_ERROR(
"You are running on a chain shorter than BurnIn cut");
430 MACH3LOG_ERROR(
"Number of entries {} BurnIn cut {}", nEntries[m], BurnIn[m]);
442 Chain->GetEntry(entry);
446 if (step[m] < BurnIn[m])
460 for (
int j = 0; j <
nDraw; ++j)
463 S2_global[j] += branch_values[j]*branch_values[j];
465 S2_chain[m][j] += branch_values[j]*branch_values[j];
479 MACH3LOG_INFO(
"Finished calculating Toys, it took {:.2f}s to finish", clock.RealTime());
490 for (
int m = 0; m <
Nchains; ++m) {
507 for (
int m = 0; m <
Nchains; ++m) {
542 for (
int m = 0; m <
Nchains; ++m)
544 for (
int j = 0; j <
nDraw; ++j)
555 for (
int j = 0; j <
nDraw; ++j)
557 for (
int m = 0; m <
Nchains; ++m)
568 for (
int j = 0; j <
nDraw; ++j)
577 for (
int m = 0; m <
Nchains; ++m)
589 for (
int j = 0; j <
nDraw; ++j)
598 for (
int j = 0; j <
nDraw; ++j)
610 for (
int j = 0; j <
nDraw; ++j)
622 MACH3LOG_INFO(
"Finished calculating RHat, it took {:.2f}s to finish", clock.RealTime());
641 #pragma omp for collapse(2)
645 for (
int m = 0; m <
Nchains; ++m)
647 for (
int j = 0; j <
nDraw; ++j)
649 for(
int i = 0; i <
Ntoys; i++)
663 for (
int j = 0; j <
nDraw; ++j)
665 for (
int m = 0; m <
Nchains; ++m)
676 #pragma omp for collapse(2)
679 for (
int m = 0; m <
Nchains; ++m)
681 for (
int j = 0; j <
nDraw; ++j)
683 for(
int i = 0; i <
Ntoys; i++)
697 for (
int j = 0; j <
nDraw; ++j)
699 for (
int m = 0; m <
Nchains; ++m)
711 for (
int j = 0; j <
nDraw; ++j)
721 for (
int m = 0; m <
Nchains; ++m)
734 for (
int j = 0; j <
nDraw; ++j)
744 for (
int j = 0; j <
nDraw; ++j)
758 for (
int j = 0; j <
nDraw; ++j)
772 MACH3LOG_INFO(
"Finished calculating RHat, it took {:.2f}s to finish", clock.RealTime());
778 #pragma GCC diagnostic push
779 #pragma GCC diagnostic ignored "-Wfloat-conversion"
781 std::string NameTemp =
"";
785 for (
int i = 0; i <
Nchains; i++)
789 while (temp.find(
".root") != std::string::npos) {
790 temp = temp.substr(0, temp.find(
".root"));
793 const auto slash = temp.find_last_of(
"/\\");
794 if (slash != std::string::npos) {
795 temp = temp.substr(slash + 1);
798 NameTemp = NameTemp + temp +
"_";
802 NameTemp = std::to_string(
Nchains) +
"Chains" +
"_";
804 NameTemp +=
"diag.root";
806 TFile *DiagFile =
M3::Open(NameTemp,
"recreate", __FILE__, __LINE__);
809 TH1D *StandardDeviationGlobalPlot =
new TH1D(
"StandardDeviationGlobalPlot",
"StandardDeviationGlobalPlot",
nDraw, 0,
nDraw);
810 TH1D *BetweenChainVariancePlot =
new TH1D(
"BetweenChainVariancePlot",
"BetweenChainVariancePlot",
nDraw, 0,
nDraw);
811 TH1D *MarginalPosteriorVariancePlot =
new TH1D(
"MarginalPosteriorVariancePlot",
"MarginalPosteriorVariancePlot",
nDraw, 0,
nDraw);
812 TH1D *RhatPlot =
new TH1D(
"RhatPlot",
"RhatPlot", 200, 0, 2);
813 TH1D *EffectiveSampleSizePlot =
new TH1D(
"EffectiveSampleSizePlot",
"EffectiveSampleSizePlot", 400, 0, 10000);
815 TH1D *RhatLogPlot =
new TH1D(
"RhatLogPlot",
"RhatLogPlot", 200, 0, 2);
817 TH1D *StandardDeviationGlobalFoldedPlot =
nullptr;
818 TH1D *BetweenChainVarianceFoldedPlot =
nullptr;
819 TH1D *MarginalPosteriorVarianceFoldedPlot =
nullptr;
820 TH1D *RhatFoldedPlot =
nullptr;
821 TH1D *EffectiveSampleSizeFoldedPlot =
nullptr;
822 TH1D *RhatFoldedLogPlot =
nullptr;
826 StandardDeviationGlobalFoldedPlot =
new TH1D(
"StandardDeviationGlobalFoldedPlot",
"StandardDeviationGlobalFoldedPlot",
nDraw, 0,
nDraw);
827 BetweenChainVarianceFoldedPlot =
new TH1D(
"BetweenChainVarianceFoldedPlot",
"BetweenChainVarianceFoldedPlot",
nDraw, 0,
nDraw);
828 MarginalPosteriorVarianceFoldedPlot =
new TH1D(
"MarginalPosteriorVarianceFoldedPlot",
"MarginalPosteriorVarianceFoldedPlot",
nDraw, 0,
nDraw);
829 RhatFoldedPlot =
new TH1D(
"RhatFoldedPlot",
"RhatFoldedPlot", 200, 0, 2);
830 EffectiveSampleSizeFoldedPlot =
new TH1D(
"EffectiveSampleSizeFoldedPlot",
"EffectiveSampleSizeFoldedPlot", 400, 0, 10000);
831 RhatFoldedLogPlot =
new TH1D(
"RhatFoldedLogPlot",
"RhatFoldedLogPlot", 200, 0, 2);
835 int CiteriumFolded = 0;
836 for(
int j = 0; j <
nDraw; j++)
844 RhatPlot->Fill(
RHat[j]);
846 if(
RHat[j] > 1.1) Criterium++;
858 RhatLogPlot->Fill(
RHat[j]);
866 MACH3LOG_WARN(
"Number of parameters which has R hat greater than 1.1 is {}({:.2f}%) while for R hat folded {}({:.2f}%)",
867 Criterium, 100*
double(Criterium)/
double(
nDraw), CiteriumFolded, 100*
double(CiteriumFolded)/
double(
nDraw));
868 for(
int j = 0; j <
nDraw; j++)
879 MACH3LOG_WARN(
"Number of parameters which has R hat greater than 1.1 is {}({:.2f}%)", Criterium, 100*
double(Criterium)/
double(
nDraw));
880 for(
int j = 0; j <
nDraw; j++)
889 StandardDeviationGlobalPlot->Write();
890 BetweenChainVariancePlot->Write();
891 MarginalPosteriorVariancePlot->Write();
893 EffectiveSampleSizePlot->Write();
895 RhatLogPlot->Write();
899 StandardDeviationGlobalFoldedPlot->Write();
900 BetweenChainVarianceFoldedPlot->Write();
901 MarginalPosteriorVarianceFoldedPlot->Write();
902 RhatFoldedPlot->Write();
903 EffectiveSampleSizeFoldedPlot->Write();
905 RhatFoldedLogPlot->Write();
909 auto TempCanvas = std::make_unique<TCanvas>(
"Canvas",
"Canvas", 1024, 1024);
910 gStyle->SetOptStat(0);
911 TempCanvas->SetGridx();
912 TempCanvas->SetGridy();
915 auto TempLine = std::make_unique<TLine>(0, 0, 0, 0);
916 TempLine->SetLineColor(kBlack);
918 RhatPlot->GetXaxis()->SetTitle(
"R hat");
919 RhatPlot->SetLineColor(kRed);
920 RhatPlot->SetFillColor(kRed);
923 RhatFoldedPlot->SetLineColor(kBlue);
924 RhatFoldedPlot->SetFillColor(kBlue);
927 TLegend Legend(0.55, 0.6, 0.9, 0.9);
928 Legend.SetTextSize(0.04);
929 Legend.SetFillColor(0);
930 Legend.SetFillStyle(0);
931 Legend.SetLineWidth(0);
932 Legend.SetLineColor(0);
934 Legend.AddEntry(TempLine.get(), Form(
"Number of throws=%.0i, Number of chains=%.1i",
TotToys,
Nchains),
"");
935 Legend.AddEntry(RhatPlot,
"Rhat Gelman 2013",
"l");
936 if(
HighMemoryMode) Legend.AddEntry(RhatFoldedPlot,
"Rhat-Folded Gelman 2021",
"l");
941 TempCanvas->Write(
"Rhat");
944 RhatLogPlot->GetXaxis()->SetTitle(
"R hat for LogL");
945 RhatLogPlot->SetLineColor(kRed);
946 RhatLogPlot->SetFillColor(kRed);
950 TLegend LegendFolded(0.55, 0.6, 0.9, 0.9);
952 LegendFolded.SetTextSize(0.04);
953 LegendFolded.SetFillColor(0);
954 LegendFolded.SetFillStyle(0);
955 LegendFolded.SetLineWidth(0);
956 LegendFolded.SetLineColor(0);
958 LegendFolded.AddEntry(TempLine.get(), Form(
"Number of throws=%.0i, Number of chains=%.1i",
TotToys,
Nchains),
"");
959 LegendFolded.AddEntry(RhatLogPlot,
"Rhat Gelman 2013",
"l");
960 if(
HighMemoryMode) LegendFolded.AddEntry(RhatFoldedLogPlot,
"Rhat-Folded Gelman 2021",
"l");
963 LegendFolded.Draw(
"same");
964 TempCanvas->Write(
"RhatLog");
967 EffectiveSampleSizePlot->GetXaxis()->SetTitle(
"S_{eff, BDA2}");
968 EffectiveSampleSizePlot->SetLineColor(kRed);
969 if(
HighMemoryMode) EffectiveSampleSizeFoldedPlot->SetLineColor(kBlue);
971 TLegend LegendESS(0.45, 0.6, 0.9, 0.9);
972 LegendESS.SetTextSize(0.03);
973 LegendESS.SetFillColor(0);
974 LegendESS.SetFillStyle(0);
975 LegendESS.SetLineWidth(0);
976 LegendESS.SetLineColor(0);
978 const double Mean1 = EffectiveSampleSizePlot->GetMean();
979 const double RMS1 = EffectiveSampleSizePlot->GetRMS();
981 LegendESS.AddEntry(TempLine.get(), Form(
"Number of throws=%.0i, Number of chains=%.1i",
TotToys,
Nchains),
"");
982 LegendESS.AddEntry(EffectiveSampleSizePlot, Form(
"S_{eff, BDA2} #mu = %.2f, #sigma = %.2f",Mean1 ,RMS1),
"l");
985 const double Mean2 = EffectiveSampleSizeFoldedPlot->GetMean();
986 const double RMS2 = EffectiveSampleSizeFoldedPlot->GetRMS();
987 LegendESS.AddEntry(EffectiveSampleSizeFoldedPlot, Form(
"S_{eff, BDA2} Folded, #mu = %.2f, #sigma = %.2f", Mean2, RMS2),
"l");
989 EffectiveSampleSizePlot->Draw();
990 LegendESS.Draw(
"same");
992 TempCanvas->Write(
"EffectiveSampleSize");
996 delete StandardDeviationGlobalPlot;
997 delete BetweenChainVariancePlot;
998 delete MarginalPosteriorVariancePlot;
1000 delete EffectiveSampleSizePlot;
1006 delete StandardDeviationGlobalFoldedPlot;
1007 delete BetweenChainVarianceFoldedPlot;
1008 delete MarginalPosteriorVarianceFoldedPlot;
1009 delete RhatFoldedPlot;
1010 delete EffectiveSampleSizeFoldedPlot;
1012 delete RhatFoldedLogPlot;
1018 MACH3LOG_INFO(
"Finished and wrote results to {}", NameTemp);
1019 #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.
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.