MaCh3  2.6.1
Reference Guide
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
MCMCProcessor Class Reference

Class responsible for processing MCMC chains, performing diagnostics, generating plots, and managing Bayesian analysis. More...

#include <Fitters/MCMCProcessor.h>

Inheritance diagram for MCMCProcessor:
[legend]
Collaboration diagram for MCMCProcessor:
[legend]

Public Member Functions

 MCMCProcessor (const std::string &InputFile)
 Constructs an MCMCProcessor object with the specified input file and options. More...
 
virtual ~MCMCProcessor ()
 Destroys the MCMCProcessor object. More...
 
void Initialise ()
 Scan chain, what parameters we have and load information from covariance matrices. More...
 
void MakePostfit (const std::map< std::string, std::pair< double, double >> &Edges={})
 Make 1D projection for each parameter and prepare structure. More...
 
void MakeCovariance ()
 Calculate covariance by making 2D projection of each combination of parameters. More...
 
void CacheSteps ()
 KS:By caching each step we use multithreading. More...
 
void MakeCovariance_MP (const bool Mute=false)
 Calculate covariance by making 2D projection of each combination of parameters using multithreading. More...
 
void MakeSubOptimality (const int NIntervals=10)
 Make and Draw SubOptimality [31]. More...
 
void Reset2DPosteriors ()
 Reset 2D posteriors, in case we would like to calculate in again with different BurnInCut. More...
 
void DrawPostfit ()
 Draw the post-fit comparisons. More...
 
void MakeViolin ()
 Make and Draw Violin. More...
 
void MakeCredibleIntervals (const std::vector< double > &CredibleIntervals={0.99, 0.90, 0.68 }, const std::vector< Color_t > &CredibleIntervalsColours={kCyan+4, kCyan-2, kCyan-10}, const bool CredibleInSigmas=false)
 Make and Draw Credible intervals. More...
 
void DrawCovariance ()
 Draw the post-fit covariances. More...
 
void MakeCovarianceYAML (const std::string &OutputYAMLFile, const std::string &MeansMethod) const
 Make YAML file from post-fit covariance. More...
 
void MakeCredibleRegions (const std::vector< double > &CredibleRegions={0.99, 0.90, 0.68}, const std::vector< Style_t > &CredibleRegionStyle={kDashed, kSolid, kDotted}, const std::vector< Color_t > &CredibleRegionColor={kGreen-3, kGreen-10, kGreen}, const bool CredibleInSigmas=false, const bool Draw2DPosterior=true, const bool DrawBestFit=true)
 Make and Draw Credible Regions. More...
 
void MakeTrianglePlot (const std::vector< std::string > &ParNames, const std::vector< double > &CredibleIntervals={0.99, 0.90, 0.68 }, const std::vector< Color_t > &CredibleIntervalsColours={kCyan+4, kCyan-2, kCyan-10}, const std::vector< double > &CredibleRegions={0.99, 0.90, 0.68}, const std::vector< Style_t > &CredibleRegionStyle={kDashed, kSolid, kDotted}, const std::vector< Color_t > &CredibleRegionColor={kGreen-3, kGreen-10, kGreen}, const bool CredibleInSigmas=false)
 Make fancy triangle plot for selected parameters. More...
 
void CheckCredibleIntervalsOrder (const std::vector< double > &CredibleIntervals, const std::vector< Color_t > &CredibleIntervalsColours) const
 Checks the order and size consistency of the CredibleIntervals and CredibleIntervalsColours vectors. More...
 
void CheckCredibleRegionsOrder (const std::vector< double > &CredibleRegions, const std::vector< Style_t > &CredibleRegionStyle, const std::vector< Color_t > &CredibleRegionColor)
 Checks the order and size consistency of the CredibleRegions, CredibleRegionStyle, and CredibleRegionColor vectors. More...
 
void GetPolarPlot (const std::vector< std::string > &ParNames)
 Make funny polar plot. More...
 
void GetBayesFactor (const std::vector< std::string > &ParName, const std::vector< std::vector< double >> &Model1Bounds, const std::vector< std::vector< double >> &Model2Bounds, const std::vector< std::vector< std::string >> &ModelNames)
 Calculate Bayes factor for vector of params, and model boundaries. More...
 
void GetSavageDickey (const std::vector< std::string > &ParName, const std::vector< double > &EvaluationPoint, const std::vector< std::vector< double >> &Bounds)
 Calculate Bayes factor for point like hypothesis using SavageDickey. More...
 
void SavageDickeyPlot (std::unique_ptr< TH1D > &PriorHist, std::unique_ptr< TH1D > &PosteriorHist, const std::string &Title, const double EvaluationPoint) const
 Produce Savage Dickey plot. More...
 
void ProduceChi2 (const std::string &GroupName) const
 Convert posterior likelihood to Delta Chi2 used for comparison with frequentists fitter. More...
 
void SmearChain (const std::vector< std::string > &Names, const std::vector< double > &Error, const bool &SaveBranch) const
 Smear chain contours. More...
 
void ParameterEvolution (const std::vector< std::string > &Names, const std::vector< int > &NIntervals)
 Make .gif of parameter evolution. More...
 
void ThinMCMC (const int ThinningCut) const
 Thin MCMC Chain, to save space and maintain low autocorrelations. More...
 
void DiagMCMC ()
 KS: Perform MCMC diagnostic including Autocorrelation, Trace etc. More...
 
int GetNParams () const
 Get total number of used parameters. More...
 
int GetNXSec () const
 
int GetNND () const
 
int GetNFD () const
 
YAML::Node GetCovConfig (const int i) const
 Get Yaml config obtained from a Chain. More...
 
int GetGroup (const std::string &name) const
 Number of params from a given group, for example flux. More...
 
TH1D * GetHpost (const int i) const
 Get 1D posterior for a given parameter. More...
 
TH2D * GetHpost2D (const int i, const int j) const
 Get 2D posterior for a given parameter combination. More...
 
TH2D * GetViolin () const
 Get Violin plot for all parameters with posterior values. More...
 
TH2D * GetViolinPrior () const
 Get Violin plot for all parameters with prior values. More...
 
std::vector< std::string > GetXSecCov () const
 
std::string GetNDCov () const
 
std::string GetFDCov () const
 
void GetPostfit (TVectorD *&Central, TVectorD *&Errors, TVectorD *&Central_Gauss, TVectorD *&Errors_Gauss, TVectorD *&Peaks)
 Get the post-fit results (arithmetic and Gaussian) More...
 
void GetCovariance (TMatrixDSym *&Cov, TMatrixDSym *&Corr)
 Get the post-fit covariances and correlations. More...
 
void GetPostfit_Ind (TVectorD *&Central, TVectorD *&Errors, TVectorD *&Peaks, ParameterEnum kParam)
 Or the individual post-fits. More...
 
const std::vector< TString > & GetBranchNames () const
 Get the vector of branch names from root file. More...
 
const std::vector< TString > & GetSampleBranchNames () const
 Get the vector of each sample branch names from root file. More...
 
const std::vector< TString > & GetSystBranchNames () const
 Get the vector of each systematic branch names from root file. More...
 
void GetNthParameter (const int param, double &Prior, double &PriorError, TString &Title) const
 Get properties of parameter by passing it number. More...
 
int GetParamIndexFromName (const std::string &Name) const
 Get parameter number based on name. More...
 
bool GetParamFlat (const int iParam) const
 Get whether param has flat prior or not. More...
 
Long64_t GetnEntries ()
 Get Number of entries that Chain has, for merged chains will not be the same Nsteps. More...
 
Long64_t GetnSteps ()
 Get Number of Steps that Chain has, for merged chains will not be the same nEntries. More...
 
void SetNBins (const int NewBins)
 Modify number of bins used for 1D and 2D Histograms. More...
 
void SetEntries (const int NewEntries)
 Set number of entries to make potentially MCMC Processing faster. More...
 
void SetReweightNames (std::vector< std::string > NewName)
 Set reweight branch names. More...
 
void SetStepCut (const std::string &Cuts)
 Set the step cutting by string. More...
 
void SetStepCut (const int Cuts)
 Set the step cutting by int. More...
 
void CheckStepCut () const
 Check if step cut isn't larger than highest values of step in a chain. More...
 
void SetPlotRelativeToPrior (const bool PlotOrNot)
 You can set relative to prior or relative to generated. It is advised to use relate to prior. More...
 
void SetPrintToPDF (const bool PlotOrNot)
 Whether to dump all plots into PDF. More...
 
void SetPlotErrorForFlatPrior (const bool PlotOrNot)
 Set whether you want to plot error for parameters which have flat prior. More...
 
void SetPlotBinValue (const bool PlotOrNot)
 
void SetFancyNames (const bool PlotOrNot)
 
void SetSmoothing (const bool PlotOrNot)
 Set whether want to use smoothing for histograms using ROOT algorithm. More...
 
void SetPost2DPlotThreshold (const double Threshold)
 Code will only plot 2D posteriors if Correlation are larger than defined threshold. More...
 
void SetUseFFTAutoCorrelation (const bool useFFT)
 Toggle using the FFT-based autocorrelation calculator. More...
 
void SetExcludedTypes (std::vector< std::string > Name)
 Setter related what parameters we want to exclude from analysis, for example if cross-section parameters look like param_, then passing "param_" will. More...
 
void SetExcludedNames (std::vector< std::string > Name)
 
void SetExcludedGroups (std::vector< std::string > Name)
 
void SetnBatches (const int Batches)
 Set value of Nbatches used for batched mean, this need to be done earlier as batches are made when reading tree. More...
 
void SetnLags (const int nLags)
 
void SetOutputSuffix (const std::string Suffix)
 Sett output suffix, this way jobs using the same file will have different names. More...
 
void SetPosterior1DCut (const std::string Cut)
 Allow to set addtional cuts based on ROOT TBrowser cut, for to only affect one mass ordering. More...
 

Protected Member Functions

std::unique_ptr< TH1D > MakePrefit ()
 Prepare prefit histogram for parameter overlay plot. More...
 
void DrawPosterior (const int i, TDirectory *PostDir, TDirectory *PostHistDir)
 Perform plot of 1d marginalised posterior with HPD etc. More...
 
void MakeOutputFile ()
 prepare output root file and canvas to which we will save EVERYTHING More...
 
void DrawCorrelations1D ()
 Draw 1D correlations which might be more helpful than looking at huge 2D Corr matrix. More...
 
void DrawCorrelationsGroup (const std::unique_ptr< TH2D > &CorrMatrix) const
 Produces correlation matrix but instead of giving name for each param it only give name for param group. More...
 
void ReadInputCov ()
 CW: Read the input Covariance matrix entries. Get stuff like parameter input errors, names, and so on. More...
 
void ReadInputCovLegacy ()
 
void FindInputFiles ()
 Read the output MCMC file and find what inputs were used. More...
 
void FindInputFilesLegacy ()
 
void ReadModelFile ()
 Read the xsec file and get the input central values and errors. More...
 
virtual void LoadAdditionalInfo ()
 allow loading additional info for example used for oscillation parameters More...
 
void ReadNDFile ()
 Read the ND cov file and get the input central values and errors. More...
 
void ReadFDFile ()
 Read the FD cov file and get the input central values and errors. More...
 
void PrintInfo () const
 Print info like how many params have been loaded etc. More...
 
void ScanInput ()
 Scan Input etc. More...
 
void ScanParameterOrder ()
 Scan order of params from a different groups. More...
 
void SetupOutput ()
 Prepare all objects used for output. More...
 
void PrepareDiagMCMC ()
 CW: Prepare branches etc. for DiagMCMC. More...
 
std::vector< double > GetParameterSums ()
 Computes the average of each parameter across all MCMC entries. Useful for autocorrelation. More...
 
void ParamTraces ()
 CW: Draw trace plots of the parameters i.e. parameter vs step. More...
 
void AutoCorrelation ()
 KS: Calculate autocorrelations supports both OpenMP and CUDA :) More...
 
void AutoCorrelation_FFT ()
 MJR: Autocorrelation function using FFT algorithm for extra speed. More...
 
void CalculateESS (const int nLags, const std::vector< std::vector< double >> &LagL)
 KS: calc Effective Sample Size. More...
 
void BatchedAnalysis ()
 Get the batched means variance estimation and variable indicating if number of batches is sensible [4] [32]. More...
 
void BatchedMeans ()
 CW: Batched means, literally read from an array and chuck into TH1D. More...
 
void GewekeDiagnostic ()
 Geweke Diagnostic based on the methods described by Fang (2014) and Karlsbakk (2011). [8] [23]. More...
 
void AcceptanceProbabilities ()
 Acceptance Probability. More...
 
void PowerSpectrumAnalysis ()
 RC: Perform spectral analysis of MCMC [7]. More...
 
std::vector< double > GetMargins (const std::unique_ptr< TCanvas > &Canv) const
 Get TCanvas margins, to be able to reset them if particular function need different margins. More...
 
void SetMargins (std::unique_ptr< TCanvas > &Canv, const std::vector< double > &margins)
 Set TCanvas margins to specified values. More...
 
void SetTLineStyle (TLine *Line, const Color_t Colour, const Width_t Width, const ELineStyle Style) const
 Configures a TLine object with the specified style parameters. More...
 
void SetLegendStyle (TLegend *Legend, const double size) const
 Configures the style of a TLegend object. More...
 
std::pair< double, double > GetHistRange (const int iParam) const
 Get Min/Max ranges for single parameter. More...
 

Protected Attributes

std::string MCMCFile
 Name of MCMC file. More...
 
std::string OutputSuffix
 Output file suffix useful when running over same file with different settings. More...
 
std::vector< std::vector< std::string > > CovPos
 Covariance matrix file name position. More...
 
std::vector< std::string > CovNamePos
 Covariance matrix name position. More...
 
std::vector< YAML::Node > CovConfig
 Covariance matrix config. More...
 
TChain * Chain
 Main chain storing all steps etc. More...
 
std::string StepCut
 BurnIn Cuts. More...
 
std::string Posterior1DCut
 Cut used when making 1D Posterior distribution. More...
 
unsigned int UpperCut
 KS: Used only for SubOptimality. More...
 
unsigned int BurnInCut
 Value of burn in cut. More...
 
int nBranches
 Number of branches in a TTree. More...
 
int nEntries
 KS: For merged chains number of entries will be different from nSteps. More...
 
int nSteps
 KS: For merged chains number of entries will be different from nSteps. More...
 
int nSampleHandlers
 Number of sample PDF objects. More...
 
int nParameterHandlers
 Number of covariance objects. More...
 
int nDraw
 Number of all parameters used in the analysis. More...
 
std::vector< TString > BranchNames
 
std::vector< std::string > ExcludedTypes
 
std::vector< std::string > ExcludedNames
 
std::vector< std::string > ExcludedGroups
 
std::vector< bool > ParamVaried
 Is the ith parameter varied. More...
 
std::vector< std::vector< TString > > ParamNames
 Name of parameters which we are going to analyse. More...
 
std::vector< std::vector< double > > ParamCentral
 Parameters central values which we are going to analyse. More...
 
std::vector< std::vector< double > > ParamErrors
 Uncertainty on a single parameter. More...
 
std::vector< std::vector< bool > > ParamFlat
 Whether Param has flat prior or not. More...
 
std::vector< int > nParam
 Number of parameters per type. More...
 
std::vector< ParameterEnumParamType
 Make an enum for which class this parameter belongs to so we don't have to keep string comparing. More...
 
std::vector< int > ParamTypeStartPos
 
std::vector< std::string > ParameterGroup
 
std::vector< TString > SampleName_v
 Vector of each sample PDF object. More...
 
std::vector< TString > SystName_v
 Vector of each systematic. More...
 
std::string OutputName
 Name of output files. More...
 
TString CanvasName
 Name of canvas which help to save to the sample pdf. More...
 
bool PlotFlatPrior
 Whether we plot flat prior or not, we usually provide error even for flat prior params. More...
 
bool plotRelativeToPrior
 Whether we plot relative to prior or nominal, in most cases is prior. More...
 
bool MadePostfit
 Sanity check if Postfit is already done to not make several times. More...
 
bool printToPDF
 Will plot all plot to PDF not only to root file. More...
 
bool FancyPlotNames
 Whether we want fancy plot names or not. More...
 
bool plotBinValue
 If true it will print value on each bin of covariance matrix. More...
 
bool ApplySmoothing
 Apply smoothing for 2D histos using root algorithm. More...
 
double Post2DPlotThreshold
 KS: Set Threshold when to plot 2D posterior as by default we get a LOT of plots. More...
 
bool useFFTAutoCorrelation
 MJR: Use FFT-based autocorrelation algorithm (save time & resources)? More...
 
std::vector< int > NDSamplesBins
 
std::vector< std::string > NDSamplesNames
 
std::unique_ptr< TF1 > Gauss
 Gaussian fitter. More...
 
TFile * OutputFile
 The output file. More...
 
std::unique_ptr< TCanvas > Posterior
 Fancy canvas used for our beautiful plots. More...
 
TVectorD * Central_Value
 Vector with central value for each parameter. More...
 
TVectorD * Means
 Vector with mean values using Arithmetic Mean. More...
 
TVectorD * Errors
 Vector with errors values using RMS. More...
 
TVectorD * Means_Gauss
 Vector with mean values using Gaussian fit. More...
 
TVectorD * Errors_Gauss
 Vector with error values using Gaussian fit. More...
 
TVectorD * Means_HPD
 Vector with mean values using Highest Posterior Density. More...
 
TVectorD * Errors_HPD
 Vector with error values using Highest Posterior Density. More...
 
TVectorD * Errors_HPD_Positive
 Vector with positive error (right hand side) values using Highest Posterior Density. More...
 
TVectorD * Errors_HPD_Negative
 Vector with negative error (left hand side) values using Highest Posterior Density. More...
 
TMatrixDSym * Covariance
 Posterior Covariance Matrix. More...
 
TMatrixDSym * Correlation
 Posterior Correlation Matrix. More...
 
std::vector< TH1D * > hpost
 Holds 1D Posterior Distributions. More...
 
std::vector< std::vector< TH2D * > > hpost2D
 Holds 2D Posterior Distributions. More...
 
std::unique_ptr< TH2D > hviolin
 Holds violin plot for all dials. More...
 
std::unique_ptr< TH2D > hviolin_prior
 Holds prior violin plot for all dials,. More...
 
M3::float_t ** ParStep
 Array holding values for all parameters. More...
 
unsigned int * StepNumber
 Step number for step, important if chains were merged. More...
 
int nBins
 Number of bins. More...
 
double DrawRange
 Drawrange for SetMaximum. More...
 
bool CacheMCMC
 MCMC Chain has been cached. More...
 
bool doDiagMCMC
 Doing MCMC Diagnostic. More...
 
int nBatches
 Number of batches for Batched Mean. More...
 
int AutoCorrLag
 LagL used in AutoCorrelation. More...
 
double ** BatchedAverages
 Values of batched average for every param and batch. More...
 
double ** SampleValues
 Holds the sample values. More...
 
double ** SystValues
 Holds the systs values. More...
 
double * AccProbValues
 Holds all accProb. More...
 
double * AccProbBatchedAverages
 Holds all accProb in batches. More...
 
bool ReweightPosterior
 Whether to apply reweighting weight or not. More...
 
std::vector< std::string > ReweightNames
 Name of branch used for chain reweighting. More...
 
double * WeightValue
 Stores value of weight for each step. More...
 

Detailed Description

Class responsible for processing MCMC chains, performing diagnostics, generating plots, and managing Bayesian analysis.

This class provides utilities to handle MCMC output generated by MCMCBase::RunMCMC. It is particularly useful for extracting values from previous MCMC runs and initiating new MCMC runs with those values. Inspired by nd280_utils/DrawComp.cpp.

See also
For more details and examples, visit the Bayesian Analysis page.
Todo:
KS: Implement Diagnostics/GetPenaltyTerm.cpp here.
Author
Clarence Wret
Kamil Skwarczynski

Definition at line 61 of file MCMCProcessor.h.

Constructor & Destructor Documentation

◆ MCMCProcessor()

_MaCh3_Safe_Include_Start_ _MaCh3_Safe_Include_End_ MCMCProcessor::MCMCProcessor ( const std::string &  InputFile)

Constructs an MCMCProcessor object with the specified input file and options.

Parameters
InputFileThe path to the input file containing MCMC data.

Definition at line 19 of file MCMCProcessor.cpp.

19  :
20  Chain(nullptr), StepCut(""), MadePostfit(false) {
21 // ****************************
22  MCMCFile = InputFile;
23 
26  MACH3LOG_INFO("Making post-fit processor for: {}", MCMCFile);
27 
28  ParStep = nullptr;
29  StepNumber = nullptr;
30  ReweightPosterior = false;
31  WeightValue = nullptr;
32 
33  Posterior = nullptr;
34  hviolin = nullptr;
35  hviolin_prior = nullptr;
36 
37  OutputFile = nullptr;
38 
39  BatchedAverages = nullptr;
40  SampleValues = nullptr;
41  SystValues = nullptr;
42  AccProbValues = nullptr;
43  AccProbBatchedAverages = nullptr;
44 
45  //KS:Hardcoded should be a way to get it via config or something
46  plotRelativeToPrior = false;
47  printToPDF = false;
48  plotBinValue = false;
49  PlotFlatPrior = true;
50  CacheMCMC = false;
51  ApplySmoothing = true;
52  FancyPlotNames = true;
53  doDiagMCMC = false;
54 
55  // KS: ROOT can compile FFT code but it will crash during run time. Turn off FFT dynamically
56 #ifdef MaCh3_FFT
57  useFFTAutoCorrelation = true;
58 #else
59  useFFTAutoCorrelation = false;
60 #endif
61  OutputSuffix = "_Process";
62  Post2DPlotThreshold = 1.e-5;
63 
64  nDraw = 0;
65  nEntries = 0;
67  nSteps = 0;
68  nBatches = 0;
69  AutoCorrLag = 0;
70 
71  nBins = 70;
72  DrawRange = 1.5;
73 
74  Posterior1DCut = "";
75  //KS:Those keep basic information for ParameterEnum
79  ParamFlat.resize(kNParameterEnum);
81  nParam.resize(kNParameterEnum);
82  CovPos.resize(kNParameterEnum);
84  CovConfig.resize(kNParameterEnum);
85 
86  ReweightNames = {"Weight"};
87  for(int i = 0; i < kNParameterEnum; i++)
88  {
89  ParamTypeStartPos[i] = 0;
90  nParam[i] = 0;
91  }
92  //Only if GPU is enabled
93  #ifdef MaCh3_CUDA
94  GPUProcessor = std::make_unique<MCMCProcessorGPU>();
95  #endif
96 }
@ kNParameterEnum
Definition: MCMCProcessor.h:50
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:60
int nBatches
Number of batches for Batched Mean.
M3::float_t ** ParStep
Array holding values for all parameters.
double Post2DPlotThreshold
KS: Set Threshold when to plot 2D posterior as by default we get a LOT of plots.
std::vector< std::string > ReweightNames
Name of branch used for chain reweighting.
double ** SampleValues
Holds the sample values.
double * WeightValue
Stores value of weight for each step.
std::vector< std::vector< double > > ParamCentral
Parameters central values which we are going to analyse.
std::vector< std::vector< double > > ParamErrors
Uncertainty on a single parameter.
std::unique_ptr< TH2D > hviolin_prior
Holds prior violin plot for all dials,.
std::vector< int > nParam
Number of parameters per type.
std::vector< std::string > CovNamePos
Covariance matrix name position.
double DrawRange
Drawrange for SetMaximum.
std::vector< std::vector< bool > > ParamFlat
Whether Param has flat prior or not.
std::vector< YAML::Node > CovConfig
Covariance matrix config.
double ** SystValues
Holds the systs values.
double * AccProbBatchedAverages
Holds all accProb in batches.
bool useFFTAutoCorrelation
MJR: Use FFT-based autocorrelation algorithm (save time & resources)?
std::string StepCut
BurnIn Cuts.
unsigned int * StepNumber
Step number for step, important if chains were merged.
int AutoCorrLag
LagL used in AutoCorrelation.
std::unique_ptr< TCanvas > Posterior
Fancy canvas used for our beautiful plots.
TFile * OutputFile
The output file.
bool ApplySmoothing
Apply smoothing for 2D histos using root algorithm.
unsigned int UpperCut
KS: Used only for SubOptimality.
int nBins
Number of bins.
TChain * Chain
Main chain storing all steps etc.
std::string MCMCFile
Name of MCMC file.
bool ReweightPosterior
Whether to apply reweighting weight or not.
std::vector< std::vector< std::string > > CovPos
Covariance matrix file name position.
std::string Posterior1DCut
Cut used when making 1D Posterior distribution.
double * AccProbValues
Holds all accProb.
std::unique_ptr< TH2D > hviolin
Holds violin plot for all dials.
int nDraw
Number of all parameters used in the analysis.
std::string OutputSuffix
Output file suffix useful when running over same file with different settings.
bool plotBinValue
If true it will print value on each bin of covariance matrix.
int nSteps
KS: For merged chains number of entries will be different from nSteps.
double ** BatchedAverages
Values of batched average for every param and batch.
bool PlotFlatPrior
Whether we plot flat prior or not, we usually provide error even for flat prior params.
bool FancyPlotNames
Whether we want fancy plot names or not.
bool printToPDF
Will plot all plot to PDF not only to root file.
std::vector< std::vector< TString > > ParamNames
Name of parameters which we are going to analyse.
bool doDiagMCMC
Doing MCMC Diagnostic.
bool CacheMCMC
MCMC Chain has been cached.
std::vector< int > ParamTypeStartPos
bool MadePostfit
Sanity check if Postfit is already done to not make several times.
int nEntries
KS: For merged chains number of entries will be different from nSteps.
bool plotRelativeToPrior
Whether we plot relative to prior or nominal, in most cases is prior.
void MaCh3Welcome()
KS: Prints welcome message with MaCh3 logo.
Definition: Monitor.cpp:13
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Definition: Core.h:55

◆ ~MCMCProcessor()

MCMCProcessor::~MCMCProcessor ( )
virtual

Destroys the MCMCProcessor object.

Definition at line 100 of file MCMCProcessor.cpp.

100  {
101 // ****************************
102  // Close the pdf file
103  MACH3LOG_INFO("Closing pdf in MCMCProcessor: {}", CanvasName.Data());
104  CanvasName += "]";
105  if(printToPDF) Posterior->Print(CanvasName);
106 
107  delete Covariance;
108  delete Correlation;
109  delete Central_Value;
110  delete Means;
111  delete Errors;
112  delete Means_Gauss;
113  delete Errors_Gauss;
114  delete Means_HPD;
115  delete Errors_HPD;
116  delete Errors_HPD_Positive;
117  delete Errors_HPD_Negative;
118 
119  if(WeightValue) delete[] WeightValue;
120  for (int i = 0; i < nDraw; ++i)
121  {
122  if(hpost[i] != nullptr) delete hpost[i];
123  }
124  if(CacheMCMC)
125  {
126  for (int i = 0; i < nDraw; ++i)
127  {
128  for (int j = 0; j < nDraw; ++j)
129  {
130  delete hpost2D[i][j];
131  }
132  delete[] ParStep[i];
133  }
134  delete[] ParStep;
135  }
136  if(StepNumber != nullptr) delete[] StepNumber;
137 
138  if(OutputFile != nullptr) OutputFile->Close();
139  if(OutputFile != nullptr) delete OutputFile;
140  delete Chain;
141 }
TMatrixDSym * Correlation
Posterior Correlation Matrix.
TVectorD * Means_HPD
Vector with mean values using Highest Posterior Density.
TVectorD * Errors
Vector with errors values using RMS.
TVectorD * Means_Gauss
Vector with mean values using Gaussian fit.
std::vector< TH1D * > hpost
Holds 1D Posterior Distributions.
TVectorD * Errors_HPD_Negative
Vector with negative error (left hand side) values using Highest Posterior Density.
TVectorD * Errors_Gauss
Vector with error values using Gaussian fit.
TVectorD * Central_Value
Vector with central value for each parameter.
TString CanvasName
Name of canvas which help to save to the sample pdf.
TVectorD * Errors_HPD
Vector with error values using Highest Posterior Density.
std::vector< std::vector< TH2D * > > hpost2D
Holds 2D Posterior Distributions.
TVectorD * Means
Vector with mean values using Arithmetic Mean.
TVectorD * Errors_HPD_Positive
Vector with positive error (right hand side) values using Highest Posterior Density.
TMatrixDSym * Covariance
Posterior Covariance Matrix.

Member Function Documentation

◆ AcceptanceProbabilities()

void MCMCProcessor::AcceptanceProbabilities ( )
protected

Acceptance Probability.

Definition at line 4484 of file MCMCProcessor.cpp.

4484  {
4485 // **************************
4486  if (AccProbBatchedAverages == nullptr) PrepareDiagMCMC();
4487 
4488  MACH3LOG_INFO("Making AccProb plots...");
4489 
4490  // Set the titles and limits for TH1Ds
4491  auto AcceptanceProbPlot = std::make_unique<TH1D>("AcceptanceProbability", "Acceptance Probability", nEntries, 0, nEntries);
4492  AcceptanceProbPlot->SetDirectory(nullptr);
4493  AcceptanceProbPlot->GetXaxis()->SetTitle("Step");
4494  AcceptanceProbPlot->GetYaxis()->SetTitle("Acceptance Probability");
4495 
4496  auto BatchedAcceptanceProblot = std::make_unique<TH1D>("AcceptanceProbability_Batch", "AcceptanceProbability_Batch", nBatches, 0, nBatches);
4497  BatchedAcceptanceProblot->SetDirectory(nullptr);
4498  BatchedAcceptanceProblot->GetYaxis()->SetTitle("Acceptance Probability");
4499 
4500  for (int i = 0; i < nBatches; ++i) {
4501  BatchedAcceptanceProblot->SetBinContent(i+1, AccProbBatchedAverages[i]);
4502  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4503  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4504  std::stringstream ss;
4505  ss << BatchRangeLow << " - " << BatchRangeHigh;
4506  BatchedAcceptanceProblot->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4507  }
4508 
4509  #ifdef MULTITHREAD
4510  #pragma omp parallel for
4511  #endif
4512  for (int i = 0; i < nEntries; ++i) {
4513  // Set bin content for the i-th bin to the parameter values
4514  AcceptanceProbPlot->SetBinContent(i, AccProbValues[i]);
4515  }
4516 
4517  TDirectory *probDir = OutputFile->mkdir("AccProb");
4518  probDir->cd();
4519 
4520  AcceptanceProbPlot->Write();
4521  BatchedAcceptanceProblot->Write();
4522  delete[] AccProbValues;
4523  delete[] AccProbBatchedAverages;
4524 
4525  probDir->Close();
4526  delete probDir;
4527 
4528  OutputFile->cd();
4529 }
void PrepareDiagMCMC()
CW: Prepare branches etc. for DiagMCMC.

◆ AutoCorrelation()

void MCMCProcessor::AutoCorrelation ( )
protected

KS: Calculate autocorrelations supports both OpenMP and CUDA :)

Definition at line 3755 of file MCMCProcessor.cpp.

3755  {
3756 // *********************************
3757  if (ParStep == nullptr) PrepareDiagMCMC();
3758 
3759  TStopwatch clock;
3760  clock.Start();
3761  const int nLags = AutoCorrLag;
3762  MACH3LOG_INFO("Making auto-correlations for nLags = {}", nLags);
3763 
3764  // The sum of (Y-Ymean)^2 over all steps for each parameter
3765  std::vector<std::vector<double>> DenomSum(nDraw);
3766  std::vector<std::vector<double>> NumeratorSum(nDraw);
3767  std::vector<std::vector<double>> LagL(nDraw);
3768  auto ParamSums = GetParameterSums();
3769  for (int j = 0; j < nDraw; ++j) {
3770  DenomSum[j].resize(nLags);
3771  NumeratorSum[j].resize(nLags);
3772  LagL[j].resize(nLags);
3773  }
3774  std::vector<std::unique_ptr<TH1D>> LagKPlots(nDraw);
3775  // Loop over the parameters of interest
3776  for (int j = 0; j < nDraw; ++j)
3777  {
3778  // Loop over each lag
3779  for (int k = 0; k < nLags; ++k) {
3780  NumeratorSum[j][k] = 0.0;
3781  DenomSum[j][k] = 0.0;
3782  LagL[j][k] = 0.0;
3783  }
3784 
3785  // Make TH1Ds for each parameter which hold the lag
3786  TString Title = "";
3787  double Prior = 1.0, PriorError = 1.0;
3788 
3789  GetNthParameter(j, Prior, PriorError, Title);
3790  std::string HistName = Form("%s_%s_Lag", Title.Data(), BranchNames[j].Data());
3791  LagKPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nLags, 0.0, nLags);
3792  LagKPlots[j]->SetDirectory(nullptr);
3793  LagKPlots[j]->GetXaxis()->SetTitle("Lag");
3794  LagKPlots[j]->GetYaxis()->SetTitle("Auto-correlation function");
3795  }
3796 //KS: If CUDA is not enabled do calculations on CPU
3797 #ifndef MaCh3_CUDA
3798  // Loop over the lags
3799  //CW: Each lag is independent so might as well multi-thread them!
3800  #ifdef MULTITHREAD
3801  MACH3LOG_INFO("Using multi-threading...");
3802  #pragma omp parallel for collapse(2)
3803  #endif // Loop over the number of parameters
3804  for (int j = 0; j < nDraw; ++j) {
3805  for (int k = 0; k < nLags; ++k) {
3806  // Loop over the number of entries
3807  for (int i = 0; i < nEntries; ++i) {
3808  const double Diff = ParStep[j][i]-ParamSums[j];
3809 
3810  // Only sum the numerator up to i = N-k
3811  if (i < nEntries-k) {
3812  const double LagTerm = ParStep[j][i+k]-ParamSums[j];
3813  const double Product = Diff*LagTerm;
3814  NumeratorSum[j][k] += Product;
3815  }
3816  // Square the difference to form the denominator
3817  const double Denom = Diff*Diff;
3818  DenomSum[j][k] += Denom;
3819  }
3820  }
3821  }
3822 #else //NOW GPU specific code
3823  MACH3LOG_INFO("Using GPU");
3825  float* ParStep_cpu = nullptr;
3826  float* NumeratorSum_cpu = nullptr;
3827  float* ParamSums_cpu = nullptr;
3828  float* DenomSum_cpu = nullptr;
3829 
3830  //KS: This allocates memory and copy data from CPU to GPU
3831  PrepareGPU_AutoCorr(nLags, ParamSums, ParStep_cpu, NumeratorSum_cpu, ParamSums_cpu, DenomSum_cpu);
3832 
3833  //KS: This runs the main kernel and copy results back to CPU
3834  GPUProcessor->RunGPU_AutoCorr(NumeratorSum_cpu,
3835  DenomSum_cpu);
3836 
3837  #ifdef MULTITHREAD
3838  #pragma omp parallel for collapse(2)
3839  #endif
3840  //KS: Now that that we received data from GPU convert it to CPU-like format
3841  for (int j = 0; j < nDraw; ++j)
3842  {
3843  for (int k = 0; k < nLags; ++k)
3844  {
3845  const int temp_index = j*nLags+k;
3846  NumeratorSum[j][k] = NumeratorSum_cpu[temp_index];
3847  DenomSum[j][k] = DenomSum_cpu[temp_index];
3848  }
3849  }
3850  //delete auxiliary variables
3851  if(NumeratorSum_cpu) delete[] NumeratorSum_cpu;
3852  if(DenomSum_cpu) delete[] DenomSum_cpu;
3853  if(ParStep_cpu) delete[] ParStep_cpu;
3854  if(ParamSums_cpu) delete[] ParamSums_cpu;
3855 
3856  //KS: Delete stuff at GPU as well
3857  GPUProcessor->CleanupGPU_AutoCorr();
3858 
3859 //KS: End of GPU specific code
3860 #endif
3861 
3862  OutputFile->cd();
3863  TDirectory *AutoCorrDir = OutputFile->mkdir("Auto_corr");
3864  // Now fill the LagK auto-correlation plots
3865  for (int j = 0; j < nDraw; ++j) {
3866  for (int k = 0; k < nLags; ++k) {
3867  LagL[j][k] = NumeratorSum[j][k]/DenomSum[j][k];
3868  LagKPlots[j]->SetBinContent(k, NumeratorSum[j][k]/DenomSum[j][k]);
3869  }
3870  AutoCorrDir->cd();
3871  LagKPlots[j]->Write();
3872  }
3873 
3874  //KS: This is different diagnostic however it relies on calculated Lag, thus we call it before we delete LagKPlots
3875  CalculateESS(nLags, LagL);
3876 
3877  AutoCorrDir->Close();
3878  delete AutoCorrDir;
3879 
3880  OutputFile->cd();
3881 
3882  clock.Stop();
3883  MACH3LOG_INFO("Making auto-correlations took {:.2f}s", clock.RealTime());
3884 }
void GetNthParameter(const int param, double &Prior, double &PriorError, TString &Title) const
Get properties of parameter by passing it number.
std::vector< double > GetParameterSums()
Computes the average of each parameter across all MCMC entries. Useful for autocorrelation.
void CalculateESS(const int nLags, const std::vector< std::vector< double >> &LagL)
KS: calc Effective Sample Size.
std::vector< TString > BranchNames

