MaCh3  2.5.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 [30]. 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 ReweightPrior (const std::vector< std::string > &Names, const std::vector< double > &NewCentral, const std::vector< double > &NewError)
 Reweight Prior by giving new central value and new error. 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...
 
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...
 
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 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 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] [31]. 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...
 

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 systematic. More...
 
std::vector< TString > SystName_v
 Vector of each sample PDF object. 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::string ReweightName
 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 18 of file MCMCProcessor.cpp.

18  :
19  Chain(nullptr), StepCut(""), MadePostfit(false) {
20 // ****************************
21  MCMCFile = InputFile;
22 
25  MACH3LOG_INFO("Making post-fit processor for: {}", MCMCFile);
26 
27  ParStep = nullptr;
28  StepNumber = nullptr;
29  ReweightPosterior = false;
30  WeightValue = nullptr;
31 
32  Posterior = nullptr;
33  hviolin = nullptr;
34  hviolin_prior = nullptr;
35 
36  OutputFile = nullptr;
37 
38  BatchedAverages = nullptr;
39  SampleValues = nullptr;
40  SystValues = nullptr;
41  AccProbValues = nullptr;
42  AccProbBatchedAverages = nullptr;
43 
44  //KS:Hardcoded should be a way to get it via config or something
45  plotRelativeToPrior = false;
46  printToPDF = false;
47  plotBinValue = false;
48  PlotFlatPrior = true;
49  CacheMCMC = false;
50  ApplySmoothing = true;
51  FancyPlotNames = true;
52  doDiagMCMC = false;
53 
54  // KS: ROOT can compile FFT code but it will crash during run time. Turn off FFT dynamically
55 #ifdef MaCh3_FFT
56  useFFTAutoCorrelation = true;
57 #else
58  useFFTAutoCorrelation = false;
59 #endif
60  OutputSuffix = "_Process";
61  Post2DPlotThreshold = 1.e-5;
62 
63  nDraw = 0;
64  nEntries = 0;
66  nSteps = 0;
67  nBatches = 0;
68  AutoCorrLag = 0;
69 
70  nBins = 70;
71  DrawRange = 1.5;
72 
73  Posterior1DCut = "";
74  //KS:Those keep basic information for ParameterEnum
78  ParamFlat.resize(kNParameterEnum);
80  nParam.resize(kNParameterEnum);
81  CovPos.resize(kNParameterEnum);
83  CovConfig.resize(kNParameterEnum);
84 
85  for(int i = 0; i < kNParameterEnum; i++)
86  {
87  ParamTypeStartPos[i] = 0;
88  nParam[i] = 0;
89  }
90  //Only if GPU is enabled
91  #ifdef MaCh3_CUDA
92  GPUProcessor = std::make_unique<MCMCProcessorGPU>();
93  #endif
94 }
@ kNParameterEnum
Definition: MCMCProcessor.h:50
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:61
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.
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 98 of file MCMCProcessor.cpp.

98  {
99 // ****************************
100  // Close the pdf file
101  MACH3LOG_INFO("Closing pdf in MCMCProcessor: {}", CanvasName.Data());
102  CanvasName += "]";
103  if(printToPDF) Posterior->Print(CanvasName);
104 
105  delete Covariance;
106  delete Correlation;
107  delete Central_Value;
108  delete Means;
109  delete Errors;
110  delete Means_Gauss;
111  delete Errors_Gauss;
112  delete Means_HPD;
113  delete Errors_HPD;
114  delete Errors_HPD_Positive;
115  delete Errors_HPD_Negative;
116 
117  if(WeightValue) delete[] WeightValue;
118  for (int i = 0; i < nDraw; ++i)
119  {
120  if(hpost[i] != nullptr) delete hpost[i];
121  }
122  if(CacheMCMC)
123  {
124  for (int i = 0; i < nDraw; ++i)
125  {
126  for (int j = 0; j < nDraw; ++j)
127  {
128  delete hpost2D[i][j];
129  }
130  delete[] ParStep[i];
131  }
132  delete[] ParStep;
133  }
134  if(StepNumber != nullptr) delete[] StepNumber;
135 
136  if(OutputFile != nullptr) OutputFile->Close();
137  if(OutputFile != nullptr) delete OutputFile;
138  delete Chain;
139 }
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 4504 of file MCMCProcessor.cpp.

4504  {
4505 // **************************
4506  if (AccProbBatchedAverages == nullptr) PrepareDiagMCMC();
4507 
4508  MACH3LOG_INFO("Making AccProb plots...");
4509 
4510  // Set the titles and limits for TH1Ds
4511  auto AcceptanceProbPlot = std::make_unique<TH1D>("AcceptanceProbability", "Acceptance Probability", nEntries, 0, nEntries);
4512  AcceptanceProbPlot->SetDirectory(nullptr);
4513  AcceptanceProbPlot->GetXaxis()->SetTitle("Step");
4514  AcceptanceProbPlot->GetYaxis()->SetTitle("Acceptance Probability");
4515 
4516  auto BatchedAcceptanceProblot = std::make_unique<TH1D>("AcceptanceProbability_Batch", "AcceptanceProbability_Batch", nBatches, 0, nBatches);
4517  BatchedAcceptanceProblot->SetDirectory(nullptr);
4518  BatchedAcceptanceProblot->GetYaxis()->SetTitle("Acceptance Probability");
4519 
4520  for (int i = 0; i < nBatches; ++i) {
4521  BatchedAcceptanceProblot->SetBinContent(i+1, AccProbBatchedAverages[i]);
4522  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4523  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4524  std::stringstream ss;
4525  ss << BatchRangeLow << " - " << BatchRangeHigh;
4526  BatchedAcceptanceProblot->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4527  }
4528 
4529  #ifdef MULTITHREAD
4530  #pragma omp parallel for
4531  #endif
4532  for (int i = 0; i < nEntries; ++i) {
4533  // Set bin content for the i-th bin to the parameter values
4534  AcceptanceProbPlot->SetBinContent(i, AccProbValues[i]);
4535  }
4536 
4537  TDirectory *probDir = OutputFile->mkdir("AccProb");
4538  probDir->cd();
4539 
4540  AcceptanceProbPlot->Write();
4541  BatchedAcceptanceProblot->Write();
4542  delete[] AccProbValues;
4543  delete[] AccProbBatchedAverages;
4544 
4545  probDir->Close();
4546  delete probDir;
4547 
4548  OutputFile->cd();
4549 }
void PrepareDiagMCMC()
CW: Prepare branches etc. for DiagMCMC.

◆ AutoCorrelation()

void MCMCProcessor::AutoCorrelation ( )
protected

KS: Calculate autocorrelations supports both OpenMP and CUDA :)

Definition at line 3775 of file MCMCProcessor.cpp.

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

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

◆ BatchedAnalysis()

void MCMCProcessor::BatchedAnalysis ( )
protected

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

Definition at line 4136 of file MCMCProcessor.cpp.

4136  {
4137 // **************************
4138  if(BatchedAverages == nullptr)
4139  {
4140  MACH3LOG_ERROR("BatchedAverages haven't been initialises or have been deleted something is wrong");
4141  MACH3LOG_ERROR("I need it and refuse to go further");
4142  throw MaCh3Exception(__FILE__ , __LINE__ );
4143  }
4144 
4145  // Calculate variance estimator using batched means following @cite chakraborty2019estimating see Eq. 1.2
4146  TVectorD* BatchedVariance = new TVectorD(nDraw);
4147  //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
4148  TVectorD* C_Test_Statistics = new TVectorD(nDraw);
4149 
4150  std::vector<double> OverallBatchMean(nDraw);
4151  std::vector<double> C_Rho_Nominator(nDraw);
4152  std::vector<double> C_Rho_Denominator(nDraw);
4153  std::vector<double> C_Nominator(nDraw);
4154  std::vector<double> C_Denominator(nDraw);
4155  const int BatchLength = nEntries/nBatches+1;
4156 //KS: Start parallel region
4157 #ifdef MULTITHREAD
4158 #pragma omp parallel
4159 {
4160 #endif
4161  #ifdef MULTITHREAD
4162  #pragma omp for
4163  #endif
4164  //KS: First calculate mean of batched means for each param and Initialise everything to 0
4165  for (int j = 0; j < nDraw; ++j)
4166  {
4167  OverallBatchMean[j] = 0.0;
4168  C_Rho_Nominator[j] = 0.0;
4169  C_Rho_Denominator[j] = 0.0;
4170  C_Nominator[j] = 0.0;
4171  C_Denominator[j] = 0.0;
4172 
4173  (*BatchedVariance)(j) = 0.0;
4174  (*C_Test_Statistics)(j) = 0.0;
4175  for (int i = 0; i < nBatches; ++i)
4176  {
4177  OverallBatchMean[j] += BatchedAverages[i][j];
4178  }
4179  OverallBatchMean[j] /= nBatches;
4180  }
4181 
4182  #ifdef MULTITHREAD
4183  #pragma omp for nowait
4184  #endif
4185  //KS: next loop is completely independent thus nowait clause
4186  for (int j = 0; j < nDraw; ++j)
4187  {
4188  for (int i = 0; i < nBatches; ++i)
4189  {
4190  (*BatchedVariance)(j) += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4191  }
4192  (*BatchedVariance)(j) = (BatchLength/(nBatches-1))* (*BatchedVariance)(j);
4193  }
4194 
4195  //KS: Now we focus on C test statistic, again use nowait as next is calculation is independent
4196  #ifdef MULTITHREAD
4197  #pragma omp for nowait
4198  #endif
4199  for (int j = 0; j < nDraw; ++j)
4200  {
4201  C_Nominator[j] = (OverallBatchMean[j] - BatchedAverages[0][j])*(OverallBatchMean[j] - BatchedAverages[0][j]) +
4202  (OverallBatchMean[j] - BatchedAverages[nBatches-1][j])*(OverallBatchMean[j] - BatchedAverages[nBatches-1][j]);
4203  for (int i = 0; i < nBatches; ++i)
4204  {
4205  C_Denominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4206  }
4207  C_Denominator[j] = 2*C_Denominator[j];
4208  }
4209 
4210  //KS: We still calculate C and for this we need rho wee need autocorrelations between batches
4211  #ifdef MULTITHREAD
4212  #pragma omp for
4213  #endif
4214  for (int j = 0; j < nDraw; ++j)
4215  {
4216  for (int i = 0; i < nBatches-1; ++i)
4217  {
4218  C_Rho_Nominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i+1][j]);
4219  }
4220 
4221  for (int i = 0; i < nBatches; ++i)
4222  {
4223  C_Rho_Denominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4224  }
4225  }
4226 
4227  //KS: Final calculations of C
4228  #ifdef MULTITHREAD
4229  #pragma omp for
4230  #endif
4231  for (int j = 0; j < nDraw; ++j)
4232  {
4233  (*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]);
4234  }
4235 #ifdef MULTITHREAD
4236 } //End parallel region
4237 #endif
4238 
4239  //Save to file
4240  OutputFile->cd();
4241  BatchedVariance->Write("BatchedMeansVariance");
4242  C_Test_Statistics->Write("C_Test_Statistics");
4243 
4244  //Delete all variables
4245  delete BatchedVariance;
4246  delete C_Test_Statistics;
4247 }
#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 4079 of file MCMCProcessor.cpp.

4079  {
4080 // **************************
4081  if (BatchedAverages == nullptr) PrepareDiagMCMC();
4082  MACH3LOG_INFO("Making BatchedMeans plots...");
4083 
4084  std::vector<std::unique_ptr<TH1D>> BatchedParamPlots(nDraw);
4085  for (int j = 0; j < nDraw; ++j) {
4086  TString Title = "";
4087  double Prior = 1.0, PriorError = 1.0;
4088 
4089  GetNthParameter(j, Prior, PriorError, Title);
4090 
4091  std::string HistName = Form("%s_%s_batch", Title.Data(), BranchNames[j].Data());
4092  BatchedParamPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nBatches, 0, nBatches);
4093  BatchedParamPlots[j]->SetDirectory(nullptr);
4094  }
4095 
4096  #ifdef MULTITHREAD
4097  #pragma omp parallel for
4098  #endif
4099  for (int j = 0; j < nDraw; ++j) {
4100  for (int i = 0; i < nBatches; ++i) {
4101  BatchedParamPlots[j]->SetBinContent(i+1, BatchedAverages[i][j]);
4102  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4103  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4104  std::stringstream ss;
4105  ss << BatchRangeLow << " - " << BatchRangeHigh;
4106  BatchedParamPlots[j]->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4107  }
4108  }
4109 
4110  TDirectory *BatchDir = OutputFile->mkdir("Batched_means");
4111  BatchDir->cd();
4112  for (int j = 0; j < nDraw; ++j) {
4113  auto Fitter = std::make_unique<TF1>("Fitter", "[0]", 0, nBatches);
4114  Fitter->SetLineColor(kRed);
4115  BatchedParamPlots[j]->Fit("Fitter","Rq");
4116  BatchedParamPlots[j]->Write();
4117  }
4118 
4119  //KS: Get the batched means variance estimation and variable indicating if number of batches is sensible
4120  // We do this before deleting BatchedAverages
4121  BatchedAnalysis();
4122 
4123  for (int i = 0; i < nBatches; ++i) {
4124  delete BatchedAverages[i];
4125  }
4126  delete[] BatchedAverages;
4127 
4128  BatchDir->Close();
4129  delete BatchDir;
4130 
4131  OutputFile->cd();
4132 }
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 1060 of file MCMCProcessor.cpp.

