MaCh3  2.2.3
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 [27]. More...
 
void ResetHistograms ()
 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 > &NewCentral, const bool &SaveBranch)
 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)
 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)
 
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 xsec_, then passing "xsec_" 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...
 
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] [28]. 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] [20]. 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 nSamples
 Number of sample PDF objects. More...
 
int nSysts
 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 > > ParamNom
 
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...
 
double ** 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 * ParamSums
 Total parameter sum for each param. 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 Wiki.
Author
Clarence Wret
Kamil Skwarczynski

Definition at line 61 of file MCMCProcessor.h.

Constructor & Destructor Documentation

◆ MCMCProcessor()

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

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

Parameters
InputFileThe path to the input file containing MCMC data.

Definition at line 17 of file MCMCProcessor.cpp.

17  :
18  Chain(nullptr), StepCut(""), MadePostfit(false) {
19 // ****************************
20  MCMCFile = InputFile;
21 
24  MACH3LOG_INFO("Making post-fit processor for: {}", MCMCFile);
25 
26  ParStep = nullptr;
27  StepNumber = nullptr;
28  ReweightPosterior = false;
29  WeightValue = nullptr;
30 
31  Posterior = nullptr;
32  hviolin = nullptr;
33  hviolin_prior = nullptr;
34 
35  OutputFile = nullptr;
36 
37  ParamSums = nullptr;
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  nSysts = 0;
70  nSamples = 0;
71 
72  nBins = 70;
73  DrawRange = 1.5;
74 
75  Posterior1DCut = "";
76  //KS:Those keep basic information for ParameterEnum
79  ParamNom.resize(kNParameterEnum);
81  ParamFlat.resize(kNParameterEnum);
83  nParam.resize(kNParameterEnum);
84  CovPos.resize(kNParameterEnum);
86  CovConfig.resize(kNParameterEnum);
87 
88  for(int i = 0; i < kNParameterEnum; i++)
89  {
90  ParamTypeStartPos[i] = 0;
91  nParam[i] = 0;
92  }
93  //Only if GPU is enabled
94  #ifdef MaCh3_CUDA
95  ParStep_cpu = nullptr;
96  NumeratorSum_cpu = nullptr;
97  ParamSums_cpu = nullptr;
98  DenomSum_cpu = nullptr;
99 
100  ParStep_gpu = nullptr;
101  NumeratorSum_gpu = nullptr;
102  ParamSums_gpu = nullptr;
103  DenomSum_gpu = nullptr;
104  #endif
105 }
@ kNParameterEnum
Definition: MCMCProcessor.h:53
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:25
void SetMaCh3LoggerFormat()
Set messaging format of the logger.
Definition: MaCh3Logger.h:51
int nBatches
Number of batches for Batched Mean.
double ** 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,.
int nSamples
Number of sample PDF objects.
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.
std::vector< std::vector< double > > ParamNom
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.
double * ParamSums
Total parameter sum for each param.
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.
int nSysts
Number of covariance objects.
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:48
void MaCh3Welcome()
KS: Prints welcome message with MaCh3 logo.
Definition: Monitor.cpp:12

◆ ~MCMCProcessor()

MCMCProcessor::~MCMCProcessor ( )
virtual

Destroys the MCMCProcessor object.

Definition at line 109 of file MCMCProcessor.cpp.

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

4428  {
4429 // **************************
4430  if (AccProbBatchedAverages == nullptr) PrepareDiagMCMC();
4431 
4432  MACH3LOG_INFO("Making AccProb plots...");
4433 
4434  // Set the titles and limits for TH1Ds
4435  auto AcceptanceProbPlot = std::make_unique<TH1D>("AcceptanceProbability", "Acceptance Probability", nEntries, 0, nEntries);
4436  AcceptanceProbPlot->GetXaxis()->SetTitle("Step");
4437  AcceptanceProbPlot->GetYaxis()->SetTitle("Acceptance Probability");
4438 
4439  auto BatchedAcceptanceProblot = std::make_unique<TH1D>("AcceptanceProbability_Batch", "AcceptanceProbability_Batch", nBatches, 0, nBatches);
4440  BatchedAcceptanceProblot->GetYaxis()->SetTitle("Acceptance Probability");
4441 
4442  for (int i = 0; i < nBatches; ++i) {
4443  BatchedAcceptanceProblot->SetBinContent(i+1, AccProbBatchedAverages[i]);
4444  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4445  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4446  std::stringstream ss;
4447  ss << BatchRangeLow << " - " << BatchRangeHigh;
4448  BatchedAcceptanceProblot->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4449  }
4450 
4451  #ifdef MULTITHREAD
4452  #pragma omp parallel for
4453  #endif
4454  for (int i = 0; i < nEntries; ++i) {
4455  // Set bin content for the i-th bin to the parameter values
4456  AcceptanceProbPlot->SetBinContent(i, AccProbValues[i]);
4457  }
4458 
4459  TDirectory *probDir = OutputFile->mkdir("AccProb");
4460  probDir->cd();
4461 
4462  AcceptanceProbPlot->Write();
4463  BatchedAcceptanceProblot->Write();
4464  delete[] AccProbValues;
4465  delete[] AccProbBatchedAverages;
4466 
4467  probDir->Close();
4468  delete probDir;
4469 
4470  OutputFile->cd();
4471 }
void PrepareDiagMCMC()
CW: Prepare branches etc. for DiagMCMC.

◆ AutoCorrelation()

void MCMCProcessor::AutoCorrelation ( )
inlineprotected

KS: Calculate autocorrelations supports both OpenMP and CUDA :)

Definition at line 3685 of file MCMCProcessor.cpp.

3685  {
3686 // *********************************
3687  if (ParStep == nullptr) PrepareDiagMCMC();
3688 
3689  TStopwatch clock;
3690  clock.Start();
3691  const int nLags = AutoCorrLag;
3692  MACH3LOG_INFO("Making auto-correlations for nLags = {}", nLags);
3693 
3694  // The sum of (Y-Ymean)^2 over all steps for each parameter
3695  std::vector<std::vector<double>> DenomSum(nDraw);
3696  std::vector<std::vector<double>> NumeratorSum(nDraw);
3697  std::vector<std::vector<double>> LagL(nDraw);
3698  for (int j = 0; j < nDraw; ++j) {
3699  DenomSum[j].resize(nLags);
3700  NumeratorSum[j].resize(nLags);
3701  LagL[j].resize(nLags);
3702  }
3703  std::vector<TH1D*> LagKPlots(nDraw);
3704  // Loop over the parameters of interest
3705  for (int j = 0; j < nDraw; ++j)
3706  {
3707  // Loop over each lag
3708  for (int k = 0; k < nLags; ++k) {
3709  NumeratorSum[j][k] = 0.0;
3710  DenomSum[j][k] = 0.0;
3711  LagL[j][k] = 0.0;
3712  }
3713 
3714  // Make TH1Ds for each parameter which hold the lag
3715  TString Title = "";
3716  double Prior = 1.0, PriorError = 1.0;
3717 
3718  GetNthParameter(j, Prior, PriorError, Title);
3719  std::string HistName = Form("%s_%s_Lag", Title.Data(), BranchNames[j].Data());
3720  LagKPlots[j] = new TH1D(HistName.c_str(), HistName.c_str(), nLags, 0.0, nLags);
3721  LagKPlots[j]->GetXaxis()->SetTitle("Lag");
3722  LagKPlots[j]->GetYaxis()->SetTitle("Auto-correlation function");
3723  }
3724 //KS: If CUDA is not enabled do calculations on CPU
3725 #ifndef MaCh3_CUDA
3726  // Loop over the lags
3727  //CW: Each lag is independent so might as well multi-thread them!
3728  #ifdef MULTITHREAD
3729  MACH3LOG_INFO("Using multi-threading...");
3730  #pragma omp parallel for collapse(2)
3731  #endif // Loop over the number of parameters
3732  for (int j = 0; j < nDraw; ++j) {
3733  for (int k = 0; k < nLags; ++k) {
3734  // Loop over the number of entries
3735  for (int i = 0; i < nEntries; ++i) {
3736  const double Diff = ParStep[j][i]-ParamSums[j];
3737 
3738  // Only sum the numerator up to i = N-k
3739  if (i < nEntries-k) {
3740  const double LagTerm = ParStep[j][i+k]-ParamSums[j];
3741  const double Product = Diff*LagTerm;
3742  NumeratorSum[j][k] += Product;
3743  }
3744  // Square the difference to form the denominator
3745  const double Denom = Diff*Diff;
3746  DenomSum[j][k] += Denom;
3747  }
3748  }
3749  }
3750 #else //NOW GPU specific code
3751  MACH3LOG_INFO("Using GPU");
3752  //KS: This allocates memory and copy data from CPU to GPU
3753  PrepareGPU_AutoCorr(nLags);
3754 
3755  //KS: This runs the main kernel and copy results back to CPU
3757  ParStep_gpu,
3758  ParamSums_gpu,
3759  NumeratorSum_gpu,
3760  DenomSum_gpu,
3761  NumeratorSum_cpu,
3762  DenomSum_cpu);
3763 
3764  #ifdef MULTITHREAD
3765  #pragma omp parallel for collapse(2)
3766  #endif
3767  //KS: Now that that we received data from GPU convert it to CPU-like format
3768  for (int j = 0; j < nDraw; ++j)
3769  {
3770  for (int k = 0; k < nLags; ++k)
3771  {
3772  const int temp_index = j*nLags+k;
3773  NumeratorSum[j][k] = NumeratorSum_cpu[temp_index];
3774  DenomSum[j][k] = DenomSum_cpu[temp_index];
3775  }
3776  }
3777  //delete auxiliary variables
3778  delete[] NumeratorSum_cpu;
3779  delete[] DenomSum_cpu;
3780  delete[] ParStep_cpu;
3781  delete[] ParamSums_cpu;
3782 
3783  //KS: Delete stuff at GPU as well
3785  ParStep_gpu,
3786  NumeratorSum_gpu,
3787  ParamSums_gpu,
3788  DenomSum_gpu);
3789 
3790 //KS: End of GPU specific code
3791 #endif
3792 
3793  OutputFile->cd();
3794  TDirectory *AutoCorrDir = OutputFile->mkdir("Auto_corr");
3795  // Now fill the LagK auto-correlation plots
3796  for (int j = 0; j < nDraw; ++j) {
3797  for (int k = 0; k < nLags; ++k) {
3798  LagL[j][k] = NumeratorSum[j][k]/DenomSum[j][k];
3799  LagKPlots[j]->SetBinContent(k, NumeratorSum[j][k]/DenomSum[j][k]);
3800  }
3801  AutoCorrDir->cd();
3802  LagKPlots[j]->Write();
3803  delete LagKPlots[j];
3804  }
3805 
3806  //KS: This is different diagnostic however it relies on calculated Lag, thus we call it before we delete LagKPlots
3807  CalculateESS(nLags, LagL);
3808 
3809  delete[] ParamSums;
3810 
3811  AutoCorrDir->Close();
3812  delete AutoCorrDir;
3813 
3814  OutputFile->cd();
3815 
3816  clock.Stop();
3817  MACH3LOG_INFO("Making auto-correlations took {:.2f}s", clock.RealTime());
3818 }
void GetNthParameter(const int param, double &Prior, double &PriorError, TString &Title) const
Get properties of parameter by passing it number.
void CalculateESS(const int nLags, const std::vector< std::vector< double >> &LagL)
KS: calc Effective Sample Size.
std::vector< TString > BranchNames
__host__ void RunGPU_AutoCorr(float *ParStep_gpu, float *ParamSums_gpu, float *NumeratorSum_gpu, float *DenomSum_gpu, float *NumeratorSum_cpu, float *DenomSum_cpu)
KS: This call the main kernel responsible for calculating LagL and later copy results back to CPU.
__host__ void CleanupGPU_AutoCorr(float *ParStep_gpu, float *NumeratorSum_gpu, float *ParamSums_gpu, float *DenomSum_gpu)
KS: free memory on gpu.

◆ AutoCorrelation_FFT()

void MCMCProcessor::AutoCorrelation_FFT ( )
inlineprotected

MJR: Autocorrelation function using FFT algorithm for extra speed.

Author
Michael Reh

Definition at line 3590 of file MCMCProcessor.cpp.

3590  {
3591 // *********************************
3592  if (ParStep == nullptr) PrepareDiagMCMC();
3593 
3594  TStopwatch clock;
3595  clock.Start();
3596  const int nLags = AutoCorrLag;
3597  MACH3LOG_INFO("Making auto-correlations for nLags = {}", nLags);
3598 
3599  // Prep outputs
3600  OutputFile->cd();
3601  TDirectory* AutoCorrDir = OutputFile->mkdir("Auto_corr");
3602  std::vector<TH1D*> LagKPlots(nDraw);
3603  std::vector<std::vector<double>> LagL(nDraw);
3604 
3605  // Arrays needed to perform FFT using ROOT
3606  std::vector<double> ACFFT(nEntries, 0.0); // Main autocorrelation array
3607  std::vector<double> ParVals(nEntries, 0.0); // Param values for full chain
3608  std::vector<double> ParValsFFTR(nEntries, 0.0); // FFT Real part
3609  std::vector<double> ParValsFFTI(nEntries, 0.0); // FFT Imaginary part
3610  std::vector<double> ParValsFFTSquare(nEntries, 0.0); // FFT Absolute square
3611  std::vector<double> ParValsComplex(nEntries, 0.0); // Input Imaginary values (0)
3612 
3613  // Create forward and reverse FFT objects. I don't love using ROOT here,
3614  // but it works so I can't complain
3615  TVirtualFFT* fftf = TVirtualFFT::FFT(1, &nEntries, "C2CFORWARD");
3616  TVirtualFFT* fftb = TVirtualFFT::FFT(1, &nEntries, "C2CBACKWARD");
3617 
3618  // Loop over all pars and calculate the full autocorrelation function using FFT
3619  for (int j = 0; j < nDraw; ++j) {
3620  // Initialize
3621  LagL[j].resize(nLags);
3622  for (int i = 0; i < nEntries; ++i) {
3623  ParVals[i] = ParStep[j][i]-ParamSums[j]; // Subtract the mean to make it numerically tractable
3624  ParValsComplex[i] = 0.; // Reset dummy array
3625  }
3626 
3627  // Transform
3628  fftf->SetPointsComplex(ParVals.data(), ParValsComplex.data());
3629  fftf->Transform();
3630  fftf->GetPointsComplex(ParValsFFTR.data(), ParValsFFTI.data());
3631 
3632  // Square the results to get the power spectrum
3633  for (int i = 0; i < nEntries; ++i) {
3634  ParValsFFTSquare[i] = ParValsFFTR[i]*ParValsFFTR[i] + ParValsFFTI[i]*ParValsFFTI[i];
3635  }
3636 
3637  // Transforming back gives the autocovariance
3638  fftb->SetPointsComplex(ParValsFFTSquare.data(), ParValsComplex.data());
3639  fftb->Transform();
3640  fftb->GetPointsComplex(ACFFT.data(), ParValsComplex.data());
3641 
3642  // Divide by norm to get autocorrelation
3643  double normAC = ACFFT[0];
3644  for (int i = 0; i < nEntries; ++i) {
3645  ACFFT[i] /= normAC;
3646  }
3647 
3648  // Get plotting info
3649  TString Title = "";
3650  double Prior = 1.0, PriorError = 1.0;
3651  GetNthParameter(j, Prior, PriorError, Title);
3652  std::string HistName = Form("%s_%s_Lag", Title.Data(), BranchNames[j].Data());
3653 
3654  // Initialize Lag plot
3655  LagKPlots[j] = new TH1D(HistName.c_str(), HistName.c_str(), nLags, 0.0, nLags);
3656  LagKPlots[j]->GetXaxis()->SetTitle("Lag");
3657  LagKPlots[j]->GetYaxis()->SetTitle("Auto-correlation function");
3658 
3659  // Fill plot
3660  for (int k = 0; k < nLags; ++k) {
3661  LagL[j][k] = ACFFT[k];
3662  LagKPlots[j]->SetBinContent(k, ACFFT[k]);
3663  }
3664 
3665  // Write and clean up
3666  AutoCorrDir->cd();
3667  LagKPlots[j]->Write();
3668  delete LagKPlots[j];
3669  }
3670 
3671  //KS: This is different diagnostic however it relies on calculated Lag, thus we call it before we delete LagKPlots
3672  CalculateESS(nLags, LagL);
3673 
3674  AutoCorrDir->Close();
3675  delete AutoCorrDir;
3676 
3677  OutputFile->cd();
3678 
3679  clock.Stop();
3680  MACH3LOG_INFO("Making auto-correlations took {:.2f}s", clock.RealTime());
3681 }