◆ AutoCorrelation_FFT()

void MCMCProcessor::AutoCorrelation_FFT ( )
protected

MJR: Autocorrelation function using FFT algorithm for extra speed.

Author
Michael Reh

Definition at line 3659 of file MCMCProcessor.cpp.

3659  {
3660 // *********************************
3661  if (ParStep == nullptr) PrepareDiagMCMC();
3662 
3663  TStopwatch clock;
3664  clock.Start();
3665  const int nLags = AutoCorrLag;
3666  MACH3LOG_INFO("Making auto-correlations for nLags = {}", nLags);
3667 
3668  // Prep outputs
3669  OutputFile->cd();
3670  TDirectory* AutoCorrDir = OutputFile->mkdir("Auto_corr");
3671  std::vector<std::unique_ptr<TH1D>> LagKPlots(nDraw);
3672  std::vector<std::vector<double>> LagL(nDraw);
3673 
3674  // Arrays needed to perform FFT using ROOT
3675  std::vector<double> ACFFT(nEntries, 0.0); // Main autocorrelation array
3676  std::vector<double> ParVals(nEntries, 0.0); // Param values for full chain
3677  std::vector<double> ParValsFFTR(nEntries, 0.0); // FFT Real part
3678  std::vector<double> ParValsFFTI(nEntries, 0.0); // FFT Imaginary part
3679  std::vector<double> ParValsFFTSquare(nEntries, 0.0); // FFT Absolute square
3680  std::vector<double> ParValsComplex(nEntries, 0.0); // Input Imaginary values (0)
3681 
3682  auto ParamSums = GetParameterSums();
3683  // Create forward and reverse FFT objects. I don't love using ROOT here,
3684  // but it works so I can't complain
3685  TVirtualFFT* fftf = TVirtualFFT::FFT(1, &nEntries, "C2CFORWARD");
3686  TVirtualFFT* fftb = TVirtualFFT::FFT(1, &nEntries, "C2CBACKWARD");
3687 
3688  // Loop over all pars and calculate the full autocorrelation function using FFT
3689  for (int j = 0; j < nDraw; ++j) {
3690  // Initialize
3691  LagL[j].resize(nLags);
3692  for (int i = 0; i < nEntries; ++i) {
3693  ParVals[i] = ParStep[j][i]-ParamSums[j]; // Subtract the mean to make it numerically tractable
3694  ParValsComplex[i] = 0.; // Reset dummy array
3695  }
3696 
3697  // Transform
3698  fftf->SetPointsComplex(ParVals.data(), ParValsComplex.data());
3699  fftf->Transform();
3700  fftf->GetPointsComplex(ParValsFFTR.data(), ParValsFFTI.data());
3701 
3702  // Square the results to get the power spectrum
3703  for (int i = 0; i < nEntries; ++i) {
3704  ParValsFFTSquare[i] = ParValsFFTR[i]*ParValsFFTR[i] + ParValsFFTI[i]*ParValsFFTI[i];
3705  }
3706 
3707  // Transforming back gives the autocovariance
3708  fftb->SetPointsComplex(ParValsFFTSquare.data(), ParValsComplex.data());
3709  fftb->Transform();
3710  fftb->GetPointsComplex(ACFFT.data(), ParValsComplex.data());
3711 
3712  // Divide by norm to get autocorrelation
3713  double normAC = ACFFT[0];
3714  for (int i = 0; i < nEntries; ++i) {
3715  ACFFT[i] /= normAC;
3716  }
3717 
3718  // Get plotting info
3719  TString Title = "";
3720  double Prior = 1.0, PriorError = 1.0;
3721  GetNthParameter(j, Prior, PriorError, Title);
3722  std::string HistName = Form("%s_%s_Lag", Title.Data(), BranchNames[j].Data());
3723 
3724  // Initialize Lag plot
3725  LagKPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nLags, 0.0, nLags);
3726  LagKPlots[j]->SetDirectory(nullptr);
3727  LagKPlots[j]->GetXaxis()->SetTitle("Lag");
3728  LagKPlots[j]->GetYaxis()->SetTitle("Auto-correlation function");
3729 
3730  // Fill plot
3731  for (int k = 0; k < nLags; ++k) {
3732  LagL[j][k] = ACFFT[k];
3733  LagKPlots[j]->SetBinContent(k, ACFFT[k]);
3734  }
3735 
3736  // Write and clean up
3737  AutoCorrDir->cd();
3738  LagKPlots[j]->Write();
3739  }
3740 
3741  //KS: This is different diagnostic however it relies on calculated Lag, thus we call it before we delete LagKPlots
3742  CalculateESS(nLags, LagL);
3743 
3744  AutoCorrDir->Close();
3745  delete AutoCorrDir;
3746 
3747  OutputFile->cd();
3748 
3749  clock.Stop();
3750  MACH3LOG_INFO("Making auto-correlations took {:.2f}s", clock.RealTime());
3751 }

◆ BatchedAnalysis()

void MCMCProcessor::BatchedAnalysis ( )
protected

Get the batched means variance estimation and variable indicating if number of batches is sensible [4] [32].

Definition at line 4116 of file MCMCProcessor.cpp.

4116  {
4117 // **************************
4118  if(BatchedAverages == nullptr)
4119  {
4120  MACH3LOG_ERROR("BatchedAverages haven't been initialises or have been deleted something is wrong");
4121  MACH3LOG_ERROR("I need it and refuse to go further");
4122  throw MaCh3Exception(__FILE__ , __LINE__ );
4123  }
4124 
4125  // Calculate variance estimator using batched means following @cite chakraborty2019estimating see Eq. 1.2
4126  TVectorD* BatchedVariance = new TVectorD(nDraw);
4127  //KS: The hypothesis is rejected if C > z α for a given confidence level α. If the batch means do not pass the test, Correlated is reported for the half-width on the statistical reports following @cite rossetti2024batch alternatively for more old-school see Alexopoulos and Seila 1998 section 3.4.3
4128  TVectorD* C_Test_Statistics = new TVectorD(nDraw);
4129 
4130  std::vector<double> OverallBatchMean(nDraw);
4131  std::vector<double> C_Rho_Nominator(nDraw);
4132  std::vector<double> C_Rho_Denominator(nDraw);
4133  std::vector<double> C_Nominator(nDraw);
4134  std::vector<double> C_Denominator(nDraw);
4135  const int BatchLength = nEntries/nBatches+1;
4136 //KS: Start parallel region
4137 #ifdef MULTITHREAD
4138 #pragma omp parallel
4139 {
4140 #endif
4141  #ifdef MULTITHREAD
4142  #pragma omp for
4143  #endif
4144  //KS: First calculate mean of batched means for each param and Initialise everything to 0
4145  for (int j = 0; j < nDraw; ++j)
4146  {
4147  OverallBatchMean[j] = 0.0;
4148  C_Rho_Nominator[j] = 0.0;
4149  C_Rho_Denominator[j] = 0.0;
4150  C_Nominator[j] = 0.0;
4151  C_Denominator[j] = 0.0;
4152 
4153  (*BatchedVariance)(j) = 0.0;
4154  (*C_Test_Statistics)(j) = 0.0;
4155  for (int i = 0; i < nBatches; ++i)
4156  {
4157  OverallBatchMean[j] += BatchedAverages[i][j];
4158  }
4159  OverallBatchMean[j] /= nBatches;
4160  }
4161 
4162  #ifdef MULTITHREAD
4163  #pragma omp for nowait
4164  #endif
4165  //KS: next loop is completely independent thus nowait clause
4166  for (int j = 0; j < nDraw; ++j)
4167  {
4168  for (int i = 0; i < nBatches; ++i)
4169  {
4170  (*BatchedVariance)(j) += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4171  }
4172  (*BatchedVariance)(j) = (BatchLength/(nBatches-1))* (*BatchedVariance)(j);
4173  }
4174 
4175  //KS: Now we focus on C test statistic, again use nowait as next is calculation is independent
4176  #ifdef MULTITHREAD
4177  #pragma omp for nowait
4178  #endif
4179  for (int j = 0; j < nDraw; ++j)
4180  {
4181  C_Nominator[j] = (OverallBatchMean[j] - BatchedAverages[0][j])*(OverallBatchMean[j] - BatchedAverages[0][j]) +
4182  (OverallBatchMean[j] - BatchedAverages[nBatches-1][j])*(OverallBatchMean[j] - BatchedAverages[nBatches-1][j]);
4183  for (int i = 0; i < nBatches; ++i)
4184  {
4185  C_Denominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4186  }
4187  C_Denominator[j] = 2*C_Denominator[j];
4188  }
4189 
4190  //KS: We still calculate C and for this we need rho wee need autocorrelations between batches
4191  #ifdef MULTITHREAD
4192  #pragma omp for
4193  #endif
4194  for (int j = 0; j < nDraw; ++j)
4195  {
4196  for (int i = 0; i < nBatches-1; ++i)
4197  {
4198  C_Rho_Nominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i+1][j]);
4199  }
4200 
4201  for (int i = 0; i < nBatches; ++i)
4202  {
4203  C_Rho_Denominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4204  }
4205  }
4206 
4207  //KS: Final calculations of C
4208  #ifdef MULTITHREAD
4209  #pragma omp for
4210  #endif
4211  for (int j = 0; j < nDraw; ++j)
4212  {
4213  (*C_Test_Statistics)(j) = std::sqrt((nBatches*nBatches - 1)/(nBatches-2)) * ( C_Rho_Nominator[j]/C_Rho_Denominator[j] + C_Nominator[j]/ C_Denominator[j]);
4214  }
4215 #ifdef MULTITHREAD
4216 } //End parallel region
4217 #endif
4218 
4219  //Save to file
4220  OutputFile->cd();
4221  BatchedVariance->Write("BatchedMeansVariance");
4222  C_Test_Statistics->Write("C_Test_Statistics");
4223 
4224  //Delete all variables
4225  delete BatchedVariance;
4226  delete C_Test_Statistics;
4227 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
Custom exception class used throughout MaCh3.

◆ BatchedMeans()

void MCMCProcessor::BatchedMeans ( )
protected

CW: Batched means, literally read from an array and chuck into TH1D.

Definition at line 4059 of file MCMCProcessor.cpp.

4059  {
4060 // **************************
4061  if (BatchedAverages == nullptr) PrepareDiagMCMC();
4062  MACH3LOG_INFO("Making BatchedMeans plots...");
4063 
4064  std::vector<std::unique_ptr<TH1D>> BatchedParamPlots(nDraw);
4065  for (int j = 0; j < nDraw; ++j) {
4066  TString Title = "";
4067  double Prior = 1.0, PriorError = 1.0;
4068 
4069  GetNthParameter(j, Prior, PriorError, Title);
4070 
4071  std::string HistName = Form("%s_%s_batch", Title.Data(), BranchNames[j].Data());
4072  BatchedParamPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nBatches, 0, nBatches);
4073  BatchedParamPlots[j]->SetDirectory(nullptr);
4074  }
4075 
4076  #ifdef MULTITHREAD
4077  #pragma omp parallel for
4078  #endif
4079  for (int j = 0; j < nDraw; ++j) {
4080  for (int i = 0; i < nBatches; ++i) {
4081  BatchedParamPlots[j]->SetBinContent(i+1, BatchedAverages[i][j]);
4082  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4083  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4084  std::stringstream ss;
4085  ss << BatchRangeLow << " - " << BatchRangeHigh;
4086  BatchedParamPlots[j]->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4087  }
4088  }
4089 
4090  TDirectory *BatchDir = OutputFile->mkdir("Batched_means");
4091  BatchDir->cd();
4092  for (int j = 0; j < nDraw; ++j) {
4093  auto Fitter = std::make_unique<TF1>("Fitter", "[0]", 0, nBatches);
4094  Fitter->SetLineColor(kRed);
4095  BatchedParamPlots[j]->Fit("Fitter","Rq");
4096  BatchedParamPlots[j]->Write();
4097  }
4098 
4099  //KS: Get the batched means variance estimation and variable indicating if number of batches is sensible
4100  // We do this before deleting BatchedAverages
4101  BatchedAnalysis();
4102 
4103  for (int i = 0; i < nBatches; ++i) {
4104  delete BatchedAverages[i];
4105  }
4106  delete[] BatchedAverages;
4107 
4108  BatchDir->Close();
4109  delete BatchDir;
4110 
4111  OutputFile->cd();
4112 }
void BatchedAnalysis()
Get the batched means variance estimation and variable indicating if number of batches is sensible .

◆ CacheSteps()

void MCMCProcessor::CacheSteps ( )

KS:By caching each step we use multithreading.

Definition at line 1128 of file MCMCProcessor.cpp.

1128  {
1129 // ***************
1130  if(CacheMCMC == true) return;
1131 
1132  CacheMCMC = true;
1133 
1134  if(ParStep != nullptr)
1135  {
1136  MACH3LOG_ERROR("It look like ParStep was already filled ");
1137  MACH3LOG_ERROR("Even though it is used for MakeCovariance_MP and for DiagMCMC ");
1138  MACH3LOG_ERROR("it has different structure in both for cache hits, sorry ");
1139  throw MaCh3Exception(__FILE__ , __LINE__ );
1140  }
1141 
1142  MACH3LOG_INFO("Caching input tree...");
1143  MACH3LOG_INFO("Allocating {:.2f} MB", double(sizeof(M3::float_t)*nDraw*nEntries)/1.E6);
1144  TStopwatch clock;
1145  clock.Start();
1146 
1147  ParStep = new M3::float_t*[nDraw];
1148  StepNumber = new unsigned int[nEntries];
1149 
1150  hpost2D.resize(nDraw);
1151  for (int i = 0; i < nDraw; ++i)
1152  {
1153  ParStep[i] = new M3::float_t[nEntries];
1154  hpost2D[i].resize(nDraw);
1155  for (int j = 0; j < nEntries; ++j)
1156  {
1157  ParStep[i][j] = -999.99;
1158  //KS: Set this only once
1159  if(i == 0) StepNumber[j] = 0;
1160  }
1161  }
1162 
1163  // Set all the branches to off
1164  Chain->SetBranchStatus("*", false);
1165  unsigned int stepBranch = 0;
1166  std::vector<double> ParValBranch(nDraw);
1167  // Turn on the branches which we want for parameters
1168  for (int i = 0; i < nDraw; ++i)
1169  {
1170  Chain->SetBranchStatus(BranchNames[i].Data(), true);
1171  Chain->SetBranchAddress(BranchNames[i].Data(), &ParValBranch[i]);
1172  }
1173  Chain->SetBranchStatus("step", true);
1174  Chain->SetBranchAddress("step", &stepBranch);
1175 
1176  std::vector<double> ReweightWeight(ReweightNames.size(), 1.0);
1177  if (ReweightPosterior)
1178  {
1179  WeightValue = new double[nEntries]();
1180  for (size_t i = 0; i < ReweightNames.size(); ++i) {
1181  Chain->SetBranchStatus(ReweightNames[i].c_str(), true);
1182  Chain->SetBranchAddress(ReweightNames[i].c_str(), &ReweightWeight[i]);
1183  }
1184  }
1185 
1186  const Long64_t countwidth = nEntries/10;
1187 
1188  // Loop over the entries
1189  //KS: This is really a bottleneck right now, thus revisit with ROOT6 https://pep-root6.github.io/docs/analysis/parallell/root.html
1190  for (Long64_t j = 0; j < nEntries; ++j)
1191  {
1192  if (j % countwidth == 0) {
1195  } else {
1196  Chain->GetEntry(j);
1197  }
1198  StepNumber[j] = stepBranch;
1199  // Set the branch addresses for params
1200  for (int i = 0; i < nDraw; ++i) {
1201  ParStep[i][j] = ParValBranch[i];
1202  }
1203  if (ReweightPosterior) {
1204  WeightValue[j] = 1.0;
1205  for (size_t i = 0; i < ReweightWeight.size(); ++i) {
1206  WeightValue[j] *= ReweightWeight[i];
1207  }
1208  }
1209  }
1210  // Set all the branches to on
1211  Chain->SetBranchStatus("*", true);
1212 
1213  // Calculate the total number of TH2D objects
1214  size_t nHistograms = nDraw * (nDraw + 1) / 2;
1215  MACH3LOG_INFO("Caching 2D posterior histograms...");
1216  MACH3LOG_INFO("Allocating {:.2f} MB for {} 2D Posteriors (each {}x{} bins)",
1217  double(nHistograms * nBins * nBins * sizeof(double)) / 1.E6, nHistograms, nBins, nBins);
1218  // Cache max and min in chain for covariance matrix
1219  for (int i = 0; i < nDraw; ++i)
1220  {
1221  TString Title_i = "";
1222  double Prior_i, PriorError_i;
1223  GetNthParameter(i, Prior_i, PriorError_i, Title_i);
1224 
1225  for (int j = 0; j <= i; ++j)
1226  {
1227  TString Title_j = "";
1228  double Prior_j, PriorError_j;
1229  GetNthParameter(j, Prior_j, PriorError_j, Title_j);
1230 
1231  auto range_x = GetHistRange(i);
1232  auto range_y = GetHistRange(j);
1233  // TH2D to hold the Correlation
1234  hpost2D[i][j] = new TH2D((Title_i + "_" + Title_j).Data(), (Title_i + "_" + Title_j).Data(),
1235  nBins, range_x.first, range_x.second,
1236  nBins, range_y.first, range_y.second);
1237  hpost2D[i][j]->SetMinimum(0);
1238  hpost2D[i][j]->GetXaxis()->SetTitle(Title_i);
1239  hpost2D[i][j]->GetYaxis()->SetTitle(Title_j);
1240  hpost2D[i][j]->GetZaxis()->SetTitle("Steps");
1241  }
1242  }
1243  clock.Stop();
1244  MACH3LOG_INFO("Caching steps took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries );
1245 }
std::pair< double, double > GetHistRange(const int iParam) const
Get Min/Max ranges for single parameter.
void EstimateDataTransferRate(TChain *chain, const Long64_t entry)
KS: Check what CPU you are using.
Definition: Monitor.cpp:212
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:229
double float_t
Definition: Core.h:37

◆ CalculateESS()

void MCMCProcessor::CalculateESS ( const int  nLags,
const std::vector< std::vector< double >> &  LagL 
)
protected

KS: calc Effective Sample Size.

Parameters
nLagsShould be the same nLags as used in AutoCorrelation()
LagLValue of LagL for each dial and each Lag

This function computes the Effective Sample Size (ESS) using the autocorrelations calculated by AutoCorrelation(). Ensure that the parameter nLags here matches the number of lags used in AutoCorrelation() to obtain accurate results. [34] [17] [9]

Definition at line 3961 of file MCMCProcessor.cpp.

3961  {
3962 // **************************
3963  if(LagL.size() == 0)
3964  {
3965  MACH3LOG_ERROR("Size of LagL is {}", LagL.size());
3966  throw MaCh3Exception(__FILE__ , __LINE__ );
3967  }
3968  MACH3LOG_INFO("Making ESS plots...");
3969  TVectorD* EffectiveSampleSize = new TVectorD(nDraw);
3970  TVectorD* SamplingEfficiency = new TVectorD(nDraw);
3971  std::vector<double> TempDenominator(nDraw);
3972 
3973  constexpr int Nhists = 5;
3974  constexpr double Thresholds[Nhists + 1] = {1, 0.02, 0.005, 0.001, 0.0001, 0.0};
3975  constexpr Color_t ESSColours[Nhists] = {kGreen, kGreen + 2, kYellow, kOrange, kRed};
3976 
3977  //KS: This histogram is inspired by the following: @cite gabry2024visual
3978  std::vector<std::unique_ptr<TH1D>> EffectiveSampleSizeHist(Nhists);
3979  for(int i = 0; i < Nhists; ++i)
3980  {
3981  EffectiveSampleSizeHist[i] =
3982  std::make_unique<TH1D>(Form("EffectiveSampleSizeHist_%i", i), Form("EffectiveSampleSizeHist_%i", i), nDraw, 0, nDraw);
3983  EffectiveSampleSizeHist[i]->SetDirectory(nullptr);
3984  EffectiveSampleSizeHist[i]->GetYaxis()->SetTitle("N_{eff}/N");
3985  EffectiveSampleSizeHist[i]->SetFillColor(ESSColours[i]);
3986  EffectiveSampleSizeHist[i]->SetLineColor(ESSColours[i]);
3987  EffectiveSampleSizeHist[i]->Sumw2();
3988  for (int j = 0; j < nDraw; ++j)
3989  {
3990  TString Title = "";
3991  double Prior = 1.0, PriorError = 1.0;
3992  GetNthParameter(j, Prior, PriorError, Title);
3993  EffectiveSampleSizeHist[i]->GetXaxis()->SetBinLabel(j+1, Title.Data());
3994  }
3995  }
3996 
3997  #ifdef MULTITHREAD
3998  #pragma omp parallel for
3999  #endif
4000  //KS: Calculate ESS and MCMC efficiency for each parameter
4001  for (int j = 0; j < nDraw; ++j)
4002  {
4003  (*EffectiveSampleSize)(j) = M3::_BAD_DOUBLE_;
4004  (*SamplingEfficiency)(j) = M3::_BAD_DOUBLE_;
4005  TempDenominator[j] = 0.;
4006  //KS: Firs sum over all Calculated autocorrelations
4007  for (int k = 0; k < nLags; ++k)
4008  {
4009  TempDenominator[j] += LagL[j][k];
4010  }
4011  TempDenominator[j] = 1+2*TempDenominator[j];
4012  (*EffectiveSampleSize)(j) = double(nEntries)/TempDenominator[j];
4013  // 100 because we convert to percentage
4014  (*SamplingEfficiency)(j) = 100 * 1/TempDenominator[j];
4015 
4016  for(int i = 0; i < Nhists; ++i)
4017  {
4018  EffectiveSampleSizeHist[i]->SetBinContent(j+1, 0);
4019  EffectiveSampleSizeHist[i]->SetBinError(j+1, 0);
4020 
4021  const double TempEntry = std::fabs((*EffectiveSampleSize)(j)) / double(nEntries);
4022  if(Thresholds[i] >= TempEntry && TempEntry > Thresholds[i+1])
4023  {
4024  if( std::isnan((*EffectiveSampleSize)(j)) ) continue;
4025  EffectiveSampleSizeHist[i]->SetBinContent(j+1, TempEntry);
4026  }
4027  }
4028  }
4029 
4030  //KS Write to the output tree
4031  //Save to file
4032  OutputFile->cd();
4033  EffectiveSampleSize->Write("EffectiveSampleSize");
4034  SamplingEfficiency->Write("SamplingEfficiency");
4035 
4036  EffectiveSampleSizeHist[0]->SetTitle("Effective Sample Size");
4037  EffectiveSampleSizeHist[0]->Draw();
4038  for(int i = 1; i < Nhists; ++i)
4039  {
4040  EffectiveSampleSizeHist[i]->Draw("SAME");
4041  }
4042 
4043  auto leg = std::make_unique<TLegend>(0.2, 0.7, 0.6, 0.95);
4044  SetLegendStyle(leg.get(), 0.03);
4045  for(int i = 0; i < Nhists; ++i)
4046  {
4047  leg->AddEntry(EffectiveSampleSizeHist[i].get(), Form("%.4f >= N_{eff}/N > %.4f", Thresholds[i], Thresholds[i+1]), "f");
4048  } leg->Draw("SAME");
4049 
4050  Posterior->Write("EffectiveSampleSizeCanvas");
4051 
4052  //Delete all variables
4053  delete EffectiveSampleSize;
4054  delete SamplingEfficiency;
4055 }
void SetLegendStyle(TLegend *Legend, const double size) const
Configures the style of a TLegend object.
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:53

◆ CheckCredibleIntervalsOrder()

void MCMCProcessor::CheckCredibleIntervalsOrder ( const std::vector< double > &  CredibleIntervals,
const std::vector< Color_t > &  CredibleIntervalsColours 
) const

Checks the order and size consistency of the CredibleIntervals and CredibleIntervalsColours vectors.

Parameters
CredibleIntervalsA vector of credible interval values.
CredibleIntervalsColoursA vector of colors associated with each credible interval.
Exceptions
MaCh3ExceptionIf the sizes are not equal or the intervals are not in decreasing order.

Definition at line 4532 of file MCMCProcessor.cpp.

4532  {
4533 // **************************
4534  if (CredibleIntervals.size() != CredibleIntervalsColours.size()) {
4535  MACH3LOG_ERROR("size of CredibleIntervals is not equal to size of CredibleIntervalsColours");
4536  throw MaCh3Exception(__FILE__, __LINE__);
4537  }
4538  if (CredibleIntervals.size() > 1) {
4539  for (unsigned int i = 1; i < CredibleIntervals.size(); i++) {
4540  if (CredibleIntervals[i] > CredibleIntervals[i - 1]) {
4541  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4542  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleIntervals[i], CredibleIntervals[i - 1]);
4543  MACH3LOG_ERROR("They should be grouped in decreasing order");
4544  throw MaCh3Exception(__FILE__, __LINE__);
4545  }
4546  }
4547  }
4548 }

◆ CheckCredibleRegionsOrder()

void MCMCProcessor::CheckCredibleRegionsOrder ( const std::vector< double > &  CredibleRegions,
const std::vector< Style_t > &  CredibleRegionStyle,
const std::vector< Color_t > &  CredibleRegionColor 
)

Checks the order and size consistency of the CredibleRegions, CredibleRegionStyle, and CredibleRegionColor vectors.

Parameters
CredibleRegionsA vector of credible region values.
CredibleRegionStyleA vector of styles associated with each credible region.
CredibleRegionColorA vector of colors associated with each credible region.
Exceptions
MaCh3ExceptionIf the sizes are not equal or the regions are not in decreasing order.

Definition at line 4551 of file MCMCProcessor.cpp.

4553  {
4554 // **************************
4555  if ((CredibleRegions.size() != CredibleRegionStyle.size()) || (CredibleRegionStyle.size() != CredibleRegionColor.size())) {
4556  MACH3LOG_ERROR("size of CredibleRegions is not equal to size of CredibleRegionStyle or CredibleRegionColor");
4557  throw MaCh3Exception(__FILE__, __LINE__);
4558  }
4559  for (unsigned int i = 1; i < CredibleRegions.size(); i++) {
4560  if (CredibleRegions[i] > CredibleRegions[i - 1]) {
4561  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4562  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleRegions[i], CredibleRegions[i - 1]);
4563  MACH3LOG_ERROR("They should be grouped in decreasing order");
4564  throw MaCh3Exception(__FILE__, __LINE__);
4565  }
4566  }
4567 }

◆ CheckStepCut()

void MCMCProcessor::CheckStepCut ( ) const

Check if step cut isn't larger than highest values of step in a chain.

Definition at line 2837 of file MCMCProcessor.cpp.

2837  {
2838 // ***************
2839  const unsigned int maxNsteps = Chain->GetMaximum("step");
2840  if(BurnInCut > maxNsteps){
2841  MACH3LOG_ERROR("StepCut({}) is larger than highest value of step({})", BurnInCut, maxNsteps);
2842  throw MaCh3Exception(__FILE__ , __LINE__ );
2843  }
2844 }
unsigned int BurnInCut
Value of burn in cut.

◆ DiagMCMC()

void MCMCProcessor::DiagMCMC ( )

KS: Perform MCMC diagnostic including Autocorrelation, Trace etc.

Definition at line 3347 of file MCMCProcessor.cpp.

3347  {
3348 // **************************
3349  // Prepare branches etc for DiagMCMC
3350  PrepareDiagMCMC();
3351 
3352  // Draw the simple trace matrices
3353  ParamTraces();
3354 
3355  // Get the batched means
3356  BatchedMeans();
3357 
3358  // Draw the auto-correlations
3359  if (useFFTAutoCorrelation) {
3361  } else {
3362  AutoCorrelation();
3363  }
3364 
3365  // Calculate Power Spectrum for each param
3367 
3368  // Get Geweke Z score helping select burn-in
3369  GewekeDiagnostic();
3370 
3371  // Draw acceptance Probability
3373 }
void GewekeDiagnostic()
Geweke Diagnostic based on the methods described by Fang (2014) and Karlsbakk (2011)....
void AcceptanceProbabilities()
Acceptance Probability.
void AutoCorrelation()
KS: Calculate autocorrelations supports both OpenMP and CUDA :)
void ParamTraces()
CW: Draw trace plots of the parameters i.e. parameter vs step.
void AutoCorrelation_FFT()
MJR: Autocorrelation function using FFT algorithm for extra speed.
void PowerSpectrumAnalysis()
RC: Perform spectral analysis of MCMC .
void BatchedMeans()
CW: Batched means, literally read from an array and chuck into TH1D.

◆ DrawCorrelations1D()

void MCMCProcessor::DrawCorrelations1D ( )
protected

Draw 1D correlations which might be more helpful than looking at huge 2D Corr matrix.

Definition at line 1690 of file MCMCProcessor.cpp.