1060  {
1061 // ***************
1062  if(CacheMCMC == true) return;
1063 
1064  CacheMCMC = true;
1065 
1066  if(ParStep != nullptr)
1067  {
1068  MACH3LOG_ERROR("It look like ParStep was already filled ");
1069  MACH3LOG_ERROR("Even though it is used for MakeCovariance_MP and for DiagMCMC ");
1070  MACH3LOG_ERROR("it has different structure in both for cache hits, sorry ");
1071  throw MaCh3Exception(__FILE__ , __LINE__ );
1072  }
1073 
1074  MACH3LOG_INFO("Caching input tree...");
1075  MACH3LOG_INFO("Allocating {:.2f} MB", double(sizeof(M3::float_t)*nDraw*nEntries)/1.E6);
1076  TStopwatch clock;
1077  clock.Start();
1078 
1079  ParStep = new M3::float_t*[nDraw];
1080  StepNumber = new unsigned int[nEntries];
1081 
1082  hpost2D.resize(nDraw);
1083  for (int i = 0; i < nDraw; ++i)
1084  {
1085  ParStep[i] = new M3::float_t[nEntries];
1086  hpost2D[i].resize(nDraw);
1087  for (int j = 0; j < nEntries; ++j)
1088  {
1089  ParStep[i][j] = -999.99;
1090  //KS: Set this only once
1091  if(i == 0) StepNumber[j] = 0;
1092  }
1093  }
1094 
1095  // Set all the branches to off
1096  Chain->SetBranchStatus("*", false);
1097  unsigned int stepBranch = 0;
1098  std::vector<double> ParValBranch(nDraw);
1099  // Turn on the branches which we want for parameters
1100  for (int i = 0; i < nDraw; ++i)
1101  {
1102  Chain->SetBranchStatus(BranchNames[i].Data(), true);
1103  Chain->SetBranchAddress(BranchNames[i].Data(), &ParValBranch[i]);
1104  }
1105  Chain->SetBranchStatus("step", true);
1106  Chain->SetBranchAddress("step", &stepBranch);
1107 
1108  double ReweightWeight = 1.;
1109  if(ReweightPosterior)
1110  {
1111  WeightValue = new double[nEntries]();
1112  Chain->SetBranchStatus(ReweightName.c_str(), true);
1113  Chain->SetBranchAddress(ReweightName.c_str(), &ReweightWeight);
1114  }
1115 
1116  const Long64_t countwidth = nEntries/10;
1117 
1118  // Loop over the entries
1119  //KS: This is really a bottleneck right now, thus revisit with ROOT6 https://pep-root6.github.io/docs/analysis/parallell/root.html
1120  for (Long64_t j = 0; j < nEntries; ++j)
1121  {
1122  if (j % countwidth == 0) {
1125  } else {
1126  Chain->GetEntry(j);
1127  }
1128  StepNumber[j] = stepBranch;
1129  // Set the branch addresses for params
1130  for (int i = 0; i < nDraw; ++i) {
1131  ParStep[i][j] = ParValBranch[i];
1132  }
1133 
1134  if(ReweightPosterior){
1135  WeightValue[j] = ReweightWeight;
1136  }
1137  }
1138  // Set all the branches to on
1139  Chain->SetBranchStatus("*", true);
1140 
1141  // KS: Set temporary branch address to allow min/max, otherwise ROOT can segfaults
1142  double tempVal = 0.0;
1143  std::vector<double> Min_Chain(nDraw);
1144  std::vector<double> Max_Chain(nDraw);
1145  for (int i = 0; i < nDraw; ++i)
1146  {
1147  Chain->SetBranchAddress(BranchNames[i].Data(), &tempVal);
1148  Min_Chain[i] = Chain->GetMinimum(BranchNames[i]);
1149  Max_Chain[i] = Chain->GetMaximum(BranchNames[i]);
1150  }
1151 
1152  // Calculate the total number of TH2D objects
1153  size_t nHistograms = nDraw * (nDraw + 1) / 2;
1154  MACH3LOG_INFO("Caching 2D posterior histograms...");
1155  MACH3LOG_INFO("Allocating {:.2f} MB for {} 2D Posteriors (each {}x{} bins)",
1156  double(nHistograms * nBins * nBins * sizeof(double)) / 1.E6, nHistograms, nBins, nBins);
1157  // Cache max and min in chain for covariance matrix
1158  for (int i = 0; i < nDraw; ++i)
1159  {
1160  TString Title_i = "";
1161  double Prior_i, PriorError_i;
1162  GetNthParameter(i, Prior_i, PriorError_i, Title_i);
1163 
1164  for (int j = 0; j <= i; ++j)
1165  {
1166  TString Title_j = "";
1167  double Prior_j, PriorError_j;
1168  GetNthParameter(j, Prior_j, PriorError_j, Title_j);
1169 
1170  // TH2D to hold the Correlation
1171  hpost2D[i][j] = new TH2D((Title_i + "_" + Title_j).Data(), (Title_i + "_" + Title_j).Data(),
1172  nBins, hpost[i]->GetXaxis()->GetXmin(), hpost[i]->GetXaxis()->GetXmax(),
1173  nBins, hpost[j]->GetXaxis()->GetXmin(), hpost[j]->GetXaxis()->GetXmax());
1174  hpost2D[i][j]->SetMinimum(0);
1175  hpost2D[i][j]->GetXaxis()->SetTitle(Title_i);
1176  hpost2D[i][j]->GetYaxis()->SetTitle(Title_j);
1177  hpost2D[i][j]->GetZaxis()->SetTitle("Steps");
1178  }
1179  }
1180  clock.Stop();
1181  MACH3LOG_INFO("Caching steps took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries );
1182 }
std::string ReweightName
Name of branch used for chain reweighting.
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. [33] [17] [9]

Definition at line 3981 of file MCMCProcessor.cpp.

3981  {
3982 // **************************
3983  if(LagL.size() == 0)
3984  {
3985  MACH3LOG_ERROR("Size of LagL is {}", LagL.size());
3986  throw MaCh3Exception(__FILE__ , __LINE__ );
3987  }
3988  MACH3LOG_INFO("Making ESS plots...");
3989  TVectorD* EffectiveSampleSize = new TVectorD(nDraw);
3990  TVectorD* SamplingEfficiency = new TVectorD(nDraw);
3991  std::vector<double> TempDenominator(nDraw);
3992 
3993  constexpr int Nhists = 5;
3994  constexpr double Thresholds[Nhists + 1] = {1, 0.02, 0.005, 0.001, 0.0001, 0.0};
3995  constexpr Color_t ESSColours[Nhists] = {kGreen, kGreen + 2, kYellow, kOrange, kRed};
3996 
3997  //KS: This histogram is inspired by the following: @cite gabry2024visual
3998  std::vector<std::unique_ptr<TH1D>> EffectiveSampleSizeHist(Nhists);
3999  for(int i = 0; i < Nhists; ++i)
4000  {
4001  EffectiveSampleSizeHist[i] =
4002  std::make_unique<TH1D>(Form("EffectiveSampleSizeHist_%i", i), Form("EffectiveSampleSizeHist_%i", i), nDraw, 0, nDraw);
4003  EffectiveSampleSizeHist[i]->SetDirectory(nullptr);
4004  EffectiveSampleSizeHist[i]->GetYaxis()->SetTitle("N_{eff}/N");
4005  EffectiveSampleSizeHist[i]->SetFillColor(ESSColours[i]);
4006  EffectiveSampleSizeHist[i]->SetLineColor(ESSColours[i]);
4007  EffectiveSampleSizeHist[i]->Sumw2();
4008  for (int j = 0; j < nDraw; ++j)
4009  {
4010  TString Title = "";
4011  double Prior = 1.0, PriorError = 1.0;
4012  GetNthParameter(j, Prior, PriorError, Title);
4013  EffectiveSampleSizeHist[i]->GetXaxis()->SetBinLabel(j+1, Title.Data());
4014  }
4015  }
4016 
4017  #ifdef MULTITHREAD
4018  #pragma omp parallel for
4019  #endif
4020  //KS: Calculate ESS and MCMC efficiency for each parameter
4021  for (int j = 0; j < nDraw; ++j)
4022  {
4023  (*EffectiveSampleSize)(j) = M3::_BAD_DOUBLE_;
4024  (*SamplingEfficiency)(j) = M3::_BAD_DOUBLE_;
4025  TempDenominator[j] = 0.;
4026  //KS: Firs sum over all Calculated autocorrelations
4027  for (int k = 0; k < nLags; ++k)
4028  {
4029  TempDenominator[j] += LagL[j][k];
4030  }
4031  TempDenominator[j] = 1+2*TempDenominator[j];
4032  (*EffectiveSampleSize)(j) = double(nEntries)/TempDenominator[j];
4033  // 100 because we convert to percentage
4034  (*SamplingEfficiency)(j) = 100 * 1/TempDenominator[j];
4035 
4036  for(int i = 0; i < Nhists; ++i)
4037  {
4038  EffectiveSampleSizeHist[i]->SetBinContent(j+1, 0);
4039  EffectiveSampleSizeHist[i]->SetBinError(j+1, 0);
4040 
4041  const double TempEntry = std::fabs((*EffectiveSampleSize)(j)) / double(nEntries);
4042  if(Thresholds[i] >= TempEntry && TempEntry > Thresholds[i+1])
4043  {
4044  if( std::isnan((*EffectiveSampleSize)(j)) ) continue;
4045  EffectiveSampleSizeHist[i]->SetBinContent(j+1, TempEntry);
4046  }
4047  }
4048  }
4049 
4050  //KS Write to the output tree
4051  //Save to file
4052  OutputFile->cd();
4053  EffectiveSampleSize->Write("EffectiveSampleSize");
4054  SamplingEfficiency->Write("SamplingEfficiency");
4055 
4056  EffectiveSampleSizeHist[0]->SetTitle("Effective Sample Size");
4057  EffectiveSampleSizeHist[0]->Draw();
4058  for(int i = 1; i < Nhists; ++i)
4059  {
4060  EffectiveSampleSizeHist[i]->Draw("SAME");
4061  }
4062 
4063  auto leg = std::make_unique<TLegend>(0.2, 0.7, 0.6, 0.95);
4064  SetLegendStyle(leg.get(), 0.03);
4065  for(int i = 0; i < Nhists; ++i)
4066  {
4067  leg->AddEntry(EffectiveSampleSizeHist[i].get(), Form("%.4f >= N_{eff}/N > %.4f", Thresholds[i], Thresholds[i+1]), "f");
4068  } leg->Draw("SAME");
4069 
4070  Posterior->Write("EffectiveSampleSizeCanvas");
4071 
4072  //Delete all variables
4073  delete EffectiveSampleSize;
4074  delete SamplingEfficiency;
4075 }
double * EffectiveSampleSize
Definition: RHat.cpp:72
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 4552 of file MCMCProcessor.cpp.

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

◆ 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 4571 of file MCMCProcessor.cpp.

4573  {
4574 // **************************
4575  if ((CredibleRegions.size() != CredibleRegionStyle.size()) || (CredibleRegionStyle.size() != CredibleRegionColor.size())) {
4576  MACH3LOG_ERROR("size of CredibleRegions is not equal to size of CredibleRegionStyle or CredibleRegionColor");
4577  throw MaCh3Exception(__FILE__, __LINE__);
4578  }
4579  for (unsigned int i = 1; i < CredibleRegions.size(); i++) {
4580  if (CredibleRegions[i] > CredibleRegions[i - 1]) {
4581  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4582  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleRegions[i], CredibleRegions[i - 1]);
4583  MACH3LOG_ERROR("They should be grouped in decreasing order");
4584  throw MaCh3Exception(__FILE__, __LINE__);
4585  }
4586  }
4587 }

◆ CheckStepCut()

void MCMCProcessor::CheckStepCut ( ) const

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

Definition at line 2747 of file MCMCProcessor.cpp.

2747  {
2748 // ***************
2749  const unsigned int maxNsteps = Chain->GetMaximum("step");
2750  if(BurnInCut > maxNsteps){
2751  MACH3LOG_ERROR("StepCut({}) is larger than highest value of step({})", BurnInCut, maxNsteps);
2752  throw MaCh3Exception(__FILE__ , __LINE__ );
2753  }
2754 }
unsigned int BurnInCut
Value of burn in cut.

◆ DiagMCMC()

void MCMCProcessor::DiagMCMC ( )

KS: Perform MCMC diagnostic including Autocorrelation, Trace etc.

Definition at line 3378 of file MCMCProcessor.cpp.

3378  {
3379 // **************************
3380  // Prepare branches etc for DiagMCMC
3381  PrepareDiagMCMC();
3382 
3383  // Draw the simple trace matrices
3384  ParamTraces();
3385 
3386  // Get the batched means
3387  BatchedMeans();
3388 
3389  // Draw the auto-correlations
3390  if (useFFTAutoCorrelation) {
3392  } else {
3393  AutoCorrelation();
3394  }
3395 
3396  // Calculate Power Spectrum for each param
3398 
3399  // Get Geweke Z score helping select burn-in
3400  GewekeDiagnostic();
3401 
3402  // Draw acceptance Probability
3404 }
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 1631 of file MCMCProcessor.cpp.

1631  {
1632 // *********************
1633  //KS: Store it as we go back to them at the end
1634  const std::vector<double> Margins = GetMargins(Posterior);
1635  const int OptTitle = gStyle->GetOptTitle();
1636 
1637  Posterior->SetTopMargin(0.1);
1638  Posterior->SetBottomMargin(0.2);
1639  gStyle->SetOptTitle(1);
1640 
1641  constexpr int Nhists = 3;
1642  //KS: Highest value is just meant bo be sliglhy higher than 1 to catch >,
1643  constexpr double Thresholds[Nhists+1] = {0, 0.25, 0.5, 1.0001};
1644  constexpr Color_t CorrColours[Nhists] = {kRed-10, kRed-6, kRed};
1645 
1646  //KS: This store necessary entries for stripped covariance which store only "meaningful correlations
1647  std::vector<std::vector<double>> CorrOfInterest;
1648  CorrOfInterest.resize(nDraw);
1649  std::vector<std::vector<std::string>> NameCorrOfInterest;
1650  NameCorrOfInterest.resize(nDraw);
1651 
1652  std::vector<std::vector<std::unique_ptr<TH1D>>> Corr1DHist(nDraw);
1653  //KS: Initialising ROOT objects is never safe in MP loop
1654  for(int i = 0; i < nDraw; ++i)
1655  {
1656  TString Title = "";
1657  double Prior = 1.0, PriorError = 1.0;
1658  GetNthParameter(i, Prior, PriorError, Title);
1659 
1660  Corr1DHist[i].resize(Nhists);
1661  for(int j = 0; j < Nhists; ++j)
1662  {
1663  Corr1DHist[i][j] = std::make_unique<TH1D>(Form("Corr1DHist_%i_%i", i, j), Form("Corr1DHist_%i_%i", i, j), nDraw, 0, nDraw);
1664  Corr1DHist[i][j]->SetTitle(Form("%s",Title.Data()));
1665  Corr1DHist[i][j]->SetDirectory(nullptr);
1666  Corr1DHist[i][j]->GetYaxis()->SetTitle("Correlation");
1667  Corr1DHist[i][j]->SetFillColor(CorrColours[j]);
1668  Corr1DHist[i][j]->SetLineColor(kBlack);
1669 
1670  for (int k = 0; k < nDraw; ++k)
1671  {
1672  TString Title_y = "";
1673  double Prior_y = 1.0;
1674  double PriorError_y = 1.0;
1675  GetNthParameter(k, Prior_y, PriorError_y, Title_y);
1676  Corr1DHist[i][j]->GetXaxis()->SetBinLabel(k+1, Title_y.Data());
1677  }
1678  }
1679  }
1680 
1681  // KS: Do not add collapse(2) otherwise one can intorduce race condition :(
1682  #ifdef MULTITHREAD
1683  #pragma omp parallel for
1684  #endif
1685  for(int i = 0; i < nDraw; ++i)
1686  {
1687  for(int j = 0; j < nDraw; ++j)
1688  {
1689  for(int k = 0; k < Nhists; ++k)
1690  {
1691  const double TempEntry = std::fabs((*Correlation)(i,j));
1692  if(Thresholds[k+1] > TempEntry && TempEntry >= Thresholds[k])
1693  {
1694  Corr1DHist[i][k]->SetBinContent(j+1, (*Correlation)(i,j));
1695  }
1696  }
1697  if(std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold && i != j)
1698  {
1699  CorrOfInterest[i].push_back((*Correlation)(i,j));
1700  NameCorrOfInterest[i].push_back(Corr1DHist[i][0]->GetXaxis()->GetBinLabel(j+1));
1701  }
1702  }
1703  }
1704 
1705  TDirectory *CorrDir = OutputFile->mkdir("Corr1D");
1706  CorrDir->cd();
1707 
1708  for(int i = 0; i < nDraw; i++)
1709  {
1710  if (ParamVaried[i] == false) continue;
1711 
1712  Corr1DHist[i][0]->GetXaxis()->LabelsOption("v");
1713  Corr1DHist[i][0]->SetMaximum(+1.);
1714  Corr1DHist[i][0]->SetMinimum(-1.);
1715  Corr1DHist[i][0]->Draw();
1716  for(int k = 1; k < Nhists; k++) {
1717  Corr1DHist[i][k]->Draw("SAME");
1718  }
1719 
1720  auto leg = std::make_unique<TLegend>(0.3, 0.75, 0.6, 0.90);
1721  SetLegendStyle(leg.get(), 0.02);
1722  for(int k = 0; k < Nhists; k++) {
1723  leg->AddEntry(Corr1DHist[i][k].get(), Form("%.2f > |Corr| >= %.2f", Thresholds[k+1], Thresholds[k]), "f");
1724  }
1725  leg->Draw("SAME");
1726 
1727  Posterior->Write(Corr1DHist[i][0]->GetTitle());
1728  if(printToPDF) Posterior->Print(CanvasName);
1729  }
1730 
1731  //KS: Plot only meaningful correlations
1732  for(int i = 0; i < nDraw; i++)
1733  {
1734  const int size = int(CorrOfInterest[i].size());
1735 
1736  if(size == 0) continue;
1737  auto Corr1DHist_Reduced = std::make_unique<TH1D>("Corr1DHist_Reduced", "Corr1DHist_Reduced", size, 0, size);
1738  Corr1DHist_Reduced->SetDirectory(nullptr);
1739  Corr1DHist_Reduced->SetTitle(Corr1DHist[i][0]->GetTitle());
1740  Corr1DHist_Reduced->GetYaxis()->SetTitle("Correlation");
1741  Corr1DHist_Reduced->SetFillColor(kBlue);
1742  Corr1DHist_Reduced->SetLineColor(kBlue);
1743 
1744  for (int j = 0; j < size; ++j)
1745  {
1746  Corr1DHist_Reduced->GetXaxis()->SetBinLabel(j+1, NameCorrOfInterest[i][j].c_str());
1747  Corr1DHist_Reduced->SetBinContent(j+1, CorrOfInterest[i][j]);
1748  }
1749  Corr1DHist_Reduced->GetXaxis()->LabelsOption("v");
1750 
1751  Corr1DHist_Reduced->SetMaximum(+1.);
1752  Corr1DHist_Reduced->SetMinimum(-1.);
1753  Corr1DHist_Reduced->Draw();
1754 
1755  Posterior->Write(Form("%s_Red", Corr1DHist_Reduced->GetTitle()));
1756  if(printToPDF) Posterior->Print(CanvasName);
1757  }
1758 
1759  CorrDir->Close();
1760  delete CorrDir;
1761  OutputFile->cd();
1762 
1763  SetMargins(Posterior, Margins);
1764  gStyle->SetOptTitle(OptTitle);
1765 }
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 1521 of file MCMCProcessor.cpp.

1521  {
1522 // *********************
1523  MACH3LOG_INFO("Starting {}", __func__);
1524  const double RightMargin = Posterior->GetRightMargin();
1525  Posterior->SetRightMargin(0.15);
1526  auto MatrixCopy = M3::Clone(CorrMatrix.get());
1527 
1528  std::vector<std::string> GroupName;
1529  std::vector<int> GroupStart;
1530  std::vector<int> GroupEnd;
1531 
1532  // Loop over the Covariance matrix entries
1533  for (int iPar = 0; iPar < nDraw; ++iPar)
1534  {
1535  std::string GroupNameCurr;
1536  if(ParamType[iPar] == kXSecPar){
1537  const int InternalNumeration = iPar - ParamTypeStartPos[kXSecPar];
1538  GroupNameCurr = ParameterGroup[InternalNumeration];
1539  } else {
1540  GroupNameCurr = "Other"; // Use Other for all legacy params
1541  }
1542 
1543  if(iPar == 0) {
1544  GroupName.push_back(GroupNameCurr);
1545  GroupStart.push_back(0);
1546  } else if(GroupName.back() != GroupNameCurr ){
1547  GroupName.push_back(GroupNameCurr);
1548  GroupEnd.push_back(iPar);
1549  GroupStart.push_back(iPar);
1550  }
1551 
1552  MatrixCopy->GetXaxis()->SetBinLabel(iPar+1, "");
1553  MatrixCopy->GetYaxis()->SetBinLabel(iPar+1, "");
1554  }
1555  GroupEnd.push_back(nDraw);
1556 
1557  for(size_t iPar = 0; iPar < GroupName.size(); iPar++) {
1558  MACH3LOG_INFO("Group name {} from {} to {}", GroupName[iPar], GroupStart[iPar], GroupEnd[iPar]);
1559  }
1560  Posterior->cd();
1561  Posterior->Clear();
1562  MatrixCopy->Draw("colz");
1563 
1564  std::vector<std::unique_ptr<TLine>> groupLines; //((GroupStart.size() - 1) * 2);
1565 
1566  int nBinsX = MatrixCopy->GetNbinsX();
1567  int nBinsY = MatrixCopy->GetNbinsY();
1568 
1569  // Axis bounds from the histogram itself
1570  double xMin = MatrixCopy->GetXaxis()->GetBinLowEdge(1);
1571  double xMax = MatrixCopy->GetXaxis()->GetBinUpEdge(nBinsX);
1572  double yMin = MatrixCopy->GetYaxis()->GetBinLowEdge(1);
1573  double yMax = MatrixCopy->GetYaxis()->GetBinUpEdge(nBinsY);
1574 
1575  for (size_t g = 1; g < GroupStart.size(); ++g) {
1576  const double posX = MatrixCopy->GetXaxis()->GetBinLowEdge(GroupStart[g] + 1);
1577  const double posY = MatrixCopy->GetYaxis()->GetBinLowEdge(GroupStart[g] + 1);
1578 
1579  // Vertical line at group start
1580  auto vLine = std::make_unique<TLine>(posX, yMin, posX, yMax);
1581  vLine->SetLineColor(kBlack);
1582  vLine->SetLineWidth(2);
1583  vLine->Draw();
1584  groupLines.push_back(std::move(vLine));
1585 
1586  // Horizontal line at group start
1587  auto hLine = std::make_unique<TLine>(xMin, posY, xMax, posY);
1588  hLine->SetLineColor(kBlack);
1589  hLine->SetLineWidth(2);
1590  hLine->Draw();
1591  groupLines.push_back(std::move(hLine));
1592  }
1593 
1594  std::vector<std::unique_ptr<TText>> groupLabels(GroupName.size() * 2);
1595  const double yOffsetBelow = 0.05 * (yMax - yMin); // space below x-axis
1596  const double xOffsetRight = 0.02 * (xMax - xMin); // space right of y-axis
1597 
1598  for (size_t g = 0; g < GroupName.size(); ++g) {
1599  const int startBin = GroupStart[g] + 1; // hist bins start at 1
1600  const int endBin = GroupEnd[g];
1601 
1602  const double xStart = MatrixCopy->GetXaxis()->GetBinLowEdge(startBin);
1603  const double xEnd = MatrixCopy->GetXaxis()->GetBinUpEdge(endBin);
1604  const double xMid = 0.5 * (xStart + xEnd);
1605 
1606  const double yStart = MatrixCopy->GetYaxis()->GetBinLowEdge(startBin);
1607  const double yEnd = MatrixCopy->GetYaxis()->GetBinUpEdge(endBin);
1608  const double yMid = 0.5 * (yStart + yEnd);
1609 
1610  // Label along X-axis (below histogram)
1611  auto labelX = std::make_unique<TText>(xMid, yMin - yOffsetBelow, GroupName[g].c_str());
1612  labelX->SetTextAlign(23); // center horizontally, top-aligned vertically
1613  labelX->SetTextSize(0.025);
1614  labelX->Draw();
1615  groupLabels.push_back(std::move(labelX));
1616 
1617  // Label along Y-axis (left of histogram)
1618  auto labelY = std::make_unique<TText>(xMin - xOffsetRight, yMid, GroupName[g].c_str());
1619  labelY->SetTextAlign(32); // right-aligned horizontally, center vertically
1620  labelY->SetTextSize(0.025);
1621  labelY->Draw();
1622  groupLabels.push_back(std::move(labelY));
1623  }
1624 
1625  if(printToPDF) Posterior->Print(CanvasName);
1626  Posterior->SetRightMargin(RightMargin);
1627 }
@ 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 1372 of file MCMCProcessor.cpp.

