MaCh3  2.4.2
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 [28]. 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 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] [29]. 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] [21]. 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 > IamVaried
 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 mcmc::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.
Author
Clarence Wret
Kamil Skwarczynski

Definition at line 58 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.
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Definition: Core.h:55
void MaCh3Welcome()
KS: Prints welcome message with MaCh3 logo.
Definition: Monitor.cpp:12

◆ ~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 ( )
inlineprotected

Acceptance Probability.

Definition at line 4472 of file MCMCProcessor.cpp.

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

◆ AutoCorrelation()

void MCMCProcessor::AutoCorrelation ( )
inlineprotected

KS: Calculate autocorrelations supports both OpenMP and CUDA :)

Definition at line 3743 of file MCMCProcessor.cpp.

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

MJR: Autocorrelation function using FFT algorithm for extra speed.

Author
Michael Reh

Definition at line 3647 of file MCMCProcessor.cpp.

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

◆ BatchedAnalysis()

void MCMCProcessor::BatchedAnalysis ( )
inlineprotected

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

Definition at line 4104 of file MCMCProcessor.cpp.

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

◆ BatchedMeans()

void MCMCProcessor::BatchedMeans ( )
inlineprotected

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

Definition at line 4047 of file MCMCProcessor.cpp.

4047  {
4048 // **************************
4049  if (BatchedAverages == nullptr) PrepareDiagMCMC();
4050  MACH3LOG_INFO("Making BatchedMeans plots...");
4051 
4052  std::vector<std::unique_ptr<TH1D>> BatchedParamPlots(nDraw);
4053  for (int j = 0; j < nDraw; ++j) {
4054  TString Title = "";
4055  double Prior = 1.0, PriorError = 1.0;
4056 
4057  GetNthParameter(j, Prior, PriorError, Title);
4058 
4059  std::string HistName = Form("%s_%s_batch", Title.Data(), BranchNames[j].Data());
4060  BatchedParamPlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), nBatches, 0, nBatches);
4061  BatchedParamPlots[j]->SetDirectory(nullptr);
4062  }
4063 
4064  #ifdef MULTITHREAD
4065  #pragma omp parallel for
4066  #endif
4067  for (int j = 0; j < nDraw; ++j) {
4068  for (int i = 0; i < nBatches; ++i) {
4069  BatchedParamPlots[j]->SetBinContent(i+1, BatchedAverages[i][j]);
4070  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4071  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4072  std::stringstream ss;
4073  ss << BatchRangeLow << " - " << BatchRangeHigh;
4074  BatchedParamPlots[j]->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4075  }
4076  }
4077 
4078  TDirectory *BatchDir = OutputFile->mkdir("Batched_means");
4079  BatchDir->cd();
4080  for (int j = 0; j < nDraw; ++j) {
4081  auto Fitter = std::make_unique<TF1>("Fitter", "[0]", 0, nBatches);
4082  Fitter->SetLineColor(kRed);
4083  BatchedParamPlots[j]->Fit("Fitter","Rq");
4084  BatchedParamPlots[j]->Write();
4085  }
4086 
4087  //KS: Get the batched means variance estimation and variable indicating if number of batches is sensible
4088  // We do this before deleting BatchedAverages
4089  BatchedAnalysis();
4090 
4091  for (int i = 0; i < nBatches; ++i) {
4092  delete BatchedAverages[i];
4093  }
4094  delete[] BatchedAverages;
4095 
4096  BatchDir->Close();
4097  delete BatchDir;
4098 
4099  OutputFile->cd();
4100 }
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.
double float_t
Definition: Core.h:37
void PrintProgressBar(const Long64_t Done, const Long64_t All)
KS: Simply print progress bar.
Definition: Monitor.cpp:228
void EstimateDataTransferRate(TChain *chain, const Long64_t entry)
KS: Check what CPU you are using.
Definition: Monitor.cpp:211

◆ CalculateESS()

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

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. [31] [15] [9]

Definition at line 3949 of file MCMCProcessor.cpp.

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

4520  {
4521 // **************************
4522  if (CredibleIntervals.size() != CredibleIntervalsColours.size()) {
4523  MACH3LOG_ERROR("size of CredibleIntervals is not equal to size of CredibleIntervalsColours");
4524  throw MaCh3Exception(__FILE__, __LINE__);
4525  }
4526  if (CredibleIntervals.size() > 1) {
4527  for (unsigned int i = 1; i < CredibleIntervals.size(); i++) {
4528  if (CredibleIntervals[i] > CredibleIntervals[i - 1]) {
4529  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4530  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleIntervals[i], CredibleIntervals[i - 1]);
4531  MACH3LOG_ERROR("They should be grouped in decreasing order");
4532  throw MaCh3Exception(__FILE__, __LINE__);
4533  }
4534  }
4535  }
4536 }

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

4541  {
4542 // **************************
4543  if ((CredibleRegions.size() != CredibleRegionStyle.size()) || (CredibleRegionStyle.size() != CredibleRegionColor.size())) {
4544  MACH3LOG_ERROR("size of CredibleRegions is not equal to size of CredibleRegionStyle or CredibleRegionColor");
4545  throw MaCh3Exception(__FILE__, __LINE__);
4546  }
4547  for (unsigned int i = 1; i < CredibleRegions.size(); i++) {
4548  if (CredibleRegions[i] > CredibleRegions[i - 1]) {
4549  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4550  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleRegions[i], CredibleRegions[i - 1]);
4551  MACH3LOG_ERROR("They should be grouped in decreasing order");
4552  throw MaCh3Exception(__FILE__, __LINE__);
4553  }
4554  }
4555 }

◆ CheckStepCut()

void MCMCProcessor::CheckStepCut ( ) const

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

Definition at line 2715 of file MCMCProcessor.cpp.

2715  {
2716 // ***************
2717  const unsigned int maxNsteps = Chain->GetMaximum("step");
2718  if(BurnInCut > maxNsteps){
2719  MACH3LOG_ERROR("StepCut({}) is larger than highest value of step({})", BurnInCut, maxNsteps);
2720  throw MaCh3Exception(__FILE__ , __LINE__ );
2721  }
2722 }
unsigned int BurnInCut
Value of burn in cut.

◆ DiagMCMC()

void MCMCProcessor::DiagMCMC ( )

KS: Perform MCMC diagnostic including Autocorrelation, Trace etc.

Definition at line 3346 of file MCMCProcessor.cpp.