1690  {
1691 // *********************
1692  //KS: Store it as we go back to them at the end
1693  const std::vector<double> Margins = GetMargins(Posterior);
1694  const int OptTitle = gStyle->GetOptTitle();
1695 
1696  Posterior->SetTopMargin(0.1);
1697  Posterior->SetBottomMargin(0.2);
1698  gStyle->SetOptTitle(1);
1699 
1700  constexpr int Nhists = 3;
1701  //KS: Highest value is just meant bo be sliglhy higher than 1 to catch >,
1702  constexpr double Thresholds[Nhists+1] = {0, 0.25, 0.5, 1.0001};
1703  constexpr Color_t CorrColours[Nhists] = {kRed-10, kRed-6, kRed};
1704 
1705  //KS: This store necessary entries for stripped covariance which store only "meaningful correlations
1706  std::vector<std::vector<double>> CorrOfInterest;
1707  CorrOfInterest.resize(nDraw);
1708  std::vector<std::vector<std::string>> NameCorrOfInterest;
1709  NameCorrOfInterest.resize(nDraw);
1710 
1711  std::vector<std::vector<std::unique_ptr<TH1D>>> Corr1DHist(nDraw);
1712  //KS: Initialising ROOT objects is never safe in MP loop
1713  for(int i = 0; i < nDraw; ++i)
1714  {
1715  TString Title = "";
1716  double Prior = 1.0, PriorError = 1.0;
1717  GetNthParameter(i, Prior, PriorError, Title);
1718 
1719  Corr1DHist[i].resize(Nhists);
1720  for(int j = 0; j < Nhists; ++j)
1721  {
1722  Corr1DHist[i][j] = std::make_unique<TH1D>(Form("Corr1DHist_%i_%i", i, j), Form("Corr1DHist_%i_%i", i, j), nDraw, 0, nDraw);
1723  Corr1DHist[i][j]->SetTitle(Form("%s",Title.Data()));
1724  Corr1DHist[i][j]->SetDirectory(nullptr);
1725  Corr1DHist[i][j]->GetYaxis()->SetTitle("Correlation");
1726  Corr1DHist[i][j]->SetFillColor(CorrColours[j]);
1727  Corr1DHist[i][j]->SetLineColor(kBlack);
1728 
1729  for (int k = 0; k < nDraw; ++k)
1730  {
1731  TString Title_y = "";
1732  double Prior_y = 1.0;
1733  double PriorError_y = 1.0;
1734  GetNthParameter(k, Prior_y, PriorError_y, Title_y);
1735  Corr1DHist[i][j]->GetXaxis()->SetBinLabel(k+1, Title_y.Data());
1736  }
1737  }
1738  }
1739 
1740  // KS: Do not add collapse(2) otherwise one can intorduce race condition :(
1741  #ifdef MULTITHREAD
1742  #pragma omp parallel for
1743  #endif
1744  for(int i = 0; i < nDraw; ++i)
1745  {
1746  for(int j = 0; j < nDraw; ++j)
1747  {
1748  for(int k = 0; k < Nhists; ++k)
1749  {
1750  const double TempEntry = std::fabs((*Correlation)(i,j));
1751  if(Thresholds[k+1] > TempEntry && TempEntry >= Thresholds[k])
1752  {
1753  Corr1DHist[i][k]->SetBinContent(j+1, (*Correlation)(i,j));
1754  }
1755  }
1756  if(std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold && i != j)
1757  {
1758  CorrOfInterest[i].push_back((*Correlation)(i,j));
1759  NameCorrOfInterest[i].push_back(Corr1DHist[i][0]->GetXaxis()->GetBinLabel(j+1));
1760  }
1761  }
1762  }
1763 
1764  TDirectory *CorrDir = OutputFile->mkdir("Corr1D");
1765  CorrDir->cd();
1766 
1767  for(int i = 0; i < nDraw; i++)
1768  {
1769  if (ParamVaried[i] == false) continue;
1770 
1771  Corr1DHist[i][0]->GetXaxis()->LabelsOption("v");
1772  Corr1DHist[i][0]->SetMaximum(+1.);
1773  Corr1DHist[i][0]->SetMinimum(-1.);
1774  Corr1DHist[i][0]->Draw();
1775  for(int k = 1; k < Nhists; k++) {
1776  Corr1DHist[i][k]->Draw("SAME");
1777  }
1778 
1779  auto leg = std::make_unique<TLegend>(0.3, 0.75, 0.6, 0.90);
1780  SetLegendStyle(leg.get(), 0.02);
1781  for(int k = 0; k < Nhists; k++) {
1782  leg->AddEntry(Corr1DHist[i][k].get(), Form("%.2f > |Corr| >= %.2f", Thresholds[k+1], Thresholds[k]), "f");
1783  }
1784  leg->Draw("SAME");
1785 
1786  Posterior->Write(Corr1DHist[i][0]->GetTitle());
1787  if(printToPDF) Posterior->Print(CanvasName);
1788  }
1789 
1790  //KS: Plot only meaningful correlations
1791  for(int i = 0; i < nDraw; i++)
1792  {
1793  const int size = int(CorrOfInterest[i].size());
1794 
1795  if(size == 0) continue;
1796  auto Corr1DHist_Reduced = std::make_unique<TH1D>("Corr1DHist_Reduced", "Corr1DHist_Reduced", size, 0, size);
1797  Corr1DHist_Reduced->SetDirectory(nullptr);
1798  Corr1DHist_Reduced->SetTitle(Corr1DHist[i][0]->GetTitle());
1799  Corr1DHist_Reduced->GetYaxis()->SetTitle("Correlation");
1800  Corr1DHist_Reduced->SetFillColor(kBlue);
1801  Corr1DHist_Reduced->SetLineColor(kBlue);
1802 
1803  for (int j = 0; j < size; ++j)
1804  {
1805  Corr1DHist_Reduced->GetXaxis()->SetBinLabel(j+1, NameCorrOfInterest[i][j].c_str());
1806  Corr1DHist_Reduced->SetBinContent(j+1, CorrOfInterest[i][j]);
1807  }
1808  Corr1DHist_Reduced->GetXaxis()->LabelsOption("v");
1809 
1810  Corr1DHist_Reduced->SetMaximum(+1.);
1811  Corr1DHist_Reduced->SetMinimum(-1.);
1812  Corr1DHist_Reduced->Draw();
1813 
1814  Posterior->Write(Form("%s_Red", Corr1DHist_Reduced->GetTitle()));
1815  if(printToPDF) Posterior->Print(CanvasName);
1816  }
1817 
1818  CorrDir->Close();
1819  delete CorrDir;
1820  OutputFile->cd();
1821 
1822  SetMargins(Posterior, Margins);
1823  gStyle->SetOptTitle(OptTitle);
1824 }
std::vector< double > GetMargins(const std::unique_ptr< TCanvas > &Canv) const
Get TCanvas margins, to be able to reset them if particular function need different margins.
void SetMargins(std::unique_ptr< TCanvas > &Canv, const std::vector< double > &margins)
Set TCanvas margins to specified values.
std::vector< bool > ParamVaried
Is the ith parameter varied.

◆ DrawCorrelationsGroup()

void MCMCProcessor::DrawCorrelationsGroup ( const std::unique_ptr< TH2D > &  CorrMatrix) const
protected

Produces correlation matrix but instead of giving name for each param it only give name for param group.

Parameters
CorrMatrixcorrelation matrix that we are going to plot
Note
Inspired by plot in Ewan thesis see https://www.t2k.org/docs/thesis/152/Thesis#page=147

Definition at line 1580 of file MCMCProcessor.cpp.

1580  {
1581 // *********************
1582  MACH3LOG_INFO("Starting {}", __func__);
1583  const double RightMargin = Posterior->GetRightMargin();
1584  Posterior->SetRightMargin(0.15);
1585  auto MatrixCopy = M3::Clone(CorrMatrix.get());
1586 
1587  std::vector<std::string> GroupName;
1588  std::vector<int> GroupStart;
1589  std::vector<int> GroupEnd;
1590 
1591  // Loop over the Covariance matrix entries
1592  for (int iPar = 0; iPar < nDraw; ++iPar)
1593  {
1594  std::string GroupNameCurr;
1595  if(ParamType[iPar] == kXSecPar){
1596  const int InternalNumeration = iPar - ParamTypeStartPos[kXSecPar];
1597  GroupNameCurr = ParameterGroup[InternalNumeration];
1598  } else {
1599  GroupNameCurr = "Other"; // Use Other for all legacy params
1600  }
1601 
1602  if(iPar == 0) {
1603  GroupName.push_back(GroupNameCurr);
1604  GroupStart.push_back(0);
1605  } else if(GroupName.back() != GroupNameCurr ){
1606  GroupName.push_back(GroupNameCurr);
1607  GroupEnd.push_back(iPar);
1608  GroupStart.push_back(iPar);
1609  }
1610 
1611  MatrixCopy->GetXaxis()->SetBinLabel(iPar+1, "");
1612  MatrixCopy->GetYaxis()->SetBinLabel(iPar+1, "");
1613  }
1614  GroupEnd.push_back(nDraw);
1615 
1616  for(size_t iPar = 0; iPar < GroupName.size(); iPar++) {
1617  MACH3LOG_INFO("Group name {} from {} to {}", GroupName[iPar], GroupStart[iPar], GroupEnd[iPar]);
1618  }
1619  Posterior->cd();
1620  Posterior->Clear();
1621  MatrixCopy->Draw("colz");
1622 
1623  std::vector<std::unique_ptr<TLine>> groupLines; //((GroupStart.size() - 1) * 2);
1624 
1625  int nBinsX = MatrixCopy->GetNbinsX();
1626  int nBinsY = MatrixCopy->GetNbinsY();
1627 
1628  // Axis bounds from the histogram itself
1629  double xMin = MatrixCopy->GetXaxis()->GetBinLowEdge(1);
1630  double xMax = MatrixCopy->GetXaxis()->GetBinUpEdge(nBinsX);
1631  double yMin = MatrixCopy->GetYaxis()->GetBinLowEdge(1);
1632  double yMax = MatrixCopy->GetYaxis()->GetBinUpEdge(nBinsY);
1633 
1634  for (size_t g = 1; g < GroupStart.size(); ++g) {
1635  const double posX = MatrixCopy->GetXaxis()->GetBinLowEdge(GroupStart[g] + 1);
1636  const double posY = MatrixCopy->GetYaxis()->GetBinLowEdge(GroupStart[g] + 1);
1637 
1638  // Vertical line at group start
1639  auto vLine = std::make_unique<TLine>(posX, yMin, posX, yMax);
1640  vLine->SetLineColor(kBlack);
1641  vLine->SetLineWidth(2);
1642  vLine->Draw();
1643  groupLines.push_back(std::move(vLine));
1644 
1645  // Horizontal line at group start
1646  auto hLine = std::make_unique<TLine>(xMin, posY, xMax, posY);
1647  hLine->SetLineColor(kBlack);
1648  hLine->SetLineWidth(2);
1649  hLine->Draw();
1650  groupLines.push_back(std::move(hLine));
1651  }
1652 
1653  std::vector<std::unique_ptr<TText>> groupLabels(GroupName.size() * 2);
1654  const double yOffsetBelow = 0.05 * (yMax - yMin); // space below x-axis
1655  const double xOffsetRight = 0.02 * (xMax - xMin); // space right of y-axis
1656 
1657  for (size_t g = 0; g < GroupName.size(); ++g) {
1658  const int startBin = GroupStart[g] + 1; // hist bins start at 1
1659  const int endBin = GroupEnd[g];
1660 
1661  const double xStart = MatrixCopy->GetXaxis()->GetBinLowEdge(startBin);
1662  const double xEnd = MatrixCopy->GetXaxis()->GetBinUpEdge(endBin);
1663  const double xMid = 0.5 * (xStart + xEnd);
1664 
1665  const double yStart = MatrixCopy->GetYaxis()->GetBinLowEdge(startBin);
1666  const double yEnd = MatrixCopy->GetYaxis()->GetBinUpEdge(endBin);
1667  const double yMid = 0.5 * (yStart + yEnd);
1668 
1669  // Label along X-axis (below histogram)
1670  auto labelX = std::make_unique<TText>(xMid, yMin - yOffsetBelow, GroupName[g].c_str());
1671  labelX->SetTextAlign(23); // center horizontally, top-aligned vertically
1672  labelX->SetTextSize(0.025);
1673  labelX->Draw();
1674  groupLabels.push_back(std::move(labelX));
1675 
1676  // Label along Y-axis (left of histogram)
1677  auto labelY = std::make_unique<TText>(xMin - xOffsetRight, yMid, GroupName[g].c_str());
1678  labelY->SetTextAlign(32); // right-aligned horizontally, center vertically
1679  labelY->SetTextSize(0.025);
1680  labelY->Draw();
1681  groupLabels.push_back(std::move(labelY));
1682  }
1683 
1684  if(printToPDF) Posterior->Print(CanvasName);
1685  Posterior->SetRightMargin(RightMargin);
1686 }
@ kXSecPar
Definition: MCMCProcessor.h:46
std::vector< ParameterEnum > ParamType
Make an enum for which class this parameter belongs to so we don't have to keep string comparing.
std::vector< std::string > ParameterGroup
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.

◆ DrawCovariance()

void MCMCProcessor::DrawCovariance ( )

Draw the post-fit covariances.

Definition at line 1431 of file MCMCProcessor.cpp.

1431  {
1432 // *********************
1433  const double RightMargin = Posterior->GetRightMargin();
1434  Posterior->SetRightMargin(0.15);
1435 
1436  // The Covariance matrix from the fit
1437  auto hCov = std::make_unique<TH2D>("hCov", "hCov", nDraw, 0, nDraw, nDraw, 0, nDraw);
1438  hCov->GetZaxis()->SetTitle("Covariance");
1439  hCov->SetDirectory(nullptr);
1440  // The Covariance matrix square root, with correct sign
1441  auto hCovSq = std::make_unique<TH2D>("hCovSq", "hCovSq", nDraw, 0, nDraw, nDraw, 0, nDraw);
1442  hCovSq->SetDirectory(nullptr);
1443  hCovSq->GetZaxis()->SetTitle("Covariance");
1444  // The Correlation
1445  auto hCorr = std::make_unique<TH2D>("hCorr", "hCorr", nDraw, 0, nDraw, nDraw, 0, nDraw);
1446  hCorr->SetDirectory(nullptr);
1447  hCorr->GetZaxis()->SetTitle("Correlation");
1448  hCorr->SetMinimum(-1);
1449  hCorr->SetMaximum(1);
1450  hCov->GetXaxis()->SetLabelSize(0.015);
1451  hCov->GetYaxis()->SetLabelSize(0.015);
1452  hCovSq->GetXaxis()->SetLabelSize(0.015);
1453  hCovSq->GetYaxis()->SetLabelSize(0.015);
1454  hCorr->GetXaxis()->SetLabelSize(0.015);
1455  hCorr->GetYaxis()->SetLabelSize(0.015);
1456 
1457  // Loop over the Covariance matrix entries
1458  for (int i = 0; i < nDraw; ++i)
1459  {
1460  TString titlex = "";
1461  double nom, err;
1462  GetNthParameter(i, nom, err, titlex);
1463 
1464  hCov->GetXaxis()->SetBinLabel(i+1, titlex);
1465  hCovSq->GetXaxis()->SetBinLabel(i+1, titlex);
1466  hCorr->GetXaxis()->SetBinLabel(i+1, titlex);
1467 
1468  for (int j = 0; j < nDraw; ++j)
1469  {
1470  // The value of the Covariance
1471  const double cov = (*Covariance)(i,j);
1472  const double corr = (*Correlation)(i,j);
1473 
1474  hCov->SetBinContent(i+1, j+1, cov);
1475  hCovSq->SetBinContent(i+1, j+1, ((cov > 0) - (cov < 0))*std::sqrt(std::fabs(cov)));
1476  hCorr->SetBinContent(i+1, j+1, corr);
1477 
1478  TString titley = "";
1479  double nom_j, err_j;
1480  GetNthParameter(j, nom_j, err_j, titley);
1481 
1482  hCov->GetYaxis()->SetBinLabel(j+1, titley);
1483  hCovSq->GetYaxis()->SetBinLabel(j+1, titley);
1484  hCorr->GetYaxis()->SetBinLabel(j+1, titley);
1485  }
1486  }
1487 
1488  // Take away the stat box
1489  gStyle->SetOptStat(0);
1490  if(plotBinValue)gStyle->SetPaintTextFormat("4.1f"); //Precision of value in matrix element
1491  // Make pretty Correlation colors (red to blue)
1492  constexpr int NRGBs = 5;
1493  TColor::InitializeColors();
1494  Double_t stops[NRGBs] = { 0.00, 0.25, 0.50, 0.75, 1.00 };
1495  Double_t red[NRGBs] = { 0.00, 0.25, 1.00, 1.00, 0.50 };
1496  Double_t green[NRGBs] = { 0.00, 0.25, 1.00, 0.25, 0.00 };
1497  Double_t blue[NRGBs] = { 0.50, 1.00, 1.00, 0.25, 0.00 };
1498  TColor::CreateGradientColorTable(5, stops, red, green, blue, 255);
1499  gStyle->SetNumberContours(255);
1500 
1501  // cd into the correlation directory
1502  OutputFile->cd();
1503 
1504  Posterior->cd();
1505  Posterior->Clear();
1506  if(plotBinValue) hCov->Draw("colz text");
1507  else hCov->Draw("colz");
1508  if(printToPDF) Posterior->Print(CanvasName);
1509 
1510  Posterior->cd();
1511  Posterior->Clear();
1512  if(plotBinValue) hCorr->Draw("colz text");
1513  else hCorr->Draw("colz");
1514  if(printToPDF) Posterior->Print(CanvasName);
1515 
1516  hCov->Write("Covariance_plot");
1517  hCovSq->Write("Covariance_sq_plot");
1518  hCorr->Write("Correlation_plot");
1519 
1520  //Back to normal
1521  Posterior->SetRightMargin(RightMargin);
1522  DrawCorrelationsGroup(hCorr);
1524 }
void DrawCorrelations1D()
Draw 1D correlations which might be more helpful than looking at huge 2D Corr matrix.
void DrawCorrelationsGroup(const std::unique_ptr< TH2D > &CorrMatrix) const
Produces correlation matrix but instead of giving name for each param it only give name for param gro...

◆ DrawPosterior()

void MCMCProcessor::DrawPosterior ( const int  i,
TDirectory *  PostDir,
TDirectory *  PostHistDir 
)
protected

Perform plot of 1d marginalised posterior with HPD etc.

Definition at line 229 of file MCMCProcessor.cpp.

229  {
230 // ***************
231  TString Title = "";
232  double Prior = 1.0, PriorError = 1.0;
233  GetNthParameter(i, Prior, PriorError, Title);
234  bool isFlat = GetParamFlat(i);
235 
236  if(ApplySmoothing) hpost[i]->Smooth();
237 
238  (*Central_Value)(i) = Prior;
239 
240  double Mean, Err, Err_p, Err_m;
241  GetArithmetic(hpost[i], Mean, Err);
242  (*Means)(i) = Mean;
243  (*Errors)(i) = Err;
244 
245  GetGaussian(hpost[i], Gauss.get(), Mean, Err);
246  (*Means_Gauss)(i) = Mean;
247  (*Errors_Gauss)(i) = Err;
248 
249  GetHPD(hpost[i], Mean, Err, Err_p, Err_m);
250  (*Means_HPD)(i) = Mean;
251  (*Errors_HPD)(i) = Err;
252  (*Errors_HPD_Positive)(i) = Err_p;
253  (*Errors_HPD_Negative)(i) = Err_m;
254 
255  // Write the results from the projection into the TVectors and TMatrices
256  (*Covariance)(i,i) = (*Errors)(i)*(*Errors)(i);
257  (*Correlation)(i,i) = 1.0;
258 
259  //KS: This need to be before SetMaximum(), this way plot is nicer as line end at the maximum
260  auto hpd = std::make_unique<TLine>((*Means_HPD)(i), hpost[i]->GetMinimum(), (*Means_HPD)(i), hpost[i]->GetMaximum());
261  SetTLineStyle(hpd.get(), kBlack, 2, kSolid);
262 
263  hpost[i]->SetLineWidth(2);
264  hpost[i]->SetLineColor(kBlue-1);
265  hpost[i]->SetMaximum(hpost[i]->GetMaximum()*DrawRange);
266  hpost[i]->SetTitle(Title);
267  hpost[i]->GetXaxis()->SetTitle(hpost[i]->GetTitle());
268 
269  // Now make the TLine for the Asimov
270  auto Asimov = std::make_unique<TLine>(Prior, hpost[i]->GetMinimum(), Prior, hpost[i]->GetMaximum());
271  SetTLineStyle(Asimov.get(), kRed-3, 2, kDashed);
272 
273  auto leg = std::make_unique<TLegend>(0.15, 0.6, 0.6, 0.95);
274  SetLegendStyle(leg.get(), 0.04);
275  leg->AddEntry(hpost[i], Form("#splitline{PDF}{#mu = %.2f, #sigma = %.2f}", hpost[i]->GetMean(), hpost[i]->GetRMS()), "l");
276  leg->AddEntry(Gauss.get(), Form("#splitline{Gauss}{#mu = %.2f, #sigma = %.2f}", Gauss->GetParameter(1), Gauss->GetParameter(2)), "l");
277  leg->AddEntry(hpd.get(), Form("#splitline{HPD}{#mu = %.2f, #sigma = %.2f (+%.2f-%.2f)}", (*Means_HPD)(i), (*Errors_HPD)(i), (*Errors_HPD_Positive)(i), (*Errors_HPD_Negative)(i)), "l");
278  if(isFlat && !PlotFlatPrior) leg->AddEntry(Asimov.get(), Form("#splitline{Prior}{x = %.2f}", Prior), "l");
279  else leg->AddEntry(Asimov.get(), Form("#splitline{Prior}{x = %.2f , #sigma = %.2f}", Prior, PriorError), "l");
280 
281  // Write to file
282  Posterior->SetName(Title);
283  Posterior->SetTitle(Title);
284 
285  //CW: Don't plot if this is a fixed histogram (i.e. the peak is the whole integral)
286  if (hpost[i]->GetMaximum() == hpost[i]->Integral()*DrawRange)
287  {
288  MACH3LOG_WARN("Found fixed parameter: {} ({}), moving on", Title, i);
289  ParamVaried[i] = false;
290  //KS:Set mean and error to prior for fixed parameters, it looks much better when fixed parameter has mean on prior rather than on 0 with 0 error.
291  (*Means_HPD)(i) = Prior;
292  (*Errors_HPD)(i) = PriorError;
293  (*Errors_HPD_Positive)(i) = PriorError;
294  (*Errors_HPD_Negative)(i) = PriorError;
295 
296  (*Means_Gauss)(i) = Prior;
297  (*Errors_Gauss)(i) = PriorError;
298 
299  (*Means)(i) = Prior;
300  (*Errors)(i) = PriorError;
301  return;
302  }
303 
304  // Store that this parameter is indeed being varied
305  ParamVaried[i] = true;
306 
307  // Draw onto the TCanvas
308  hpost[i]->Draw();
309  hpd->Draw("same");
310  Asimov->Draw("same");
311  leg->Draw("same");
312 
313  if(printToPDF) Posterior->Print(CanvasName);
314 
315  // cd into params directory in root file
316  PostDir->cd();
317  Posterior->Write();
318 
319  hpost[i]->SetName(Title);
320  hpost[i]->SetTitle(Title);
321  PostHistDir->cd();
322  hpost[i]->Write();
323 }
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
bool isFlat(TSpline3_red *&spl)
CW: Helper function used in the constructor, tests to see if the spline is flat.
void GetGaussian(TH1D *&hist, TF1 *gauss, double &Mean, double &Error)
CW: Fit Gaussian to posterior.
void GetHPD(TH1D *const hist, double &Mean, double &Error, double &Error_p, double &Error_m, const double coverage)
Get Highest Posterior Density (HPD)
void GetArithmetic(TH1D *const hist, double &Mean, double &Error)
CW: Get Arithmetic mean from posterior.
std::unique_ptr< TF1 > Gauss
Gaussian fitter.
bool GetParamFlat(const int iParam) const
Get whether param has flat prior or not.
void SetTLineStyle(TLine *Line, const Color_t Colour, const Width_t Width, const ELineStyle Style) const
Configures a TLine object with the specified style parameters.

◆ DrawPostfit()

void MCMCProcessor::DrawPostfit ( )

Draw the post-fit comparisons.

Definition at line 452 of file MCMCProcessor.cpp.

452  {
453 // *******************
454  if (OutputFile == nullptr) MakeOutputFile();
455 
456  // Make the prefit plot
457  std::unique_ptr<TH1D> prefit = MakePrefit();
458 
459  prefit->GetXaxis()->SetTitle("");
460  // cd into the output file
461  OutputFile->cd();
462 
463  std::string CutPosterior1D = "";
464  if(Posterior1DCut != "")
465  {
466  CutPosterior1D = StepCut +" && " + Posterior1DCut;
467  }
468  else CutPosterior1D = StepCut;
469 
470  // Make a TH1D of the central values and the errors
471  std::unique_ptr<TH1D> paramPlot = std::make_unique<TH1D>("paramPlot", "paramPlot", nDraw, 0, nDraw);
472  paramPlot->SetDirectory(nullptr);
473  paramPlot->SetName("mach3params");
474  paramPlot->SetTitle(CutPosterior1D.c_str());
475  paramPlot->SetFillStyle(3001);
476  paramPlot->SetFillColor(kBlue-1);
477  paramPlot->SetMarkerColor(paramPlot->GetFillColor());
478  paramPlot->SetMarkerStyle(20);
479  paramPlot->SetLineColor(paramPlot->GetFillColor());
480  paramPlot->SetMarkerSize(prefit->GetMarkerSize());
481  paramPlot->GetXaxis()->SetTitle("");
482 
483  // Same but with Gaussian output
484  std::unique_ptr<TH1D> paramPlot_Gauss = M3::Clone(paramPlot.get());
485  paramPlot_Gauss->SetMarkerColor(kOrange-5);
486  paramPlot_Gauss->SetMarkerStyle(23);
487  paramPlot_Gauss->SetLineWidth(2);
488  paramPlot_Gauss->SetMarkerSize((prefit->GetMarkerSize())*0.75);
489  paramPlot_Gauss->SetFillColor(paramPlot_Gauss->GetMarkerColor());
490  paramPlot_Gauss->SetFillStyle(3244);
491  paramPlot_Gauss->SetLineColor(paramPlot_Gauss->GetMarkerColor());
492  paramPlot_Gauss->GetXaxis()->SetTitle("");
493 
494  // Same but with Gaussian output
495  std::unique_ptr<TH1D> paramPlot_HPD = M3::Clone(paramPlot.get());
496  paramPlot_HPD->SetMarkerColor(kBlack);
497  paramPlot_HPD->SetMarkerStyle(25);
498  paramPlot_HPD->SetLineWidth(2);
499  paramPlot_HPD->SetMarkerSize((prefit->GetMarkerSize())*0.5);
500  paramPlot_HPD->SetFillColor(0);
501  paramPlot_HPD->SetFillStyle(0);
502  paramPlot_HPD->SetLineColor(paramPlot_HPD->GetMarkerColor());
503  paramPlot_HPD->GetXaxis()->SetTitle("");
504 
505  // Set labels and data
506  for (int i = 0; i < nDraw; ++i)
507  {
508  //Those keep which parameter type we run currently and relative number
509  int ParamEnu = ParamType[i];
510  int ParamNo = i - ParamTypeStartPos[ParameterEnum(ParamEnu)];
511 
512  //KS: Slightly hacky way to get relative to prior or nominal as this is convention we use
513  //This only applies for xsec for other systematic types doesn't matter
514  double CentralValueTemp = 0;
515  double Central, Central_gauss, Central_HPD;
516  double Err, Err_Gauss, Err_HPD;
517 
519  {
520  CentralValueTemp = ParamCentral[ParamEnu][ParamNo];
521  // Normalise the prior relative the nominal/prior, just the way we get our fit results in MaCh3
522  if ( CentralValueTemp != 0)
523  {
524  Central = (*Means)(i) / CentralValueTemp;
525  Err = (*Errors)(i) / CentralValueTemp;
526 
527  Central_gauss = (*Means_Gauss)(i) / CentralValueTemp;
528  Err_Gauss = (*Errors_Gauss)(i) / CentralValueTemp;
529 
530  Central_HPD = (*Means_HPD)(i) / CentralValueTemp;
531  Err_HPD = (*Errors_HPD)(i) / CentralValueTemp;
532  }
533  else {
534  Central = 1+(*Means)(i);
535  Err = (*Errors)(i);
536 
537  Central_gauss = 1+(*Means_Gauss)(i);
538  Err_Gauss = (*Errors_Gauss)(i);
539 
540  Central_HPD = 1+(*Means_HPD)(i) ;
541  Err_HPD = (*Errors_HPD)(i);
542  }
543  }
544  //KS: Just get value of each parameter without dividing by prior
545  else
546  {
547  Central = (*Means)(i);
548  Err = (*Errors)(i);
549 
550  Central_gauss = (*Means_Gauss)(i);
551  Err_Gauss = (*Errors_Gauss)(i);
552 
553  Central_HPD = (*Means_HPD)(i) ;
554  Err_HPD = (*Errors_HPD)(i);
555  }
556 
557  paramPlot->SetBinContent(i+1, Central);
558  paramPlot->SetBinError(i+1, Err);
559 
560  paramPlot_Gauss->SetBinContent(i+1, Central_gauss);
561  paramPlot_Gauss->SetBinError(i+1, Err_Gauss);
562 
563  paramPlot_HPD->SetBinContent(i+1, Central_HPD);
564  paramPlot_HPD->SetBinError(i+1, Err_HPD);
565 
566  paramPlot->GetXaxis()->SetBinLabel(i+1, prefit->GetXaxis()->GetBinLabel(i+1));
567  paramPlot_Gauss->GetXaxis()->SetBinLabel(i+1, prefit->GetXaxis()->GetBinLabel(i+1));
568  paramPlot_HPD->GetXaxis()->SetBinLabel(i+1, prefit->GetXaxis()->GetBinLabel(i+1));
569  }
570  prefit->GetXaxis()->LabelsOption("v");
571  paramPlot->GetXaxis()->LabelsOption("v");\
572  paramPlot_Gauss->GetXaxis()->LabelsOption("v");
573  paramPlot_HPD->GetXaxis()->LabelsOption("v");
574 
575  // Make a TLegend
576  auto CompLeg = std::make_unique<TLegend>(0.33, 0.73, 0.76, 0.95);
577  CompLeg->AddEntry(prefit.get(), "Prefit", "fp");
578  CompLeg->AddEntry(paramPlot.get(), "Postfit PDF", "fp");
579  CompLeg->AddEntry(paramPlot_Gauss.get(), "Postfit Gauss", "fp");
580  CompLeg->AddEntry(paramPlot_HPD.get(), "Postfit HPD", "lfep");
581  CompLeg->SetFillColor(0);
582  CompLeg->SetFillStyle(0);
583  CompLeg->SetLineWidth(0);
584  CompLeg->SetLineStyle(0);
585  CompLeg->SetBorderSize(0);
586 
587  const std::vector<double> Margins = GetMargins(Posterior);
588  Posterior->SetBottomMargin(0.2);
589 
590  OutputFile->cd();
591 
592  // Write the individual ones
593  prefit->Write("param_xsec_prefit");
594  paramPlot->Write("param_xsec");
595  paramPlot_Gauss->Write("param_xsec_gaus");
596  paramPlot_HPD->Write("param_xsec_HPD");
597 
598  // Plot the xsec parameters (0 to ~nXsec-nFlux) nXsec == xsec + flux, quite confusing I know
599  // Have already looked through the branches earlier
600  if(plotRelativeToPrior) prefit->GetYaxis()->SetTitle("Variation rel. prior");
601  else prefit->GetYaxis()->SetTitle("Parameter Value");
602  prefit->GetYaxis()->SetRangeUser(-2.5, 2.5);
603 
604  // And the combined
605  prefit->Draw("e2");
606  paramPlot->Draw("e2, same");
607  paramPlot_Gauss->Draw("e2, same");
608  paramPlot_HPD->Draw("e1, same");
609  CompLeg->Draw("same");
610  Posterior->Write("param_xsec_canv");
611 
612  //KS: Tells how many parameters in one canvas we want
613  constexpr int IntervalsSize = 20;
614  const int NIntervals = nDraw/IntervalsSize;
615 
616  for (int i = 0; i < NIntervals+1; ++i)
617  {
618  int RangeMin = i*IntervalsSize;
619  int RangeMax =RangeMin + IntervalsSize;
620  if(i == NIntervals+1) {
621  RangeMin = i*IntervalsSize;
622  RangeMax = nDraw;
623  }
624  if(RangeMin >= nDraw) break;
625 
626  double ymin = std::numeric_limits<double>::max();
627  double ymax = -std::numeric_limits<double>::max();
628  for (int b = RangeMin; b <= RangeMax; ++b) {
629  // prefit
630  {
631  double val = prefit->GetBinContent(b);
632  double err = prefit->GetBinError(b);
633  ymin = std::min(ymin, val - err);
634  ymax = std::max(ymax, val + err);
635  }
636  // paramPlot_HPD
637  {
638  double val = paramPlot_HPD->GetBinContent(b);
639  double err = paramPlot_HPD->GetBinError(b);
640  ymin = std::min(ymin, val - err);
641  ymax = std::max(ymax, val + err);
642  }
643  }
644 
645  double margin = 0.1 * (ymax - ymin);
646  prefit->GetYaxis()->SetRangeUser(ymin - margin, ymax + margin);
647 
648  prefit->GetXaxis()->SetRangeUser(RangeMin, RangeMax);
649  paramPlot->GetXaxis()->SetRangeUser(RangeMin, RangeMax);
650  paramPlot_Gauss->GetXaxis()->SetRangeUser(RangeMin, RangeMax);
651  paramPlot_HPD->GetXaxis()->SetRangeUser(RangeMin, RangeMax);
652 
653  // And the combined
654  prefit->Draw("e2");
655  paramPlot->Draw("e2, same");
656  paramPlot_Gauss->Draw("e2, same");
657  paramPlot_HPD->Draw("e1, same");
658  CompLeg->Draw("same");
659  if(printToPDF) Posterior->Print(CanvasName);
660  Posterior->Clear();
661  }
662 
663  if(nParam[kNDPar] > 0)
664  {
665  int Start = ParamTypeStartPos[kNDPar];
666  int NDbinCounter = Start;
667  //KS: Make prefit postfit for each ND sample, having all of them at the same plot is unreadable
668  for(unsigned int i = 0; i < NDSamplesNames.size(); i++ )
669  {
670  std::string NDname = NDSamplesNames[i];
671  NDbinCounter += NDSamplesBins[i];
672  OutputFile->cd();
673  prefit->GetYaxis()->SetTitle(("Variation for "+NDname).c_str());
674  prefit->GetYaxis()->SetRangeUser(0.6, 1.4);
675  prefit->GetXaxis()->SetRangeUser(Start, NDbinCounter);
676 
677  paramPlot->GetYaxis()->SetTitle(("Variation for "+NDname).c_str());
678  paramPlot->GetYaxis()->SetRangeUser(0.6, 1.4);
679  paramPlot->GetXaxis()->SetRangeUser(Start, NDbinCounter);
680  paramPlot->SetTitle(CutPosterior1D.c_str());
681 
682  paramPlot_Gauss->GetYaxis()->SetTitle(("Variation for "+NDname).c_str());
683  paramPlot_Gauss->GetYaxis()->SetRangeUser(0.6, 1.4);
684  paramPlot_Gauss->GetXaxis()->SetRangeUser(Start, NDbinCounter);
685  paramPlot_Gauss->SetTitle(CutPosterior1D.c_str());
686 
687  paramPlot_HPD->GetYaxis()->SetTitle(("Variation for "+NDname).c_str());
688  paramPlot_HPD->GetYaxis()->SetRangeUser(0.6, 1.4);
689  paramPlot_HPD->GetXaxis()->SetRangeUser(Start, NDbinCounter);
690  paramPlot_HPD->SetTitle(CutPosterior1D.c_str());
691 
692  prefit->Write(("param_"+NDname+"_prefit").c_str());
693  paramPlot->Write(("param_"+NDname).c_str());
694  paramPlot_Gauss->Write(("param_"+NDname+"_gaus").c_str());
695  paramPlot_HPD->Write(("param_"+NDname+"_HPD").c_str());
696 
697  prefit->Draw("e2");
698  paramPlot->Draw("e2, same");
699  paramPlot_Gauss->Draw("e1, same");
700  paramPlot_HPD->Draw("e1, same");
701  CompLeg->Draw("same");
702  Posterior->Write(("param_"+NDname+"_canv").c_str());
703  if(printToPDF) Posterior->Print(CanvasName);
704  Posterior->Clear();
705  Start += NDSamplesBins[i];
706  }
707  }
708  //KS: Return Margin to default one
709  SetMargins(Posterior, Margins);
710 }
ParameterEnum
Definition: MCMCProcessor.h:45
@ kNDPar
Definition: MCMCProcessor.h:47
std::unique_ptr< TH1D > MakePrefit()
Prepare prefit histogram for parameter overlay plot.
void MakeOutputFile()
prepare output root file and canvas to which we will save EVERYTHING
std::vector< std::string > NDSamplesNames
std::vector< int > NDSamplesBins