◆ BatchedAnalysis()

void MCMCProcessor::BatchedAnalysis ( )
inlineprotected

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

Definition at line 4059 of file MCMCProcessor.cpp.

4059  {
4060 // **************************
4061  if(BatchedAverages == nullptr)
4062  {
4063  MACH3LOG_ERROR("BatchedAverages haven't been initialises or have been deleted something is wrong");
4064  MACH3LOG_ERROR("I need it and refuse to go further");
4065  throw MaCh3Exception(__FILE__ , __LINE__ );
4066  }
4067 
4068  // Calculate variance estimator using batched means following @cite chakraborty2019estimating see Eq. 1.2
4069  TVectorD* BatchedVariance = new TVectorD(nDraw);
4070  //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
4071  TVectorD* C_Test_Statistics = new TVectorD(nDraw);
4072 
4073  std::vector<double> OverallBatchMean(nDraw);
4074  std::vector<double> C_Rho_Nominator(nDraw);
4075  std::vector<double> C_Rho_Denominator(nDraw);
4076  std::vector<double> C_Nominator(nDraw);
4077  std::vector<double> C_Denominator(nDraw);
4078  const int BatchLength = nEntries/nBatches+1;
4079 //KS: Start parallel region
4080 #ifdef MULTITHREAD
4081 #pragma omp parallel
4082 {
4083 #endif
4084  #ifdef MULTITHREAD
4085  #pragma omp for
4086  #endif
4087  //KS: First calculate mean of batched means for each param and Initialise everything to 0
4088  for (int j = 0; j < nDraw; ++j)
4089  {
4090  OverallBatchMean[j] = 0.0;
4091  C_Rho_Nominator[j] = 0.0;
4092  C_Rho_Denominator[j] = 0.0;
4093  C_Nominator[j] = 0.0;
4094  C_Denominator[j] = 0.0;
4095 
4096  (*BatchedVariance)(j) = 0.0;
4097  (*C_Test_Statistics)(j) = 0.0;
4098  for (int i = 0; i < nBatches; ++i)
4099  {
4100  OverallBatchMean[j] += BatchedAverages[i][j];
4101  }
4102  OverallBatchMean[j] /= nBatches;
4103  }
4104 
4105  #ifdef MULTITHREAD
4106  #pragma omp for nowait
4107  #endif
4108  //KS: next loop is completely independent thus nowait clause
4109  for (int j = 0; j < nDraw; ++j)
4110  {
4111  for (int i = 0; i < nBatches; ++i)
4112  {
4113  (*BatchedVariance)(j) += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4114  }
4115  (*BatchedVariance)(j) = (BatchLength/(nBatches-1))* (*BatchedVariance)(j);
4116  }
4117 
4118  //KS: Now we focus on C test statistic, again use nowait as next is calculation is independent
4119  #ifdef MULTITHREAD
4120  #pragma omp for nowait
4121  #endif
4122  for (int j = 0; j < nDraw; ++j)
4123  {
4124  C_Nominator[j] = (OverallBatchMean[j] - BatchedAverages[0][j])*(OverallBatchMean[j] - BatchedAverages[0][j]) +
4125  (OverallBatchMean[j] - BatchedAverages[nBatches-1][j])*(OverallBatchMean[j] - BatchedAverages[nBatches-1][j]);
4126  for (int i = 0; i < nBatches; ++i)
4127  {
4128  C_Denominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4129  }
4130  C_Denominator[j] = 2*C_Denominator[j];
4131  }
4132 
4133  //KS: We still calculate C and for this we need rho wee need autocorrelations between batches
4134  #ifdef MULTITHREAD
4135  #pragma omp for
4136  #endif
4137  for (int j = 0; j < nDraw; ++j)
4138  {
4139  for (int i = 0; i < nBatches-1; ++i)
4140  {
4141  C_Rho_Nominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i+1][j]);
4142  }
4143 
4144  for (int i = 0; i < nBatches; ++i)
4145  {
4146  C_Rho_Denominator[j] += (OverallBatchMean[j] - BatchedAverages[i][j])*(OverallBatchMean[j] - BatchedAverages[i][j]);
4147  }
4148  }
4149 
4150  //KS: Final calculations of C
4151  #ifdef MULTITHREAD
4152  #pragma omp for
4153  #endif
4154  for (int j = 0; j < nDraw; ++j)
4155  {
4156  (*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]);
4157  }
4158 #ifdef MULTITHREAD
4159 } //End parallel region
4160 #endif
4161 
4162  //Save to file
4163  OutputFile->cd();
4164  BatchedVariance->Write("BatchedMeansVariance");
4165  C_Test_Statistics->Write("C_Test_Statistics");
4166 
4167  //Delete all variables
4168  delete BatchedVariance;
4169  delete C_Test_Statistics;
4170 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:27
Custom exception class for MaCh3 errors.

◆ BatchedMeans()

void MCMCProcessor::BatchedMeans ( )
inlineprotected

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

Definition at line 4001 of file MCMCProcessor.cpp.

4001  {
4002 // **************************
4003  if (BatchedAverages == nullptr) PrepareDiagMCMC();
4004  MACH3LOG_INFO("Making BatchedMeans plots...");
4005 
4006  std::vector<TH1D*> BatchedParamPlots(nDraw);
4007  for (int j = 0; j < nDraw; ++j) {
4008  TString Title = "";
4009  double Prior = 1.0, PriorError = 1.0;
4010 
4011  GetNthParameter(j, Prior, PriorError, Title);
4012 
4013  std::string HistName = Form("%s_%s_batch", Title.Data(), BranchNames[j].Data());
4014  BatchedParamPlots[j] = new TH1D(HistName.c_str(), HistName.c_str(), nBatches, 0, nBatches);
4015  }
4016 
4017  #ifdef MULTITHREAD
4018  #pragma omp parallel for
4019  #endif
4020  for (int j = 0; j < nDraw; ++j) {
4021  for (int i = 0; i < nBatches; ++i) {
4022  BatchedParamPlots[j]->SetBinContent(i+1, BatchedAverages[i][j]);
4023  const int BatchRangeLow = double(i)*double(nEntries)/double(nBatches);
4024  const int BatchRangeHigh = double(i+1)*double(nEntries)/double(nBatches);
4025  std::stringstream ss;
4026  ss << BatchRangeLow << " - " << BatchRangeHigh;
4027  BatchedParamPlots[j]->GetXaxis()->SetBinLabel(i+1, ss.str().c_str());
4028  }
4029  }
4030 
4031  TDirectory *BatchDir = OutputFile->mkdir("Batched_means");
4032  BatchDir->cd();
4033  for (int j = 0; j < nDraw; ++j) {
4034  TF1 *Fitter = new TF1("Fitter","[0]", 0, nBatches);
4035  Fitter->SetLineColor(kRed);
4036  BatchedParamPlots[j]->Fit("Fitter","Rq");
4037  BatchedParamPlots[j]->Write();
4038  delete Fitter;
4039  delete BatchedParamPlots[j];
4040  }
4041 
4042  //KS: Get the batched means variance estimation and variable indicating if number of batches is sensible
4043  // We do this before deleting BatchedAverages
4044  BatchedAnalysis();
4045 
4046  for (int i = 0; i < nBatches; ++i) {
4047  delete BatchedAverages[i];
4048  }
4049  delete[] BatchedAverages;
4050 
4051  BatchDir->Close();
4052  delete BatchDir;
4053 
4054  OutputFile->cd();
4055 }
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 1072 of file MCMCProcessor.cpp.

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

◆ 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. [30] [14] [9]

Definition at line 3904 of file MCMCProcessor.cpp.

3904  {
3905 // **************************
3906  if(LagL.size() == 0)
3907  {
3908  MACH3LOG_ERROR("Size of LagL is {}", LagL.size());
3909  throw MaCh3Exception(__FILE__ , __LINE__ );
3910  }
3911  MACH3LOG_INFO("Making ESS plots...");
3912  TVectorD* EffectiveSampleSize = new TVectorD(nDraw);
3913  TVectorD* SamplingEfficiency = new TVectorD(nDraw);
3914  std::vector<double> TempDenominator(nDraw);
3915 
3916  constexpr int Nhists = 5;
3917  constexpr double Thresholds[Nhists + 1] = {1, 0.02, 0.005, 0.001, 0.0001, 0.0};
3918  constexpr Color_t ESSColours[Nhists] = {kGreen, kGreen + 2, kYellow, kOrange, kRed};
3919 
3920  //KS: This histogram is inspired by the following: @cite gabry2024visual
3921  std::vector<std::unique_ptr<TH1D>> EffectiveSampleSizeHist(Nhists);
3922  for(int i = 0; i < Nhists; ++i)
3923  {
3924  EffectiveSampleSizeHist[i] =
3925  std::make_unique<TH1D>(Form("EffectiveSampleSizeHist_%i", i), Form("EffectiveSampleSizeHist_%i", i), nDraw, 0, nDraw);
3926  EffectiveSampleSizeHist[i]->GetYaxis()->SetTitle("N_{eff}/N");
3927  EffectiveSampleSizeHist[i]->SetFillColor(ESSColours[i]);
3928  EffectiveSampleSizeHist[i]->SetLineColor(ESSColours[i]);
3929  EffectiveSampleSizeHist[i]->Sumw2();
3930  for (int j = 0; j < nDraw; ++j)
3931  {
3932  TString Title = "";
3933  double Prior = 1.0, PriorError = 1.0;
3934  GetNthParameter(j, Prior, PriorError, Title);
3935  EffectiveSampleSizeHist[i]->GetXaxis()->SetBinLabel(j+1, Title.Data());
3936  }
3937  }
3938 
3939  #ifdef MULTITHREAD
3940  #pragma omp parallel for
3941  #endif
3942  //KS: Calculate ESS and MCMC efficiency for each parameter
3943  for (int j = 0; j < nDraw; ++j)
3944  {
3945  (*EffectiveSampleSize)(j) = M3::_BAD_DOUBLE_;
3946  (*SamplingEfficiency)(j) = M3::_BAD_DOUBLE_;
3947  TempDenominator[j] = 0.;
3948  //KS: Firs sum over all Calculated autocorrelations
3949  for (int k = 0; k < nLags; ++k)
3950  {
3951  TempDenominator[j] += LagL[j][k];
3952  }
3953  TempDenominator[j] = 1+2*TempDenominator[j];
3954  (*EffectiveSampleSize)(j) = double(nEntries)/TempDenominator[j];
3955  // 100 because we convert to percentage
3956  (*SamplingEfficiency)(j) = 100 * 1/TempDenominator[j];
3957 
3958  for(int i = 0; i < Nhists; ++i)
3959  {
3960  EffectiveSampleSizeHist[i]->SetBinContent(j+1, 0);
3961  EffectiveSampleSizeHist[i]->SetBinError(j+1, 0);
3962 
3963  const double TempEntry = std::fabs((*EffectiveSampleSize)(j)) / double(nEntries);
3964  if(Thresholds[i] >= TempEntry && TempEntry > Thresholds[i+1])
3965  {
3966  if( std::isnan((*EffectiveSampleSize)(j)) ) continue;
3967  EffectiveSampleSizeHist[i]->SetBinContent(j+1, TempEntry);
3968  }
3969  }
3970  }
3971 
3972  //KS Write to the output tree
3973  //Save to file
3974  OutputFile->cd();
3975  EffectiveSampleSize->Write("EffectiveSampleSize");
3976  SamplingEfficiency->Write("SamplingEfficiency");
3977 
3978  EffectiveSampleSizeHist[0]->SetTitle("Effective Sample Size");
3979  EffectiveSampleSizeHist[0]->Draw();
3980  for(int i = 1; i < Nhists; ++i)
3981  {
3982  EffectiveSampleSizeHist[i]->Draw("SAME");
3983  }
3984 
3985  auto leg = std::make_unique<TLegend>(0.2, 0.7, 0.6, 0.95);
3986  SetLegendStyle(leg.get(), 0.03);
3987  for(int i = 0; i < Nhists; ++i)
3988  {
3989  leg->AddEntry(EffectiveSampleSizeHist[i].get(), Form("%.4f >= N_{eff}/N > %.4f", Thresholds[i], Thresholds[i+1]), "f");
3990  } leg->Draw("SAME");
3991 
3992  Posterior->Write("EffectiveSampleSizeCanvas");
3993 
3994  //Delete all variables
3995  delete EffectiveSampleSize;
3996  delete SamplingEfficiency;
3997 }
double * EffectiveSampleSize
Definition: RHat.cpp:67
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:46

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

4474  {
4475 // **************************
4476  if (CredibleIntervals.size() != CredibleIntervalsColours.size()) {
4477  MACH3LOG_ERROR("size of CredibleIntervals is not equal to size of CredibleIntervalsColours");
4478  throw MaCh3Exception(__FILE__, __LINE__);
4479  }
4480  if (CredibleIntervals.size() > 1) {
4481  for (unsigned int i = 1; i < CredibleIntervals.size(); i++) {
4482  if (CredibleIntervals[i] > CredibleIntervals[i - 1]) {
4483  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4484  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleIntervals[i], CredibleIntervals[i - 1]);
4485  MACH3LOG_ERROR("They should be grouped in decreasing order");
4486  throw MaCh3Exception(__FILE__, __LINE__);
4487  }
4488  }
4489  }
4490 }

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