1372  {
1373 // *********************
1374  const double RightMargin = Posterior->GetRightMargin();
1375  Posterior->SetRightMargin(0.15);
1376 
1377  // The Covariance matrix from the fit
1378  auto hCov = std::make_unique<TH2D>("hCov", "hCov", nDraw, 0, nDraw, nDraw, 0, nDraw);
1379  hCov->GetZaxis()->SetTitle("Covariance");
1380  hCov->SetDirectory(nullptr);
1381  // The Covariance matrix square root, with correct sign
1382  auto hCovSq = std::make_unique<TH2D>("hCovSq", "hCovSq", nDraw, 0, nDraw, nDraw, 0, nDraw);
1383  hCovSq->SetDirectory(nullptr);
1384  hCovSq->GetZaxis()->SetTitle("Covariance");
1385  // The Correlation
1386  auto hCorr = std::make_unique<TH2D>("hCorr", "hCorr", nDraw, 0, nDraw, nDraw, 0, nDraw);
1387  hCorr->SetDirectory(nullptr);
1388  hCorr->GetZaxis()->SetTitle("Correlation");
1389  hCorr->SetMinimum(-1);
1390  hCorr->SetMaximum(1);
1391  hCov->GetXaxis()->SetLabelSize(0.015);
1392  hCov->GetYaxis()->SetLabelSize(0.015);
1393  hCovSq->GetXaxis()->SetLabelSize(0.015);
1394  hCovSq->GetYaxis()->SetLabelSize(0.015);
1395  hCorr->GetXaxis()->SetLabelSize(0.015);
1396  hCorr->GetYaxis()->SetLabelSize(0.015);
1397 
1398  // Loop over the Covariance matrix entries
1399  for (int i = 0; i < nDraw; ++i)
1400  {
1401  TString titlex = "";
1402  double nom, err;
1403  GetNthParameter(i, nom, err, titlex);
1404 
1405  hCov->GetXaxis()->SetBinLabel(i+1, titlex);
1406  hCovSq->GetXaxis()->SetBinLabel(i+1, titlex);
1407  hCorr->GetXaxis()->SetBinLabel(i+1, titlex);
1408 
1409  for (int j = 0; j < nDraw; ++j)
1410  {
1411  // The value of the Covariance
1412  const double cov = (*Covariance)(i,j);
1413  const double corr = (*Correlation)(i,j);
1414 
1415  hCov->SetBinContent(i+1, j+1, cov);
1416  hCovSq->SetBinContent(i+1, j+1, ((cov > 0) - (cov < 0))*std::sqrt(std::fabs(cov)));
1417  hCorr->SetBinContent(i+1, j+1, corr);
1418 
1419  TString titley = "";
1420  double nom_j, err_j;
1421  GetNthParameter(j, nom_j, err_j, titley);
1422 
1423  hCov->GetYaxis()->SetBinLabel(j+1, titley);
1424  hCovSq->GetYaxis()->SetBinLabel(j+1, titley);
1425  hCorr->GetYaxis()->SetBinLabel(j+1, titley);
1426  }
1427  }
1428 
1429  // Take away the stat box
1430  gStyle->SetOptStat(0);
1431  if(plotBinValue)gStyle->SetPaintTextFormat("4.1f"); //Precision of value in matrix element
1432  // Make pretty Correlation colors (red to blue)
1433  constexpr int NRGBs = 5;
1434  TColor::InitializeColors();
1435  Double_t stops[NRGBs] = { 0.00, 0.25, 0.50, 0.75, 1.00 };
1436  Double_t red[NRGBs] = { 0.00, 0.25, 1.00, 1.00, 0.50 };
1437  Double_t green[NRGBs] = { 0.00, 0.25, 1.00, 0.25, 0.00 };
1438  Double_t blue[NRGBs] = { 0.50, 1.00, 1.00, 0.25, 0.00 };
1439  TColor::CreateGradientColorTable(5, stops, red, green, blue, 255);
1440  gStyle->SetNumberContours(255);
1441 
1442  // cd into the correlation directory
1443  OutputFile->cd();
1444 
1445  Posterior->cd();
1446  Posterior->Clear();
1447  if(plotBinValue) hCov->Draw("colz text");
1448  else hCov->Draw("colz");
1449  if(printToPDF) Posterior->Print(CanvasName);
1450 
1451  Posterior->cd();
1452  Posterior->Clear();
1453  if(plotBinValue) hCorr->Draw("colz text");
1454  else hCorr->Draw("colz");
1455  if(printToPDF) Posterior->Print(CanvasName);
1456 
1457  hCov->Write("Covariance_plot");
1458  hCovSq->Write("Covariance_sq_plot");
1459  hCorr->Write("Correlation_plot");
1460 
1461  //Back to normal
1462  Posterior->SetRightMargin(RightMargin);
1463  DrawCorrelationsGroup(hCorr);
1465 }
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...

◆ DrawPostfit()

void MCMCProcessor::DrawPostfit ( )

Draw the post-fit comparisons.

Definition at line 427 of file MCMCProcessor.cpp.

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

2486  {
2487 // **************************
2488  // Now read the MCMC file
2489  TFile *TempFile = M3::Open(MCMCFile, "open", __FILE__, __LINE__);
2490  TDirectory* CovarianceFolder = TempFile->Get<TDirectory>("CovarianceFolder");
2491 
2492  // Get the settings for the MCMC
2493  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2494 
2495  if (Config == nullptr) {
2496  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2497  TempFile->ls();
2498  throw MaCh3Exception(__FILE__ , __LINE__ );
2499  }
2500  MACH3LOG_INFO("Loading YAML config from MCMC chain");
2501 
2502  YAML::Node Settings = TMacroToYAML(*Config);
2503 
2504  bool InputNotFound = false;
2505  //CW: Get the xsec Covariance matrix
2506  CovPos[kXSecPar] = GetFromManager<std::vector<std::string>>(Settings["General"]["Systematics"]["XsecCovFile"], {"none"});
2507  if(CovPos[kXSecPar].back() == "none")
2508  {
2509  MACH3LOG_WARN("Couldn't find XsecCov branch in output");
2510  InputNotFound = true;
2511  }
2512 
2513  TMacro *XsecConfig = M3::GetConfigMacroFromChain(CovarianceFolder);
2514  if (XsecConfig == nullptr) {
2515  MACH3LOG_WARN("Didn't find Config_xsec_cov tree in MCMC file! {}", MCMCFile);
2516  } else {
2517  CovConfig[kXSecPar] = TMacroToYAML(*XsecConfig);
2518  }
2519  if(InputNotFound) M3::Utils::PrintConfig(Settings);
2520 
2521  for(size_t i = 0; i < CovPos[kXSecPar].size(); i++)
2523 
2524  // Delete the TTrees and the input file handle since we've now got the settings we need
2525  delete Config;
2526  delete XsecConfig;
2527 
2528  TMacro *ReweightConfig = TempFile->Get<TMacro>("Reweight_Config");
2529  if (ReweightConfig != nullptr) {
2530  YAML::Node ReweightSettings = TMacroToYAML(*ReweightConfig);
2531 
2532  if (ReweightSettings["Weight"]) {
2533  ReweightName = "Weight";
2534  ReweightPosterior = true;
2535  MACH3LOG_INFO("Enabling reweighting with following Config");
2536  } else {
2537  MACH3LOG_WARN("Found reweight config but without field ''Weight''");
2538  }
2539  M3::Utils::PrintConfig(ReweightSettings);
2540  }
2541 
2542  // Delete the MCMCFile pointer we're reading
2543  CovarianceFolder->Close();
2544  delete CovarianceFolder;
2545  TempFile->Close();
2546  delete TempFile;
2547 }
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
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 2551 of file MCMCProcessor.cpp.

2551  {
2552 // **************************
2553  // Now read the MCMC file
2554  TFile *TempFile = M3::Open(MCMCFile, "open", __FILE__, __LINE__);
2555  // Get the settings for the MCMC
2556  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2557 
2558  if (Config == nullptr) {
2559  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2560  TempFile->ls();
2561  throw MaCh3Exception(__FILE__ , __LINE__ );
2562  }
2563  YAML::Node Settings = TMacroToYAML(*Config);
2564 
2565  //CW: And the ND Covariance matrix
2566  CovPos[kNDPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovFile"], "none"));
2567 
2568  if(CovPos[kNDPar].back() == "none") {
2569  MACH3LOG_WARN("Couldn't find NDCov (legacy) branch in output");
2570  } else{
2571  //If the FD Cov is not none, then you need the name of the covariance object to grab
2572  CovNamePos[kNDPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovName"], "none");
2573  MACH3LOG_INFO("Given NDCovFile {} and NDCovName {}", CovPos[kNDPar].back(), CovNamePos[kNDPar]);
2574  }
2575 
2576  //CW: And the FD Covariance matrix
2577  CovPos[kFDDetPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovFile"], "none"));
2578 
2579  if(CovPos[kFDDetPar].back() == "none") {
2580  MACH3LOG_WARN("Couldn't find FDCov (legacy) branch in output");
2581  } else {
2582  //If the FD Cov is not none, then you need the name of the covariance object to grab
2583  CovNamePos[kFDDetPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovName"], "none");
2584  MACH3LOG_INFO("Given FDCovFile {} and FDCovName {}", CovPos[kFDDetPar].back(), CovNamePos[kFDDetPar]);
2585  }
2586 
2587  for(size_t i = 0; i < CovPos[kNDPar].size(); i++)
2588  M3::AddPath(CovPos[kNDPar][i]);
2589 
2590  for(size_t i = 0; i < CovPos[kFDDetPar].size(); i++)
2592 
2593  TempFile->Close();
2594  delete TempFile;
2595 }
@ 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 2878 of file MCMCProcessor.cpp.

2881  {
2882 // **************************
2883  if(hpost[0] == nullptr) MakePostfit();
2884 
2885  MACH3LOG_INFO("Calculating Bayes Factor");
2886  if((ParNames.size() != Model1Bounds.size()) || (Model2Bounds.size() != Model1Bounds.size()) || (Model2Bounds.size() != ModelNames.size()))
2887  {
2888  MACH3LOG_ERROR("Size doesn't match");
2889  throw MaCh3Exception(__FILE__ , __LINE__ );
2890  }
2891  for(unsigned int k = 0; k < ParNames.size(); ++k)
2892  {
2893  //KS: First we need to find parameter number based on name
2894  int ParamNo = GetParamIndexFromName(ParNames[k]);
2895  if(ParamNo == M3::_BAD_INT_)
2896  {
2897  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Bayes Factor", ParNames[k]);
2898  continue;
2899  }
2900 
2901  const double M1_min = Model1Bounds[k][0];
2902  const double M2_min = Model2Bounds[k][0];
2903  const double M1_max = Model1Bounds[k][1];
2904  const double M2_max = Model2Bounds[k][1];
2905 
2906  long double IntegralMode1 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M1_min), hpost[ParamNo]->FindFixBin(M1_max));
2907  long double IntegralMode2 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M2_min), hpost[ParamNo]->FindFixBin(M2_max));
2908 
2909  double BayesFactor = 0.;
2910  std::string Name = "";
2911  //KS: Calc Bayes Factor
2912  //If M1 is more likely
2913  if(IntegralMode1 >= IntegralMode2)
2914  {
2915  BayesFactor = IntegralMode1/IntegralMode2;
2916  Name = "\\mathfrak{B}(" + ModelNames[k][0]+ "/" + ModelNames[k][1] + ") = " + std::to_string(BayesFactor);
2917  }
2918  else //If M2 is more likely
2919  {
2920  BayesFactor = IntegralMode2/IntegralMode1;
2921  Name = "\\mathfrak{B}(" + ModelNames[k][1]+ "/" + ModelNames[k][0] + ") = " + std::to_string(BayesFactor);
2922  }
2923  std::string JeffreysScale = GetJeffreysScale(BayesFactor);
2924  std::string DunneKabothScale = GetDunneKaboth(BayesFactor);
2925 
2926  MACH3LOG_INFO("{} for {}", Name, ParNames[k]);
2927  MACH3LOG_INFO("Following Jeffreys Scale = {}", JeffreysScale);
2928  MACH3LOG_INFO("Following Dunne-Kaboth Scale = {}", DunneKabothScale);
2929  MACH3LOG_INFO("");
2930  }
2931 }
std::string GetJeffreysScale(const double BayesFactor)
KS: Following H. Jeffreys .
std::string GetDunneKaboth(const double BayesFactor)
Convert a Bayes factor into an approximate particle-physics significance level using the Dunne–Kaboth...
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 257 of file MCMCProcessor.h.