◆ FindInputFiles()

void MCMCProcessor::FindInputFiles ( )
protected

Read the output MCMC file and find what inputs were used.

Definition at line 2545 of file MCMCProcessor.cpp.

2545  {
2546 // **************************
2547  // Now read the MCMC file
2548  TFile *TempFile = M3::Open(MCMCFile, "open", __FILE__, __LINE__);
2549  TDirectory* CovarianceFolder = TempFile->Get<TDirectory>("CovarianceFolder");
2550 
2551  // Get the settings for the MCMC
2552  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2553 
2554  if (Config == nullptr) {
2555  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2556  TempFile->ls();
2557  throw MaCh3Exception(__FILE__ , __LINE__ );
2558  }
2559  MACH3LOG_INFO("Loading YAML config from MCMC chain");
2560 
2561  YAML::Node Settings = TMacroToYAML(*Config);
2562 
2563  bool InputNotFound = false;
2564  //CW: Get the xsec Covariance matrix
2565  CovPos[kXSecPar] = GetFromManager<std::vector<std::string>>(Settings["General"]["Systematics"]["XsecCovFile"], {"none"}, __FILE__ , __LINE__);
2566  if(CovPos[kXSecPar].back() == "none")
2567  {
2568  MACH3LOG_WARN("Couldn't find XsecCov branch in output");
2569  InputNotFound = true;
2570  }
2571 
2572  TMacro *XsecConfig = M3::GetConfigMacroFromChain(CovarianceFolder);
2573  if (XsecConfig == nullptr) {
2574  MACH3LOG_WARN("Didn't find Config_xsec_cov tree in MCMC file! {}", MCMCFile);
2575  } else {
2576  CovConfig[kXSecPar] = TMacroToYAML(*XsecConfig);
2577  }
2578  if(InputNotFound) M3::Utils::PrintConfig(Settings);
2579 
2580  for(size_t i = 0; i < CovPos[kXSecPar].size(); i++)
2582 
2583  // Delete the TTrees and the input file handle since we've now got the settings we need
2584  delete Config;
2585  delete XsecConfig;
2586 
2587  TMacro *ReweightConfig = TempFile->Get<TMacro>("Reweight_Config");
2588  TMacro *UmbrellaConfig = TempFile->Get<TMacro>("Umbrella_Config");
2589 
2590  YAML::Node ReweightSettings;
2591  YAML::Node UmbrellaSettings;
2592 
2593  if (ReweightConfig != nullptr) {
2594  ReweightSettings = TMacroToYAML(*ReweightConfig);
2595  }
2596 
2597  if (UmbrellaConfig != nullptr) {
2598  UmbrellaSettings = TMacroToYAML(*UmbrellaConfig);
2599  }
2600 
2601  ReweightPosterior = true;
2602  for (const auto &name : ReweightNames) {
2603  bool found = false;
2604  // KS: For now umbrella_weight is specialised
2605  if (name == "umbrella_weight") {
2606  found = UmbrellaConfig != nullptr;
2607  } else {
2608  found = (ReweightConfig != nullptr) && ReweightSettings[name];
2609  }
2610 
2611  if (found) {
2612  MACH3LOG_INFO("Found reweight config for {}", name);
2613  } else {
2614  MACH3LOG_WARN("Missing reweight config for {}", name);
2615  ReweightPosterior = false;
2616  break;
2617  }
2618  }
2619 
2620  if (ReweightPosterior) {
2621  MACH3LOG_INFO("Enabling reweighting with configured weights.");
2622  }
2623 
2624  if (ReweightConfig != nullptr) {
2625  M3::Utils::PrintConfig(ReweightSettings);
2626  }
2627 
2628  if (UmbrellaConfig != nullptr) {
2629  M3::Utils::PrintConfig(UmbrellaSettings);
2630  }
2631 
2632  // Delete the MCMCFile pointer we're reading
2633  CovarianceFolder->Close();
2634  delete CovarianceFolder;
2635  TempFile->Close();
2636  delete TempFile;
2637 }
YAML::Node TMacroToYAML(const TMacro &macro)
KS: Convert a ROOT TMacro object to a YAML node.
Definition: YamlHelper.h:152
void PrintConfig(const YAML::Node &node)
KS: Print Yaml config using logger.
Definition: Monitor.cpp:311
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.
void AddPath(std::string &FilePath)
Prepends the MACH3 environment path to FilePath if it is not already present.
Definition: Monitor.cpp:382
TMacro * GetConfigMacroFromChain(TDirectory *CovarianceFolder)
KS: We store configuration macros inside the chain. In the past, multiple configs were stored,...
Structure to hold reweight configuration.

◆ FindInputFilesLegacy()

void MCMCProcessor::FindInputFilesLegacy ( )
protected
Warning
This will no longer be supported in future

Definition at line 2641 of file MCMCProcessor.cpp.

2641  {
2642 // **************************
2643  // Now read the MCMC file
2644  TFile *TempFile = M3::Open(MCMCFile, "open", __FILE__, __LINE__);
2645  // Get the settings for the MCMC
2646  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2647 
2648  if (Config == nullptr) {
2649  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2650  TempFile->ls();
2651  throw MaCh3Exception(__FILE__ , __LINE__ );
2652  }
2653  YAML::Node Settings = TMacroToYAML(*Config);
2654 
2655  //CW: And the ND Covariance matrix
2656  CovPos[kNDPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovFile"], "none", __FILE__ , __LINE__));
2657 
2658  if(CovPos[kNDPar].back() == "none") {
2659  MACH3LOG_WARN("Couldn't find NDCov (legacy) branch in output");
2660  } else{
2661  //If the FD Cov is not none, then you need the name of the covariance object to grab
2662  CovNamePos[kNDPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovName"], "none", __FILE__ , __LINE__);
2663  MACH3LOG_INFO("Given NDCovFile {} and NDCovName {}", CovPos[kNDPar].back(), CovNamePos[kNDPar]);
2664  }
2665 
2666  //CW: And the FD Covariance matrix
2667  CovPos[kFDDetPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovFile"], "none", __FILE__ , __LINE__));
2668 
2669  if(CovPos[kFDDetPar].back() == "none") {
2670  MACH3LOG_WARN("Couldn't find FDCov (legacy) branch in output");
2671  } else {
2672  //If the FD Cov is not none, then you need the name of the covariance object to grab
2673  CovNamePos[kFDDetPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovName"], "none", __FILE__ , __LINE__);
2674  MACH3LOG_INFO("Given FDCovFile {} and FDCovName {}", CovPos[kFDDetPar].back(), CovNamePos[kFDDetPar]);
2675  }
2676 
2677  for(size_t i = 0; i < CovPos[kNDPar].size(); i++)
2678  M3::AddPath(CovPos[kNDPar][i]);
2679 
2680  for(size_t i = 0; i < CovPos[kFDDetPar].size(); i++)
2682 
2683  TempFile->Close();
2684  delete TempFile;
2685 }
@ kFDDetPar
Definition: MCMCProcessor.h:48

◆ GetBayesFactor()

void MCMCProcessor::GetBayesFactor ( const std::vector< std::string > &  ParName,
const std::vector< std::vector< double >> &  Model1Bounds,
const std::vector< std::vector< double >> &  Model2Bounds,
const std::vector< std::vector< std::string >> &  ModelNames 
)

Calculate Bayes factor for vector of params, and model boundaries.

Parameters
ParNameVector with parameter names for which we calculate Bayes factor
Model1BoundsLower and upper bound for hypothesis 1. Within this bound we calculate integral used later for Bayes Factor
Model2BoundsLower and upper bound for hypothesis 2. Within this bound we calculate integral used later for Bayes Factor
ModelNamesNames for hypothesis 1 and 2

Definition at line 2968 of file MCMCProcessor.cpp.

2971  {
2972 // **************************
2973  if(hpost[0] == nullptr) MakePostfit();
2974 
2975  MACH3LOG_INFO("Calculating Bayes Factor");
2976  if((ParNames.size() != Model1Bounds.size()) || (Model2Bounds.size() != Model1Bounds.size()) || (Model2Bounds.size() != ModelNames.size()))
2977  {
2978  MACH3LOG_ERROR("Size doesn't match");
2979  throw MaCh3Exception(__FILE__ , __LINE__ );
2980  }
2981  for(unsigned int k = 0; k < ParNames.size(); ++k)
2982  {
2983  //KS: First we need to find parameter number based on name
2984  int ParamNo = GetParamIndexFromName(ParNames[k]);
2985  if(ParamNo == M3::_BAD_INT_)
2986  {
2987  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Bayes Factor", ParNames[k]);
2988  continue;
2989  }
2990 
2991  const double M1_min = Model1Bounds[k][0];
2992  const double M2_min = Model2Bounds[k][0];
2993  const double M1_max = Model1Bounds[k][1];
2994  const double M2_max = Model2Bounds[k][1];
2995 
2996  long double IntegralMode1 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M1_min), hpost[ParamNo]->FindFixBin(M1_max));
2997  long double IntegralMode2 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M2_min), hpost[ParamNo]->FindFixBin(M2_max));
2998 
2999  double BayesFactor = 0.;
3000  std::string Name = "";
3001  //KS: Calc Bayes Factor
3002  //If M1 is more likely
3003  if(IntegralMode1 >= IntegralMode2)
3004  {
3005  BayesFactor = IntegralMode1/IntegralMode2;
3006  Name = "\\mathfrak{B}(" + ModelNames[k][0]+ "/" + ModelNames[k][1] + ") = " + std::to_string(BayesFactor);
3007  }
3008  else //If M2 is more likely
3009  {
3010  BayesFactor = IntegralMode2/IntegralMode1;
3011  Name = "\\mathfrak{B}(" + ModelNames[k][1]+ "/" + ModelNames[k][0] + ") = " + std::to_string(BayesFactor);
3012  }
3013  std::string JeffreysScale = GetJeffreysScale(BayesFactor);
3014  std::string DunneKabothScale = GetDunneKaboth(BayesFactor);
3015 
3016  MACH3LOG_INFO("{} for {}", Name, ParNames[k]);
3017  MACH3LOG_INFO("Following Jeffreys Scale = {}", JeffreysScale);
3018  MACH3LOG_INFO("Following Dunne-Kaboth Scale = {}", DunneKabothScale);
3019  MACH3LOG_INFO("");
3020  }
3021 }
std::string GetDunneKaboth(const double BayesFactor)
Convert a Bayes factor into an approximate particle-physics significance level using the Dunne–Kaboth...
_MaCh3_Safe_Include_Start_ _MaCh3_Safe_Include_End_ std::string GetJeffreysScale(const double BayesFactor)
KS: Following H. Jeffreys .
void MakePostfit(const std::map< std::string, std::pair< double, double >> &Edges={})
Make 1D projection for each parameter and prepare structure.
int GetParamIndexFromName(const std::string &Name) const
Get parameter number based on name.

◆ GetBranchNames()

const std::vector<TString>& MCMCProcessor::GetBranchNames ( ) const
inline

Get the vector of branch names from root file.

Definition at line 248 of file MCMCProcessor.h.

248 { return BranchNames;};

◆ GetCovariance()

void MCMCProcessor::GetCovariance ( TMatrixDSym *&  Cov,
TMatrixDSym *&  Corr 
)

Get the post-fit covariances and correlations.

Parameters
CovCovariance matrix
CorrCorrelation matrix

Definition at line 187 of file MCMCProcessor.cpp.

187  {
188 // ***************
190  else MakeCovariance();
191  Cov = static_cast<TMatrixDSym*>(Covariance->Clone());
192  Corr = static_cast<TMatrixDSym*>(Correlation->Clone());
193 }
void MakeCovariance_MP(const bool Mute=false)
Calculate covariance by making 2D projection of each combination of parameters using multithreading.
void MakeCovariance()
Calculate covariance by making 2D projection of each combination of parameters.

◆ GetCovConfig()

YAML::Node MCMCProcessor::GetCovConfig ( const int  i) const
inline

Get Yaml config obtained from a Chain.

Definition at line 216 of file MCMCProcessor.h.

216 {return CovConfig.at(i); }

◆ GetFDCov()

std::string MCMCProcessor::GetFDCov ( ) const
inline

Definition at line 236 of file MCMCProcessor.h.

236 { return CovPos[kFDDetPar].back(); };

◆ GetGroup()

int MCMCProcessor::GetGroup ( const std::string &  name) const

Number of params from a given group, for example flux.

Definition at line 4570 of file MCMCProcessor.cpp.

4570  {
4571 // **************************
4572  // Lambda to compare strings case-insensitively
4573  auto caseInsensitiveCompare = [](const std::string& a, const std::string& b) {
4574  return std::equal(a.begin(), a.end(), b.begin(), b.end(),
4575  [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
4576  };
4577  int numerator = 0;
4578  for (const auto& groupName : ParameterGroup) {
4579  if (caseInsensitiveCompare(groupName, name)) {
4580  numerator++;
4581  }
4582  }
4583  return numerator;
4584 }

◆ GetHistRange()

std::pair< double, double > MCMCProcessor::GetHistRange ( const int  iParam) const
protected

Get Min/Max ranges for single parameter.

Definition at line 326 of file MCMCProcessor.cpp.

326  {
327 // ****************************
328  return {
329  hpost[iParam]->GetXaxis()->GetXmin(),
330  hpost[iParam]->GetXaxis()->GetXmax()
331  };
332 }

◆ GetHpost()

TH1D* MCMCProcessor::GetHpost ( const int  i) const
inline

Get 1D posterior for a given parameter.

Parameters
iparameter index

Definition at line 223 of file MCMCProcessor.h.

223 { return hpost[i]; };

◆ GetHpost2D()

TH2D* MCMCProcessor::GetHpost2D ( const int  i,
const int  j 
) const
inline

Get 2D posterior for a given parameter combination.

Parameters
iparameter index X
jparameter index Y

Definition at line 227 of file MCMCProcessor.h.

227 { return hpost2D[i][j]; };

◆ GetMargins()

std::vector< double > MCMCProcessor::GetMargins ( const std::unique_ptr< TCanvas > &  Canv) const
protected

Get TCanvas margins, to be able to reset them if particular function need different margins.

Definition at line 4614 of file MCMCProcessor.cpp.

4614  {
4615 // **************************
4616  return std::vector<double>{Canv->GetTopMargin(), Canv->GetBottomMargin(),
4617  Canv->GetLeftMargin(), Canv->GetRightMargin()};
4618 }

◆ GetNDCov()

std::string MCMCProcessor::GetNDCov ( ) const
inline

Definition at line 235 of file MCMCProcessor.h.

235 { return CovPos[kNDPar].back(); };

◆ GetnEntries()

Long64_t MCMCProcessor::GetnEntries ( )
inline

Get Number of entries that Chain has, for merged chains will not be the same Nsteps.

Definition at line 261 of file MCMCProcessor.h.

261 {return nEntries;};

◆ GetNFD()

int MCMCProcessor::GetNFD ( ) const
inline

Definition at line 213 of file MCMCProcessor.h.

213 { return nParam[kFDDetPar]; };

◆ GetNND()

int MCMCProcessor::GetNND ( ) const
inline

Definition at line 212 of file MCMCProcessor.h.

212 { return nParam[kNDPar]; };

◆ GetNParams()

int MCMCProcessor::GetNParams ( ) const
inline

Get total number of used parameters.

Definition at line 210 of file MCMCProcessor.h.

210 { return nDraw; };

◆ GetnSteps()

Long64_t MCMCProcessor::GetnSteps ( )
inline

Get Number of Steps that Chain has, for merged chains will not be the same nEntries.

Definition at line 263 of file MCMCProcessor.h.

263 {return nSteps;};

◆ GetNthParameter()

void MCMCProcessor::GetNthParameter ( const int  param,
double &  Prior,
double &  PriorError,
TString &  Title 
) const

Get properties of parameter by passing it number.

Definition at line 2848 of file MCMCProcessor.cpp.

2848  {
2849 // **************************
2850  ParameterEnum ParType = ParamType[param];
2851  int ParamNo = M3::_BAD_INT_;
2852  ParamNo = param - ParamTypeStartPos[ParType];
2853 
2854  Prior = ParamCentral[ParType][ParamNo];
2855  PriorError = ParamErrors[ParType][ParamNo];
2856  Title = ParamNames[ParType][ParamNo];
2857 }

◆ GetNXSec()

int MCMCProcessor::GetNXSec ( ) const
inline

Definition at line 211 of file MCMCProcessor.h.

211 { return nParam[kXSecPar]; };

◆ GetParameterSums()

std::vector< double > MCMCProcessor::GetParameterSums ( )
protected

Computes the average of each parameter across all MCMC entries. Useful for autocorrelation.

Definition at line 3633 of file MCMCProcessor.cpp.

3633  {
3634 // *********************************
3635  // Initialise the sums
3636  std::vector <double> ParamSums(nDraw,0);
3637 
3638  #ifdef MULTITHREAD
3639  #pragma omp parallel for
3640  #endif
3641  for (int j = 0; j < nDraw; ++j) {
3642  for (int i = 0; i < nEntries; ++i) {
3643  ParamSums[j] += ParStep[j][i];
3644  }
3645  }
3646  // Make the sums into average
3647  #ifdef MULTITHREAD
3648  #pragma omp parallel for
3649  #endif
3650  for (int i = 0; i < nDraw; ++i) {
3651  ParamSums[i] /= double(nEntries);
3652  }
3653  return ParamSums;
3654 }

◆ GetParamFlat()

bool MCMCProcessor::GetParamFlat ( const int  iParam) const

Get whether param has flat prior or not.

Definition at line 4657 of file MCMCProcessor.cpp.

4657  {
4658 // **************************
4659  ParameterEnum ParType = ParamType[iParam];
4660  int ParamTemp = iParam - ParamTypeStartPos[ParType];
4661  return ParamFlat[ParType][ParamTemp];
4662 }

◆ GetParamIndexFromName()

int MCMCProcessor::GetParamIndexFromName ( const std::string &  Name) const

Get parameter number based on name.

Definition at line 2861 of file MCMCProcessor.cpp.

2861  {
2862 // **************************
2863  int ParamNo = M3::_BAD_INT_;
2864  for (int i = 0; i < nDraw; ++i)
2865  {
2866  TString Title = "";
2867  double Prior = 1.0, PriorError = 1.0;
2868  GetNthParameter(i, Prior, PriorError, Title);
2869 
2870  if(Name == Title)
2871  {
2872  ParamNo = i;
2873  break;
2874  }
2875  }
2876  return ParamNo;
2877 }

◆ GetPolarPlot()

void MCMCProcessor::GetPolarPlot ( const std::vector< std::string > &  ParNames)

Make funny polar plot.

Parameters
ParNamesVector with parameter names for which Polar Plot will be made

Definition at line 2899 of file MCMCProcessor.cpp.

2899  {
2900 // **************************
2901  if(hpost[0] == nullptr) MakePostfit();
2902 
2903  std::vector<double> Margins = GetMargins(Posterior);
2904 
2905  Posterior->SetTopMargin(0.1);
2906  Posterior->SetBottomMargin(0.1);
2907  Posterior->SetLeftMargin(0.1);
2908  Posterior->SetRightMargin(0.1);
2909  Posterior->Update();
2910 
2911  MACH3LOG_INFO("Calculating Polar Plot");
2912  TDirectory *PolarDir = OutputFile->mkdir("PolarDir");
2913  PolarDir->cd();
2914 
2915  for(unsigned int k = 0; k < ParNames.size(); ++k)
2916  {
2917  //KS: First we need to find parameter number based on name
2918  int ParamNo = GetParamIndexFromName(ParNames[k]);
2919  if(ParamNo == M3::_BAD_INT_)
2920  {
2921  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Polar Plot", ParNames[k]);
2922  continue;
2923  }
2924 
2925  TString Title = "";
2926  double Prior = 1.0, PriorError = 1.0;
2927  GetNthParameter(ParamNo, Prior, PriorError, Title);
2928 
2929  std::vector<double> x_val(nBins);
2930  std::vector<double> y_val(nBins);
2931 
2932  constexpr double xmin = 0;
2933  constexpr double xmax = 2*TMath::Pi();
2934 
2935  double Integral = hpost[ParamNo]->Integral();
2936  for (Int_t ipt = 0; ipt < nBins; ipt++)
2937  {
2938  x_val[ipt] = ipt*(xmax-xmin)/nBins+xmin;
2939  y_val[ipt] = hpost[ParamNo]->GetBinContent(ipt+1)/Integral;
2940  }
2941 
2942  auto PolarGraph = std::make_unique<TGraphPolar>(nBins, x_val.data(), y_val.data());
2943  PolarGraph->SetLineWidth(2);
2944  PolarGraph->SetFillStyle(3001);
2945  PolarGraph->SetLineColor(kRed);
2946  PolarGraph->SetFillColor(kRed);
2947  PolarGraph->Draw("AFL");
2948 
2949  auto Text = std::make_unique<TText>(0.6, 0.1, Title);
2950  Text->SetTextSize(0.04);
2951  Text->SetNDC(true);
2952  Text->Draw("");
2953 
2954  Posterior->Print(CanvasName);
2955  Posterior->Write(Title);
2956  } //End loop over parameters
2957 
2958  PolarDir->Close();
2959  delete PolarDir;
2960 
2961  OutputFile->cd();
2962 
2963  SetMargins(Posterior, Margins);
2964 }

◆ GetPostfit()

void MCMCProcessor::GetPostfit ( TVectorD *&  Central,
TVectorD *&  Errors,
TVectorD *&  Central_Gauss,
TVectorD *&  Errors_Gauss,
TVectorD *&  Peaks 
)

Get the post-fit results (arithmetic and Gaussian)

Definition at line 154 of file MCMCProcessor.cpp.

154  {
155 // ***************
156  // Make the post fit
157  MakePostfit();
158 
159  // We now have the private members
160  Central_PDF = Means;
161  Errors_PDF = Errors;
162  Central_G = Means_Gauss;
163  Errors_G = Errors_Gauss;
164  Peak_Values = Means_HPD;
165 }

◆ GetPostfit_Ind()

void MCMCProcessor::GetPostfit_Ind ( TVectorD *&  Central,
TVectorD *&  Errors,
TVectorD *&  Peaks,
ParameterEnum  kParam 
)

Or the individual post-fits.

Definition at line 169 of file MCMCProcessor.cpp.

169  {
170 // ***************
171  // Make the post fit
172  MakePostfit();
173 
174  // Loop over the loaded param types
175  const int ParamTypeSize = int(ParamType.size());
176  int ParamNumber = 0;
177  for (int i = 0; i < ParamTypeSize; ++i) {
178  if (ParamType[i] != kParam) continue;
179  (*PDF_Central)(ParamNumber) = (*Means)(i);
180  (*PDF_Errors)(ParamNumber) = (*Errors)(i);
181  (*Peak_Values)(ParamNumber) = (*Means_HPD)(i);
182  ++ParamNumber;
183  }
184 }

◆ GetSampleBranchNames()

const std::vector<TString>& MCMCProcessor::GetSampleBranchNames ( ) const
inline

Get the vector of each sample branch names from root file.

Definition at line 250 of file MCMCProcessor.h.

250 { return SampleName_v;};
std::vector< TString > SampleName_v
Vector of each sample PDF object.

◆ GetSavageDickey()

void MCMCProcessor::GetSavageDickey ( const std::vector< std::string > &  ParName,
const std::vector< double > &  EvaluationPoint,
const std::vector< std::vector< double >> &  Bounds 
)

Calculate Bayes factor for point like hypothesis using SavageDickey.

Definition at line 3025 of file MCMCProcessor.cpp.

3027  {
3028 // **************************
3029  if((ParNames.size() != EvaluationPoint.size()) || (Bounds.size() != EvaluationPoint.size()))
3030  {
3031  MACH3LOG_ERROR("Size doesn't match");
3032  throw MaCh3Exception(__FILE__ , __LINE__ );
3033  }
3034 
3035  if(hpost[0] == nullptr) MakePostfit();
3036 
3037  MACH3LOG_INFO("Calculating Savage Dickey");
3038  TDirectory *SavageDickeyDir = OutputFile->mkdir("SavageDickey");
3039  SavageDickeyDir->cd();
3040 
3041  for(unsigned int k = 0; k < ParNames.size(); ++k)
3042  {
3043  //KS: First we need to find parameter number based on name
3044  int ParamNo = GetParamIndexFromName(ParNames[k]);
3045  if(ParamNo == M3::_BAD_INT_)
3046  {
3047  MACH3LOG_WARN("Couldn't find param {}. Will not calculate SavageDickey", ParNames[k]);
3048  continue;
3049  }
3050 
3051  TString Title = "";
3052  double Prior = 1.0, PriorError = 1.0;
3053  GetNthParameter(ParamNo, Prior, PriorError, Title);
3054  bool FlatPrior = GetParamFlat(ParamNo);
3055 
3056  auto PosteriorHist = M3::Clone<TH1D>(hpost[ParamNo], std::string(Title));
3057  RemoveFitter(PosteriorHist.get(), "Gauss");
3058 
3059  std::unique_ptr<TH1D> PriorHist;
3060  //KS: If flat prior we need to have well defined bounds otherwise Prior distribution will not make sense
3061  if(FlatPrior)
3062  {
3063  int NBins = PosteriorHist->GetNbinsX();
3064  if(Bounds[k][0] > Bounds[k][1])
3065  {
3066  MACH3LOG_ERROR("Lower bound is higher than upper bound");
3067  throw MaCh3Exception(__FILE__ , __LINE__ );
3068  }
3069  PriorHist = std::make_unique<TH1D>("PriorHist", Title, NBins, Bounds[k][0], Bounds[k][1]);
3070  PriorHist->SetDirectory(nullptr);
3071  double FlatProb = ( Bounds[k][1] - Bounds[k][0]) / NBins;
3072  for (int g = 0; g < NBins + 1; ++g)
3073  {
3074  PriorHist->SetBinContent(g+1, FlatProb);
3075  }
3076  }
3077  else //KS: Otherwise throw from Gaussian
3078  {
3079  PriorHist = M3::Clone<TH1D>(PosteriorHist.get(), "Prior");
3080  PriorHist->Reset("");
3081  PriorHist->Fill(0.0, 0.0);
3082 
3083  auto rand = std::make_unique<TRandom3>(0);
3084  //KS: Throw nice gaussian, just need big number to have smooth distribution
3085  for(int g = 0; g < 1000000; ++g)
3086  {
3087  PriorHist->Fill(rand->Gaus(Prior, PriorError));
3088  }
3089  }
3090  SavageDickeyPlot(PriorHist, PosteriorHist, std::string(Title), EvaluationPoint[k]);
3091  } //End loop over parameters
3092 
3093  SavageDickeyDir->Close();
3094  delete SavageDickeyDir;
3095 
3096  OutputFile->cd();
3097 }
void RemoveFitter(TH1D *hist, const std::string &name)
KS: Remove fitted TF1 from hist to make comparison easier.
void SavageDickeyPlot(std::unique_ptr< TH1D > &PriorHist, std::unique_ptr< TH1D > &PosteriorHist, const std::string &Title, const double EvaluationPoint) const
Produce Savage Dickey plot.

◆ GetSystBranchNames()

const std::vector<TString>& MCMCProcessor::GetSystBranchNames ( ) const
inline

Get the vector of each systematic branch names from root file.

Definition at line 252 of file MCMCProcessor.h.

252 { return SystName_v;};
std::vector< TString > SystName_v
Vector of each systematic.

◆ GetViolin()

TH2D* MCMCProcessor::GetViolin ( ) const
inline

Get Violin plot for all parameters with posterior values.

Definition at line 229 of file MCMCProcessor.h.

229 { return hviolin.get(); };

◆ GetViolinPrior()

TH2D* MCMCProcessor::GetViolinPrior ( ) const
inline

Get Violin plot for all parameters with prior values.

Definition at line 231 of file MCMCProcessor.h.

231 { return hviolin_prior.get(); };

◆ GetXSecCov()

std::vector<std::string> MCMCProcessor::GetXSecCov ( ) const
inline

Definition at line 234 of file MCMCProcessor.h.

234 { return CovPos[kXSecPar]; };

◆ GewekeDiagnostic()

void MCMCProcessor::GewekeDiagnostic ( )
protected

Geweke Diagnostic based on the methods described by Fang (2014) and Karlsbakk (2011). [8] [23].

Definition at line 4351 of file MCMCProcessor.cpp.

4351  {
4352 // **************************
4353  MACH3LOG_INFO("Making Geweke Diagnostic");
4354  //KS: Up refers to upper limit we check, it stays constant, in literature it is mostly 50% thus using 0.5 for threshold
4355  std::vector<double> MeanUp(nDraw, 0.0);
4356  std::vector<double> SpectralVarianceUp(nDraw, 0.0);
4357  std::vector<int> DenomCounterUp(nDraw, 0);
4358  const double Threshold = 0.5 * nSteps;
4359 
4360  //KS: Select values between which you want to scan, for example 0 means 0% burn in and 1 100% burn in.
4361  constexpr double LowerThreshold = 0;
4362  constexpr double UpperThreshold = 1.0;
4363  // Tells how many intervals between thresholds we want to check
4364  constexpr int NChecks = 100;
4365  constexpr double Division = (UpperThreshold - LowerThreshold)/NChecks;
4366 
4367  std::vector<std::unique_ptr<TH1D>> GewekePlots(nDraw);
4368  for (int j = 0; j < nDraw; ++j)
4369  {
4370  TString Title = "";
4371  double Prior = 1.0, PriorError = 1.0;
4372  GetNthParameter(j, Prior, PriorError, Title);
4373  std::string HistName = Form("%s_%s_Geweke", Title.Data(), BranchNames[j].Data());
4374  GewekePlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), NChecks, 0.0, 100 * UpperThreshold);
4375  GewekePlots[j]->SetDirectory(nullptr);
4376  GewekePlots[j]->GetXaxis()->SetTitle("Burn-In (%)");
4377  GewekePlots[j]->GetYaxis()->SetTitle("Geweke T score");
4378  }
4379 
4380 //KS: Start parallel region
4381 #ifdef MULTITHREAD
4382 #pragma omp parallel
4383 {
4384 #endif
4385  //KS: First we calculate mean and spectral variance for the upper limit, this doesn't change and in literature is most often 50%
4386  #ifdef MULTITHREAD
4387  #pragma omp for
4388  #endif
4389  for (int j = 0; j < nDraw; ++j)
4390  {
4391  for(int i = 0; i < nEntries; ++i)
4392  {
4393  if(StepNumber[i] > Threshold)
4394  {
4395  MeanUp[j] += ParStep[j][i];
4396  DenomCounterUp[j]++;
4397  }
4398  }
4399  MeanUp[j] = MeanUp[j]/DenomCounterUp[j];
4400  }
4401 
4402  //KS: now Spectral variance which in this case is sample variance
4403  #ifdef MULTITHREAD
4404  #pragma omp for collapse(2)
4405  #endif
4406  for (int j = 0; j < nDraw; ++j)
4407  {
4408  for(int i = 0; i < nEntries; ++i)
4409  {
4410  if(StepNumber[i] > Threshold)
4411  {
4412  SpectralVarianceUp[j] += (ParStep[j][i] - MeanUp[j])*(ParStep[j][i] - MeanUp[j]);
4413  }
4414  }
4415  }
4416 
4417  //Loop over how many intervals we calculate
4418  #ifdef MULTITHREAD
4419  #pragma omp for
4420  #endif
4421  for (int k = 1; k < NChecks+1; ++k)
4422  {
4423  //KS each thread has it's own
4424  std::vector<double> MeanDown(nDraw, 0.0);
4425  std::vector<double> SpectralVarianceDown(nDraw, 0.0);
4426  std::vector<int> DenomCounterDown(nDraw, 0);
4427 
4428  const unsigned int ThresholsCheck = Division*k*nSteps;
4429  //KS: First mean
4430  for (int j = 0; j < nDraw; ++j)
4431  {
4432  for(int i = 0; i < nEntries; ++i)
4433  {
4434  if(StepNumber[i] < ThresholsCheck)
4435  {
4436  MeanDown[j] += ParStep[j][i];
4437  DenomCounterDown[j]++;
4438  }
4439  }
4440  MeanDown[j] = MeanDown[j]/DenomCounterDown[j];
4441  }
4442  //Now spectral variance
4443  for (int j = 0; j < nDraw; ++j)
4444  {
4445  for(int i = 0; i < nEntries; ++i)
4446  {
4447  if(StepNumber[i] < ThresholsCheck)
4448  {
4449  SpectralVarianceDown[j] += (ParStep[j][i] - MeanDown[j])*(ParStep[j][i] - MeanDown[j]);
4450  }
4451  }
4452  }
4453  //Lastly calc T score and fill histogram entry
4454  for (int j = 0; j < nDraw; ++j)
4455  {
4456  double T_score = std::fabs((MeanDown[j] - MeanUp[j])/std::sqrt(SpectralVarianceDown[j]/DenomCounterDown[j] + SpectralVarianceUp[j]/DenomCounterUp[j]));
4457  GewekePlots[j]->SetBinContent(k, T_score);
4458  }
4459  } //end loop over intervals
4460 #ifdef MULTITHREAD
4461 } //End parallel region
4462 #endif
4463 
4464  //Finally save it to TFile
4465  OutputFile->cd();
4466  TDirectory *GewekeDir = OutputFile->mkdir("Geweke");
4467  for (int j = 0; j < nDraw; ++j)
4468  {
4469  GewekeDir->cd();
4470  GewekePlots[j]->Write();
4471  }
4472  for (int i = 0; i < nDraw; ++i) {
4473  delete[] ParStep[i];
4474  }
4475  delete[] ParStep;
4476 
4477  GewekeDir->Close();
4478  delete GewekeDir;
4479  OutputFile->cd();
4480 }