4495  {
4496 // **************************
4497  if ((CredibleRegions.size() != CredibleRegionStyle.size()) || (CredibleRegionStyle.size() != CredibleRegionColor.size())) {
4498  MACH3LOG_ERROR("size of CredibleRegions is not equal to size of CredibleRegionStyle or CredibleRegionColor");
4499  throw MaCh3Exception(__FILE__, __LINE__);
4500  }
4501  for (unsigned int i = 1; i < CredibleRegions.size(); i++) {
4502  if (CredibleRegions[i] > CredibleRegions[i - 1]) {
4503  MACH3LOG_ERROR("Interval {} is smaller than {}", i, i - 1);
4504  MACH3LOG_ERROR("{:.2f} {:.2f}", CredibleRegions[i], CredibleRegions[i - 1]);
4505  MACH3LOG_ERROR("They should be grouped in decreasing order");
4506  throw MaCh3Exception(__FILE__, __LINE__);
4507  }
4508  }
4509 }

◆ CheckStepCut()

void MCMCProcessor::CheckStepCut ( ) const

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

Definition at line 2685 of file MCMCProcessor.cpp.

2685  {
2686 // ***************
2687  const unsigned int maxNsteps = Chain->GetMaximum("step");
2688  if(BurnInCut > maxNsteps){
2689  MACH3LOG_ERROR("StepCut({}) is larger than highest value of step({})", BurnInCut, maxNsteps);
2690  throw MaCh3Exception(__FILE__ , __LINE__ );
2691  }
2692 }
unsigned int BurnInCut
Value of burn in cut.

◆ DiagMCMC()

void MCMCProcessor::DiagMCMC ( )

KS: Perform MCMC diagnostic including Autocorrelation, Trace etc.

Definition at line 3304 of file MCMCProcessor.cpp.

3304  {
3305 // **************************
3306  // Prepare branches etc for DiagMCMC
3307  PrepareDiagMCMC();
3308 
3309  // Draw the simple trace matrices
3310  ParamTraces();
3311 
3312  // Get the batched means
3313  BatchedMeans();
3314 
3315  // Draw the auto-correlations
3316  if (useFFTAutoCorrelation) {
3318  } else {
3319  AutoCorrelation();
3320  }
3321 
3322  // Calculate Power Spectrum for each param
3324 
3325  // Get Geweke Z score helping select burn-in
3326  GewekeDiagnostic();
3327 
3328  // Draw acceptance Probability
3330 }
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 1641 of file MCMCProcessor.cpp.

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

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

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

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

2411  {
2412 // **************************
2413  // Now read the MCMC file
2414  TFile *TempFile = new TFile(MCMCFile.c_str(), "open");
2415  TDirectory* CovarianceFolder = TempFile->Get<TDirectory>("CovarianceFolder");
2416 
2417  // Get the settings for the MCMC
2418  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2419 
2420  if (Config == nullptr) {
2421  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2422  TempFile->ls();
2423  throw MaCh3Exception(__FILE__ , __LINE__ );
2424  }
2425  MACH3LOG_INFO("Loading YAML config from MCMC chain");
2426 
2427  YAML::Node Settings = TMacroToYAML(*Config);
2428 
2429  bool InputNotFound = false;
2430  //CW: Get the xsec Covariance matrix
2431  CovPos[kXSecPar] = GetFromManager<std::vector<std::string>>(Settings["General"]["Systematics"]["XsecCovFile"], {"none"});
2432  if(CovPos[kXSecPar].back() == "none")
2433  {
2434  MACH3LOG_WARN("Couldn't find XsecCov branch in output");
2435  InputNotFound = true;
2436  }
2437 
2438  TMacro *XsecConfig = M3::GetConfigMacroFromChain(CovarianceFolder);
2439  if (XsecConfig == nullptr) {
2440  MACH3LOG_WARN("Didn't find Config_xsec_cov tree in MCMC file! {}", MCMCFile);
2441  } else {
2442  CovConfig[kXSecPar] = TMacroToYAML(*XsecConfig);
2443  }
2444  if(InputNotFound) MaCh3Utils::PrintConfig(Settings);
2445 
2446  for(size_t i = 0; i < CovPos[kXSecPar].size(); i++)
2448 
2449  // Delete the TTrees and the input file handle since we've now got the settings we need
2450  delete Config;
2451  delete XsecConfig;
2452 
2453  TMacro *ReweightConfig = TempFile->Get<TMacro>("Reweight_Config");
2454  if (ReweightConfig != nullptr) {
2455  YAML::Node ReweightSettings = TMacroToYAML(*ReweightConfig);
2456 
2457  if (ReweightSettings["Weight"]) {
2458  ReweightName = "Weight";
2459  ReweightPosterior = true;
2460  MACH3LOG_INFO("Enabling reweighting with following Config");
2461  } else {
2462  MACH3LOG_WARN("Found reweight config but without field ''Weight''");
2463  }
2464  MaCh3Utils::PrintConfig(ReweightSettings);
2465  }
2466 
2467  // Delete the MCMCFile pointer we're reading
2468  CovarianceFolder->Close();
2469  delete CovarianceFolder;
2470  TempFile->Close();
2471  delete TempFile;
2472 }
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:26
YAML::Node TMacroToYAML(const TMacro &macro)
KS: Convert a ROOT TMacro object to a YAML node.
Definition: YamlHelper.h:147
void AddPath(std::string &FilePath)
Prepends the MACH3 environment path to FilePath if it is not already present.
Definition: Monitor.cpp:367
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:295

◆ FindInputFilesLegacy()

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

Definition at line 2476 of file MCMCProcessor.cpp.

2476  {
2477 // **************************
2478  // Now read the MCMC file
2479  TFile *TempFile = new TFile(MCMCFile.c_str(), "open");
2480 
2481  // Get the settings for the MCMC
2482  TMacro *Config = TempFile->Get<TMacro>("MaCh3_Config");
2483 
2484  if (Config == nullptr) {
2485  MACH3LOG_ERROR("Didn't find MaCh3_Config tree in MCMC file! {}", MCMCFile);
2486  TempFile->ls();
2487  throw MaCh3Exception(__FILE__ , __LINE__ );
2488  }
2489  YAML::Node Settings = TMacroToYAML(*Config);
2490 
2491  //CW: And the ND Covariance matrix
2492  CovPos[kNDPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovFile"], "none"));
2493 
2494  if(CovPos[kNDPar].back() == "none") {
2495  MACH3LOG_WARN("Couldn't find NDCov (legacy) branch in output");
2496  } else{
2497  //If the FD Cov is not none, then you need the name of the covariance object to grab
2498  CovNamePos[kNDPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["NDCovName"], "none");
2499  MACH3LOG_INFO("Given NDCovFile {} and NDCovName {}", CovPos[kNDPar].back(), CovNamePos[kNDPar]);
2500  }
2501 
2502  //CW: And the FD Covariance matrix
2503  CovPos[kFDDetPar].push_back(GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovFile"], "none"));
2504 
2505  if(CovPos[kFDDetPar].back() == "none") {
2506  MACH3LOG_WARN("Couldn't find FDCov (legacy) branch in output");
2507  } else {
2508  //If the FD Cov is not none, then you need the name of the covariance object to grab
2509  CovNamePos[kFDDetPar] = GetFromManager<std::string>(Settings["General"]["Systematics"]["FDCovName"], "none");
2510  MACH3LOG_INFO("Given FDCovFile {} and FDCovName {}", CovPos[kFDDetPar].back(), CovNamePos[kFDDetPar]);
2511  }
2512 
2513  for(size_t i = 0; i < CovPos[kNDPar].size(); i++)
2514  M3::AddPath(CovPos[kNDPar][i]);
2515 
2516  for(size_t i = 0; i < CovPos[kFDDetPar].size(); i++)
2518 
2519  TempFile->Close();
2520  delete TempFile;
2521 }
@ kFDDetPar
Definition: MCMCProcessor.h:51

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

2819  {
2820 // **************************
2821  if(hpost[0] == nullptr) MakePostfit();
2822 
2823  MACH3LOG_INFO("Calculating Bayes Factor");
2824  if((ParNames.size() != Model1Bounds.size()) || (Model2Bounds.size() != Model1Bounds.size()) || (Model2Bounds.size() != ModelNames.size()))
2825  {
2826  MACH3LOG_ERROR("Size doesn't match");
2827  throw MaCh3Exception(__FILE__ , __LINE__ );
2828  }
2829  for(unsigned int k = 0; k < ParNames.size(); ++k)
2830  {
2831  //KS: First we need to find parameter number based on name
2832  int ParamNo = GetParamIndexFromName(ParNames[k]);
2833  if(ParamNo == M3::_BAD_INT_)
2834  {
2835  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Bayes Factor", ParNames[k]);
2836  continue;
2837  }
2838 
2839  const double M1_min = Model1Bounds[k][0];
2840  const double M2_min = Model2Bounds[k][0];
2841  const double M1_max = Model1Bounds[k][1];
2842  const double M2_max = Model2Bounds[k][1];
2843 
2844  long double IntegralMode1 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M1_min), hpost[ParamNo]->FindFixBin(M1_max));
2845  long double IntegralMode2 = hpost[ParamNo]->Integral(hpost[ParamNo]->FindFixBin(M2_min), hpost[ParamNo]->FindFixBin(M2_max));
2846 
2847  double BayesFactor = 0.;
2848  std::string Name = "";
2849  //KS: Calc Bayes Factor
2850  //If M1 is more likely
2851  if(IntegralMode1 >= IntegralMode2)
2852  {
2853  BayesFactor = IntegralMode1/IntegralMode2;
2854  Name = "\\mathfrak{B}(" + ModelNames[k][0]+ "/" + ModelNames[k][1] + ") = " + std::to_string(BayesFactor);
2855  }
2856  else //If M2 is more likely
2857  {
2858  BayesFactor = IntegralMode2/IntegralMode1;
2859  Name = "\\mathfrak{B}(" + ModelNames[k][1]+ "/" + ModelNames[k][0] + ") = " + std::to_string(BayesFactor);
2860  }
2861  std::string JeffreysScale = GetJeffreysScale(BayesFactor);
2862  std::string DunneKabothScale = GetDunneKaboth(BayesFactor);
2863 
2864  MACH3LOG_INFO("{} for {}", Name, ParNames[k]);
2865  MACH3LOG_INFO("Following Jeffreys Scale = {}", JeffreysScale);
2866  MACH3LOG_INFO("Following Dunne-Kaboth Scale = {}", DunneKabothScale);
2867  MACH3LOG_INFO("");
2868  }
2869 }
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)
Get parameter number based on name.

◆ GetBranchNames()

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

Get the vector of branch names from root file.

Definition at line 248 of file MCMCProcessor.h.

248 { return BranchNames;};

◆ GetCovariance()

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

Get the post-fit covariances and correlations.

Parameters
CovCovariance matrix
CorrCorrelation matrix

Definition at line 196 of file MCMCProcessor.cpp.

196  {
197 // ***************
199  else MakeCovariance();
200  Cov = static_cast<TMatrixDSym*>(Covariance->Clone());
201  Corr = static_cast<TMatrixDSym*>(Correlation->Clone());
202 }
void MakeCovariance_MP(const bool Mute=false)
Calculate covariance by making 2D projection of each combination of parameters using multithreading.
void MakeCovariance()
Calculate covariance by making 2D projection of each combination of parameters.

◆ GetCovConfig()

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

Get Yaml config obtained from a Chain.

Definition at line 216 of file MCMCProcessor.h.

216 {return CovConfig.at(i); }

◆ GetFDCov()

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

Definition at line 236 of file MCMCProcessor.h.

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

◆ GetGroup()

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

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

Definition at line 4512 of file MCMCProcessor.cpp.