3346  {
3347 // **************************
3348  // Prepare branches etc for DiagMCMC
3349  PrepareDiagMCMC();
3350 
3351  // Draw the simple trace matrices
3352  ParamTraces();
3353 
3354  // Get the batched means
3355  BatchedMeans();
3356 
3357  // Draw the auto-correlations
3358  if (useFFTAutoCorrelation) {
3360  } else {
3361  AutoCorrelation();
3362  }
3363 
3364  // Calculate Power Spectrum for each param
3366 
3367  // Get Geweke Z score helping select burn-in
3368  GewekeDiagnostic();
3369 
3370  // Draw acceptance Probability
3372 }
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 ( )
inlineprotected

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 (IamVaried[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 > IamVaried
Is the ith parameter varied.

◆ DrawCorrelationsGroup()

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

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 ( )
inlineprotected

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

Definition at line 2454 of file MCMCProcessor.cpp.

2454  {
2455 // **************************
2456  // Now read the MCMC file
2457  TFile *TempFile = M3::Open(MCMCFile, "open", __FILE__, __LINE__);
2458  TDirectory* CovarianceFolder = TempFile->Get<TDirectory>("CovarianceFolder");
2459 
2460  // Get the settings for the MCMC
2461  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2462 
2463  if (Config == nullptr) {
2464  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2465  TempFile->ls();
2466  throw MaCh3Exception(__FILE__ , __LINE__ );
2467  }
2468  MACH3LOG_INFO("Loading YAML config from MCMC chain");
2469 
2470  YAML::Node Settings = TMacroToYAML(*Config);
2471 
2472  bool InputNotFound = false;
2473  //CW: Get the xsec Covariance matrix
2474  CovPos[kXSecPar] = GetFromManager<std::vector<std::string>>(Settings["General"]["Systematics"]["XsecCovFile"], {"none"});
2475  if(CovPos[kXSecPar].back() == "none")
2476  {
2477  MACH3LOG_WARN("Couldn't find XsecCov branch in output");
2478  InputNotFound = true;
2479  }
2480 
2481  TMacro *XsecConfig = M3::GetConfigMacroFromChain(CovarianceFolder);
2482  if (XsecConfig == nullptr) {
2483  MACH3LOG_WARN("Didn't find Config_xsec_cov tree in MCMC file! {}", MCMCFile);
2484  } else {
2485  CovConfig[kXSecPar] = TMacroToYAML(*XsecConfig);
2486  }
2487  if(InputNotFound) MaCh3Utils::PrintConfig(Settings);
2488 
2489  for(size_t i = 0; i < CovPos[kXSecPar].size(); i++)
2491 
2492  // Delete the TTrees and the input file handle since we've now got the settings we need
2493  delete Config;
2494  delete XsecConfig;
2495 
2496  TMacro *ReweightConfig = TempFile->Get<TMacro>("Reweight_Config");
2497  if (ReweightConfig != nullptr) {
2498  YAML::Node ReweightSettings = TMacroToYAML(*ReweightConfig);
2499 
2500  if (ReweightSettings["Weight"]) {
2501  ReweightName = "Weight";
2502  ReweightPosterior = true;
2503  MACH3LOG_INFO("Enabling reweighting with following Config");
2504  } else {
2505  MACH3LOG_WARN("Found reweight config but without field ''Weight''");
2506  }
2507  MaCh3Utils::PrintConfig(ReweightSettings);
2508  }
2509 
2510  // Delete the MCMCFile pointer we're reading
2511  CovarianceFolder->Close();
2512  delete CovarianceFolder;
2513  TempFile->Close();
2514  delete TempFile;
2515 }
#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
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,...
void PrintConfig(const YAML::Node &node)
KS: Print Yaml config using logger.
Definition: Monitor.cpp:310
Structure to hold reweight configuration.

◆ FindInputFilesLegacy()

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

Definition at line 2519 of file MCMCProcessor.cpp.

2519  {
2520 // **************************
2521  // Now read the MCMC file
2522  TFile *TempFile = M3::Open(MCMCFile, "open", __FILE__, __LINE__);
2523  // Get the settings for the MCMC
2524  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2525 
2526  if (Config == nullptr) {
2527  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2528  TempFile->ls();
2529  throw MaCh3Exception(__FILE__ , __LINE__ );
2530  }
2531  YAML::Node Settings = TMacroToYAML(*Config);
2532 
2533  //CW: And the ND Covariance matrix
2534  CovPos[kNDPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovFile"], "none"));
2535 
2536  if(CovPos[kNDPar].back() == "none") {
2537  MACH3LOG_WARN("Couldn't find NDCov (legacy) branch in output");
2538  } else{
2539  //If the FD Cov is not none, then you need the name of the covariance object to grab
2540  CovNamePos[kNDPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovName"], "none");
2541  MACH3LOG_INFO("Given NDCovFile {} and NDCovName {}", CovPos[kNDPar].back(), CovNamePos[kNDPar]);
2542  }
2543 
2544  //CW: And the FD Covariance matrix
2545  CovPos[kFDDetPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovFile"], "none"));
2546 
2547  if(CovPos[kFDDetPar].back() == "none") {
2548  MACH3LOG_WARN("Couldn't find FDCov (legacy) branch in output");
2549  } else {
2550  //If the FD Cov is not none, then you need the name of the covariance object to grab
2551  CovNamePos[kFDDetPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovName"], "none");
2552  MACH3LOG_INFO("Given FDCovFile {} and FDCovName {}", CovPos[kFDDetPar].back(), CovNamePos[kFDDetPar]);
2553  }
2554 
2555  for(size_t i = 0; i < CovPos[kNDPar].size(); i++)
2556  M3::AddPath(CovPos[kNDPar][i]);
2557 
2558  for(size_t i = 0; i < CovPos[kFDDetPar].size(); i++)
2560 
2561  TempFile->Close();
2562  delete TempFile;
2563 }
@ 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 2846 of file MCMCProcessor.cpp.

2849  {
2850 // **************************
2851  if(hpost[0] == nullptr) MakePostfit();
2852 
2853  MACH3LOG_INFO("Calculating Bayes Factor");
2854  if((ParNames.size() != Model1Bounds.size()) || (Model2Bounds.size() != Model1Bounds.size()) || (Model2Bounds.size() != ModelNames.size()))
2855  {
2856  MACH3LOG_ERROR("Size doesn't match");
2857  throw MaCh3Exception(__FILE__ , __LINE__ );
2858  }
2859  for(unsigned int k = 0; k < ParNames.size(); ++k)
2860  {
2861  //KS: First we need to find parameter number based on name
2862  int ParamNo = GetParamIndexFromName(ParNames[k]);
2863  if(ParamNo == M3::_BAD_INT_)
2864  {
2865  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Bayes Factor", ParNames[k]);
2866  continue;
2867  }
2868 
2869  const double M1_min = Model1Bounds[k][0];
2870  const double M2_min = Model2Bounds[k][0];
2871  const double M1_max = Model1Bounds[k][1];
2872  const double M2_max = Model2Bounds[k][1];
2873 
2874  long double IntegralMode1 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M1_min), hpost[ParamNo]->FindFixBin(M1_max));
2875  long double IntegralMode2 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M2_min), hpost[ParamNo]->FindFixBin(M2_max));
2876 
2877  double BayesFactor = 0.;
2878  std::string Name = "";
2879  //KS: Calc Bayes Factor
2880  //If M1 is more likely
2881  if(IntegralMode1 >= IntegralMode2)
2882  {
2883  BayesFactor = IntegralMode1/IntegralMode2;
2884  Name = "\\mathfrak{B}(" + ModelNames[k][0]+ "/" + ModelNames[k][1] + ") = " + std::to_string(BayesFactor);
2885  }
2886  else //If M2 is more likely
2887  {
2888  BayesFactor = IntegralMode2/IntegralMode1;
2889  Name = "\\mathfrak{B}(" + ModelNames[k][1]+ "/" + ModelNames[k][0] + ") = " + std::to_string(BayesFactor);
2890  }
2891  std::string JeffreysScale = GetJeffreysScale(BayesFactor);
2892  std::string DunneKabothScale = GetDunneKaboth(BayesFactor);
2893 
2894  MACH3LOG_INFO("{} for {}", Name, ParNames[k]);
2895  MACH3LOG_INFO("Following Jeffreys Scale = {}", JeffreysScale);
2896  MACH3LOG_INFO("Following Dunne-Kaboth Scale = {}", DunneKabothScale);
2897  MACH3LOG_INFO("");
2898  }
2899 }
std::string GetJeffreysScale(const double BayesFactor)
KS: Following H. Jeffreys .
std::string GetDunneKaboth(const double BayesFactor)
KS: Based on Table 1 in https://www.t2k.org/docs/technotes/435.
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 251 of file MCMCProcessor.h.

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

219 {return CovConfig.at(i); }

◆ GetFDCov()

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

Definition at line 239 of file MCMCProcessor.h.

239 { 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 4558 of file MCMCProcessor.cpp.

4558  {
4559 // **************************
4560  // Lambda to compare strings case-insensitively
4561  auto caseInsensitiveCompare = [](const std::string& a, const std::string& b) {
4562  return std::equal(a.begin(), a.end(), b.begin(), b.end(),
4563  [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
4564  };
4565  int numerator = 0;
4566  for (const auto& groupName : ParameterGroup) {
4567  if (caseInsensitiveCompare(groupName, name)) {
4568  numerator++;
4569  }
4570  }
4571  return numerator;
4572 }

◆ GetHpost()

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

Get 1D posterior for a given parameter.

Parameters
iparameter index

Definition at line 226 of file MCMCProcessor.h.

226 { 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 230 of file MCMCProcessor.h.

230 { 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 4602 of file MCMCProcessor.cpp.

4602  {
4603 // **************************
4604  return std::vector<double>{Canv->GetTopMargin(), Canv->GetBottomMargin(),
4605  Canv->GetLeftMargin(), Canv->GetRightMargin()};
4606 }

◆ GetNDCov()

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

Definition at line 238 of file MCMCProcessor.h.

238 { 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 257 of file MCMCProcessor.h.

257 {return nEntries;};

◆ GetNFD()

int MCMCProcessor::GetNFD ( ) const
inline

Definition at line 216 of file MCMCProcessor.h.

216 { return nParam[kFDDetPar]; };

◆ GetNND()

int MCMCProcessor::GetNND ( ) const
inline

Definition at line 215 of file MCMCProcessor.h.

215 { return nParam[kNDPar]; };

◆ GetNParams()

int MCMCProcessor::GetNParams ( ) const
inline

Get total number of used parameters.

Definition at line 213 of file MCMCProcessor.h.

213 { 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 259 of file MCMCProcessor.h.

259 {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 2726 of file MCMCProcessor.cpp.

2726  {
2727 // **************************
2728  ParameterEnum ParType = ParamType[param];
2729  int ParamNo = M3::_BAD_INT_;
2730  ParamNo = param - ParamTypeStartPos[ParType];
2731 
2732  Prior = ParamCentral[ParType][ParamNo];
2733  PriorError = ParamErrors[ParType][ParamNo];
2734  Title = ParamNames[ParType][ParamNo];
2735 }

◆ GetNXSec()

int MCMCProcessor::GetNXSec ( ) const
inline

Definition at line 214 of file MCMCProcessor.h.

214 { 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 3621 of file MCMCProcessor.cpp.

3621  {
3622 // *********************************
3623  // Initialise the sums
3624  std::vector <double> ParamSums(nDraw,0);
3625 
3626  #ifdef MULTITHREAD
3627  #pragma omp parallel for
3628  #endif
3629  for (int j = 0; j < nDraw; ++j) {
3630  for (int i = 0; i < nEntries; ++i) {
3631  ParamSums[j] += ParStep[j][i];
3632  }
3633  }
3634  // Make the sums into average
3635  #ifdef MULTITHREAD
3636  #pragma omp parallel for
3637  #endif
3638  for (int i = 0; i < nDraw; ++i) {
3639  ParamSums[i] /= double(nEntries);
3640  }
3641  return ParamSums;
3642 }

◆ GetParamIndexFromName()

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

Get parameter number based on name.

Definition at line 2739 of file MCMCProcessor.cpp.

2739  {
2740 // **************************
2741  int ParamNo = M3::_BAD_INT_;
2742  for (int i = 0; i < nDraw; ++i)
2743  {
2744  TString Title = "";
2745  double Prior = 1.0, PriorError = 1.0;
2746  GetNthParameter(i, Prior, PriorError, Title);
2747 
2748  if(Name == Title)
2749  {
2750  ParamNo = i;
2751  break;
2752  }
2753  }
2754  return ParamNo;
2755 }

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

2777  {
2778 // **************************
2779  if(hpost[0] == nullptr) MakePostfit();
2780 
2781  std::vector<double> Margins = GetMargins(Posterior);
2782 
2783  Posterior->SetTopMargin(0.1);
2784  Posterior->SetBottomMargin(0.1);
2785  Posterior->SetLeftMargin(0.1);
2786  Posterior->SetRightMargin(0.1);
2787  Posterior->Update();
2788 
2789  MACH3LOG_INFO("Calculating Polar Plot");
2790  TDirectory *PolarDir = OutputFile->mkdir("PolarDir");
2791  PolarDir->cd();
2792 
2793  for(unsigned int k = 0; k < ParNames.size(); ++k)
2794  {
2795  //KS: First we need to find parameter number based on name
2796  int ParamNo = GetParamIndexFromName(ParNames[k]);
2797  if(ParamNo == M3::_BAD_INT_)
2798  {
2799  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Polar Plot", ParNames[k]);
2800  continue;
2801  }
2802 
2803  TString Title = "";
2804  double Prior = 1.0, PriorError = 1.0;
2805  GetNthParameter(ParamNo, Prior, PriorError, Title);
2806 
2807  std::vector<double> x_val(nBins);
2808  std::vector<double> y_val(nBins);
2809 
2810  constexpr double xmin = 0;
2811  constexpr double xmax = 2*TMath::Pi();
2812 
2813  double Integral = hpost[ParamNo]->Integral();
2814  for (Int_t ipt = 0; ipt < nBins; ipt++)
2815  {
2816  x_val[ipt] = ipt*(xmax-xmin)/nBins+xmin;
2817  y_val[ipt] = hpost[ParamNo]->GetBinContent(ipt+1)/Integral;
2818  }
2819 
2820  auto PolarGraph = std::make_unique<TGraphPolar>(nBins, x_val.data(), y_val.data());
2821  PolarGraph->SetLineWidth(2);
2822  PolarGraph->SetFillStyle(3001);
2823  PolarGraph->SetLineColor(kRed);
2824  PolarGraph->SetFillColor(kRed);
2825  PolarGraph->Draw("AFL");
2826 
2827  auto Text = std::make_unique<TText>(0.6, 0.1, Title);
2828  Text->SetTextSize(0.04);
2829  Text->SetNDC(true);
2830  Text->Draw("");
2831 
2832  Posterior->Print(CanvasName);
2833  Posterior->Write(Title);
2834  } //End loop over parameters
2835 
2836  PolarDir->Close();
2837  delete PolarDir;
2838 
2839  OutputFile->cd();
2840 
2841  SetMargins(Posterior, Margins);
2842 }

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

2905  {
2906 // **************************
2907  if((ParNames.size() != EvaluationPoint.size()) || (Bounds.size() != EvaluationPoint.size()))
2908  {
2909  MACH3LOG_ERROR("Size doesn't match");
2910  throw MaCh3Exception(__FILE__ , __LINE__ );
2911  }
2912 
2913  if(hpost[0] == nullptr) MakePostfit();
2914 
2915  MACH3LOG_INFO("Calculating Savage Dickey");
2916  TDirectory *SavageDickeyDir = OutputFile->mkdir("SavageDickey");
2917  SavageDickeyDir->cd();
2918 
2919  for(unsigned int k = 0; k < ParNames.size(); ++k)
2920  {
2921  //KS: First we need to find parameter number based on name
2922  int ParamNo = GetParamIndexFromName(ParNames[k]);
2923  if(ParamNo == M3::_BAD_INT_)
2924  {
2925  MACH3LOG_WARN("Couldn't find param {}. Will not calculate SavageDickey", ParNames[k]);
2926  continue;
2927  }
2928 
2929  TString Title = "";
2930  double Prior = 1.0, PriorError = 1.0;
2931  bool FlatPrior = false;
2932  GetNthParameter(ParamNo, Prior, PriorError, Title);
2933 
2934  ParameterEnum ParType = ParamType[ParamNo];
2935  int ParamTemp = ParamNo - ParamTypeStartPos[ParType];
2936  FlatPrior = ParamFlat[ParType][ParamTemp];
2937 
2938  auto PosteriorHist = M3::Clone<TH1D>(hpost[ParamNo], std::string(Title));
2939  RemoveFitter(PosteriorHist.get(), "Gauss");
2940 
2941  std::unique_ptr<TH1D> PriorHist;
2942  //KS: If flat prior we need to have well defined bounds otherwise Prior distribution will not make sense
2943  if(FlatPrior)
2944  {
2945  int NBins = PosteriorHist->GetNbinsX();
2946  if(Bounds[k][0] > Bounds[k][1])
2947  {
2948  MACH3LOG_ERROR("Lower bound is higher than upper bound");
2949  throw MaCh3Exception(__FILE__ , __LINE__ );
2950  }
2951  PriorHist = std::make_unique<TH1D>("PriorHist", Title, NBins, Bounds[k][0], Bounds[k][1]);
2952  PriorHist->SetDirectory(nullptr);
2953  double FlatProb = ( Bounds[k][1] - Bounds[k][0]) / NBins;
2954  for (int g = 0; g < NBins + 1; ++g)
2955  {
2956  PriorHist->SetBinContent(g+1, FlatProb);
2957  }
2958  }
2959  else //KS: Otherwise throw from Gaussian
2960  {
2961  PriorHist = M3::Clone<TH1D>(PosteriorHist.get(), "Prior");
2962  PriorHist->Reset("");
2963  PriorHist->Fill(0.0, 0.0);
2964 
2965  auto rand = std::make_unique<TRandom3>(0);
2966  //KS: Throw nice gaussian, just need big number to have smooth distribution
2967  for(int g = 0; g < 1000000; ++g)
2968  {
2969  PriorHist->Fill(rand->Gaus(Prior, PriorError));
2970  }
2971  }
2972  SavageDickeyPlot(PriorHist, PosteriorHist, std::string(Title), EvaluationPoint[k]);
2973  } //End loop over parameters
2974 
2975  SavageDickeyDir->Close();
2976  delete SavageDickeyDir;
2977 
2978  OutputFile->cd();
2979 }
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 232 of file MCMCProcessor.h.

232 { return hviolin.get(); };

◆ GetViolinPrior()

TH2D* MCMCProcessor::GetViolinPrior ( ) const
inline

Get Violin plot for all parameters with prior values.

Definition at line 234 of file MCMCProcessor.h.

234 { return hviolin_prior.get(); };

◆ GetXSecCov()

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

Definition at line 237 of file MCMCProcessor.h.

237 { return CovPos[kXSecPar]; };

◆ GewekeDiagnostic()

void MCMCProcessor::GewekeDiagnostic ( )
inlineprotected

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

Definition at line 4339 of file MCMCProcessor.cpp.

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

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

347 {};

◆ 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 (IamVaried[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 (IamVaried[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 (IamVaried[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(!IamVaried[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 1769 of file MCMCProcessor.cpp.

1774  {
1775 // *********************
1776  if(hpost2D.size() == 0) MakeCovariance_MP();
1777  MACH3LOG_INFO("Making Credible Regions");
1778 
1779  CheckCredibleRegionsOrder(CredibleRegions, CredibleRegionStyle, CredibleRegionColor);
1780  const int nCredible = int(CredibleRegions.size());
1781 
1782  std::vector<std::vector<std::unique_ptr<TH2D>>> hpost_2D_copy(nDraw);
1783  std::vector<std::vector<std::vector<std::unique_ptr<TH2D>>>> hpost_2D_cl(nDraw);
1784  //KS: Copy all histograms to be thread safe
1785  for (int i = 0; i < nDraw; ++i)
1786  {
1787  hpost_2D_copy[i].resize(nDraw);
1788  hpost_2D_cl[i].resize(nDraw);
1789  for (int j = 0; j <= i; ++j)
1790  {
1791  hpost_2D_copy[i][j] = M3::Clone<TH2D>(hpost2D[i][j], Form("hpost_copy_%i_%i", i, j));
1792  hpost_2D_cl[i][j].resize(nCredible);
1793  for (int k = 0; k < nCredible; ++k)
1794  {
1795  hpost_2D_cl[i][j][k] = M3::Clone<TH2D>(hpost2D[i][j], Form("hpost_copy_%i_%i_CL_%f", i, j, CredibleRegions[k]));
1796  }
1797  }
1798  }
1799 
1800  #ifdef MULTITHREAD
1801  #pragma omp parallel for
1802  #endif
1803  //Calculate credible histogram
1804  for (int i = 0; i < nDraw; ++i)
1805  {
1806  for (int j = 0; j <= i; ++j)
1807  {
1808  for (int k = 0; k < nCredible; ++k)
1809  {
1810  GetCredibleRegionSig(hpost_2D_cl[i][j][k], CredibleInSigmas, CredibleRegions[k]);
1811  hpost_2D_cl[i][j][k]->SetLineColor(CredibleRegionColor[k]);
1812  hpost_2D_cl[i][j][k]->SetLineWidth(2);
1813  hpost_2D_cl[i][j][k]->SetLineStyle(CredibleRegionStyle[k]);
1814  }
1815  }
1816  }
1817 
1818  gStyle->SetPalette(51);
1819  for (int i = 0; i < nDraw; ++i)
1820  {
1821  for (int j = 0; j <= i; ++j)
1822  {
1823  // Skip the diagonal elements which we've already done above
1824  if (j == i) continue;
1825  if (IamVaried[j] == false) continue;
1826 
1827  auto legend = std::make_unique<TLegend>(0.20, 0.7, 0.4, 0.92);
1828  legend->SetTextColor(kRed);
1829  SetLegendStyle(legend.get(), 0.03);
1830 
1831  //Get Best point
1832  auto bestfitM = std::make_unique<TGraph>(1);
1833  const int MaxBin = hpost_2D_copy[i][j]->GetMaximumBin();
1834  int Mbx, Mby, Mbz;
1835  hpost_2D_copy[i][j]->GetBinXYZ(MaxBin, Mbx, Mby, Mbz);
1836  const double Mx = hpost_2D_copy[i][j]->GetXaxis()->GetBinCenter(Mbx);
1837  const double My = hpost_2D_copy[i][j]->GetYaxis()->GetBinCenter(Mby);
1838 
1839  bestfitM->SetPoint(0, Mx, My);
1840  bestfitM->SetMarkerStyle(22);
1841  bestfitM->SetMarkerSize(1);
1842  bestfitM->SetMarkerColor(kMagenta);
1843 
1844  //Plot default 2D posterior
1845 
1846  if(Draw2DPosterior){
1847  hpost_2D_copy[i][j]->Draw("COLZ");
1848  } else{
1849  hpost_2D_copy[i][j]->Draw("AXIS");
1850  }
1851 
1852  //Now credible regions
1853  for (int k = 0; k < nCredible; ++k)
1854  hpost_2D_cl[i][j][k]->Draw("CONT3 SAME");
1855  for (int k = nCredible-1; k >= 0; --k)
1856  {
1857  if(CredibleInSigmas)
1858  legend->AddEntry(hpost_2D_cl[i][j][k].get(), Form("%.0f#sigma Credible Interval", CredibleRegions[k]), "l");
1859  else
1860  legend->AddEntry(hpost_2D_cl[i][j][k].get(), Form("%.0f%% Credible Region", CredibleRegions[k]*100), "l");
1861  }
1862  legend->Draw("SAME");
1863 
1864  if(DrawBestFit){
1865  legend->AddEntry(bestfitM.get(),"Best Fit","p");
1866  bestfitM->Draw("SAME.P");
1867  }
1868 
1869  // Write to file
1870  Posterior->SetName(hpost2D[i][j]->GetName());
1871  Posterior->SetTitle(hpost2D[i][j]->GetTitle());
1872 
1873  //KS: Print only regions with correlation greater than specified value, by default 0.2. This is done to avoid dumping thousands of plots
1874  if(printToPDF && std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold) Posterior->Print(CanvasName);
1875  // Write it to root file
1876  //OutputFile->cd();
1877  //if( std::fabs((*Correlation)(i,j)) > Post2DPlotThreshold ) Posterior->Write();
1878  }
1879  }
1880 
1881  OutputFile->cd();
1882 }
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 ( )
inlineprotected

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  IamVaried[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  IamVaried[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 ( )
inlineprotected

Prepare prefit histogram for parameter overlay plot.

Definition at line 2374 of file MCMCProcessor.cpp.

2374  {
2375 // *****************************
2376  if (OutputFile == nullptr) MakeOutputFile();
2377 
2378  auto PreFitPlot = std::make_unique<TH1D>("Prefit", "Prefit", nDraw, 0, nDraw);
2379  PreFitPlot->SetDirectory(nullptr);
2380  for (int i = 0; i < PreFitPlot->GetNbinsX() + 1; ++i) {
2381  PreFitPlot->SetBinContent(i+1, 0);
2382  PreFitPlot->SetBinError(i+1, 0);
2383  }
2384 
2385  //KS: Slightly hacky way to get relative to prior or nominal as this is convention we use,
2386  //Only applies for xsec, for other systematic it make no difference
2387  double CentralValueTemp, Central, Error;
2388 
2389  // Set labels and data
2390  for (int i = 0; i < nDraw; ++i)
2391  {
2392  //Those keep which parameter type we run currently and relative number
2393  int ParamEnum = ParamType[i];
2394  int ParamNo = i - ParamTypeStartPos[ParameterEnum(ParamEnum)];
2395  CentralValueTemp = ParamCentral[ParamEnum][ParamNo];
2396  if(plotRelativeToPrior)
2397  {
2398  // Normalise the prior relative the nominal/prior, just the way we get our fit results in MaCh3
2399  if ( CentralValueTemp != 0) {
2400  Central = ParamCentral[ParamEnum][ParamNo] / CentralValueTemp;
2401  Error = ParamErrors[ParamEnum][ParamNo]/CentralValueTemp;
2402  } else {
2403  Central = CentralValueTemp + 1.0;
2404  Error = ParamErrors[ParamEnum][ParamNo];
2405  }
2406  }
2407  else
2408  {
2409  Central = CentralValueTemp;
2410  Error = ParamErrors[ParamEnum][ParamNo];
2411  }
2412  //KS: If plotting error for param with flat prior is turned off and given param really has flat prior set error to 0
2413  if(!PlotFlatPrior && ParamFlat[ParamEnum][ParamNo]) {
2414  Error = 0.;
2415  }
2416  PreFitPlot->SetBinContent(i+1, Central);
2417  PreFitPlot->SetBinError(i+1, Error);
2418  PreFitPlot->GetXaxis()->SetBinLabel(i+1, ParamNames[ParamEnum][ParamNo]);
2419  }
2420  PreFitPlot->SetDirectory(nullptr);
2421 
2422  PreFitPlot->SetFillStyle(1001);
2423  PreFitPlot->SetFillColor(kRed-3);
2424  PreFitPlot->SetMarkerStyle(21);
2425  PreFitPlot->SetMarkerSize(2.4);
2426  PreFitPlot->SetMarkerColor(kWhite);
2427  PreFitPlot->SetLineColor(PreFitPlot->GetFillColor());
2428  PreFitPlot->GetXaxis()->LabelsOption("v");
2429 
2430  return PreFitPlot;
2431 }

◆ MakeSubOptimality()

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

Make and Draw SubOptimality [28].

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

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

◆ 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 (IamVaried[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 3264 of file MCMCProcessor.cpp.

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

◆ ParamTraces()

void MCMCProcessor::ParamTraces ( )
inlineprotected

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

Definition at line 3532 of file MCMCProcessor.cpp.

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

◆ PowerSpectrumAnalysis()

void MCMCProcessor::PowerSpectrumAnalysis ( )
inlineprotected

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

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

◆ PrepareDiagMCMC()

void MCMCProcessor::PrepareDiagMCMC ( )
inlineprotected

CW: Prepare branches etc. for DiagMCMC.

Definition at line 3376 of file MCMCProcessor.cpp.

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

◆ PrintInfo()

void MCMCProcessor::PrintInfo ( ) const
inlineprotected

Print info like how many params have been loaded etc.

Definition at line 4575 of file MCMCProcessor.cpp.

4575  {
4576 // **************************
4577  // KS: Create a map to store the counts of unique strings
4578  std::unordered_map<std::string, int> paramCounts;
4579  std::vector<std::string> orderedKeys;
4580 
4581  for (const std::string& param : ParameterGroup) {
4582  if (paramCounts[param] == 0) {
4583  orderedKeys.push_back(param); // preserve order of first appearance
4584  }
4585  paramCounts[param]++;
4586  }
4587 
4588  MACH3LOG_INFO("************************************************");
4589  MACH3LOG_INFO("Scanning output branches...");
4590  MACH3LOG_INFO("# Useful entries in tree: \033[1;32m {} \033[0m ", nDraw);
4591  MACH3LOG_INFO("# Model params: \033[1;32m {} starting at {} \033[0m ", nParam[kXSecPar], ParamTypeStartPos[kXSecPar]);
4592  MACH3LOG_INFO("# With following groups: ");
4593  for (const std::string& key : orderedKeys) {
4594  MACH3LOG_INFO(" # {} params: {}", key, paramCounts[key]);
4595  }
4596  MACH3LOG_INFO("# ND params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kNDPar], ParamTypeStartPos[kNDPar]);
4597  MACH3LOG_INFO("# FD params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kFDDetPar], ParamTypeStartPos[kFDDetPar]);
4598  MACH3LOG_INFO("************************************************");
4599 }

◆ ReadFDFile()

void MCMCProcessor::ReadFDFile ( )
inlineprotected

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

Definition at line 2664 of file MCMCProcessor.cpp.

2664  {
2665 // ***************
2666  // Do the same for the FD
2667  TFile *FDdetFile = M3::Open(CovPos[kFDDetPar].back(), "open", __FILE__, __LINE__);
2668  FDdetFile->cd();
2669 
2670  TMatrixD *FDdetMatrix = FDdetFile->Get<TMatrixD>(CovNamePos[kFDDetPar].c_str());
2671 
2672  for (int i = 0; i < FDdetMatrix->GetNrows(); ++i)
2673  {
2674  //KS: FD parameters start at 1. in contrary to ND280
2675  ParamCentral[kFDDetPar].push_back(1.);
2676 
2677  ParamErrors[kFDDetPar].push_back( std::sqrt((*FDdetMatrix)(i,i)) );
2678  ParamNames[kFDDetPar].push_back( Form("FD Det %i", i) );
2679 
2680  //KS: Currently we can only set it via config, change it in future
2681  ParamFlat[kFDDetPar].push_back( false );
2682  }
2683  //KS: The last parameter is p scale
2684  //ETA: we need to be careful here, this is only true for SK in the T2K beam analysis...
2685  if(FancyPlotNames) ParamNames[kFDDetPar].back() = "Momentum Scale";
2686 
2687  FDdetFile->Close();
2688  delete FDdetFile;
2689  delete FDdetMatrix;
2690 }

◆ ReadInputCov()

void MCMCProcessor::ReadInputCov ( )
inlineprotected

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

Definition at line 2436 of file MCMCProcessor.cpp.

2436  {
2437 // **************************
2438  FindInputFiles();
2439  if(CovPos[kXSecPar].back() != "none") ReadModelFile();
2440 }
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 ( )
inlineprotected
Warning
This will no longer be supported in future

Definition at line 2445 of file MCMCProcessor.cpp.

2445  {
2446 // **************************
2448  if(nParam[kNDPar] > 0) ReadNDFile();
2449  if(nParam[kFDDetPar] > 0) ReadFDFile();
2450 }
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 ( )
inlineprotected

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

Definition at line 2567 of file MCMCProcessor.cpp.

2567  {
2568 // ***************
2569  YAML::Node XSecFile = CovConfig[kXSecPar];
2570 
2571  auto systematics = XSecFile["Systematics"];
2572  int paramIndex = 0;
2573  for (auto it = systematics.begin(); it != systematics.end(); ++it, ++paramIndex )
2574  {
2575  auto const &param = *it;
2576  // Push back the name
2577  std::string ParName = (param["Systematic"]["Names"]["FancyName"].as<std::string>());
2578  std::string Group = param["Systematic"]["ParameterGroup"].as<std::string>();
2579 
2580  bool rejected = false;
2581  for (unsigned int ik = 0; ik < ExcludedNames.size(); ++ik)
2582  {
2583  if (ParName.rfind(ExcludedNames[ik], 0) == 0)
2584  {
2585  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2586  rejected = true;
2587  break;
2588  }
2589  }
2590  for (unsigned int ik = 0; ik < ExcludedGroups.size(); ++ik)
2591  {
2592  if (Group == ExcludedGroups[ik])
2593  {
2594  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2595  rejected = true;
2596  break;
2597  }
2598  }
2599  if(rejected) continue;
2600 
2601  ParamNames[kXSecPar].push_back(ParName);
2602  ParamCentral[kXSecPar].push_back(param["Systematic"]["ParameterValues"]["PreFitValue"].as<double>());
2603  ParamErrors[kXSecPar].push_back(param["Systematic"]["Error"].as<double>() );
2604  ParamFlat[kXSecPar].push_back(GetFromManager<bool>(param["Systematic"]["FlatPrior"], false));
2605 
2606  ParameterGroup.push_back(Group);
2607 
2608  nParam[kXSecPar]++;
2609  ParamType.push_back(kXSecPar);
2610  // Params from osc group have branch name equal to fancy name while all others are basically xsec_0 for example
2611  if(ParameterGroup.back() == "Osc") {
2612  BranchNames.push_back(ParamNames[kXSecPar].back());
2613  } else {
2614  BranchNames.push_back("param_" + std::to_string(paramIndex));
2615  }
2616 
2617  // Check that the branch exists before setting address
2618  if (!Chain->GetBranch(BranchNames.back())) {
2619  MACH3LOG_WARN("Couldn't find branch '{}', if you are not planning to draw posteriors this might be fine", BranchNames.back());
2620  }
2621  }
2622 }
std::vector< std::string > ExcludedNames
std::vector< std::string > ExcludedGroups

◆ ReadNDFile()

void MCMCProcessor::ReadNDFile ( )
inlineprotected

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

Definition at line 2626 of file MCMCProcessor.cpp.

2626  {
2627 // ***************
2628  // Do the same for the ND280
2629  TFile *NDdetFile = M3::Open(CovPos[kNDPar].back(), "open", __FILE__, __LINE__);
2630  NDdetFile->cd();
2631 
2632  TMatrixDSym *NDdetMatrix = NDdetFile->Get<TMatrixDSym>(CovNamePos[kNDPar].c_str());
2633  TVectorD *NDdetNominal = NDdetFile->Get<TVectorD>("det_weights");
2634  TDirectory *BinningDirectory = NDdetFile->Get<TDirectory>("Binning");
2635 
2636  for (int i = 0; i < NDdetNominal->GetNrows(); ++i)
2637  {
2638  ParamCentral[kNDPar].push_back( (*NDdetNominal)(i) );
2639 
2640  ParamErrors[kNDPar].push_back( std::sqrt((*NDdetMatrix)(i,i)) );
2641  ParamNames[kNDPar].push_back( Form("ND Det %i", i) );
2642  //KS: Currently we can only set it via config, change it in future
2643  ParamFlat[kNDPar].push_back( false );
2644  }
2645 
2646  TIter next(BinningDirectory->GetListOfKeys());
2647  TKey *key = nullptr;
2648  // Loop through all entries
2649  while ((key = static_cast<TKey*>(next())))
2650  {
2651  std::string name = std::string(key->GetName());
2652  TH2Poly* RefPoly = BinningDirectory->Get<TH2Poly>((name).c_str());
2653  int size = RefPoly->GetNumberOfBins();
2654  NDSamplesBins.push_back(size);
2655  NDSamplesNames.push_back(RefPoly->GetTitle());
2656  }
2657 
2658  NDdetFile->Close();
2659  delete NDdetFile;
2660 }

◆ Reset2DPosteriors()

void MCMCProcessor::Reset2DPosteriors ( )

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

Definition at line 2759 of file MCMCProcessor.cpp.

2759  {
2760 // **************************************************
2761  #ifdef MULTITHREAD
2762  #pragma omp parallel for
2763  #endif
2764  for (int i = 0; i < nDraw; ++i)
2765  {
2766  for (int j = 0; j <= i; ++j)
2767  {
2768  // TH2D to hold the Correlation
2769  hpost2D[i][j]->Reset("");
2770  hpost2D[i][j]->Fill(0.0, 0.0, 0.0);
2771  }
2772  }
2773 }

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

3047  {
3048 // **************************
3049  MACH3LOG_INFO("Reweighting Prior");
3050 
3051  if( (Names.size() != NewCentral.size()) || (NewCentral.size() != NewError.size()))
3052  {
3053  MACH3LOG_ERROR("Size of passed vectors doesn't match in {}", __func__);
3054  throw MaCh3Exception(__FILE__ , __LINE__ );
3055  }
3056  std::vector<int> Param;
3057  std::vector<double> OldCentral;
3058  std::vector<double> OldError;
3059  std::vector<bool> FlatPrior;
3060 
3061  //KS: First we need to find parameter number based on name
3062  for(unsigned int k = 0; k < Names.size(); ++k)
3063  {
3064  //KS: First we need to find parameter number based on name
3065  int ParamNo = GetParamIndexFromName(Names[k]);
3066  if(ParamNo == M3::_BAD_INT_)
3067  {
3068  MACH3LOG_WARN("Couldn't find param {}. Can't reweight Prior", Names[k]);
3069  return;
3070  }
3071 
3072  TString Title = "";
3073  double Prior = 1.0, PriorError = 1.0;
3074  GetNthParameter(ParamNo, Prior, PriorError, Title);
3075 
3076  Param.push_back(ParamNo);
3077  OldCentral.push_back(Prior);
3078  OldError.push_back(PriorError);
3079 
3080  ParameterEnum ParType = ParamType[ParamNo];
3081  int ParamTemp = ParamNo - ParamTypeStartPos[ParType];
3082 
3083  FlatPrior.push_back(ParamFlat[ParType][ParamTemp]);
3084  }
3085  std::vector<double> ParameterPos(Names.size());
3086 
3087  std::string InputFile = MCMCFile+".root";
3088  std::string OutputFilename = MCMCFile + "_reweighted.root";
3089 
3090  //KS: Simply create copy of file and add there new branch
3091  int ret = system(("cp " + InputFile + " " + OutputFilename).c_str());
3092  if (ret != 0)
3093  MACH3LOG_WARN("Error: system call to copy file failed with code {}", ret);
3094 
3095  TFile *OutputChain = M3::Open(OutputFilename, "UPDATE", __FILE__, __LINE__);
3096  OutputChain->cd();
3097  TTree *post = OutputChain->Get<TTree>("posteriors");
3098 
3099  double Weight = 1.;
3100 
3101  post->SetBranchStatus("*",false);
3102  // Set the branch addresses for params
3103  for (unsigned int j = 0; j < Names.size(); ++j) {
3104  post->SetBranchStatus(BranchNames[Param[j]].Data(), true);
3105  post->SetBranchAddress(BranchNames[Param[j]].Data(), &ParameterPos[j]);
3106  }
3107  TBranch *bpt = post->Branch("Weight", &Weight, "Weight/D");
3108  post->SetBranchStatus("Weight", true);
3109 
3110  for (int i = 0; i < nEntries; ++i)
3111  {
3112  if(i % (nEntries/10) == 0) MaCh3Utils::PrintProgressBar(i, nEntries);
3113  post->GetEntry(i);
3114  Weight = 1.;
3115 
3116  //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 :(
3117  for (unsigned int j = 0; j < Names.size(); ++j)
3118  {
3119  double new_chi = (ParameterPos[j] - NewCentral[j])/NewError[j];
3120  double new_prior = std::exp(-0.5 * new_chi * new_chi);
3121 
3122  double old_chi = -1;
3123  double old_prior = -1;
3124  if(FlatPrior[j]) {
3125  old_prior = 1.0;
3126  } else {
3127  old_chi = (ParameterPos[j] - OldCentral[j])/OldError[j];
3128  old_prior = std::exp(-0.5 * old_chi * old_chi);
3129  }
3130  Weight *= new_prior/old_prior;
3131  }
3132  bpt->Fill();
3133  }
3134  post->SetBranchStatus("*",true);
3135  OutputChain->cd();
3136  post->Write("posteriors", TObject::kOverwrite);
3137 
3138  // KS: Save reweight metadeta
3139  std::ostringstream yaml_stream;
3140  yaml_stream << "Weight:\n";
3141  yaml_stream << " ReweightDim: 1\n";
3142  yaml_stream << " ReweightType: \"Gaussian\"\n";
3143  yaml_stream << " ReweightVar: [";
3144  for (size_t k = 0; k < Names.size(); ++k) {
3145  yaml_stream << "\"" << Names[k] << "\"";
3146  if (k < Names.size() - 1) yaml_stream << ", ";
3147  }
3148  yaml_stream << "]\n";
3149  yaml_stream << " ReweightPrior: [";
3150  for (size_t k = 0; k < Names.size(); ++k) {
3151  yaml_stream << "[" << NewCentral[k] << ", " << NewError[k] << "]";
3152  if (k < Names.size() - 1) yaml_stream << ", ";
3153  }
3154  yaml_stream << "]\n";
3155  std::string yaml_string = yaml_stream.str();
3156  YAML::Node root = STRINGtoYAML(yaml_string);
3157  TMacro ConfigSave = YAMLtoTMacro(root, "Reweight_Config");
3158  ConfigSave.Write();
3159 
3160  OutputChain->Close();
3161  delete OutputChain;
3162 
3163  OutputFile->cd();
3164 }
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 2983 of file MCMCProcessor.cpp.

2986  {
2987 // **************************
2988  // Area normalise the distributions
2989  PriorHist->Scale(1./PriorHist->Integral(), "width");
2990  PosteriorHist->Scale(1./PosteriorHist->Integral(), "width");
2991 
2992  PriorHist->SetLineColor(kRed);
2993  PriorHist->SetMarkerColor(kRed);
2994  PriorHist->SetFillColorAlpha(kRed, 0.35);
2995  PriorHist->SetFillStyle(1001);
2996  PriorHist->GetXaxis()->SetTitle(Title.c_str());
2997  PriorHist->GetYaxis()->SetTitle("Posterior Probability");
2998  PriorHist->SetMaximum(PosteriorHist->GetMaximum()*1.5);
2999  PriorHist->GetYaxis()->SetLabelOffset(999);
3000  PriorHist->GetYaxis()->SetLabelSize(0);
3001  PriorHist->SetLineWidth(2);
3002  PriorHist->SetLineStyle(kSolid);
3003 
3004  PosteriorHist->SetLineColor(kBlue);
3005  PosteriorHist->SetMarkerColor(kBlue);
3006  PosteriorHist->SetFillColorAlpha(kBlue, 0.35);
3007  PosteriorHist->SetFillStyle(1001);
3008 
3009  PriorHist->Draw("hist");
3010  PosteriorHist->Draw("hist same");
3011 
3012  double ProbPrior = PriorHist->GetBinContent(PriorHist->FindBin(EvaluationPoint));
3013  //KS: In case we go so far away that prior is 0, set this to small value to avoid dividing by 0
3014  if(ProbPrior < 0) ProbPrior = 0.00001;
3015  double ProbPosterior = PosteriorHist->GetBinContent(PosteriorHist->FindBin(EvaluationPoint));
3016  double SavageDickey = ProbPosterior/ProbPrior;
3017 
3018  std::string DunneKabothScale = GetDunneKaboth(SavageDickey);
3019  //Get Best point
3020  auto PostPoint = std::make_unique<TGraph>(1);
3021  PostPoint->SetPoint(0, EvaluationPoint, ProbPosterior);
3022  PostPoint->SetMarkerStyle(20);
3023  PostPoint->SetMarkerSize(1);
3024  PostPoint->Draw("P same");
3025 
3026  auto PriorPoint = std::make_unique<TGraph>(1);
3027  PriorPoint->SetPoint(0, EvaluationPoint, ProbPrior);
3028  PriorPoint->SetMarkerStyle(20);
3029  PriorPoint->SetMarkerSize(1);
3030  PriorPoint->Draw("P same");
3031 
3032  auto legend = std::make_unique<TLegend>(0.12, 0.6, 0.6, 0.97);
3033  SetLegendStyle(legend.get(), 0.04);
3034  legend->AddEntry(PriorHist.get(), "Prior", "l");
3035  legend->AddEntry(PosteriorHist.get(), "Posterior", "l");
3036  legend->AddEntry(PostPoint.get(), Form("SavageDickey = %.2f, (%s)", SavageDickey, DunneKabothScale.c_str()),"");
3037  legend->Draw("same");
3038 
3039  Posterior->Print(CanvasName);
3040  Posterior->Write(Title.c_str());
3041 }

◆ ScanInput()

void MCMCProcessor::ScanInput ( )
inlineprotected

Scan Input etc.

Definition at line 2196 of file MCMCProcessor.cpp.

2196  {
2197 // **************************
2198  // KS: This can reduce time necessary for caching even by half
2199  #ifdef MULTITHREAD
2200  //ROOT::EnableImplicitMT();
2201  #endif
2202 
2203  // Open the Chain
2204  Chain = new TChain("posteriors","posteriors");
2205  Chain->Add(MCMCFile.c_str());
2206 
2207  nEntries = int(Chain->GetEntries());
2208 
2209  //Only is suboptimality we might want to change it, therefore set it high enough so it doesn't affect other functionality
2210  UpperCut = nEntries+1;
2211 
2212  // Get the list of branches
2213  TObjArray* brlis = Chain->GetListOfBranches();
2214 
2215  // Get the number of branches
2216  nBranches = brlis->GetEntries();
2217 
2218  BranchNames.reserve(nBranches);
2219  ParamType.reserve(nBranches);
2220 
2221  // Read the input Covariances
2222  ReadInputCov();
2223 
2224  // Set all the branches to off
2225  Chain->SetBranchStatus("*", false);
2226 
2227  // Loop over the number of branches
2228  // Find the name and how many of each systematic we have
2229  for (int i = 0; i < nBranches; i++)
2230  {
2231  // Get the TBranch and its name
2232  TBranch* br = static_cast<TBranch*>(brlis->At(i));
2233  if(!br){
2234  MACH3LOG_ERROR("Invalid branch at position {}", i);
2235  throw MaCh3Exception(__FILE__,__LINE__);
2236  }
2237  TString bname = br->GetName();
2238 
2239  //KS: Exclude parameter types
2240  bool rejected = false;
2241  for(unsigned int ik = 0; ik < ExcludedTypes.size(); ++ik )
2242  {
2243  if(bname.BeginsWith(ExcludedTypes[ik]))
2244  {
2245  rejected = true;
2246  break;
2247  }
2248  }
2249  if(rejected) continue;
2250 
2251  // Turn on the branches which we want for parameters
2252  Chain->SetBranchStatus(bname.Data(), true);
2253 
2254  if (bname.BeginsWith("ndd_"))
2255  {
2256  BranchNames.push_back(bname);
2257  ParamType.push_back(kNDPar);
2258  nParam[kNDPar]++;
2259  }
2260  else if (bname.BeginsWith("skd_joint_"))
2261  {
2262  BranchNames.push_back(bname);
2263  ParamType.push_back(kFDDetPar);
2264  nParam[kFDDetPar]++;
2265  }
2266 
2267  //KS: as a bonus get LogL systematic
2268  if (bname.BeginsWith("LogL_sample_")) {
2269  SampleName_v.push_back(bname);
2270  }
2271  else if (bname.BeginsWith("LogL_systematic_")) {
2272  SystName_v.push_back(bname);
2273  }
2274  }
2275  nDraw = int(BranchNames.size());
2276 
2277  // Read the input Covariances
2279 
2280  // Check order of parameter types
2282 
2283  IamVaried.resize(nDraw, true);
2284 
2285  // Print useful Info
2286  PrintInfo();
2287 
2288  nSteps = Chain->GetMaximum("step");
2289  // Set the step cut to be 20%
2290  int cut = nSteps/5;
2291  SetStepCut(cut);
2292 
2293  // Basically allow loading oscillation parameters
2295 }
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 ( )
inlineprotected

Scan order of params from a different groups.

Definition at line 2356 of file MCMCProcessor.cpp.

2356  {
2357 // *****************************
2358  for(int i = 0; i < kNParameterEnum; i++)
2359  {
2360  for(unsigned int j = 0; j < ParamType.size(); j++)
2361  {
2362  if(ParamType[j] == ParameterEnum(i))
2363  {
2364  //KS: When we find that i-th parameter types start at j, save and move to the next parameter.
2365  ParamTypeStartPos[i] = j;
2366  break;
2367  }
2368  }
2369  }
2370 }

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

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

◆ SetExcludedGroups()

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

Definition at line 313 of file MCMCProcessor.h.

313 {ExcludedGroups = Name; };

◆ SetExcludedNames()

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

Definition at line 312 of file MCMCProcessor.h.

312 {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 311 of file MCMCProcessor.h.

311 {ExcludedTypes = Name; };

◆ SetFancyNames()

void MCMCProcessor::SetFancyNames ( const bool  PlotOrNot)
inline

Definition at line 301 of file MCMCProcessor.h.

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

4634  {
4635 // **************************
4636  Legend->SetTextSize(size);
4637  Legend->SetLineColor(0);
4638  Legend->SetLineStyle(0);
4639  Legend->SetFillColor(0);
4640  Legend->SetFillStyle(0);
4641  Legend->SetBorderSize(0);
4642 }

◆ SetMargins()

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

Set TCanvas margins to specified values.

Definition at line 4609 of file MCMCProcessor.cpp.

4609  {
4610 // **************************
4611  if (!Canv) {
4612  MACH3LOG_ERROR("Canv is nullptr");
4613  throw MaCh3Exception(__FILE__, __LINE__);
4614  }
4615  if (margins.size() != 4) {
4616  MACH3LOG_ERROR("Margin vector must have exactly 4 elements");
4617  throw MaCh3Exception(__FILE__, __LINE__);
4618  }
4619  Canv->SetTopMargin(margins[0]);
4620  Canv->SetBottomMargin(margins[1]);
4621  Canv->SetLeftMargin(margins[2]);
4622  Canv->SetRightMargin(margins[3]);
4623 }

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

317 {nBatches = Batches; };

◆ SetNBins()

void MCMCProcessor::SetNBins ( const int  NewBins)
inline

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

Definition at line 261 of file MCMCProcessor.h.

261 {nBins = NewBins;};

◆ SetnLags()

void MCMCProcessor::SetnLags ( const int  nLags)
inline

Definition at line 318 of file MCMCProcessor.h.

318 {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 321 of file MCMCProcessor.h.

321 {OutputSuffix = Suffix; };

◆ SetPlotBinValue()

void MCMCProcessor::SetPlotBinValue ( const bool  PlotOrNot)
inline

Definition at line 300 of file MCMCProcessor.h.

300 {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 299 of file MCMCProcessor.h.

299 {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 295 of file MCMCProcessor.h.

295 {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 306 of file MCMCProcessor.h.

306 {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 323 of file MCMCProcessor.h.

323 {Posterior1DCut = Cut; };

◆ SetPrintToPDF()

void MCMCProcessor::SetPrintToPDF ( const bool  PlotOrNot)
inline

Whether to dump all plots into PDF.

Definition at line 297 of file MCMCProcessor.h.

297 {printToPDF = PlotOrNot; };

◆ SetSmoothing()

void MCMCProcessor::SetSmoothing ( const bool  PlotOrNot)
inline

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

Definition at line 303 of file MCMCProcessor.h.

303 {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 2704 of file MCMCProcessor.cpp.

2704  {
2705 // ***************
2706  std::stringstream TempStream;
2707  TempStream << "step > " << Cuts;
2708  StepCut = TempStream.str();
2709  BurnInCut = Cuts;
2710  CheckStepCut();
2711 }
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 2694 of file MCMCProcessor.cpp.

2694  {
2695 // ***************
2696  StepCut = Cuts;
2697  BurnInCut = std::stoi( Cuts );
2698 
2699  CheckStepCut();
2700 }

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

4626  {
4627 // **************************
4628  Line->SetLineColor(Colour);
4629  Line->SetLineWidth(Width);
4630  Line->SetLineStyle(Style);
4631 }
constexpr ELineStyle Style[NVars]

◆ SetupOutput()

void MCMCProcessor::SetupOutput ( )
inlineprotected

Prepare all objects used for output.

Definition at line 2299 of file MCMCProcessor.cpp.

2299  {
2300 // ****************************
2301  // Make sure we can read files located anywhere and strip the .root ending
2302  MCMCFile = MCMCFile.substr(0, MCMCFile.find(".root"));
2303 
2304  // Check if the output file is ready
2305  if (OutputFile == nullptr) MakeOutputFile();
2306 
2307  CanvasName = MCMCFile + OutputSuffix + ".pdf[";
2308  if(printToPDF) Posterior->Print(CanvasName);
2309 
2310  // Once the pdf file is open no longer need to bracket
2311  CanvasName.ReplaceAll("[","");
2312 
2313  // We fit with this Gaussian
2314  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);
2315  Gauss->SetLineWidth(2);
2316  Gauss->SetLineColor(kOrange-5);
2317 
2318  // Declare the TVectors
2319  Covariance = new TMatrixDSym(nDraw);
2320  Correlation = new TMatrixDSym(nDraw);
2321  Central_Value = new TVectorD(nDraw);
2322  Means = new TVectorD(nDraw);
2323  Errors = new TVectorD(nDraw);
2324  Means_Gauss = new TVectorD(nDraw);
2325  Errors_Gauss = new TVectorD(nDraw);
2326  Means_HPD = new TVectorD(nDraw);
2327  Errors_HPD = new TVectorD(nDraw);
2328  Errors_HPD_Positive = new TVectorD(nDraw);
2329  Errors_HPD_Negative = new TVectorD(nDraw);
2330 
2331  // Initialise to something silly
2332  #ifdef MULTITHREAD
2333  #pragma omp parallel for
2334  #endif
2335  for (int i = 0; i < nDraw; ++i)
2336  {
2337  (*Central_Value)(i) = M3::_BAD_DOUBLE_;
2338  (*Means)(i) = M3::_BAD_DOUBLE_;
2339  (*Errors)(i) = M3::_BAD_DOUBLE_;
2340  (*Means_Gauss)(i) = M3::_BAD_DOUBLE_;
2341  (*Errors_Gauss)(i) = M3::_BAD_DOUBLE_;
2342  (*Means_HPD)(i) = M3::_BAD_DOUBLE_;
2343  (*Errors_HPD)(i) = M3::_BAD_DOUBLE_;
2344  (*Errors_HPD_Positive)(i) = M3::_BAD_DOUBLE_;
2345  (*Errors_HPD_Negative)(i) = M3::_BAD_DOUBLE_;
2346  for (int j = 0; j < nDraw; ++j) {
2347  (*Covariance)(i, j) = M3::_BAD_DOUBLE_;
2348  (*Correlation)(i, j) = M3::_BAD_DOUBLE_;
2349  }
2350  }
2351  hpost.resize(nDraw);
2352 }

◆ SetUseFFTAutoCorrelation()

void MCMCProcessor::SetUseFFTAutoCorrelation ( const bool  useFFT)
inline

Toggle using the FFT-based autocorrelation calculator.

Definition at line 308 of file MCMCProcessor.h.

308 {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 3169 of file MCMCProcessor.cpp.

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

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

206 { 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 586 of file MCMCProcessor.h.

◆ AccProbValues

double* MCMCProcessor::AccProbValues
protected

Holds all accProb.

Definition at line 584 of file MCMCProcessor.h.

◆ ApplySmoothing

bool MCMCProcessor::ApplySmoothing
protected

Apply smoothing for 2D histos using root algorithm.

Definition at line 502 of file MCMCProcessor.h.

◆ AutoCorrLag

int MCMCProcessor::AutoCorrLag
protected

LagL used in AutoCorrelation.

Definition at line 573 of file MCMCProcessor.h.

◆ BatchedAverages

double** MCMCProcessor::BatchedAverages
protected

Values of batched average for every param and batch.

Definition at line 576 of file MCMCProcessor.h.

◆ BranchNames

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

Definition at line 452 of file MCMCProcessor.h.

◆ BurnInCut

unsigned int MCMCProcessor::BurnInCut
protected

Value of burn in cut.

Definition at line 437 of file MCMCProcessor.h.

◆ CacheMCMC

bool MCMCProcessor::CacheMCMC
protected

MCMC Chain has been cached.

Definition at line 565 of file MCMCProcessor.h.

◆ CanvasName

TString MCMCProcessor::CanvasName
protected

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

Definition at line 485 of file MCMCProcessor.h.

◆ Central_Value

TVectorD* MCMCProcessor::Central_Value
protected

Vector with central value for each parameter.

Definition at line 522 of file MCMCProcessor.h.

◆ Chain

TChain* MCMCProcessor::Chain
protected

Main chain storing all steps etc.

Definition at line 429 of file MCMCProcessor.h.

◆ Correlation

TMatrixDSym* MCMCProcessor::Correlation
protected

Posterior Correlation Matrix.

Definition at line 543 of file MCMCProcessor.h.

◆ Covariance

TMatrixDSym* MCMCProcessor::Covariance
protected

Posterior Covariance Matrix.

Definition at line 541 of file MCMCProcessor.h.

◆ CovConfig

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

Covariance matrix config.

Definition at line 426 of file MCMCProcessor.h.

◆ CovNamePos

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

Covariance matrix name position.

Definition at line 424 of file MCMCProcessor.h.

◆ CovPos

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

Covariance matrix file name position.

Definition at line 422 of file MCMCProcessor.h.

◆ doDiagMCMC

bool MCMCProcessor::doDiagMCMC
protected

Doing MCMC Diagnostic.

Definition at line 567 of file MCMCProcessor.h.

◆ DrawRange

double MCMCProcessor::DrawRange
protected

Drawrange for SetMaximum.

Definition at line 562 of file MCMCProcessor.h.

◆ Errors

TVectorD* MCMCProcessor::Errors
protected

Vector with errors values using RMS.

Definition at line 526 of file MCMCProcessor.h.

◆ Errors_Gauss

TVectorD* MCMCProcessor::Errors_Gauss
protected

Vector with error values using Gaussian fit.

Definition at line 530 of file MCMCProcessor.h.

◆ Errors_HPD

TVectorD* MCMCProcessor::Errors_HPD
protected

Vector with error values using Highest Posterior Density.

Definition at line 534 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 538 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 536 of file MCMCProcessor.h.

◆ ExcludedGroups

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

Definition at line 455 of file MCMCProcessor.h.

◆ ExcludedNames

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

Definition at line 454 of file MCMCProcessor.h.

◆ ExcludedTypes

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

Definition at line 453 of file MCMCProcessor.h.

◆ FancyPlotNames

bool MCMCProcessor::FancyPlotNames
protected

Whether we want fancy plot names or not.

Definition at line 498 of file MCMCProcessor.h.

◆ Gauss

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

Gaussian fitter.

Definition at line 512 of file MCMCProcessor.h.

◆ hpost

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

Holds 1D Posterior Distributions.

Definition at line 546 of file MCMCProcessor.h.

◆ hpost2D

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

Holds 2D Posterior Distributions.

Definition at line 548 of file MCMCProcessor.h.

◆ hviolin

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

Holds violin plot for all dials.

Definition at line 550 of file MCMCProcessor.h.

◆ hviolin_prior

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

Holds prior violin plot for all dials,.

Definition at line 552 of file MCMCProcessor.h.

◆ IamVaried

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

Is the ith parameter varied.

Definition at line 458 of file MCMCProcessor.h.

◆ MadePostfit

bool MCMCProcessor::MadePostfit
protected

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

Definition at line 494 of file MCMCProcessor.h.

◆ MCMCFile

std::string MCMCProcessor::MCMCFile
protected

Name of MCMC file.

Definition at line 418 of file MCMCProcessor.h.

◆ Means

TVectorD* MCMCProcessor::Means
protected

Vector with mean values using Arithmetic Mean.

Definition at line 524 of file MCMCProcessor.h.

◆ Means_Gauss

TVectorD* MCMCProcessor::Means_Gauss
protected

Vector with mean values using Gaussian fit.

Definition at line 528 of file MCMCProcessor.h.

◆ Means_HPD

TVectorD* MCMCProcessor::Means_HPD
protected

Vector with mean values using Highest Posterior Density.

Definition at line 532 of file MCMCProcessor.h.

◆ nBatches

int MCMCProcessor::nBatches
protected

Number of batches for Batched Mean.

Definition at line 571 of file MCMCProcessor.h.

◆ nBins

int MCMCProcessor::nBins
protected

Number of bins.

Definition at line 560 of file MCMCProcessor.h.

◆ nBranches

int MCMCProcessor::nBranches
protected

Number of branches in a TTree.

Definition at line 439 of file MCMCProcessor.h.

◆ nDraw

int MCMCProcessor::nDraw
protected

Number of all parameters used in the analysis.

Definition at line 449 of file MCMCProcessor.h.

◆ NDSamplesBins

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

Definition at line 508 of file MCMCProcessor.h.

◆ NDSamplesNames

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

Definition at line 509 of file MCMCProcessor.h.

◆ nEntries

int MCMCProcessor::nEntries
protected

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

Definition at line 441 of file MCMCProcessor.h.

◆ nParam

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

Number of parameters per type.

Definition at line 468 of file MCMCProcessor.h.

◆ nParameterHandlers

int MCMCProcessor::nParameterHandlers
protected

Number of covariance objects.

Definition at line 447 of file MCMCProcessor.h.

◆ nSampleHandlers

int MCMCProcessor::nSampleHandlers
protected

Number of sample PDF objects.

Definition at line 445 of file MCMCProcessor.h.

◆ nSteps

int MCMCProcessor::nSteps
protected

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

Definition at line 443 of file MCMCProcessor.h.

◆ OutputFile

TFile* MCMCProcessor::OutputFile
protected

The output file.

Definition at line 515 of file MCMCProcessor.h.

◆ OutputName

std::string MCMCProcessor::OutputName
protected

Name of output files.

Definition at line 483 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 420 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 462 of file MCMCProcessor.h.

◆ ParamErrors

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

Uncertainty on a single parameter.

Definition at line 464 of file MCMCProcessor.h.

◆ ParameterGroup

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

Definition at line 475 of file MCMCProcessor.h.

◆ ParamFlat

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

Whether Param has flat prior or not.

Definition at line 466 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 460 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 470 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 473 of file MCMCProcessor.h.

◆ ParStep

M3::float_t** MCMCProcessor::ParStep
protected

Array holding values for all parameters.

Definition at line 555 of file MCMCProcessor.h.

◆ plotBinValue

bool MCMCProcessor::plotBinValue
protected

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

Definition at line 500 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 488 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 492 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 504 of file MCMCProcessor.h.

◆ Posterior

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

Fancy canvas used for our beautiful plots.

Definition at line 518 of file MCMCProcessor.h.

◆ Posterior1DCut

std::string MCMCProcessor::Posterior1DCut
protected

Cut used when making 1D Posterior distribution.

Definition at line 433 of file MCMCProcessor.h.

◆ printToPDF

bool MCMCProcessor::printToPDF
protected

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

Definition at line 496 of file MCMCProcessor.h.

◆ ReweightName

std::string MCMCProcessor::ReweightName
protected

Name of branch used for chain reweighting.

Definition at line 591 of file MCMCProcessor.h.

◆ ReweightPosterior

bool MCMCProcessor::ReweightPosterior
protected

Whether to apply reweighting weight or not.

Definition at line 589 of file MCMCProcessor.h.

◆ SampleName_v

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

Vector of each systematic.

Definition at line 478 of file MCMCProcessor.h.

◆ SampleValues

double** MCMCProcessor::SampleValues
protected

Holds the sample values.

Definition at line 579 of file MCMCProcessor.h.

◆ StepCut

std::string MCMCProcessor::StepCut
protected

BurnIn Cuts.

Definition at line 431 of file MCMCProcessor.h.

◆ StepNumber

unsigned int* MCMCProcessor::StepNumber
protected

Step number for step, important if chains were merged.

Definition at line 557 of file MCMCProcessor.h.

◆ SystName_v

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

Vector of each sample PDF object.

Definition at line 480 of file MCMCProcessor.h.

◆ SystValues

double** MCMCProcessor::SystValues
protected

Holds the systs values.

Definition at line 581 of file MCMCProcessor.h.

◆ UpperCut

unsigned int MCMCProcessor::UpperCut
protected

KS: Used only for SubOptimality.

Definition at line 435 of file MCMCProcessor.h.

◆ useFFTAutoCorrelation

bool MCMCProcessor::useFFTAutoCorrelation
protected

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

Definition at line 506 of file MCMCProcessor.h.

◆ WeightValue

double* MCMCProcessor::WeightValue
protected

Stores value of weight for each step.

Definition at line 593 of file MCMCProcessor.h.


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