◆ Initialise()

void MCMCProcessor::Initialise ( )

Scan chain, what parameters we have and load information from covariance matrices.

Definition at line 144 of file MCMCProcessor.cpp.

144  {
145 // ***************
146  // Scan the ROOT file for useful branches
147  ScanInput();
148 
149  // Setup the output
150  SetupOutput();
151 }
void SetupOutput()
Prepare all objects used for output.
void ScanInput()
Scan Input etc.

◆ LoadAdditionalInfo()

virtual void MCMCProcessor::LoadAdditionalInfo ( )
inlineprotectedvirtual

allow loading additional info for example used for oscillation parameters

Reimplemented in OscProcessor.

Definition at line 355 of file MCMCProcessor.h.

355 {};

◆ MakeCovariance()

void MCMCProcessor::MakeCovariance ( )

Calculate covariance by making 2D projection of each combination of parameters.

Warning
This is deprecated and slower, however it is less RAM intensive

Definition at line 962 of file MCMCProcessor.cpp.

962  {
963 // *********************
964  if (OutputFile == nullptr) MakeOutputFile();
965 
966  MACH3LOG_INFO("Making post-fit covariances...");
967  // Check that the diagonal entries have been filled
968  // i.e. MakePostfit() has been called
969  for (int i = 0; i < nDraw; ++i) {
970  if ((*Covariance)(i,i) == M3::_BAD_DOUBLE_) {
971  MACH3LOG_INFO("Have not run diagonal elements in covariance, will do so now by calling MakePostfit()");
972  MakePostfit();
973  break;
974  }
975  }
976 
977  TStopwatch clock;
978  clock.Start();
979 
980  TDirectory *PostHistDir = OutputFile->mkdir("Post_2d_hists");
981  PostHistDir->cd();
982  gStyle->SetPalette(55);
983 
984 
985  // Define RDataFrame
986  ROOT::RDataFrame df(*Chain);
987 
988  // Apply selection once
989  ROOT::RDF::RNode dfToUse = df.Filter(StepCut);
990 
991  // Apply reweighting once
992  if (ReweightPosterior)
993  {
994  TString WeightExpression = "1.0";
995  for (const auto &name : ReweightNames) {
996  WeightExpression = "(" + WeightExpression + ")*(" + name + ")";
997  }
998  dfToUse = dfToUse.Define("MCMC_RDF_WEIGHT", WeightExpression.Data());
999  }
1000 
1001  struct CovarianceHistogram {
1002  int i, j;
1003  TString Title_i, Title_j, DrawMe;
1004  ROOT::RDF::RResultPtr<TH2D> Histogram;
1005  };
1006 
1007  std::vector<CovarianceHistogram> Histograms;
1008 
1009  // Number of covariance elements
1010  const int nCov = nDraw * (nDraw - 1) / 2;
1011  Histograms.reserve(nCov);
1012 
1013  MACH3LOG_INFO("Booking {} 2D histograms...", nCov);
1014 
1015  // Now we are sure we have the diagonal elements, let's make the off-diagonals
1016  for (int i = 0; i < nDraw; ++i)
1017  {
1018  TString Title_i = "";
1019  double Prior_i, PriorError;
1020 
1021  GetNthParameter(i, Prior_i, PriorError, Title_i);
1022 
1023  double xmin = hpost[i]->GetXaxis()->GetXmin();
1024  double xmax = hpost[i]->GetXaxis()->GetXmax();
1025 
1026  // Loop over the other parameters to get the correlations
1027  for (int j = 0; j <= i; ++j) {
1028  // Skip the diagonal elements which we've already done above
1029  if (j == i) continue;
1030 
1031  // If this parameter isn't varied
1032  if (ParamVaried[j] == false) {
1033  (*Covariance)(i,j) = 0.0;
1034  (*Covariance)(j,i) = (*Covariance)(i,j);
1035  (*Correlation)(i,j) = 0.0;
1036  (*Correlation)(j,i) = (*Correlation)(i,j);
1037  continue;
1038  }
1039 
1040  TString Title_j = "";
1041  double Prior_j, PriorError_j;
1042  GetNthParameter(j, Prior_j, PriorError_j, Title_j);
1043 
1044  TString DrawMe = BranchNames[j] + ":" + BranchNames[i];
1045  double ymin = hpost[j]->GetXaxis()->GetXmin();
1046  double ymax = hpost[j]->GetXaxis()->GetXmax();
1047 
1048  ROOT::RDF::RResultPtr<TH2D> hpost_2D;
1049 
1050  // Book unweighted histogram
1051  if (!ReweightPosterior)
1052  {
1053  hpost_2D = dfToUse.Histo2D({DrawMe.Data(), DrawMe.Data(),
1054  nBins, xmin, xmax, nBins, ymin, ymax},
1055  BranchNames[i].Data(), BranchNames[j].Data());
1056  }
1057  else // Book weighted histogram[
1058  {
1059  hpost_2D = dfToUse.Histo2D({DrawMe.Data(), DrawMe.Data(),
1060  nBins, xmin, xmax, nBins, ymin, ymax},
1061  BranchNames[i].Data(), BranchNames[j].Data(), "MCMC_RDF_WEIGHT");
1062  }
1063  Histograms.push_back({i, j, Title_i, Title_j, DrawMe, hpost_2D});
1064  } // End j loop
1065  } // End i loop
1066  MACH3LOG_INFO("Finished booking {} histograms. Now executing RDF event loop...", Histograms.size());
1067 
1068  // The first GetPtr() triggers the RDF event loop.
1069  //
1070  // Because ALL histograms have already been booked, RDF fills
1071  // all of them in the same event loop.
1072  if (!Histograms.empty()) {
1073  TH2D *dummy = Histograms[0].Histogram.GetPtr();
1074  (void)dummy;
1075  }
1076 
1077  clock.Stop();
1078 
1079  MACH3LOG_INFO("RDataFrame event loop took {:.2f}s for {} entries",
1080  clock.RealTime(), nEntries);
1081  TStopwatch processingClock;
1082  processingClock.Start();
1083 
1084  for (auto &Entry : Histograms)
1085  {
1086  const int i = Entry.i;
1087  const int j = Entry.j;
1088 
1089  TH2D *hpost_2D = Entry.Histogram.GetPtr();
1090  hpost_2D->SetMinimum(0);
1091  hpost_2D->GetXaxis()->SetTitle(Entry.Title_i);
1092  hpost_2D->GetYaxis()->SetTitle(Entry.Title_j);
1093  hpost_2D->GetZaxis()->SetTitle("Steps");
1094 
1095  if (ApplySmoothing) hpost_2D->Smooth();
1096  // Get the Covariance for these two parameters
1097  (*Covariance)(i,j) = hpost_2D->GetCovariance();
1098  (*Covariance)(j,i) = (*Covariance)(i,j);
1099  (*Correlation)(i,j) = hpost_2D->GetCorrelationFactor();
1100  (*Correlation)(j,i) = (*Correlation)(i,j);
1101 
1102  if(printToPDF)
1103  {
1104  if(std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold)
1105  {
1106  Posterior->cd();
1107  hpost_2D->Draw("colz");
1108  Posterior->SetName(hpost_2D->GetName());
1109  Posterior->SetTitle(hpost_2D->GetTitle());
1110  Posterior->Print(CanvasName);
1111  hpost_2D->Write(hpost_2D->GetTitle());
1112  }
1113  }
1114  }
1115  processingClock.Stop();
1116 
1117  MACH3LOG_INFO("Processing covariance histograms took {:.2f}s", processingClock.RealTime());
1118 
1119  PostHistDir->Close();
1120  delete PostHistDir;
1121  OutputFile->cd();
1122  Covariance->Write("Covariance");
1123  Correlation->Write("Correlation");
1124 }

◆ MakeCovariance_MP()

void MCMCProcessor::MakeCovariance_MP ( const bool  Mute = false)

Calculate covariance by making 2D projection of each combination of parameters using multithreading.

Parameters
MuteAllow silencing many messages, especially important if we calculate matrix many times

Definition at line 1249 of file MCMCProcessor.cpp.