4512  {
4513 // **************************
4514  // Lambda to compare strings case-insensitively
4515  auto caseInsensitiveCompare = [](const std::string& a, const std::string& b) {
4516  return std::equal(a.begin(), a.end(), b.begin(), b.end(),
4517  [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
4518  };
4519  int numerator = 0;
4520  for (const auto& groupName : ParameterGroup) {
4521  if (caseInsensitiveCompare(groupName, name)) {
4522  numerator++;
4523  }
4524  }
4525  return numerator;
4526 }

◆ GetHpost()

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

Get 1D posterior for a given parameter.

Parameters
iparameter index

Definition at line 223 of file MCMCProcessor.h.

223 { return hpost[i]; };

◆ GetHpost2D()

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

Get 2D posterior for a given parameter combination.

Parameters
iparameter index X
jparameter index Y

Definition at line 227 of file MCMCProcessor.h.

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

◆ GetMargins()

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

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

Definition at line 4556 of file MCMCProcessor.cpp.

4556  {
4557 // **************************
4558  return std::vector<double>{Canv->GetTopMargin(), Canv->GetBottomMargin(),
4559  Canv->GetLeftMargin(), Canv->GetRightMargin()};
4560 }

◆ GetNDCov()

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

Definition at line 235 of file MCMCProcessor.h.

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

◆ GetnEntries()

Long64_t MCMCProcessor::GetnEntries ( )
inline

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

Definition at line 254 of file MCMCProcessor.h.

254 {return nEntries;};

◆ GetNFD()

int MCMCProcessor::GetNFD ( ) const
inline

Definition at line 213 of file MCMCProcessor.h.

213 { return nParam[kFDDetPar]; };

◆ GetNND()

int MCMCProcessor::GetNND ( ) const
inline

Definition at line 212 of file MCMCProcessor.h.

212 { return nParam[kNDPar]; };

◆ GetNParams()

int MCMCProcessor::GetNParams ( ) const
inline

Get total number of used parameters.

Definition at line 210 of file MCMCProcessor.h.

210 { return nDraw; };

◆ GetnSteps()

Long64_t MCMCProcessor::GetnSteps ( )
inline

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

Definition at line 256 of file MCMCProcessor.h.

256 {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 2696 of file MCMCProcessor.cpp.

2696  {
2697 // **************************
2698  ParameterEnum ParType = ParamType[param];
2699  int ParamNo = M3::_BAD_INT_;
2700  ParamNo = param - ParamTypeStartPos[ParType];
2701 
2702  Prior = ParamCentral[ParType][ParamNo];
2703  PriorError = ParamErrors[ParType][ParamNo];
2704  Title = ParamNames[ParType][ParamNo];
2705 }

◆ GetNXSec()

int MCMCProcessor::GetNXSec ( ) const
inline

Definition at line 211 of file MCMCProcessor.h.

211 { return nParam[kXSecPar]; };

◆ GetParamIndexFromName()

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

Get parameter number based on name.

Definition at line 2709 of file MCMCProcessor.cpp.

2709  {
2710 // **************************
2711  int ParamNo = M3::_BAD_INT_;
2712  for (int i = 0; i < nDraw; ++i)
2713  {
2714  TString Title = "";
2715  double Prior = 1.0, PriorError = 1.0;
2716  GetNthParameter(i, Prior, PriorError, Title);
2717 
2718  if(Name == Title)
2719  {
2720  ParamNo = i;
2721  break;
2722  }
2723  }
2724  return ParamNo;
2725 }

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

2747  {
2748 // **************************
2749  if(hpost[0] == nullptr) MakePostfit();
2750 
2751  std::vector<double> Margins = GetMargins(Posterior);
2752 
2753  Posterior->SetTopMargin(0.1);
2754  Posterior->SetBottomMargin(0.1);
2755  Posterior->SetLeftMargin(0.1);
2756  Posterior->SetRightMargin(0.1);
2757  Posterior->Update();
2758 
2759  MACH3LOG_INFO("Calculating Polar Plot");
2760  TDirectory *PolarDir = OutputFile->mkdir("PolarDir");
2761  PolarDir->cd();
2762 
2763  for(unsigned int k = 0; k < ParNames.size(); ++k)
2764  {
2765  //KS: First we need to find parameter number based on name
2766  int ParamNo = GetParamIndexFromName(ParNames[k]);
2767  if(ParamNo == M3::_BAD_INT_)
2768  {
2769  MACH3LOG_WARN("Couldn't find param {}. Will not calculate Polar Plot", ParNames[k]);
2770  continue;
2771  }
2772 
2773  TString Title = "";
2774  double Prior = 1.0, PriorError = 1.0;
2775  GetNthParameter(ParamNo, Prior, PriorError, Title);
2776 
2777  std::vector<double> x_val(nBins);
2778  std::vector<double> y_val(nBins);
2779 
2780  constexpr double xmin = 0;
2781  constexpr double xmax = 2*TMath::Pi();
2782 
2783  double Integral = hpost[ParamNo]->Integral();
2784  for (Int_t ipt = 0; ipt < nBins; ipt++)
2785  {
2786  x_val[ipt] = ipt*(xmax-xmin)/nBins+xmin;
2787  y_val[ipt] = hpost[ParamNo]->GetBinContent(ipt+1)/Integral;
2788  }
2789 
2790  auto PolarGraph = std::make_unique<TGraphPolar>(nBins, x_val.data(), y_val.data());
2791  PolarGraph->SetLineWidth(2);
2792  PolarGraph->SetFillStyle(3001);
2793  PolarGraph->SetLineColor(kRed);
2794  PolarGraph->SetFillColor(kRed);
2795  PolarGraph->Draw("AFL");
2796 
2797  auto Text = std::make_unique<TText>(0.6, 0.1, Title);
2798  Text->SetTextSize(0.04);
2799  Text->SetNDC(true);
2800  Text->Draw("");
2801 
2802  Posterior->Print(CanvasName);
2803  Posterior->Write(Title);
2804  } //End loop over parameters
2805 
2806  PolarDir->Close();
2807  delete PolarDir;
2808 
2809  OutputFile->cd();
2810 
2811  SetMargins(Posterior, Margins);
2812 }

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

163  {
164 // ***************
165  // Make the post fit
166  MakePostfit();
167 
168  // We now have the private members
169  Central_PDF = Means;
170  Errors_PDF = Errors;
171  Central_G = Means_Gauss;
172  Errors_G = Errors_Gauss;
173  Peak_Values = Means_HPD;
174 }

◆ GetPostfit_Ind()

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

Or the individual post-fits.

Definition at line 178 of file MCMCProcessor.cpp.

178  {
179 // ***************
180  // Make the post fit
181  MakePostfit();
182 
183  // Loop over the loaded param types
184  const int ParamTypeSize = int(ParamType.size());
185  int ParamNumber = 0;
186  for (int i = 0; i < ParamTypeSize; ++i) {
187  if (ParamType[i] != kParam) continue;
188  (*PDF_Central)(ParamNumber) = (*Means)(i);
189  (*PDF_Errors)(ParamNumber) = (*Errors)(i);
190  (*Peak_Values)(ParamNumber) = (*Means_HPD)(i);
191  ++ParamNumber;
192  }
193 }

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

2875  {
2876 // **************************
2877  if((ParNames.size() != EvaluationPoint.size()) || (Bounds.size() != EvaluationPoint.size()))
2878  {
2879  MACH3LOG_ERROR("Size doesn't match");
2880  throw MaCh3Exception(__FILE__ , __LINE__ );
2881  }
2882 
2883  if(hpost[0] == nullptr) MakePostfit();
2884 
2885  MACH3LOG_INFO("Calculating Savage Dickey");
2886  TDirectory *SavageDickeyDir = OutputFile->mkdir("SavageDickey");
2887  SavageDickeyDir->cd();
2888 
2889  for(unsigned int k = 0; k < ParNames.size(); ++k)
2890  {
2891  //KS: First we need to find parameter number based on name
2892  int ParamNo = GetParamIndexFromName(ParNames[k]);
2893  if(ParamNo == M3::_BAD_INT_)
2894  {
2895  MACH3LOG_WARN("Couldn't find param {}. Will not calculate SavageDickey", ParNames[k]);
2896  continue;
2897  }
2898 
2899  TString Title = "";
2900  double Prior = 1.0, PriorError = 1.0;
2901  bool FlatPrior = false;
2902  GetNthParameter(ParamNo, Prior, PriorError, Title);
2903 
2904  ParameterEnum ParType = ParamType[ParamNo];
2905  int ParamTemp = ParamNo - ParamTypeStartPos[ParType];
2906  FlatPrior = ParamFlat[ParType][ParamTemp];
2907 
2908  auto PosteriorHist = M3::Clone<TH1D>(hpost[ParamNo], std::string(Title));
2909  RemoveFitter(PosteriorHist.get(), "Gauss");
2910 
2911  std::unique_ptr<TH1D> PriorHist;
2912  //KS: If flat prior we need to have well defined bounds otherwise Prior distribution will not make sense
2913  if(FlatPrior)
2914  {
2915  int NBins = PosteriorHist->GetNbinsX();
2916  if(Bounds[k][0] > Bounds[k][1])
2917  {
2918  MACH3LOG_ERROR("Lower bound is higher than upper bound");
2919  throw MaCh3Exception(__FILE__ , __LINE__ );
2920  }
2921  PriorHist = std::make_unique<TH1D>("PriorHist", Title, NBins, Bounds[k][0], Bounds[k][1]);
2922 
2923  double FlatProb = ( Bounds[k][1] - Bounds[k][0]) / NBins;
2924  for (int g = 0; g < NBins + 1; ++g)
2925  {
2926  PriorHist->SetBinContent(g+1, FlatProb);
2927  }
2928  }
2929  else //KS: Otherwise throw from Gaussian
2930  {
2931  PriorHist = M3::Clone<TH1D>(PosteriorHist.get(), "Prior");
2932  PriorHist->Reset("");
2933  PriorHist->Fill(0.0, 0.0);
2934 
2935  auto rand = std::make_unique<TRandom3>(0);
2936  //KS: Throw nice gaussian, just need big number to have smooth distribution
2937  for(int g = 0; g < 1000000; ++g)
2938  {
2939  PriorHist->Fill(rand->Gaus(Prior, PriorError));
2940  }
2941  }
2942  SavageDickeyPlot(PriorHist, PosteriorHist, std::string(Title), EvaluationPoint[k]);
2943  } //End loop over parameters
2944 
2945  SavageDickeyDir->Close();
2946  delete SavageDickeyDir;
2947 
2948  OutputFile->cd();
2949 }
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 229 of file MCMCProcessor.h.

229 { return hviolin.get(); };

◆ GetViolinPrior()

TH2D* MCMCProcessor::GetViolinPrior ( ) const
inline

Get Violin plot for all parameters with prior values.

Definition at line 231 of file MCMCProcessor.h.

231 { return hviolin_prior.get(); };

◆ GetXSecCov()

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

Definition at line 234 of file MCMCProcessor.h.

234 { return CovPos[kXSecPar]; };

◆ GewekeDiagnostic()

void MCMCProcessor::GewekeDiagnostic ( )
inlineprotected

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

Definition at line 4296 of file MCMCProcessor.cpp.

4296  {
4297 // **************************
4298  MACH3LOG_INFO("Making Geweke Diagnostic");
4299  //KS: Up refers to upper limit we check, it stays constant, in literature it is mostly 50% thus using 0.5 for threshold
4300  std::vector<double> MeanUp(nDraw, 0.0);
4301  std::vector<double> SpectralVarianceUp(nDraw, 0.0);
4302  std::vector<int> DenomCounterUp(nDraw, 0);
4303  const double Threshold = 0.5 * nSteps;
4304 
4305  //KS: Select values between which you want to scan, for example 0 means 0% burn in and 1 100% burn in.
4306  constexpr double LowerThreshold = 0;
4307  constexpr double UpperThreshold = 1.0;
4308  // Tells how many intervals between thresholds we want to check
4309  constexpr int NChecks = 100;
4310  constexpr double Division = (UpperThreshold - LowerThreshold)/NChecks;
4311 
4312  std::vector<std::unique_ptr<TH1D>> GewekePlots(nDraw);
4313  for (int j = 0; j < nDraw; ++j)
4314  {
4315  TString Title = "";
4316  double Prior = 1.0, PriorError = 1.0;
4317  GetNthParameter(j, Prior, PriorError, Title);
4318  std::string HistName = Form("%s_%s_Geweke", Title.Data(), BranchNames[j].Data());
4319  GewekePlots[j] = std::make_unique<TH1D>(HistName.c_str(), HistName.c_str(), NChecks, 0.0, 100 * UpperThreshold);
4320  GewekePlots[j]->GetXaxis()->SetTitle("Burn-In (%)");
4321  GewekePlots[j]->GetYaxis()->SetTitle("Geweke T score");
4322  }
4323 
4324 //KS: Start parallel region
4325 #ifdef MULTITHREAD
4326 #pragma omp parallel
4327 {
4328 #endif
4329  //KS: First we calculate mean and spectral variance for the upper limit, this doesn't change and in literature is most often 50%
4330  #ifdef MULTITHREAD
4331  #pragma omp for
4332  #endif
4333  for (int j = 0; j < nDraw; ++j)
4334  {
4335  for(int i = 0; i < nEntries; ++i)
4336  {
4337  if(StepNumber[i] > Threshold)
4338  {
4339  MeanUp[j] += ParStep[j][i];
4340  DenomCounterUp[j]++;
4341  }
4342  }
4343  MeanUp[j] = MeanUp[j]/DenomCounterUp[j];
4344  }
4345 
4346  //KS: now Spectral variance which in this case is sample variance
4347  #ifdef MULTITHREAD
4348  #pragma omp for collapse(2)
4349  #endif
4350  for (int j = 0; j < nDraw; ++j)
4351  {
4352  for(int i = 0; i < nEntries; ++i)
4353  {
4354  if(StepNumber[i] > Threshold)
4355  {
4356  SpectralVarianceUp[j] += (ParStep[j][i] - MeanUp[j])*(ParStep[j][i] - MeanUp[j]);
4357  }
4358  }
4359  }
4360 
4361  //Loop over how many intervals we calculate
4362  #ifdef MULTITHREAD
4363  #pragma omp for
4364  #endif
4365  for (int k = 1; k < NChecks+1; ++k)
4366  {
4367  //KS each thread has it's own
4368  std::vector<double> MeanDown(nDraw, 0.0);
4369  std::vector<double> SpectralVarianceDown(nDraw, 0.0);
4370  std::vector<int> DenomCounterDown(nDraw, 0);
4371 
4372  const unsigned int ThresholsCheck = Division*k*nSteps;
4373  //KS: First mean
4374  for (int j = 0; j < nDraw; ++j)
4375  {
4376  for(int i = 0; i < nEntries; ++i)
4377  {
4378  if(StepNumber[i] < ThresholsCheck)
4379  {
4380  MeanDown[j] += ParStep[j][i];
4381  DenomCounterDown[j]++;
4382  }
4383  }
4384  MeanDown[j] = MeanDown[j]/DenomCounterDown[j];
4385  }
4386  //Now spectral variance
4387  for (int j = 0; j < nDraw; ++j)
4388  {
4389  for(int i = 0; i < nEntries; ++i)
4390  {
4391  if(StepNumber[i] < ThresholsCheck)
4392  {
4393  SpectralVarianceDown[j] += (ParStep[j][i] - MeanDown[j])*(ParStep[j][i] - MeanDown[j]);
4394  }
4395  }
4396  }
4397  //Lastly calc T score and fill histogram entry
4398  for (int j = 0; j < nDraw; ++j)
4399  {
4400  double T_score = std::fabs((MeanDown[j] - MeanUp[j])/std::sqrt(SpectralVarianceDown[j]/DenomCounterDown[j] + SpectralVarianceUp[j]/DenomCounterUp[j]));
4401  GewekePlots[j]->SetBinContent(k, T_score);
4402  }
4403  } //end loop over intervals
4404 #ifdef MULTITHREAD
4405 } //End parallel region
4406 #endif
4407 
4408  //Finally save it to TFile
4409  OutputFile->cd();
4410  TDirectory *GewekeDir = OutputFile->mkdir("Geweke");
4411  for (int j = 0; j < nDraw; ++j)
4412  {
4413  GewekeDir->cd();
4414  GewekePlots[j]->Write();
4415  }
4416  for (int i = 0; i < nDraw; ++i) {
4417  delete[] ParStep[i];
4418  }
4419  delete[] ParStep;
4420 
4421  GewekeDir->Close();
4422  delete GewekeDir;
4423  OutputFile->cd();
4424 }

◆ Initialise()

void MCMCProcessor::Initialise ( )

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

Definition at line 153 of file MCMCProcessor.cpp.

153  {
154 // ***************
155  // Scan the ROOT file for useful branches
156  ScanInput();
157 
158  // Setup the output
159  SetupOutput();
160 }
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 343 of file MCMCProcessor.h.

343 {};

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

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

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

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

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

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

Definition at line 1776 of file MCMCProcessor.cpp.

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

205  {
206 // ***************
207  //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
208  auto rand = std::make_unique<TRandom3>(0);
209  const int uniform = int(rand->Uniform(0, 10000));
210  // Open a TCanvas to write the posterior onto
211  Posterior = std::make_unique<TCanvas>(("Posterior" + std::to_string(uniform)).c_str(), ("Posterior" + std::to_string(uniform)).c_str(), 0, 0, 1024, 1024);
212  //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.
213  TCandle::SetScaledViolin(false);
214 
215  Posterior->SetGrid();
216  gStyle->SetOptStat(0);
217  gStyle->SetOptTitle(0);
218  Posterior->SetTickx();
219  Posterior->SetTicky();
220 
221  Posterior->SetBottomMargin(0.1);
222  Posterior->SetTopMargin(0.05);
223  Posterior->SetRightMargin(0.03);
224  Posterior->SetLeftMargin(0.15);
225 
226  //To avoid TCanvas::Print> messages
227  gErrorIgnoreLevel = kWarning;
228 
229  // Output file to write to
230  OutputName = MCMCFile + OutputSuffix +".root";
231 
232  // Output file
233  OutputFile = new TFile(OutputName.c_str(), "recreate");
234  OutputFile->cd();
235 }
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 239 of file MCMCProcessor.cpp.

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

2331  {
2332 // *****************************
2333  if (OutputFile == nullptr) MakeOutputFile();
2334 
2335  auto PreFitPlot = std::make_unique<TH1D>("Prefit", "Prefit", nDraw, 0, nDraw);
2336  PreFitPlot->SetDirectory(nullptr);
2337  for (int i = 0; i < PreFitPlot->GetNbinsX() + 1; ++i) {
2338  PreFitPlot->SetBinContent(i+1, 0);
2339  PreFitPlot->SetBinError(i+1, 0);
2340  }
2341 
2342  //KS: Slightly hacky way to get relative to prior or nominal as this is convention we use,
2343  //Only applies for xsec, for other systematic it make no difference
2344  double CentralValueTemp, Central, Error;
2345 
2346  // Set labels and data
2347  for (int i = 0; i < nDraw; ++i)
2348  {
2349  //Those keep which parameter type we run currently and relative number
2350  int ParamEnum = ParamType[i];
2351  int ParamNo = i - ParamTypeStartPos[ParameterEnum(ParamEnum)];
2352  CentralValueTemp = ParamCentral[ParamEnum][ParamNo];
2353  if(plotRelativeToPrior)
2354  {
2355  // Normalise the prior relative the nominal/prior, just the way we get our fit results in MaCh3
2356  if ( CentralValueTemp != 0) {
2357  Central = ParamCentral[ParamEnum][ParamNo] / CentralValueTemp;
2358  Error = ParamErrors[ParamEnum][ParamNo]/CentralValueTemp;
2359  } else {
2360  Central = CentralValueTemp + 1.0;
2361  Error = ParamErrors[ParamEnum][ParamNo];
2362  }
2363  }
2364  else
2365  {
2366  Central = CentralValueTemp;
2367  Error = ParamErrors[ParamEnum][ParamNo];
2368  }
2369  //KS: If plotting error for param with flat prior is turned off and given param really has flat prior set error to 0
2370  if(!PlotFlatPrior && ParamFlat[ParamEnum][ParamNo]) {
2371  Error = 0.;
2372  }
2373  PreFitPlot->SetBinContent(i+1, Central);
2374  PreFitPlot->SetBinError(i+1, Error);
2375  PreFitPlot->GetXaxis()->SetBinLabel(i+1, ParamNames[ParamEnum][ParamNo]);
2376  }
2377  PreFitPlot->SetDirectory(nullptr);
2378 
2379  PreFitPlot->SetFillStyle(1001);
2380  PreFitPlot->SetFillColor(kRed-3);
2381  PreFitPlot->SetMarkerStyle(21);
2382  PreFitPlot->SetMarkerSize(2.4);
2383  PreFitPlot->SetMarkerColor(kWhite);
2384  PreFitPlot->SetLineColor(PreFitPlot->GetFillColor());
2385  PreFitPlot->GetXaxis()->LabelsOption("v");
2386 
2387  return PreFitPlot;
2388 }

◆ MakeSubOptimality()

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

Make and Draw SubOptimality [27].

Author
Henry Wallace

Definition at line 1316 of file MCMCProcessor.cpp.

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

Scale the histograms so it shows the posterior probability

Definition at line 1893 of file MCMCProcessor.cpp.

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

◆ MakeViolin()

void MCMCProcessor::MakeViolin ( )

Make and Draw Violin.

Definition at line 808 of file MCMCProcessor.cpp.

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

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

3223  {
3224 // **************************
3225  MACH3LOG_INFO("Parameter Evolution gif");
3226 
3227  //KS: First we need to find parameter number based on name
3228  for(unsigned int k = 0; k < Names.size(); ++k)
3229  {
3230  //KS: First we need to find parameter number based on name
3231  int ParamNo = GetParamIndexFromName(Names[k]);
3232  if(ParamNo == M3::_BAD_INT_)
3233  {
3234  MACH3LOG_WARN("Couldn't find param {}. Can't reweight Prior", Names[k]);
3235  continue;
3236  }
3237 
3238  const int IntervalsSize = nSteps/NIntervals[k];
3239  // ROOT won't overwrite gifs so we need to delete the file if it's there already
3240  std::string filename = Names[k] + ".gif";
3241  std::ifstream f(filename);
3242  if (f.good()) {
3243  f.close();
3244  int ret = system(fmt::format("rm {}", filename).c_str());
3245  if (ret != 0) {
3246  MACH3LOG_WARN("Error: system call to delete {} failed with code {}", filename, ret);
3247  }
3248  }
3249 
3250  int Counter = 0;
3251  for(int i = NIntervals[k]-1; i >= 0; --i)
3252  {
3253  // This holds the posterior density
3254  // KS: WARNING do not change to smart pointer, it breaks and I don't know why
3255  TH1D* EvePlot = new TH1D(BranchNames[ParamNo], BranchNames[ParamNo], nBins,
3256  hpost[ParamNo]->GetXaxis()->GetXmin(), hpost[ParamNo]->GetXaxis()->GetXmax());
3257  EvePlot->SetMinimum(0);
3258  EvePlot->GetYaxis()->SetTitle("PDF");
3259  EvePlot->GetYaxis()->SetNoExponent(false);
3260 
3261  //KS: Apply additional Cuts, like mass ordering
3262  std::string CutPosterior1D = "step > " + std::to_string(i*IntervalsSize+IntervalsSize);
3263 
3264  // If Posterior1DCut is not empty, append it
3265  if (!Posterior1DCut.empty()) {
3266  CutPosterior1D += " && " + Posterior1DCut;
3267  }
3268 
3269  // Apply reweighting if requested
3270  if (ReweightPosterior) {
3271  CutPosterior1D = "(" + CutPosterior1D + ")*(" + ReweightName + ")";
3272  }
3273 
3274  std::string TextTitle = "Steps = 0 - "+std::to_string(Counter*IntervalsSize+IntervalsSize);
3275  // Project BranchNames[ParamNo] onto hpost, applying stepcut
3276  Chain->Project(BranchNames[ParamNo], BranchNames[ParamNo], CutPosterior1D.c_str());
3277 
3278  EvePlot->SetLineWidth(2);
3279  EvePlot->SetLineColor(kBlue-1);
3280  EvePlot->SetTitle(Names[k].c_str());
3281  EvePlot->GetXaxis()->SetTitle(EvePlot->GetTitle());
3282  EvePlot->GetYaxis()->SetLabelOffset(1000);
3283  if(ApplySmoothing) EvePlot->Smooth();
3284 
3285  EvePlot->Scale(1. / EvePlot->Integral());
3286  EvePlot->Draw("HIST");
3287 
3288  TText text(0.3, 0.8, TextTitle.c_str());
3289  text.SetTextFont (43);
3290  text.SetTextSize (40);
3291  text.SetNDC(true);
3292  text.Draw("SAME");
3293 
3294  if(i == 0) Posterior->Print((Names[k] + ".gif++20").c_str()); // produces infinite loop animated GIF
3295  else Posterior->Print((Names[k] + ".gif+20").c_str()); // add picture to .gif
3296  delete EvePlot;
3297  Counter++;
3298  }
3299  }
3300 }

◆ ParamTraces()

void MCMCProcessor::ParamTraces ( )
inlineprotected

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

Definition at line 3497 of file MCMCProcessor.cpp.

3497  {
3498 // *****************
3499  if (ParStep == nullptr) PrepareDiagMCMC();
3500  MACH3LOG_INFO("Making trace plots...");
3501  // Make the TH1Ds
3502  std::vector<TH1D*> TraceParamPlots(nDraw);
3503  std::vector<TH1D*> TraceSamplePlots(nSamples);
3504  std::vector<TH1D*> TraceSystsPlots(nSysts);
3505 
3506  // Set the titles and limits for TH2Ds
3507  for (int j = 0; j < nDraw; ++j) {
3508  TString Title = "";
3509  double Prior = 1.0, PriorError = 1.0;
3510 
3511  GetNthParameter(j, Prior, PriorError, Title);
3512  std::string HistName = Form("%s_%s_Trace", Title.Data(), BranchNames[j].Data());
3513  TraceParamPlots[j] = new TH1D(HistName.c_str(), HistName.c_str(), nEntries, 0, nEntries);
3514  TraceParamPlots[j]->GetXaxis()->SetTitle("Step");
3515  TraceParamPlots[j]->GetYaxis()->SetTitle("Parameter Variation");
3516  }
3517 
3518  for (int j = 0; j < nSamples; ++j) {
3519  std::string HistName = SampleName_v[j].Data();
3520  TraceSamplePlots[j] = new TH1D(HistName.c_str(), HistName.c_str(), nEntries, 0, nEntries);
3521  TraceSamplePlots[j]->GetXaxis()->SetTitle("Step");
3522  TraceSamplePlots[j]->GetYaxis()->SetTitle("Sample -logL");
3523  }
3524 
3525  for (int j = 0; j < nSysts; ++j) {
3526  std::string HistName = SystName_v[j].Data();
3527  TraceSystsPlots[j] = new TH1D(HistName.c_str(), HistName.c_str(), nEntries, 0, nEntries);
3528  TraceSystsPlots[j]->GetXaxis()->SetTitle("Step");
3529  TraceSystsPlots[j]->GetYaxis()->SetTitle("Systematic -logL");
3530  }
3531 
3532  // Have now made the empty TH1Ds, now for writing content to them!
3533  // Loop over the number of parameters to draw their traces
3534  // Each histogram
3535 #ifdef MULTITHREAD
3536  MACH3LOG_INFO("Using multi-threading...");
3537  #pragma omp parallel for
3538 #endif
3539  for (int i = 0; i < nEntries; ++i) {
3540  // Set bin content for the ith bin to the parameter values
3541  for (int j = 0; j < nDraw; ++j) {
3542  TraceParamPlots[j]->SetBinContent(i, ParStep[j][i]);
3543  }
3544  for (int j = 0; j < nSamples; ++j) {
3545  TraceSamplePlots[j]->SetBinContent(i, SampleValues[i][j]);
3546  }
3547  for (int j = 0; j < nSysts; ++j) {
3548  TraceSystsPlots[j]->SetBinContent(i, SystValues[i][j]);
3549  }
3550  }
3551 
3552  // Write the output and delete the TH2Ds
3553  TDirectory *TraceDir = OutputFile->mkdir("Trace");
3554  TraceDir->cd();
3555  for (int j = 0; j < nDraw; ++j) {
3556  // Fit a linear function to the traces
3557  TF1 *Fitter = new TF1("Fitter","[0]", nEntries/2, nEntries);
3558  Fitter->SetLineColor(kRed);
3559  TraceParamPlots[j]->Fit("Fitter","Rq");
3560  TraceParamPlots[j]->Write();
3561  delete Fitter;
3562  delete TraceParamPlots[j];
3563  }
3564 
3565  TDirectory *LLDir = OutputFile->mkdir("LogL");
3566  LLDir->cd();
3567  for (int j = 0; j < nSamples; ++j) {
3568  TraceSamplePlots[j]->Write();
3569  delete TraceSamplePlots[j];
3570  delete[] SampleValues[j];
3571  }
3572  delete[] SampleValues;
3573 
3574  for (int j = 0; j < nSysts; ++j) {
3575  TraceSystsPlots[j]->Write();
3576  delete TraceSystsPlots[j];
3577  delete SystValues[j];
3578  }
3579  delete[] SystValues;
3580 
3581  TraceDir->Close();
3582  delete TraceDir;
3583 
3584  OutputFile->cd();
3585 }
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 4174 of file MCMCProcessor.cpp.

4174  {
4175 // **************************
4176  TStopwatch clock;
4177  clock.Start();
4178 
4179  //KS: Store it as we go back to them at the end
4180  const double TopMargin = Posterior->GetTopMargin();
4181  const int OptTitle = gStyle->GetOptTitle();
4182 
4183  Posterior->SetTopMargin(0.1);
4184  gStyle->SetOptTitle(1);
4185 
4186  MACH3LOG_INFO("Making Power Spectrum plots...");
4187 
4188  // This is only to reduce number of computations...
4189  const int N_Coeffs = std::min(10000, nEntries);
4190  const int start = -(N_Coeffs/2-1);
4191  const int end = N_Coeffs/2-1;
4192  const int v_size = end - start;
4193 
4194  int nPrams = nDraw;
4196  nPrams = 1;
4197 
4198  std::vector<std::vector<float>> k_j(nPrams, std::vector<float>(v_size, 0.0));
4199  std::vector<std::vector<float>> P_j(nPrams, std::vector<float>(v_size, 0.0));
4200 
4201  int _N = nEntries;
4202  if (_N % 2 != 0) _N -= 1; // N must be even
4203 
4204  //This is being used a lot so calculate it once to increase performance
4205  const double two_pi_over_N = 2 * TMath::Pi() / static_cast<double>(_N);
4206 
4207  // KS: This could be moved to GPU I guess
4208  #ifdef MULTITHREAD
4209  #pragma omp parallel for collapse(2)
4210  #endif
4211  // RC: equation 11: for each value of j coef, from range -N/2 -> N/2
4212  for (int j = 0; j < nPrams; ++j)
4213  {
4214  for (int jj = start; jj < end; ++jj)
4215  {
4216  std::complex<double> a_j = 0.0;
4217  for (int n = 0; n < _N; ++n)
4218  {
4219  //if(StepNumber[n] < BurnInCut) continue;
4220  std::complex<double> exp_temp(0, two_pi_over_N * jj * n);
4221  a_j += ParStep[j][n] * std::exp(exp_temp);
4222  }
4223  a_j /= std::sqrt(float(_N));
4224  const int _c = jj - start;
4225 
4226  k_j[j][_c] = two_pi_over_N * jj;
4227  // Equation 13
4228  P_j[j][_c] = std::norm(a_j);
4229  }
4230  }
4231 
4232  TDirectory *PowerDir = OutputFile->mkdir("PowerSpectrum");
4233  PowerDir->cd();
4234 
4235  TVectorD* PowerSpectrumStepSize = new TVectorD(nPrams);
4236  for (int j = 0; j < nPrams; ++j)
4237  {
4238  auto plot = std::make_unique<TGraph>(v_size, k_j[j].data(), P_j[j].data());
4239 
4240  TString Title = "";
4241  double Prior = 1.0, PriorError = 1.0;
4242  GetNthParameter(j, Prior, PriorError, Title);
4243 
4244  std::string name = Form("Power Spectrum of %s;k;P(k)", Title.Data());
4245 
4246  plot->SetTitle(name.c_str());
4247  name = Form("%s_power_spectrum", Title.Data());
4248  plot->SetName(name.c_str());
4249  plot->SetMarkerStyle(7);
4250 
4251  // Equation 18
4252  TF1 *func = new TF1("power_template", "[0]*( ([1] / x)^[2] / (([1] / x)^[2] +1) )", 0.0, 1.0);
4253  // P0 gives the amplitude of the white noise spectrum in the k → 0 limit
4254  func->SetParameter(0, 10.0);
4255  // k* indicates the position of the turnover to a different power law behaviour
4256  func->SetParameter(1, 0.1);
4257  // alpha free parameter
4258  func->SetParameter(2, 2.0);
4259 
4260  // Set parameter limits for stability
4261  func->SetParLimits(0, 0.0, 100.0); // Amplitude should be non-negative
4262  func->SetParLimits(1, 0.001, 1.0); // k* should be within a reasonable range
4263  func->SetParLimits(2, 0.0, 5.0); // alpha should be positive
4264 
4265  plot->Fit("power_template","Rq");
4266 
4267  Posterior->SetLogx();
4268  Posterior->SetLogy();
4269  Posterior->SetGrid();
4270  plot->Write(plot->GetName());
4271  plot->Draw("AL");
4272  func->Draw("SAME");
4273  if(printToPDF) Posterior->Print(CanvasName);
4274 
4275  //KS: I have no clue what is the reason behind this. Found this in Rick Calland code...
4276  (*PowerSpectrumStepSize)(j) = std::sqrt(func->GetParameter(0)/float(v_size*0.5));
4277  delete func;
4278  }
4279 
4280  PowerSpectrumStepSize->Write("PowerSpectrumStepSize");
4281  delete PowerSpectrumStepSize;
4282  PowerDir->Close();
4283  delete PowerDir;
4284 
4285  clock.Stop();
4286  MACH3LOG_INFO("Making Power Spectrum took {:.2f}s", clock.RealTime());
4287 
4288  Posterior->SetTopMargin(TopMargin);
4289  gStyle->SetOptTitle(OptTitle);
4290 }

◆ PrepareDiagMCMC()

void MCMCProcessor::PrepareDiagMCMC ( )
inlineprotected

CW: Prepare branches etc. for DiagMCMC.

Definition at line 3334 of file MCMCProcessor.cpp.

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

◆ PrintInfo()

void MCMCProcessor::PrintInfo ( ) const
inlineprotected

Print info like how many params have been loaded etc.

Definition at line 4529 of file MCMCProcessor.cpp.

4529  {
4530 // **************************
4531  // KS: Create a map to store the counts of unique strings
4532  std::unordered_map<std::string, int> paramCounts;
4533  std::vector<std::string> orderedKeys;
4534 
4535  for (const std::string& param : ParameterGroup) {
4536  if (paramCounts[param] == 0) {
4537  orderedKeys.push_back(param); // preserve order of first appearance
4538  }
4539  paramCounts[param]++;
4540  }
4541 
4542  MACH3LOG_INFO("************************************************");
4543  MACH3LOG_INFO("Scanning output branches...");
4544  MACH3LOG_INFO("# Useful entries in tree: \033[1;32m {} \033[0m ", nDraw);
4545  MACH3LOG_INFO("# Model params: \033[1;32m {} starting at {} \033[0m ", nParam[kXSecPar], ParamTypeStartPos[kXSecPar]);
4546  MACH3LOG_INFO("# With following groups: ");
4547  for (const std::string& key : orderedKeys) {
4548  MACH3LOG_INFO(" # {} params: {}", key, paramCounts[key]);
4549  }
4550  MACH3LOG_INFO("# ND params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kNDPar], ParamTypeStartPos[kNDPar]);
4551  MACH3LOG_INFO("# FD params (legacy): \033[1;32m {} starting at {} \033[0m ", nParam[kFDDetPar], ParamTypeStartPos[kFDDetPar]);
4552  MACH3LOG_INFO("************************************************");
4553 }

◆ ReadFDFile()

void MCMCProcessor::ReadFDFile ( )
inlineprotected

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

Definition at line 2629 of file MCMCProcessor.cpp.

2629  {
2630 // ***************
2631  // Do the same for the FD
2632  TFile *FDdetFile = new TFile(CovPos[kFDDetPar].back().c_str(), "open");
2633  if (FDdetFile->IsZombie()) {
2634  MACH3LOG_ERROR("Couldn't find FDdetFile {}", CovPos[kFDDetPar].back());
2635  throw MaCh3Exception(__FILE__ , __LINE__ );
2636  }
2637  FDdetFile->cd();
2638 
2639  TMatrixD *FDdetMatrix = FDdetFile->Get<TMatrixD>(CovNamePos[kFDDetPar].c_str());
2640 
2641  for (int i = 0; i < FDdetMatrix->GetNrows(); ++i)
2642  {
2643  //KS: FD parameters start at 1. in contrary to ND280
2644  ParamNom[kFDDetPar].push_back(1.);
2645  ParamCentral[kFDDetPar].push_back(1.);
2646 
2647  ParamErrors[kFDDetPar].push_back( std::sqrt((*FDdetMatrix)(i,i)) );
2648  ParamNames[kFDDetPar].push_back( Form("FD Det %i", i) );
2649 
2650  //KS: Currently we can only set it via config, change it in future
2651  ParamFlat[kFDDetPar].push_back( false );
2652  }
2653  //KS: The last parameter is p scale
2654  //ETA: we need to be careful here, this is only true for SK in the T2K beam analysis...
2655  if(FancyPlotNames) ParamNames[kFDDetPar].back() = "Momentum Scale";
2656 
2657  FDdetFile->Close();
2658  delete FDdetFile;
2659  delete FDdetMatrix;
2660 }

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

2393  {
2394 // **************************
2395  FindInputFiles();
2396  if(CovPos[kXSecPar].back() != "none") ReadModelFile();
2397 }
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 2402 of file MCMCProcessor.cpp.

2402  {
2403 // **************************
2405  if(nParam[kNDPar] > 0) ReadNDFile();
2406  if(nParam[kFDDetPar] > 0) ReadFDFile();
2407 }
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 2525 of file MCMCProcessor.cpp.

2525  {
2526 // ***************
2527  YAML::Node XSecFile = CovConfig[kXSecPar];
2528 
2529  auto systematics = XSecFile["Systematics"];
2530  int paramIndex = 0;
2531  for (auto it = systematics.begin(); it != systematics.end(); ++it, ++paramIndex )
2532  {
2533  auto const &param = *it;
2534  // Push back the name
2535  std::string ParName = (param["Systematic"]["Names"]["FancyName"].as<std::string>());
2536  std::string Group = param["Systematic"]["ParameterGroup"].as<std::string>();
2537 
2538  bool rejected = false;
2539  for (unsigned int ik = 0; ik < ExcludedNames.size(); ++ik)
2540  {
2541  if (ParName.rfind(ExcludedNames[ik], 0) == 0)
2542  {
2543  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2544  rejected = true;
2545  break;
2546  }
2547  }
2548  for (unsigned int ik = 0; ik < ExcludedGroups.size(); ++ik)
2549  {
2550  if (Group == ExcludedGroups[ik])
2551  {
2552  MACH3LOG_DEBUG("Excluding param {}, from group {}", ParName, Group);
2553  rejected = true;
2554  break;
2555  }
2556  }
2557  if(rejected) continue;
2558 
2559  ParamNames[kXSecPar].push_back(ParName);
2560  ParamCentral[kXSecPar].push_back(param["Systematic"]["ParameterValues"]["PreFitValue"].as<double>());
2561  ParamNom[kXSecPar].push_back(param["Systematic"]["ParameterValues"]["Generated"].as<double>());
2562  ParamErrors[kXSecPar].push_back(param["Systematic"]["Error"].as<double>() );
2563  ParamFlat[kXSecPar].push_back(GetFromManager<bool>(param["Systematic"]["FlatPrior"], false));
2564 
2565  ParameterGroup.push_back(Group);
2566 
2567  nParam[kXSecPar]++;
2568  ParamType.push_back(kXSecPar);
2569  // Params from osc group have branch name equal to fancy name while all others are basically xsec_0 for example
2570  if(ParameterGroup.back() == "Osc") {
2571  BranchNames.push_back(ParamNames[kXSecPar].back());
2572  } else {
2573  BranchNames.push_back("xsec_" + std::to_string(paramIndex));
2574  }
2575 
2576  // Check that the branch exists before setting address
2577  if (!Chain->GetBranch(BranchNames.back())) {
2578  MACH3LOG_ERROR("Couldn't find branch '{}'", BranchNames.back());
2579  throw MaCh3Exception(__FILE__, __LINE__);
2580  }
2581  }
2582 }
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 2586 of file MCMCProcessor.cpp.

2586  {
2587 // ***************
2588  // Do the same for the ND280
2589  TFile *NDdetFile = new TFile(CovPos[kNDPar].back().c_str(), "open");
2590  if (NDdetFile->IsZombie()) {
2591  MACH3LOG_ERROR("Couldn't find NDdetFile {}", CovPos[kNDPar].back());
2592  throw MaCh3Exception(__FILE__ , __LINE__ );
2593  }
2594  NDdetFile->cd();
2595 
2596  TMatrixDSym *NDdetMatrix = NDdetFile->Get<TMatrixDSym>(CovNamePos[kNDPar].c_str());
2597  TVectorD *NDdetNominal = NDdetFile->Get<TVectorD>("det_weights");
2598  TDirectory *BinningDirectory = NDdetFile->Get<TDirectory>("Binning");
2599 
2600  for (int i = 0; i < NDdetNominal->GetNrows(); ++i)
2601  {
2602  ParamNom[kNDPar].push_back( (*NDdetNominal)(i) );
2603  ParamCentral[kNDPar].push_back( (*NDdetNominal)(i) );
2604 
2605  ParamErrors[kNDPar].push_back( std::sqrt((*NDdetMatrix)(i,i)) );
2606  ParamNames[kNDPar].push_back( Form("ND Det %i", i) );
2607  //KS: Currently we can only set it via config, change it in future
2608  ParamFlat[kNDPar].push_back( false );
2609  }
2610 
2611  TIter next(BinningDirectory->GetListOfKeys());
2612  TKey *key = nullptr;
2613  // Loop through all entries
2614  while ((key = static_cast<TKey*>(next())))
2615  {
2616  std::string name = std::string(key->GetName());
2617  TH2Poly* RefPoly = BinningDirectory->Get<TH2Poly>((name).c_str());
2618  int size = RefPoly->GetNumberOfBins();
2619  NDSamplesBins.push_back(size);
2620  NDSamplesNames.push_back(RefPoly->GetTitle());
2621  }
2622 
2623  NDdetFile->Close();
2624  delete NDdetFile;
2625 }

◆ ResetHistograms()

void MCMCProcessor::ResetHistograms ( )

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

Definition at line 2729 of file MCMCProcessor.cpp.

2729  {
2730 // **************************************************
2731  #ifdef MULTITHREAD
2732  #pragma omp parallel for
2733  #endif
2734  for (int i = 0; i < nDraw; ++i)
2735  {
2736  for (int j = 0; j <= i; ++j)
2737  {
2738  // TH2D to hold the Correlation
2739  hpost2D[i][j]->Reset("");
2740  hpost2D[i][j]->Fill(0.0, 0.0, 0.0);
2741  }
2742  }
2743 }

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

3017  {
3018 // **************************
3019  MACH3LOG_INFO("Reweighting Prior");
3020 
3021  if( (Names.size() != NewCentral.size()) || (NewCentral.size() != NewError.size()))
3022  {
3023  MACH3LOG_ERROR("Size of passed vectors doesn't match in {}", __func__);
3024  throw MaCh3Exception(__FILE__ , __LINE__ );
3025  }
3026  std::vector<int> Param;
3027  std::vector<double> OldCentral;
3028  std::vector<double> OldError;
3029  std::vector<bool> FlatPrior;
3030 
3031  //KS: First we need to find parameter number based on name
3032  for(unsigned int k = 0; k < Names.size(); ++k)
3033  {
3034  //KS: First we need to find parameter number based on name
3035  int ParamNo = GetParamIndexFromName(Names[k]);
3036  if(ParamNo == M3::_BAD_INT_)
3037  {
3038  MACH3LOG_WARN("Couldn't find param {}. Can't reweight Prior", Names[k]);
3039  return;
3040  }
3041 
3042  TString Title = "";
3043  double Prior = 1.0, PriorError = 1.0;
3044  GetNthParameter(ParamNo, Prior, PriorError, Title);
3045 
3046  Param.push_back(ParamNo);
3047  OldCentral.push_back(Prior);
3048  OldError.push_back(PriorError);
3049 
3050  ParameterEnum ParType = ParamType[ParamNo];
3051  int ParamTemp = ParamNo - ParamTypeStartPos[ParType];
3052 
3053  FlatPrior.push_back(ParamFlat[ParType][ParamTemp]);
3054  }
3055  std::vector<double> ParameterPos(Names.size());
3056 
3057  std::string InputFile = MCMCFile+".root";
3058  std::string OutputFilename = MCMCFile + "_reweighted.root";
3059 
3060  //KS: Simply create copy of file and add there new branch
3061  int ret = system(("cp " + InputFile + " " + OutputFilename).c_str());
3062  if (ret != 0)
3063  MACH3LOG_WARN("Error: system call to copy file failed with code {}", ret);
3064 
3065  TFile *OutputChain = new TFile(OutputFilename.c_str(), "UPDATE");
3066  OutputChain->cd();
3067  TTree *post = OutputChain->Get<TTree>("posteriors");
3068 
3069  double Weight = 1.;
3070 
3071  post->SetBranchStatus("*",false);
3072  // Set the branch addresses for params
3073  for (unsigned int j = 0; j < Names.size(); ++j) {
3074  post->SetBranchStatus(BranchNames[Param[j]].Data(), true);
3075  post->SetBranchAddress(BranchNames[Param[j]].Data(), &ParameterPos[j]);
3076  }
3077  TBranch *bpt = post->Branch("Weight", &Weight, "Weight/D");
3078  post->SetBranchStatus("Weight", true);
3079 
3080  for (int i = 0; i < nEntries; ++i)
3081  {
3082  post->GetEntry(i);
3083  Weight = 1.;
3084 
3085  //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 :(
3086  for (unsigned int j = 0; j < Names.size(); ++j)
3087  {
3088  double new_chi = (ParameterPos[j] - NewCentral[j])/NewError[j];
3089  double new_prior = std::exp(-0.5 * new_chi * new_chi);
3090 
3091  double old_chi = -1;
3092  double old_prior = -1;
3093  if(FlatPrior[j]) {
3094  old_prior = 1.0;
3095  } else {
3096  old_chi = (ParameterPos[j] - OldCentral[j])/OldError[j];
3097  old_prior = std::exp(-0.5 * old_chi * old_chi);
3098  }
3099  Weight *= new_prior/old_prior;
3100  }
3101  bpt->Fill();
3102  }
3103  post->SetBranchStatus("*",true);
3104  OutputChain->cd();
3105  post->Write("posteriors", TObject::kOverwrite);
3106 
3107  // KS: Save reweight metadeta
3108  std::ostringstream yaml_stream;
3109  yaml_stream << "Weight:\n";
3110  for (size_t k = 0; k < Names.size(); ++k) {
3111  yaml_stream << " " << Names[k] << ": [" << NewCentral[k] << ", " << NewError[k] << "]\n";
3112  }
3113  std::string yaml_string = yaml_stream.str();
3114  YAML::Node root = STRINGtoYAML(yaml_string);
3115  TMacro ConfigSave = YAMLtoTMacro(root, "Reweight_Config");
3116  ConfigSave.Write();
3117 
3118  OutputChain->Close();
3119  delete OutputChain;
3120 
3121  OutputFile->cd();
3122 }
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Definition: YamlHelper.h:162
YAML::Node STRINGtoYAML(const std::string &yaml_string)
Function to convert a YAML string to a YAML node.
Definition: YamlHelper.h:92

◆ 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

Definition at line 2953 of file MCMCProcessor.cpp.

2956  {
2957 // **************************
2958  // Area normalise the distributions
2959  PriorHist->Scale(1./PriorHist->Integral(), "width");
2960  PosteriorHist->Scale(1./PosteriorHist->Integral(), "width");
2961 
2962  PriorHist->SetLineColor(kRed);
2963  PriorHist->SetMarkerColor(kRed);
2964  PriorHist->SetFillColorAlpha(kRed, 0.35);
2965  PriorHist->SetFillStyle(1001);
2966  PriorHist->GetXaxis()->SetTitle(Title.c_str());
2967  PriorHist->GetYaxis()->SetTitle("Posterior Probability");
2968  PriorHist->SetMaximum(PosteriorHist->GetMaximum()*1.5);
2969  PriorHist->GetYaxis()->SetLabelOffset(999);
2970  PriorHist->GetYaxis()->SetLabelSize(0);
2971  PriorHist->SetLineWidth(2);
2972  PriorHist->SetLineStyle(kSolid);
2973 
2974  PosteriorHist->SetLineColor(kBlue);
2975  PosteriorHist->SetMarkerColor(kBlue);
2976  PosteriorHist->SetFillColorAlpha(kBlue, 0.35);
2977  PosteriorHist->SetFillStyle(1001);
2978 
2979  PriorHist->Draw("hist");
2980  PosteriorHist->Draw("hist same");
2981 
2982  double ProbPrior = PriorHist->GetBinContent(PriorHist->FindBin(EvaluationPoint));
2983  //KS: In case we go so far away that prior is 0, set this to small value to avoid dividing by 0
2984  if(ProbPrior < 0) ProbPrior = 0.00001;
2985  double ProbPosterior = PosteriorHist->GetBinContent(PosteriorHist->FindBin(EvaluationPoint));
2986  double SavageDickey = ProbPosterior/ProbPrior;
2987 
2988  std::string DunneKabothScale = GetDunneKaboth(SavageDickey);
2989  //Get Best point
2990  auto PostPoint = std::make_unique<TGraph>(1);
2991  PostPoint->SetPoint(0, EvaluationPoint, ProbPosterior);
2992  PostPoint->SetMarkerStyle(20);
2993  PostPoint->SetMarkerSize(1);
2994  PostPoint->Draw("P same");
2995 
2996  auto PriorPoint = std::make_unique<TGraph>(1);
2997  PriorPoint->SetPoint(0, EvaluationPoint, ProbPrior);
2998  PriorPoint->SetMarkerStyle(20);
2999  PriorPoint->SetMarkerSize(1);
3000  PriorPoint->Draw("P same");
3001 
3002  auto legend = std::make_unique<TLegend>(0.12, 0.6, 0.6, 0.97);
3003  SetLegendStyle(legend.get(), 0.04);
3004  legend->AddEntry(PriorHist.get(), "Prior", "l");
3005  legend->AddEntry(PosteriorHist.get(), "Posterior", "l");
3006  legend->AddEntry(PostPoint.get(), Form("SavageDickey = %.2f, (%s)", SavageDickey, DunneKabothScale.c_str()),"");
3007  legend->Draw("same");
3008 
3009  Posterior->Print(CanvasName);
3010  Posterior->Write(Title.c_str());
3011 }

◆ ScanInput()

void MCMCProcessor::ScanInput ( )
inlineprotected

Scan Input etc.

Definition at line 2151 of file MCMCProcessor.cpp.

2151  {
2152 // **************************
2153  // KS: This can reduce time necessary for caching even by half
2154  #ifdef MULTITHREAD
2155  //ROOT::EnableImplicitMT();
2156  #endif
2157 
2158  // Open the Chain
2159  Chain = new TChain("posteriors","posteriors");
2160  Chain->Add(MCMCFile.c_str());
2161 
2162  nEntries = int(Chain->GetEntries());
2163 
2164  //Only is suboptimality we might want to change it, therefore set it high enough so it doesn't affect other functionality
2165  UpperCut = nEntries+1;
2166 
2167  // Get the list of branches
2168  TObjArray* brlis = Chain->GetListOfBranches();
2169 
2170  // Get the number of branches
2171  nBranches = brlis->GetEntries();
2172 
2173  BranchNames.reserve(nBranches);
2174  ParamType.reserve(nBranches);
2175 
2176  // Read the input Covariances
2177  ReadInputCov();
2178 
2179  // Set all the branches to off
2180  Chain->SetBranchStatus("*", false);
2181 
2182  // Loop over the number of branches
2183  // Find the name and how many of each systematic we have
2184  for (int i = 0; i < nBranches; i++)
2185  {
2186  // Get the TBranch and its name
2187  TBranch* br = static_cast<TBranch*>(brlis->At(i));
2188  if(!br){
2189  MACH3LOG_ERROR("Invalid branch at position {}", i);
2190  throw MaCh3Exception(__FILE__,__LINE__);
2191  }
2192  TString bname = br->GetName();
2193 
2194  //KS: Exclude parameter types
2195  bool rejected = false;
2196  for(unsigned int ik = 0; ik < ExcludedTypes.size(); ++ik )
2197  {
2198  if(bname.BeginsWith(ExcludedTypes[ik]))
2199  {
2200  rejected = true;
2201  break;
2202  }
2203  }
2204  if(rejected) continue;
2205 
2206  // Turn on the branches which we want for parameters
2207  Chain->SetBranchStatus(bname.Data(), true);
2208 
2209  if (bname.BeginsWith("ndd_"))
2210  {
2211  BranchNames.push_back(bname);
2212  ParamType.push_back(kNDPar);
2213  nParam[kNDPar]++;
2214  }
2215  else if (bname.BeginsWith("skd_joint_"))
2216  {
2217  BranchNames.push_back(bname);
2218  ParamType.push_back(kFDDetPar);
2219  nParam[kFDDetPar]++;
2220  }
2221 
2222  //KS: as a bonus get LogL systematic
2223  if (bname.BeginsWith("LogL_sample_")) {
2224  SampleName_v.push_back(bname);
2225  nSamples++;
2226  }
2227  else if (bname.BeginsWith("LogL_systematic_")) {
2228  SystName_v.push_back(bname);
2229  nSysts++;
2230  }
2231  }
2232  nDraw = int(BranchNames.size());
2233 
2234  // Read the input Covariances
2236 
2237  // Check order of parameter types
2239 
2240  IamVaried.resize(nDraw, true);
2241 
2242  // Print useful Info
2243  PrintInfo();
2244 
2245  nSteps = Chain->GetMaximum("step");
2246  // Set the step cut to be 20%
2247  int cut = nSteps/5;
2248  SetStepCut(cut);
2249 
2250  // Basically allow loading oscillation parameters
2252 }
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 2313 of file MCMCProcessor.cpp.

2313  {
2314 // *****************************
2315  for(int i = 0; i < kNParameterEnum; i++)
2316  {
2317  for(unsigned int j = 0; j < ParamType.size(); j++)
2318  {
2319  if(ParamType[j] == ParameterEnum(i))
2320  {
2321  //KS: When we find that i-th parameter types start at j, save and move to the next parameter.
2322  ParamTypeStartPos[i] = j;
2323  break;
2324  }
2325  }
2326  }
2327 }

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

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

◆ SetExcludedGroups()

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

Definition at line 310 of file MCMCProcessor.h.

310 {ExcludedGroups = Name; };

◆ SetExcludedNames()

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

Definition at line 309 of file MCMCProcessor.h.

309 {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 xsec_, then passing "xsec_" will.

Parameters
BatchesVector with parameters type names we want to exclude

Definition at line 308 of file MCMCProcessor.h.

308 {ExcludedTypes = Name; };

◆ SetFancyNames()

void MCMCProcessor::SetFancyNames ( const bool  PlotOrNot)
inline

Definition at line 297 of file MCMCProcessor.h.

297 {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 4588 of file MCMCProcessor.cpp.

4588  {
4589 // **************************
4590  Legend->SetTextSize(size);
4591  Legend->SetLineColor(0);
4592  Legend->SetLineStyle(0);
4593  Legend->SetFillColor(0);
4594  Legend->SetFillStyle(0);
4595  Legend->SetBorderSize(0);
4596 }

◆ SetMargins()

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

Set TCanvas margins to specified values.

Definition at line 4563 of file MCMCProcessor.cpp.

4563  {
4564 // **************************
4565  if (!Canv) {
4566  MACH3LOG_ERROR("Canv is nullptr");
4567  throw MaCh3Exception(__FILE__, __LINE__);
4568  }
4569  if (margins.size() != 4) {
4570  MACH3LOG_ERROR("Margin vector must have exactly 4 elements");
4571  throw MaCh3Exception(__FILE__, __LINE__);
4572  }
4573  Canv->SetTopMargin(margins[0]);
4574  Canv->SetBottomMargin(margins[1]);
4575  Canv->SetLeftMargin(margins[2]);
4576  Canv->SetRightMargin(margins[3]);
4577 }

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

314 {nBatches = Batches; };

◆ SetNBins()

void MCMCProcessor::SetNBins ( const int  NewBins)
inline

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

Definition at line 258 of file MCMCProcessor.h.

258 {nBins = NewBins;};

◆ SetnLags()

void MCMCProcessor::SetnLags ( const int  nLags)
inline

Definition at line 315 of file MCMCProcessor.h.

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

318 {OutputSuffix = Suffix; };

◆ SetPlotBinValue()

void MCMCProcessor::SetPlotBinValue ( const bool  PlotOrNot)
inline

Definition at line 296 of file MCMCProcessor.h.

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

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

292 {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 302 of file MCMCProcessor.h.

302 {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 320 of file MCMCProcessor.h.

320 {Posterior1DCut = Cut; };

◆ SetPrintToPDF()

void MCMCProcessor::SetPrintToPDF ( const bool  PlotOrNot)
inline

Definition at line 293 of file MCMCProcessor.h.

293 {printToPDF = PlotOrNot; };

◆ SetSmoothing()

void MCMCProcessor::SetSmoothing ( const bool  PlotOrNot)
inline

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

Definition at line 299 of file MCMCProcessor.h.

299 {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 2674 of file MCMCProcessor.cpp.

2674  {
2675 // ***************
2676  std::stringstream TempStream;
2677  TempStream << "step > " << Cuts;
2678  StepCut = TempStream.str();
2679  BurnInCut = Cuts;
2680  CheckStepCut();
2681 }
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 2664 of file MCMCProcessor.cpp.

2664  {
2665 // ***************
2666  StepCut = Cuts;
2667  BurnInCut = std::stoi( Cuts );
2668 
2669  CheckStepCut();
2670 }

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

4580  {
4581 // **************************
4582  Line->SetLineColor(Colour);
4583  Line->SetLineWidth(Width);
4584  Line->SetLineStyle(Style);
4585 }
constexpr ELineStyle Style[NVars]

◆ SetupOutput()

void MCMCProcessor::SetupOutput ( )
inlineprotected

Prepare all objects used for output.

Definition at line 2256 of file MCMCProcessor.cpp.

2256  {
2257 // ****************************
2258  // Make sure we can read files located anywhere and strip the .root ending
2259  MCMCFile = MCMCFile.substr(0, MCMCFile.find(".root"));
2260 
2261  // Check if the output file is ready
2262  if (OutputFile == nullptr) MakeOutputFile();
2263 
2264  CanvasName = MCMCFile + OutputSuffix + ".pdf[";
2265  if(printToPDF) Posterior->Print(CanvasName);
2266 
2267  // Once the pdf file is open no longer need to bracket
2268  CanvasName.ReplaceAll("[","");
2269 
2270  // We fit with this Gaussian
2271  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);
2272  Gauss->SetLineWidth(2);
2273  Gauss->SetLineColor(kOrange-5);
2274 
2275  // Declare the TVectors
2276  Covariance = new TMatrixDSym(nDraw);
2277  Correlation = new TMatrixDSym(nDraw);
2278  Central_Value = new TVectorD(nDraw);
2279  Means = new TVectorD(nDraw);
2280  Errors = new TVectorD(nDraw);
2281  Means_Gauss = new TVectorD(nDraw);
2282  Errors_Gauss = new TVectorD(nDraw);
2283  Means_HPD = new TVectorD(nDraw);
2284  Errors_HPD = new TVectorD(nDraw);
2285  Errors_HPD_Positive = new TVectorD(nDraw);
2286  Errors_HPD_Negative = new TVectorD(nDraw);
2287 
2288  // Initialise to something silly
2289  #ifdef MULTITHREAD
2290  #pragma omp parallel for
2291  #endif
2292  for (int i = 0; i < nDraw; ++i)
2293  {
2294  (*Central_Value)(i) = M3::_BAD_DOUBLE_;
2295  (*Means)(i) = M3::_BAD_DOUBLE_;
2296  (*Errors)(i) = M3::_BAD_DOUBLE_;
2297  (*Means_Gauss)(i) = M3::_BAD_DOUBLE_;
2298  (*Errors_Gauss)(i) = M3::_BAD_DOUBLE_;
2299  (*Means_HPD)(i) = M3::_BAD_DOUBLE_;
2300  (*Errors_HPD)(i) = M3::_BAD_DOUBLE_;
2301  (*Errors_HPD_Positive)(i) = M3::_BAD_DOUBLE_;
2302  (*Errors_HPD_Negative)(i) = M3::_BAD_DOUBLE_;
2303  for (int j = 0; j < nDraw; ++j) {
2304  (*Covariance)(i, j) = M3::_BAD_DOUBLE_;
2305  (*Correlation)(i, j) = M3::_BAD_DOUBLE_;
2306  }
2307  }
2308  hpost.resize(nDraw);
2309 }

◆ SetUseFFTAutoCorrelation()

void MCMCProcessor::SetUseFFTAutoCorrelation ( const bool  useFFT)
inline

Toggle using the FFT-based autocorrelation calculator.

Definition at line 304 of file MCMCProcessor.h.

304 {useFFTAutoCorrelation = useFFT; };

◆ SmearChain()

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

Smear chain contours.

Parameters
NamesParameter names for which we do smearing
ErrorError based on which we smear
SaveBranchWhether we save unsmeared branch or not

Definition at line 3127 of file MCMCProcessor.cpp.

3129  {
3130 // **************************
3131  MACH3LOG_INFO("Starting {}", __func__);
3132 
3133  if( (Names.size() != Error.size()))
3134  {
3135  MACH3LOG_ERROR("Size of passed vectors doesn't match in {}", __func__);
3136  throw MaCh3Exception(__FILE__ , __LINE__ );
3137  }
3138  std::vector<int> Param;
3139 
3140  //KS: First we need to find parameter number based on name
3141  for(unsigned int k = 0; k < Names.size(); ++k)
3142  {
3143  //KS: First we need to find parameter number based on name
3144  int ParamNo = GetParamIndexFromName(Names[k]);
3145  if(ParamNo == M3::_BAD_INT_)
3146  {
3147  MACH3LOG_WARN("Couldn't find param {}. Can't Smear", Names[k]);
3148  return;
3149  }
3150 
3151  TString Title = "";
3152  double Prior = 1.0, PriorError = 1.0;
3153  GetNthParameter(ParamNo, Prior, PriorError, Title);
3154 
3155  Param.push_back(ParamNo);
3156  }
3157  std::string InputFile = MCMCFile+".root";
3158  std::string OutputFilename = MCMCFile + "_smeared.root";
3159 
3160  //KS: Simply create copy of file and add there new branch
3161  int ret = system(("cp " + InputFile + " " + OutputFilename).c_str());
3162  if (ret != 0)
3163  MACH3LOG_WARN("Error: system call to copy file failed with code {}", ret);
3164 
3165  TFile *OutputChain = new TFile(OutputFilename.c_str(), "UPDATE");
3166  OutputChain->cd();
3167  TTree *post = OutputChain->Get<TTree>("posteriors");
3168  TTree *treeNew = post->CloneTree(0);
3169 
3170  std::vector<double> NewParameter(Names.size());
3171  for(size_t i = 0; i < Param.size(); i++) {
3172  post->SetBranchAddress(BranchNames[Param[i]], &NewParameter[i]);
3173  }
3174 
3175  std::vector<double> Unsmeared_Parameter;
3176  if(SaveBranch){
3177  Unsmeared_Parameter.resize(Param.size());
3178  for(size_t i = 0; i < Param.size(); i++) {
3179  treeNew->Branch((BranchNames[Param[i]] + "_unsmeared"), &Unsmeared_Parameter[i]);
3180  }
3181  }
3182 
3183  auto rand = std::make_unique<TRandom3>(0);
3184  Long64_t AllEntries = post->GetEntries();
3185  for (Long64_t i = 0; i < AllEntries; ++i) {
3186  // Entry from the old chain
3187  post->GetEntry(i);
3188 
3189  if(SaveBranch){
3190  for(size_t iPar = 0; iPar < Param.size(); iPar++) {
3191  Unsmeared_Parameter[iPar] = NewParameter[iPar];
3192  }
3193  }
3194  // Smear it
3195  for(size_t iPar = 0; iPar < Param.size(); iPar++) {
3196  NewParameter[iPar] = NewParameter[iPar] + rand->Gaus(0, Error[iPar]);
3197  }
3198  // Fill to the new chain
3199  treeNew->Fill();
3200  }
3201 
3202  OutputChain->cd();
3203  treeNew->Write("posteriors", TObject::kOverwrite);
3204 
3205  // KS: Save reweight metadeta
3206  std::ostringstream yaml_stream;
3207  yaml_stream << "Smearing:\n";
3208  for (size_t k = 0; k < Names.size(); ++k) {
3209  yaml_stream << " " << Names[k] << ": [" << Error[k] << ", " << "Gauss" << "]\n";
3210  }
3211  std::string yaml_string = yaml_stream.str();
3212  YAML::Node root = STRINGtoYAML(yaml_string);
3213  TMacro ConfigSave = YAMLtoTMacro(root, "Smearing_Config");
3214  ConfigSave.Write();
3215 
3216  OutputChain->Close();
3217  delete OutputChain;
3218 }

◆ 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
AverageIf true will perform MCMC averaging instead of thinning

Definition at line 203 of file MCMCProcessor.h.

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

Member Data Documentation

◆ AccProbBatchedAverages

double* MCMCProcessor::AccProbBatchedAverages
protected

Holds all accProb in batches.

Definition at line 583 of file MCMCProcessor.h.

◆ AccProbValues

double* MCMCProcessor::AccProbValues
protected

Holds all accProb.

Definition at line 581 of file MCMCProcessor.h.

◆ ApplySmoothing

bool MCMCProcessor::ApplySmoothing
protected

Apply smoothing for 2D histos using root algorithm.

Definition at line 497 of file MCMCProcessor.h.

◆ AutoCorrLag

int MCMCProcessor::AutoCorrLag
protected

LagL used in AutoCorrelation.

Definition at line 568 of file MCMCProcessor.h.

◆ BatchedAverages

double** MCMCProcessor::BatchedAverages
protected

Values of batched average for every param and batch.

Definition at line 573 of file MCMCProcessor.h.

◆ BranchNames

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

Definition at line 446 of file MCMCProcessor.h.

◆ BurnInCut

unsigned int MCMCProcessor::BurnInCut
protected

Value of burn in cut.

Definition at line 431 of file MCMCProcessor.h.

◆ CacheMCMC

bool MCMCProcessor::CacheMCMC
protected

MCMC Chain has been cached.

Definition at line 560 of file MCMCProcessor.h.

◆ CanvasName

TString MCMCProcessor::CanvasName
protected

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

Definition at line 480 of file MCMCProcessor.h.

◆ Central_Value

TVectorD* MCMCProcessor::Central_Value
protected

Vector with central value for each parameter.

Definition at line 517 of file MCMCProcessor.h.

◆ Chain

TChain* MCMCProcessor::Chain
protected

Main chain storing all steps etc.

Definition at line 423 of file MCMCProcessor.h.

◆ Correlation

TMatrixDSym* MCMCProcessor::Correlation
protected

Posterior Correlation Matrix.

Definition at line 538 of file MCMCProcessor.h.

◆ Covariance

TMatrixDSym* MCMCProcessor::Covariance
protected

Posterior Covariance Matrix.

Definition at line 536 of file MCMCProcessor.h.

◆ CovConfig

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

Covariance matrix config.

Definition at line 420 of file MCMCProcessor.h.

◆ CovNamePos

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

Covariance matrix name position.

Definition at line 418 of file MCMCProcessor.h.

◆ CovPos

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

Covariance matrix file name position.

Definition at line 416 of file MCMCProcessor.h.

◆ doDiagMCMC

bool MCMCProcessor::doDiagMCMC
protected

Doing MCMC Diagnostic.

Definition at line 562 of file MCMCProcessor.h.

◆ DrawRange

double MCMCProcessor::DrawRange
protected

Drawrange for SetMaximum.

Definition at line 557 of file MCMCProcessor.h.

◆ Errors

TVectorD* MCMCProcessor::Errors
protected

Vector with errors values using RMS.

Definition at line 521 of file MCMCProcessor.h.

◆ Errors_Gauss

TVectorD* MCMCProcessor::Errors_Gauss
protected

Vector with error values using Gaussian fit.

Definition at line 525 of file MCMCProcessor.h.

◆ Errors_HPD

TVectorD* MCMCProcessor::Errors_HPD
protected

Vector with error values using Highest Posterior Density.

Definition at line 529 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 533 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 531 of file MCMCProcessor.h.

◆ ExcludedGroups

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

Definition at line 449 of file MCMCProcessor.h.

◆ ExcludedNames

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

Definition at line 448 of file MCMCProcessor.h.

◆ ExcludedTypes

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

Definition at line 447 of file MCMCProcessor.h.

◆ FancyPlotNames

bool MCMCProcessor::FancyPlotNames
protected

Whether we want fancy plot names or not.

Definition at line 493 of file MCMCProcessor.h.

◆ Gauss

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

Gaussian fitter.

Definition at line 507 of file MCMCProcessor.h.

◆ hpost

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

Holds 1D Posterior Distributions.

Definition at line 541 of file MCMCProcessor.h.

◆ hpost2D

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

Holds 2D Posterior Distributions.

Definition at line 543 of file MCMCProcessor.h.

◆ hviolin

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

Holds violin plot for all dials.

Definition at line 545 of file MCMCProcessor.h.

◆ hviolin_prior

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

Holds prior violin plot for all dials,.

Definition at line 547 of file MCMCProcessor.h.

◆ IamVaried

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

Is the ith parameter varied.

Definition at line 452 of file MCMCProcessor.h.

◆ MadePostfit

bool MCMCProcessor::MadePostfit
protected

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

Definition at line 489 of file MCMCProcessor.h.

◆ MCMCFile

std::string MCMCProcessor::MCMCFile
protected

Name of MCMC file.

Definition at line 412 of file MCMCProcessor.h.

◆ Means

TVectorD* MCMCProcessor::Means
protected

Vector with mean values using Arithmetic Mean.

Definition at line 519 of file MCMCProcessor.h.

◆ Means_Gauss

TVectorD* MCMCProcessor::Means_Gauss
protected

Vector with mean values using Gaussian fit.

Definition at line 523 of file MCMCProcessor.h.

◆ Means_HPD

TVectorD* MCMCProcessor::Means_HPD
protected

Vector with mean values using Highest Posterior Density.

Definition at line 527 of file MCMCProcessor.h.

◆ nBatches

int MCMCProcessor::nBatches
protected

Number of batches for Batched Mean.

Definition at line 566 of file MCMCProcessor.h.

◆ nBins

int MCMCProcessor::nBins
protected

Number of bins.

Definition at line 555 of file MCMCProcessor.h.

◆ nBranches

int MCMCProcessor::nBranches
protected

Number of branches in a TTree.

Definition at line 433 of file MCMCProcessor.h.

◆ nDraw

int MCMCProcessor::nDraw
protected

Number of all parameters used in the analysis.

Definition at line 443 of file MCMCProcessor.h.

◆ NDSamplesBins

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

Definition at line 503 of file MCMCProcessor.h.

◆ NDSamplesNames

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

Definition at line 504 of file MCMCProcessor.h.

◆ nEntries

int MCMCProcessor::nEntries
protected

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

Definition at line 435 of file MCMCProcessor.h.

◆ nParam

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

Number of parameters per type.

Definition at line 463 of file MCMCProcessor.h.

◆ nSamples

int MCMCProcessor::nSamples
protected

Number of sample PDF objects.

Definition at line 439 of file MCMCProcessor.h.

◆ nSteps

int MCMCProcessor::nSteps
protected

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

Definition at line 437 of file MCMCProcessor.h.

◆ nSysts

int MCMCProcessor::nSysts
protected

Number of covariance objects.

Definition at line 441 of file MCMCProcessor.h.

◆ OutputFile

TFile* MCMCProcessor::OutputFile
protected

The output file.

Definition at line 510 of file MCMCProcessor.h.

◆ OutputName

std::string MCMCProcessor::OutputName
protected

Name of output files.

Definition at line 478 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 414 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 456 of file MCMCProcessor.h.

◆ ParamErrors

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

Uncertainty on a single parameter.

Definition at line 459 of file MCMCProcessor.h.

◆ ParameterGroup

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

Definition at line 470 of file MCMCProcessor.h.

◆ ParamFlat

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

Whether Param has flat prior or not.

Definition at line 461 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 454 of file MCMCProcessor.h.

◆ ParamNom

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

Definition at line 457 of file MCMCProcessor.h.

◆ ParamSums

double* MCMCProcessor::ParamSums
protected

Total parameter sum for each param.

Definition at line 571 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 465 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 468 of file MCMCProcessor.h.

◆ ParStep

double** MCMCProcessor::ParStep
protected

Array holding values for all parameters.

Definition at line 550 of file MCMCProcessor.h.

◆ plotBinValue

bool MCMCProcessor::plotBinValue
protected

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

Definition at line 495 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 483 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 487 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 499 of file MCMCProcessor.h.

◆ Posterior

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

Fancy canvas used for our beautiful plots.

Definition at line 513 of file MCMCProcessor.h.

◆ Posterior1DCut

std::string MCMCProcessor::Posterior1DCut
protected

Cut used when making 1D Posterior distribution.

Definition at line 427 of file MCMCProcessor.h.

◆ printToPDF

bool MCMCProcessor::printToPDF
protected

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

Definition at line 491 of file MCMCProcessor.h.

◆ ReweightName

std::string MCMCProcessor::ReweightName
protected

Name of branch used for chain reweighting.

Definition at line 588 of file MCMCProcessor.h.

◆ ReweightPosterior

bool MCMCProcessor::ReweightPosterior
protected

Whether to apply reweighting weight or not.

Definition at line 586 of file MCMCProcessor.h.

◆ SampleName_v

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

Vector of each systematic.

Definition at line 473 of file MCMCProcessor.h.

◆ SampleValues

double** MCMCProcessor::SampleValues
protected

Holds the sample values.

Definition at line 576 of file MCMCProcessor.h.

◆ StepCut

std::string MCMCProcessor::StepCut
protected

BurnIn Cuts.

Definition at line 425 of file MCMCProcessor.h.

◆ StepNumber

unsigned int* MCMCProcessor::StepNumber
protected

Step number for step, important if chains were merged.

Definition at line 552 of file MCMCProcessor.h.

◆ SystName_v

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

Vector of each sample PDF object.

Definition at line 475 of file MCMCProcessor.h.

◆ SystValues

double** MCMCProcessor::SystValues
protected

Holds the systs values.

Definition at line 578 of file MCMCProcessor.h.

◆ UpperCut

unsigned int MCMCProcessor::UpperCut
protected

KS: Used only for SubOptimality.

Definition at line 429 of file MCMCProcessor.h.

◆ useFFTAutoCorrelation

bool MCMCProcessor::useFFTAutoCorrelation
protected

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

Definition at line 501 of file MCMCProcessor.h.

◆ WeightValue

double* MCMCProcessor::WeightValue
protected

Stores value of weight for each step.

Definition at line 590 of file MCMCProcessor.h.


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