257 { 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 185 of file MCMCProcessor.cpp.

185  {
186 // ***************
188  else MakeCovariance();
189  Cov = static_cast<TMatrixDSym*>(Covariance->Clone());
190  Corr = static_cast<TMatrixDSym*>(Correlation->Clone());
191 }
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 225 of file MCMCProcessor.h.

225 {return CovConfig.at(i); }

◆ GetFDCov()

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

Definition at line 245 of file MCMCProcessor.h.

245 { 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 4590 of file MCMCProcessor.cpp.

4590  {
4591 // **************************
4592  // Lambda to compare strings case-insensitively
4593  auto caseInsensitiveCompare = [](const std::string& a, const std::string& b) {
4594  return std::equal(a.begin(), a.end(), b.begin(), b.end(),
4595  [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
4596  };
4597  int numerator = 0;
4598  for (const auto& groupName : ParameterGroup) {
4599  if (caseInsensitiveCompare(groupName, name)) {
4600  numerator++;
4601  }
4602  }
4603  return numerator;
4604 }

◆ GetHpost()

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

Get 1D posterior for a given parameter.

Parameters
iparameter index

Definition at line 232 of file MCMCProcessor.h.

232 { 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 236 of file MCMCProcessor.h.

236 { 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 4634 of file MCMCProcessor.cpp.

4634  {
4635 // **************************
4636  return std::vector<double>{Canv->GetTopMargin(), Canv->GetBottomMargin(),
4637  Canv->GetLeftMargin(), Canv->GetRightMargin()};
4638 }

◆ GetNDCov()

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

Definition at line 244 of file MCMCProcessor.h.

244 { 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 263 of file MCMCProcessor.h.

263 {return nEntries;};

◆ GetNFD()

int MCMCProcessor::GetNFD ( ) const
inline

Definition at line 222 of file MCMCProcessor.h.

222 { return nParam[kFDDetPar]; };

◆ GetNND()

int MCMCProcessor::GetNND ( ) const
inline

Definition at line 221 of file MCMCProcessor.h.

221 { return nParam[kNDPar]; };

◆ GetNParams()

int MCMCProcessor::GetNParams ( ) const
inline

Get total number of used parameters.

Definition at line 219 of file MCMCProcessor.h.

219 { 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 265 of file MCMCProcessor.h.

265 {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 2758 of file MCMCProcessor.cpp.

2758  {
2759 // **************************
2760  ParameterEnum ParType = ParamType[param];
2761  int ParamNo = M3::_BAD_INT_;
2762  ParamNo = param - ParamTypeStartPos[ParType];
2763 
2764  Prior = ParamCentral[ParType][ParamNo];
2765  PriorError = ParamErrors[ParType][ParamNo];
2766  Title = ParamNames[ParType][ParamNo];
2767 }

◆ GetNXSec()

int MCMCProcessor::GetNXSec ( ) const
inline

Definition at line 220 of file MCMCProcessor.h.

220 { 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 3653 of file MCMCProcessor.cpp.

3653  {
3654 // *********************************
3655  // Initialise the sums
3656  std::vector <double> ParamSums(nDraw,0);
3657 
3658  #ifdef MULTITHREAD
3659  #pragma omp parallel for
3660  #endif
3661  for (int j = 0; j < nDraw; ++j) {
3662  for (int i = 0; i < nEntries; ++i) {
3663  ParamSums[j] += ParStep[j][i];
3664  }
3665  }
3666  // Make the sums into average
3667  #ifdef MULTITHREAD
3668  #pragma omp parallel for
3669  #endif
3670  for (int i = 0; i < nDraw; ++i) {
3671  ParamSums[i] /= double(nEntries);
3672  }
3673  return ParamSums;
3674 }

◆ GetParamIndexFromName()

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

Get parameter number based on name.

Definition at line 2771 of file MCMCProcessor.cpp.

2771  {
2772 // **************************
2773  int ParamNo = M3::_BAD_INT_;
2774  for (int i = 0; i < nDraw; ++i)
2775  {
2776  TString Title = "";
2777  double Prior = 1.0, PriorError = 1.0;
2778  GetNthParameter(i, Prior, PriorError, Title);
2779 
2780  if(Name == Title)
2781  {
2782  ParamNo = i;
2783  break;
2784  }
2785  }
2786  return ParamNo;
2787 }

◆ 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 2809 of file MCMCProcessor.cpp.

2809  {
2810 // **************************
2811  if(hpost[0] == nullptr) MakePostfit();
2812 
2813  std::vector<double> Margins = GetMargins(Posterior);
2814 
2815  Posterior->SetTopMargin(0.1);
2816  Posterior->SetBottomMargin(0.1);
2817  Posterior->SetLeftMargin(0.1);
2818  Posterior->SetRightMargin(0.1);
2819  Posterior->Update();
2820 
2821  MACH3LOG_INFO("Calculating Polar Plot");
2822  TDirectory *PolarDir = OutputFile->mkdir("PolarDir");
2823  PolarDir->cd();
2824 
2825  for(unsigned int k = 0; k < ParNames.size(); ++k)
2826  {
2827  //KS: First we need to find parameter number based on name
2828  int ParamNo = GetParamIndexFromName(ParNames[k]);
2829  if(ParamNo == M3::_BAD_INT_)
2830  {
2831  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Polar Plot", ParNames[k]);
2832  continue;
2833  }
2834 
2835  TString Title = "";
2836  double Prior = 1.0, PriorError = 1.0;
2837  GetNthParameter(ParamNo, Prior, PriorError, Title);
2838 
2839  std::vector<double> x_val(nBins);
2840  std::vector<double> y_val(nBins);
2841 
2842  constexpr double xmin = 0;
2843  constexpr double xmax = 2*TMath::Pi();
2844 
2845  double Integral = hpost[ParamNo]->Integral();
2846  for (Int_t ipt = 0; ipt < nBins; ipt++)
2847  {
2848  x_val[ipt] = ipt*(xmax-xmin)/nBins+xmin;
2849  y_val[ipt] = hpost[ParamNo]->GetBinContent(ipt+1)/Integral;
2850  }
2851 
2852  auto PolarGraph = std::make_unique<TGraphPolar>(nBins, x_val.data(), y_val.data());
2853  PolarGraph->SetLineWidth(2);
2854  PolarGraph->SetFillStyle(3001);
2855  PolarGraph->SetLineColor(kRed);
2856  PolarGraph->SetFillColor(kRed);
2857  PolarGraph->Draw("AFL");
2858 
2859  auto Text = std::make_unique<TText>(0.6, 0.1, Title);
2860  Text->SetTextSize(0.04);
2861  Text->SetNDC(true);
2862  Text->Draw("");
2863 
2864  Posterior->Print(CanvasName);
2865  Posterior->Write(Title);
2866  } //End loop over parameters
2867 
2868  PolarDir->Close();
2869  delete PolarDir;
2870 
2871  OutputFile->cd();
2872 
2873  SetMargins(Posterior, Margins);
2874 }

◆ 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 152 of file MCMCProcessor.cpp.

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

◆ GetPostfit_Ind()

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

Or the individual post-fits.

Definition at line 167 of file MCMCProcessor.cpp.

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

◆ 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 2935 of file MCMCProcessor.cpp.

2937  {
2938 // **************************
2939  if((ParNames.size() != EvaluationPoint.size()) || (Bounds.size() != EvaluationPoint.size()))
2940  {
2941  MACH3LOG_ERROR("Size doesn't match");
2942  throw MaCh3Exception(__FILE__ , __LINE__ );
2943  }
2944 
2945  if(hpost[0] == nullptr) MakePostfit();
2946 
2947  MACH3LOG_INFO("Calculating Savage Dickey");
2948  TDirectory *SavageDickeyDir = OutputFile->mkdir("SavageDickey");
2949  SavageDickeyDir->cd();
2950 
2951  for(unsigned int k = 0; k < ParNames.size(); ++k)
2952  {
2953  //KS: First we need to find parameter number based on name
2954  int ParamNo = GetParamIndexFromName(ParNames[k]);
2955  if(ParamNo == M3::_BAD_INT_)
2956  {
2957  MACH3LOG_WARN("Couldn't find param {}. Will not calculate SavageDickey", ParNames[k]);
2958  continue;
2959  }
2960 
2961  TString Title = "";
2962  double Prior = 1.0, PriorError = 1.0;
2963  bool FlatPrior = false;
2964  GetNthParameter(ParamNo, Prior, PriorError, Title);
2965 
2966  ParameterEnum ParType = ParamType[ParamNo];
2967  int ParamTemp = ParamNo - ParamTypeStartPos[ParType];
2968  FlatPrior = ParamFlat[ParType][ParamTemp];
2969 
2970  auto PosteriorHist = M3::Clone<TH1D>(hpost[ParamNo], std::string(Title));
2971  RemoveFitter(PosteriorHist.get(), "Gauss");
2972 
2973  std::unique_ptr<TH1D> PriorHist;
2974  //KS: If flat prior we need to have well defined bounds otherwise Prior distribution will not make sense
2975  if(FlatPrior)
2976  {
2977  int NBins = PosteriorHist->GetNbinsX();
2978  if(Bounds[k][0] > Bounds[k][1])
2979  {
2980  MACH3LOG_ERROR("Lower bound is higher than upper bound");
2981  throw MaCh3Exception(__FILE__ , __LINE__ );
2982  }
2983  PriorHist = std::make_unique<TH1D>("PriorHist", Title, NBins, Bounds[k][0], Bounds[k][1]);
2984  PriorHist->SetDirectory(nullptr);
2985  double FlatProb = ( Bounds[k][1] - Bounds[k][0]) / NBins;
2986  for (int g = 0; g < NBins + 1; ++g)
2987  {
2988  PriorHist->SetBinContent(g+1, FlatProb);
2989  }
2990  }
2991  else //KS: Otherwise throw from Gaussian
2992  {
2993  PriorHist = M3::Clone<TH1D>(PosteriorHist.get(), "Prior");
2994  PriorHist->Reset("");
2995  PriorHist->Fill(0.0, 0.0);
2996 
2997  auto rand = std::make_unique<TRandom3>(0);
2998  //KS: Throw nice gaussian, just need big number to have smooth distribution
2999  for(int g = 0; g < 1000000; ++g)
3000  {
3001  PriorHist->Fill(rand->Gaus(Prior, PriorError));
3002  }
3003  }
3004  SavageDickeyPlot(PriorHist, PosteriorHist, std::string(Title), EvaluationPoint[k]);
3005  } //End loop over parameters
3006 
3007  SavageDickeyDir->Close();
3008  delete SavageDickeyDir;
3009 
3010  OutputFile->cd();
3011 }
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.

◆ GetViolin()

TH2D* MCMCProcessor::GetViolin ( ) const
inline

Get Violin plot for all parameters with posterior values.

Definition at line 238 of file MCMCProcessor.h.

238 { return hviolin.get(); };

◆ GetViolinPrior()

TH2D* MCMCProcessor::GetViolinPrior ( ) const
inline

Get Violin plot for all parameters with prior values.

Definition at line 240 of file MCMCProcessor.h.

240 { return hviolin_prior.get(); };

◆ GetXSecCov()

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

Definition at line 243 of file MCMCProcessor.h.

243 { 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 4371 of file MCMCProcessor.cpp.

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

◆ Initialise()

void MCMCProcessor::Initialise ( )

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

Definition at line 142 of file MCMCProcessor.cpp.

142  {
143 // ***************
144  // Scan the ROOT file for useful branches
145  ScanInput();
146 
147  // Setup the output
148  SetupOutput();
149 }
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 353 of file MCMCProcessor.h.

353 {};

◆ 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 946 of file MCMCProcessor.cpp.

946  {
947 // *********************
948  if (OutputFile == nullptr) MakeOutputFile();
949 
950  bool HaveMadeDiagonal = false;
951  MACH3LOG_INFO("Making post-fit covariances...");
952  // Check that the diagonal entries have been filled
953  // i.e. MakePostfit() has been called
954  for (int i = 0; i < nDraw; ++i) {
955  if ((*Covariance)(i,i) == M3::_BAD_DOUBLE_) {
956  HaveMadeDiagonal = false;
957  MACH3LOG_INFO("Have not run diagonal elements in covariance, will do so now by calling MakePostfit()");
958  break;
959  } else {
960  HaveMadeDiagonal = true;
961  }
962  }
963 
964  if (HaveMadeDiagonal == false) {
965  MakePostfit();
966  }
967 
968  TDirectory *PostHistDir = OutputFile->mkdir("Post_2d_hists");
969  PostHistDir->cd();
970  gStyle->SetPalette(55);
971  // Now we are sure we have the diagonal elements, let's make the off-diagonals
972  for (int i = 0; i < nDraw; ++i)
973  {
974  if (i % (nDraw/5) == 0)
976 
977  TString Title_i = "";
978  double Prior_i, PriorError;
979 
980  GetNthParameter(i, Prior_i, PriorError, Title_i);
981 
982  // Loop over the other parameters to get the correlations
983  for (int j = 0; j <= i; ++j) {
984  // Skip the diagonal elements which we've already done above
985  if (j == i) continue;
986 
987  // If this parameter isn't varied
988  if (ParamVaried[j] == false) {
989  (*Covariance)(i,j) = 0.0;
990  (*Covariance)(j,i) = (*Covariance)(i,j);
991  (*Correlation)(i,j) = 0.0;
992  (*Correlation)(j,i) = (*Correlation)(i,j);
993  continue;
994  }
995 
996  TString Title_j = "";
997  double Prior_j, PriorError_j;
998  GetNthParameter(j, Prior_j, PriorError_j, Title_j);
999 
1000  OutputFile->cd();
1001 
1002  // The draw which we want to perform
1003  TString DrawMe = BranchNames[j]+":"+BranchNames[i];
1004 
1005  // TH2F to hold the Correlation
1006  auto hpost_2D = new TH2D(DrawMe, DrawMe,
1007  nBins, hpost[i]->GetXaxis()->GetXmin(), hpost[i]->GetXaxis()->GetXmax(),
1008  nBins, hpost[j]->GetXaxis()->GetXmin(), hpost[j]->GetXaxis()->GetXmax());
1009  hpost_2D->SetMinimum(0);
1010  hpost_2D->GetXaxis()->SetTitle(Title_i);
1011  hpost_2D->GetYaxis()->SetTitle(Title_j);
1012  hpost_2D->GetZaxis()->SetTitle("Steps");
1013 
1014  std::string SelectionStr = StepCut;
1015  if (ReweightPosterior) {
1016  SelectionStr = "(" + StepCut + ")*(" + ReweightName + ")";
1017  }
1018  // The draw command we want, i.e. draw param j vs param i
1019  Chain->Project(DrawMe, DrawMe, SelectionStr.c_str());
1020 
1021  if(ApplySmoothing) hpost_2D->Smooth();
1022  // Get the Covariance for these two parameters
1023  (*Covariance)(i,j) = hpost_2D->GetCovariance();
1024  (*Covariance)(j,i) = (*Covariance)(i,j);
1025 
1026  (*Correlation)(i,j) = hpost_2D->GetCorrelationFactor();
1027  (*Correlation)(j,i) = (*Correlation)(i,j);
1028 
1029  if(printToPDF)
1030  {
1031  //KS: Skip Flux Params
1032  if(ParamType[i] == kXSecPar && ParamType[j] == kXSecPar)
1033  {
1034  if(std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold)
1035  {
1036  Posterior->cd();
1037  hpost_2D->Draw("colz");
1038  Posterior->SetName(hpost_2D->GetName());
1039  Posterior->SetTitle(hpost_2D->GetTitle());
1040  Posterior->Print(CanvasName);
1041  hpost2D[i][j]->Write(hpost2D[i][j]->GetTitle());
1042  }
1043  }
1044  }
1045  // Write it to root file
1046  //OutputFile->cd();
1047  //if( std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold ) hpost_2D->Write();
1048  delete hpost_2D;
1049  } // End j loop
1050  } // End i loop
1051  PostHistDir->Close();
1052  delete PostHistDir;
1053  OutputFile->cd();
1054  Covariance->Write("Covariance");
1055  Correlation->Write("Correlation");
1056 }

◆ 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 1186 of file MCMCProcessor.cpp.

1186  {
1187 // *********************
1188  if (OutputFile == nullptr) MakeOutputFile();
1189 
1190  if(!CacheMCMC) CacheSteps();
1191 
1192  bool HaveMadeDiagonal = false;
1193  // Check that the diagonal entries have been filled
1194  // i.e. MakePostfit() has been called
1195  for (int i = 0; i < nDraw; ++i) {
1196  if ((*Covariance)(i,i) == M3::_BAD_DOUBLE_) {
1197  HaveMadeDiagonal = false;
1198  MACH3LOG_WARN("Have not run diagonal elements in covariance, will do so now by calling MakePostfit()");
1199  break;
1200  } else {
1201  HaveMadeDiagonal = true;
1202  }
1203  }
1204 
1205  if (HaveMadeDiagonal == false) MakePostfit();
1206  TStopwatch clock;
1207  TDirectory *PostHistDir = nullptr;
1208  if(!Mute)
1209  {
1210  MACH3LOG_INFO("Calculating covariance matrix");
1211  clock.Start();
1212  PostHistDir = OutputFile->mkdir("Post_2d_hists");
1213  PostHistDir->cd();
1214  }
1215 
1216  if(!Mute)
1217 
1218  gStyle->SetPalette(55);
1219  // Now we are sure we have the diagonal elements, let's make the off-diagonals
1220  #ifdef MULTITHREAD
1221  #pragma omp parallel for
1222  #endif
1223  for (int i = 0; i < nDraw; ++i)
1224  {
1225  for (int j = 0; j <= i; ++j)
1226  {
1227  // Skip the diagonal elements which we've already done above
1228  if (j == i) continue;
1229 
1230  // If this parameter isn't varied
1231  if (ParamVaried[j] == false) {
1232  (*Covariance)(i,j) = 0.0;
1233  (*Covariance)(j,i) = (*Covariance)(i,j);
1234  (*Correlation)(i,j) = 0.0;
1235  (*Correlation)(j,i) = (*Correlation)(i,j);
1236  continue;
1237  }
1238  hpost2D[i][j]->SetMinimum(0);
1239 
1240  for (int k = 0; k < nEntries; ++k)
1241  {
1242  //KS: Burn in cut
1243  if(StepNumber[k] < BurnInCut) continue;
1244 
1245  const double Weight = ReweightPosterior ? WeightValue[i] : 1.;
1246  //KS: Fill histogram with cached steps
1247  hpost2D[i][j]->Fill(ParStep[i][k], ParStep[j][k], Weight);
1248  }
1249  if(ApplySmoothing) hpost2D[i][j]->Smooth();
1250 
1251  // Get the Covariance for these two parameters
1252  (*Covariance)(i,j) = hpost2D[i][j]->GetCovariance();
1253  (*Covariance)(j,i) = (*Covariance)(i,j);
1254 
1255  //KS: Since we already have covariance consider calculating correlation using it, right now we effectively calculate covariance twice
1256  //https://root.cern.ch/doc/master/TH2_8cxx_source.html#l01099
1257  (*Correlation)(i,j) = hpost2D[i][j]->GetCorrelationFactor();
1258  (*Correlation)(j,i) = (*Correlation)(i,j);
1259  }// End j loop
1260  }// End i loop
1261 
1262  if(!Mute) {
1263  clock.Stop();
1264  MACH3LOG_INFO("Making Covariance took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries);
1265  if(printToPDF)
1266  {
1267  Posterior->cd();
1268  for (int i = 0; i < nDraw; ++i)
1269  {
1270  for (int j = 0; j <= i; ++j)
1271  {
1272  // Skip the diagonal elements which we've already done above
1273  if (j == i) continue;
1274  if (ParamVaried[j] == false) continue;
1275 
1276  if(ParamType[i] == kXSecPar && ParamType[j] == kXSecPar)
1277  {
1278  if(std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold)
1279  {
1280  hpost2D[i][j]->Draw("colz");
1281  Posterior->SetName(hpost2D[i][j]->GetName());
1282  Posterior->SetTitle(hpost2D[i][j]->GetTitle());
1283  Posterior->Print(CanvasName);
1284  hpost2D[i][j]->Write(hpost2D[i][j]->GetTitle());
1285  }
1286  }
1287  //if( std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold) hpost2D[i][j]->Write();
1288  }// End j loop
1289  }// End i loop
1290  } //end if pdf
1291  PostHistDir->Close();
1292  delete PostHistDir;
1293  OutputFile->cd();
1294  Covariance->Write("Covariance");
1295  Correlation->Write("Correlation");
1296  } // end if not mute
1297 }
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 1468 of file MCMCProcessor.cpp.

1468  {
1469 // *********************
1470  MACH3LOG_INFO("Making covariance matrix YAML file");
1471 
1472  if (ParamNames[kXSecPar].size() != static_cast<size_t>(nDraw)) {
1473  MACH3LOG_ERROR("Using Legacy Parameters i.e. not one from Parameter Handler Generic, this will not work");
1474  throw MaCh3Exception(__FILE__, __LINE__);
1475  }
1476  std::vector<double> MeanArray(nDraw);
1477  std::vector<double> ErrorArray(nDraw);
1478  std::vector<std::vector<double>> CorrelationMatrix(nDraw, std::vector<double>(nDraw, 0.0));
1479 
1480  TVectorD* means_vec;
1481  TVectorD* errors_vec;
1482 
1483  if (MeansMethod == "Arithmetic") {
1484  means_vec = Means;
1485  errors_vec = Errors;
1486  } else if (MeansMethod == "Gaussian") {
1487  means_vec = Means_Gauss;
1488  errors_vec = Errors_Gauss;
1489  } else if (MeansMethod == "HPD") {
1490  means_vec = Means_HPD;
1491  errors_vec = Errors_HPD;
1492  } else {
1493  MACH3LOG_ERROR("Unknown means method: {}, should be either 'Arithmetic', 'Gaussian', or 'HPD'.", MeansMethod);
1494  throw MaCh3Exception(__FILE__, __LINE__);
1495  }
1496 
1497  //Make vectors of mean, error, and correlations
1498  for (int i = 0; i < nDraw; i++)
1499  {
1500  MeanArray[i] = (*means_vec)(i);
1501  ErrorArray[i] = (*errors_vec)(i);
1502  for (int j = 0; j <= i; j++)
1503  {
1504  CorrelationMatrix[i][j] = (*Correlation)(i,j);
1505  if(i != j) CorrelationMatrix[j][i] = (*Correlation)(i,j);
1506  }
1507  }
1508 
1509  //Make std::string param name vector
1510  std::vector<std::string> ParamStrings(ParamNames[kXSecPar].size());
1511  for (size_t i = 0; i < ParamNames[kXSecPar].size(); ++i) {
1512  ParamStrings[i] = static_cast<std::string>(ParamNames[kXSecPar][i]);
1513  }
1514 
1515  YAML::Node XSecFile = CovConfig[kXSecPar];
1516  M3::MakeCorrelationMatrix(XSecFile, MeanArray, ErrorArray, CorrelationMatrix, OutputYAMLFile, ParamStrings);
1517 }
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 689 of file MCMCProcessor.cpp.

691  {
692 // *********************
693  if(hpost[0] == nullptr) MakePostfit();
694 
695  MACH3LOG_INFO("Starting {}", __func__);
696  const double LeftMargin = Posterior->GetLeftMargin();
697  Posterior->SetLeftMargin(0.15);
698 
699  // KS: Sanity check of size and ordering is correct
700  CheckCredibleIntervalsOrder(CredibleIntervals, CredibleIntervalsColours);
701  const int nCredible = int(CredibleIntervals.size());
702  std::vector<std::unique_ptr<TH1D>> hpost_copy(nDraw);
703  std::vector<std::vector<std::unique_ptr<TH1D>>> hpost_cl(nDraw);
704 
705  //KS: Copy all histograms to be thread safe
706  for (int i = 0; i < nDraw; ++i)
707  {
708  hpost_copy[i] = M3::Clone<TH1D>(hpost[i], Form("hpost_copy_%i", i));
709  hpost_cl[i].resize(nCredible);
710  for (int j = 0; j < nCredible; ++j)
711  {
712  hpost_cl[i][j] = M3::Clone<TH1D>(hpost[i], Form("hpost_copy_%i_CL_%f", i, CredibleIntervals[j]));
713 
714  //KS: Reset to get rid to TF1 otherwise we run into segfault :(
715  hpost_cl[i][j]->Reset("");
716  hpost_cl[i][j]->Fill(0.0, 0.0);
717  }
718  }
719 
720  #ifdef MULTITHREAD
721  #pragma omp parallel for
722  #endif
723  for (int i = 0; i < nDraw; ++i)
724  {
726  hpost_copy[i]->Scale(1. / hpost_copy[i]->Integral());
727  for (int j = 0; j < nCredible; ++j)
728  {
729  // Scale the histograms before gettindg credible intervals
730  hpost_cl[i][j]->Scale(1. / hpost_cl[i][j]->Integral());
731  GetCredibleIntervalSig(hpost_copy[i], hpost_cl[i][j], CredibleInSigmas, CredibleIntervals[j]);
732 
733  hpost_cl[i][j]->SetFillColor(CredibleIntervalsColours[j]);
734  hpost_cl[i][j]->SetLineWidth(1);
735  }
736  hpost_copy[i]->GetYaxis()->SetTitleOffset(1.8);
737  hpost_copy[i]->SetLineWidth(1);
738  hpost_copy[i]->SetMaximum(hpost_copy[i]->GetMaximum()*1.2);
739  hpost_copy[i]->SetLineWidth(2);
740  hpost_copy[i]->SetLineColor(kBlack);
741  hpost_copy[i]->GetYaxis()->SetTitle("Posterior Probability");
742  }
743 
744  OutputFile->cd();
745  TDirectory *CredibleDir = OutputFile->mkdir("Credible");
746 
747  for (int i = 0; i < nDraw; ++i)
748  {
749  if(!ParamVaried[i]) continue;
750 
751  // Now make the TLine for the Asimov
752  TString Title = "";
753  double Prior = 1.0, PriorError = 1.0;
754  GetNthParameter(i, Prior, PriorError, Title);
755 
756  auto Asimov = std::make_unique<TLine>(Prior, hpost_copy[i]->GetMinimum(), Prior, hpost_copy[i]->GetMaximum());
757  SetTLineStyle(Asimov.get(), kRed-3, 2, kDashed);
758 
759  auto legend = std::make_unique<TLegend>(0.20, 0.7, 0.4, 0.92);
760  SetLegendStyle(legend.get(), 0.03);
761  hpost_copy[i]->Draw("HIST");
762 
763  for (int j = 0; j < nCredible; ++j)
764  hpost_cl[i][j]->Draw("HIST SAME");
765  for (int j = nCredible-1; j >= 0; --j)
766  {
767  if(CredibleInSigmas)
768  legend->AddEntry(hpost_cl[i][j].get(), Form("%.0f#sigma Credible Interval", CredibleIntervals[j]), "f");
769  else
770  legend->AddEntry(hpost_cl[i][j].get(), Form("%.0f%% Credible Interval", CredibleIntervals[j]*100), "f");
771  }
772  legend->AddEntry(Asimov.get(), Form("#splitline{Prior}{x = %.2f , #sigma = %.2f}", Prior, PriorError), "l");
773  legend->Draw("SAME");
774  Asimov->Draw("SAME");
775 
776  // Write to file
777  Posterior->SetName(hpost[i]->GetName());
778  Posterior->SetTitle(hpost[i]->GetTitle());
779 
780  if(printToPDF) Posterior->Print(CanvasName);
781  // cd into directory in root file
782  CredibleDir->cd();
783  Posterior->Write();
784  }
785  CredibleDir->Close();
786  delete CredibleDir;
787 
788  OutputFile->cd();
789 
790  //Set back to normal
791  Posterior->SetLeftMargin(LeftMargin);
792 }
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.
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.

◆ 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 1801 of file MCMCProcessor.cpp.

1806  {
1807 // *********************
1808  if(hpost2D.size() == 0) MakeCovariance_MP();
1809  MACH3LOG_INFO("Making Credible Regions");
1810 
1811  CheckCredibleRegionsOrder(CredibleRegions, CredibleRegionStyle, CredibleRegionColor);
1812  const int nCredible = int(CredibleRegions.size());
1813 
1814  std::vector<std::vector<std::unique_ptr<TH2D>>> hpost_2D_copy(nDraw);
1815  std::vector<std::vector<std::vector<std::unique_ptr<TH2D>>>> hpost_2D_cl(nDraw);
1816  //KS: Copy all histograms to be thread safe
1817  for (int i = 0; i < nDraw; ++i)
1818  {
1819  hpost_2D_copy[i].resize(nDraw);
1820  hpost_2D_cl[i].resize(nDraw);
1821  for (int j = 0; j <= i; ++j)
1822  {
1823  hpost_2D_copy[i][j] = M3::Clone<TH2D>(hpost2D[i][j], Form("hpost_copy_%i_%i", i, j));
1824  hpost_2D_cl[i][j].resize(nCredible);
1825  for (int k = 0; k < nCredible; ++k)
1826  {
1827  hpost_2D_cl[i][j][k] = M3::Clone<TH2D>(hpost2D[i][j], Form("hpost_copy_%i_%i_CL_%f", i, j, CredibleRegions[k]));
1828  }
1829  }
1830  }
1831 
1832  #ifdef MULTITHREAD
1833  #pragma omp parallel for
1834  #endif
1835  //Calculate credible histogram
1836  for (int i = 0; i < nDraw; ++i)
1837  {
1838  for (int j = 0; j <= i; ++j)
1839  {
1840  for (int k = 0; k < nCredible; ++k)
1841  {
1842  GetCredibleRegionSig(hpost_2D_cl[i][j][k], CredibleInSigmas, CredibleRegions[k]);
1843  hpost_2D_cl[i][j][k]->SetLineColor(CredibleRegionColor[k]);
1844  hpost_2D_cl[i][j][k]->SetLineWidth(2);
1845  hpost_2D_cl[i][j][k]->SetLineStyle(CredibleRegionStyle[k]);
1846  }
1847  }
1848  }
1849 
1850  gStyle->SetPalette(51);
1851  for (int i = 0; i < nDraw; ++i)
1852  {
1853  for (int j = 0; j <= i; ++j)
1854  {
1855  // Skip the diagonal elements which we've already done above
1856  if (j == i) continue;
1857  if (ParamVaried[j] == false) continue;
1858 
1859  auto legend = std::make_unique<TLegend>(0.20, 0.7, 0.4, 0.92);
1860  legend->SetTextColor(kRed);
1861  SetLegendStyle(legend.get(), 0.03);
1862 
1863  //Get Best point
1864  auto bestfitM = std::make_unique<TGraph>(1);
1865  const int MaxBin = hpost_2D_copy[i][j]->GetMaximumBin();
1866  int Mbx, Mby, Mbz;
1867  hpost_2D_copy[i][j]->GetBinXYZ(MaxBin, Mbx, Mby, Mbz);
1868  const double Mx = hpost_2D_copy[i][j]->GetXaxis()->GetBinCenter(Mbx);
1869  const double My = hpost_2D_copy[i][j]->GetYaxis()->GetBinCenter(Mby);
1870 
1871  bestfitM->SetPoint(0, Mx, My);
1872  bestfitM->SetMarkerStyle(22);
1873  bestfitM->SetMarkerSize(1);
1874  bestfitM->SetMarkerColor(kMagenta);
1875 
1876  //Plot default 2D posterior
1877 
1878  if(Draw2DPosterior){
1879  hpost_2D_copy[i][j]->Draw("COLZ");
1880  } else{
1881  hpost_2D_copy[i][j]->Draw("AXIS");
1882  }
1883 
1884  //Now credible regions
1885  for (int k = 0; k < nCredible; ++k)
1886  hpost_2D_cl[i][j][k]->Draw("CONT3 SAME");
1887  for (int k = nCredible-1; k >= 0; --k)
1888  {
1889  if(CredibleInSigmas)
1890  legend->AddEntry(hpost_2D_cl[i][j][k].get(), Form("%.0f#sigma Credible Interval", CredibleRegions[k]), "l");
1891  else
1892  legend->AddEntry(hpost_2D_cl[i][j][k].get(), Form("%.0f%% Credible Region", CredibleRegions[k]*100), "l");
1893  }
1894  legend->Draw("SAME");
1895 
1896  if(DrawBestFit){
1897  legend->AddEntry(bestfitM.get(),"Best Fit","p");
1898  bestfitM->Draw("SAME.P");
1899  }
1900 
1901  // Write to file
1902  Posterior->SetName(hpost2D[i][j]->GetName());
1903  Posterior->SetTitle(hpost2D[i][j]->GetTitle());
1904 
1905  //KS: Print only regions with correlation greater than specified value, by default 0.2. This is done to avoid dumping thousands of plots
1906  if(printToPDF && std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold) Posterior->Print(CanvasName);
1907  // Write it to root file
1908  //OutputFile->cd();
1909  //if( std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold ) Posterior->Write();
1910  }
1911  }
1912 
1913  OutputFile->cd();
1914 }
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 194 of file MCMCProcessor.cpp.

194  {
195 // ***************
196  //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
197  auto rand = std::make_unique<TRandom3>(0);
198  const int uniform = int(rand->Uniform(0, 10000));
199  // Open a TCanvas to write the posterior onto
200  Posterior = std::make_unique<TCanvas>(("Posterior" + std::to_string(uniform)).c_str(), ("Posterior" + std::to_string(uniform)).c_str(), 0, 0, 1024, 1024);
201  //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.
202  TCandle::SetScaledViolin(false);
203 
204  Posterior->SetGrid();
205  gStyle->SetOptStat(0);
206  gStyle->SetOptTitle(0);
207  Posterior->SetTickx();
208  Posterior->SetTicky();
209 
210  Posterior->SetBottomMargin(0.1);
211  Posterior->SetTopMargin(0.05);
212  Posterior->SetRightMargin(0.03);
213  Posterior->SetLeftMargin(0.15);
214 
215  //To avoid TCanvas::Print> messages
216  gErrorIgnoreLevel = kWarning;
217 
218  // Output file to write to
219  OutputName = MCMCFile + OutputSuffix +".root";
220 
221  // Output file
222  OutputFile = M3::Open(OutputName, "recreate", __FILE__, __LINE__);
223  OutputFile->cd();
224 }
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 228 of file MCMCProcessor.cpp.

228  {
229 // ****************************
230  // Check if we've already made post-fit
231  if (MadePostfit == true) return;
232  MadePostfit = true;
233 
234  // Check if the output file is ready
235  if (OutputFile == nullptr) MakeOutputFile();
236 
237  MACH3LOG_INFO("MCMCProcessor is making post-fit plots...");
238 
239  int originalErrorLevel = gErrorIgnoreLevel;
240  gErrorIgnoreLevel = kFatal;
241 
242  // Directory for posteriors
243  TDirectory *PostDir = OutputFile->mkdir("Post");
244  TDirectory *PostHistDir = OutputFile->mkdir("Post_1d_hists");
245 
246  //KS: Apply additional Cuts, like mass ordering
247  std::string CutPosterior1D = "";
248  if(Posterior1DCut != "") {
249  CutPosterior1D = StepCut +" && " + Posterior1DCut;
250  } else CutPosterior1D = StepCut;
251 
252  // Apply reweighting
253  if (ReweightPosterior) {
254  CutPosterior1D = "(" + CutPosterior1D + ")*(" + ReweightName + ")";
255  }
256  MACH3LOG_DEBUG("Using following cut {}", CutPosterior1D);
257 
258  // nDraw is number of draws we want to do
259  for (int i = 0; i < nDraw; ++i)
260  {
261  if (i % (nDraw/5) == 0) {
263  }
264  OutputFile->cd();
265  TString Title = "";
266  double Prior = 1.0, PriorError = 1.0;
267  GetNthParameter(i, Prior, PriorError, Title);
268 
269  ParameterEnum ParType = ParamType[i];
270  int ParamTemp = i - ParamTypeStartPos[ParType];
271  bool isFlat = ParamFlat[ParType][ParamTemp];
272 
273  // Get bin edges for histograms
274  double maxi, mini = M3::_BAD_DOUBLE_;
275  if (Edges.find(Title.Data()) != Edges.end()) {
276  mini = Edges.at(Title.Data()).first;
277  maxi = Edges.at(Title.Data()).second;
278  } else {
279  maxi = Chain->GetMaximum(BranchNames[i]);
280  mini = Chain->GetMinimum(BranchNames[i]);
281  }
282  MACH3LOG_DEBUG("Initialising histogram for {} with binning {:.4f}, {:.4f}", Title, mini, maxi);
283  // This holds the posterior density
284  // KS: WARNING do NOT SetDirectory(nullptr) this will cause issue with Project()
285  // I know is tempting to avoid ROOT memory management but please do not.
286  hpost[i] = new TH1D(BranchNames[i], BranchNames[i], nBins, mini, maxi);
287  hpost[i]->SetMinimum(0);
288  hpost[i]->GetYaxis()->SetTitle("Steps");
289  hpost[i]->GetYaxis()->SetNoExponent(false);
290 
291  // Project BranchNames[i] onto hpost, applying stepcut
292  Chain->Project(BranchNames[i], BranchNames[i], CutPosterior1D.c_str());
293 
294  if(ApplySmoothing) hpost[i]->Smooth();
295 
296  (*Central_Value)(i) = Prior;
297 
298  double Mean, Err, Err_p, Err_m;
299  GetArithmetic(hpost[i], Mean, Err);
300  (*Means)(i) = Mean;
301  (*Errors)(i) = Err;
302 
303  GetGaussian(hpost[i], Gauss.get(), Mean, Err);
304  (*Means_Gauss)(i) = Mean;
305  (*Errors_Gauss)(i) = Err;
306 
307  GetHPD(hpost[i], Mean, Err, Err_p, Err_m);
308  (*Means_HPD)(i) = Mean;
309  (*Errors_HPD)(i) = Err;
310  (*Errors_HPD_Positive)(i) = Err_p;
311  (*Errors_HPD_Negative)(i) = Err_m;
312 
313  // Write the results from the projection into the TVectors and TMatrices
314  (*Covariance)(i,i) = (*Errors)(i)*(*Errors)(i);
315  (*Correlation)(i,i) = 1.0;
316 
317  //KS: This need to be before SetMaximum(), this way plot is nicer as line end at the maximum
318  auto hpd = std::make_unique<TLine>((*Means_HPD)(i), hpost[i]->GetMinimum(), (*Means_HPD)(i), hpost[i]->GetMaximum());
319  SetTLineStyle(hpd.get(), kBlack, 2, kSolid);
320 
321  hpost[i]->SetLineWidth(2);
322  hpost[i]->SetLineColor(kBlue-1);
323  hpost[i]->SetMaximum(hpost[i]->GetMaximum()*DrawRange);
324  hpost[i]->SetTitle(Title);
325  hpost[i]->GetXaxis()->SetTitle(hpost[i]->GetTitle());
326 
327  // Now make the TLine for the Asimov
328  auto Asimov = std::make_unique<TLine>(Prior, hpost[i]->GetMinimum(), Prior, hpost[i]->GetMaximum());
329  SetTLineStyle(Asimov.get(), kRed-3, 2, kDashed);
330 
331  auto leg = std::make_unique<TLegend>(0.12, 0.6, 0.6, 0.97);
332  SetLegendStyle(leg.get(), 0.04);
333  leg->AddEntry(hpost[i], Form("#splitline{PDF}{#mu = %.2f, #sigma = %.2f}", hpost[i]->GetMean(), hpost[i]->GetRMS()), "l");
334  leg->AddEntry(Gauss.get(), Form("#splitline{Gauss}{#mu = %.2f, #sigma = %.2f}", Gauss->GetParameter(1), Gauss->GetParameter(2)), "l");
335  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");
336  if(isFlat && !PlotFlatPrior) leg->AddEntry(Asimov.get(), Form("#splitline{Prior}{x = %.2f}", Prior), "l");
337  else leg->AddEntry(Asimov.get(), Form("#splitline{Prior}{x = %.2f , #sigma = %.2f}", Prior, PriorError), "l");
338 
339  // Write to file
340  Posterior->SetName(Title);
341  Posterior->SetTitle(Title);
342 
343  //CW: Don't plot if this is a fixed histogram (i.e. the peak is the whole integral)
344  if (hpost[i]->GetMaximum() == hpost[i]->Integral()*DrawRange)
345  {
346  MACH3LOG_WARN("Found fixed parameter: {} ({}), moving on", Title, i);
347  ParamVaried[i] = false;
348  //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.
349  (*Means_HPD)(i) = Prior;
350  (*Errors_HPD)(i) = PriorError;
351  (*Errors_HPD_Positive)(i) = PriorError;
352  (*Errors_HPD_Negative)(i) = PriorError;
353 
354  (*Means_Gauss)(i) = Prior;
355  (*Errors_Gauss)(i) = PriorError;
356 
357  (*Means)(i) = Prior;
358  (*Errors)(i) = PriorError;
359  continue;
360  }
361 
362  // Store that this parameter is indeed being varied
363  ParamVaried[i] = true;
364 
365  // Draw onto the TCanvas
366  hpost[i]->Draw();
367  hpd->Draw("same");
368  Asimov->Draw("same");
369  leg->Draw("same");
370 
371  if(printToPDF) Posterior->Print(CanvasName);
372 
373  // cd into params directory in root file
374  PostDir->cd();
375  Posterior->Write();
376 
377  hpost[i]->SetName(Title);
378  hpost[i]->SetTitle(Title);
379  PostHistDir->cd();
380  hpost[i]->Write();
381  } // end the for loop over nDraw
382 
383  OutputFile->cd();
384  TTree *SettingsBranch = new TTree("Settings", "Settings");
385  int NDParameters = nParam[kNDPar];
386  SettingsBranch->Branch("NDParameters", &NDParameters);
388  SettingsBranch->Branch("NDParametersStartingPos", &NDParametersStartingPos);
389 
390  SettingsBranch->Branch("NDSamplesBins", &NDSamplesBins);
391  SettingsBranch->Branch("NDSamplesNames", &NDSamplesNames);
392 
393  SettingsBranch->Fill();
394  SettingsBranch->Write();
395  delete SettingsBranch;
396 
397  TDirectory *Names = OutputFile->mkdir("Names");
398  Names->cd();
399  for (std::vector<TString>::iterator it = BranchNames.begin(); it != BranchNames.end(); ++it) {
400  TObjString((*it)).Write();
401  }
402  Names->Close();
403  delete Names;
404 
405  OutputFile->cd();
406  Central_Value->Write("Central_Value");
407  Means->Write("PDF_Means");
408  Errors->Write("PDF_Error");
409  Means_Gauss->Write("Gauss_Means");
410  Errors_Gauss->Write("Gauss_Errors");
411  Means_HPD->Write("Means_HPD");
412  Errors_HPD->Write("Errors_HPD");
413  Errors_HPD_Positive->Write("Errors_HPD_Positive");
414  Errors_HPD_Negative->Write("Errors_HPD_Negative");
415 
416  PostDir->Close();
417  delete PostDir;
418  PostHistDir->Close();
419  delete PostHistDir;
420 
421  // restore original warning setting
422  gErrorIgnoreLevel = originalErrorLevel;
423 } // Have now written the postfit projections
int NDParametersStartingPos
int NDParameters
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
double ** Mean
Definition: RHat.cpp:63
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.

◆ MakePrefit()

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

Prepare prefit histogram for parameter overlay plot.

Definition at line 2406 of file MCMCProcessor.cpp.

2406  {
2407 // *****************************
2408  if (OutputFile == nullptr) MakeOutputFile();
2409 
2410  auto PreFitPlot = std::make_unique<TH1D>("Prefit", "Prefit", nDraw, 0, nDraw);
2411  PreFitPlot->SetDirectory(nullptr);
2412  for (int i = 0; i < PreFitPlot->GetNbinsX() + 1; ++i) {
2413  PreFitPlot->SetBinContent(i+1, 0);
2414  PreFitPlot->SetBinError(i+1, 0);
2415  }
2416 
2417  //KS: Slightly hacky way to get relative to prior or nominal as this is convention we use,
2418  //Only applies for xsec, for other systematic it make no difference
2419  double CentralValueTemp, Central, Error;
2420 
2421  // Set labels and data
2422  for (int i = 0; i < nDraw; ++i)
2423  {
2424  //Those keep which parameter type we run currently and relative number
2425  int ParamEnum = ParamType[i];
2426  int ParamNo = i - ParamTypeStartPos[ParameterEnum(ParamEnum)];
2427  CentralValueTemp = ParamCentral[ParamEnum][ParamNo];
2428  if(plotRelativeToPrior)
2429  {
2430  // Normalise the prior relative the nominal/prior, just the way we get our fit results in MaCh3
2431  if ( CentralValueTemp != 0) {
2432  Central = ParamCentral[ParamEnum][ParamNo] / CentralValueTemp;
2433  Error = ParamErrors[ParamEnum][ParamNo]/CentralValueTemp;
2434  } else {
2435  Central = CentralValueTemp + 1.0;
2436  Error = ParamErrors[ParamEnum][ParamNo];
2437  }
2438  }
2439  else
2440  {
2441  Central = CentralValueTemp;
2442  Error = ParamErrors[ParamEnum][ParamNo];
2443  }
2444  //KS: If plotting error for param with flat prior is turned off and given param really has flat prior set error to 0
2445  if(!PlotFlatPrior && ParamFlat[ParamEnum][ParamNo]) {
2446  Error = 0.;
2447  }
2448  PreFitPlot->SetBinContent(i+1, Central);
2449  PreFitPlot->SetBinError(i+1, Error);
2450  PreFitPlot->GetXaxis()->SetBinLabel(i+1, ParamNames[ParamEnum][ParamNo]);
2451  }
2452  PreFitPlot->SetDirectory(nullptr);
2453 
2454  PreFitPlot->SetFillStyle(1001);
2455  PreFitPlot->SetFillColor(kRed-3);
2456  PreFitPlot->SetMarkerStyle(21);
2457  PreFitPlot->SetMarkerSize(2.4);
2458  PreFitPlot->SetMarkerColor(kWhite);
2459  PreFitPlot->SetLineColor(PreFitPlot->GetFillColor());
2460  PreFitPlot->GetXaxis()->LabelsOption("v");
2461 
2462  return PreFitPlot;
2463 }

◆ MakeSubOptimality()

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

Make and Draw SubOptimality [30].

Author
Henry Wallace

Definition at line 1302 of file MCMCProcessor.cpp.

1302  {
1303 // *********************
1304  //Save burn in cut, at the end of the loop we will return to default values
1305  const int DefaultUpperCut = UpperCut;
1306  const int DefaultBurnInCut = BurnInCut;
1307  bool defaultPrintToPDF = printToPDF;
1308  BurnInCut = 0;
1309  UpperCut = 0;
1310  printToPDF = false;
1311 
1312  //Set via config in future
1313  int MaxStep = nSteps;
1314  int MinStep = 0;
1315  const int IntervalsSize = nSteps/NIntervals;
1316 
1317  MACH3LOG_INFO("Making Suboptimality");
1318  TStopwatch clock;
1319  clock.Start();
1320 
1321  std::unique_ptr<TH1D> SubOptimality = std::make_unique<TH1D>("Suboptimality", "Suboptimality", NIntervals, MinStep, MaxStep);
1322  SubOptimality->SetDirectory(nullptr);
1323  SubOptimality->GetXaxis()->SetTitle("Step");
1324  SubOptimality->GetYaxis()->SetTitle("Suboptimality");
1325  SubOptimality->SetLineWidth(2);
1326  SubOptimality->SetLineColor(kBlue);
1327 
1328  for(int i = 0; i < NIntervals; ++i)
1329  {
1330  //Reset our cov matrix
1332 
1333  //Set threshold for calculating new matrix
1334  UpperCut = i*IntervalsSize;
1335  //Calculate cov matrix
1336  MakeCovariance_MP(true);
1337 
1338  //Calculate eigen values
1339  TMatrixDSymEigen eigen(*Covariance);
1340  TVectorD eigen_values;
1341  eigen_values.ResizeTo(eigen.GetEigenValues());
1342  eigen_values = eigen.GetEigenValues();
1343 
1344  //KS: Converting from ROOT to vector as to make using other libraires (Eigen) easier in future
1345  std::vector<double> EigenValues(eigen_values.GetNrows());
1346  for(unsigned int j = 0; j < EigenValues.size(); j++)
1347  {
1348  EigenValues[j] = eigen_values(j);
1349  }
1350  const double SubOptimalityValue = GetSubOptimality(EigenValues, nDraw);
1351  SubOptimality->SetBinContent(i+1, SubOptimalityValue);
1352  }
1353  clock.Stop();
1354  MACH3LOG_INFO("Making Suboptimality took {:.2f}s to finish for {} steps", clock.RealTime(), nEntries);
1355 
1356  UpperCut = DefaultUpperCut;
1357  BurnInCut = DefaultBurnInCut;
1358  printToPDF = defaultPrintToPDF;
1359 
1360  SubOptimality->Draw("l");
1361  Posterior->SetName(SubOptimality->GetName());
1362  Posterior->SetTitle(SubOptimality->GetTitle());
1363 
1364  if(printToPDF) Posterior->Print(CanvasName);
1365  // Write it to root file
1366  OutputFile->cd();
1367  Posterior->Write();
1368 }
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 1918 of file MCMCProcessor.cpp.

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

◆ MakeViolin()

void MCMCProcessor::MakeViolin ( )

Make and Draw Violin.

Definition at line 796 of file MCMCProcessor.cpp.

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

◆ 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 3296 of file MCMCProcessor.cpp.

3297  {
3298 // **************************
3299  MACH3LOG_INFO("Starting {}", __func__);
3300 
3301  //KS: First we need to find parameter number based on name
3302  for(unsigned int k = 0; k < Names.size(); ++k)
3303  {
3304  //KS: First we need to find parameter number based on name
3305  int ParamNo = GetParamIndexFromName(Names[k]);
3306  if(ParamNo == M3::_BAD_INT_)
3307  {
3308  MACH3LOG_WARN("Couldn't find param {}. Can't reweight Prior", Names[k]);
3309  continue;
3310  }
3311 
3312  const int IntervalsSize = nSteps/NIntervals[k];
3313  // ROOT won't overwrite gifs so we need to delete the file if it's there already
3314  std::string filename = Names[k] + ".gif";
3315  std::ifstream f(filename);
3316  if (f.good()) {
3317  f.close();
3318  int ret = system(fmt::format("rm {}", filename).c_str());
3319  if (ret != 0) {
3320  MACH3LOG_WARN("Error: system call to delete {} failed with code {}", filename, ret);
3321  }
3322  }
3323 
3324  int Counter = 0;
3325  for(int i = NIntervals[k]-1; i >= 0; --i)
3326  {
3327  // This holds the posterior density
3328  // KS: WARNING do not change to smart pointer, it breaks and I don't know why
3329  TH1D* EvePlot = new TH1D(BranchNames[ParamNo], BranchNames[ParamNo], nBins,
3330  hpost[ParamNo]->GetXaxis()->GetXmin(), hpost[ParamNo]->GetXaxis()->GetXmax());
3331  EvePlot->SetMinimum(0);
3332  EvePlot->GetYaxis()->SetTitle("PDF");
3333  EvePlot->GetYaxis()->SetNoExponent(false);
3334 
3335  //KS: Apply additional Cuts, like mass ordering
3336  std::string CutPosterior1D = "step > " + std::to_string(i*IntervalsSize+IntervalsSize);
3337 
3338  // If Posterior1DCut is not empty, append it
3339  if (!Posterior1DCut.empty()) {
3340  CutPosterior1D += " && " + Posterior1DCut;
3341  }
3342 
3343  // Apply reweighting if requested
3344  if (ReweightPosterior) {
3345  CutPosterior1D = "(" + CutPosterior1D + ")*(" + ReweightName + ")";
3346  }
3347 
3348  std::string TextTitle = "Steps = 0 - "+std::to_string(Counter*IntervalsSize+IntervalsSize);
3349  // Project BranchNames[ParamNo] onto hpost, applying stepcut
3350  Chain->Project(BranchNames[ParamNo], BranchNames[ParamNo], CutPosterior1D.c_str());
3351 
3352  EvePlot->SetLineWidth(2);
3353  EvePlot->SetLineColor(kBlue-1);
3354  EvePlot->SetTitle(Names[k].c_str());
3355  EvePlot->GetXaxis()->SetTitle(EvePlot->GetTitle());
3356  EvePlot->GetYaxis()->SetLabelOffset(1000);
3357  if(ApplySmoothing) EvePlot->Smooth();
3358 
3359  EvePlot->Scale(1. / EvePlot->Integral());
3360  EvePlot->Draw("HIST");
3361 
3362  TText text(0.3, 0.8, TextTitle.c_str());
3363  text.SetTextFont (43);
3364  text.SetTextSize (40);
3365  text.SetNDC(true);
3366  text.Draw("SAME");
3367 
3368  if(i == 0) Posterior->Print((Names[k] + ".gif++20").c_str()); // produces infinite loop animated GIF
3369  else Posterior->Print((Names[k] + ".gif+20").c_str()); // add picture to .gif
3370  delete EvePlot;
3371  Counter++;
3372  }
3373  }
3374 }

◆ ParamTraces()

void MCMCProcessor::ParamTraces ( )
protected

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

Definition at line 3564 of file MCMCProcessor.cpp.

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

◆ 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 4251 of file MCMCProcessor.cpp.

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

◆ PrepareDiagMCMC()

void MCMCProcessor::PrepareDiagMCMC ( )
protected

CW: Prepare branches etc. for DiagMCMC.

Definition at line 3408 of file MCMCProcessor.cpp.

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

◆ PrintInfo()

void MCMCProcessor::PrintInfo ( ) const
protected

Print info like how many params have been loaded etc.

Definition at line 4607 of file MCMCProcessor.cpp.

4607  {
4608 // **************************
4609  // KS: Create a map to store the counts of unique strings
4610  std::unordered_map<std::string, int> paramCounts;
4611  std::vector<std::string> orderedKeys;
4612 
4613  for (const std::string& param : ParameterGroup) {
4614  if (paramCounts[param] == 0) {
4615  orderedKeys.push_back(param); // preserve order of first appearance
4616  }
4617  paramCounts[param]++;
4618  }
4619 
4620  MACH3LOG_INFO("************************************************");
4621  MACH3LOG_INFO("Scanning output branches...");
4622  MACH3LOG_INFO("# Useful entries in tree: \033[1;32m {} \033[0m ", nDraw);
4623  MACH3LOG_INFO("# Model params: \033[1;32m {} starting at {} \033[0m ", nParam[kXSecPar], ParamTypeStartPos[kXSecPar]);
4624  MACH3LOG_INFO("# With following groups: ");
4625  for (const std::string& key : orderedKeys) {
4626  MACH3LOG_INFO(" # {} params: {}", key, paramCounts[key]);
4627  }
4628  MACH3LOG_INFO("# ND params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kNDPar], ParamTypeStartPos[kNDPar]);
4629  MACH3LOG_INFO("# FD params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kFDDetPar], ParamTypeStartPos[kFDDetPar]);
4630  MACH3LOG_INFO("************************************************");
4631 }

◆ ProduceChi2()

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

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

Definition at line 1770 of file MCMCProcessor.cpp.

1770  {
1771 // *********************
1772  if(GroupName == "") return;
1773  MACH3LOG_INFO("Starting {}", __func__);
1774  TDirectory* Chi2Folder = OutputFile->mkdir("DeltaChi2");
1775 
1776  Chi2Folder->cd();
1777  for (int iPar = 0; iPar < nDraw; iPar++)
1778  {
1779  std::string GroupNameCurr;
1780  if(ParamType[iPar] == kXSecPar){
1781  const int InternalNumeration = iPar - ParamTypeStartPos[kXSecPar];
1782  GroupNameCurr = ParameterGroup[InternalNumeration];
1783  } else {
1784  GroupNameCurr = "Other"; // Use Other for all legacy params
1785  }
1786  if (ParamVaried[iPar] == false) continue;
1787  if (GroupName != "All" && GroupNameCurr != GroupName) continue;
1788 
1789  auto Chi2 = GetDeltaChi2(hpost[iPar]);
1790  RemoveFitter(Chi2.get(), "Gauss");
1791 
1792  Chi2->Write();
1793  }
1794  Chi2Folder->Close();
1795  delete Chi2Folder;
1796  OutputFile->cd();
1797 }
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 2696 of file MCMCProcessor.cpp.

2696  {
2697 // ***************
2698  // Do the same for the FD
2699  TFile *FDdetFile = M3::Open(CovPos[kFDDetPar].back(), "open", __FILE__, __LINE__);
2700  FDdetFile->cd();
2701 
2702  TMatrixD *FDdetMatrix = FDdetFile->Get<TMatrixD>(CovNamePos[kFDDetPar].c_str());
2703 
2704  for (int i = 0; i < FDdetMatrix->GetNrows(); ++i)
2705  {
2706  //KS: FD parameters start at 1. in contrary to ND280
2707  ParamCentral[kFDDetPar].push_back(1.);
2708 
2709  ParamErrors[kFDDetPar].push_back( std::sqrt((*FDdetMatrix)(i,i)) );
2710  ParamNames[kFDDetPar].push_back( Form("FD Det %i", i) );
2711 
2712  //KS: Currently we can only set it via config, change it in future
2713  ParamFlat[kFDDetPar].push_back( false );
2714  }
2715  //KS: The last parameter is p scale
2716  //ETA: we need to be careful here, this is only true for SK in the T2K beam analysis...
2717  if(FancyPlotNames) ParamNames[kFDDetPar].back() = "Momentum Scale";
2718 
2719  FDdetFile->Close();
2720  delete FDdetFile;
2721  delete FDdetMatrix;
2722 }

◆ 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 2468 of file MCMCProcessor.cpp.

2468  {
2469 // **************************
2470  FindInputFiles();
2471  if(CovPos[kXSecPar].back() != "none") ReadModelFile();
2472 }
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 2477 of file MCMCProcessor.cpp.

2477  {
2478 // **************************
2480  if(nParam[kNDPar] > 0) ReadNDFile();
2481  if(nParam[kFDDetPar] > 0) ReadFDFile();
2482 }
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 2599 of file MCMCProcessor.cpp.

2599  {
2600 // ***************
2601  YAML::Node XSecFile = CovConfig[kXSecPar];
2602 
2603  auto systematics = XSecFile["Systematics"];
2604  int paramIndex = 0;
2605  for (auto it = systematics.begin(); it != systematics.end(); ++it, ++paramIndex )
2606  {
2607  auto const &param = *it;
2608  // Push back the name
2609  std::string ParName = (param["Systematic"]["Names"]["FancyName"].as<std::string>());
2610  std::string Group = param["Systematic"]["ParameterGroup"].as<std::string>();
2611 
2612  bool rejected = false;
2613  for (unsigned int ik = 0; ik < ExcludedNames.size(); ++ik)
2614  {
2615  if (ParName.rfind(ExcludedNames[ik], 0) == 0)
2616  {
2617  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2618  rejected = true;
2619  break;
2620  }
2621  }
2622  for (unsigned int ik = 0; ik < ExcludedGroups.size(); ++ik)
2623  {
2624  if (Group == ExcludedGroups[ik])
2625  {
2626  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2627  rejected = true;
2628  break;
2629  }
2630  }
2631  if(rejected) continue;
2632 
2633  ParamNames[kXSecPar].push_back(ParName);
2634  ParamCentral[kXSecPar].push_back(param["Systematic"]["ParameterValues"]["PreFitValue"].as<double>());
2635  ParamErrors[kXSecPar].push_back(param["Systematic"]["Error"].as<double>() );
2636  ParamFlat[kXSecPar].push_back(GetFromManager<bool>(param["Systematic"]["FlatPrior"], false));
2637 
2638  ParameterGroup.push_back(Group);
2639 
2640  nParam[kXSecPar]++;
2641  ParamType.push_back(kXSecPar);
2642  // Params from osc group have branch name equal to fancy name while all others are basically xsec_0 for example
2643  if(ParameterGroup.back() == "Osc") {
2644  BranchNames.push_back(ParamNames[kXSecPar].back());
2645  } else {
2646  BranchNames.push_back("param_" + std::to_string(paramIndex));
2647  }
2648 
2649  // Check that the branch exists before setting address
2650  if (!Chain->GetBranch(BranchNames.back())) {
2651  MACH3LOG_WARN("Couldn't find branch '{}', if you are not planning to draw posteriors this might be fine", BranchNames.back());
2652  }
2653  }
2654 }
std::vector< std::string > ExcludedNames
std::vector< std::string > ExcludedGroups

◆ 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 2658 of file MCMCProcessor.cpp.

2658  {
2659 // ***************
2660  // Do the same for the ND280
2661  TFile *NDdetFile = M3::Open(CovPos[kNDPar].back(), "open", __FILE__, __LINE__);
2662  NDdetFile->cd();
2663 
2664  TMatrixDSym *NDdetMatrix = NDdetFile->Get<TMatrixDSym>(CovNamePos[kNDPar].c_str());
2665  TVectorD *NDdetNominal = NDdetFile->Get<TVectorD>("det_weights");
2666  TDirectory *BinningDirectory = NDdetFile->Get<TDirectory>("Binning");
2667 
2668  for (int i = 0; i < NDdetNominal->GetNrows(); ++i)
2669  {
2670  ParamCentral[kNDPar].push_back( (*NDdetNominal)(i) );
2671 
2672  ParamErrors[kNDPar].push_back( std::sqrt((*NDdetMatrix)(i,i)) );
2673  ParamNames[kNDPar].push_back( Form("ND Det %i", i) );
2674  //KS: Currently we can only set it via config, change it in future
2675  ParamFlat[kNDPar].push_back( false );
2676  }
2677 
2678  TIter next(BinningDirectory->GetListOfKeys());
2679  TKey *key = nullptr;
2680  // Loop through all entries
2681  while ((key = static_cast<TKey*>(next())))
2682  {
2683  std::string name = std::string(key->GetName());
2684  TH2Poly* RefPoly = BinningDirectory->Get<TH2Poly>((name).c_str());
2685  int size = RefPoly->GetNumberOfBins();
2686  NDSamplesBins.push_back(size);
2687  NDSamplesNames.push_back(RefPoly->GetTitle());
2688  }
2689 
2690  NDdetFile->Close();
2691  delete NDdetFile;
2692 }

◆ Reset2DPosteriors()

void MCMCProcessor::Reset2DPosteriors ( )

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

Definition at line 2791 of file MCMCProcessor.cpp.

2791  {
2792 // **************************************************
2793  #ifdef MULTITHREAD
2794  #pragma omp parallel for
2795  #endif
2796  for (int i = 0; i < nDraw; ++i)
2797  {
2798  for (int j = 0; j <= i; ++j)
2799  {
2800  // TH2D to hold the Correlation
2801  hpost2D[i][j]->Reset("");
2802  hpost2D[i][j]->Fill(0.0, 0.0, 0.0);
2803  }
2804  }
2805 }

◆ ReweightPrior()

void MCMCProcessor::ReweightPrior ( const std::vector< std::string > &  Names,
const std::vector< double > &  NewCentral,
const std::vector< double > &  NewError 
)

Reweight Prior by giving new central value and new error.

Parameters
NamesParameter names for which we do reweighting
NewCentralNew central value for which we reweight
NewErrorNew error used for calculating weight

Definition at line 3077 of file MCMCProcessor.cpp.

3079  {
3080 // **************************
3081  MACH3LOG_INFO("Reweighting Prior");
3082 
3083  if( (Names.size() != NewCentral.size()) || (NewCentral.size() != NewError.size()))
3084  {
3085  MACH3LOG_ERROR("Size of passed vectors doesn't match in {}", __func__);
3086  throw MaCh3Exception(__FILE__ , __LINE__ );
3087  }
3088  std::vector<int> Param;
3089  std::vector<double> OldCentral;
3090  std::vector<double> OldError;
3091  std::vector<bool> FlatPrior;
3092 
3093  //KS: First we need to find parameter number based on name
3094  for(unsigned int k = 0; k < Names.size(); ++k)
3095  {
3096  //KS: First we need to find parameter number based on name
3097  int ParamNo = GetParamIndexFromName(Names[k]);
3098  if(ParamNo == M3::_BAD_INT_)
3099  {
3100  MACH3LOG_WARN("Couldn't find param {}. Can't reweight Prior", Names[k]);
3101  return;
3102  }
3103 
3104  TString Title = "";
3105  double Prior = 1.0, PriorError = 1.0;
3106  GetNthParameter(ParamNo, Prior, PriorError, Title);
3107 
3108  Param.push_back(ParamNo);
3109  OldCentral.push_back(Prior);
3110  OldError.push_back(PriorError);
3111 
3112  ParameterEnum ParType = ParamType[ParamNo];
3113  int ParamTemp = ParamNo - ParamTypeStartPos[ParType];
3114 
3115  FlatPrior.push_back(ParamFlat[ParType][ParamTemp]);
3116  }
3117  std::vector<double> ParameterPos(Names.size());
3118 
3119  std::string InputFile = MCMCFile+".root";
3120  std::string OutputFilename = MCMCFile + "_reweighted.root";
3121 
3122  //KS: Simply create copy of file and add there new branch
3123  int ret = system(("cp " + InputFile + " " + OutputFilename).c_str());
3124  if (ret != 0)
3125  MACH3LOG_WARN("Error: system call to copy file failed with code {}", ret);
3126 
3127  TFile *OutputChain = M3::Open(OutputFilename, "UPDATE", __FILE__, __LINE__);
3128  OutputChain->cd();
3129  TTree *post = OutputChain->Get<TTree>("posteriors");
3130 
3131  double Weight = 1.;
3132 
3133  post->SetBranchStatus("*",false);
3134  // Set the branch addresses for params
3135  for (unsigned int j = 0; j < Names.size(); ++j) {
3136  post->SetBranchStatus(BranchNames[Param[j]].Data(), true);
3137  post->SetBranchAddress(BranchNames[Param[j]].Data(), &ParameterPos[j]);
3138  }
3139  TBranch *bpt = post->Branch("Weight", &Weight, "Weight/D");
3140  post->SetBranchStatus("Weight", true);
3141 
3142  for (int i = 0; i < nEntries; ++i)
3143  {
3144  if(i % (nEntries/10) == 0) M3::Utils::PrintProgressBar(i, nEntries);
3145  post->GetEntry(i);
3146  Weight = 1.;
3147 
3148  //KS: Calculate reweight weight. Weights are multiplicative so we can do several reweights at once. FIXME Big limitation is that code only works for uncorrelated parameters :(
3149  for (unsigned int j = 0; j < Names.size(); ++j)
3150  {
3151  double new_chi = (ParameterPos[j] - NewCentral[j])/NewError[j];
3152  double new_prior = std::exp(-0.5 * new_chi * new_chi);
3153 
3154  double old_chi = -1;
3155  double old_prior = -1;
3156  if(FlatPrior[j]) {
3157  old_prior = 1.0;
3158  } else {
3159  old_chi = (ParameterPos[j] - OldCentral[j])/OldError[j];
3160  old_prior = std::exp(-0.5 * old_chi * old_chi);
3161  }
3162  Weight *= new_prior/old_prior;
3163  }
3164  bpt->Fill();
3165  }
3166  post->SetBranchStatus("*",true);
3167  OutputChain->cd();
3168  post->Write("posteriors", TObject::kOverwrite);
3169 
3170  // KS: Save reweight metadeta
3171  std::ostringstream yaml_stream;
3172  yaml_stream << "Weight:\n";
3173  yaml_stream << " ReweightDim: 1\n";
3174  yaml_stream << " ReweightType: \"Gaussian\"\n";
3175  yaml_stream << " ReweightVar: [";
3176  for (size_t k = 0; k < Names.size(); ++k) {
3177  yaml_stream << "\"" << Names[k] << "\"";
3178  if (k < Names.size() - 1) yaml_stream << ", ";
3179  }
3180  yaml_stream << "]\n";
3181  yaml_stream << " ReweightPrior: [";
3182  for (size_t k = 0; k < Names.size(); ++k) {
3183  yaml_stream << "[" << NewCentral[k] << ", " << NewError[k] << "]";
3184  if (k < Names.size() - 1) yaml_stream << ", ";
3185  }
3186  yaml_stream << "]\n";
3187  std::string yaml_string = yaml_stream.str();
3188  YAML::Node root = STRINGtoYAML(yaml_string);
3189  TMacro ConfigSave = YAMLtoTMacro(root, "Reweight_Config");
3190  ConfigSave.Write();
3191 
3192  OutputChain->Close();
3193  delete OutputChain;
3194 
3195  OutputFile->cd();
3196 }
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Definition: YamlHelper.h:167
YAML::Node STRINGtoYAML(const std::string &yaml_string)
Function to convert a YAML string to a YAML node.
Definition: YamlHelper.h:97

◆ 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 3015 of file MCMCProcessor.cpp.

3018  {
3019 // **************************
3020  // Area normalise the distributions
3021  PriorHist->Scale(1./PriorHist->Integral(), "width");
3022  PosteriorHist->Scale(1./PosteriorHist->Integral(), "width");
3023 
3024  PriorHist->SetLineColor(kRed);
3025  PriorHist->SetMarkerColor(kRed);
3026  PriorHist->SetFillColorAlpha(kRed, 0.35);
3027  PriorHist->SetFillStyle(1001);
3028  PriorHist->GetXaxis()->SetTitle(Title.c_str());
3029  PriorHist->GetYaxis()->SetTitle("Posterior Probability");
3030  PriorHist->SetMaximum(PosteriorHist->GetMaximum()*1.5);
3031  PriorHist->GetYaxis()->SetLabelOffset(999);
3032  PriorHist->GetYaxis()->SetLabelSize(0);
3033  PriorHist->SetLineWidth(2);
3034  PriorHist->SetLineStyle(kSolid);
3035 
3036  PosteriorHist->SetLineColor(kBlue);
3037  PosteriorHist->SetMarkerColor(kBlue);
3038  PosteriorHist->SetFillColorAlpha(kBlue, 0.35);
3039  PosteriorHist->SetFillStyle(1001);
3040 
3041  PriorHist->Draw("hist");
3042  PosteriorHist->Draw("hist same");
3043 
3044  double ProbPrior = PriorHist->GetBinContent(PriorHist->FindBin(EvaluationPoint));
3045  //KS: In case we go so far away that prior is 0, set this to small value to avoid dividing by 0
3046  if(ProbPrior < 0) ProbPrior = 0.00001;
3047  double ProbPosterior = PosteriorHist->GetBinContent(PosteriorHist->FindBin(EvaluationPoint));
3048  double SavageDickey = ProbPosterior/ProbPrior;
3049 
3050  std::string DunneKabothScale = GetDunneKaboth(SavageDickey);
3051  //Get Best point
3052  auto PostPoint = std::make_unique<TGraph>(1);
3053  PostPoint->SetPoint(0, EvaluationPoint, ProbPosterior);
3054  PostPoint->SetMarkerStyle(20);
3055  PostPoint->SetMarkerSize(1);
3056  PostPoint->Draw("P same");
3057 
3058  auto PriorPoint = std::make_unique<TGraph>(1);
3059  PriorPoint->SetPoint(0, EvaluationPoint, ProbPrior);
3060  PriorPoint->SetMarkerStyle(20);
3061  PriorPoint->SetMarkerSize(1);
3062  PriorPoint->Draw("P same");
3063 
3064  auto legend = std::make_unique<TLegend>(0.12, 0.6, 0.6, 0.97);
3065  SetLegendStyle(legend.get(), 0.04);
3066  legend->AddEntry(PriorHist.get(), "Prior", "l");
3067  legend->AddEntry(PosteriorHist.get(), "Posterior", "l");
3068  legend->AddEntry(PostPoint.get(), Form("SavageDickey = %.2f, (%s)", SavageDickey, DunneKabothScale.c_str()),"");
3069  legend->Draw("same");
3070 
3071  Posterior->Print(CanvasName);
3072  Posterior->Write(Title.c_str());
3073 }

◆ ScanInput()

void MCMCProcessor::ScanInput ( )
protected

Scan Input etc.

Definition at line 2228 of file MCMCProcessor.cpp.

2228  {
2229 // **************************
2230  // KS: This can reduce time necessary for caching even by half
2231  #ifdef MULTITHREAD
2232  //ROOT::EnableImplicitMT();
2233  #endif
2234 
2235  // Open the Chain
2236  Chain = new TChain("posteriors","posteriors");
2237  Chain->Add(MCMCFile.c_str());
2238 
2239  nEntries = int(Chain->GetEntries());
2240 
2241  //Only is suboptimality we might want to change it, therefore set it high enough so it doesn't affect other functionality
2242  UpperCut = nEntries+1;
2243 
2244  // Get the list of branches
2245  TObjArray* brlis = Chain->GetListOfBranches();
2246 
2247  // Get the number of branches
2248  nBranches = brlis->GetEntries();
2249 
2250  BranchNames.reserve(nBranches);
2251  ParamType.reserve(nBranches);
2252 
2253  // Read the input Covariances
2254  ReadInputCov();
2255 
2256  // Set all the branches to off
2257  Chain->SetBranchStatus("*", false);
2258 
2259  // Loop over the number of branches
2260  // Find the name and how many of each systematic we have
2261  for (int i = 0; i < nBranches; i++)
2262  {
2263  // Get the TBranch and its name
2264  TBranch* br = static_cast<TBranch*>(brlis->At(i));
2265  if(!br){
2266  MACH3LOG_ERROR("Invalid branch at position {}", i);
2267  throw MaCh3Exception(__FILE__,__LINE__);
2268  }
2269  TString bname = br->GetName();
2270 
2271  //KS: Exclude parameter types
2272  bool rejected = false;
2273  for(unsigned int ik = 0; ik < ExcludedTypes.size(); ++ik )
2274  {
2275  if(bname.BeginsWith(ExcludedTypes[ik]))
2276  {
2277  rejected = true;
2278  break;
2279  }
2280  }
2281  if(rejected) continue;
2282 
2283  // Turn on the branches which we want for parameters
2284  Chain->SetBranchStatus(bname.Data(), true);
2285 
2286  if (bname.BeginsWith("ndd_"))
2287  {
2288  BranchNames.push_back(bname);
2289  ParamType.push_back(kNDPar);
2290  nParam[kNDPar]++;
2291  }
2292  else if (bname.BeginsWith("skd_joint_"))
2293  {
2294  BranchNames.push_back(bname);
2295  ParamType.push_back(kFDDetPar);
2296  nParam[kFDDetPar]++;
2297  }
2298 
2299  //KS: as a bonus get LogL systematic
2300  if (bname.BeginsWith("LogL_sample_")) {
2301  SampleName_v.push_back(bname);
2302  }
2303  else if (bname.BeginsWith("LogL_systematic_")) {
2304  SystName_v.push_back(bname);
2305  }
2306  }
2307  nDraw = int(BranchNames.size());
2308 
2309  // Read the input Covariances
2311 
2312  // Check order of parameter types
2314 
2315  ParamVaried.resize(nDraw, true);
2316 
2317  // Print useful Info
2318  PrintInfo();
2319 
2320  nSteps = Chain->GetMaximum("step");
2321  // Set the step cut to be 20%
2322  int cut = nSteps/5;
2323  SetStepCut(cut);
2324 
2325  // Basically allow loading oscillation parameters
2327 }
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 2388 of file MCMCProcessor.cpp.

2388  {
2389 // *****************************
2390  for(int i = 0; i < kNParameterEnum; i++)
2391  {
2392  for(unsigned int j = 0; j < ParamType.size(); j++)
2393  {
2394  if(ParamType[j] == ParameterEnum(i))
2395  {
2396  //KS: When we find that i-th parameter types start at j, save and move to the next parameter.
2397  ParamTypeStartPos[i] = j;
2398  break;
2399  }
2400  }
2401  }
2402 }

◆ 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 271 of file MCMCProcessor.h.

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

◆ 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 4666 of file MCMCProcessor.cpp.

4666  {
4667 // **************************
4668  Legend->SetTextSize(size);
4669  Legend->SetLineColor(0);
4670  Legend->SetLineStyle(0);
4671  Legend->SetFillColor(0);
4672  Legend->SetFillStyle(0);
4673  Legend->SetBorderSize(0);
4674 }

◆ SetMargins()

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

Set TCanvas margins to specified values.

Definition at line 4641 of file MCMCProcessor.cpp.

4641  {
4642 // **************************
4643  if (!Canv) {
4644  MACH3LOG_ERROR("Canv is nullptr");
4645  throw MaCh3Exception(__FILE__, __LINE__);
4646  }
4647  if (margins.size() != 4) {
4648  MACH3LOG_ERROR("Margin vector must have exactly 4 elements");
4649  throw MaCh3Exception(__FILE__, __LINE__);
4650  }
4651  Canv->SetTopMargin(margins[0]);
4652  Canv->SetBottomMargin(margins[1]);
4653  Canv->SetLeftMargin(margins[2]);
4654  Canv->SetRightMargin(margins[3]);
4655 }

◆ 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 267 of file MCMCProcessor.h.

267 {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; };

◆ 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 2736 of file MCMCProcessor.cpp.

2736  {
2737 // ***************
2738  std::stringstream TempStream;
2739  TempStream << "step > " << Cuts;
2740  StepCut = TempStream.str();
2741  BurnInCut = Cuts;
2742  CheckStepCut();
2743 }
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 2726 of file MCMCProcessor.cpp.

2726  {
2727 // ***************
2728  StepCut = Cuts;
2729  BurnInCut = std::stoi( Cuts );
2730 
2731  CheckStepCut();
2732 }

◆ 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 4658 of file MCMCProcessor.cpp.

4658  {
4659 // **************************
4660  Line->SetLineColor(Colour);
4661  Line->SetLineWidth(Width);
4662  Line->SetLineStyle(Style);
4663 }
constexpr ELineStyle Style[NVars]

◆ SetupOutput()

void MCMCProcessor::SetupOutput ( )
protected

Prepare all objects used for output.

Definition at line 2331 of file MCMCProcessor.cpp.

2331  {
2332 // ****************************
2333  // Make sure we can read files located anywhere and strip the .root ending
2334  MCMCFile = MCMCFile.substr(0, MCMCFile.find(".root"));
2335 
2336  // Check if the output file is ready
2337  if (OutputFile == nullptr) MakeOutputFile();
2338 
2339  CanvasName = MCMCFile + OutputSuffix + ".pdf[";
2340  if(printToPDF) Posterior->Print(CanvasName);
2341 
2342  // Once the pdf file is open no longer need to bracket
2343  CanvasName.ReplaceAll("[","");
2344 
2345  // We fit with this Gaussian
2346  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);
2347  Gauss->SetLineWidth(2);
2348  Gauss->SetLineColor(kOrange-5);
2349 
2350  // Declare the TVectors
2351  Covariance = new TMatrixDSym(nDraw);
2352  Correlation = new TMatrixDSym(nDraw);
2353  Central_Value = new TVectorD(nDraw);
2354  Means = new TVectorD(nDraw);
2355  Errors = new TVectorD(nDraw);
2356  Means_Gauss = new TVectorD(nDraw);
2357  Errors_Gauss = new TVectorD(nDraw);
2358  Means_HPD = new TVectorD(nDraw);
2359  Errors_HPD = new TVectorD(nDraw);
2360  Errors_HPD_Positive = new TVectorD(nDraw);
2361  Errors_HPD_Negative = new TVectorD(nDraw);
2362 
2363  // Initialise to something silly
2364  #ifdef MULTITHREAD
2365  #pragma omp parallel for
2366  #endif
2367  for (int i = 0; i < nDraw; ++i)
2368  {
2369  (*Central_Value)(i) = M3::_BAD_DOUBLE_;
2370  (*Means)(i) = M3::_BAD_DOUBLE_;
2371  (*Errors)(i) = M3::_BAD_DOUBLE_;
2372  (*Means_Gauss)(i) = M3::_BAD_DOUBLE_;
2373  (*Errors_Gauss)(i) = M3::_BAD_DOUBLE_;
2374  (*Means_HPD)(i) = M3::_BAD_DOUBLE_;
2375  (*Errors_HPD)(i) = M3::_BAD_DOUBLE_;
2376  (*Errors_HPD_Positive)(i) = M3::_BAD_DOUBLE_;
2377  (*Errors_HPD_Negative)(i) = M3::_BAD_DOUBLE_;
2378  for (int j = 0; j < nDraw; ++j) {
2379  (*Covariance)(i, j) = M3::_BAD_DOUBLE_;
2380  (*Correlation)(i, j) = M3::_BAD_DOUBLE_;
2381  }
2382  }
2383  hpost.resize(nDraw);
2384 }

◆ 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 3201 of file MCMCProcessor.cpp.

3203  {
3204 // **************************
3205  MACH3LOG_INFO("Starting {}", __func__);
3206 
3207  if( (Names.size() != Error.size()))
3208  {
3209  MACH3LOG_ERROR("Size of passed vectors doesn't match in {}", __func__);
3210  throw MaCh3Exception(__FILE__ , __LINE__ );
3211  }
3212  std::vector<int> Param;
3213 
3214  //KS: First we need to find parameter number based on name
3215  for(unsigned int k = 0; k < Names.size(); ++k)
3216  {
3217  //KS: First we need to find parameter number based on name
3218  int ParamNo = GetParamIndexFromName(Names[k]);
3219  if(ParamNo == M3::_BAD_INT_)
3220  {
3221  MACH3LOG_WARN("Couldn't find param {}. Can't Smear", Names[k]);
3222  return;
3223  }
3224 
3225  TString Title = "";
3226  double Prior = 1.0, PriorError = 1.0;
3227  GetNthParameter(ParamNo, Prior, PriorError, Title);
3228 
3229  Param.push_back(ParamNo);
3230  }
3231  std::string InputFile = MCMCFile+".root";
3232  std::string OutputFilename = MCMCFile + "_smeared.root";
3233 
3234  //KS: Simply create copy of file and add there new branch
3235  int ret = system(("cp " + InputFile + " " + OutputFilename).c_str());
3236  if (ret != 0)
3237  MACH3LOG_WARN("Error: system call to copy file failed with code {}", ret);
3238 
3239  TFile *OutputChain = M3::Open(OutputFilename, "UPDATE", __FILE__, __LINE__);
3240  OutputChain->cd();
3241  TTree *post = OutputChain->Get<TTree>("posteriors");
3242  TTree *treeNew = post->CloneTree(0);
3243 
3244  std::vector<double> NewParameter(Names.size());
3245  for(size_t i = 0; i < Param.size(); i++) {
3246  post->SetBranchAddress(BranchNames[Param[i]], &NewParameter[i]);
3247  }
3248 
3249  std::vector<double> Unsmeared_Parameter;
3250  if(SaveBranch){
3251  Unsmeared_Parameter.resize(Param.size());
3252  for(size_t i = 0; i < Param.size(); i++) {
3253  treeNew->Branch((BranchNames[Param[i]] + "_unsmeared"), &Unsmeared_Parameter[i]);
3254  }
3255  }
3256 
3257  auto rand = std::make_unique<TRandom3>(0);
3258  Long64_t AllEntries = post->GetEntries();
3259  for (Long64_t i = 0; i < AllEntries; ++i) {
3260  // Entry from the old chain
3261  post->GetEntry(i);
3262 
3263  if(SaveBranch){
3264  for(size_t iPar = 0; iPar < Param.size(); iPar++) {
3265  Unsmeared_Parameter[iPar] = NewParameter[iPar];
3266  }
3267  }
3268  // Smear it
3269  for(size_t iPar = 0; iPar < Param.size(); iPar++) {
3270  NewParameter[iPar] = NewParameter[iPar] + rand->Gaus(0, Error[iPar]);
3271  }
3272  // Fill to the new chain
3273  treeNew->Fill();
3274  }
3275 
3276  OutputChain->cd();
3277  treeNew->Write("posteriors", TObject::kOverwrite);
3278 
3279  // KS: Save reweight metadeta
3280  std::ostringstream yaml_stream;
3281  yaml_stream << "Smearing:\n";
3282  for (size_t k = 0; k < Names.size(); ++k) {
3283  yaml_stream << " " << Names[k] << ": [" << Error[k] << ", " << "Gauss" << "]\n";
3284  }
3285  std::string yaml_string = yaml_stream.str();
3286  YAML::Node root = STRINGtoYAML(yaml_string);
3287  TMacro ConfigSave = YAMLtoTMacro(root, "Smearing_Config");
3288  ConfigSave.Write();
3289 
3290  OutputChain->Close();
3291  delete OutputChain;
3292 }

◆ 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 212 of file MCMCProcessor.h.

212 { 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 594 of file MCMCProcessor.h.

◆ AccProbValues

double* MCMCProcessor::AccProbValues
protected

Holds all accProb.

Definition at line 592 of file MCMCProcessor.h.

◆ ApplySmoothing

bool MCMCProcessor::ApplySmoothing
protected

Apply smoothing for 2D histos using root algorithm.

Definition at line 510 of file MCMCProcessor.h.

◆ AutoCorrLag

int MCMCProcessor::AutoCorrLag
protected

LagL used in AutoCorrelation.

Definition at line 581 of file MCMCProcessor.h.

◆ BatchedAverages

double** MCMCProcessor::BatchedAverages
protected

Values of batched average for every param and batch.

Definition at line 584 of file MCMCProcessor.h.

◆ BranchNames

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

Definition at line 460 of file MCMCProcessor.h.

◆ BurnInCut

unsigned int MCMCProcessor::BurnInCut
protected

Value of burn in cut.

Definition at line 445 of file MCMCProcessor.h.

◆ CacheMCMC

bool MCMCProcessor::CacheMCMC
protected

MCMC Chain has been cached.

Definition at line 573 of file MCMCProcessor.h.

◆ CanvasName

TString MCMCProcessor::CanvasName
protected

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

Definition at line 493 of file MCMCProcessor.h.

◆ Central_Value

TVectorD* MCMCProcessor::Central_Value
protected

Vector with central value for each parameter.

Definition at line 530 of file MCMCProcessor.h.

◆ Chain

TChain* MCMCProcessor::Chain
protected

Main chain storing all steps etc.

Definition at line 437 of file MCMCProcessor.h.

◆ Correlation

TMatrixDSym* MCMCProcessor::Correlation
protected

Posterior Correlation Matrix.

Definition at line 551 of file MCMCProcessor.h.

◆ Covariance

TMatrixDSym* MCMCProcessor::Covariance
protected

Posterior Covariance Matrix.

Definition at line 549 of file MCMCProcessor.h.

◆ CovConfig

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

Covariance matrix config.

Definition at line 434 of file MCMCProcessor.h.

◆ CovNamePos

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

Covariance matrix name position.

Definition at line 432 of file MCMCProcessor.h.

◆ CovPos

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

Covariance matrix file name position.

Definition at line 430 of file MCMCProcessor.h.

◆ doDiagMCMC

bool MCMCProcessor::doDiagMCMC
protected

Doing MCMC Diagnostic.

Definition at line 575 of file MCMCProcessor.h.

◆ DrawRange

double MCMCProcessor::DrawRange
protected

Drawrange for SetMaximum.

Definition at line 570 of file MCMCProcessor.h.

◆ Errors

TVectorD* MCMCProcessor::Errors
protected

Vector with errors values using RMS.

Definition at line 534 of file MCMCProcessor.h.

◆ Errors_Gauss

TVectorD* MCMCProcessor::Errors_Gauss
protected

Vector with error values using Gaussian fit.

Definition at line 538 of file MCMCProcessor.h.

◆ Errors_HPD

TVectorD* MCMCProcessor::Errors_HPD
protected

Vector with error values using Highest Posterior Density.

Definition at line 542 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 546 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 544 of file MCMCProcessor.h.

◆ ExcludedGroups

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

Definition at line 463 of file MCMCProcessor.h.

◆ ExcludedNames

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

Definition at line 462 of file MCMCProcessor.h.

◆ ExcludedTypes

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

Definition at line 461 of file MCMCProcessor.h.

◆ FancyPlotNames

bool MCMCProcessor::FancyPlotNames
protected

Whether we want fancy plot names or not.

Definition at line 506 of file MCMCProcessor.h.

◆ Gauss

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

Gaussian fitter.

Definition at line 520 of file MCMCProcessor.h.

◆ hpost

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

Holds 1D Posterior Distributions.

Definition at line 554 of file MCMCProcessor.h.

◆ hpost2D

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

Holds 2D Posterior Distributions.

Definition at line 556 of file MCMCProcessor.h.

◆ hviolin

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

Holds violin plot for all dials.

Definition at line 558 of file MCMCProcessor.h.

◆ hviolin_prior

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

Holds prior violin plot for all dials,.

Definition at line 560 of file MCMCProcessor.h.

◆ MadePostfit

bool MCMCProcessor::MadePostfit
protected

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

Definition at line 502 of file MCMCProcessor.h.

◆ MCMCFile

std::string MCMCProcessor::MCMCFile
protected

Name of MCMC file.

Definition at line 426 of file MCMCProcessor.h.

◆ Means

TVectorD* MCMCProcessor::Means
protected

Vector with mean values using Arithmetic Mean.

Definition at line 532 of file MCMCProcessor.h.

◆ Means_Gauss

TVectorD* MCMCProcessor::Means_Gauss
protected

Vector with mean values using Gaussian fit.

Definition at line 536 of file MCMCProcessor.h.

◆ Means_HPD

TVectorD* MCMCProcessor::Means_HPD
protected

Vector with mean values using Highest Posterior Density.

Definition at line 540 of file MCMCProcessor.h.

◆ nBatches

int MCMCProcessor::nBatches
protected

Number of batches for Batched Mean.

Definition at line 579 of file MCMCProcessor.h.

◆ nBins

int MCMCProcessor::nBins
protected

Number of bins.

Definition at line 568 of file MCMCProcessor.h.

◆ nBranches

int MCMCProcessor::nBranches
protected

Number of branches in a TTree.

Definition at line 447 of file MCMCProcessor.h.

◆ nDraw

int MCMCProcessor::nDraw
protected

Number of all parameters used in the analysis.

Definition at line 457 of file MCMCProcessor.h.

◆ NDSamplesBins

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

Definition at line 516 of file MCMCProcessor.h.

◆ NDSamplesNames

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

Definition at line 517 of file MCMCProcessor.h.

◆ nEntries

int MCMCProcessor::nEntries
protected

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

Definition at line 449 of file MCMCProcessor.h.

◆ nParam

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

Number of parameters per type.

Definition at line 476 of file MCMCProcessor.h.

◆ nParameterHandlers

int MCMCProcessor::nParameterHandlers
protected

Number of covariance objects.

Definition at line 455 of file MCMCProcessor.h.

◆ nSampleHandlers

int MCMCProcessor::nSampleHandlers
protected

Number of sample PDF objects.

Definition at line 453 of file MCMCProcessor.h.

◆ nSteps

int MCMCProcessor::nSteps
protected

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

Definition at line 451 of file MCMCProcessor.h.

◆ OutputFile

TFile* MCMCProcessor::OutputFile
protected

The output file.

Definition at line 523 of file MCMCProcessor.h.

◆ OutputName

std::string MCMCProcessor::OutputName
protected

Name of output files.

Definition at line 491 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 428 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 470 of file MCMCProcessor.h.

◆ ParamErrors

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

Uncertainty on a single parameter.

Definition at line 472 of file MCMCProcessor.h.

◆ ParameterGroup

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

Definition at line 483 of file MCMCProcessor.h.

◆ ParamFlat

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

Whether Param has flat prior or not.

Definition at line 474 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 468 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 478 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 481 of file MCMCProcessor.h.

◆ ParamVaried

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

Is the ith parameter varied.

Definition at line 466 of file MCMCProcessor.h.

◆ ParStep

M3::float_t** MCMCProcessor::ParStep
protected

Array holding values for all parameters.

Definition at line 563 of file MCMCProcessor.h.

◆ plotBinValue

bool MCMCProcessor::plotBinValue
protected

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

Definition at line 508 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 496 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 500 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 512 of file MCMCProcessor.h.

◆ Posterior

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

Fancy canvas used for our beautiful plots.

Definition at line 526 of file MCMCProcessor.h.

◆ Posterior1DCut

std::string MCMCProcessor::Posterior1DCut
protected

Cut used when making 1D Posterior distribution.

Definition at line 441 of file MCMCProcessor.h.

◆ printToPDF

bool MCMCProcessor::printToPDF
protected

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

Definition at line 504 of file MCMCProcessor.h.

◆ ReweightName

std::string MCMCProcessor::ReweightName
protected

Name of branch used for chain reweighting.

Definition at line 599 of file MCMCProcessor.h.

◆ ReweightPosterior

bool MCMCProcessor::ReweightPosterior
protected

Whether to apply reweighting weight or not.

Definition at line 597 of file MCMCProcessor.h.

◆ SampleName_v

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

Vector of each systematic.

Definition at line 486 of file MCMCProcessor.h.

◆ SampleValues

double** MCMCProcessor::SampleValues
protected

Holds the sample values.

Definition at line 587 of file MCMCProcessor.h.

◆ StepCut

std::string MCMCProcessor::StepCut
protected

BurnIn Cuts.

Definition at line 439 of file MCMCProcessor.h.

◆ StepNumber

unsigned int* MCMCProcessor::StepNumber
protected

Step number for step, important if chains were merged.

Definition at line 565 of file MCMCProcessor.h.

◆ SystName_v

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

Vector of each sample PDF object.

Definition at line 488 of file MCMCProcessor.h.

◆ SystValues

double** MCMCProcessor::SystValues
protected

Holds the systs values.

Definition at line 589 of file MCMCProcessor.h.

◆ UpperCut

unsigned int MCMCProcessor::UpperCut
protected

KS: Used only for SubOptimality.

Definition at line 443 of file MCMCProcessor.h.

◆ useFFTAutoCorrelation

bool MCMCProcessor::useFFTAutoCorrelation
protected

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

Definition at line 514 of file MCMCProcessor.h.

◆ WeightValue

double* MCMCProcessor::WeightValue
protected

Stores value of weight for each step.

Definition at line 601 of file MCMCProcessor.h.


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