1249  {
1250 // *********************
1251  if (OutputFile == nullptr) MakeOutputFile();
1252 
1253  if(!CacheMCMC) CacheSteps();
1254 
1255  // Check that the diagonal entries have been filled
1256  // i.e. MakePostfit() has been called
1257  for (int i = 0; i < nDraw; ++i) {
1258  if ((*Covariance)(i,i) == M3::_BAD_DOUBLE_) {
1259  MACH3LOG_WARN("Have not run diagonal elements in covariance, will do so now by calling MakePostfit()");
1260  MakePostfit();
1261  break;
1262  }
1263  }
1264 
1265  TStopwatch clock;
1266  TDirectory *PostHistDir = nullptr;
1267  if(!Mute)
1268  {
1269  MACH3LOG_INFO("Calculating covariance matrix");
1270  clock.Start();
1271  PostHistDir = OutputFile->mkdir("Post_2d_hists");
1272  PostHistDir->cd();
1273  }
1274 
1275  if(!Mute)
1276 
1277  gStyle->SetPalette(55);
1278  // Now we are sure we have the diagonal elements, let's make the off-diagonals
1279  #ifdef MULTITHREAD
1280  #pragma omp parallel for
1281  #endif
1282  for (int i = 0; i < nDraw; ++i)
1283  {
1284  for (int j = 0; j <= i; ++j)
1285  {
1286  // Skip the diagonal elements which we've already done above
1287  if (j == i) continue;
1288 
1289  // If this parameter isn't varied
1290  if (ParamVaried[j] == false) {
1291  (*Covariance)(i,j) = 0.0;
1292  (*Covariance)(j,i) = (*Covariance)(i,j);
1293  (*Correlation)(i,j) = 0.0;
1294  (*Correlation)(j,i) = (*Correlation)(i,j);
1295  continue;
1296  }
1297  hpost2D[i][j]->SetMinimum(0);
1298 
1299  for (int k = 0; k < nEntries; ++k)
1300  {
1301  //KS: Burn in cut
1302  if(StepNumber[k] < BurnInCut) continue;
1303 
1304  const double Weight = ReweightPosterior ? WeightValue[i] : 1.;
1305  //KS: Fill histogram with cached steps
1306  hpost2D[i][j]->Fill(ParStep[i][k], ParStep[j][k], Weight);
1307  }
1308  if(ApplySmoothing) hpost2D[i][j]->Smooth();
1309 
1310  // Get the Covariance for these two parameters
1311  (*Covariance)(i,j) = hpost2D[i][j]->GetCovariance();
1312  (*Covariance)(j,i) = (*Covariance)(i,j);
1313 
1314  //KS: Since we already have covariance consider calculating correlation using it, right now we effectively calculate covariance twice
1315  //https://root.cern.ch/doc/master/TH2_8cxx_source.html#l01099
1316  (*Correlation)(i,j) = hpost2D[i][j]->GetCorrelationFactor();
1317  (*Correlation)(j,i) = (*Correlation)(i,j);
1318  }// End j loop
1319  }// End i loop
1320 
1321  if(!Mute) {
1322  clock.Stop();
1323  MACH3LOG_INFO("Making Covariance took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries);
1324  if(printToPDF)
1325  {
1326  Posterior->cd();
1327  for (int i = 0; i < nDraw; ++i)
1328  {
1329  for (int j = 0; j <= i; ++j)
1330  {
1331  // Skip the diagonal elements which we've already done above
1332  if (j == i) continue;
1333  if (ParamVaried[j] == false) continue;
1334 
1335  if(ParamType[i] == kXSecPar && ParamType[j] == kXSecPar)
1336  {
1337  if(std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold)
1338  {
1339  hpost2D[i][j]->Draw("colz");
1340  Posterior->SetName(hpost2D[i][j]->GetName());
1341  Posterior->SetTitle(hpost2D[i][j]->GetTitle());
1342  Posterior->Print(CanvasName);
1343  hpost2D[i][j]->Write(hpost2D[i][j]->GetTitle());
1344  }
1345  }
1346  //if( std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold) hpost2D[i][j]->Write();
1347  }// End j loop
1348  }// End i loop
1349  } //end if pdf
1350  PostHistDir->Close();
1351  delete PostHistDir;
1352  OutputFile->cd();
1353  Covariance->Write("Covariance");
1354  Correlation->Write("Correlation");
1355  } // end if not mute
1356 }
void GetCovariance(TMatrixDSym *&Cov, TMatrixDSym *&Corr)
Get the post-fit covariances and correlations.
void CacheSteps()
KS:By caching each step we use multithreading.

◆ MakeCovarianceYAML()

void MCMCProcessor::MakeCovarianceYAML ( const std::string &  OutputYAMLFile,
const std::string &  MeansMethod 
) const

Make YAML file from post-fit covariance.

Definition at line 1527 of file MCMCProcessor.cpp.

1527  {
1528 // *********************
1529  MACH3LOG_INFO("Making covariance matrix YAML file");
1530 
1531  if (ParamNames[kXSecPar].size() != static_cast<size_t>(nDraw)) {
1532  MACH3LOG_ERROR("Using Legacy Parameters i.e. not one from Parameter Handler Generic, this will not work");
1533  throw MaCh3Exception(__FILE__, __LINE__);
1534  }
1535  std::vector<double> MeanArray(nDraw);
1536  std::vector<double> ErrorArray(nDraw);
1537  std::vector<std::vector<double>> CorrelationMatrix(nDraw, std::vector<double>(nDraw, 0.0));
1538 
1539  TVectorD* means_vec;
1540  TVectorD* errors_vec;
1541 
1542  if (MeansMethod == "Arithmetic") {
1543  means_vec = Means;
1544  errors_vec = Errors;
1545  } else if (MeansMethod == "Gaussian") {
1546  means_vec = Means_Gauss;
1547  errors_vec = Errors_Gauss;
1548  } else if (MeansMethod == "HPD") {
1549  means_vec = Means_HPD;
1550  errors_vec = Errors_HPD;
1551  } else {
1552  MACH3LOG_ERROR("Unknown means method: {}, should be either 'Arithmetic', 'Gaussian', or 'HPD'.", MeansMethod);
1553  throw MaCh3Exception(__FILE__, __LINE__);
1554  }
1555 
1556  //Make vectors of mean, error, and correlations
1557  for (int i = 0; i < nDraw; i++)
1558  {
1559  MeanArray[i] = (*means_vec)(i);
1560  ErrorArray[i] = (*errors_vec)(i);
1561  for (int j = 0; j <= i; j++)
1562  {
1563  CorrelationMatrix[i][j] = (*Correlation)(i,j);
1564  if(i != j) CorrelationMatrix[j][i] = (*Correlation)(i,j);
1565  }
1566  }
1567 
1568  //Make std::string param name vector
1569  std::vector<std::string> ParamStrings(ParamNames[kXSecPar].size());
1570  for (size_t i = 0; i < ParamNames[kXSecPar].size(); ++i) {
1571  ParamStrings[i] = static_cast<std::string>(ParamNames[kXSecPar][i]);
1572  }
1573 
1574  YAML::Node XSecFile = CovConfig[kXSecPar];
1575  M3::MakeCorrelationMatrix(XSecFile, MeanArray, ErrorArray, CorrelationMatrix, OutputYAMLFile, ParamStrings);
1576 }
void MakeCorrelationMatrix(YAML::Node &root, const std::vector< double > &Values, const std::vector< double > &Errors, const std::vector< std::vector< double >> &Correlation, const std::string &OutYAMLName, const std::vector< std::string > &FancyNames={})
KS: Replace correlation matrix and tune values in YAML covariance matrix.

◆ MakeCredibleIntervals()

void MCMCProcessor::MakeCredibleIntervals ( const std::vector< double > &  CredibleIntervals = {0.99, 0.90, 0.68 },
const std::vector< Color_t > &  CredibleIntervalsColours = {kCyan+4, kCyan-2, kCyan-10},
const bool  CredibleInSigmas = false 
)

Make and Draw Credible intervals.

Parameters
CredibleIntervalsVector with values of credible intervals, must be in descending order
CredibleIntervalsColoursColor_t telling what colour to use for each Interval line
CredibleInSigmasBool telling whether intervals are in percentage or in sigmas, then special conversions is used

Scale the histograms so it shows the posterior probability

Definition at line 714 of file MCMCProcessor.cpp.

716  {
717 // *********************
718  if(hpost[0] == nullptr) MakePostfit();
719 
720  MACH3LOG_INFO("Starting {}", __func__);
721  const double LeftMargin = Posterior->GetLeftMargin();
722  Posterior->SetLeftMargin(0.15);
723 
724  // KS: Sanity check of size and ordering is correct
725  CheckCredibleIntervalsOrder(CredibleIntervals, CredibleIntervalsColours);
726  const int nCredible = int(CredibleIntervals.size());
727  std::vector<std::unique_ptr<TH1D>> hpost_copy(nDraw);
728  std::vector<std::vector<std::unique_ptr<TH1D>>> hpost_cl(nDraw);
729 
730  //KS: Copy all histograms to be thread safe
731  for (int i = 0; i < nDraw; ++i)
732  {
733  hpost_copy[i] = M3::Clone<TH1D>(hpost[i], Form("hpost_copy_%i", i));
734  hpost_cl[i].resize(nCredible);
735  for (int j = 0; j < nCredible; ++j)
736  {
737  hpost_cl[i][j] = M3::Clone<TH1D>(hpost[i], Form("hpost_copy_%i_CL_%f", i, CredibleIntervals[j]));
738 
739  //KS: Reset to get rid to TF1 otherwise we run into segfault :(
740  hpost_cl[i][j]->Reset("");
741  hpost_cl[i][j]->Fill(0.0, 0.0);
742  }
743  }
744 
745  #ifdef MULTITHREAD
746  #pragma omp parallel for
747  #endif
748  for (int i = 0; i < nDraw; ++i)
749  {
751  hpost_copy[i]->Scale(1. / hpost_copy[i]->Integral());
752  for (int j = 0; j < nCredible; ++j)
753  {
754  // Scale the histograms before getting credible intervals
755  hpost_cl[i][j]->Scale(1. / hpost_cl[i][j]->Integral());
756  GetCredibleIntervalSig(hpost_copy[i], hpost_cl[i][j], CredibleInSigmas, CredibleIntervals[j]);
757 
758  hpost_cl[i][j]->SetFillColor(CredibleIntervalsColours[j]);
759  hpost_cl[i][j]->SetLineWidth(1);
760  }
761  hpost_copy[i]->GetYaxis()->SetTitleOffset(1.8);
762  hpost_copy[i]->SetLineWidth(1);
763  hpost_copy[i]->SetMaximum(hpost_copy[i]->GetMaximum()*1.2);
764  hpost_copy[i]->SetLineWidth(2);
765  hpost_copy[i]->SetLineColor(kBlack);
766  hpost_copy[i]->GetYaxis()->SetTitle("Posterior Probability");
767  }
768 
769  OutputFile->cd();
770  TDirectory *CredibleDir = OutputFile->mkdir("Credible");
771 
772  for (int i = 0; i < nDraw; ++i)
773  {
774  if(!ParamVaried[i]) continue;
775 
776  // Now make the TLine for the Asimov
777  TString Title = "";
778  double Prior = 1.0, PriorError = 1.0;
779  GetNthParameter(i, Prior, PriorError, Title);
780 
781  auto Asimov = std::make_unique<TLine>(Prior, hpost_copy[i]->GetMinimum(), Prior, hpost_copy[i]->GetMaximum());
782  SetTLineStyle(Asimov.get(), kRed-3, 2, kDashed);
783 
784  auto legend = std::make_unique<TLegend>(0.20, 0.7, 0.4, 0.92);
785  SetLegendStyle(legend.get(), 0.03);
786  hpost_copy[i]->Draw("HIST");
787 
788  for (int j = 0; j < nCredible; ++j)
789  hpost_cl[i][j]->Draw("HIST SAME");
790  for (int j = nCredible-1; j >= 0; --j)
791  {
792  if(CredibleInSigmas)
793  legend->AddEntry(hpost_cl[i][j].get(), Form("%.0f#sigma Credible Interval", CredibleIntervals[j]), "f");
794  else
795  legend->AddEntry(hpost_cl[i][j].get(), Form("%.0f%% Credible Interval", CredibleIntervals[j]*100), "f");
796  }
797  legend->AddEntry(Asimov.get(), Form("#splitline{Prior}{x = %.2f , #sigma = %.2f}", Prior, PriorError), "l");
798  legend->Draw("SAME");
799  Asimov->Draw("SAME");
800 
801  // Write to file
802  Posterior->SetName(hpost[i]->GetName());
803  Posterior->SetTitle(hpost[i]->GetTitle());
804 
805  if(printToPDF) Posterior->Print(CanvasName);
806  // cd into directory in root file
807  CredibleDir->cd();
808  Posterior->Write();
809  }
810  CredibleDir->Close();
811  delete CredibleDir;
812 
813  OutputFile->cd();
814 
815  //Set back to normal
816  Posterior->SetLeftMargin(LeftMargin);
817 }
void GetCredibleIntervalSig(const std::unique_ptr< TH1D > &hist, std::unique_ptr< TH1D > &hpost_copy, const bool CredibleInSigmas, const double coverage)
KS: Get 1D histogram within credible interval, hpost_copy has to have the same binning,...
void CheckCredibleIntervalsOrder(const std::vector< double > &CredibleIntervals, const std::vector< Color_t > &CredibleIntervalsColours) const
Checks the order and size consistency of the CredibleIntervals and CredibleIntervalsColours vectors.

◆ MakeCredibleRegions()

void MCMCProcessor::MakeCredibleRegions ( const std::vector< double > &  CredibleRegions = {0.99, 0.90, 0.68},
const std::vector< Style_t > &  CredibleRegionStyle = {kDashed, kSolid, kDotted},
const std::vector< Color_t > &  CredibleRegionColor = {kGreen-3, kGreen-10, kGreen},
const bool  CredibleInSigmas = false,
const bool  Draw2DPosterior = true,
const bool  DrawBestFit = true 
)

Make and Draw Credible Regions.

Parameters
CredibleRegionsVector with values of credible intervals, must be in descending order
CredibleRegionStyleStyle_t telling what line style to use for each Interval line
CredibleRegionColorColor_t telling what colour to use for each Interval line
CredibleInSigmasBool telling whether intervals are in percentage or in sigmas, then special conversions is used
Draw2DPosteriorBool telling whether to draw the 2D posterior distributions
DrawBestFitBool telling whether to draw the best-fit point on the plots

Definition at line 1860 of file MCMCProcessor.cpp.

1865  {
1866 // *********************
1867  if(hpost2D.size() == 0) MakeCovariance_MP();
1868  MACH3LOG_INFO("Making Credible Regions");
1869 
1870  CheckCredibleRegionsOrder(CredibleRegions, CredibleRegionStyle, CredibleRegionColor);
1871  const int nCredible = int(CredibleRegions.size());
1872 
1873  std::vector<std::vector<std::unique_ptr<TH2D>>> hpost_2D_copy(nDraw);
1874  std::vector<std::vector<std::vector<std::unique_ptr<TH2D>>>> hpost_2D_cl(nDraw);
1875  //KS: Copy all histograms to be thread safe
1876  for (int i = 0; i < nDraw; ++i)
1877  {
1878  hpost_2D_copy[i].resize(nDraw);
1879  hpost_2D_cl[i].resize(nDraw);
1880  for (int j = 0; j <= i; ++j)
1881  {
1882  hpost_2D_copy[i][j] = M3::Clone<TH2D>(hpost2D[i][j], Form("hpost_copy_%i_%i", i, j));
1883  hpost_2D_cl[i][j].resize(nCredible);
1884  for (int k = 0; k < nCredible; ++k)
1885  {
1886  hpost_2D_cl[i][j][k] = M3::Clone<TH2D>(hpost2D[i][j], Form("hpost_copy_%i_%i_CL_%f", i, j, CredibleRegions[k]));
1887  }
1888  }
1889  }
1890 
1891  #ifdef MULTITHREAD
1892  #pragma omp parallel for
1893  #endif
1894  //Calculate credible histogram
1895  for (int i = 0; i < nDraw; ++i)
1896  {
1897  for (int j = 0; j <= i; ++j)
1898  {
1899  for (int k = 0; k < nCredible; ++k)
1900  {
1901  GetCredibleRegionSig(hpost_2D_cl[i][j][k], CredibleInSigmas, CredibleRegions[k]);
1902  hpost_2D_cl[i][j][k]->SetLineColor(CredibleRegionColor[k]);
1903  hpost_2D_cl[i][j][k]->SetLineWidth(2);
1904  hpost_2D_cl[i][j][k]->SetLineStyle(CredibleRegionStyle[k]);
1905  }
1906  }
1907  }
1908 
1909  gStyle->SetPalette(51);
1910  for (int i = 0; i < nDraw; ++i)
1911  {
1912  for (int j = 0; j <= i; ++j)
1913  {
1914  // Skip the diagonal elements which we've already done above
1915  if (j == i) continue;
1916  if (ParamVaried[j] == false) continue;
1917 
1918  auto legend = std::make_unique<TLegend>(0.20, 0.7, 0.4, 0.92);
1919  legend->SetTextColor(kRed);
1920  SetLegendStyle(legend.get(), 0.03);
1921 
1922  //Get Best point
1923  auto bestfitM = std::make_unique<TGraph>(1);
1924  const int MaxBin = hpost_2D_copy[i][j]->GetMaximumBin();
1925  int Mbx, Mby, Mbz;
1926  hpost_2D_copy[i][j]->GetBinXYZ(MaxBin, Mbx, Mby, Mbz);
1927  const double Mx = hpost_2D_copy[i][j]->GetXaxis()->GetBinCenter(Mbx);
1928  const double My = hpost_2D_copy[i][j]->GetYaxis()->GetBinCenter(Mby);
1929 
1930  bestfitM->SetPoint(0, Mx, My);
1931  bestfitM->SetMarkerStyle(22);
1932  bestfitM->SetMarkerSize(1);
1933  bestfitM->SetMarkerColor(kMagenta);
1934 
1935  //Plot default 2D posterior
1936 
1937  if(Draw2DPosterior){
1938  hpost_2D_copy[i][j]->Draw("COLZ");
1939  } else{
1940  hpost_2D_copy[i][j]->Draw("AXIS");
1941  }
1942 
1943  //Now credible regions
1944  for (int k = 0; k < nCredible; ++k)
1945  hpost_2D_cl[i][j][k]->Draw("CONT3 SAME");
1946  for (int k = nCredible-1; k >= 0; --k)
1947  {
1948  if(CredibleInSigmas)
1949  legend->AddEntry(hpost_2D_cl[i][j][k].get(), Form("%.0f#sigma Credible Interval", CredibleRegions[k]), "l");
1950  else
1951  legend->AddEntry(hpost_2D_cl[i][j][k].get(), Form("%.0f%% Credible Region", CredibleRegions[k]*100), "l");
1952  }
1953  legend->Draw("SAME");
1954 
1955  if(DrawBestFit){
1956  legend->AddEntry(bestfitM.get(),"Best Fit","p");
1957  bestfitM->Draw("SAME.P");
1958  }
1959 
1960  // Write to file
1961  Posterior->SetName(hpost2D[i][j]->GetName());
1962  Posterior->SetTitle(hpost2D[i][j]->GetTitle());
1963 
1964  //KS: Print only regions with correlation greater than specified value, by default 0.2. This is done to avoid dumping thousands of plots
1965  if(printToPDF && std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold) Posterior->Print(CanvasName);
1966  // Write it to root file
1967  //OutputFile->cd();
1968  //if( std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold ) Posterior->Write();
1969  }
1970  }
1971 
1972  OutputFile->cd();
1973 }
void GetCredibleRegionSig(std::unique_ptr< TH2D > &hist2D, const bool CredibleInSigmas, const double coverage)
KS: Set 2D contour within some coverage.
void CheckCredibleRegionsOrder(const std::vector< double > &CredibleRegions, const std::vector< Style_t > &CredibleRegionStyle, const std::vector< Color_t > &CredibleRegionColor)
Checks the order and size consistency of the CredibleRegions, CredibleRegionStyle,...

◆ MakeOutputFile()

void MCMCProcessor::MakeOutputFile ( )
protected

prepare output root file and canvas to which we will save EVERYTHING

Definition at line 196 of file MCMCProcessor.cpp.

196  {
197 // ***************
198  //KS: ROOT hates me... but we can create several instances of MCMC Processor, each with own TCanvas ROOT is mad and will delete if there is more than one canvas with the same name, so we add random number to avoid issue
199  auto rand = std::make_unique<TRandom3>(0);
200  const int uniform = int(rand->Uniform(0, 10000));
201  // Open a TCanvas to write the posterior onto
202  Posterior = std::make_unique<TCanvas>(("Posterior" + std::to_string(uniform)).c_str(), ("Posterior" + std::to_string(uniform)).c_str(), 0, 0, 1024, 1024);
203  //KS: No idea why but ROOT changed treatment of violin in R6. If you have non uniform binning this will results in very hard to see violin plots.
204  TCandle::SetScaledViolin(false);
205 
206  Posterior->SetGrid();
207  gStyle->SetOptStat(0);
208  gStyle->SetOptTitle(0);
209  Posterior->SetTickx();
210  Posterior->SetTicky();
211 
212  Posterior->SetBottomMargin(0.1);
213  Posterior->SetTopMargin(0.05);
214  Posterior->SetRightMargin(0.03);
215  Posterior->SetLeftMargin(0.15);
216 
217  //To avoid TCanvas::Print> messages
218  gErrorIgnoreLevel = kWarning;
219 
220  // Output file to write to
221  OutputName = MCMCFile + OutputSuffix +".root";
222 
223  // Output file
224  OutputFile = M3::Open(OutputName, "recreate", __FILE__, __LINE__);
225  OutputFile->cd();
226 }
std::string OutputName
Name of output files.

◆ MakePostfit()

void MCMCProcessor::MakePostfit ( const std::map< std::string, std::pair< double, double >> &  Edges = {})

Make 1D projection for each parameter and prepare structure.

Definition at line 336 of file MCMCProcessor.cpp.

336  {
337 // ****************************
338  // Check if we've already made post-fit
339  if (MadePostfit == true) return;
340  MadePostfit = true;
341 
342  // Check if the output file is ready
343  if (OutputFile == nullptr) MakeOutputFile();
344 
345  MACH3LOG_INFO("Starting {}", __func__);
346  TStopwatch clock;
347  clock.Start();
348 
349  int originalErrorLevel = gErrorIgnoreLevel;
350  gErrorIgnoreLevel = kFatal;
351 
352  // Directory for posteriors
353  TDirectory *PostDir = OutputFile->mkdir("Post");
354  TDirectory *PostHistDir = OutputFile->mkdir("Post_1d_hists");
355 
356  //KS: Apply additional Cuts, like mass ordering
357  std::string CutPosterior1D = "";
358  if(Posterior1DCut != "") {
359  CutPosterior1D = StepCut +" && " + Posterior1DCut;
360  } else CutPosterior1D = StepCut;
361 
362  // Apply reweighting
363  if (ReweightPosterior) {
364  for (const auto& name : ReweightNames) {
365  CutPosterior1D = "(" + CutPosterior1D + ")*(" + name + ")";
366  }
367  }
368  MACH3LOG_DEBUG("Using following cut {}", CutPosterior1D);
369 
370  // nDraw is number of draws we want to do
371  for (int i = 0; i < nDraw; ++i)
372  {
373  if (i % (nDraw/5) == 0) {
375  }
376  OutputFile->cd();
377  TString Title = "";
378  double Prior = 1.0, PriorError = 1.0;
379  GetNthParameter(i, Prior, PriorError, Title);
380 
381  // Get bin edges for histograms
382  double maxi, mini = M3::_BAD_DOUBLE_;
383  if (Edges.find(Title.Data()) != Edges.end()) {
384  mini = Edges.at(Title.Data()).first;
385  maxi = Edges.at(Title.Data()).second;
386  } else {
387  maxi = Chain->GetMaximum(BranchNames[i]);
388  mini = Chain->GetMinimum(BranchNames[i]);
389  }
390  MACH3LOG_DEBUG("Initialising histogram for {} with binning {:.4f}, {:.4f}", Title, mini, maxi);
391  // This holds the posterior density
392  // KS: WARNING do NOT SetDirectory(nullptr) this will cause issue with Project()
393  // I know is tempting to avoid ROOT memory management but please do not.
394  hpost[i] = new TH1D(BranchNames[i], BranchNames[i], nBins, mini, maxi);
395  hpost[i]->SetMinimum(0);
396  hpost[i]->GetYaxis()->SetTitle("Steps");
397  hpost[i]->GetYaxis()->SetNoExponent(false);
398 
399  // Project BranchNames[i] onto hpost, applying stepcut
400  Chain->Project(BranchNames[i], BranchNames[i], CutPosterior1D.c_str());
401 
402  DrawPosterior(i, PostDir, PostHistDir);
403  } // end the for loop over nDraw
404 
405  OutputFile->cd();
406  TTree *SettingsBranch = new TTree("Settings", "Settings");
407  int NDParameters = nParam[kNDPar];
408  SettingsBranch->Branch("NDParameters", &NDParameters);
410  SettingsBranch->Branch("NDParametersStartingPos", &NDParametersStartingPos);
411 
412  SettingsBranch->Branch("NDSamplesBins", &NDSamplesBins);
413  SettingsBranch->Branch("NDSamplesNames", &NDSamplesNames);
414 
415  SettingsBranch->Fill();
416  SettingsBranch->Write();
417  delete SettingsBranch;
418 
419  TDirectory *Names = OutputFile->mkdir("Names");
420  Names->cd();
421  for (std::vector<TString>::iterator it = BranchNames.begin(); it != BranchNames.end(); ++it) {
422  TObjString((*it)).Write();
423  }
424  Names->Close();
425  delete Names;
426 
427  OutputFile->cd();
428  Central_Value->Write("Central_Value");
429  Means->Write("PDF_Means");
430  Errors->Write("PDF_Error");
431  Means_Gauss->Write("Gauss_Means");
432  Errors_Gauss->Write("Gauss_Errors");
433  Means_HPD->Write("Means_HPD");
434  Errors_HPD->Write("Errors_HPD");
435  Errors_HPD_Positive->Write("Errors_HPD_Positive");
436  Errors_HPD_Negative->Write("Errors_HPD_Negative");
437 
438  PostDir->Close();
439  delete PostDir;
440  PostHistDir->Close();
441  delete PostHistDir;
442 
443  clock.Stop();
444  MACH3LOG_INFO("{} took {:.2f}s to", __func__, clock.RealTime());
445 
446  // restore original warning setting
447  gErrorIgnoreLevel = originalErrorLevel;
448 } // Have now written the postfit projections
int NDParametersStartingPos
int NDParameters
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
void DrawPosterior(const int i, TDirectory *PostDir, TDirectory *PostHistDir)
Perform plot of 1d marginalised posterior with HPD etc.

◆ MakePrefit()

std::unique_ptr< TH1D > MCMCProcessor::MakePrefit ( )
protected

Prepare prefit histogram for parameter overlay plot.

Definition at line 2465 of file MCMCProcessor.cpp.

2465  {
2466 // *****************************
2467  if (OutputFile == nullptr) MakeOutputFile();
2468 
2469  auto PreFitPlot = std::make_unique<TH1D>("Prefit", "Prefit", nDraw, 0, nDraw);
2470  PreFitPlot->SetDirectory(nullptr);
2471  for (int i = 0; i < PreFitPlot->GetNbinsX() + 1; ++i) {
2472  PreFitPlot->SetBinContent(i+1, 0);
2473  PreFitPlot->SetBinError(i+1, 0);
2474  }
2475 
2476  //KS: Slightly hacky way to get relative to prior or nominal as this is convention we use,
2477  //Only applies for xsec, for other systematic it make no difference
2478  double CentralValueTemp, Central, Error;
2479 
2480  // Set labels and data
2481  for (int i = 0; i < nDraw; ++i)
2482  {
2483  //Those keep which parameter type we run currently and relative number
2484  int ParamEnum = ParamType[i];
2485  int ParamNo = i - ParamTypeStartPos[ParameterEnum(ParamEnum)];
2486  CentralValueTemp = ParamCentral[ParamEnum][ParamNo];
2487  if(plotRelativeToPrior)
2488  {
2489  // Normalise the prior relative the nominal/prior, just the way we get our fit results in MaCh3
2490  if ( CentralValueTemp != 0) {
2491  Central = ParamCentral[ParamEnum][ParamNo] / CentralValueTemp;
2492  Error = ParamErrors[ParamEnum][ParamNo]/CentralValueTemp;
2493  } else {
2494  Central = CentralValueTemp + 1.0;
2495  Error = ParamErrors[ParamEnum][ParamNo];
2496  }
2497  }
2498  else
2499  {
2500  Central = CentralValueTemp;
2501  Error = ParamErrors[ParamEnum][ParamNo];
2502  }
2503  //KS: If plotting error for param with flat prior is turned off and given param really has flat prior set error to 0
2504  if(!PlotFlatPrior && ParamFlat[ParamEnum][ParamNo]) {
2505  Error = 0.;
2506  }
2507  PreFitPlot->SetBinContent(i+1, Central);
2508  PreFitPlot->SetBinError(i+1, Error);
2509  PreFitPlot->GetXaxis()->SetBinLabel(i+1, ParamNames[ParamEnum][ParamNo]);
2510  }
2511  PreFitPlot->SetDirectory(nullptr);
2512 
2513  PreFitPlot->SetFillStyle(1001);
2514  PreFitPlot->SetFillColor(kRed-3);
2515  PreFitPlot->SetMarkerStyle(21);
2516  PreFitPlot->SetMarkerSize(2.4);
2517  PreFitPlot->SetMarkerColor(kWhite);
2518  PreFitPlot->SetLineColor(PreFitPlot->GetFillColor());
2519  PreFitPlot->GetXaxis()->LabelsOption("v");
2520 
2521  return PreFitPlot;
2522 }

◆ MakeSubOptimality()

void MCMCProcessor::MakeSubOptimality ( const int  NIntervals = 10)

Make and Draw SubOptimality [31].

Author
Henry Wallace

Definition at line 1361 of file MCMCProcessor.cpp.

1361  {
1362 // *********************
1363  //Save burn in cut, at the end of the loop we will return to default values
1364  const int DefaultUpperCut = UpperCut;
1365  const int DefaultBurnInCut = BurnInCut;
1366  bool defaultPrintToPDF = printToPDF;
1367  BurnInCut = 0;
1368  UpperCut = 0;
1369  printToPDF = false;
1370 
1371  //Set via config in future
1372  int MaxStep = nSteps;
1373  int MinStep = 0;
1374  const int IntervalsSize = nSteps/NIntervals;
1375 
1376  MACH3LOG_INFO("Making Suboptimality");
1377  TStopwatch clock;
1378  clock.Start();
1379 
1380  std::unique_ptr<TH1D> SubOptimality = std::make_unique<TH1D>("Suboptimality", "Suboptimality", NIntervals, MinStep, MaxStep);
1381  SubOptimality->SetDirectory(nullptr);
1382  SubOptimality->GetXaxis()->SetTitle("Step");
1383  SubOptimality->GetYaxis()->SetTitle("Suboptimality");
1384  SubOptimality->SetLineWidth(2);
1385  SubOptimality->SetLineColor(kBlue);
1386 
1387  for(int i = 0; i < NIntervals; ++i)
1388  {
1389  //Reset our cov matrix
1391 
1392  //Set threshold for calculating new matrix
1393  UpperCut = i*IntervalsSize;
1394  //Calculate cov matrix
1395  MakeCovariance_MP(true);
1396 
1397  //Calculate eigen values
1398  TMatrixDSymEigen eigen(*Covariance);
1399  TVectorD eigen_values;
1400  eigen_values.ResizeTo(eigen.GetEigenValues());
1401  eigen_values = eigen.GetEigenValues();
1402 
1403  //KS: Converting from ROOT to vector as to make using other libraires (Eigen) easier in future
1404  std::vector<double> EigenValues(eigen_values.GetNrows());
1405  for(unsigned int j = 0; j < EigenValues.size(); j++)
1406  {
1407  EigenValues[j] = eigen_values(j);
1408  }
1409  const double SubOptimalityValue = GetSubOptimality(EigenValues, nDraw);
1410  SubOptimality->SetBinContent(i+1, SubOptimalityValue);
1411  }
1412  clock.Stop();
1413  MACH3LOG_INFO("Making Suboptimality took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries);
1414 
1415  UpperCut = DefaultUpperCut;
1416  BurnInCut = DefaultBurnInCut;
1417  printToPDF = defaultPrintToPDF;
1418 
1419  SubOptimality->Draw("l");
1420  Posterior->SetName(SubOptimality->GetName());
1421  Posterior->SetTitle(SubOptimality->GetTitle());
1422 
1423  if(printToPDF) Posterior->Print(CanvasName);
1424  // Write it to root file
1425  OutputFile->cd();
1426  Posterior->Write();
1427 }
double GetSubOptimality(const std::vector< double > &EigenValues, const int TotalTarameters)
Based on .
void Reset2DPosteriors()
Reset 2D posteriors, in case we would like to calculate in again with different BurnInCut.

◆ MakeTrianglePlot()

void MCMCProcessor::MakeTrianglePlot ( const std::vector< std::string > &  ParNames,
const std::vector< double > &  CredibleIntervals = {0.99, 0.90, 0.68 },
const std::vector< Color_t > &  CredibleIntervalsColours = {kCyan+4, kCyan-2, kCyan-10},
const std::vector< double > &  CredibleRegions = {0.99, 0.90, 0.68},
const std::vector< Style_t > &  CredibleRegionStyle = {kDashed, kSolid, kDotted},
const std::vector< Color_t > &  CredibleRegionColor = {kGreen-3, kGreen-10, kGreen},
const bool  CredibleInSigmas = false 
)

Make fancy triangle plot for selected parameters.

Parameters
ParNamesParameters for which Triangle plot will be made
CredibleIntervalsVector with values of credible intervals, must be in descending order
CredibleIntervalsColoursColor_t telling what colour to use for each Interval line
CredibleRegionsVector with values of credible intervals, must be in descending order
CredibleRegionStyleStyle_t telling what line style to use for each Interval line
CredibleRegionColorColor_t telling what colour to use for each Interval line
CredibleInSigmasBool telling whether intervals are in percentage or in sigmas, then special conversions is used

Scale the histograms so it shows the posterior probability

Definition at line 1977 of file MCMCProcessor.cpp.

1986  {
1987 // *********************
1988  if(hpost2D.size() == 0) MakeCovariance_MP();
1989 
1990  const int nParamPlot = int(ParNames.size());
1991  std::vector<int> ParamNumber;
1992  std::string ParamInfoNames = "Making Triangle Plot for { ";
1993  for(int j = 0; j < nParamPlot; ++j)
1994  {
1995  ParamInfoNames += fmt::format("{} ", ParNames[j]);
1996  int ParamNo = GetParamIndexFromName(ParNames[j]);
1997  if(ParamNo == M3::_BAD_INT_)
1998  {
1999  MACH3LOG_WARN("Couldn't find param {}. Will not plot Triangle plot", ParNames[j]);
2000  return;
2001  }
2002  ParamNumber.push_back(ParamNo);
2003  }
2004  ParamInfoNames += "}";
2005  MACH3LOG_INFO("{}", ParamInfoNames);
2006 
2007  //KS: Store it as we go back to them at the end
2008  const std::vector<double> Margins = GetMargins(Posterior);
2009  Posterior->SetTopMargin(0.001);
2010  Posterior->SetBottomMargin(0.001);
2011  Posterior->SetLeftMargin(0.001);
2012  Posterior->SetRightMargin(0.001);
2013 
2014  // KS: We later format hist several times so make one unfired lambda
2015  auto FormatHistogram = [](auto& hist) {
2016  hist->GetXaxis()->SetTitle("");
2017  hist->GetYaxis()->SetTitle("");
2018  hist->SetTitle("");
2019 
2020  hist->GetXaxis()->SetLabelSize(0.1);
2021  hist->GetYaxis()->SetLabelSize(0.1);
2022 
2023  hist->GetXaxis()->SetNdivisions(4);
2024  hist->GetYaxis()->SetNdivisions(4);
2025  };
2026 
2027  Posterior->cd();
2028  Posterior->Clear();
2029  Posterior->Update();
2030 
2031  //KS: We sort to have parameters from highest to lowest, this is related to how we make 2D projections in MakeCovariance_MP
2032  std::sort(ParamNumber.begin(), ParamNumber.end(), std::greater<int>());
2033 
2034  //KS: Calculate how many pads/plots we need
2035  int Npad = 0;
2036  for(int j = 1; j < nParamPlot+1; j++) Npad += j;
2037  Posterior->cd();
2038  // KS: Sanity check of size and ordering is correct
2039  CheckCredibleIntervalsOrder(CredibleIntervals, CredibleIntervalsColours);
2040  CheckCredibleRegionsOrder(CredibleRegions, CredibleRegionStyle, CredibleRegionColor);
2041 
2042  const int nCredibleIntervals = int(CredibleIntervals.size());
2043  const int nCredibleRegions = int(CredibleRegions.size());
2044 
2045  //KS: Initialise Tpad histograms etc we will need
2046  std::vector<TPad*> TrianglePad(Npad);
2047  //KS: 1D copy of posterior, we need it as we modify them
2048  std::vector<std::unique_ptr<TH1D>> hpost_copy(nParamPlot);
2049  std::vector<std::vector<std::unique_ptr<TH1D>>> hpost_cl(nParamPlot);
2050  std::vector<std::unique_ptr<TText>> TriangleText(nParamPlot * 2);
2051  std::vector<std::unique_ptr<TH2D>> hpost_2D_copy(Npad-nParamPlot);
2052  std::vector<std::vector<std::unique_ptr<TH2D>>> hpost_2D_cl(Npad-nParamPlot);
2053  gStyle->SetPalette(51);
2054 
2055  //KS: Super convoluted way of calculating ranges for our pads, trust me it works...
2056  std::vector<double> X_Min(nParamPlot);
2057  std::vector<double> X_Max(nParamPlot);
2058 
2059  //TN:
2060  // n = number of params (nParamPlot)
2061  // a_x = width of the left margin space for pad axis labels on the left in canvas coordinates
2062  // a_y = height of the bottom margin space for pad axis labels on the bottom in canvas coordinates
2063  // b_x = pad plot width in canvas coordinates
2064  // b_y = pad plot height in canvas coordinates
2065  // Pm = a/(a+b) = actual margin within the first plot from the left (a_x,b_x) or bottom (a_y,b_y); Pm = {left,bottom}
2066  // TPm = desired margin of the whole triangle plot in canvas coordinates; TPm = {left, bottom, right, top}
2067  // TPw = 1.-TPm[0]-TPm[2] width of the triangle plot in canvas coordinates
2068  // TPh = 1.-TPm[1]-TPm[3] height of the triangle plot in canvas coordinates
2069  // Then a_x+n*b_x = TPw = 1.-TPm[0]-TPm[1]
2070  // Hence from that:
2071  // a_x = Pm[0]*(a_x+b_x) = Pm[0]*(a_x+(TPw-a_x)/n) => a_x = (Pm[0]*TPw)/(n+Pm[0]*(1-n))
2072  // b_x = (TPw-a_x)/n
2073 
2074  // The inputs:
2075  const double TPm[4] = {.07,.07,.05,.05};
2076  const double Pm[2] = {.2,.1};
2077 
2078  // Auxiliary x-direction:
2079  const double TPw = 1. - TPm[0] - TPm[2];
2080  const double a_x = ( Pm[0] * TPw ) / ( 1. * nParamPlot + Pm[0] * ( 1. - 1.*nParamPlot ) );
2081  const double b_x = ( TPw - a_x ) / ( 1. * nParamPlot );
2082 
2083  X_Min[0] = TPm[0];
2084  X_Max[0] = X_Min[0] + a_x + b_x;
2085  for(int i = 1; i < nParamPlot; i++)
2086  {
2087  X_Min[i] = X_Max[i-1];
2088  X_Max[i] = X_Min[i]+b_x;
2089  }
2090 
2091  std::vector<double> Y_Min(nParamPlot);
2092  std::vector<double> Y_Max(nParamPlot);
2093 
2094  // Auxiliary y-direction:
2095  const double TPh = 1. - TPm[1] - TPm[3];
2096  const double a_y = ( Pm[1] * TPh ) / ( 1. * nParamPlot + Pm[1] * ( 1. - 1.*nParamPlot ) );
2097  const double b_y = ( TPh - a_y ) / ( 1. * nParamPlot );
2098 
2099  Y_Min[nParamPlot-1] = TPm[1];
2100  Y_Max[nParamPlot-1] = Y_Min[nParamPlot-1] + a_y + b_y;
2101  for(int i = nParamPlot-2; i >= 0; i--)
2102  {
2103  Y_Min[i] = Y_Max[i+1];
2104  Y_Max[i] = Y_Min[i]+b_y;
2105  }
2106 
2107  //KS: We store as numbering of isn't straightforward
2108  int counterPad = 0, counterText = 0, counterPost = 0, counter2DPost = 0;
2109  //KS: We start from top of the plot, might be confusing but works very well
2110  for(int y = 0; y < nParamPlot; y++)
2111  {
2112  //KS: start from left and go right, depending on y
2113  for(int x = 0; x <= y; x++)
2114  {
2115  //KS: Need to go to canvas every time to have our pads in the same canvas, not pads in the pads
2116  Posterior->cd();
2117  TrianglePad[counterPad] = new TPad(Form("TPad_%i", counterPad), Form("TPad_%i", counterPad), X_Min[x], Y_Min[y], X_Max[x], Y_Max[y]);
2118 
2119  TrianglePad[counterPad]->SetTopMargin(0);
2120  TrianglePad[counterPad]->SetRightMargin(0);
2121 
2122  TrianglePad[counterPad]->SetGrid();
2123  TrianglePad[counterPad]->SetFrameBorderMode(0);
2124  TrianglePad[counterPad]->SetBorderMode(0);
2125  TrianglePad[counterPad]->SetBorderSize(0);
2126 
2127  //KS: Corresponds to bottom part of the plot, need margins for labels
2128  TrianglePad[counterPad]->SetBottomMargin(y == (nParamPlot - 1) ? Pm[1] : 0);
2129  //KS: Corresponds to left part, need margins for labels
2130  TrianglePad[counterPad]->SetLeftMargin(x == 0 ? Pm[0] : 0);
2131 
2132  TrianglePad[counterPad]->Draw();
2133  TrianglePad[counterPad]->cd();
2134 
2135  //KS:if diagonal plot main posterior
2136  if(x == y)
2137  {
2138  hpost_copy[counterPost] = M3::Clone<TH1D>(hpost[ParamNumber[x]], Form("hpost_copy_%i", ParamNumber[x]));
2139  hpost_cl[counterPost].resize(nCredibleIntervals);
2141  hpost_copy[counterPost]->Scale(1. / hpost_copy[counterPost]->Integral());
2142  for (int j = 0; j < nCredibleIntervals; ++j)
2143  {
2144  hpost_cl[counterPost][j] = M3::Clone<TH1D>(hpost[ParamNumber[x]], Form("hpost_copy_%i_CL_%f", ParamNumber[x], CredibleIntervals[j]));
2145  //KS: Reset to get rid to TF1 otherwise we run into segfault :(
2146  hpost_cl[counterPost][j]->Reset("");
2147  hpost_cl[counterPost][j]->Fill(0.0, 0.0);
2148 
2149  // Scale the histograms before gettindg credible intervals
2150  hpost_cl[counterPost][j]->Scale(1. / hpost_cl[counterPost][j]->Integral());
2151  GetCredibleIntervalSig(hpost_copy[counterPost], hpost_cl[counterPost][j], CredibleInSigmas, CredibleIntervals[j]);
2152 
2153  hpost_cl[counterPost][j]->SetFillColor(CredibleIntervalsColours[j]);
2154  hpost_cl[counterPost][j]->SetLineWidth(1);
2155  }
2156 
2157  hpost_copy[counterPost]->SetMaximum(hpost_copy[counterPost]->GetMaximum()*1.2);
2158  hpost_copy[counterPost]->SetLineWidth(2);
2159  hpost_copy[counterPost]->SetLineColor(kBlack);
2160 
2161  //KS: Don't want any titles
2162  FormatHistogram(hpost_copy[counterPost]);
2163 
2164  //TN: Scale the size of labels with the plots size.
2165  //Unfortunately, this needs to managed through absolute sizes
2166  //as each pad is of different size.
2167  hpost_copy[counterPost]->GetXaxis()->SetLabelFont(133);
2168  hpost_copy[counterPost]->GetXaxis()->SetLabelSize(.08*(a_y+b_y)*Posterior->GetWh());
2169 
2170  hpost_copy[counterPost]->GetYaxis()->SetLabelFont(133);
2171  hpost_copy[counterPost]->GetYaxis()->SetLabelSize(.08*(a_y+b_y)*Posterior->GetWh());
2172 
2173  hpost_copy[counterPost]->Draw("HIST");
2174  for (int j = 0; j < nCredibleIntervals; ++j){
2175  hpost_cl[counterPost][j]->Draw("HIST SAME");
2176  }
2177  counterPost++;
2178  }
2179  //KS: Here we plot 2D credible regions
2180  else
2181  {
2182  hpost_2D_copy[counter2DPost] = M3::Clone<TH2D>(hpost2D[ParamNumber[x]][ParamNumber[y]],
2183  Form("hpost_copy_%i_%i", ParamNumber[x], ParamNumber[y]));
2184  hpost_2D_cl[counter2DPost].resize(nCredibleRegions);
2185  //KS: Now copy for every credible region
2186  for (int k = 0; k < nCredibleRegions; ++k)
2187  {
2188  hpost_2D_cl[counter2DPost][k] = M3::Clone<TH2D>(hpost2D[ParamNumber[x]][ParamNumber[y]],
2189  Form("hpost_copy_%i_%i_CL_%f", ParamNumber[x], ParamNumber[y], CredibleRegions[k]));
2190  GetCredibleRegionSig(hpost_2D_cl[counter2DPost][k], CredibleInSigmas, CredibleRegions[k]);
2191 
2192  hpost_2D_cl[counter2DPost][k]->SetLineColor(CredibleRegionColor[k]);
2193  hpost_2D_cl[counter2DPost][k]->SetLineWidth(2);
2194  hpost_2D_cl[counter2DPost][k]->SetLineStyle(CredibleRegionStyle[k]);
2195  }
2196  //KS: Don't want any titles
2197  FormatHistogram(hpost_2D_copy[counter2DPost]);
2198 
2199  //TN: Scale the size of labels with the plots size.
2200  //Unfortunately, this needs to managed through absolute sizes
2201  //as each pad is of different size.
2202  hpost_2D_copy[counter2DPost]->GetXaxis()->SetLabelFont(133);
2203  hpost_2D_copy[counter2DPost]->GetXaxis()->SetLabelSize(.08*(a_y+b_y)*Posterior->GetWh());
2204 
2205  hpost_2D_copy[counter2DPost]->GetYaxis()->SetLabelFont(133);
2206  hpost_2D_copy[counter2DPost]->GetYaxis()->SetLabelSize(.08*(a_y+b_y)*Posterior->GetWh());
2207 
2208  hpost_2D_copy[counter2DPost]->Draw("COL");
2209  //Now credible regions
2210  for (int k = 0; k < nCredibleRegions; ++k){
2211  hpost_2D_cl[counter2DPost][k]->Draw("CONT3 SAME");
2212  }
2213  counter2DPost++;
2214  }
2215  //KS: Corresponds to bottom part of the plot
2216  if(y == (nParamPlot-1))
2217  {
2218  Posterior->cd();
2219  TriangleText[counterText] = std::make_unique<TText>(X_Min[x] + (X_Max[x]-X_Min[x]+(x == 0 ? a_x : .0))/2., .05, hpost[ParamNumber[x]]->GetTitle());
2220  //KS: Unfortunately for many plots or long names this can go out of bounds :(
2221  //TN: Align the axis titles and scale them with the size of the plots
2222  TriangleText[counterText]->SetTextAlign(22);
2223  TriangleText[counterText]->SetTextSize(.08*(a_y+b_y));
2224  TriangleText[counterText]->SetNDC(true);
2225  TriangleText[counterText]->Draw();
2226  counterText++;
2227  }
2228  //KS: Corresponds to left part
2229  if(x == 0)
2230  {
2231  Posterior->cd();
2232  TriangleText[counterText] = std::make_unique<TText>(.05, Y_Min[y] + (Y_Max[y]-Y_Min[y]+(y == nParamPlot-1 ? a_y : .0))/2., hpost[ParamNumber[y]]->GetTitle());
2233  //KS: Rotate as this is y axis
2234  TriangleText[counterText]->SetTextAngle(90);
2235  //KS: Unfortunately for many plots or long names this can go out of bounds :(
2236  //TN: Align the axis titles and scale them with the size of the plots
2237  TriangleText[counterText]->SetTextAlign(22);
2238  TriangleText[counterText]->SetTextSize(.08*(a_y+b_y));
2239  TriangleText[counterText]->SetNDC(true);
2240  TriangleText[counterText]->Draw();
2241  counterText++;
2242  }
2243  Posterior->Update();
2244  counterPad++;
2245  }
2246  }
2247 
2248  Posterior->cd();
2249  auto legend = std::make_unique<TLegend>(0.60, 0.7, 0.9, 0.9);
2250  SetLegendStyle(legend.get(), 0.03);
2251  //KS: Legend is shared so just take first histograms
2252  for (int j = nCredibleIntervals-1; j >= 0; --j)
2253  {
2254  if(CredibleInSigmas)
2255  legend->AddEntry(hpost_cl[0][j].get(), Form("%.0f#sigma Credible Interval", CredibleIntervals[j]), "f");
2256  else
2257  legend->AddEntry(hpost_cl[0][j].get(), Form("%.0f%% Credible Interval", CredibleRegions[j]*100), "f");
2258  }
2259  for (int k = nCredibleRegions-1; k >= 0; --k)
2260  {
2261  if(CredibleInSigmas)
2262  legend->AddEntry(hpost_2D_cl[0][k].get(), Form("%.0f#sigma Credible Region", CredibleRegions[k]), "l");
2263  else
2264  legend->AddEntry(hpost_2D_cl[0][k].get(), Form("%.0f%% Credible Region", CredibleRegions[k]*100), "l");
2265  }
2266  legend->Draw("SAME");
2267  Posterior->Update();
2268 
2269  // Write to file
2270  Posterior->SetName("TrianglePlot");
2271  Posterior->SetTitle("TrianglePlot");
2272 
2273  if(printToPDF) Posterior->Print(CanvasName);
2274  // Write it to root file
2275  OutputFile->cd();
2276  Posterior->Write();
2277 
2278  //KS: Remove allocated structures
2279  for(int i = 0; i < Npad; i++) delete TrianglePad[i];
2280 
2281  //KS: Restore margin
2282  SetMargins(Posterior, Margins);
2283 }

◆ MakeViolin()

void MCMCProcessor::MakeViolin ( )

Make and Draw Violin.

Definition at line 821 of file MCMCProcessor.cpp.

821  {
822 // *********************
823  //KS: Make sure we have steps
824  if(!CacheMCMC) CacheSteps();
825  MACH3LOG_INFO("Starting {}", __func__);
826 
827  //KS: Find min and max to make histogram in range
828  double maxi_y = -9999;
829  double mini_y = +9999;
830  for (int i = 0; i < nDraw; ++i)
831  {
832  auto range = GetHistRange(i);
833  mini_y = std::min(mini_y, range.first);
834  maxi_y = std::max(maxi_y, range.second);
835  }
836 
837  const int vBins = (maxi_y-mini_y)*25;
838  hviolin = std::make_unique<TH2D>("hviolin", "hviolin", nDraw, 0, nDraw, vBins, mini_y, maxi_y);
839  hviolin->SetDirectory(nullptr);
840  //KS: Prior has larger errors so we increase range and number of bins
841  constexpr int PriorFactor = 4;
842  hviolin_prior = std::make_unique<TH2D>("hviolin_prior", "hviolin_prior", nDraw, 0, nDraw, PriorFactor*vBins, PriorFactor*mini_y, PriorFactor*maxi_y);
843  hviolin_prior->SetDirectory(nullptr);
844 
845  auto rand = std::make_unique<TRandom3>(0);
846  std::vector<double> PriorVec(nDraw);
847  std::vector<double> PriorErrorVec(nDraw);
848  std::vector<bool> PriorFlatVec(nDraw);
849 
850  for (int x = 0; x < nDraw; ++x)
851  {
852  TString Title;
853  double Prior, PriorError;
854 
855  GetNthParameter(x, Prior, PriorError, Title);
856  //Set fancy labels
857  hviolin->GetXaxis()->SetBinLabel(x+1, Title);
858  hviolin_prior->GetXaxis()->SetBinLabel(x+1, Title);
859  PriorVec[x] = Prior;
860  PriorErrorVec[x] = PriorError;
861 
862  PriorFlatVec[x] = GetParamFlat(x);
863  }
864 
865  TStopwatch clock;
866  clock.Start();
867 
868  // nDraw is number of draws we want to do
869  #ifdef MULTITHREAD
870  #pragma omp parallel for
871  #endif
872  for (int x = 0; x < nDraw; ++x)
873  {
874  //KS: Consider another treatment for fixed params
875  //if (ParamVaried[x] == false) continue;
876  for (int k = 0; k < nEntries; ++k)
877  {
878  //KS: Burn in cut
879  if(StepNumber[k] < BurnInCut) continue;
880 
881  //KS: We know exactly which x bin we will end up, find y bin. This allow to avoid costly Fill() and enable multithreading because I am master of faster
882  const double y = hviolin->GetYaxis()->FindBin(ParStep[x][k]);
883  hviolin->SetBinContent(x+1, y, hviolin->GetBinContent(x+1, y)+1);
884  }
885 
886  //KS: If we set option to not plot flat prior and param has flat prior then we skip this step
887  if(!(!PlotFlatPrior && PriorFlatVec[x]))
888  {
889  for (int k = 0; k < nEntries; ++k)
890  {
891  const double Entry = rand->Gaus(PriorVec[x], PriorErrorVec[x]);
892  const double y = hviolin_prior->GetYaxis()->FindBin(Entry);
893  hviolin_prior->SetBinContent(x+1, y, hviolin_prior->GetBinContent(x+1, y)+1);
894  }
895  }
896  } // end the for loop over nDraw
897  clock.Stop();
898  MACH3LOG_INFO("Making Violin plot took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries);
899 
900  //KS: Tells how many parameters in one canvas we want
901  constexpr int IntervalsSize = 10;
902  const int NIntervals = nDraw/IntervalsSize;
903 
904  hviolin->GetYaxis()->SetTitle("Parameter Value");
905  hviolin->GetXaxis()->SetTitle();
906  hviolin->GetXaxis()->LabelsOption("v");
907 
908  hviolin_prior->GetYaxis()->SetTitle("Parameter Value");
909  hviolin_prior->GetXaxis()->SetTitle();
910  hviolin_prior->GetXaxis()->LabelsOption("v");
911 
912  hviolin_prior->SetLineColor(kRed);
913  hviolin_prior->SetMarkerColor(kRed);
914  hviolin_prior->SetFillColorAlpha(kRed, 0.35);
915  hviolin_prior->SetMarkerStyle(20);
916  hviolin_prior->SetMarkerSize(0.5);
917 
918  // These control violin width, if you use larger then 1 they will most likely overlay, so be cautious
919  hviolin_prior->SetBarWidth(1.0);
920  hviolin_prior->SetBarOffset(0);
921 
922  hviolin->SetLineColor(kBlue);
923  hviolin->SetMarkerColor(kBlue);
924  hviolin->SetFillColorAlpha(kBlue, 0.35);
925  hviolin->SetMarkerStyle(20);
926  hviolin->SetMarkerSize(1.0);
927 
928  const double BottomMargin = Posterior->GetBottomMargin();
929  Posterior->SetBottomMargin(0.2);
930 
931  OutputFile->cd();
932  hviolin->Write("param_violin");
933  hviolin_prior->Write("param_violin_prior");
934  //KS: This is mostly for example plots, we have full file in the ROOT file so can do much better plot later
935  hviolin->GetYaxis()->SetRangeUser(-1, +2);
936  hviolin_prior->GetYaxis()->SetRangeUser(-1, +2);
937  for (int i = 0; i < NIntervals+1; ++i)
938  {
939  int RangeMin = i*IntervalsSize;
940  int RangeMax = RangeMin + IntervalsSize;
941  if(i == NIntervals+1) {
942  RangeMin = i*IntervalsSize;
943  RangeMax = nDraw;
944  }
945  if(RangeMin >= nDraw) break;
946 
947  hviolin->GetXaxis()->SetRangeUser(RangeMin, RangeMax);
948  hviolin_prior->GetXaxis()->SetRangeUser(RangeMin, RangeMax);
949 
950  //KS: ROOT6 has some additional options, consider updating it. more https://root.cern/doc/master/classTHistPainter.html#HP140b
951  hviolin_prior->Draw("violinX(03100300)");
952  hviolin->Draw("violinX(03100300) SAME");
953  if(printToPDF) Posterior->Print(CanvasName);
954  }
955  //KS: Return Margin to default one
956  Posterior->SetBottomMargin(BottomMargin);
957 }

◆ ParameterEvolution()

void MCMCProcessor::ParameterEvolution ( const std::vector< std::string > &  Names,
const std::vector< int > &  NIntervals 
)

Make .gif of parameter evolution.

Parameters
NamesParameter names for which we do .gif
NIntervalsNumber of intervals for a gif

Definition at line 3263 of file MCMCProcessor.cpp.

3264  {
3265 // **************************
3266  MACH3LOG_INFO("Starting {}", __func__);
3267 
3268  //KS: First we need to find parameter number based on name
3269  for(unsigned int k = 0; k < Names.size(); ++k)
3270  {
3271  //KS: First we need to find parameter number based on name
3272  int ParamNo = GetParamIndexFromName(Names[k]);
3273  if(ParamNo == M3::_BAD_INT_)
3274  {
3275  MACH3LOG_WARN("Couldn't find param {}. Can't reweight Prior", Names[k]);
3276  continue;
3277  }
3278 
3279  const int IntervalsSize = nSteps/NIntervals[k];
3280  // ROOT won't overwrite gifs so we need to delete the file if it's there already
3281  std::string filename = Names[k] + ".gif";
3282  std::ifstream f(filename);
3283  if (f.good()) {
3284  f.close();
3285  int ret = system(fmt::format("rm {}", filename).c_str());
3286  if (ret != 0) {
3287  MACH3LOG_WARN("Error: system call to delete {} failed with code {}", filename, ret);
3288  }
3289  }
3290 
3291  int Counter = 0;
3292  for(int i = NIntervals[k]-1; i >= 0; --i)
3293  {
3294  // This holds the posterior density
3295  // KS: WARNING do not change to smart pointer, it breaks and I don't know why
3296  TH1D* EvePlot = new TH1D(BranchNames[ParamNo], BranchNames[ParamNo], nBins,
3297  hpost[ParamNo]->GetXaxis()->GetXmin(), hpost[ParamNo]->GetXaxis()->GetXmax());
3298  EvePlot->SetMinimum(0);
3299  EvePlot->GetYaxis()->SetTitle("PDF");
3300  EvePlot->GetYaxis()->SetNoExponent(false);
3301 
3302  //KS: Apply additional Cuts, like mass ordering
3303  std::string CutPosterior1D = "step > " + std::to_string(i*IntervalsSize+IntervalsSize);
3304 
3305  // If Posterior1DCut is not empty, append it
3306  if (!Posterior1DCut.empty()) {
3307  CutPosterior1D += " && " + Posterior1DCut;
3308  }
3309 
3310  // Apply reweighting if requested
3311  if (ReweightPosterior) {
3312  for (const auto& name : ReweightNames) {
3313  CutPosterior1D = "(" + CutPosterior1D + ")*(" + name + ")";
3314  }
3315  }
3316 
3317  std::string TextTitle = "Steps = 0 - "+std::to_string(Counter*IntervalsSize+IntervalsSize);
3318  // Project BranchNames[ParamNo] onto hpost, applying stepcut
3319  Chain->Project(BranchNames[ParamNo], BranchNames[ParamNo], CutPosterior1D.c_str());
3320 
3321  EvePlot->SetLineWidth(2);
3322  EvePlot->SetLineColor(kBlue-1);
3323  EvePlot->SetTitle(Names[k].c_str());
3324  EvePlot->GetXaxis()->SetTitle(EvePlot->GetTitle());
3325  EvePlot->GetYaxis()->SetLabelOffset(1000);
3326  if(ApplySmoothing) EvePlot->Smooth();
3327 
3328  EvePlot->Scale(1. / EvePlot->Integral());
3329  EvePlot->Draw("HIST");
3330 
3331  TText text(0.3, 0.8, TextTitle.c_str());
3332  text.SetTextFont (43);
3333  text.SetTextSize (40);
3334  text.SetNDC(true);
3335  text.Draw("SAME");
3336 
3337  if(i == 0) Posterior->Print((Names[k] + ".gif++20").c_str()); // produces infinite loop animated GIF
3338  else Posterior->Print((Names[k] + ".gif+20").c_str()); // add picture to .gif
3339  delete EvePlot;
3340  Counter++;
3341  }
3342  }
3343 }

◆ ParamTraces()

void MCMCProcessor::ParamTraces ( )
protected

CW: Draw trace plots of the parameters i.e. parameter vs step.

Definition at line 3544 of file MCMCProcessor.cpp.

3544  {
3545 // *****************
3546  if (ParStep == nullptr) PrepareDiagMCMC();
3547  MACH3LOG_INFO("Making trace plots...");
3548  // Make the TH1Ds
3549  std::vector<std::unique_ptr<TH1D>> TraceParamPlots(nDraw);
3550  std::vector<std::unique_ptr<TH1D>> TraceSamplePlots(SampleName_v.size());
3551  std::vector<std::unique_ptr<TH1D>> TraceSystsPlots(SystName_v.size());
3552 
3553  // Set the titles and limits for TH2Ds
3554  for (int j = 0; j < nDraw; ++j) {
3555  TString Title = "";
3556  double Prior = 1.0, PriorError = 1.0;
3557 
3558  GetNthParameter(j, Prior, PriorError, Title);
3559  std::string HistName = Form("%s_%s_Trace", Title.Data(), BranchNames[j].Data());
3560  TraceParamPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nEntries, 0, nEntries);
3561  TraceParamPlots[j]->SetDirectory(nullptr);
3562  TraceParamPlots[j]->GetXaxis()->SetTitle("Step");
3563  TraceParamPlots[j]->GetYaxis()->SetTitle("Parameter Variation");
3564  }
3565 
3566  for (size_t j = 0; j < SampleName_v.size(); ++j) {
3567  std::string HistName = SampleName_v[j].Data();
3568  TraceSamplePlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nEntries, 0, nEntries);
3569  TraceSamplePlots[j]->SetDirectory(nullptr);
3570  TraceSamplePlots[j]->GetXaxis()->SetTitle("Step");
3571  TraceSamplePlots[j]->GetYaxis()->SetTitle("Sample -logL");
3572  }
3573 
3574  for (size_t j = 0; j < SystName_v.size(); ++j) {
3575  std::string HistName = SystName_v[j].Data();
3576  TraceSystsPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nEntries, 0, nEntries);
3577  TraceSystsPlots[j]->SetDirectory(nullptr);
3578  TraceSystsPlots[j]->GetXaxis()->SetTitle("Step");
3579  TraceSystsPlots[j]->GetYaxis()->SetTitle("Systematic -logL");
3580  }
3581 
3582  // Have now made the empty TH1Ds, now for writing content to them!
3583  // Loop over the number of parameters to draw their traces
3584  // Each histogram
3585  #ifdef MULTITHREAD
3586  #pragma omp parallel for
3587  #endif
3588  for (int i = 0; i < nEntries; ++i) {
3589  // Set bin content for the ith bin to the parameter values
3590  for (int j = 0; j < nDraw; ++j) {
3591  TraceParamPlots[j]->SetBinContent(i, ParStep[j][i]);
3592  }
3593  for (size_t j = 0; j < SampleName_v.size(); ++j) {
3594  TraceSamplePlots[j]->SetBinContent(i, SampleValues[i][j]);
3595  }
3596  for (size_t j = 0; j < SystName_v.size(); ++j) {
3597  TraceSystsPlots[j]->SetBinContent(i, SystValues[i][j]);
3598  }
3599  }
3600 
3601  // Write the output and delete the TH2Ds
3602  TDirectory *TraceDir = OutputFile->mkdir("Trace");
3603  TraceDir->cd();
3604  for (int j = 0; j < nDraw; ++j) {
3605  // Fit a linear function to the traces
3606  auto Fitter = std::make_unique<TF1>("Fitter", "[0]", nEntries/2, nEntries);
3607  Fitter->SetLineColor(kRed);
3608  TraceParamPlots[j]->Fit("Fitter","Rq");
3609  TraceParamPlots[j]->Write();
3610  }
3611 
3612  TDirectory *LLDir = OutputFile->mkdir("LogL");
3613  LLDir->cd();
3614  for (size_t j = 0; j < SampleName_v.size(); ++j) {
3615  TraceSamplePlots[j]->Write();
3616  delete[] SampleValues[j];
3617  }
3618  delete[] SampleValues;
3619 
3620  for (size_t j = 0; j < SystName_v.size(); ++j) {
3621  TraceSystsPlots[j]->Write();
3622  delete SystValues[j];
3623  }
3624  delete[] SystValues;
3625 
3626  TraceDir->Close();
3627  delete TraceDir;
3628 
3629  OutputFile->cd();
3630 }

◆ PowerSpectrumAnalysis()

void MCMCProcessor::PowerSpectrumAnalysis ( )
protected

RC: Perform spectral analysis of MCMC [7].

Author
Richard Calland
Todo:
KS: Code is awfully slow... I know how to make it faster (GPU scream in a distant) but for now just make it for two params, bit hacky sry...

Definition at line 4231 of file MCMCProcessor.cpp.

4231  {
4232 // **************************
4233  TStopwatch clock;
4234  clock.Start();
4235 
4236  //KS: Store it as we go back to them at the end
4237  const double TopMargin = Posterior->GetTopMargin();
4238  const int OptTitle = gStyle->GetOptTitle();
4239 
4240  Posterior->SetTopMargin(0.1);
4241  gStyle->SetOptTitle(1);
4242 
4243  MACH3LOG_INFO("Making Power Spectrum plots...");
4244 
4245  // This is only to reduce number of computations...
4246  const int N_Coeffs = std::min(10000, nEntries);
4247  const int start = -(N_Coeffs/2-1);
4248  const int end = N_Coeffs/2-1;
4249  const int v_size = end - start;
4250 
4251  int nPrams = nDraw;
4253  nPrams = 1;
4254 
4255  std::vector<std::vector<float>> k_j(nPrams, std::vector<float>(v_size, 0.0));
4256  std::vector<std::vector<float>> P_j(nPrams, std::vector<float>(v_size, 0.0));
4257 
4258  int _N = nEntries;
4259  if (_N % 2 != 0) _N -= 1; // N must be even
4260 
4261  //This is being used a lot so calculate it once to increase performance
4262  const double two_pi_over_N = 2 * TMath::Pi() / static_cast<double>(_N);
4263 
4264  // KS: This could be moved to GPU I guess
4265  #ifdef MULTITHREAD
4266  #pragma omp parallel for collapse(2)
4267  #endif
4268  // RC: equation 11: for each value of j coef, from range -N/2 -> N/2
4269  for (int j = 0; j < nPrams; ++j)
4270  {
4271  for (int jj = start; jj < end; ++jj)
4272  {
4273  std::complex<M3::float_t> a_j = 0.0;
4274  const double two_pi_over_N_jj = two_pi_over_N * jj;
4275  for (int n = 0; n < _N; ++n)
4276  {
4277  //if(StepNumber[n] < BurnInCut) continue;
4278  std::complex<M3::float_t> exp_temp(0, two_pi_over_N_jj * n);
4279  a_j += ParStep[j][n] * std::exp(exp_temp);
4280  }
4281  a_j /= std::sqrt(float(_N));
4282  const int _c = jj - start;
4283 
4284  k_j[j][_c] = two_pi_over_N_jj;
4285  // Equation 13
4286  P_j[j][_c] = std::norm(a_j);
4287  }
4288  }
4289 
4290  TDirectory *PowerDir = OutputFile->mkdir("PowerSpectrum");
4291  PowerDir->cd();
4292 
4293  TVectorD* PowerSpectrumStepSize = new TVectorD(nPrams);
4294  for (int j = 0; j < nPrams; ++j)
4295  {
4296  auto plot = std::make_unique<TGraph>(v_size, k_j[j].data(), P_j[j].data());
4297 
4298  TString Title = "";
4299  double Prior = 1.0, PriorError = 1.0;
4300  GetNthParameter(j, Prior, PriorError, Title);
4301 
4302  std::string name = Form("Power Spectrum of %s;k;P(k)", Title.Data());
4303 
4304  plot->SetTitle(name.c_str());
4305  name = Form("%s_power_spectrum", Title.Data());
4306  plot->SetName(name.c_str());
4307  plot->SetMarkerStyle(7);
4308 
4309  // Equation 18
4310  auto func = std::make_unique<TF1>("power_template", "[0]*( ([1] / x)^[2] / (([1] / x)^[2] +1) )", 0.0, 1.0);
4311  // P0 gives the amplitude of the white noise spectrum in the k → 0 limit
4312  func->SetParameter(0, 10.0);
4313  // k* indicates the position of the turnover to a different power law behaviour
4314  func->SetParameter(1, 0.1);
4315  // alpha free parameter
4316  func->SetParameter(2, 2.0);
4317 
4318  // Set parameter limits for stability
4319  func->SetParLimits(0, 0.0, 100.0); // Amplitude should be non-negative
4320  func->SetParLimits(1, 0.001, 1.0); // k* should be within a reasonable range
4321  func->SetParLimits(2, 0.0, 5.0); // alpha should be positive
4322 
4323  plot->Fit("power_template","Rq");
4324 
4325  Posterior->SetLogx();
4326  Posterior->SetLogy();
4327  Posterior->SetGrid();
4328  plot->Draw("AL");
4329  func->Draw("SAME");
4330 
4331  //KS: I have no clue what is the reason behind this. Found this in Rick Calland code...
4332  (*PowerSpectrumStepSize)(j) = std::sqrt(func->GetParameter(0)/float(v_size*0.5));
4333  }
4334 
4335  PowerSpectrumStepSize->Write("PowerSpectrumStepSize");
4336  delete PowerSpectrumStepSize;
4337  PowerDir->Close();
4338  delete PowerDir;
4339 
4340  clock.Stop();
4341  MACH3LOG_INFO("Making Power Spectrum took {:.2f}s", clock.RealTime());
4342 
4343  Posterior->SetTopMargin(TopMargin);
4344  gStyle->SetOptTitle(OptTitle);
4345 }

◆ PrepareDiagMCMC()

void MCMCProcessor::PrepareDiagMCMC ( )
protected

CW: Prepare branches etc. for DiagMCMC.

Definition at line 3383 of file MCMCProcessor.cpp.

3383  {
3384 // **************************
3385  doDiagMCMC = true;
3386 
3387  if(ParStep != nullptr) {
3388  MACH3LOG_ERROR("It look like ParStep was already filled ");
3389  MACH3LOG_ERROR("Even though it is used for MakeCovariance_MP and for DiagMCMC");
3390  MACH3LOG_ERROR("it has different structure in both for cache hits, sorry ");
3391  throw MaCh3Exception(__FILE__ , __LINE__ );
3392  }
3393  if(nBatches == 0) {
3394  MACH3LOG_ERROR("nBatches is equal to 0");
3395  MACH3LOG_ERROR("please use SetnBatches to set other value fore example 20");
3396  throw MaCh3Exception(__FILE__ , __LINE__ );
3397  }
3398 
3399  // Initialise ParStep
3400  ParStep = new M3::float_t*[nDraw]();
3401  for (int j = 0; j < nDraw; ++j) {
3402  ParStep[j] = new M3::float_t[nEntries]();
3403  for (int i = 0; i < nEntries; ++i) {
3404  ParStep[j][i] = -999.99;
3405  }
3406  }
3407 
3408  SampleValues = new double*[nEntries]();
3409  SystValues = new double*[nEntries]();
3410  AccProbValues = new double[nEntries]();
3411  StepNumber = new unsigned int[nEntries]();
3412  for (int i = 0; i < nEntries; ++i) {
3413  SampleValues[i] = new double[SampleName_v.size()]();
3414  SystValues[i] = new double[SystName_v.size()]();
3415 
3416  for (size_t j = 0; j < SampleName_v.size(); ++j) {
3417  SampleValues[i][j] = -999.99;
3418  }
3419  for (size_t j = 0; j < SystName_v.size(); ++j) {
3420  SystValues[i][j] = -999.99;
3421  }
3422  AccProbValues[i] = -999.99;
3423  StepNumber[i] = 0;
3424  }
3425 
3426  MACH3LOG_INFO("Reading input tree...");
3427  TStopwatch clock;
3428  clock.Start();
3429 
3430  // Set all the branches to off
3431  Chain->SetBranchStatus("*", false);
3432 
3433  // 10 entries output
3434  const int countwidth = nEntries/10;
3435 
3436  // Can also do the batched means here to minimize excessive loops
3437  // The length of each batch
3438  const int BatchLength = nEntries/nBatches+1;
3439  BatchedAverages = new double*[nBatches]();
3440  AccProbBatchedAverages = new double[nBatches]();
3441  for (int i = 0; i < nBatches; ++i) {
3442  BatchedAverages[i] = new double[nDraw];
3443  AccProbBatchedAverages[i] = 0;
3444  for (int j = 0; j < nDraw; ++j) {
3445  BatchedAverages[i][j] = 0.0;
3446  }
3447  }
3448  std::vector<double> ParStepBranch(nDraw);
3449  std::vector<double> SampleValuesBranch(SampleName_v.size());
3450  std::vector<double> SystValuesBranch(SystName_v.size());
3451  unsigned int StepNumberBranch = 0;
3452  double AccProbValuesBranch = 0;
3453  // Set the branch addresses for params
3454  for (int j = 0; j < nDraw; ++j) {
3455  Chain->SetBranchStatus(BranchNames[j].Data(), true);
3456  Chain->SetBranchAddress(BranchNames[j].Data(), &ParStepBranch[j]);
3457  }
3458  // Set the branch addresses for samples
3459  for (size_t j = 0; j < SampleName_v.size(); ++j) {
3460  Chain->SetBranchStatus(SampleName_v[j].Data(), true);
3461  Chain->SetBranchAddress(SampleName_v[j].Data(), &SampleValuesBranch[j]);
3462  }
3463  // Set the branch addresses for systematics
3464  for (size_t j = 0; j < SystName_v.size(); ++j) {
3465  Chain->SetBranchStatus(SystName_v[j].Data(), true);
3466  Chain->SetBranchAddress(SystName_v[j].Data(), &SystValuesBranch[j]);
3467  }
3468  // Only needed for Geweke right now
3469  Chain->SetBranchStatus("step", true);
3470  Chain->SetBranchAddress("step", &StepNumberBranch);
3471  // Turn on the branches which we want for acc prob
3472  Chain->SetBranchStatus("accProb", true);
3473  Chain->SetBranchAddress("accProb", &AccProbValuesBranch);
3474 
3475  // Loop over the entries
3476  //KS: This is really a bottleneck right now, thus revisit with ROOT6 https://pep-root6.github.io/docs/analysis/parallell/root.html
3477  for (int i = 0; i < nEntries; ++i) {
3478  // Fill up the arrays
3479  Chain->GetEntry(i);
3480 
3481  if (i % countwidth == 0)
3483 
3484  // Set the branch addresses for params
3485  for (int j = 0; j < nDraw; ++j) {
3486  ParStep[j][i] = ParStepBranch[j];
3487  }
3488  // Set the branch addresses for samples
3489  for (size_t j = 0; j < SampleName_v.size(); ++j) {
3490  SampleValues[i][j] = SampleValuesBranch[j];
3491  }
3492  // Set the branch addresses for systematics
3493  for (size_t j = 0; j < SystName_v.size(); ++j) {
3494  SystValues[i][j] = SystValuesBranch[j];
3495  }
3496 
3497  // Set the branch addresses for Acceptance Probability
3498  AccProbValues[i] = AccProbValuesBranch;
3499  StepNumber[i] = StepNumberBranch;
3500 
3501  // Find which batch the event belongs in
3502  int BatchNumber = -1;
3503  // I'm so lazy! But it's OK, the major overhead here is GetEntry: saved by ROOT!
3504  for (int j = 0; j < nBatches; ++j) {
3505  if (i < (j+1)*BatchLength) {
3506  BatchNumber = j;
3507  break;
3508  }
3509  }
3510  // Fill up the sum for each j param
3511  for (int j = 0; j < nDraw; ++j) {
3512  BatchedAverages[BatchNumber][j] += ParStep[j][i];
3513  }
3514 
3515  //KS: Could easily add this to above loop but I accProb is different beast so better keep it like this
3516  AccProbBatchedAverages[BatchNumber] += AccProbValues[i];
3517  }
3518  clock.Stop();
3519  MACH3LOG_INFO("Took {:.2f}s to finish caching statistic for Diag MCMC with {} steps", clock.RealTime(), nEntries);
3520 
3521  if(AllUnique(StepNumber, nEntries) == false){
3522  MACH3LOG_ERROR("Found steps with duplicate StepNumber, this indicate merged chain has been passed to DiagMCMC");
3523  MACH3LOG_ERROR("Code hasn't been optimised to work with merged chains, results may be unintended");
3524  throw MaCh3Exception(__FILE__ , __LINE__ );
3525  }
3526  // Make the sums into average
3527  #ifdef MULTITHREAD
3528  #pragma omp parallel for
3529  #endif
3530  for (int i = 0; i < nDraw; ++i) {
3531  for (int j = 0; j < nBatches; ++j) {
3532  // Divide by the total number of events in the batch
3533  BatchedAverages[j][i] /= BatchLength;
3534  if(i == 0) AccProbBatchedAverages[j] /= BatchLength; //KS: we have only one accProb, keep it like this for now
3535  }
3536  }
3537 
3538  // And make our sweet output file
3539  if (OutputFile == nullptr) MakeOutputFile();
3540 }
bool AllUnique(unsigned int *StepNumber, size_t size)

◆ PrintInfo()

void MCMCProcessor::PrintInfo ( ) const
protected

Print info like how many params have been loaded etc.

Definition at line 4587 of file MCMCProcessor.cpp.

4587  {
4588 // **************************
4589  // KS: Create a map to store the counts of unique strings
4590  std::unordered_map<std::string, int> paramCounts;
4591  std::vector<std::string> orderedKeys;
4592 
4593  for (const std::string& param : ParameterGroup) {
4594  if (paramCounts[param] == 0) {
4595  orderedKeys.push_back(param); // preserve order of first appearance
4596  }
4597  paramCounts[param]++;
4598  }
4599 
4600  MACH3LOG_INFO("************************************************");
4601  MACH3LOG_INFO("Scanning output branches...");
4602  MACH3LOG_INFO("# Useful entries in tree: \033[1;32m {} \033[0m ", nDraw);
4603  MACH3LOG_INFO("# Model params: \033[1;32m {} starting at {} \033[0m ", nParam[kXSecPar], ParamTypeStartPos[kXSecPar]);
4604  MACH3LOG_INFO("# With following groups: ");
4605  for (const std::string& key : orderedKeys) {
4606  MACH3LOG_INFO(" # {} params: {}", key, paramCounts[key]);
4607  }
4608  MACH3LOG_INFO("# ND params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kNDPar], ParamTypeStartPos[kNDPar]);
4609  MACH3LOG_INFO("# FD params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kFDDetPar], ParamTypeStartPos[kFDDetPar]);
4610  MACH3LOG_INFO("************************************************");
4611 }

◆ ProduceChi2()

void MCMCProcessor::ProduceChi2 ( const std::string &  GroupName) const

Convert posterior likelihood to Delta Chi2 used for comparison with frequentists fitter.

Definition at line 1829 of file MCMCProcessor.cpp.

1829  {
1830 // *********************
1831  if(GroupName == "") return;
1832  MACH3LOG_INFO("Starting {}", __func__);
1833  TDirectory* Chi2Folder = OutputFile->mkdir("DeltaChi2");
1834 
1835  Chi2Folder->cd();
1836  for (int iPar = 0; iPar < nDraw; iPar++)
1837  {
1838  std::string GroupNameCurr;
1839  if(ParamType[iPar] == kXSecPar){
1840  const int InternalNumeration = iPar - ParamTypeStartPos[kXSecPar];
1841  GroupNameCurr = ParameterGroup[InternalNumeration];
1842  } else {
1843  GroupNameCurr = "Other"; // Use Other for all legacy params
1844  }
1845  if (ParamVaried[iPar] == false) continue;
1846  if (GroupName != "All" && GroupNameCurr != GroupName) continue;
1847 
1848  auto Chi2 = GetDeltaChi2(hpost[iPar]);
1849  RemoveFitter(Chi2.get(), "Gauss");
1850 
1851  Chi2->Write();
1852  }
1853  Chi2Folder->Close();
1854  delete Chi2Folder;
1855  OutputFile->cd();
1856 }
std::unique_ptr< TH1D > GetDeltaChi2(TH1D *posterior_probability_hist)
Convert a posterior probability histogram into a distribution. Using the likelihood-ratio definition...

◆ ReadFDFile()

void MCMCProcessor::ReadFDFile ( )
protected

Read the FD cov file and get the input central values and errors.

Warning
This will no longer be supported in future

Definition at line 2786 of file MCMCProcessor.cpp.

2786  {
2787 // ***************
2788  // Do the same for the FD
2789  TFile *FDdetFile = M3::Open(CovPos[kFDDetPar].back(), "open", __FILE__, __LINE__);
2790  FDdetFile->cd();
2791 
2792  TMatrixD *FDdetMatrix = FDdetFile->Get<TMatrixD>(CovNamePos[kFDDetPar].c_str());
2793 
2794  for (int i = 0; i < FDdetMatrix->GetNrows(); ++i)
2795  {
2796  //KS: FD parameters start at 1. in contrary to ND280
2797  ParamCentral[kFDDetPar].push_back(1.);
2798 
2799  ParamErrors[kFDDetPar].push_back( std::sqrt((*FDdetMatrix)(i,i)) );
2800  ParamNames[kFDDetPar].push_back( Form("FD Det %i", i) );
2801 
2802  //KS: Currently we can only set it via config, change it in future
2803  ParamFlat[kFDDetPar].push_back( false );
2804  }
2805  //KS: The last parameter is p scale
2806  //ETA: we need to be careful here, this is only true for SK in the T2K beam analysis...
2807  if(FancyPlotNames) ParamNames[kFDDetPar].back() = "Momentum Scale";
2808 
2809  FDdetFile->Close();
2810  delete FDdetFile;
2811  delete FDdetMatrix;
2812 }

◆ ReadInputCov()

void MCMCProcessor::ReadInputCov ( )
protected

CW: Read the input Covariance matrix entries. Get stuff like parameter input errors, names, and so on.

Definition at line 2527 of file MCMCProcessor.cpp.

2527  {
2528 // **************************
2529  FindInputFiles();
2530  if(CovPos[kXSecPar].back() != "none") ReadModelFile();
2531 }
void ReadModelFile()
Read the xsec file and get the input central values and errors.
void FindInputFiles()
Read the output MCMC file and find what inputs were used.

◆ ReadInputCovLegacy()

void MCMCProcessor::ReadInputCovLegacy ( )
protected
Warning
This will no longer be supported in future

Definition at line 2536 of file MCMCProcessor.cpp.

2536  {
2537 // **************************
2539  if(nParam[kNDPar] > 0) ReadNDFile();
2540  if(nParam[kFDDetPar] > 0) ReadFDFile();
2541 }
void ReadNDFile()
Read the ND cov file and get the input central values and errors.
void FindInputFilesLegacy()
void ReadFDFile()
Read the FD cov file and get the input central values and errors.

◆ ReadModelFile()

void MCMCProcessor::ReadModelFile ( )
protected

Read the xsec file and get the input central values and errors.

Definition at line 2689 of file MCMCProcessor.cpp.

2689  {
2690 // ***************
2691  YAML::Node XSecFile = CovConfig[kXSecPar];
2692 
2693  auto systematics = XSecFile["Systematics"];
2694  int paramIndex = 0;
2695  for (auto it = systematics.begin(); it != systematics.end(); ++it, ++paramIndex )
2696  {
2697  auto const &param = *it;
2698  // Push back the name
2699  std::string ParName = (param["Systematic"]["Names"]["FancyName"].as<std::string>());
2700  std::string Group = param["Systematic"]["ParameterGroup"].as<std::string>();
2701 
2702  bool rejected = false;
2703  for (unsigned int ik = 0; ik < ExcludedNames.size(); ++ik)
2704  {
2705  if (M3::CaseInsentiveMatch(ParName, ExcludedNames[ik]))
2706  {
2707  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2708  rejected = true;
2709  break;
2710  }
2711  }
2712  for (unsigned int ik = 0; ik < ExcludedGroups.size(); ++ik)
2713  {
2714  if (Group == ExcludedGroups[ik])
2715  {
2716  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2717  rejected = true;
2718  break;
2719  }
2720  }
2721  if(rejected) continue;
2722 
2723  ParamNames[kXSecPar].push_back(ParName);
2724  ParamCentral[kXSecPar].push_back(param["Systematic"]["ParameterValues"]["PreFitValue"].as<double>());
2725  ParamErrors[kXSecPar].push_back(param["Systematic"]["Error"].as<double>() );
2726  ParamFlat[kXSecPar].push_back(GetFromManager<bool>(param["Systematic"]["FlatPrior"], false, __FILE__ , __LINE__));
2727 
2728  ParameterGroup.push_back(Group);
2729 
2730  nParam[kXSecPar]++;
2731  ParamType.push_back(kXSecPar);
2732  // Params from osc group have branch name equal to fancy name while all others are basically xsec_0 for example
2733  if(ParameterGroup.back() == "Osc") {
2734  BranchNames.push_back(ParamNames[kXSecPar].back());
2735  } else {
2736  BranchNames.push_back("param_" + std::to_string(paramIndex));
2737  }
2738 
2739  // Check that the branch exists before setting address
2740  if (!Chain->GetBranch(BranchNames.back())) {
2741  MACH3LOG_WARN("Couldn't find branch '{}', if you are not planning to draw posteriors this might be fine", BranchNames.back());
2742  }
2743  }
2744 }
std::vector< std::string > ExcludedNames
std::vector< std::string > ExcludedGroups
bool CaseInsentiveMatch(std::string Text, std::string Pattern)
Matches a string against a simple wildcard Pattern using regex. Is not case sensitive.

◆ ReadNDFile()

void MCMCProcessor::ReadNDFile ( )
protected

Read the ND cov file and get the input central values and errors.

Warning
This will no longer be supported in future

Definition at line 2748 of file MCMCProcessor.cpp.

2748  {
2749 // ***************
2750  // Do the same for the ND280
2751  TFile *NDdetFile = M3::Open(CovPos[kNDPar].back(), "open", __FILE__, __LINE__);
2752  NDdetFile->cd();
2753 
2754  TMatrixDSym *NDdetMatrix = NDdetFile->Get<TMatrixDSym>(CovNamePos[kNDPar].c_str());
2755  TVectorD *NDdetNominal = NDdetFile->Get<TVectorD>("det_weights");
2756  TDirectory *BinningDirectory = NDdetFile->Get<TDirectory>("Binning");
2757 
2758  for (int i = 0; i < NDdetNominal->GetNrows(); ++i)
2759  {
2760  ParamCentral[kNDPar].push_back( (*NDdetNominal)(i) );
2761 
2762  ParamErrors[kNDPar].push_back( std::sqrt((*NDdetMatrix)(i,i)) );
2763  ParamNames[kNDPar].push_back( Form("ND Det %i", i) );
2764  //KS: Currently we can only set it via config, change it in future
2765  ParamFlat[kNDPar].push_back( false );
2766  }
2767 
2768  TIter next(BinningDirectory->GetListOfKeys());
2769  TKey *key = nullptr;
2770  // Loop through all entries
2771  while ((key = static_cast<TKey*>(next())))
2772  {
2773  std::string name = std::string(key->GetName());
2774  TH2Poly* RefPoly = BinningDirectory->Get<TH2Poly>((name).c_str());
2775  int size = RefPoly->GetNumberOfBins();
2776  NDSamplesBins.push_back(size);
2777  NDSamplesNames.push_back(RefPoly->GetTitle());
2778  }
2779 
2780  NDdetFile->Close();
2781  delete NDdetFile;
2782 }

◆ Reset2DPosteriors()

void MCMCProcessor::Reset2DPosteriors ( )

Reset 2D posteriors, in case we would like to calculate in again with different BurnInCut.

Definition at line 2881 of file MCMCProcessor.cpp.

2881  {
2882 // **************************************************
2883  #ifdef MULTITHREAD
2884  #pragma omp parallel for
2885  #endif
2886  for (int i = 0; i < nDraw; ++i)
2887  {
2888  for (int j = 0; j <= i; ++j)
2889  {
2890  // TH2D to hold the Correlation
2891  hpost2D[i][j]->Reset("");
2892  hpost2D[i][j]->Fill(0.0, 0.0, 0.0);
2893  }
2894  }
2895 }

◆ SavageDickeyPlot()

void MCMCProcessor::SavageDickeyPlot ( std::unique_ptr< TH1D > &  PriorHist,
std::unique_ptr< TH1D > &  PosteriorHist,
const std::string &  Title,
const double  EvaluationPoint 
) const

Produce Savage Dickey plot.

Parameters
PriorHistHistogram with prior distribution
PosteriorHistHistogram with posterior distribution
TitleTitle for the plot
EvaluationPointPoint at which the Savage-Dickey ratio is evaluated

Definition at line 3101 of file MCMCProcessor.cpp.

3104  {
3105 // **************************
3106  // Area normalise the distributions
3107  PriorHist->Scale(1./PriorHist->Integral(), "width");
3108  PosteriorHist->Scale(1./PosteriorHist->Integral(), "width");
3109 
3110  PriorHist->SetLineColor(kRed);
3111  PriorHist->SetMarkerColor(kRed);
3112  PriorHist->SetFillColorAlpha(kRed, 0.35);
3113  PriorHist->SetFillStyle(1001);
3114  PriorHist->GetXaxis()->SetTitle(Title.c_str());
3115  PriorHist->GetYaxis()->SetTitle("Posterior Probability");
3116  PriorHist->SetMaximum(PosteriorHist->GetMaximum()*1.5);
3117  PriorHist->GetYaxis()->SetLabelOffset(999);
3118  PriorHist->GetYaxis()->SetLabelSize(0);
3119  PriorHist->SetLineWidth(2);
3120  PriorHist->SetLineStyle(kSolid);
3121 
3122  PosteriorHist->SetLineColor(kBlue);
3123  PosteriorHist->SetMarkerColor(kBlue);
3124  PosteriorHist->SetFillColorAlpha(kBlue, 0.35);
3125  PosteriorHist->SetFillStyle(1001);
3126 
3127  PriorHist->Draw("hist");
3128  PosteriorHist->Draw("hist same");
3129 
3130  double ProbPrior = PriorHist->GetBinContent(PriorHist->FindBin(EvaluationPoint));
3131  //KS: In case we go so far away that prior is 0, set this to small value to avoid dividing by 0
3132  if(ProbPrior < 0) ProbPrior = 0.00001;
3133  double ProbPosterior = PosteriorHist->GetBinContent(PosteriorHist->FindBin(EvaluationPoint));
3134  double SavageDickey = ProbPosterior/ProbPrior;
3135 
3136  std::string DunneKabothScale = GetDunneKaboth(SavageDickey);
3137  //Get Best point
3138  auto PostPoint = std::make_unique<TGraph>(1);
3139  PostPoint->SetPoint(0, EvaluationPoint, ProbPosterior);
3140  PostPoint->SetMarkerStyle(20);
3141  PostPoint->SetMarkerSize(1);
3142  PostPoint->Draw("P same");
3143 
3144  auto PriorPoint = std::make_unique<TGraph>(1);
3145  PriorPoint->SetPoint(0, EvaluationPoint, ProbPrior);
3146  PriorPoint->SetMarkerStyle(20);
3147  PriorPoint->SetMarkerSize(1);
3148  PriorPoint->Draw("P same");
3149 
3150  auto legend = std::make_unique<TLegend>(0.12, 0.6, 0.6, 0.97);
3151  SetLegendStyle(legend.get(), 0.04);
3152  legend->AddEntry(PriorHist.get(), "Prior", "l");
3153  legend->AddEntry(PosteriorHist.get(), "Posterior", "l");
3154  legend->AddEntry(PostPoint.get(), Form("SavageDickey = %.2f, (%s)", SavageDickey, DunneKabothScale.c_str()),"");
3155  legend->Draw("same");
3156 
3157  Posterior->Print(CanvasName);
3158  Posterior->Write(Title.c_str());
3159 }

◆ ScanInput()

void MCMCProcessor::ScanInput ( )
protected

Scan Input etc.

Definition at line 2287 of file MCMCProcessor.cpp.

2287  {
2288 // **************************
2289  // KS: This can reduce time necessary for caching even by half
2290  #ifdef MULTITHREAD
2291  //ROOT::EnableImplicitMT();
2292  #endif
2293 
2294  // Open the Chain
2295  Chain = new TChain("posteriors","posteriors");
2296  Chain->Add(MCMCFile.c_str());
2297 
2298  nEntries = int(Chain->GetEntries());
2299 
2300  //Only is suboptimality we might want to change it, therefore set it high enough so it doesn't affect other functionality
2301  UpperCut = nEntries+1;
2302 
2303  // Get the list of branches
2304  TObjArray* brlis = Chain->GetListOfBranches();
2305 
2306  // Get the number of branches
2307  nBranches = brlis->GetEntries();
2308 
2309  BranchNames.reserve(nBranches);
2310  ParamType.reserve(nBranches);
2311 
2312  // Read the input Covariances
2313  ReadInputCov();
2314 
2315  // Set all the branches to off
2316  Chain->SetBranchStatus("*", false);
2317 
2318  // Loop over the number of branches
2319  // Find the name and how many of each systematic we have
2320  for (int i = 0; i < nBranches; i++)
2321  {
2322  // Get the TBranch and its name
2323  TBranch* br = static_cast<TBranch*>(brlis->At(i));
2324  if(!br){
2325  MACH3LOG_ERROR("Invalid branch at position {}", i);
2326  throw MaCh3Exception(__FILE__,__LINE__);
2327  }
2328  TString bname = br->GetName();
2329 
2330  //KS: Exclude parameter types
2331  bool rejected = false;
2332  for(unsigned int ik = 0; ik < ExcludedTypes.size(); ++ik )
2333  {
2334  if(bname.BeginsWith(ExcludedTypes[ik]))
2335  {
2336  rejected = true;
2337  break;
2338  }
2339  }
2340  if(rejected) continue;
2341 
2342  // Turn on the branches which we want for parameters
2343  Chain->SetBranchStatus(bname.Data(), true);
2344 
2345  if (bname.BeginsWith("ndd_"))
2346  {
2347  BranchNames.push_back(bname);
2348  ParamType.push_back(kNDPar);
2349  nParam[kNDPar]++;
2350  }
2351  else if (bname.BeginsWith("skd_joint_"))
2352  {
2353  BranchNames.push_back(bname);
2354  ParamType.push_back(kFDDetPar);
2355  nParam[kFDDetPar]++;
2356  }
2357 
2358  //KS: as a bonus get LogL systematic
2359  if (bname.BeginsWith("LogL_sample_")) {
2360  SampleName_v.push_back(bname);
2361  }
2362  else if (bname.BeginsWith("LogL_systematic_")) {
2363  SystName_v.push_back(bname);
2364  }
2365  }
2366  nDraw = int(BranchNames.size());
2367 
2368  // Read the input Covariances
2370 
2371  // Check order of parameter types
2373 
2374  ParamVaried.resize(nDraw, true);
2375 
2376  // Print useful Info
2377  PrintInfo();
2378 
2379  nSteps = Chain->GetMaximum("step");
2380  // Set the step cut to be 20%
2381  int cut = nSteps/5;
2382  SetStepCut(cut);
2383 
2384  // Basically allow loading oscillation parameters
2386 }
void ScanParameterOrder()
Scan order of params from a different groups.
void PrintInfo() const
Print info like how many params have been loaded etc.
virtual void LoadAdditionalInfo()
allow loading additional info for example used for oscillation parameters
std::vector< std::string > ExcludedTypes
void ReadInputCovLegacy()
void SetStepCut(const std::string &Cuts)
Set the step cutting by string.
int nBranches
Number of branches in a TTree.
void ReadInputCov()
CW: Read the input Covariance matrix entries. Get stuff like parameter input errors,...

◆ ScanParameterOrder()

void MCMCProcessor::ScanParameterOrder ( )
protected

Scan order of params from a different groups.

Definition at line 2447 of file MCMCProcessor.cpp.

2447  {
2448 // *****************************
2449  for(int i = 0; i < kNParameterEnum; i++)
2450  {
2451  for(unsigned int j = 0; j < ParamType.size(); j++)
2452  {
2453  if(ParamType[j] == ParameterEnum(i))
2454  {
2455  //KS: When we find that i-th parameter types start at j, save and move to the next parameter.
2456  ParamTypeStartPos[i] = j;
2457  break;
2458  }
2459  }
2460  }
2461 }

◆ SetEntries()

void MCMCProcessor::SetEntries ( const int  NewEntries)
inline

Set number of entries to make potentially MCMC Processing faster.

Warning
This option only sets an upper limit; burn-in events will NOT be discarded

Definition at line 269 of file MCMCProcessor.h.

269  {
270  if (NewEntries > nEntries) {
271  MACH3LOG_ERROR("Cannot increase entries from {} to {}. Only decreasing is allowed.", nEntries, NewEntries);
272  throw MaCh3Exception(__FILE__, __LINE__);
273  }
274  if (NewEntries <= 0) {
275  MACH3LOG_ERROR("Entries cannot be below 0, but {} was passed.", NewEntries);
276  throw MaCh3Exception(__FILE__, __LINE__);
277  }
278 
279  if (static_cast<int>(BurnInCut) > NewEntries) {
280  MACH3LOG_ERROR("BurnInCut ({}) is larger than NewEntries ({})", BurnInCut, NewEntries);
281  throw MaCh3Exception(__FILE__, __LINE__);
282  }
283 
284  MACH3LOG_INFO("Setting entries to {} from {}.", NewEntries, nEntries);
285  MACH3LOG_WARN("This may behave not as expected when using merged multiple chains");
286  nEntries = NewEntries;
287  }

◆ SetExcludedGroups()

void MCMCProcessor::SetExcludedGroups ( std::vector< std::string >  Name)
inline

Definition at line 319 of file MCMCProcessor.h.

319 {ExcludedGroups = Name; };

◆ SetExcludedNames()

void MCMCProcessor::SetExcludedNames ( std::vector< std::string >  Name)
inline

Definition at line 318 of file MCMCProcessor.h.

318 {ExcludedNames = Name; };

◆ SetExcludedTypes()

void MCMCProcessor::SetExcludedTypes ( std::vector< std::string >  Name)
inline

Setter related what parameters we want to exclude from analysis, for example if cross-section parameters look like param_, then passing "param_" will.

Definition at line 317 of file MCMCProcessor.h.

317 {ExcludedTypes = Name; };

◆ SetFancyNames()

void MCMCProcessor::SetFancyNames ( const bool  PlotOrNot)
inline

Definition at line 307 of file MCMCProcessor.h.

307 {FancyPlotNames = PlotOrNot; };

◆ SetLegendStyle()

void MCMCProcessor::SetLegendStyle ( TLegend *  Legend,
const double  size 
) const
protected

Configures the style of a TLegend object.

Parameters
LegendPointer to the TLegend object to modify
sizeThe text size to set for the legend

Definition at line 4646 of file MCMCProcessor.cpp.

4646  {
4647 // **************************
4648  Legend->SetTextSize(size);
4649  Legend->SetLineColor(0);
4650  Legend->SetLineStyle(0);
4651  Legend->SetFillColor(0);
4652  Legend->SetFillStyle(0);
4653  Legend->SetBorderSize(0);
4654 }

◆ SetMargins()

void MCMCProcessor::SetMargins ( std::unique_ptr< TCanvas > &  Canv,
const std::vector< double > &  margins 
)
protected

Set TCanvas margins to specified values.

Definition at line 4621 of file MCMCProcessor.cpp.

4621  {
4622 // **************************
4623  if (!Canv) {
4624  MACH3LOG_ERROR("Canv is nullptr");
4625  throw MaCh3Exception(__FILE__, __LINE__);
4626  }
4627  if (margins.size() != 4) {
4628  MACH3LOG_ERROR("Margin vector must have exactly 4 elements");
4629  throw MaCh3Exception(__FILE__, __LINE__);
4630  }
4631  Canv->SetTopMargin(margins[0]);
4632  Canv->SetBottomMargin(margins[1]);
4633  Canv->SetLeftMargin(margins[2]);
4634  Canv->SetRightMargin(margins[3]);
4635 }

◆ SetnBatches()

void MCMCProcessor::SetnBatches ( const int  Batches)
inline

Set value of Nbatches used for batched mean, this need to be done earlier as batches are made when reading tree.

Parameters
BatchesNumber of batches, default is 20

Definition at line 323 of file MCMCProcessor.h.

323 {nBatches = Batches; };

◆ SetNBins()

void MCMCProcessor::SetNBins ( const int  NewBins)
inline

Modify number of bins used for 1D and 2D Histograms.

Definition at line 265 of file MCMCProcessor.h.

265 {nBins = NewBins;};

◆ SetnLags()

void MCMCProcessor::SetnLags ( const int  nLags)
inline

Definition at line 324 of file MCMCProcessor.h.

324 {AutoCorrLag = nLags; };

◆ SetOutputSuffix()

void MCMCProcessor::SetOutputSuffix ( const std::string  Suffix)
inline

Sett output suffix, this way jobs using the same file will have different names.

Definition at line 327 of file MCMCProcessor.h.

327 {OutputSuffix = Suffix; };

◆ SetPlotBinValue()

void MCMCProcessor::SetPlotBinValue ( const bool  PlotOrNot)
inline

Definition at line 306 of file MCMCProcessor.h.

306 {plotBinValue = PlotOrNot; };

◆ SetPlotErrorForFlatPrior()

void MCMCProcessor::SetPlotErrorForFlatPrior ( const bool  PlotOrNot)
inline

Set whether you want to plot error for parameters which have flat prior.

Definition at line 305 of file MCMCProcessor.h.

305 {PlotFlatPrior = PlotOrNot; };

◆ SetPlotRelativeToPrior()

void MCMCProcessor::SetPlotRelativeToPrior ( const bool  PlotOrNot)
inline

You can set relative to prior or relative to generated. It is advised to use relate to prior.

Parameters
PlotOrNotbool controlling plotRelativeToPrior argument

Definition at line 301 of file MCMCProcessor.h.

301 {plotRelativeToPrior = PlotOrNot; };

◆ SetPost2DPlotThreshold()

void MCMCProcessor::SetPost2DPlotThreshold ( const double  Threshold)
inline

Code will only plot 2D posteriors if Correlation are larger than defined threshold.

Parameters
ThresholdThis threshold is compared with correlation value

Definition at line 312 of file MCMCProcessor.h.

312 {Post2DPlotThreshold = Threshold; };

◆ SetPosterior1DCut()

void MCMCProcessor::SetPosterior1DCut ( const std::string  Cut)
inline

Allow to set addtional cuts based on ROOT TBrowser cut, for to only affect one mass ordering.

Definition at line 329 of file MCMCProcessor.h.

329 {Posterior1DCut = Cut; };

◆ SetPrintToPDF()

void MCMCProcessor::SetPrintToPDF ( const bool  PlotOrNot)
inline

Whether to dump all plots into PDF.

Definition at line 303 of file MCMCProcessor.h.

303 {printToPDF = PlotOrNot; };

◆ SetReweightNames()

void MCMCProcessor::SetReweightNames ( std::vector< std::string >  NewName)
inline

Set reweight branch names.

Definition at line 289 of file MCMCProcessor.h.

289 { ReweightNames = NewName; }

◆ SetSmoothing()

void MCMCProcessor::SetSmoothing ( const bool  PlotOrNot)
inline

Set whether want to use smoothing for histograms using ROOT algorithm.

Definition at line 309 of file MCMCProcessor.h.

309 {ApplySmoothing = PlotOrNot; };

◆ SetStepCut() [1/2]

void MCMCProcessor::SetStepCut ( const int  Cuts)

Set the step cutting by int.

Parameters
Cutsinteger telling cut value

Definition at line 2826 of file MCMCProcessor.cpp.

2826  {
2827 // ***************
2828  std::stringstream TempStream;
2829  TempStream << "step > " << Cuts;
2830  StepCut = TempStream.str();
2831  BurnInCut = Cuts;
2832  CheckStepCut();
2833 }
void CheckStepCut() const
Check if step cut isn't larger than highest values of step in a chain.

◆ SetStepCut() [2/2]

void MCMCProcessor::SetStepCut ( const std::string &  Cuts)

Set the step cutting by string.

Parameters
Cutsstring telling cut value

Definition at line 2816 of file MCMCProcessor.cpp.

2816  {
2817 // ***************
2818  StepCut = Cuts;
2819  BurnInCut = std::stoi( Cuts );
2820 
2821  CheckStepCut();
2822 }

◆ SetTLineStyle()

void MCMCProcessor::SetTLineStyle ( TLine *  Line,
const Color_t  Colour,
const Width_t  Width,
const ELineStyle  Style 
) const
protected

Configures a TLine object with the specified style parameters.

Parameters
LinePointer to the TLine object to modify. Must not be nullptr.
ColourThe color to set for the line.
WidthThe width of the line.
StyleThe line style (e.g., solid, dashed, etc.).

Definition at line 4638 of file MCMCProcessor.cpp.

4638  {
4639 // **************************
4640  Line->SetLineColor(Colour);
4641  Line->SetLineWidth(Width);
4642  Line->SetLineStyle(Style);
4643 }
constexpr ELineStyle Style[NVars]

◆ SetupOutput()

void MCMCProcessor::SetupOutput ( )
protected

Prepare all objects used for output.

Definition at line 2390 of file MCMCProcessor.cpp.

2390  {
2391 // ****************************
2392  // Make sure we can read files located anywhere and strip the .root ending
2393  MCMCFile = MCMCFile.substr(0, MCMCFile.find(".root"));
2394 
2395  // Check if the output file is ready
2396  if (OutputFile == nullptr) MakeOutputFile();
2397 
2398  CanvasName = MCMCFile + OutputSuffix + ".pdf[";
2399  if(printToPDF) Posterior->Print(CanvasName);
2400 
2401  // Once the pdf file is open no longer need to bracket
2402  CanvasName.ReplaceAll("[","");
2403 
2404  // We fit with this Gaussian
2405  Gauss = std::make_unique<TF1>("Gauss", "[0]/sqrt(2.0*3.14159)/[2]*TMath::Exp(-0.5*pow(x-[1],2)/[2]/[2])", -5, 5);
2406  Gauss->SetLineWidth(2);
2407  Gauss->SetLineColor(kOrange-5);
2408 
2409  // Declare the TVectors
2410  Covariance = new TMatrixDSym(nDraw);
2411  Correlation = new TMatrixDSym(nDraw);
2412  Central_Value = new TVectorD(nDraw);
2413  Means = new TVectorD(nDraw);
2414  Errors = new TVectorD(nDraw);
2415  Means_Gauss = new TVectorD(nDraw);
2416  Errors_Gauss = new TVectorD(nDraw);
2417  Means_HPD = new TVectorD(nDraw);
2418  Errors_HPD = new TVectorD(nDraw);
2419  Errors_HPD_Positive = new TVectorD(nDraw);
2420  Errors_HPD_Negative = new TVectorD(nDraw);
2421 
2422  // Initialise to something silly
2423  #ifdef MULTITHREAD
2424  #pragma omp parallel for
2425  #endif
2426  for (int i = 0; i < nDraw; ++i)
2427  {
2428  (*Central_Value)(i) = M3::_BAD_DOUBLE_;
2429  (*Means)(i) = M3::_BAD_DOUBLE_;
2430  (*Errors)(i) = M3::_BAD_DOUBLE_;
2431  (*Means_Gauss)(i) = M3::_BAD_DOUBLE_;
2432  (*Errors_Gauss)(i) = M3::_BAD_DOUBLE_;
2433  (*Means_HPD)(i) = M3::_BAD_DOUBLE_;
2434  (*Errors_HPD)(i) = M3::_BAD_DOUBLE_;
2435  (*Errors_HPD_Positive)(i) = M3::_BAD_DOUBLE_;
2436  (*Errors_HPD_Negative)(i) = M3::_BAD_DOUBLE_;
2437  for (int j = 0; j < nDraw; ++j) {
2438  (*Covariance)(i, j) = M3::_BAD_DOUBLE_;
2439  (*Correlation)(i, j) = M3::_BAD_DOUBLE_;
2440  }
2441  }
2442  hpost.resize(nDraw);
2443 }

◆ SetUseFFTAutoCorrelation()

void MCMCProcessor::SetUseFFTAutoCorrelation ( const bool  useFFT)
inline

Toggle using the FFT-based autocorrelation calculator.

Definition at line 314 of file MCMCProcessor.h.

314 {useFFTAutoCorrelation = useFFT; };

◆ SmearChain()

void MCMCProcessor::SmearChain ( const std::vector< std::string > &  Names,
const std::vector< double > &  Error,
const bool &  SaveBranch 
) const

Smear chain contours.

Parameters
NamesParameter names for which we do smearing
ErrorError based on which we smear
SaveBranchWhether we save unsmeared branch or not
Note
based on smear_parameter.C
Author
Dan Barrow

Definition at line 3163 of file MCMCProcessor.cpp.

3165  {
3166 // **************************
3167  MACH3LOG_INFO("Starting {}", __func__);
3168 
3169  if( (Names.size() != Error.size()))
3170  {
3171  MACH3LOG_ERROR("Size of passed vectors doesn't match in {}", __func__);
3172  throw MaCh3Exception(__FILE__ , __LINE__ );
3173  }
3174  std::vector<int> Param;
3175 
3176  //KS: First we need to find parameter number based on name
3177  for(unsigned int k = 0; k < Names.size(); ++k)
3178  {
3179  //KS: First we need to find parameter number based on name
3180  int ParamNo = GetParamIndexFromName(Names[k]);
3181  if(ParamNo == M3::_BAD_INT_)
3182  {
3183  MACH3LOG_WARN("Couldn't find param {}. Can't Smear", Names[k]);
3184  return;
3185  }
3186 
3187  TString Title = "";
3188  double Prior = 1.0, PriorError = 1.0;
3189  GetNthParameter(ParamNo, Prior, PriorError, Title);
3190 
3191  Param.push_back(ParamNo);
3192  }
3193  std::string InputFile = MCMCFile+".root";
3194  std::string OutputFilename = MCMCFile + "_smeared.root";
3195 
3196  //KS: Simply create copy of file and add there new branch
3197  int ret = system(("cp " + InputFile + " " + OutputFilename).c_str());
3198  if (ret != 0)
3199  MACH3LOG_WARN("Error: system call to copy file failed with code {}", ret);
3200 
3201  TFile *OutputChain = M3::Open(OutputFilename, "UPDATE", __FILE__, __LINE__);
3202  OutputChain->cd();
3203  TTree *post = OutputChain->Get<TTree>("posteriors");
3204  TTree *treeNew = post->CloneTree(0);
3205 
3206  std::vector<double> NewParameter(Names.size());
3207  for(size_t i = 0; i < Param.size(); i++) {
3208  post->SetBranchAddress(BranchNames[Param[i]], &NewParameter[i]);
3209  }
3210 
3211  std::vector<double> Unsmeared_Parameter;
3212  if(SaveBranch){
3213  Unsmeared_Parameter.resize(Param.size());
3214  for(size_t i = 0; i < Param.size(); i++) {
3215  treeNew->Branch((BranchNames[Param[i]] + "_unsmeared"), &Unsmeared_Parameter[i]);
3216  }
3217  }
3218 
3219  auto rand = std::make_unique<TRandom3>(0);
3220  Long64_t AllEntries = post->GetEntries();
3221  for (Long64_t i = 0; i < AllEntries; ++i) {
3222  // Entry from the old chain
3223  post->GetEntry(i);
3224 
3225  if(SaveBranch){
3226  for(size_t iPar = 0; iPar < Param.size(); iPar++) {
3227  Unsmeared_Parameter[iPar] = NewParameter[iPar];
3228  }
3229  }
3230  // Smear it
3231  for(size_t iPar = 0; iPar < Param.size(); iPar++) {
3232  NewParameter[iPar] = NewParameter[iPar] + rand->Gaus(0, Error[iPar]);
3233  }
3234  // Fill to the new chain
3235  treeNew->Fill();
3236  }
3237 
3238  OutputChain->cd();
3239  treeNew->Write("posteriors", TObject::kOverwrite);
3240 
3241  // KS: Save smearing metadata
3242  YAML::Node yaml_node;
3243  yaml_node["Smearing"].SetStyle(YAML::EmitterStyle::Block);
3244 
3245  for (size_t k = 0; k < Names.size(); ++k) {
3246  YAML::Node entry;
3247  entry.SetStyle(YAML::EmitterStyle::Flow);
3248 
3249  entry.push_back(Error[k]);
3250  entry.push_back("Gauss");
3251 
3252  yaml_node["Smearing"][Names[k]] = entry;
3253  }
3254  TMacro ConfigSave = YAMLtoTMacro(yaml_node, "Smearing_Config");
3255  ConfigSave.Write();
3256 
3257  OutputChain->Close();
3258  delete OutputChain;
3259 }
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Definition: YamlHelper.h:167

◆ ThinMCMC()

void MCMCProcessor::ThinMCMC ( const int  ThinningCut) const
inline

Thin MCMC Chain, to save space and maintain low autocorrelations.

Parameters
ThinningCutevery which entry you want to thin

Definition at line 203 of file MCMCProcessor.h.

203 { ThinningMCMC(MCMCFile+".root", ThinningCut); };
void ThinningMCMC(const std::string &FilePath, const int ThinningCut)
Thin MCMC Chain, to save space and maintain low autocorrelations.

Member Data Documentation

◆ AccProbBatchedAverages

double* MCMCProcessor::AccProbBatchedAverages
protected

Holds all accProb in batches.

Definition at line 598 of file MCMCProcessor.h.

◆ AccProbValues

double* MCMCProcessor::AccProbValues
protected

Holds all accProb.

Definition at line 596 of file MCMCProcessor.h.

◆ ApplySmoothing

bool MCMCProcessor::ApplySmoothing
protected

Apply smoothing for 2D histos using root algorithm.

Definition at line 514 of file MCMCProcessor.h.

◆ AutoCorrLag

int MCMCProcessor::AutoCorrLag
protected

LagL used in AutoCorrelation.

Definition at line 585 of file MCMCProcessor.h.

◆ BatchedAverages

double** MCMCProcessor::BatchedAverages
protected

Values of batched average for every param and batch.

Definition at line 588 of file MCMCProcessor.h.

◆ BranchNames

std::vector<TString> MCMCProcessor::BranchNames
protected

Definition at line 464 of file MCMCProcessor.h.

◆ BurnInCut

unsigned int MCMCProcessor::BurnInCut
protected

Value of burn in cut.

Definition at line 449 of file MCMCProcessor.h.

◆ CacheMCMC

bool MCMCProcessor::CacheMCMC
protected

MCMC Chain has been cached.

Definition at line 577 of file MCMCProcessor.h.

◆ CanvasName

TString MCMCProcessor::CanvasName
protected

Name of canvas which help to save to the sample pdf.

Definition at line 497 of file MCMCProcessor.h.

◆ Central_Value

TVectorD* MCMCProcessor::Central_Value
protected

Vector with central value for each parameter.

Definition at line 534 of file MCMCProcessor.h.

◆ Chain

TChain* MCMCProcessor::Chain
protected

Main chain storing all steps etc.

Definition at line 441 of file MCMCProcessor.h.

◆ Correlation

TMatrixDSym* MCMCProcessor::Correlation
protected

Posterior Correlation Matrix.

Definition at line 555 of file MCMCProcessor.h.

◆ Covariance

TMatrixDSym* MCMCProcessor::Covariance
protected

Posterior Covariance Matrix.

Definition at line 553 of file MCMCProcessor.h.

◆ CovConfig

std::vector<YAML::Node> MCMCProcessor::CovConfig
protected

Covariance matrix config.

Definition at line 438 of file MCMCProcessor.h.

◆ CovNamePos

std::vector<std::string> MCMCProcessor::CovNamePos
protected

Covariance matrix name position.

Definition at line 436 of file MCMCProcessor.h.

◆ CovPos

std::vector<std::vector<std::string> > MCMCProcessor::CovPos
protected

Covariance matrix file name position.

Definition at line 434 of file MCMCProcessor.h.

◆ doDiagMCMC

bool MCMCProcessor::doDiagMCMC
protected

Doing MCMC Diagnostic.

Definition at line 579 of file MCMCProcessor.h.

◆ DrawRange

double MCMCProcessor::DrawRange
protected

Drawrange for SetMaximum.

Definition at line 574 of file MCMCProcessor.h.

◆ Errors

TVectorD* MCMCProcessor::Errors
protected

Vector with errors values using RMS.

Definition at line 538 of file MCMCProcessor.h.

◆ Errors_Gauss

TVectorD* MCMCProcessor::Errors_Gauss
protected

Vector with error values using Gaussian fit.

Definition at line 542 of file MCMCProcessor.h.

◆ Errors_HPD

TVectorD* MCMCProcessor::Errors_HPD
protected

Vector with error values using Highest Posterior Density.

Definition at line 546 of file MCMCProcessor.h.

◆ Errors_HPD_Negative

TVectorD* MCMCProcessor::Errors_HPD_Negative
protected

Vector with negative error (left hand side) values using Highest Posterior Density.

Definition at line 550 of file MCMCProcessor.h.

◆ Errors_HPD_Positive

TVectorD* MCMCProcessor::Errors_HPD_Positive
protected

Vector with positive error (right hand side) values using Highest Posterior Density.

Definition at line 548 of file MCMCProcessor.h.

◆ ExcludedGroups

std::vector<std::string> MCMCProcessor::ExcludedGroups
protected

Definition at line 467 of file MCMCProcessor.h.

◆ ExcludedNames

std::vector<std::string> MCMCProcessor::ExcludedNames
protected

Definition at line 466 of file MCMCProcessor.h.

◆ ExcludedTypes

std::vector<std::string> MCMCProcessor::ExcludedTypes
protected

Definition at line 465 of file MCMCProcessor.h.

◆ FancyPlotNames

bool MCMCProcessor::FancyPlotNames
protected

Whether we want fancy plot names or not.

Definition at line 510 of file MCMCProcessor.h.

◆ Gauss

std::unique_ptr<TF1> MCMCProcessor::Gauss
protected

Gaussian fitter.

Definition at line 524 of file MCMCProcessor.h.

◆ hpost

std::vector<TH1D*> MCMCProcessor::hpost
protected

Holds 1D Posterior Distributions.

Definition at line 558 of file MCMCProcessor.h.

◆ hpost2D

std::vector<std::vector<TH2D*> > MCMCProcessor::hpost2D
protected

Holds 2D Posterior Distributions.

Definition at line 560 of file MCMCProcessor.h.

◆ hviolin

std::unique_ptr<TH2D> MCMCProcessor::hviolin
protected

Holds violin plot for all dials.

Definition at line 562 of file MCMCProcessor.h.

◆ hviolin_prior

std::unique_ptr<TH2D> MCMCProcessor::hviolin_prior
protected

Holds prior violin plot for all dials,.

Definition at line 564 of file MCMCProcessor.h.

◆ MadePostfit

bool MCMCProcessor::MadePostfit
protected

Sanity check if Postfit is already done to not make several times.

Definition at line 506 of file MCMCProcessor.h.

◆ MCMCFile

std::string MCMCProcessor::MCMCFile
protected

Name of MCMC file.

Definition at line 430 of file MCMCProcessor.h.

◆ Means

TVectorD* MCMCProcessor::Means
protected

Vector with mean values using Arithmetic Mean.

Definition at line 536 of file MCMCProcessor.h.

◆ Means_Gauss

TVectorD* MCMCProcessor::Means_Gauss
protected

Vector with mean values using Gaussian fit.

Definition at line 540 of file MCMCProcessor.h.

◆ Means_HPD

TVectorD* MCMCProcessor::Means_HPD
protected

Vector with mean values using Highest Posterior Density.

Definition at line 544 of file MCMCProcessor.h.

◆ nBatches

int MCMCProcessor::nBatches
protected

Number of batches for Batched Mean.

Definition at line 583 of file MCMCProcessor.h.

◆ nBins

int MCMCProcessor::nBins
protected

Number of bins.

Definition at line 572 of file MCMCProcessor.h.

◆ nBranches

int MCMCProcessor::nBranches
protected

Number of branches in a TTree.

Definition at line 451 of file MCMCProcessor.h.

◆ nDraw

int MCMCProcessor::nDraw
protected

Number of all parameters used in the analysis.

Definition at line 461 of file MCMCProcessor.h.

◆ NDSamplesBins

std::vector<int> MCMCProcessor::NDSamplesBins
protected

Definition at line 520 of file MCMCProcessor.h.

◆ NDSamplesNames

std::vector<std::string> MCMCProcessor::NDSamplesNames
protected

Definition at line 521 of file MCMCProcessor.h.

◆ nEntries

int MCMCProcessor::nEntries
protected

KS: For merged chains number of entries will be different from nSteps.

Definition at line 453 of file MCMCProcessor.h.

◆ nParam

std::vector<int> MCMCProcessor::nParam
protected

Number of parameters per type.

Definition at line 480 of file MCMCProcessor.h.

◆ nParameterHandlers

int MCMCProcessor::nParameterHandlers
protected

Number of covariance objects.

Definition at line 459 of file MCMCProcessor.h.

◆ nSampleHandlers

int MCMCProcessor::nSampleHandlers
protected

Number of sample PDF objects.

Definition at line 457 of file MCMCProcessor.h.

◆ nSteps

int MCMCProcessor::nSteps
protected

KS: For merged chains number of entries will be different from nSteps.

Definition at line 455 of file MCMCProcessor.h.

◆ OutputFile

TFile* MCMCProcessor::OutputFile
protected

The output file.

Definition at line 527 of file MCMCProcessor.h.

◆ OutputName

std::string MCMCProcessor::OutputName
protected

Name of output files.

Definition at line 495 of file MCMCProcessor.h.

◆ OutputSuffix

std::string MCMCProcessor::OutputSuffix
protected

Output file suffix useful when running over same file with different settings.

Definition at line 432 of file MCMCProcessor.h.

◆ ParamCentral

std::vector<std::vector<double> > MCMCProcessor::ParamCentral
protected

Parameters central values which we are going to analyse.

Definition at line 474 of file MCMCProcessor.h.

◆ ParamErrors

std::vector<std::vector<double> > MCMCProcessor::ParamErrors
protected

Uncertainty on a single parameter.

Definition at line 476 of file MCMCProcessor.h.

◆ ParameterGroup

std::vector<std::string> MCMCProcessor::ParameterGroup
protected

Definition at line 487 of file MCMCProcessor.h.

◆ ParamFlat

std::vector<std::vector<bool> > MCMCProcessor::ParamFlat
protected

Whether Param has flat prior or not.

Definition at line 478 of file MCMCProcessor.h.

◆ ParamNames

std::vector<std::vector<TString> > MCMCProcessor::ParamNames
protected

Name of parameters which we are going to analyse.

Definition at line 472 of file MCMCProcessor.h.

◆ ParamType

std::vector<ParameterEnum> MCMCProcessor::ParamType
protected

Make an enum for which class this parameter belongs to so we don't have to keep string comparing.

Definition at line 482 of file MCMCProcessor.h.

◆ ParamTypeStartPos

std::vector<int> MCMCProcessor::ParamTypeStartPos
protected

KS: in MCMC output there is order of parameters so for example first goes xsec then nd det etc. Idea is that this parameter will keep track of it so code is flexible

Definition at line 485 of file MCMCProcessor.h.

◆ ParamVaried

std::vector<bool> MCMCProcessor::ParamVaried
protected

Is the ith parameter varied.

Definition at line 470 of file MCMCProcessor.h.

◆ ParStep

M3::float_t** MCMCProcessor::ParStep
protected

Array holding values for all parameters.

Definition at line 567 of file MCMCProcessor.h.

◆ plotBinValue

bool MCMCProcessor::plotBinValue
protected

If true it will print value on each bin of covariance matrix.

Definition at line 512 of file MCMCProcessor.h.

◆ PlotFlatPrior

bool MCMCProcessor::PlotFlatPrior
protected

Whether we plot flat prior or not, we usually provide error even for flat prior params.

Definition at line 500 of file MCMCProcessor.h.

◆ plotRelativeToPrior

bool MCMCProcessor::plotRelativeToPrior
protected

Whether we plot relative to prior or nominal, in most cases is prior.

Definition at line 504 of file MCMCProcessor.h.

◆ Post2DPlotThreshold

double MCMCProcessor::Post2DPlotThreshold
protected

KS: Set Threshold when to plot 2D posterior as by default we get a LOT of plots.

Definition at line 516 of file MCMCProcessor.h.

◆ Posterior

std::unique_ptr<TCanvas> MCMCProcessor::Posterior
protected

Fancy canvas used for our beautiful plots.

Definition at line 530 of file MCMCProcessor.h.

◆ Posterior1DCut

std::string MCMCProcessor::Posterior1DCut
protected

Cut used when making 1D Posterior distribution.

Definition at line 445 of file MCMCProcessor.h.

◆ printToPDF

bool MCMCProcessor::printToPDF
protected

Will plot all plot to PDF not only to root file.

Definition at line 508 of file MCMCProcessor.h.

◆ ReweightNames

std::vector<std::string> MCMCProcessor::ReweightNames
protected

Name of branch used for chain reweighting.

Definition at line 603 of file MCMCProcessor.h.

◆ ReweightPosterior

bool MCMCProcessor::ReweightPosterior
protected

Whether to apply reweighting weight or not.

Definition at line 601 of file MCMCProcessor.h.

◆ SampleName_v

std::vector<TString> MCMCProcessor::SampleName_v
protected

Vector of each sample PDF object.

Definition at line 490 of file MCMCProcessor.h.

◆ SampleValues

double** MCMCProcessor::SampleValues
protected

Holds the sample values.

Definition at line 591 of file MCMCProcessor.h.

◆ StepCut

std::string MCMCProcessor::StepCut
protected

BurnIn Cuts.

Definition at line 443 of file MCMCProcessor.h.

◆ StepNumber

unsigned int* MCMCProcessor::StepNumber
protected

Step number for step, important if chains were merged.

Definition at line 569 of file MCMCProcessor.h.

◆ SystName_v

std::vector<TString> MCMCProcessor::SystName_v
protected

Vector of each systematic.

Definition at line 492 of file MCMCProcessor.h.

◆ SystValues

double** MCMCProcessor::SystValues
protected

Holds the systs values.

Definition at line 593 of file MCMCProcessor.h.

◆ UpperCut

unsigned int MCMCProcessor::UpperCut
protected

KS: Used only for SubOptimality.

Definition at line 447 of file MCMCProcessor.h.

◆ useFFTAutoCorrelation

bool MCMCProcessor::useFFTAutoCorrelation
protected

MJR: Use FFT-based autocorrelation algorithm (save time & resources)?

Definition at line 518 of file MCMCProcessor.h.

◆ WeightValue

double* MCMCProcessor::WeightValue
protected

Stores value of weight for each step.

Definition at line 605 of file MCMCProcessor.h.


The documentation for this class was generated from the following files: