MaCh3  2.5.0
Reference Guide
Public Member Functions | Protected Member Functions | Protected Attributes | Private Types | Private Member Functions | Private Attributes | List of all members
SampleHandlerBase Class Referenceabstract

Class responsible for handling implementation of samples used in analysis, reweighting and returning LLH. More...

#include <Samples/SampleHandlerBase.h>

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

Public Member Functions

 SampleHandlerBase (std::string ConfigFileName, ParameterHandlerGeneric *xsec_cov, const std::shared_ptr< OscillationHandler > &OscillatorObj_=nullptr)
 Constructor. More...
 
virtual ~SampleHandlerBase ()
 destructor More...
 
int GetNDim (const int Sample) const final
 DB Get what dimensionality binning for given sample has. More...
 
std::string GetName () const final
 Get name for Sample Handler. More...
 
std::string GetSampleTitle (const int Sample) const final
 Get fancy title for specified samples. More...
 
std::string GetKinVarName (const int iSample, const int Dimension) const final
 Return Kinematic Variable name for specified sample and dimension for example "Reconstructed_Neutrino_Energy". More...
 
void PrintIntegral (const int iSample, const TString &OutputName="/dev/null", const int WeightStyle=0, const TString &OutputCSVName="/dev/null")
 Computes and prints the integral breakdown of all modes and oscillation channels for a given sample. More...
 
void AddData (const int Sample, TH1 *Data)
 
void AddData (const int Sample, const std::vector< double > &Data_Array)
 
void PrintRates (const bool DataOnly=false) final
 Helper function to print rates for the samples with LLH. More...
 
double GetLikelihood () const override
 DB Multi-threaded GetLikelihood. More...
 
double GetSampleLikelihood (const int isample) const override
 Get likelihood for single sample. More...
 
int GetSampleIndex (const std::string &SampleTitle) const
 Get index of sample based on name. More...
 
const TH1 * GetDataHist (const int Sample) final
 Get Data histogram. More...
 
const TH1 * GetDataHist (const std::string &Sample)
 
const TH1 * GetMCHist (const int Sample) final
 Get MC histogram. More...
 
const TH1 * GetMCHist (const std::string &Sample)
 
const TH1 * GetW2Hist (const int Sample) final
 Get W2 histogram. More...
 
const TH1 * GetW2Hist (const std::string &Sample)
 
void Reweight () override
 main routine modifying MC prediction based on proposed parameter values More...
 
M3::float_t GetEventWeight (const int iEntry)
 Computes the total event weight for a given entry. More...
 
const M3::float_tGetNuOscillatorPointers (const int iEvent) const
 
int GetNOscChannels (const int iSample) const final
 Get number of oscillation channels for a single sample. More...
 
std::string GetFlavourName (const int iSample, const int iChannel) const final
 
std::unique_ptr< TH1 > Get1DVarHist (const int iSample, const std::string &ProjectionVar, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, const std::vector< KinematicCut > &SubEventSelectionVec={}) final
 
std::unique_ptr< TH2 > Get2DVarHist (const int iSample, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, const std::vector< KinematicCut > &SubEventSelectionVec={}) final
 
std::vector< KinematicCutBuildModeChannelSelection (const int iSample, const int kModeToFill, const int kChannelToFill) const
 
void Fill1DSubEventHist (const int iSample, TH1D *_h1DVar, const std::string &ProjectionVar, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
 
void Fill2DSubEventHist (const int iSample, TH2 *_h2DVar, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
 
std::unique_ptr< TH1 > Get1DVarHistByModeAndChannel (const int iSample, const std::string &ProjectionVar_Str, const int kModeToFill=-1, const int kChannelToFill=-1, const int WeightStyle=0) final
 
std::unique_ptr< TH2 > Get2DVarHistByModeAndChannel (const int iSample, const std::string &ProjectionVar_StrX, const std::string &ProjectionVar_StrY, const int kModeToFill=-1, const int kChannelToFill=-1, const int WeightStyle=0) final
 
std::unique_ptr< TH1 > GetModeHist1D (const int iSample, int s, int m, int style=0)
 
std::unique_ptr< TH2 > GetModeHist2D (const int iSample, int s, int m, int style=0)
 
std::vector< std::unique_ptr< TH1 > > ReturnHistsBySelection1D (const int iSample, const std::string &KinematicProjection, const int Selection1, const int Selection2=-1, const int WeightStyle=0)
 
std::vector< std::unique_ptr< TH2 > > ReturnHistsBySelection2D (const int iSample, const std::string &KinematicProjectionX, const std::string &KinematicProjectionY, const int Selection1, const int Selection2=-1, const int WeightStyle=0)
 
std::unique_ptr< THStack > ReturnStackedHistBySelection1D (const int iSample, const std::string &KinematicProjection, const int Selection1, const int Selection2=-1, const int WeightStyle=0)
 
const TLegend * ReturnStackHistLegend () const
 Return the legend used for stacked histograms with sample info. More...
 
int ReturnKinematicParameterFromString (const std::string &KinematicStr) const
 ETA function to generically convert a string from xsec cov to a kinematic type. More...
 
std::string ReturnStringFromKinematicParameter (const int KinematicVariable) const
 ETA function to generically convert a kinematic type from xsec cov to a string. More...
 
void SaveAdditionalInfo (TDirectory *Dir) final
 Store additional info in a chan. More...
 
int ReturnKinematicVectorFromString (const std::string &KinematicStr) const
 JM: Convert a kinematic vector name to its corresponding integer ID. More...
 
std::string ReturnStringFromKinematicVector (const int KinematicVariable) const
 JM: Convert a kinematic vector integer ID to its corresponding name as a string. More...
 
bool IsSubEventVarString (const std::string &VarStr) const
 JM: Check if a kinematic parameter string corresponds to a subevent-level variable. More...
 
auto GetDataArray () const
 Return array storing data entries for every bin. More...
 
auto GetMCArray () const
 Return array storing MC entries for every bin. More...
 
auto GetW2Array () const
 Return array storing W2 entries for every bin. More...
 
std::vector< double > GetArrayForSample (const int Sample, std::vector< double > const &array) const
 Return a sub-array for a given sample. More...
 
std::vector< double > GetDataArray (const int Sample) const
 Return array storing data entries for every bin. More...
 
std::vector< double > GetMCArray (const int Sample) const
 Return array storing MC entries for every bin. More...
 
std::vector< double > GetW2Array (const int Sample) const
 Return array storing W2 entries for single sample. More...
 
- Public Member Functions inherited from SampleHandlerInterface
 SampleHandlerInterface ()
 The main constructor. More...
 
virtual ~SampleHandlerInterface ()
 destructor More...
 
virtual M3::int_t GetNSamples ()
 
virtual void CleanMemoryBeforeFit ()=0
 Allow to clean not used memory before fit starts. More...
 
MaCh3ModesGetMaCh3Modes () const
 Return pointer to MaCh3 modes. More...
 
unsigned int GetNEvents () const
 
double GetPoissonLLH (const double data, const double mc) const
 Calculate test statistic for a single bin using Poisson. More...
 
double GetTestStatLLH (const double data, const double mc, const double w2) const
 Calculate test statistic for a single bin. Calculation depends on setting of fTestStatistic. Data and mc -> 0 cut-offs are defined in M3::LOW_MC_BOUND. More...
 
void SetTestStatistic (TestStatistic testStat)
 Set the test statistic to be used when calculating the binned likelihoods. More...
 
TestStatistic GetTestStatistic () const
 Get the test statistic used when calculating the binned likelihoods. More...
 

Protected Member Functions

void InitialiseNuOscillatorObjects ()
 including Dan's magic NuOscillator More...
 
void SetupNuOscillatorPointers ()
 Initialise pointer to oscillation weight to NuOscillator object. More...
 
void ReadConfig ()
 Load information about sample handler and corresponding samples from config file. More...
 
void LoadSingleSample (const int iSample, const YAML::Node &Settings)
 Initialise single sample from config file. More...
 
virtual void AddAdditionalWeightPointers ()=0
 DB Function to determine which weights apply to which types of samples. More...
 
void SetupKinematicMap ()
 Ensure Kinematic Map is setup and make sure it is initialised correctly. More...
 
virtual void SetupSplines ()=0
 initialise your splineXX object and then use InitialiseSplineObject to conviently setup everything up More...
 
virtual void Init ()=0
 Initialise any variables that your experiment specific SampleHandler needs. More...
 
virtual int SetupExperimentMC ()=0
 Experiment specific setup, returns the number of events which were loaded. More...
 
virtual void SetupMC ()=0
 Function which translates experiment struct into core struct. More...
 
virtual void InititialiseData ()=0
 Function responsible for loading data from file or loading from file. More...
 
void Initialise ()
 Function which does a lot of the lifting regarding the workflow in creating different MC objects. More...
 
void SetSplinePointers ()
 Set pointers for each event to appropriate weights, for unbinned based on event number while for binned based on other kinematical properties. More...
 
std::vector< std::vector< int > > GetSplineBins (int Event, BinnedSplineHandler *BinnedSpline, bool &ThrowCrititcal) const
 Retrieve the spline bin indices associated with a given event. More...
 
void FindNominalBinAndEdges ()
 
void SetBinning ()
 set the binning for 2D sample used for the likelihood calculation More...
 
void SetupReweightArrays ()
 Initialise data, MC and W2 histograms. More...
 
virtual void SetupFunctionalParameters ()
 ETA - a function to setup and pass values to functional parameters where you need to pass a value to some custom reweight calc or engine. More...
 
void RegisterIndividualFunctionalParameter (const std::string &fpName, int fpEnum, FuncParFuncType fpFunc)
 HH - a helper function for RegisterFunctionalParameter. More...
 
virtual void RegisterFunctionalParameters ()=0
 HH - a experiment-specific function where the maps to actual functions are set up. More...
 
virtual void PrepFunctionalParameters ()
 Update the functional parameter values to the latest proposed values. Needs to be called before every new reweight so is called in fillArray. More...
 
virtual void ApplyShifts (const int iEvent)
 ETA - generic function applying shifts. More...
 
bool IsEventSelected (const int iSample, const int iEvent) _noexcept_
 DB Function which determines if an event is selected based on KinematicCut. More...
 
bool IsSubEventSelected (const std::vector< KinematicCut > &SubEventCuts, const int iEvent, unsigned const int iSubEvent, size_t nsubevents)
 JM Function which determines if a subevent is selected. More...
 
virtual void ResetShifts (const int iEvent)
 HH - reset the shifted values to the original values. More...
 
virtual void FinaliseShifts (const int iEvent)
 LP - Optionally calculate derived observables after all shifts have been applied. More...
 
void CalcNormsBins (std::vector< NormParameter > &norm_parameters, std::vector< std::vector< int > > &norms_bins)
 Check whether a normalisation systematic affects an event or not. More...
 
template<typename ParT >
bool PassesSelection (const ParT &Par, std::size_t iEvent)
 
M3::float_t CalcWeightTotal (const EventInfo *_restrict_ MCEvent) const _noexcept_
 Calculate the total weight weight for a given event. More...
 
virtual void CalcWeightFunc (const int iEvent)
 Calculate weights for function parameters. More...
 
double ReturnKinematicParameter (const std::string &KinematicParameter, int iEvent) const
 Return the value of an associated kinematic parameter for an event. More...
 
virtual double ReturnKinematicParameter (const int KinematicVariable, const int iEvent) const =0
 
std::vector< double > ReturnKinematicVector (const std::string &KinematicParameter, const int iEvent) const
 
virtual std::vector< double > ReturnKinematicVector (const int KinematicVariable, const int iEvent) const
 
std::vector< double > ReturnKinematicParameterBinning (const int Sample, const std::string &KinematicParameter) const final
 Return the binning used to draw a kinematic parameter. More...
 
const double * GetPointerToKinematicParameter (const std::string &KinematicParameter, int iEvent) const
 
virtual const double * GetPointerToKinematicParameter (const int KinematicVariable, const int iEvent) const =0
 
const double * GetPointerToOscChannel (const int iEvent) const
 Get pointer to oscillation channel associated with given event. Osc channel is const. More...
 
void SetupNormParameters ()
 Setup the norm parameters by assigning each event with bin. More...
 
void SetupOscParameters ()
 Setup the osc parameters. More...
 
void FillHist (const int Sample, TH1 *Hist, std::vector< double > &Array)
 Fill a histogram with the event-level information used in the fit. More...
 
void FillArray_MP ()
 DB Nice new multi-threaded function which calculates the event weights and fills the relevant bins of an array. More...
 
void FillArray ()
 Function which does the core reweighting, fills the SampleHandlerBase::SampleHandler_array vector with the weight calculated from reweighting. More...
 
void ResetHistograms ()
 Helper function to reset histograms. More...
 
void InitialiseSplineObject ()
 
NuPDG GetInitPDGFromFileName (const std::string &FileName) const
 Retrieve the initial neutrino PDG code associated with a given input file name. More...
 
NuPDG GetFinalPDGFromFileName (const std::string &FileName) const
 Retrieve the final neutrino PDG code associated with a given input file name. More...
 
- Protected Member Functions inherited from SampleHandlerInterface
void QuietPlease ()
 CW: Redirect std::cout to silence some experiment specific libraries. More...
 
void NowTalk ()
 CW: Redirect std::cout to silence some experiment specific libraries. More...
 
template<typename T >
bool MatchCondition (const std::vector< T > &allowedValues, const T &value)
 check if event is affected by following conditions, for example pdg, or modes etc More...
 

Protected Attributes

std::unique_ptr< SplineBaseSplineHandler
 Contains all your splines (binned or unbinned) and handles the setup and the returning of weights from spline evaluations. More...
 
std::shared_ptr< OscillationHandlerOscillator
 Contains oscillator handling calculating oscillation probabilities. More...
 
std::vector< std::vector< FunctionalShifter * > > funcParsGrid
 HH - a grid of vectors of enums for each sample and event. More...
 
std::vector< FunctionalShifterfuncParsMap
 HH - a map that relates the funcpar enum to pointer of FuncPars struct HH - Changed to a vector of pointers since it's faster than unordered_map and we are using ints as keys. More...
 
std::vector< FunctionalParameterfuncParsVec
 HH - a vector that stores all the FuncPars struct. More...
 
std::unordered_map< std::string, int > funcParsNamesMap
 HH - a map that relates the name of the functional parameter to funcpar enum. More...
 
std::unordered_map< int, FuncParFuncTypefuncParsFuncMap
 HH - a map that relates the funcpar enum to pointer of the actual function. More...
 
std::vector< std::string > funcParsNamesVec = {}
 HH - a vector of string names for each functional parameter. More...
 
std::unique_ptr< BinningHandlerBinning
 KS: This stores binning information, in future could be come vector to store binning for every used sample. More...
 
std::vector< double > SampleHandler_array
 DB Array to be filled after reweighting. More...
 
std::vector< double > SampleHandler_array_w2
 KS Array used for MC stat. More...
 
std::vector< double > SampleHandler_data
 DB Array to be filled in AddData. More...
 
std::vector< EventInfoMCEvents
 Stores information about every MC event. More...
 
std::vector< SampleInfoSampleDetails
 Stores info about currently initialised sample. More...
 
ParameterHandlerGenericParHandler = nullptr
 ETA - All experiments will need an xsec, det and osc cov. More...
 
std::string SampleHandlerName
 A unique ID for each sample based on which we can define what systematic should be applied. More...
 
std::vector< std::vector< KinematicCut > > StoredSelection
 What gets pulled from config options, these are constant after loading in this is of length 3: 0th index is the value, 1st is lower bound, 2nd is upper bound. More...
 
std::vector< std::vector< KinematicCut > > Selection
 a way to store selection cuts which you may push back in the get1DVar functions most of the time this is just the same as StoredSelection More...
 
const std::unordered_map< std::string, int > * KinematicParameters
 Mapping between string and kinematic enum. More...
 
const std::unordered_map< int, std::string > * ReversedKinematicParameters
 Mapping between kinematic enum and string. More...
 
const std::unordered_map< std::string, int > * KinematicVectors
 
const std::unordered_map< int, std::string > * ReversedKinematicVectors
 
std::unique_ptr< ManagerSampleManager
 The manager object used to read the sample yaml file. More...
 
std::unordered_map< std::string, double > _modeNomWeightMap
 
TLegend * THStackLeg = nullptr
 DB Miscellaneous Variables. More...
 
bool FirstTimeW2
 KS:Super hacky to update W2 or not. More...
 
bool UpdateW2
 KS:Super hacky to update W2 or not. More...
 
- Protected Attributes inherited from SampleHandlerInterface
TestStatistic fTestStatistic
 Test statistic tells what kind of likelihood sample is using. More...
 
std::streambuf * buf
 Keep the cout buffer. More...
 
std::streambuf * errbuf
 Keep the cerr buffer. More...
 
M3::int_t nSamples
 Contains how many samples we've got. More...
 
unsigned int nEvents
 Number of MC events are there. More...
 
std::unique_ptr< MaCh3ModesModes
 Holds information about used Generator and MaCh3 modes. More...
 

Private Types

enum  FDPlotType { kModePlot = 0 , kOscChannelPlot = 1 }
 

Private Member Functions

std::vector< std::vector< KinematicCut > > ApplyTemporarySelection (const int iSample, const std::vector< KinematicCut > &ExtraCuts)
 Temporarily extend Selection for a given sample with additional cuts. Returns the original Selection so the caller can restore it later. More...
 

Private Attributes

std::unordered_map< std::string, NuPDGFileToInitPDGMap
 
std::unordered_map< std::string, NuPDGFileToFinalPDGMap
 

Detailed Description

Class responsible for handling implementation of samples used in analysis, reweighting and returning LLH.

Author
Dan Barrow
Ed Atkin

Definition at line 21 of file SampleHandlerBase.h.

Member Enumeration Documentation

◆ FDPlotType

Enumerator
kModePlot 
kOscChannelPlot 

Definition at line 426 of file SampleHandlerBase.h.

426  {
427  kModePlot = 0,
428  kOscChannelPlot = 1
429  };

Constructor & Destructor Documentation

◆ SampleHandlerBase()

SampleHandlerBase::SampleHandlerBase ( std::string  ConfigFileName,
ParameterHandlerGeneric xsec_cov,
const std::shared_ptr< OscillationHandler > &  OscillatorObj_ = nullptr 
)

Constructor.

Parameters
ConfigFileNameName of config to initialise the sample object

Definition at line 12 of file SampleHandlerBase.cpp.

14 // ************************************************
15  MACH3LOG_INFO("-------------------------------------------------------------------");
16  MACH3LOG_INFO("Creating SampleHandlerBase object");
17 
18  //ETA - safety feature so you can't pass a NULL xsec_cov
19  if(!xsec_cov) {
20  MACH3LOG_WARN("You've passed me a nullptr ParameterHandler so I will not use any xsec parameters");
21  }
22  ParHandler = xsec_cov;
23 
24  nSamples = 1;
25 
26  if (OscillatorObj_ != nullptr) {
27  MACH3LOG_WARN("You have passed an Oscillator object through the constructor of a SampleHandlerBase object - this will be used for all oscillation channels");
28  Oscillator = OscillatorObj_;
29  if(!ParHandler) {
30  MACH3LOG_CRITICAL("You've passed me a nullptr to ParamHandler while non null to Oscillator");
31  MACH3LOG_CRITICAL("Make up you mind");
32  throw MaCh3Exception(__FILE__, __LINE__);
33  }
34  }
35 
36  KinematicParameters = nullptr;
38  KinematicVectors = nullptr;
39  ReversedKinematicVectors = nullptr;
40 
41  SampleHandlerName = "";
42  SampleManager = std::make_unique<Manager>(ConfigFileName.c_str());
43  Binning = std::make_unique<BinningHandler>();
44  // Variables related to MC stat
45  FirstTimeW2 = true;
46  UpdateW2 = false;
47 }
#define MACH3LOG_CRITICAL
Definition: MaCh3Logger.h:38
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
Custom exception class used throughout MaCh3.
std::string SampleHandlerName
A unique ID for each sample based on which we can define what systematic should be applied.
const std::unordered_map< int, std::string > * ReversedKinematicParameters
Mapping between kinematic enum and string.
std::shared_ptr< OscillationHandler > Oscillator
Contains oscillator handling calculating oscillation probabilities.
std::unique_ptr< Manager > SampleManager
The manager object used to read the sample yaml file.
const std::unordered_map< std::string, int > * KinematicParameters
Mapping between string and kinematic enum.
std::unique_ptr< BinningHandler > Binning
KS: This stores binning information, in future could be come vector to store binning for every used s...
ParameterHandlerGeneric * ParHandler
ETA - All experiments will need an xsec, det and osc cov.
bool UpdateW2
KS:Super hacky to update W2 or not.
const std::unordered_map< int, std::string > * ReversedKinematicVectors
const std::unordered_map< std::string, int > * KinematicVectors
bool FirstTimeW2
KS:Super hacky to update W2 or not.
M3::int_t nSamples
Contains how many samples we've got.
SampleHandlerInterface()
The main constructor.

◆ ~SampleHandlerBase()

SampleHandlerBase::~SampleHandlerBase ( )
virtual

destructor

Definition at line 49 of file SampleHandlerBase.cpp.

49  {
50  MACH3LOG_DEBUG("I'm deleting SampleHandlerBase");
51  if(THStackLeg != nullptr) delete THStackLeg;
52 }
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
TLegend * THStackLeg
DB Miscellaneous Variables.

Member Function Documentation

◆ AddAdditionalWeightPointers()

virtual void SampleHandlerBase::AddAdditionalWeightPointers ( )
protectedpure virtual

DB Function to determine which weights apply to which types of samples.

Implemented in PySampleHandlerBase.

◆ AddData() [1/2]

void SampleHandlerBase::AddData ( const int  Sample,
const std::vector< double > &  Data_Array 
)

Definition at line 1020 of file SampleHandlerBase.cpp.

1020  {
1021 // ************************************************
1022  const int Start = Binning->GetSampleStartBin(Sample);
1023  const int End = Binning->GetSampleEndBin(Sample);
1024  const int ExpectedSize = End - Start;
1025 
1026  if (static_cast<int>(Data_Array.size()) != ExpectedSize) {
1027  MACH3LOG_ERROR("Data_Array size mismatch for sample '{}'.", GetSampleTitle(Sample));
1028  MACH3LOG_ERROR("Expected size: {}, received size: {}.", ExpectedSize, Data_Array.size());
1029  MACH3LOG_ERROR("Start bin: {}, End bin: {}.", Start, End);
1030  MACH3LOG_ERROR("This likely indicates a binning or sample slicing bug.");
1031  throw MaCh3Exception(__FILE__, __LINE__);
1032  }
1033 
1034  std::copy_n(Data_Array.begin(), End-Start, SampleHandler_data.begin() + Start);
1035 
1036  FillHist(Sample, SampleDetails[Sample].DataHist, SampleHandler_data);
1037 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
void FillHist(const int Sample, TH1 *Hist, std::vector< double > &Array)
Fill a histogram with the event-level information used in the fit.
std::vector< SampleInfo > SampleDetails
Stores info about currently initialised sample.
std::string GetSampleTitle(const int Sample) const final
Get fancy title for specified samples.
std::vector< double > SampleHandler_data
DB Array to be filled in AddData.

◆ AddData() [2/2]

void SampleHandlerBase::AddData ( const int  Sample,
TH1 *  Data 
)

Definition at line 948 of file SampleHandlerBase.cpp.

948  {
949 // ************************************************
950  int Dim = GetNDim(Sample);
951  MACH3LOG_INFO("Adding {}D data histogram: {} with {:.2f} events", Dim, Data->GetTitle(), Data->Integral());
952  // delete old histogram
953  delete SampleDetails[Sample].DataHist;
954  SampleDetails[Sample].DataHist = static_cast<TH1*>(Data->Clone());
955 
956  if(!SampleHandler_data.size()) {
957  MACH3LOG_ERROR("SampleHandler_data haven't been initialised yet");
958  throw MaCh3Exception(__FILE__, __LINE__);
959  }
960 
961  auto ChecHistType = [&](const std::string& Type, const int Dimen, const TH1* Hist,
962  const std::string& file, const int line) {
963  if (std::string(Hist->ClassName()) != Type) {
964  MACH3LOG_ERROR("Expected {} for {}D sample, got {}", Type, Dimen, Hist->ClassName());
965  throw MaCh3Exception(file, line);
966  }
967  };
968 
969  if (Dim == 1) {
970  // Ensure we really have a TH1D
971  ChecHistType("TH1D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
972  M3::CheckBinningMatch(static_cast<TH1D*>(SampleDetails[Sample].DataHist),
973  static_cast<TH1D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
974  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
975  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin});
976  // ROOT histograms are 1-based, so bin index + 1
977  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(xBin + 1);
978  }
979  SampleDetails[Sample].DataHist->GetXaxis()->SetTitle(GetKinVarName(Sample, 0).c_str());
980  SampleDetails[Sample].DataHist->GetYaxis()->SetTitle("Number of Events");
981  } else if (Dim == 2) {
982  if(Binning->IsUniform(Sample)) {
983  ChecHistType("TH2D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
984  M3::CheckBinningMatch(static_cast<TH2D*>(SampleDetails[Sample].DataHist),
985  static_cast<TH2D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
986  for (int yBin = 0; yBin < Binning->GetNAxisBins(Sample, 1); ++yBin) {
987  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
988  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
989  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
990  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(xBin + 1, yBin + 1);
991  }
992  }
993  } else{
994  ChecHistType("TH2Poly", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
995  M3::CheckBinningMatch(static_cast<TH2Poly*>(SampleDetails[Sample].DataHist),
996  static_cast<TH2Poly*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
997  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
998  const int idx = iBin + Binning->GetSampleStartBin(Sample);
999  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
1000  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(iBin + 1);
1001  }
1002  }
1003 
1004  SampleDetails[Sample].DataHist->GetXaxis()->SetTitle(GetKinVarName(Sample, 0).c_str());
1005  SampleDetails[Sample].DataHist->GetYaxis()->SetTitle(GetKinVarName(Sample, 1).c_str());
1006  SampleDetails[Sample].DataHist->GetZaxis()->SetTitle("Number of Events");
1007  } else {
1008  ChecHistType("TH1D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
1009  M3::CheckBinningMatch(static_cast<TH1D*>(SampleDetails[Sample].DataHist),
1010  static_cast<TH1D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
1011  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
1012  const int idx = iBin + Binning->GetSampleStartBin(Sample);
1013  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
1014  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(iBin + 1);
1015  }
1016  }
1017 }
int GetNDim(const int Sample) const final
DB Get what dimensionality binning for given sample has.
std::string GetKinVarName(const int iSample, const int Dimension) const final
Return Kinematic Variable name for specified sample and dimension for example "Reconstructed_Neutrino...
void CheckBinningMatch(const TH1D *Hist1, const TH1D *Hist2, const std::string &File, const int Line)
KS: Helper function check if data and MC binning matches.

◆ ApplyShifts()

void SampleHandlerBase::ApplyShifts ( const int  iEvent)
protectedvirtual

ETA - generic function applying shifts.

Definition at line 549 of file SampleHandlerBase.cpp.

549  {
550 // ***************************************************************************
551  const auto& shifts = funcParsGrid[iEvent];
552  const auto nShifts = shifts.size();
553  // KS: If there are no shifts then there is no point in resetting which can be costly.
554  if(nShifts == 0) {
555  return;
556  }
557 
558  // Given a sample and event, apply the shifts to the event based on the vector of functional parameter enums
559  // First reset shifted array back to nominal values
560  ResetShifts(iEvent);
561 
562  for (std::size_t iShift = 0; iShift < nShifts; ++iShift) {
563  const auto* _restrict_ fp = shifts[iShift];
564  (*fp->funcPtr)(fp->valuePtr, iEvent);
565  }
566 
567  FinaliseShifts(iEvent);
568 }
#define _restrict_
KS: Using restrict limits the effects of pointer aliasing, aiding optimizations. While reading I foun...
Definition: Core.h:108
virtual void FinaliseShifts(const int iEvent)
LP - Optionally calculate derived observables after all shifts have been applied.
virtual void ResetShifts(const int iEvent)
HH - reset the shifted values to the original values.
std::vector< std::vector< FunctionalShifter * > > funcParsGrid
HH - a grid of vectors of enums for each sample and event.

◆ ApplyTemporarySelection()

std::vector< std::vector< KinematicCut > > SampleHandlerBase::ApplyTemporarySelection ( const int  iSample,
const std::vector< KinematicCut > &  ExtraCuts 
)
private

Temporarily extend Selection for a given sample with additional cuts. Returns the original Selection so the caller can restore it later.

Definition at line 1404 of file SampleHandlerBase.cpp.

1405  {
1406 // ************************************************
1407  // Backup current selection
1408  auto originalSelection = Selection;
1409 
1410  //DB Add all the predefined selections to the selection vector which will be applied
1411  auto selectionToApply = Selection;
1412 
1413  //DB Add all requested cuts from the argument to the selection vector which will be applied
1414  for (const auto& cut : ExtraCuts) {
1415  selectionToApply[iSample].emplace_back(cut);
1416  }
1417 
1418  //DB Set the member variable to be the cuts to apply
1419  Selection = std::move(selectionToApply);
1420 
1421  return originalSelection;
1422 }
std::vector< std::vector< KinematicCut > > Selection
a way to store selection cuts which you may push back in the get1DVar functions most of the time this...

◆ BuildModeChannelSelection()

std::vector< KinematicCut > SampleHandlerBase::BuildModeChannelSelection ( const int  iSample,
const int  kModeToFill,
const int  kChannelToFill 
) const

Definition at line 1734 of file SampleHandlerBase.cpp.

1734  {
1735 // ************************************************
1736  bool fChannel;
1737  bool fMode;
1738 
1739  if (kChannelToFill != -1) {
1740  if (kChannelToFill > GetNOscChannels(iSample)) {
1741  MACH3LOG_ERROR("Required channel is not available. kChannelToFill should be between 0 and {}", GetNOscChannels(iSample));
1742  MACH3LOG_ERROR("kChannelToFill given:{}", kChannelToFill);
1743  MACH3LOG_ERROR("Exiting.");
1744  throw MaCh3Exception(__FILE__, __LINE__);
1745  }
1746  fChannel = true;
1747  } else {
1748  fChannel = false;
1749  }
1750 
1751  if (kModeToFill != -1) {
1752  if (!(kModeToFill >= 0) && (kModeToFill < Modes->GetNModes())) {
1753  MACH3LOG_ERROR("Required mode is not available. kModeToFill should be between 0 and {}", Modes->GetNModes());
1754  MACH3LOG_ERROR("kModeToFill given:{}", kModeToFill);
1755  MACH3LOG_ERROR("Exiting..");
1756  throw MaCh3Exception(__FILE__, __LINE__);
1757  }
1758  fMode = true;
1759  } else {
1760  fMode = false;
1761  }
1762 
1763  std::vector< KinematicCut > SelectionVec;
1764 
1765  if (fMode) {
1766  KinematicCut SelecMode;
1768  SelecMode.LowerBound = kModeToFill;
1769  SelecMode.UpperBound = kModeToFill+1;
1770  SelectionVec.push_back(SelecMode);
1771  }
1772 
1773  if (fChannel) {
1774  KinematicCut SelecChannel;
1775  SelecChannel.ParamToCutOnIt = ReturnKinematicParameterFromString("OscillationChannel");
1776  SelecChannel.LowerBound = kChannelToFill;
1777  SelecChannel.UpperBound = kChannelToFill+1;
1778  SelectionVec.push_back(SelecChannel);
1779  }
1780 
1781  return SelectionVec;
1782 }
int GetNOscChannels(const int iSample) const final
Get number of oscillation channels for a single sample.
int ReturnKinematicParameterFromString(const std::string &KinematicStr) const
ETA function to generically convert a string from xsec cov to a kinematic type.
std::unique_ptr< MaCh3Modes > Modes
Holds information about used Generator and MaCh3 modes.
KS: Small struct used for applying kinematic cuts.
double UpperBound
Upper bound on which we apply cut.
double LowerBound
Lower bound on which we apply cut.
int ParamToCutOnIt
Index or enum value identifying the kinematic variable to cut on.

◆ CalcNormsBins()

void SampleHandlerBase::CalcNormsBins ( std::vector< NormParameter > &  norm_parameters,
std::vector< std::vector< int > > &  norms_bins 
)
protected

Check whether a normalisation systematic affects an event or not.

Definition at line 658 of file SampleHandlerBase.cpp.

658  {
659 // ************************************************
660  #ifdef MACH3_DEBUG
661  std::vector<int> VerboseCounter(norm_parameters.size(), 0);
662  #endif
663  for(unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent){
664  std::vector< int > NormBins = {};
665  if (ParHandler) {
666  // Skip oscillated NC events
667  // Not strictly needed, but these events don't get included in oscillated predictions, so
668  // no need to waste our time calculating and storing information about xsec parameters
669  // that will never be used.
670  if (MCEvents[iEvent].isNC && (MCEvents[iEvent].nupdg != MCEvents[iEvent].nupdgUnosc) ) {
671  MACH3LOG_TRACE("Event {}, missed NC/signal check", iEvent);
672  continue;
673  } //DB Abstract check on MaCh3Modes to determine which apply to neutral current
674  for (std::vector<NormParameter>::iterator it = norm_parameters.begin(); it != norm_parameters.end(); ++it) {
675  //Now check that the target of an interaction matches with the normalisation parameters
676  const int Target = static_cast<int>(std::round(ReturnKinematicParameter("TargetNucleus", iEvent)));
677  bool TargetMatch = MatchCondition(it->targets, Target);
678  if (!TargetMatch) {
679  MACH3LOG_TRACE("Event {}, missed target check ({}) for dial {}", iEvent, Target, it->name);
680  continue;
681  }
682 
683  //Now check that the neutrino flavour in an interaction matches with the normalisation parameters
684  bool FlavourMatch = MatchCondition(it->pdgs, MCEvents[iEvent].nupdg);
685  if (!FlavourMatch) {
686  MACH3LOG_TRACE("Event {}, missed PDG check ({}) for dial {}", iEvent,MCEvents[iEvent].nupdg, it->name);
687  continue;
688  }
689 
690  //Now check that the unoscillated neutrino flavour in an interaction matches with the normalisation parameters
691  bool FlavourUnoscMatch = MatchCondition(it->preoscpdgs, MCEvents[iEvent].nupdgUnosc);
692  if (!FlavourUnoscMatch){
693  MACH3LOG_TRACE("Event {}, missed FlavourUnosc check ({}) for dial {}", iEvent,MCEvents[iEvent].nupdgUnosc, it->name);
694  continue;
695  }
696 
697  //Now check that the mode of an interaction matches with the normalisation parameters
698  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", iEvent)));
699  bool ModeMatch = MatchCondition(it->modes, Mode);
700  if (!ModeMatch) {
701  MACH3LOG_TRACE("Event {}, missed Mode check ({}) for dial {}", iEvent, Mode, it->name);
702  continue;
703  }
704 
705  //Now check whether the norm has kinematic bounds
706  //i.e. does it only apply to events in a particular kinematic region?
707  // Now check whether within kinematic bounds
708  bool IsSelected = PassesSelection((*it), iEvent);
709  // Need to then break the event loop
710  if(!IsSelected){
711  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", iEvent, it->name);
712  continue;
713  }
714  // Now set 'index bin' for each normalisation parameter
715  // All normalisations are just 1 bin for 2015, so bin = index (where index is just the bin for that normalisation)
716  int bin = it->index;
717 
718  NormBins.push_back(bin);
719  MACH3LOG_TRACE("Event {}, will be affected by dial {}", iEvent, it->name);
720  #ifdef MACH3_DEBUG
721  VerboseCounter[std::distance(norm_parameters.begin(), it)]++;
722  #endif
723  //}
724  } // end iteration over norm_parameters
725  } // end if (ParHandler)
726  norms_bins[iEvent] = NormBins;
727  }//end loop over events
728  #ifdef MACH3_DEBUG
729  MACH3LOG_DEBUG("┌──────────────────────────────────────────────────────────┐");
730  for (std::size_t i = 0; i < norm_parameters.size(); ++i) {
731  const auto& norm = norm_parameters[i];
732  double eventRatio = static_cast<double>(VerboseCounter[i]) / static_cast<double>(GetNEvents());
733 
734  MACH3LOG_DEBUG("│ Param {:<15}, affects {:<8} events ({:>6.2f}%) │",
735  ParHandler->GetParFancyName(norm.index), VerboseCounter[i], eventRatio);
736  }
737  MACH3LOG_DEBUG("└──────────────────────────────────────────────────────────┘");
738  #endif
739 }
#define MACH3LOG_TRACE
Definition: MaCh3Logger.h:33
std::string GetParFancyName(const int i) const
Get fancy name of the Parameter.
bool PassesSelection(const ParT &Par, std::size_t iEvent)
double ReturnKinematicParameter(const std::string &KinematicParameter, int iEvent) const
Return the value of an associated kinematic parameter for an event.
std::vector< EventInfo > MCEvents
Stores information about every MC event.
bool MatchCondition(const std::vector< T > &allowedValues, const T &value)
check if event is affected by following conditions, for example pdg, or modes etc
unsigned int GetNEvents() const

◆ CalcWeightFunc()

virtual void SampleHandlerBase::CalcWeightFunc ( const int  iEvent)
inlineprotectedvirtual

Calculate weights for function parameters.

First you need to setup additional pointers in you experiment code in SetupWeightPointers Then in this function you can calculate whatever fancy function you want by filling weight to which you have pointer This way func weight shall be used in GetEventWeight

Definition at line 294 of file SampleHandlerBase.h.

294 {return; (void)iEvent;};

◆ CalcWeightTotal()

M3::float_t SampleHandlerBase::CalcWeightTotal ( const EventInfo *_restrict_  MCEvent) const
protected

Calculate the total weight weight for a given event.

Definition at line 572 of file SampleHandlerBase.cpp.

572  {
573 // ***************************************************************************
574  M3::float_t TotalWeight = 1.0;
575  const int TotalWeights = static_cast<int>(MCEvent->total_weight_pointers.size());
576  //DB Loop over stored pointers
577  #ifdef MULTITHREAD
578  #pragma omp simd reduction(*:TotalWeight)
579  #endif
580  for (int iWeight = 0; iWeight < TotalWeights; ++iWeight) {
581  TotalWeight *= *(MCEvent->total_weight_pointers[iWeight]);
582  }
583 
584  return TotalWeight;
585 }
double float_t
Definition: Core.h:37
std::vector< const M3::float_t * > total_weight_pointers
Pointers to weights like oscillation spline, normalisation etc.

◆ Fill1DSubEventHist()

void SampleHandlerBase::Fill1DSubEventHist ( const int  iSample,
TH1D *  _h1DVar,
const std::string &  ProjectionVar,
const std::vector< KinematicCut > &  SubEventSelectionVec = {},
int  WeightStyle = 0 
)

Definition at line 1469 of file SampleHandlerBase.cpp.

1470  {
1471 // ************************************************
1472  int ProjectionVar_Int = ReturnKinematicVectorFromString(ProjectionVar_Str);
1473 
1474  //JM Loop over all events
1475  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1476  const int EventSample = MCEvents[iEvent].NominalSample;
1477  if(EventSample != iSample) continue;
1478  if (IsEventSelected(EventSample, iEvent)) {
1479  double Weight = GetEventWeight(iEvent);
1480  if (WeightStyle == 1) {
1481  Weight = 1.;
1482  }
1483  std::vector<double> Vec = ReturnKinematicVector(ProjectionVar_Int,iEvent);
1484  size_t nsubevents = Vec.size();
1485  //JM Loop over all subevents in event
1486  for (unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1487  if (IsSubEventSelected(SubEventSelectionVec, iEvent, iSubEvent, nsubevents)) {
1488  double Var = Vec[iSubEvent];
1489  _h1DVar->Fill(Var,Weight);
1490  }
1491  }
1492  }
1493  }
1494 }
std::vector< double > ReturnKinematicVector(const std::string &KinematicParameter, const int iEvent) const
bool IsEventSelected(const int iSample, const int iEvent) _noexcept_
DB Function which determines if an event is selected based on KinematicCut.
M3::float_t GetEventWeight(const int iEntry)
Computes the total event weight for a given entry.
bool IsSubEventSelected(const std::vector< KinematicCut > &SubEventCuts, const int iEvent, unsigned const int iSubEvent, size_t nsubevents)
JM Function which determines if a subevent is selected.
int ReturnKinematicVectorFromString(const std::string &KinematicStr) const
JM: Convert a kinematic vector name to its corresponding integer ID.

◆ Fill2DSubEventHist()

void SampleHandlerBase::Fill2DSubEventHist ( const int  iSample,
TH2 *  _h2DVar,
const std::string &  ProjectionVarX,
const std::string &  ProjectionVarY,
const std::vector< KinematicCut > &  SubEventSelectionVec = {},
int  WeightStyle = 0 
)

Definition at line 1552 of file SampleHandlerBase.cpp.

1556  {
1557 // ************************************************
1558  bool IsSubEventVarX = IsSubEventVarString(ProjectionVar_StrX);
1559  bool IsSubEventVarY = IsSubEventVarString(ProjectionVar_StrY);
1560 
1561  int ProjectionVar_IntX, ProjectionVar_IntY;
1562  if (IsSubEventVarX) ProjectionVar_IntX = ReturnKinematicVectorFromString(ProjectionVar_StrX);
1563  else ProjectionVar_IntX = ReturnKinematicParameterFromString(ProjectionVar_StrX);
1564  if (IsSubEventVarY) ProjectionVar_IntY = ReturnKinematicVectorFromString(ProjectionVar_StrY);
1565  else ProjectionVar_IntY = ReturnKinematicParameterFromString(ProjectionVar_StrY);
1566 
1567  //JM Loop over all events
1568  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1569  const int EventSample = MCEvents[iEvent].NominalSample;
1570  if(EventSample != iSample) continue;
1571  if (IsEventSelected(EventSample, iEvent)) {
1572  double Weight = GetEventWeight(iEvent);
1573  if (WeightStyle == 1) {
1574  Weight = 1.;
1575  }
1576  std::vector<double> VecX = {}, VecY = {};
1577  double VarX = M3::_BAD_DOUBLE_, VarY = M3::_BAD_DOUBLE_;
1578  size_t nsubevents = 0;
1579  // JM Three cases: subeventX vs eventY || eventX vs subeventY || subeventX vs subeventY
1580  if (IsSubEventVarX && !IsSubEventVarY) {
1581  VecX = ReturnKinematicVector(ProjectionVar_IntX, iEvent);
1582  VarY = ReturnKinematicParameter(ProjectionVar_IntY, iEvent);
1583  nsubevents = VecX.size();
1584  }
1585  else if (!IsSubEventVarX && IsSubEventVarY) {
1586  VecY = ReturnKinematicVector(ProjectionVar_IntY, iEvent);
1587  VarX = ReturnKinematicParameter(ProjectionVar_IntX, iEvent);
1588  nsubevents = VecY.size();
1589  }
1590  else {
1591  VecX = ReturnKinematicVector(ProjectionVar_IntX, iEvent);
1592  VecY = ReturnKinematicVector(ProjectionVar_IntY, iEvent);
1593  if (VecX.size() != VecY.size()) {
1594  MACH3LOG_ERROR("Cannot plot {} of size {} against {} of size {}", ProjectionVar_StrX, VecX.size(), ProjectionVar_StrY, VecY.size());
1595  throw MaCh3Exception(__FILE__, __LINE__);
1596  }
1597  nsubevents = VecX.size();
1598  }
1599  //JM Loop over all subevents in event
1600  for (unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1601  if (IsSubEventSelected(SubEventSelectionVec, iEvent, iSubEvent, nsubevents)) {
1602  if (IsSubEventVarX) VarX = VecX[iSubEvent];
1603  if (IsSubEventVarY) VarY = VecY[iSubEvent];
1604  _h2DVar->Fill(VarX,VarY,Weight);
1605  }
1606  }
1607  }
1608  }
1609 }
bool IsSubEventVarString(const std::string &VarStr) const
JM: Check if a kinematic parameter string corresponds to a subevent-level variable.
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:53

◆ FillArray()

void SampleHandlerBase::FillArray ( )
protected

Function which does the core reweighting, fills the SampleHandlerBase::SampleHandler_array vector with the weight calculated from reweighting.

Definition at line 355 of file SampleHandlerBase.cpp.

355  {
356 //************************************************
357  //DB Reset which cuts to apply
359 
360  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
361  ApplyShifts(iEvent);
362  const EventInfo* _restrict_ MCEvent = &MCEvents[iEvent];
363 
364  if (!IsEventSelected(MCEvent->NominalSample, iEvent)) {
365  continue;
366  }
367 
368  // Virtual by default does nothing, has to happen before CalcWeightTotal
369  CalcWeightFunc(iEvent);
370 
371  const M3::float_t totalweight = CalcWeightTotal(MCEvent);
372  //DB Catch negative total weights and skip any event with a negative weight. Previously we would set weight to zero and continue but that is inefficient
373  if (totalweight <= 0.){
374  continue;
375  }
376 
377  //DB Find the relevant bin in the PDF for each event
378  const int GlobalBin = Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
379 
380  //DB Fill relevant part of thread array
381  if (GlobalBin > M3::UnderOverFlowBin) {
382  SampleHandler_array[GlobalBin] += totalweight;
383  if (FirstTimeW2) SampleHandler_array_w2[GlobalBin] += totalweight*totalweight;
384  }
385  }
386 }
std::vector< std::vector< KinematicCut > > StoredSelection
What gets pulled from config options, these are constant after loading in this is of length 3: 0th in...
virtual void ApplyShifts(const int iEvent)
ETA - generic function applying shifts.
M3::float_t CalcWeightTotal(const EventInfo *_restrict_ MCEvent) const _noexcept_
Calculate the total weight weight for a given event.
std::vector< double > SampleHandler_array_w2
KS Array used for MC stat.
virtual void CalcWeightFunc(const int iEvent)
Calculate weights for function parameters.
std::vector< double > SampleHandler_array
DB Array to be filled after reweighting.
constexpr static const int UnderOverFlowBin
Mark bin which is overflow or underflow in MaCh3 binning.
Definition: Core.h:91
Stores info about each MC event used during reweighting routine.

◆ FillArray_MP()

void SampleHandlerBase::FillArray_MP ( )
protected

DB Nice new multi-threaded function which calculates the event weights and fills the relevant bins of an array.

Multithreaded version of fillArray.

Function which does the core reweighting, fills the SampleHandlerBase::SampleHandler_array vector with the weight calculated from reweighting but multithreaded

See also
fillArray()

Definition at line 393 of file SampleHandlerBase.cpp.

393  {
394 // ************************************************
395  //DB Reset which cuts to apply
397 
398  // NOTE comment below is left for historical reasons
399  //DB - Brain dump of speedup ideas
400  //
401  //Those relevant to reweighting
402  // 1. Don't bother storing and calculating NC signal events - Implemented and saves marginal s/step
403  // 2. Loop over spline event weight calculation in the following event loop - Currently done in splineSKBase->calcWeight() where multi-threading won't be optimised - Implemented and saves 0.3s/step
404  // 3. Inline getDiscVar or somehow include that calculation inside the multi-threading - Implemented and saves about 0.01s/step
405  // 4. Include isCC inside SKMCStruct so don't have to have several 'if' statements determine if oscillation weight needs to be set to 1.0 for NC events - Implemented and saves marginal s/step
406  // 5. Do explicit check on adjacent bins when finding event XBin instead of looping over all BinEdge indices - Implemented but doesn't significantly affect s/step
407  //
408  //Other aspects
409  // 1. Order minituples in Y-axis variable as this will *hopefully* reduce cache misses inside SampleHandler_array_class[yBin][xBin]
410  //
411  // We will hit <0.1 s/step eventually! :D
412  const auto TotalBins = Binning->GetNBins();
413  const unsigned int NumberOfEvents = GetNEvents();
414 
415  double* _restrict_ MC_Array_for_reduction = SampleHandler_array.data();
416  double* _restrict_ W2_array_for_reduction = SampleHandler_array_w2.data();
417 
418  #pragma omp parallel for reduction(+:MC_Array_for_reduction[:TotalBins], W2_array_for_reduction[:TotalBins])
419  for (unsigned int iEvent = 0; iEvent < NumberOfEvents; ++iEvent) {
420  //ETA - generic functions to apply shifts to kinematic variables
421  // Apply this before IsEventSelected is called.
422  ApplyShifts(iEvent);
423 
424  const EventInfo* _restrict_ MCEvent = &MCEvents[iEvent];
425  //ETA - generic functions to apply shifts to kinematic variable
426  if(!IsEventSelected(MCEvent->NominalSample, iEvent)){
427  continue;
428  }
429 
430  // Virtual by default does nothing, has to happen before CalcWeightTotal
431  CalcWeightFunc(iEvent);
432 
433  const M3::float_t totalweight = CalcWeightTotal(MCEvent);
434  //DB Catch negative total weights and skip any event with a negative weight. Previously we would set weight to zero and continue but that is inefficient
435  if (totalweight <= 0.){
436  continue;
437  }
438 
439  //DB Find the relevant bin in the PDF for each event
440  const int GlobalBin = Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
441 
442  //ETA - we can probably remove this final if check on the -1?
443  //Maybe we can add an overflow bin to the array and assign any events to this bin?
444  //Might save us an extra if call?
445  //DB Fill relevant part of thread array
446  if (GlobalBin > M3::UnderOverFlowBin) {
447  MC_Array_for_reduction[GlobalBin] += totalweight;
448  if (FirstTimeW2) W2_array_for_reduction[GlobalBin] += totalweight*totalweight;
449  }
450  }
451 }

◆ FillHist()

void SampleHandlerBase::FillHist ( const int  Sample,
TH1 *  Hist,
std::vector< double > &  Array 
)
protected

Fill a histogram with the event-level information used in the fit.

DB Functions required for reweighting functions DB Replace previous implementation with reading bin contents from SampleHandler_array

Definition at line 245 of file SampleHandlerBase.cpp.

245  {
246 // ************************************************
247  int Dimension = GetNDim(Sample);
248  // DB Commented out by default - Code heading towards GetLikelihood using arrays instead of root objects
249  // Wouldn't actually need this for GetLikelihood as TH objects wouldn't be filled
250  if(Dimension == 1) {
251  Hist->Reset();
252  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
253  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin});
254  Hist->SetBinContent(xBin + 1, Array[idx]);
255  }
256  } else if (Dimension == 2) {
257  Hist->Reset();
258  if(Binning->IsUniform(Sample)) {
259  for (int yBin = 0; yBin < Binning->GetNAxisBins(Sample, 1); ++yBin) {
260  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
261  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
262  Hist->SetBinContent(xBin + 1, yBin + 1, Array[idx]);
263  }
264  }
265  } else {
266  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
267  const int idx = iBin + Binning->GetSampleStartBin(Sample);
268  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
269  Hist->SetBinContent(iBin + 1, Array[idx]);
270  }
271  }
272  } else {
273  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
274  const int idx = iBin + Binning->GetSampleStartBin(Sample);
275  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
276  Hist->SetBinContent(iBin + 1, Array[idx]);
277  }
278  }
279 }

◆ FinaliseShifts()

virtual void SampleHandlerBase::FinaliseShifts ( const int  iEvent)
inlineprotectedvirtual

LP - Optionally calculate derived observables after all shifts have been applied.

LP - For example, have shifts that varied lepton energy and hadron energy separately in a subclass implementation of this method you may add the shifted quantities together to build a shifted neutrino energy estimator

Definition at line 260 of file SampleHandlerBase.h.

260 {(void)iEvent;};

◆ FindNominalBinAndEdges()

void SampleHandlerBase::FindNominalBinAndEdges ( )
protected

Definition at line 851 of file SampleHandlerBase.cpp.

851  {
852 // ************************************************
853  for (unsigned int event_i = 0; event_i < GetNEvents(); event_i++) {
854  int Sample = MCEvents[event_i].NominalSample;
855  const int dim = GetNDim(Sample);
856  MCEvents[event_i].KinVar.resize(dim);
857  MCEvents[event_i].NomBin.resize(dim);
858 
859  auto SetNominalBin = [&](int bin, int max_bins, int& out_bin) {
860  if (bin >= 0 && bin < max_bins) {
861  out_bin = bin;
862  } else {
863  out_bin = M3::UnderOverFlowBin; // Out of bounds
864  }
865  };
866 
867  // Find nominal bin for each dimension
868  for(int iDim = 0; iDim < dim; iDim++) {
869  MCEvents[event_i].KinVar[iDim] = GetPointerToKinematicParameter(GetKinVarName(Sample, iDim), event_i);
870  if (std::isnan(*MCEvents[event_i].KinVar[iDim]) || std::isinf(*MCEvents[event_i].KinVar[iDim])) {
871  MACH3LOG_ERROR("Variable {} for sample {} and dimension {} is ill-defined and equal to {}",
872  GetKinVarName(Sample, iDim), GetSampleTitle(Sample), dim, *MCEvents[event_i].KinVar[iDim]);
873  throw MaCh3Exception(__FILE__, __LINE__);
874  }
875  const int bin = Binning->FindNominalBin(Sample, iDim, *MCEvents[event_i].KinVar[iDim]);
876  int NBins_i = static_cast<int>(Binning->GetBinEdges(Sample, iDim).size() - 1);
877  SetNominalBin(bin, NBins_i, MCEvents[event_i].NomBin[iDim]);
878  }
879  }
880 }
const double * GetPointerToKinematicParameter(const std::string &KinematicParameter, int iEvent) const

◆ Get1DVarHist()

std::unique_ptr< TH1 > SampleHandlerBase::Get1DVarHist ( const int  iSample,
const std::string &  ProjectionVar,
const std::vector< KinematicCut > &  EventSelectionVec = {},
int  WeightStyle = 0,
const std::vector< KinematicCut > &  SubEventSelectionVec = {} 
)
finalvirtual

Implements SampleHandlerInterface.

Definition at line 1426 of file SampleHandlerBase.cpp.

1429  {
1430 // ************************************************
1431  //DB Need to overwrite the Selection member variable so that IsEventSelected function operates correctly.
1432  // Consequently, store the selection cuts already saved in the sample, overwrite the Selection variable, then reset
1433  auto tmp_Selection = ApplyTemporarySelection(iSample, EventSelectionVec);
1434 
1435  //DB Define the histogram which will be returned
1436  std::vector<double> xBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_Str);
1437  auto _h1DVar = std::make_unique<TH1D>("", "", int(xBinEdges.size())-1, xBinEdges.data());
1438  _h1DVar->SetDirectory(nullptr);
1439  _h1DVar->GetXaxis()->SetTitle(ProjectionVar_Str.c_str());
1440  _h1DVar->GetYaxis()->SetTitle("Events");
1441 
1442  if (IsSubEventVarString(ProjectionVar_Str)) {
1443  Fill1DSubEventHist(iSample, _h1DVar.get(), ProjectionVar_Str, SubEventSelectionVec, WeightStyle);
1444  } else {
1445  //DB Grab the associated enum with the argument string
1446  int ProjectionVar_Int = ReturnKinematicParameterFromString(ProjectionVar_Str);
1447 
1448  //DB Loop over all events
1449  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1450  const int EventSample = MCEvents[iEvent].NominalSample;
1451  if(EventSample != iSample) continue;
1452  if (IsEventSelected(EventSample, iEvent)) {
1453  double Weight = GetEventWeight(iEvent);
1454  if (WeightStyle == 1) {
1455  Weight = 1.;
1456  }
1457  double Var = ReturnKinematicParameter(ProjectionVar_Int, iEvent);
1458  _h1DVar->Fill(Var, Weight);
1459  }
1460  }
1461  }
1462  //DB Reset the saved selection
1463  Selection = tmp_Selection;
1464 
1465  return _h1DVar;
1466 }
std::vector< double > ReturnKinematicParameterBinning(const int Sample, const std::string &KinematicParameter) const final
Return the binning used to draw a kinematic parameter.
void Fill1DSubEventHist(const int iSample, TH1D *_h1DVar, const std::string &ProjectionVar, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
std::vector< std::vector< KinematicCut > > ApplyTemporarySelection(const int iSample, const std::vector< KinematicCut > &ExtraCuts)
Temporarily extend Selection for a given sample with additional cuts. Returns the original Selection ...

◆ Get1DVarHistByModeAndChannel()

std::unique_ptr< TH1 > SampleHandlerBase::Get1DVarHistByModeAndChannel ( const int  iSample,
const std::string &  ProjectionVar_Str,
const int  kModeToFill = -1,
const int  kChannelToFill = -1,
const int  WeightStyle = 0 
)
finalvirtual

Implements SampleHandlerInterface.

Definition at line 1785 of file SampleHandlerBase.cpp.

1786  {
1787 // ************************************************
1788  auto SelectionVec = BuildModeChannelSelection(iSample, kModeToFill, kChannelToFill);
1789  return Get1DVarHist(iSample, ProjectionVar_Str, SelectionVec, WeightStyle);
1790 }
std::vector< KinematicCut > BuildModeChannelSelection(const int iSample, const int kModeToFill, const int kChannelToFill) const
std::unique_ptr< TH1 > Get1DVarHist(const int iSample, const std::string &ProjectionVar, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, const std::vector< KinematicCut > &SubEventSelectionVec={}) final

◆ Get2DVarHist()

std::unique_ptr< TH2 > SampleHandlerBase::Get2DVarHist ( const int  iSample,
const std::string &  ProjectionVarX,
const std::string &  ProjectionVarY,
const std::vector< KinematicCut > &  EventSelectionVec = {},
int  WeightStyle = 0,
const std::vector< KinematicCut > &  SubEventSelectionVec = {} 
)
finalvirtual

Implements SampleHandlerInterface.

Definition at line 1497 of file SampleHandlerBase.cpp.

1501  {
1502 // ************************************************
1503  //DB Need to overwrite the Selection member variable so that IsEventSelected function operates correctly.
1504  // Consequently, store the selection cuts already saved in the sample, overwrite the Selection variable, then reset
1505  auto tmp_Selection = ApplyTemporarySelection(iSample, EventSelectionVec);
1506 
1507  //DB Define the histogram which will be returned
1508  //KS: If we use 2D non uniform binning and wanting to plot fit variables use TH2Poly everything else uses TH2D with binning from config
1509  std::unique_ptr<TH2> _h2DVar;
1510  if(GetNDim(iSample) == 2 && !Binning->IsUniform(iSample) &&
1511  ProjectionVar_StrX == GetKinVarName(iSample, 0) && ProjectionVar_StrY == GetKinVarName(iSample, 1) ) {
1512  _h2DVar = std::unique_ptr<TH2>(static_cast<TH2*>(M3::Clone(GetMCHist(iSample)).release()));
1513  } else {
1514  std::vector<double> xBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_StrX);
1515  std::vector<double> yBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_StrY);
1516  _h2DVar = std::make_unique<TH2D>("", "", int(xBinEdges.size())-1, xBinEdges.data(), int(yBinEdges.size())-1, yBinEdges.data());
1517  }
1518  _h2DVar->SetDirectory(nullptr);
1519  _h2DVar->GetXaxis()->SetTitle(ProjectionVar_StrX.c_str());
1520  _h2DVar->GetYaxis()->SetTitle(ProjectionVar_StrY.c_str());
1521  _h2DVar->GetZaxis()->SetTitle("Events");
1522 
1523  bool IsSubEventHist = IsSubEventVarString(ProjectionVar_StrX) || IsSubEventVarString(ProjectionVar_StrY);
1524  if (IsSubEventHist) Fill2DSubEventHist(iSample, _h2DVar.get(), ProjectionVar_StrX, ProjectionVar_StrY, SubEventSelectionVec, WeightStyle);
1525  else {
1526  //DB Grab the associated enum with the argument string
1527  int ProjectionVar_IntX = ReturnKinematicParameterFromString(ProjectionVar_StrX);
1528  int ProjectionVar_IntY = ReturnKinematicParameterFromString(ProjectionVar_StrY);
1529 
1530  //DB Loop over all events
1531  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1532  const int EventSample = MCEvents[iEvent].NominalSample;
1533  if(EventSample != iSample) continue;
1534  if (IsEventSelected(EventSample, iEvent)) {
1535  double Weight = GetEventWeight(iEvent);
1536  if (WeightStyle == 1) {
1537  Weight = 1.;
1538  }
1539  double VarX = ReturnKinematicParameter(ProjectionVar_IntX, iEvent);
1540  double VarY = ReturnKinematicParameter(ProjectionVar_IntY, iEvent);
1541  _h2DVar->Fill(VarX,VarY,Weight);
1542  }
1543  }
1544  }
1545  //DB Reset the saved selection
1546  Selection = tmp_Selection;
1547 
1548  return _h2DVar;
1549 }
void Fill2DSubEventHist(const int iSample, TH2 *_h2DVar, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
const TH1 * GetMCHist(const int Sample) final
Get MC histogram.
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.

◆ Get2DVarHistByModeAndChannel()

std::unique_ptr< TH2 > SampleHandlerBase::Get2DVarHistByModeAndChannel ( const int  iSample,
const std::string &  ProjectionVar_StrX,
const std::string &  ProjectionVar_StrY,
const int  kModeToFill = -1,
const int  kChannelToFill = -1,
const int  WeightStyle = 0 
)
finalvirtual

Implements SampleHandlerInterface.

Definition at line 1793 of file SampleHandlerBase.cpp.

1795  {
1796 // ************************************************
1797  auto SelectionVec = BuildModeChannelSelection(iSample, kModeToFill, kChannelToFill);
1798  return Get2DVarHist(iSample, ProjectionVar_StrX, ProjectionVar_StrY, SelectionVec, WeightStyle);
1799 }
std::unique_ptr< TH2 > Get2DVarHist(const int iSample, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &EventSelectionVec={}, int WeightStyle=0, const std::vector< KinematicCut > &SubEventSelectionVec={}) final

◆ GetArrayForSample()

std::vector< double > SampleHandlerBase::GetArrayForSample ( const int  Sample,
std::vector< double > const &  array 
) const

Return a sub-array for a given sample.

Definition at line 2098 of file SampleHandlerBase.cpp.

2098  {
2099 // ***************************************************************************
2100  const int Start = Binning->GetSampleStartBin(Sample);
2101  const int End = Binning->GetSampleEndBin(Sample);
2102 
2103  return std::vector<double>(array.begin() + Start, array.begin() + End);
2104 }

◆ GetDataArray() [1/2]

auto SampleHandlerBase::GetDataArray ( ) const
inline

Return array storing data entries for every bin.

Definition at line 153 of file SampleHandlerBase.h.

153  {
154  return SampleHandler_data;
155  }

◆ GetDataArray() [2/2]

std::vector<double> SampleHandlerBase::GetDataArray ( const int  Sample) const
inline

Return array storing data entries for every bin.

Definition at line 168 of file SampleHandlerBase.h.

168  {
169  return GetArrayForSample(Sample, SampleHandler_data);
170  }
std::vector< double > GetArrayForSample(const int Sample, std::vector< double > const &array) const
Return a sub-array for a given sample.

◆ GetDataHist() [1/2]

const TH1 * SampleHandlerBase::GetDataHist ( const int  Sample)
finalvirtual

Get Data histogram.

Implements SampleHandlerInterface.

Definition at line 931 of file SampleHandlerBase.cpp.

931  {
932 // ************************************************
933  if(SampleDetails[Sample].DataHist == nullptr) {
934  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
935  throw MaCh3Exception(__FILE__, __LINE__);
936  }
937  return SampleDetails[Sample].DataHist;
938 }

◆ GetDataHist() [2/2]

const TH1 * SampleHandlerBase::GetDataHist ( const std::string &  Sample)

Definition at line 941 of file SampleHandlerBase.cpp.

941  {
942 // ************************************************
943  int Index = GetSampleIndex(Sample);
944  return GetDataHist(Index);
945 }
const TH1 * GetDataHist(const int Sample) final
Get Data histogram.
int GetSampleIndex(const std::string &SampleTitle) const
Get index of sample based on name.

◆ GetEventWeight()

M3::float_t SampleHandlerBase::GetEventWeight ( const int  iEntry)

Computes the total event weight for a given entry.

KS:

Warning
we have to here recalculate weight and cap because there is possibility weight wasn't calculated during FillArray because it didn't fulfil IsEventSelected

Definition at line 1176 of file SampleHandlerBase.cpp.

1176  {
1177 // ************************************************
1179 
1180  // Virtual by default does nothing, has to happen before CalcWeightTotal
1181  CalcWeightFunc(iEntry);
1182 
1183  const EventInfo* _restrict_ MCEvent = &MCEvents[iEntry];
1184  M3::float_t totalweight = CalcWeightTotal(MCEvent);
1185 
1186  //DB Catch negative total weights and skip any event with a negative weight. Previously we would set weight to zero and continue but that is inefficient
1187  if (totalweight <= 0.){
1188  totalweight = 0.;
1189  }
1190  return totalweight;
1191 }

◆ GetFinalPDGFromFileName()

NuPDG SampleHandlerBase::GetFinalPDGFromFileName ( const std::string &  FileName) const
inlineprotected

Retrieve the final neutrino PDG code associated with a given input file name.

Definition at line 415 of file SampleHandlerBase.h.

415 {return FileToFinalPDGMap.at(FileName);}
std::unordered_map< std::string, NuPDG > FileToFinalPDGMap

◆ GetFlavourName()

std::string SampleHandlerBase::GetFlavourName ( const int  iSample,
const int  iChannel 
) const
inlinefinalvirtual

Implements SampleHandlerInterface.

Definition at line 90 of file SampleHandlerBase.h.

90  {
91  if (iChannel < 0 || iChannel > GetNOscChannels(iSample)) {
92  MACH3LOG_ERROR("Invalid Channel Requested: {}", iChannel);
93  throw MaCh3Exception(__FILE__ , __LINE__);
94  }
95  return SampleDetails[iSample].OscChannels[iChannel].flavourName;
96  }

◆ GetInitPDGFromFileName()

NuPDG SampleHandlerBase::GetInitPDGFromFileName ( const std::string &  FileName) const
inlineprotected

Retrieve the initial neutrino PDG code associated with a given input file name.

Definition at line 413 of file SampleHandlerBase.h.

413 {return FileToInitPDGMap.at(FileName);}
std::unordered_map< std::string, NuPDG > FileToInitPDGMap

◆ GetKinVarName()

std::string SampleHandlerBase::GetKinVarName ( const int  iSample,
const int  Dimension 
) const
finalvirtual

Return Kinematic Variable name for specified sample and dimension for example "Reconstructed_Neutrino_Energy".

Parameters
iSampleSample index
DimensionDimension index

Implements SampleHandlerInterface.

Definition at line 2088 of file SampleHandlerBase.cpp.

2088  {
2089 // ***************************************************************************
2090  if(Dimension > GetNDim(iSample)) {
2091  MACH3LOG_ERROR("Asking for dimension {}, while sample: {} only has {}", Dimension, GetSampleTitle(iSample), GetNDim(iSample));
2092  throw MaCh3Exception(__FILE__, __LINE__);
2093  }
2094  return SampleDetails[iSample].VarStr[Dimension];
2095 }

◆ GetLikelihood()

double SampleHandlerBase::GetLikelihood ( ) const
overridevirtual

DB Multi-threaded GetLikelihood.

Implements SampleHandlerInterface.

Definition at line 1291 of file SampleHandlerBase.cpp.

1291  {
1292 // ************************************************
1293  double negLogL = 0.;
1294  #ifdef MULTITHREAD
1295  #pragma omp parallel for reduction(+:negLogL)
1296  #endif
1297  for (int idx = 0; idx < Binning->GetNBins(); ++idx)
1298  {
1299  double const &DataVal = SampleHandler_data[idx];
1300  double const &MCPred = SampleHandler_array[idx];
1301  double const &w2 = SampleHandler_array_w2[idx];
1302 
1303  //KS: Calculate likelihood using Barlow-Beeston Poisson or even IceCube
1304  negLogL += GetTestStatLLH(DataVal, MCPred, w2);
1305  }
1306  return negLogL;
1307 }
double GetTestStatLLH(const double data, const double mc, const double w2) const
Calculate test statistic for a single bin. Calculation depends on setting of fTestStatistic....

◆ GetMCArray() [1/2]

auto SampleHandlerBase::GetMCArray ( ) const
inline

Return array storing MC entries for every bin.

Definition at line 157 of file SampleHandlerBase.h.

157  {
158  return SampleHandler_array;
159  }

◆ GetMCArray() [2/2]

std::vector<double> SampleHandlerBase::GetMCArray ( const int  Sample) const
inline

Return array storing MC entries for every bin.

Definition at line 172 of file SampleHandlerBase.h.

172  {
173  return GetArrayForSample(Sample, SampleHandler_array);
174  }

◆ GetMCHist() [1/2]

const TH1 * SampleHandlerBase::GetMCHist ( const int  Sample)
finalvirtual

Get MC histogram.

Implements SampleHandlerInterface.

Definition at line 913 of file SampleHandlerBase.cpp.

913  {
914 // ************************************************
915  FillHist(Sample, SampleDetails[Sample].MCHist, SampleHandler_array);
916  if(SampleDetails[Sample].MCHist == nullptr) {
917  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
918  throw MaCh3Exception(__FILE__, __LINE__);
919  }
920  return SampleDetails[Sample].MCHist;
921 }

◆ GetMCHist() [2/2]

const TH1 * SampleHandlerBase::GetMCHist ( const std::string &  Sample)

Definition at line 924 of file SampleHandlerBase.cpp.

924  {
925 // ************************************************
926  const int Index = GetSampleIndex(Sample);
927  return GetMCHist(Index);
928 }

◆ GetModeHist1D()

std::unique_ptr<TH1> SampleHandlerBase::GetModeHist1D ( const int  iSample,
int  s,
int  m,
int  style = 0 
)
inline

Definition at line 118 of file SampleHandlerBase.h.

118  {
119  return Get1DVarHistByModeAndChannel(iSample, GetKinVarName(iSample, 0), m, s, style);
120  }
std::unique_ptr< TH1 > Get1DVarHistByModeAndChannel(const int iSample, const std::string &ProjectionVar_Str, const int kModeToFill=-1, const int kChannelToFill=-1, const int WeightStyle=0) final

◆ GetModeHist2D()

std::unique_ptr<TH2> SampleHandlerBase::GetModeHist2D ( const int  iSample,
int  s,
int  m,
int  style = 0 
)
inline

Definition at line 121 of file SampleHandlerBase.h.

121  {
122  return Get2DVarHistByModeAndChannel(iSample, GetKinVarName(iSample, 0), GetKinVarName(iSample, 1), m, s, style);
123  }
std::unique_ptr< TH2 > Get2DVarHistByModeAndChannel(const int iSample, const std::string &ProjectionVar_StrX, const std::string &ProjectionVar_StrY, const int kModeToFill=-1, const int kChannelToFill=-1, const int WeightStyle=0) final

◆ GetName()

std::string SampleHandlerBase::GetName ( ) const
finalvirtual

Get name for Sample Handler.

Implements SampleHandlerInterface.

Definition at line 1163 of file SampleHandlerBase.cpp.

1163  {
1164 // ************************************************
1165  //ETA - extra safety to make sure SampleHandlerName is actually set
1166  // probably unnecessary due to the requirement for it to be in the yaml config
1167  if(SampleHandlerName.length() == 0) {
1168  MACH3LOG_ERROR("No sample name provided");
1169  MACH3LOG_ERROR("Please provide a SampleHandlerName in your configuration file: {}", SampleManager->GetFileName());
1170  throw MaCh3Exception(__FILE__, __LINE__);
1171  }
1172  return SampleHandlerName;
1173 }

◆ GetNDim()

int SampleHandlerBase::GetNDim ( const int  Sample) const
inlinefinalvirtual

DB Get what dimensionality binning for given sample has.

Parameters
SampleNumber of sample

Implements SampleHandlerInterface.

Definition at line 34 of file SampleHandlerBase.h.

34 { return SampleDetails[Sample].nDimensions; }

◆ GetNOscChannels()

int SampleHandlerBase::GetNOscChannels ( const int  iSample) const
inlinefinalvirtual

Get number of oscillation channels for a single sample.

Implements SampleHandlerInterface.

Definition at line 88 of file SampleHandlerBase.h.

88 {return static_cast<int>(SampleDetails[iSample].OscChannels.size());};

◆ GetNuOscillatorPointers()

const M3::float_t * SampleHandlerBase::GetNuOscillatorPointers ( const int  iEvent) const

Definition at line 1123 of file SampleHandlerBase.cpp.

1123  {
1124 // ************************************************
1125  const M3::float_t* osc_w_pointer = &M3::Unity;
1126  if (MCEvents[iEvent].isNC) {
1127  if (MCEvents[iEvent].nupdg != MCEvents[iEvent].nupdgUnosc) {
1128  osc_w_pointer = &M3::Zero;
1129  } else {
1130  osc_w_pointer = &M3::Unity;
1131  }
1132  } else {
1133  int InitFlav = M3::_BAD_INT_;
1134  int FinalFlav = M3::_BAD_INT_;
1135 
1136  InitFlav = M3::Utils::PDGToNuOscillatorFlavour(MCEvents[iEvent].nupdgUnosc);
1137  FinalFlav = M3::Utils::PDGToNuOscillatorFlavour(MCEvents[iEvent].nupdg);
1138 
1139  if (InitFlav == M3::_BAD_INT_ || FinalFlav == M3::_BAD_INT_) {
1140  MACH3LOG_ERROR("Something has gone wrong in the mapping between MCEvents.nutype and the enum used within NuOscillator");
1141  MACH3LOG_ERROR("MCEvents.nupdgUnosc: {}", MCEvents[iEvent].nupdgUnosc);
1142  MACH3LOG_ERROR("InitFlav: {}", InitFlav);
1143  MACH3LOG_ERROR("MCEvents.nupdg: {}", MCEvents[iEvent].nupdg);
1144  MACH3LOG_ERROR("FinalFlav: {}", FinalFlav);
1145  throw MaCh3Exception(__FILE__, __LINE__);
1146  }
1147  const int Sample = MCEvents[iEvent].NominalSample;
1148 
1149  const int OscIndex = GetOscChannel(SampleDetails[Sample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1150  //Can only happen if truecz has been initialised within the experiment specific code
1151  if (MCEvents[iEvent].coszenith_true != M3::_BAD_DOUBLE_) {
1152  //Atmospherics
1153  osc_w_pointer = Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(MCEvents[iEvent].enu_true), FLOAT_T(MCEvents[iEvent].coszenith_true));
1154  } else {
1155  //Beam
1156  osc_w_pointer = Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(MCEvents[iEvent].enu_true));
1157  }
1158  } // end if NC
1159  return osc_w_pointer;
1160 }
int GetOscChannel(const std::vector< OscChannelInfo > &OscChannel, const int InitFlav, const int FinalFlav)
KS: Get Osc Channel Index based on initial and final PDG codes.
int PDGToNuOscillatorFlavour(const int NuPdg)
Convert from PDG flavour to NuOscillator type beware that in the case of anti-neutrinos the NuOscilla...
constexpr static const float_t Unity
Definition: Core.h:64
constexpr static const float_t Zero
Definition: Core.h:71
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Definition: Core.h:55

◆ GetPointerToKinematicParameter() [1/2]

virtual const double* SampleHandlerBase::GetPointerToKinematicParameter ( const int  KinematicVariable,
const int  iEvent 
) const
protectedpure virtual

Implemented in PySampleHandlerBase.

◆ GetPointerToKinematicParameter() [2/2]

const double* SampleHandlerBase::GetPointerToKinematicParameter ( const std::string &  KinematicParameter,
int  iEvent 
) const
inlineprotected

Definition at line 313 of file SampleHandlerBase.h.

313  {
314  return GetPointerToKinematicParameter(ReturnKinematicParameterFromString(KinematicParameter), iEvent);
315  }

◆ GetPointerToOscChannel()

const double * SampleHandlerBase::GetPointerToOscChannel ( const int  iEvent) const
protected

Get pointer to oscillation channel associated with given event. Osc channel is const.

Definition at line 2027 of file SampleHandlerBase.cpp.

2027  {
2028 // ************************************************
2029  auto& OscillationChannels = SampleDetails[MCEvents[iEvent].NominalSample].OscChannels;
2030  const int Channel = GetOscChannel(OscillationChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
2031  return &(OscillationChannels[Channel].ChannelIndex);
2032 }

◆ GetSampleIndex()

int SampleHandlerBase::GetSampleIndex ( const std::string &  SampleTitle) const

Get index of sample based on name.

Parameters
SampleTitleThe title of the sample to search for.

Definition at line 883 of file SampleHandlerBase.cpp.

883  {
884 // ************************************************
885  for (M3::int_t iSample = 0; iSample < nSamples; ++iSample) {
886  if (SampleTitle == GetSampleTitle(iSample)) {
887  return iSample;
888  }
889  }
890  MACH3LOG_ERROR("Sample name not found: {}", SampleTitle);
891  throw MaCh3Exception(__FILE__, __LINE__);
892 }
int int_t
Definition: Core.h:38

◆ GetSampleLikelihood()

double SampleHandlerBase::GetSampleLikelihood ( const int  isample) const
overridevirtual

Get likelihood for single sample.

Implements SampleHandlerInterface.

Definition at line 1269 of file SampleHandlerBase.cpp.

1269  {
1270 // ************************************************
1271  const int Start = Binning->GetSampleStartBin(isample);
1272  const int End = Binning->GetSampleEndBin(isample);
1273 
1274  double negLogL = 0.;
1275  #ifdef MULTITHREAD
1276  #pragma omp parallel for reduction(+:negLogL)
1277  #endif
1278  for (int idx = Start; idx < End; ++idx)
1279  {
1280  double const &DataVal = SampleHandler_data[idx];
1281  double const &MCPred = SampleHandler_array[idx];
1282  double const &w2 = SampleHandler_array_w2[idx];
1283 
1284  //KS: Calculate likelihood using Barlow-Beeston Poisson or even IceCube
1285  negLogL += GetTestStatLLH(DataVal, MCPred, w2);
1286  }
1287  return negLogL;
1288 }

◆ GetSampleTitle()

std::string SampleHandlerBase::GetSampleTitle ( const int  Sample) const
inlinefinalvirtual

Get fancy title for specified samples.

Implements SampleHandlerInterface.

Definition at line 38 of file SampleHandlerBase.h.

38 {return SampleDetails[Sample].SampleTitle;}

◆ GetSplineBins()

std::vector< std::vector< int > > SampleHandlerBase::GetSplineBins ( int  Event,
BinnedSplineHandler BinnedSpline,
bool &  ThrowCrititcal 
) const
protected

Retrieve the spline bin indices associated with a given event.

Warning
ThrowCrititcal argument will be eventually removed

Definition at line 1194 of file SampleHandlerBase.cpp.

1194  {
1195 // ************************************************
1196  const int SampleIndex = MCEvents[Event].NominalSample;
1197  const auto SampleTitle = GetSampleTitle(SampleIndex);
1198  bool NoOscChannels = false;
1199  if(Oscillator == nullptr && GetNOscChannels(SampleIndex) == 1) {
1200  MACH3LOG_DEBUG("Assuming there are no osc channels in {}", __func__);
1201  NoOscChannels = true;
1202  }
1203  const int OscIndex = NoOscChannels ? 0 : GetOscChannel(SampleDetails[SampleIndex].OscChannels,
1204  MCEvents[Event].nupdgUnosc, MCEvents[Event].nupdg);
1205  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", Event)));
1206  const double Etrue = MCEvents[Event].enu_true;
1207  std::vector< std::vector<int> > EventSplines;
1208  switch(GetNDim(SampleIndex)) {
1209  case 1:
1210  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(MCEvents[Event].KinVar[0]), 0.);
1211  break;
1212  case 2:
1213  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(MCEvents[Event].KinVar[0]), *(MCEvents[Event].KinVar[1]));
1214  break;
1215  default:
1216  if(ThrowCrititcal) {
1217  MACH3LOG_CRITICAL("MaCh3 doesn't support binned splines for more than 2D while you use {}", GetNDim(SampleIndex));
1218  MACH3LOG_CRITICAL("Will use 2D like approach");
1219  ThrowCrititcal = false;
1220  }
1221  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(MCEvents[Event].KinVar[0]), *(MCEvents[Event].KinVar[1]));
1222  break;
1223  }
1224  return EventSplines;
1225 }
std::vector< std::vector< int > > GetEventSplines(const std::string &SampleTitle, int iOscChan, int EventMode, double Var1Val, double Var2Val, double Var3Val)
Return the splines which affect a given event.

◆ GetW2Array() [1/2]

auto SampleHandlerBase::GetW2Array ( ) const
inline

Return array storing W2 entries for every bin.

Definition at line 161 of file SampleHandlerBase.h.

161  {
162  return SampleHandler_array_w2;
163  }

◆ GetW2Array() [2/2]

std::vector<double> SampleHandlerBase::GetW2Array ( const int  Sample) const
inline

Return array storing W2 entries for single sample.

Definition at line 176 of file SampleHandlerBase.h.

176  {
178  }

◆ GetW2Hist() [1/2]

const TH1 * SampleHandlerBase::GetW2Hist ( const int  Sample)
finalvirtual

Get W2 histogram.

Implements SampleHandlerInterface.

Definition at line 895 of file SampleHandlerBase.cpp.

895  {
896 // ************************************************
897  FillHist(Sample, SampleDetails[Sample].W2Hist, SampleHandler_array_w2);
898  if(SampleDetails[Sample].W2Hist == nullptr) {
899  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
900  throw MaCh3Exception(__FILE__, __LINE__);
901  }
902  return SampleDetails[Sample].W2Hist;
903 }

◆ GetW2Hist() [2/2]

const TH1 * SampleHandlerBase::GetW2Hist ( const std::string &  Sample)

Definition at line 906 of file SampleHandlerBase.cpp.

906  {
907 // ************************************************
908  const int Index = GetSampleIndex(Sample);
909  return GetW2Hist(Index);
910 }
const TH1 * GetW2Hist(const int Sample) final
Get W2 histogram.

◆ Init()

virtual void SampleHandlerBase::Init ( )
protectedpure virtual

Initialise any variables that your experiment specific SampleHandler needs.

Implemented in PySampleHandlerBase.

◆ Initialise()

void SampleHandlerBase::Initialise ( )
protected

Function which does a lot of the lifting regarding the workflow in creating different MC objects.

Definition at line 170 of file SampleHandlerBase.cpp.

170  {
171 // ************************************************
172  TStopwatch clock;
173  clock.Start();
174 
175  //First grab all the information from your sample config via your manager
176  ReadConfig();
177 
178  //Now initialise all the variables you will need
179  Init();
180 
182  MCEvents.resize(nEvents);
183  SetupMC();
184 
185  MACH3LOG_INFO("=============================================");
186  MACH3LOG_INFO("Total number of events is: {}", GetNEvents());
188  MACH3LOG_INFO("Setting up Sample Binning..");
189  SetBinning();
190  MACH3LOG_INFO("Setting up Splines..");
191  SetupSplines();
192  MACH3LOG_INFO("Setting up Normalisation Pointers..");
194  MACH3LOG_INFO("Setting up Functional Pointers..");
196  MACH3LOG_INFO("Setting up Additional Weight Pointers..");
198  MACH3LOG_INFO("Setting up Kinematic Map..");
200  clock.Stop();
201  MACH3LOG_INFO("Finished loading MC for {}, it took {:.2f}s to finish", GetName(), clock.RealTime());
202  MACH3LOG_INFO("Initialising Data");
204  MACH3LOG_INFO("=======================================================");
205 }
void SetBinning()
set the binning for 2D sample used for the likelihood calculation
void SetupNormParameters()
Setup the norm parameters by assigning each event with bin.
void ReadConfig()
Load information about sample handler and corresponding samples from config file.
void SetupKinematicMap()
Ensure Kinematic Map is setup and make sure it is initialised correctly.
virtual void Init()=0
Initialise any variables that your experiment specific SampleHandler needs.
virtual void SetupMC()=0
Function which translates experiment struct into core struct.
virtual void InititialiseData()=0
Function responsible for loading data from file or loading from file.
virtual void SetupSplines()=0
initialise your splineXX object and then use InitialiseSplineObject to conviently setup everything up
virtual void AddAdditionalWeightPointers()=0
DB Function to determine which weights apply to which types of samples.
virtual int SetupExperimentMC()=0
Experiment specific setup, returns the number of events which were loaded.
virtual void SetupFunctionalParameters()
ETA - a function to setup and pass values to functional parameters where you need to pass a value to ...
std::string GetName() const final
Get name for Sample Handler.
void SetupOscParameters()
Setup the osc parameters.
unsigned int nEvents
Number of MC events are there.

◆ InitialiseNuOscillatorObjects()

void SampleHandlerBase::InitialiseNuOscillatorObjects ( )
protected

including Dan's magic NuOscillator

Definition at line 1040 of file SampleHandlerBase.cpp.

1040  {
1041 // ************************************************
1042  auto NuOscillatorConfigFile = Get<std::string>(SampleManager->raw()["NuOsc"]["NuOscConfigFile"], __FILE__ , __LINE__);
1043  auto EqualBinningPerOscChannel = Get<bool>(SampleManager->raw()["NuOsc"]["EqualBinningPerOscChannel"], __FILE__ , __LINE__);
1044 
1045  // TN override the sample setting if not using binned oscillation
1046  if (EqualBinningPerOscChannel) {
1047  if (YAML::LoadFile(NuOscillatorConfigFile)["General"]["CalculationType"].as<std::string>() == "Unbinned") {
1048  MACH3LOG_WARN("Tried using EqualBinningPerOscChannel while using Unbinned oscillation calculation, changing EqualBinningPerOscChannel to false");
1049  EqualBinningPerOscChannel = false;
1050  }
1051  }
1052  std::vector<const M3::float_t*> OscParams = ParHandler->GetOscParsFromSampleName(SampleHandlerName);
1053  if (OscParams.empty()) {
1054  MACH3LOG_ERROR("OscParams is empty for sample '{}'.", GetName());
1055  MACH3LOG_ERROR("This likely indicates an error in your oscillation YAML configuration.");
1056  throw MaCh3Exception(__FILE__, __LINE__);
1057  }
1058  Oscillator = std::make_shared<OscillationHandler>(NuOscillatorConfigFile, EqualBinningPerOscChannel, OscParams, GetNOscChannels(0));
1059  // Add samples only if we don't use same binning
1060  if(!EqualBinningPerOscChannel) {
1061  // KS: Start from 1 because sample 0 already added
1062  for(int iSample = 1; iSample < GetNSamples(); iSample++) {
1063  Oscillator->AddSample(NuOscillatorConfigFile, GetNOscChannels(iSample));
1064  }
1065  for(int iSample = 0; iSample < GetNSamples(); iSample++) {
1066  for(int iChannel = 0; iChannel < GetNOscChannels(iSample); iChannel++) {
1067  std::vector<M3::float_t> EnergyArray;
1068  std::vector<M3::float_t> CosineZArray;
1069 
1070 #pragma GCC diagnostic push
1071 #pragma GCC diagnostic ignored "-Wuseless-cast"
1072  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1073  if(MCEvents[iEvent].NominalSample != iSample) continue;
1074  // KS: This is bit weird but we basically loop over all events and push to vector only these which are part of a given OscChannel
1075  const int Channel = GetOscChannel(SampleDetails[MCEvents[iEvent].NominalSample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1076  //DB Remove NC events from the arrays which are handed to the NuOscillator objects
1077  if (!MCEvents[iEvent].isNC && Channel == iChannel) {
1078  EnergyArray.push_back(M3::float_t(MCEvents[iEvent].enu_true));
1079  }
1080  }
1081  std::sort(EnergyArray.begin(),EnergyArray.end());
1082 
1083  //============================================================================
1084  //DB Atmospheric only part, can only happen if truecz has been initialised within the experiment specific code
1085  if (MCEvents[0].coszenith_true != M3::_BAD_DOUBLE_) {
1086  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1087  if(MCEvents[iEvent].NominalSample != iSample) continue;
1088  // KS: This is bit weird but we basically loop over all events and push to vector only these which are part of a given OscChannel
1089  const int Channel = GetOscChannel(SampleDetails[MCEvents[iEvent].NominalSample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1090  //DB Remove NC events from the arrays which are handed to the NuOscillator objects
1091  if (!MCEvents[iEvent].isNC && Channel == iChannel) {
1092  CosineZArray.push_back(M3::float_t(MCEvents[iEvent].coszenith_true));
1093  }
1094  }
1095  std::sort(CosineZArray.begin(),CosineZArray.end());
1096  }
1097 #pragma GCC diagnostic pop
1098  Oscillator->SetOscillatorBinning(iSample, iChannel, EnergyArray, CosineZArray);
1099  } // end loop over channels
1100  } // end loop over samples
1101  }
1102 }
std::vector< const M3::float_t * > GetOscParsFromSampleName(const std::string &SampleName)
Get pointers to Osc params from Sample name.
virtual M3::int_t GetNSamples()

◆ InitialiseSplineObject()

void SampleHandlerBase::InitialiseSplineObject ( )
protected

Definition at line 1356 of file SampleHandlerBase.cpp.

1356  {
1357 // ************************************************
1358  if(auto BinnedSplines = dynamic_cast<BinnedSplineHandler*>(SplineHandler.get())) {
1359  bool LoadSplineFile = GetFromManager<bool>(SampleManager->raw()["InputFiles"]["LoadSplineFile"], false, __FILE__, __LINE__);
1360  bool PrepSplineFile = GetFromManager<bool>(SampleManager->raw()["InputFiles"]["PrepSplineFile"], false, __FILE__, __LINE__);
1361  auto SplineFileName = GetFromManager<std::string>(SampleManager->raw()["InputFiles"]["SplineFileName"],
1362  (SampleHandlerName + "_SplineFile.root"), __FILE__, __LINE__);
1363  if(!LoadSplineFile) {
1364  for(int iSample = 0; iSample < GetNSamples(); iSample++) {
1365  std::vector<std::string> spline_filepaths = SampleDetails[iSample].spline_files;
1366 
1367  //Keep a track of the spline variables
1368  std::vector<std::string> SplineVarNames = {"TrueNeutrinoEnergy"};
1369  if (GetNDim(iSample) == 1) {
1370  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1371  } else if (GetNDim(iSample) == 2) {
1372  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1373  SplineVarNames.push_back(GetKinVarName(iSample, 1));
1374  } else {
1375  MACH3LOG_CRITICAL("{} Not implemented for dimension {}, will use 2D", __func__, GetNDim(iSample));
1376  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1377  SplineVarNames.push_back(GetKinVarName(iSample, 1));
1378  }
1379  BinnedSplines->AddSample(SampleHandlerName, GetSampleTitle(iSample), spline_filepaths, SplineVarNames);
1380  }
1381  BinnedSplines->CountNumberOfLoadedSplines(false, 1);
1382  BinnedSplines->TransferToMonolith();
1383  if(PrepSplineFile) BinnedSplines->PrepareSplineFile(SplineFileName);
1384  } else {
1385  // KS: Skip default spline loading and use flattened spline format allowing to read stuff much faster
1386  BinnedSplines->LoadSplineFile(SplineFileName);
1387  }
1388  MACH3LOG_INFO("--------------------------------");
1389  MACH3LOG_INFO("Setup Far Detector splines");
1390 
1392 
1393  BinnedSplines->cleanUpMemory();
1394  } else if (auto UnbinnedSpline = dynamic_cast<UnbinnedSplineHandler*>(SplineHandler.get())) {
1395  (void) UnbinnedSpline;
1397  } else {
1398  MACH3LOG_ERROR("Unsupported spline type encountered.");
1399  throw MaCh3Exception(__FILE__, __LINE__);
1400  }
1401 }
Bin-by-bin class calculating response for spline parameters.
void SetSplinePointers()
Set pointers for each event to appropriate weights, for unbinned based on event number while for binn...
std::unique_ptr< SplineBase > SplineHandler
Contains all your splines (binned or unbinned) and handles the setup and the returning of weights fro...
Even-by-event class calculating response for spline parameters. It is possible to use GPU acceleratio...

◆ InititialiseData()

virtual void SampleHandlerBase::InititialiseData ( )
protectedpure virtual

Function responsible for loading data from file or loading from file.

Implemented in PySampleHandlerBase.

◆ IsEventSelected()

bool SampleHandlerBase::IsEventSelected ( const int  iSample,
const int  iEvent 
)
protected

DB Function which determines if an event is selected based on KinematicCut.

Definition at line 284 of file SampleHandlerBase.cpp.

284  {
285 // ************************************************
286  const auto& SampleSelection = Selection[iSample];
287  const int SelectionSize = static_cast<int>(SampleSelection.size());
288  for (int iSelection = 0; iSelection < SelectionSize; ++iSelection) {
289  const auto& Cut = SampleSelection[iSelection];
290  const double Val = ReturnKinematicParameter(Cut.ParamToCutOnIt, iEvent);
291  if ((Val < Cut.LowerBound) || (Val >= Cut.UpperBound)) {
292  return false;
293  }
294  }
295  //DB To avoid unnecessary checks, now return false rather than setting bool to true and continuing to check
296  return true;
297 }

◆ IsSubEventSelected()

bool SampleHandlerBase::IsSubEventSelected ( const std::vector< KinematicCut > &  SubEventCuts,
const int  iEvent,
unsigned const int  iSubEvent,
size_t  nsubevents 
)
protected

JM Function which determines if a subevent is selected.

Definition at line 300 of file SampleHandlerBase.cpp.

300  {
301  for (unsigned int iSelection=0;iSelection < SubEventCuts.size() ;iSelection++) {
302  std::vector<double> Vec = ReturnKinematicVector(SubEventCuts[iSelection].ParamToCutOnIt, iEvent);
303  if (nsubevents != Vec.size()) {
304  MACH3LOG_ERROR("Cannot apply kinematic cut on {} as it is of different size to plotting variable");
305  throw MaCh3Exception(__FILE__, __LINE__);
306  }
307  const double Val = Vec[iSubEvent];
308  if ((Val < SubEventCuts[iSelection].LowerBound) || (Val >= SubEventCuts[iSelection].UpperBound)) {
309  return false;
310  }
311  }
312  //DB To avoid unnecessary checks, now return false rather than setting bool to true and continuing to check
313  return true;
314 }

◆ IsSubEventVarString()

bool SampleHandlerBase::IsSubEventVarString ( const std::string &  VarStr) const

JM: Check if a kinematic parameter string corresponds to a subevent-level variable.

Definition at line 1718 of file SampleHandlerBase.cpp.

1718  {
1719 // ************************************************
1720  if (KinematicVectors == nullptr) return false;
1721 
1722  if (KinematicVectors->count(VarStr)) {
1723  if (!KinematicParameters->count(VarStr)) return true;
1724  else {
1725  MACH3LOG_ERROR("Attempted to plot kinematic variable {}, but it appears in both KinematicVectors and KinematicParameters", VarStr);
1726  throw MaCh3Exception(__FILE__,__LINE__);
1727  }
1728  }
1729  return false;
1730 }

◆ LoadSingleSample()

void SampleHandlerBase::LoadSingleSample ( const int  iSample,
const YAML::Node &  Settings 
)
protected

Initialise single sample from config file.

Add new sample

Definition at line 108 of file SampleHandlerBase.cpp.

108  {
109 // ************************************************
110  SampleInfo SingleSample;
111  //SampleTitle has to be provided in the sample yaml otherwise this will throw an exception
112  SingleSample.SampleTitle = Get<std::string>(SampleSettings["SampleTitle"], __FILE__ , __LINE__);
113 
114  Binning->SetupSampleBinning(SampleSettings["Binning"], SingleSample);
115 
116  auto MCFilePrefix = Get<std::string>(SampleSettings["InputFiles"]["mtupleprefix"], __FILE__, __LINE__);
117  auto MCFileSuffix = Get<std::string>(SampleSettings["InputFiles"]["mtuplesuffix"], __FILE__, __LINE__);
118  auto SplinePrefix = Get<std::string>(SampleSettings["InputFiles"]["splineprefix"], __FILE__, __LINE__);
119  auto SplineSuffix = Get<std::string>(SampleSettings["InputFiles"]["splinesuffix"], __FILE__, __LINE__);
120 
121  int NChannels = static_cast<M3::int_t>(SampleSettings["OscChannels"].size());
122  SingleSample.OscChannels.reserve(NChannels);
123 
124  int OscChannelCounter = 0;
125  for (auto const &osc_channel : SampleSettings["OscChannels"]) {
126  OscChannelInfo OscInfo;
127  OscInfo.flavourName = Get<std::string>(osc_channel["Name"], __FILE__ , __LINE__);
128  OscInfo.flavourName_Latex = Get<std::string>(osc_channel["LatexName"], __FILE__ , __LINE__);
129  OscInfo.InitPDG = GetFromManager(osc_channel["nutype"], 0, __FILE__,__LINE__);
130  OscInfo.FinalPDG = GetFromManager(osc_channel["oscnutype"], 0, __FILE__,__LINE__);
131  OscInfo.ChannelIndex = OscChannelCounter;
132 
133  for (const auto& Existing : SingleSample.OscChannels) {
134  if (Existing.InitPDG == OscInfo.InitPDG && Existing.FinalPDG == OscInfo.FinalPDG) {
135  MACH3LOG_ERROR("Duplicate oscillation channel detected! InitPDG = {}, FinalPDG = {}"
136  "already defined in channel {} for sample {}",
137  OscInfo.InitPDG, OscInfo.FinalPDG, Existing.ChannelIndex, SingleSample.SampleTitle);
138  throw MaCh3Exception(__FILE__, __LINE__);
139  }
140  }
141  auto MCFileNames = Get<std::vector<std::string>>(osc_channel["mtuplefile"], __FILE__ , __LINE__);
142  for(size_t iFile = 0; iFile < MCFileNames.size(); iFile++){
143  std::string FileName = MCFilePrefix + MCFileNames[iFile] + MCFileSuffix;
144  MCFileNames[iFile] = FileName;
145  FileToInitPDGMap[FileName] = NuPDG(OscInfo.InitPDG);
146  FileToFinalPDGMap[FileName] = NuPDG(OscInfo.FinalPDG);
147  }
148 
149  SingleSample.OscChannels.push_back(std::move(OscInfo));
150  SingleSample.mc_files.push_back(MCFileNames);
151  SingleSample.spline_files.push_back(SplinePrefix+osc_channel["splinefile"].as<std::string>()+SplineSuffix);
152  OscChannelCounter++;
153  }
154  //Now grab the selection cuts from the manager
155  for ( auto const &SelectionCuts : SampleSettings["SelectionCuts"]) {
156  auto TempBoundsVec = GetBounds(SelectionCuts["Bounds"]);
157  KinematicCut CutObj;
158  CutObj.LowerBound = TempBoundsVec[0];
159  CutObj.UpperBound = TempBoundsVec[1];
160  CutObj.ParamToCutOnIt = ReturnKinematicParameterFromString(SelectionCuts["KinematicStr"].as<std::string>());
161  MACH3LOG_INFO("Adding cut on {} with bounds {} to {}", SelectionCuts["KinematicStr"].as<std::string>(), TempBoundsVec[0], TempBoundsVec[1]);
162  StoredSelection[iSample].emplace_back(CutObj);
163  }
166  SampleDetails[iSample] = std::move(SingleSample);
167 }
NuPDG
Enum to track the incoming neutrino species.
Definition: SampleStructs.h:94
Type GetFromManager(const YAML::Node &node, const Type defval, const std::string File="", const int Line=1)
Get content of config file if node is not found take default value specified.
Definition: YamlHelper.h:329
#define GetBounds(filename)
Definition: YamlHelper.h:590
KS: Store info about used osc channels.
int InitPDG
PDG of initial flavour.
double ChannelIndex
In case experiment specific would like to have pointer to channel after using GetOscChannel,...
int FinalPDG
PDG of oscillated/final flavour.
std::string flavourName
Name of osc channel.
std::string flavourName_Latex
Fancy channel name (e.g., LaTeX formatted)
KS: Store info about MC sample.
std::vector< OscChannelInfo > OscChannels
Stores info about oscillation channel for a single sample.
std::string SampleTitle
the name of this sample e.g."muon-like"
std::vector< std::string > spline_files
names of spline files associated associated with this object
std::vector< std::vector< std::string > > mc_files
names of mc files associated associated with this object

◆ PassesSelection()

template<typename ParT >
bool SampleHandlerBase::PassesSelection ( const ParT &  Par,
std::size_t  iEvent 
)
protected

Definition at line 2108 of file SampleHandlerBase.cpp.

2108  {
2109 // ***************************************************************************
2110  bool IsSelected = true;
2111  if (Par.hasKinBounds) {
2112  const auto& kinVars = Par.KinematicVarStr;
2113  const auto& selection = Par.Selection;
2114 
2115  for (std::size_t iKinPar = 0; iKinPar < kinVars.size(); ++iKinPar) {
2116  const double kinVal = ReturnKinematicParameter(kinVars[iKinPar], static_cast<int>(iEvent));
2117 
2118  bool passedAnyBound = false;
2119  const auto& boundsList = selection[iKinPar];
2120 
2121  for (const auto& bounds : boundsList) {
2122  if (kinVal > bounds[0] && kinVal <= bounds[1]) {
2123  passedAnyBound = true;
2124  break;
2125  }
2126  }
2127 
2128  if (!passedAnyBound) {
2129  MACH3LOG_TRACE("Event {}, missed kinematic check ({}) for dial {}",
2130  iEvent, kinVars[iKinPar], Par.name);
2131  IsSelected = false;
2132  break;
2133  }
2134  }
2135  }
2136  return IsSelected;
2137 }

◆ PrepFunctionalParameters()

virtual void SampleHandlerBase::PrepFunctionalParameters ( )
inlineprotectedvirtual

Update the functional parameter values to the latest proposed values. Needs to be called before every new reweight so is called in fillArray.

Definition at line 246 of file SampleHandlerBase.h.

246 {};

◆ PrintIntegral()

void SampleHandlerBase::PrintIntegral ( const int  iSample,
const TString &  OutputName = "/dev/null",
const int  WeightStyle = 0,
const TString &  OutputCSVName = "/dev/null" 
)

Computes and prints the integral breakdown of all modes and oscillation channels for a given sample.

Definition at line 1802 of file SampleHandlerBase.cpp.

1802  {
1803 // ************************************************
1804  constexpr int space = 14;
1805 
1806  bool printToFile=false;
1807  if (OutputFileName.CompareTo("/dev/null")) {printToFile = true;}
1808 
1809  bool printToCSV=false;
1810  if(OutputCSVFileName.CompareTo("/dev/null")) printToCSV=true;
1811 
1812  std::ofstream outfile;
1813  if (printToFile) {
1814  outfile.open(OutputFileName.Data(), std::ios_base::app);
1815  outfile.precision(7);
1816  }
1817 
1818  std::ofstream outcsv;
1819  if(printToCSV){
1820  outcsv.open(OutputCSVFileName, std::ios_base::app); // Appened to CSV
1821  outcsv.precision(7);
1822  }
1823 
1824  double PDFIntegral = 0.;
1825 
1826  std::vector< std::vector< std::unique_ptr<TH1> > > IntegralList;
1827  IntegralList.resize(Modes->GetNModes());
1828 
1829  std::vector<double> ChannelIntegral;
1830  ChannelIntegral.resize(GetNOscChannels(iSample));
1831  for (unsigned int i=0;i<ChannelIntegral.size();i++) {ChannelIntegral[i] = 0.;}
1832 
1833  for (int i=0;i<Modes->GetNModes();i++) {
1834  if (GetNDim(iSample) == 1) {
1835  IntegralList[i] = ReturnHistsBySelection1D(iSample, GetKinVarName(iSample, 0),1,i,WeightStyle);
1836  } else {
1837  IntegralList[i] = CastVector<TH2, TH1>(ReturnHistsBySelection2D(iSample, GetKinVarName(iSample, 0), GetKinVarName(iSample, 1),1,i,WeightStyle));
1838  }
1839  }
1840 
1841  MACH3LOG_INFO("-------------------------------------------------");
1842 
1843  if (printToFile) {
1844  outfile << "\\begin{table}[ht]" << std::endl;
1845  outfile << "\\begin{center}" << std::endl;
1846  outfile << "\\caption{Integral breakdown for sample: " << GetSampleTitle(iSample) << "}" << std::endl;
1847  outfile << "\\label{" << GetSampleTitle(iSample) << "-EventRate}" << std::endl;
1848 
1849  TString nColumns;
1850  for (int i=0;i<GetNOscChannels(iSample);i++) {nColumns+="|c";}
1851  nColumns += "|c|";
1852  outfile << "\\begin{tabular}{|l" << nColumns.Data() << "}" << std::endl;
1853  outfile << "\\hline" << std::endl;
1854  }
1855 
1856  if(printToCSV){
1857  // HW Probably a better way but oh well, here I go making MaCh3 messy again
1858  outcsv<<"Integral Breakdown for sample :"<<GetSampleTitle(iSample)<<"\n";
1859  }
1860 
1861  MACH3LOG_INFO("Integral breakdown for sample: {}", GetSampleTitle(iSample));
1862  MACH3LOG_INFO("");
1863 
1864  if (printToFile) {outfile << std::setw(space) << "Mode:";}
1865  if(printToCSV) {outcsv<<"Mode,";}
1866 
1867  std::string table_headings = fmt::format("| {:<8} |", "Mode");
1868  std::string table_footline = "------------"; //Scalable table horizontal line
1869  for (int i = 0;i < GetNOscChannels(iSample); i++) {
1870  table_headings += fmt::format(" {:<17} |", GetFlavourName(iSample, i));
1871  table_footline += "--------------------";
1872  if (printToFile) {outfile << "&" << std::setw(space) << SampleDetails[iSample].OscChannels[i].flavourName_Latex << " ";}
1873  if (printToCSV) {outcsv << GetFlavourName(iSample, i) << ",";}
1874  }
1875  if (printToFile) {outfile << "&" << std::setw(space) << "Total:" << "\\\\ \\hline" << std::endl;}
1876  if (printToCSV) {outcsv <<"Total\n";}
1877  table_headings += fmt::format(" {:<10} |", "Total");
1878  table_footline += "-------------";
1879 
1880  MACH3LOG_INFO("{}", table_headings);
1881  MACH3LOG_INFO("{}", table_footline);
1882 
1883  for (unsigned int i=0;i<IntegralList.size();i++) {
1884  double ModeIntegral = 0;
1885  if (printToFile) {outfile << std::setw(space) << Modes->GetMaCh3ModeName(i);}
1886  if(printToCSV) {outcsv << Modes->GetMaCh3ModeName(i) << ",";}
1887 
1888  table_headings = fmt::format("| {:<8} |", Modes->GetMaCh3ModeName(i)); //Start string with mode name
1889 
1890  for (unsigned int j=0;j<IntegralList[i].size();j++) {
1891  double Integral = IntegralList[i][j]->Integral();
1892 
1893  if (Integral < 1e-100) {Integral=0;}
1894 
1895  ModeIntegral += Integral;
1896  ChannelIntegral[j] += Integral;
1897  PDFIntegral += Integral;
1898 
1899  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",Integral) << " ";}
1900  if (printToCSV) {outcsv << Form("%4.5f", Integral) << ",";}
1901 
1902  table_headings += fmt::format(" {:<17.4f} |", Integral);
1903  }
1904  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",ModeIntegral) << " \\\\ \\hline" << std::endl;}
1905  if (printToCSV) {outcsv << Form("%4.5f", ModeIntegral) << "\n";}
1906 
1907  table_headings += fmt::format(" {:<10.4f} |", ModeIntegral);
1908 
1909  MACH3LOG_INFO("{}", table_headings);
1910  }
1911 
1912  if (printToFile) {outfile << std::setw(space) << "Total:";}
1913  if (printToCSV) {outcsv << "Total,";}
1914 
1915  //Clear the table_headings to print last row of totals
1916  table_headings = fmt::format("| {:<8} |", "Total");
1917  for (unsigned int i=0;i<ChannelIntegral.size();i++) {
1918  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",ChannelIntegral[i]) << " ";}
1919  if (printToCSV) {outcsv << Form("%4.5f", ChannelIntegral[i]) << ",";}
1920  table_headings += fmt::format(" {:<17.4f} |", ChannelIntegral[i]);
1921  }
1922  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",PDFIntegral) << " \\\\ \\hline" << std::endl;}
1923  if (printToCSV) {outcsv << Form("%4.5f", PDFIntegral) << "\n\n\n\n";} // Let's have a few new lines!
1924 
1925  table_headings += fmt::format(" {:<10.4f} |", PDFIntegral);
1926  MACH3LOG_INFO("{}", table_headings);
1927  MACH3LOG_INFO("{}", table_footline);
1928 
1929  if (printToFile) {
1930  outfile << "\\end{tabular}" << std::endl;
1931  outfile << "\\end{center}" << std::endl;
1932  outfile << "\\end{table}" << std::endl;
1933  }
1934 
1935  MACH3LOG_INFO("");
1936 
1937  if (printToFile) {
1938  outfile << std::endl;
1939  outfile.close();
1940  }
1941 }
std::string GetFlavourName(const int iSample, const int iChannel) const final
std::vector< std::unique_ptr< TH1 > > ReturnHistsBySelection1D(const int iSample, const std::string &KinematicProjection, const int Selection1, const int Selection2=-1, const int WeightStyle=0)
std::vector< std::unique_ptr< TH2 > > ReturnHistsBySelection2D(const int iSample, const std::string &KinematicProjectionX, const std::string &KinematicProjectionY, const int Selection1, const int Selection2=-1, const int WeightStyle=0)

◆ PrintRates()

void SampleHandlerBase::PrintRates ( const bool  DataOnly = false)
finalvirtual

Helper function to print rates for the samples with LLH.

Parameters
DataOnlywhether to print data only rates

Implements SampleHandlerInterface.

Definition at line 2036 of file SampleHandlerBase.cpp.

2036  {
2037 // ***************************************************************************
2038  if (!SampleHandler_data.size()) {
2039  MACH3LOG_ERROR("Data sample is empty!");
2040  throw MaCh3Exception(__FILE__, __LINE__);
2041  }
2042  MACH3LOG_INFO("Printing for {}", GetName());
2043 
2044  if (!DataOnly) {
2045  const std::string sep_full(71, '-');
2046  MACH3LOG_INFO("{}", sep_full);
2047  MACH3LOG_INFO("{:<40}{:<10}{:<10}{:<10}|", "Sample", "Data", "MC", "-LLH");
2048  } else {
2049  const std::string sep_data(51, '-');
2050  MACH3LOG_INFO("{}", sep_data);
2051  MACH3LOG_INFO("{:<40}{:<10}|", "Sample", "Data");
2052  }
2053 
2054  double sumData = 0.0;
2055  double sumMC = 0.0;
2056  double likelihood = 0.0;
2057 
2058  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
2059  std::string name = GetSampleTitle(iSample);
2060  std::vector<double> DataArray = GetDataArray(iSample);
2061  double dataIntegral = std::accumulate(DataArray.begin(), DataArray.end(), 0.0);
2062  sumData += dataIntegral;
2063  if (!DataOnly) {
2064  std::vector<double> MCArray = GetMCArray(iSample);
2065  double mcIntegral = std::accumulate(MCArray.begin(), MCArray.end(), 0.0);
2066  sumMC += mcIntegral;
2067  likelihood = GetSampleLikelihood(iSample);
2068 
2069  MACH3LOG_INFO("{:<40}{:<10.2f}{:<10.2f}{:<10.2f}|", name, dataIntegral, mcIntegral, likelihood);
2070  } else {
2071  MACH3LOG_INFO("{:<40}{:<10.2f}|", name, dataIntegral);
2072  }
2073  }
2074  if (!DataOnly) {
2075  likelihood = GetLikelihood();
2076  MACH3LOG_INFO("{:<40}{:<10.2f}{:<10.2f}{:<10.2f}|", "Total", sumData, sumMC, likelihood);
2077  const std::string sep_full(71, '-');
2078  MACH3LOG_INFO("{}", sep_full);
2079  } else {
2080  MACH3LOG_INFO("{:<40}{:<10.2f}|", "Total", sumData);
2081  const std::string sep_data(51, '-');
2082  MACH3LOG_INFO("{}", sep_data);
2083  }
2084 }
double GetSampleLikelihood(const int isample) const override
Get likelihood for single sample.
double GetLikelihood() const override
DB Multi-threaded GetLikelihood.
auto GetDataArray() const
Return array storing data entries for every bin.
auto GetMCArray() const
Return array storing MC entries for every bin.

◆ ReadConfig()

void SampleHandlerBase::ReadConfig ( )
protected

Load information about sample handler and corresponding samples from config file.

Definition at line 54 of file SampleHandlerBase.cpp.

55 {
56  auto ModeName = Get<std::string>(SampleManager->raw()["MaCh3ModeConfig"], __FILE__ , __LINE__);
57  Modes = std::make_unique<MaCh3Modes>(getenv("MACH3")+std::string("/") + ModeName);
58  //SampleName has to be provided in the sample yaml otherwise this will throw an exception
59  SampleHandlerName = Get<std::string>(SampleManager->raw()["SampleHandlerName"], __FILE__ , __LINE__);
60 
61  fTestStatistic = static_cast<TestStatistic>(SampleManager->GetMCStatLLH());
62  if (CheckNodeExists(SampleManager->raw(), "LikelihoodOptions")) {
63  UpdateW2 = GetFromManager<bool>(SampleManager->raw()["LikelihoodOptions"]["UpdateW2"], false);
64  }
65 
66  if (!CheckNodeExists(SampleManager->raw(), "BinningFile")){
67  MACH3LOG_ERROR("BinningFile not given in for sample handler {}, ReturnKinematicParameterBinning will not work", SampleHandlerName);
68  throw MaCh3Exception(__FILE__, __LINE__);
69  }
70 
71  auto EnabledSasmples = Get<std::vector<std::string>>(SampleManager->raw()["Samples"], __FILE__ , __LINE__);
72  // Get number of samples and resize relevant objects
73  nSamples = static_cast<M3::int_t>(EnabledSasmples.size());
74  SampleDetails.resize(nSamples);
75  StoredSelection.resize(nSamples);
76  for (int iSample = 0; iSample < nSamples; iSample++)
77  {
78  auto SampleSettings = SampleManager->raw()[EnabledSasmples[iSample]];
79  LoadSingleSample(iSample, SampleSettings);
80  } // end loop over enabling samples
81 
82  // EM: initialise the mode weight map
83  for( int iMode=0; iMode < Modes->GetNModes(); iMode++ ) {
84  _modeNomWeightMap[Modes->GetMaCh3ModeName(iMode)] = 1.0;
85  }
86 
87  // EM: multiply by the nominal weight specified in the sample config file
88  if ( SampleManager->raw()["NominalWeights"] ) {
89  for( int iMode=0; iMode<Modes->GetNModes(); iMode++ ) {
90  std::string modeStr = Modes->GetMaCh3ModeName(iMode);
91  if( SampleManager->raw()["NominalWeights"][modeStr] ) {
92  double modeWeight = SampleManager->raw()["NominalWeights"][modeStr].as<double>();
93  _modeNomWeightMap[Modes->GetMaCh3ModeName(iMode)] *= modeWeight;
94  }
95  }
96  }
97 
98  // EM: print em out
99  MACH3LOG_INFO(" Nominal mode weights to apply: ");
100  for(int iMode=0; iMode<Modes->GetNModes(); iMode++ ) {
101  std::string modeStr = Modes->GetMaCh3ModeName(iMode);
102  MACH3LOG_INFO(" - {}: {}", modeStr, _modeNomWeightMap.at(modeStr));
103  }
104 }
TestStatistic
Make an enum of the test statistic that we're using.
bool CheckNodeExists(const YAML::Node &node, Args... args)
KS: Wrapper function to call the recursive helper.
Definition: YamlHelper.h:60
std::unordered_map< std::string, double > _modeNomWeightMap
void LoadSingleSample(const int iSample, const YAML::Node &Settings)
Initialise single sample from config file.
TestStatistic fTestStatistic
Test statistic tells what kind of likelihood sample is using.

◆ RegisterFunctionalParameters()

virtual void SampleHandlerBase::RegisterFunctionalParameters ( )
protectedpure virtual

HH - a experiment-specific function where the maps to actual functions are set up.

Implemented in PySampleHandlerBase.

◆ RegisterIndividualFunctionalParameter()

void SampleHandlerBase::RegisterIndividualFunctionalParameter ( const std::string &  fpName,
int  fpEnum,
FuncParFuncType  fpFunc 
)
protected

HH - a helper function for RegisterFunctionalParameter.

Definition at line 468 of file SampleHandlerBase.cpp.

468  {
469  // Add protections to not add the same functional parameter twice
470  if (funcParsNamesMap.find(fpName) != funcParsNamesMap.end()) {
471  MACH3LOG_ERROR("Functional parameter {} already registered in funcParsNamesMap with enum {}", fpName, funcParsNamesMap[fpName]);
472  throw MaCh3Exception(__FILE__, __LINE__);
473  }
474  if (std::find(funcParsNamesVec.begin(), funcParsNamesVec.end(), fpName) != funcParsNamesVec.end()) {
475  MACH3LOG_ERROR("Functional parameter {} already in funcParsNamesVec", fpName);
476  throw MaCh3Exception(__FILE__, __LINE__);
477  }
478  if (funcParsFuncMap.find(fpEnum) != funcParsFuncMap.end()) {
479  MACH3LOG_ERROR("Functional parameter enum {} already registered in funcParsFuncMap", fpEnum);
480  throw MaCh3Exception(__FILE__, __LINE__);
481  }
482  funcParsNamesMap[fpName] = fpEnum;
483  funcParsNamesVec.push_back(fpName);
484  funcParsFuncMap[fpEnum] = fpFunc;
485 }
std::unordered_map< std::string, int > funcParsNamesMap
HH - a map that relates the name of the functional parameter to funcpar enum.
std::vector< std::string > funcParsNamesVec
HH - a vector of string names for each functional parameter.
std::unordered_map< int, FuncParFuncType > funcParsFuncMap
HH - a map that relates the funcpar enum to pointer of the actual function.

◆ ResetHistograms()

void SampleHandlerBase::ResetHistograms ( )
protected

Helper function to reset histograms.

Definition at line 457 of file SampleHandlerBase.cpp.

457  {
458 // **************************************************
459  // DB Reset values stored in PDF array to 0.
460  // Don't openMP this; no significant gain
461  const int nBins = Binning->GetNBins();
462  std::fill_n(SampleHandler_array.begin(), nBins, 0.0);
463  if (FirstTimeW2) {
464  std::fill_n(SampleHandler_array_w2.begin(), nBins, 0.0);
465  }
466 } // end function

◆ ResetShifts()

virtual void SampleHandlerBase::ResetShifts ( const int  iEvent)
inlineprotectedvirtual

HH - reset the shifted values to the original values.

Definition at line 255 of file SampleHandlerBase.h.

255 {(void)iEvent;};

◆ ReturnHistsBySelection1D()

std::vector< std::unique_ptr< TH1 > > SampleHandlerBase::ReturnHistsBySelection1D ( const int  iSample,
const std::string &  KinematicProjection,
const int  Selection1,
const int  Selection2 = -1,
const int  WeightStyle = 0 
)

Definition at line 1944 of file SampleHandlerBase.cpp.

1945  {
1946 // ************************************************
1947  std::vector<std::unique_ptr<TH1>> hHistList;
1948  std::string legendEntry;
1949 
1950  if (THStackLeg != nullptr) {delete THStackLeg;}
1951  THStackLeg = new TLegend(0.1,0.1,0.9,0.9);
1952 
1953  int iMax = -1;
1954  if (Selection1 == FDPlotType::kModePlot) {
1955  iMax = Modes->GetNModes();
1956  }
1957  if (Selection1 == FDPlotType::kOscChannelPlot) {
1958  iMax = GetNOscChannels(iSample);
1959  }
1960  if (iMax == -1) {
1961  MACH3LOG_ERROR("You've passed me a Selection1 which was not implemented in ReturnHistsBySelection1D. Selection1 and Selection2 are counters for different indexable quantities");
1962  throw MaCh3Exception(__FILE__, __LINE__);
1963  }
1964 
1965  for (int i=0;i<iMax;i++) {
1966  if (Selection1 == FDPlotType::kModePlot) {
1967  hHistList.push_back(Get1DVarHistByModeAndChannel(iSample, KinematicProjection,i,Selection2,WeightStyle));
1968  THStackLeg->AddEntry(hHistList[i].get(), (Modes->GetMaCh3ModeName(i)+Form(" : (%4.2f)",hHistList[i]->Integral())).c_str(),"f");
1969 
1970  hHistList[i]->SetFillColor(static_cast<Color_t>(Modes->GetMaCh3ModePlotColor(i)));
1971  hHistList[i]->SetLineColor(static_cast<Color_t>(Modes->GetMaCh3ModePlotColor(i)));
1972  }
1973  if (Selection1 == FDPlotType::kOscChannelPlot) {
1974  hHistList.push_back(Get1DVarHistByModeAndChannel(iSample, KinematicProjection,Selection2,i,WeightStyle));
1975  THStackLeg->AddEntry(hHistList[i].get(),(GetFlavourName(iSample, i)+Form(" | %4.2f",hHistList[i]->Integral())).c_str(),"f");
1976  }
1977  }
1978 
1979  return hHistList;
1980 }

◆ ReturnHistsBySelection2D()

std::vector< std::unique_ptr< TH2 > > SampleHandlerBase::ReturnHistsBySelection2D ( const int  iSample,
const std::string &  KinematicProjectionX,
const std::string &  KinematicProjectionY,
const int  Selection1,
const int  Selection2 = -1,
const int  WeightStyle = 0 
)

Definition at line 1983 of file SampleHandlerBase.cpp.

1985  {
1986 // ************************************************
1987  std::vector<std::unique_ptr<TH2>> hHistList;
1988 
1989  int iMax = -1;
1990  if (Selection1 == FDPlotType::kModePlot) {
1991  iMax = Modes->GetNModes();
1992  }
1993  if (Selection1 == FDPlotType::kOscChannelPlot) {
1994  iMax = GetNOscChannels(iSample);
1995  }
1996  if (iMax == -1) {
1997  MACH3LOG_ERROR("You've passed me a Selection1 which was not implemented in ReturnHistsBySelection1D. Selection1 and Selection2 are counters for different indexable quantities");
1998  throw MaCh3Exception(__FILE__, __LINE__);
1999  }
2000 
2001  for (int i=0;i<iMax;i++) {
2002  if (Selection1 == FDPlotType::kModePlot) {
2003  hHistList.push_back(Get2DVarHistByModeAndChannel(iSample, KinematicProjectionX,KinematicProjectionY,i,Selection2,WeightStyle));
2004  }
2005  if (Selection1 == FDPlotType::kOscChannelPlot) {
2006  hHistList.push_back(Get2DVarHistByModeAndChannel(iSample, KinematicProjectionX,KinematicProjectionY,Selection2,i,WeightStyle));
2007  }
2008  }
2009 
2010  return hHistList;
2011 }

◆ ReturnKinematicParameter() [1/2]

virtual double SampleHandlerBase::ReturnKinematicParameter ( const int  KinematicVariable,
const int  iEvent 
) const
protectedpure virtual

Implemented in PySampleHandlerBase.

◆ ReturnKinematicParameter() [2/2]

double SampleHandlerBase::ReturnKinematicParameter ( const std::string &  KinematicParameter,
int  iEvent 
) const
inlineprotected

Return the value of an associated kinematic parameter for an event.

Definition at line 297 of file SampleHandlerBase.h.

297  {
298  return ReturnKinematicParameter(ReturnKinematicParameterFromString(KinematicParameter), iEvent);
299  }

◆ ReturnKinematicParameterBinning()

std::vector< double > SampleHandlerBase::ReturnKinematicParameterBinning ( const int  Sample,
const std::string &  KinematicParameter 
) const
finalprotectedvirtual

Return the binning used to draw a kinematic parameter.

Todo:
might be useful to allow overwriting this

Implements SampleHandlerInterface.

Definition at line 1665 of file SampleHandlerBase.cpp.

1665  {
1666 // ************************************************
1667  // If any of fit based variables return them
1669  if(Binning->IsUniform(Sample)) {
1670  for(int iDim = 0; iDim < GetNDim(Sample); iDim++) {
1671  if(KinematicParameter == GetKinVarName(Sample, iDim)) {
1672  return Binning->GetBinEdges(Sample, iDim);
1673  }
1674  } // end loop over Dimension
1675  } // end loop over IsUniform
1676 
1677  auto MakeBins = [](int nBins) {
1678  std::vector<double> bins(nBins + 1);
1679  for (int i = 0; i <= nBins; ++i)
1680  bins[i] = static_cast<double>(i) - 0.5;
1681  return bins;
1682  };
1683 
1684  if (KinematicParameter == "OscillationChannel") {
1685  return MakeBins(GetNOscChannels(Sample));
1686  } else if (KinematicParameter == "Mode") {
1687  return MakeBins(Modes->GetNModes());
1688  }
1689 
1690  std::vector<double> BinningVect;
1691  // We first check if binning for a sample has been specified
1692  auto BinningConfig = M3OpenConfig(SampleManager->raw()["BinningFile"].as<std::string>());
1693  if(BinningConfig[GetSampleTitle(Sample)] && BinningConfig[GetSampleTitle(Sample)][KinematicParameter]){
1694  BinningVect = Get<std::vector<double>>(BinningConfig[GetSampleTitle(Sample)][KinematicParameter], __FILE__, __LINE__);
1695  } else {
1696  BinningVect = Get<std::vector<double>>(BinningConfig[KinematicParameter], __FILE__, __LINE__);
1697  }
1698 
1699  // Ensure binning is increasing
1700  auto IsIncreasing = [](const std::vector<double>& vec) {
1701  for (size_t i = 1; i < vec.size(); ++i) {
1702  if (vec[i] <= vec[i-1]) {
1703  return false;
1704  }
1705  }
1706  return true;
1707  };
1708 
1709  if (!IsIncreasing(BinningVect)) {
1710  MACH3LOG_ERROR("Binning for {} is not increasing [{}]", KinematicParameter, fmt::join(BinningVect, ", "));
1711  throw MaCh3Exception(__FILE__,__LINE__);
1712  }
1713 
1714  return BinningVect;
1715 }
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
Definition: YamlHelper.h:589

◆ ReturnKinematicParameterFromString()

int SampleHandlerBase::ReturnKinematicParameterFromString ( const std::string &  KinematicStr) const

ETA function to generically convert a string from xsec cov to a kinematic type.

Definition at line 1612 of file SampleHandlerBase.cpp.

1612  {
1613 // ************************************************
1614  auto it = KinematicParameters->find(KinematicParameterStr);
1615  if (it != KinematicParameters->end()) return it->second;
1616 
1617  MACH3LOG_ERROR("Did not recognise Kinematic Parameter type: {}", KinematicParameterStr);
1618  throw MaCh3Exception(__FILE__, __LINE__);
1619 
1620  return M3::_BAD_INT_;
1621 }

◆ ReturnKinematicVector() [1/2]

virtual std::vector<double> SampleHandlerBase::ReturnKinematicVector ( const int  KinematicVariable,
const int  iEvent 
) const
inlineprotectedvirtual

Definition at line 306 of file SampleHandlerBase.h.

306  {
307  return {}; (void)KinematicVariable; (void)iEvent;};

◆ ReturnKinematicVector() [2/2]

std::vector<double> SampleHandlerBase::ReturnKinematicVector ( const std::string &  KinematicParameter,
const int  iEvent 
) const
inlineprotected

Definition at line 303 of file SampleHandlerBase.h.

303  {
304  return ReturnKinematicVector(ReturnKinematicVectorFromString(KinematicParameter), iEvent);
305  }

◆ ReturnKinematicVectorFromString()

int SampleHandlerBase::ReturnKinematicVectorFromString ( const std::string &  KinematicStr) const

JM: Convert a kinematic vector name to its corresponding integer ID.

Definition at line 1639 of file SampleHandlerBase.cpp.

1639  {
1640 // ************************************************
1641  auto it = KinematicVectors->find(KinematicVectorStr);
1642  if (it != KinematicVectors->end()) return it->second;
1643 
1644  MACH3LOG_ERROR("Did not recognise Kinematic Vector: {}", KinematicVectorStr);
1645  throw MaCh3Exception(__FILE__, __LINE__);
1646 
1647  return M3::_BAD_INT_;
1648 }

◆ ReturnStackedHistBySelection1D()

std::unique_ptr< THStack > SampleHandlerBase::ReturnStackedHistBySelection1D ( const int  iSample,
const std::string &  KinematicProjection,
const int  Selection1,
const int  Selection2 = -1,
const int  WeightStyle = 0 
)

Definition at line 2014 of file SampleHandlerBase.cpp.

2015  {
2016 // ************************************************
2017  auto HistList = ReturnHistsBySelection1D(iSample, KinematicProjection, Selection1, Selection2, WeightStyle);
2018  auto StackHist = std::make_unique<THStack>((GetSampleTitle(iSample)+"_"+KinematicProjection+"_Stack").c_str(),"");
2019  // Note: we use .release() to transfer ownership of each TH1 to THStack.
2020  for (unsigned int i=0;i<HistList.size();i++) {
2021  StackHist->Add(HistList[i].release());
2022  }
2023  return StackHist;
2024 }

◆ ReturnStackHistLegend()

const TLegend* SampleHandlerBase::ReturnStackHistLegend ( ) const
inline

Return the legend used for stacked histograms with sample info.

Definition at line 135 of file SampleHandlerBase.h.

135 {return THStackLeg;}

◆ ReturnStringFromKinematicParameter()

std::string SampleHandlerBase::ReturnStringFromKinematicParameter ( const int  KinematicVariable) const

ETA function to generically convert a kinematic type from xsec cov to a string.

Definition at line 1624 of file SampleHandlerBase.cpp.

1624  {
1625 // ************************************************
1626  auto it = ReversedKinematicParameters->find(KinematicParameter);
1627  if (it != ReversedKinematicParameters->end()) {
1628  return it->second;
1629  }
1630 
1631  MACH3LOG_ERROR("Did not recognise Kinematic Parameter type: {}", KinematicParameter);
1632  throw MaCh3Exception(__FILE__, __LINE__);
1633 
1634  return "";
1635 }

◆ ReturnStringFromKinematicVector()

std::string SampleHandlerBase::ReturnStringFromKinematicVector ( const int  KinematicVariable) const

JM: Convert a kinematic vector integer ID to its corresponding name as a string.

Definition at line 1651 of file SampleHandlerBase.cpp.

1651  {
1652 // ************************************************
1653  auto it = ReversedKinematicVectors->find(KinematicVector);
1654  if (it != ReversedKinematicVectors->end()) {
1655  return it->second;
1656  }
1657 
1658  MACH3LOG_ERROR("Did not recognise Kinematic Vector: {}", KinematicVector);
1659  throw MaCh3Exception(__FILE__, __LINE__);
1660 
1661  return "";
1662 }

◆ Reweight()

void SampleHandlerBase::Reweight ( )
overridevirtual

main routine modifying MC prediction based on proposed parameter values

Implements SampleHandlerInterface.

Definition at line 319 of file SampleHandlerBase.cpp.

319  {
320 //************************************************
321  //KS: Reset the histograms before reweight
322  ResetHistograms();
323 
324  //You only need to do these things if Oscillator has been initialised
325  //if not then you're not considering oscillations
326  if (Oscillator) Oscillator->Evaluate();
327 
328  // Calculate weight coming from all splines if we initialised handler
329  if(SplineHandler) SplineHandler->Evaluate();
330 
331  // Update the functional parameter values to the latest proposed values
333 
334  //KS: If using CPU this does nothing, if on GPU need to make sure we finished copying memory from
335  if(SplineHandler) SplineHandler->SynchroniseMemTransfer();
336 
337  #ifdef MULTITHREAD
338  // Call entirely different routine if we're running with openMP
339  FillArray_MP();
340  #else
341  FillArray();
342  #endif
343 
344  //KS: If you want to not update W2 wights then uncomment this line
345  if(!UpdateW2) FirstTimeW2 = false;
346 }
void FillArray_MP()
DB Nice new multi-threaded function which calculates the event weights and fills the relevant bins of...
virtual void PrepFunctionalParameters()
Update the functional parameter values to the latest proposed values. Needs to be called before every...
void ResetHistograms()
Helper function to reset histograms.
void FillArray()
Function which does the core reweighting, fills the SampleHandlerBase::SampleHandler_array vector wit...

◆ SaveAdditionalInfo()

void SampleHandlerBase::SaveAdditionalInfo ( TDirectory *  Dir)
finalvirtual

Store additional info in a chan.

Reimplemented from SampleHandlerInterface.

Definition at line 1310 of file SampleHandlerBase.cpp.

1310  {
1311 // ************************************************
1312  Dir->cd();
1313 
1314  YAML::Node Config = SampleManager->raw();
1315  TMacro ConfigSave = YAMLtoTMacro(Config, (std::string("Config_") + GetName()));
1316  ConfigSave.Write();
1317 
1318  for(int iSample = 0; iSample < GetNSamples(); iSample++)
1319  {
1320  std::unique_ptr<TH1> data_hist;
1321 
1322  if (GetNDim(iSample) == 1) {
1323  data_hist = M3::Clone<TH1D>(dynamic_cast<const TH1D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1324  data_hist->GetXaxis()->SetTitle(GetKinVarName(iSample, 0).c_str());
1325  data_hist->GetYaxis()->SetTitle("Number of Events");
1326  } else if (GetNDim(iSample) == 2) {
1327  if(Binning->IsUniform(iSample)) {
1328  data_hist = M3::Clone<TH2D>(dynamic_cast<const TH2D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1329  } else {
1330  data_hist = M3::Clone<TH2Poly>(dynamic_cast<const TH2Poly*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1331  }
1332  data_hist->GetXaxis()->SetTitle(GetKinVarName(iSample, 0).c_str());
1333  data_hist->GetYaxis()->SetTitle(GetKinVarName(iSample, 1).c_str());
1334  data_hist->GetZaxis()->SetTitle("Number of Events");
1335  } else {
1336  data_hist = M3::Clone<TH1D>(dynamic_cast<const TH1D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1337  int nbins = Binning->GetNBins(iSample);
1338  for(int iBin = 0; iBin < nbins; iBin++) {
1339  auto BinName = Binning->GetBinName(iSample, iBin);
1340  data_hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
1341  }
1342  data_hist->GetYaxis()->SetTitle("Number of Events");
1343  }
1344 
1345  if (!data_hist) {
1346  MACH3LOG_ERROR("nullptr data hist :(");
1347  throw MaCh3Exception(__FILE__, __LINE__);
1348  }
1349 
1350  data_hist->SetTitle(("data_" + GetSampleTitle(iSample)).c_str());
1351  data_hist->Write();
1352  }
1353 }
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Definition: YamlHelper.h:167

◆ SetBinning()

void SampleHandlerBase::SetBinning ( )
protected

set the binning for 2D sample used for the likelihood calculation

Definition at line 750 of file SampleHandlerBase.cpp.

750  {
751 // ************************************************
752  for(int iSample = 0; iSample < GetNSamples(); iSample++)
753  {
754  int Dimension = GetNDim(iSample);
755  std::string HistTitle = GetSampleTitle(iSample);
756 
757  auto* SamDet = &SampleDetails[iSample];
758  if(Dimension == 1) {
759  auto XVec = Binning->GetBinEdges(iSample, 0);
760  SamDet->DataHist = new TH1D(("d" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
761  SamDet->MCHist = new TH1D(("h" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
762  SamDet->W2Hist = new TH1D(("w" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
763 
764  // Set all titles so most of projections don't have empty titles...
765  SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
766  SamDet->DataHist->GetYaxis()->SetTitle("Events");
767  SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
768  SamDet->MCHist->GetYaxis()->SetTitle("Events");
769  SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
770  SamDet->W2Hist->GetYaxis()->SetTitle("Events");
771  } else if (Dimension == 2){
772  if(Binning->IsUniform(iSample)) {
773  auto XVec = Binning->GetBinEdges(iSample, 0);
774  auto YVec = Binning->GetBinEdges(iSample, 1);
775  int nX = static_cast<int>(XVec.size() - 1);
776  int nY = static_cast<int>(YVec.size() - 1);
777 
778  SamDet->DataHist = new TH2D(("d" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
779  SamDet->MCHist = new TH2D(("h" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
780  SamDet->W2Hist = new TH2D(("w" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
781  } else {
782  auto AddBinsToTH2Poly = [](TH2Poly* hist, const std::vector<BinInfo>& bins) {
783  for (const auto& bin : bins) {
784  double xLow = bin.Extent[0][0];
785  double xHigh = bin.Extent[0][1];
786  double yLow = bin.Extent[1][0];
787  double yHigh = bin.Extent[1][1];
788 
789  double x[4] = {xLow, xHigh, xHigh, xLow};
790  double y[4] = {yLow, yLow, yHigh, yHigh};
791 
792  hist->AddBin(4, x, y);
793  }
794  };
795  // Create all three histograms
796  SamDet->DataHist = new TH2Poly();
797  SamDet->DataHist->SetName(("d" + HistTitle).c_str());
798  SamDet->DataHist->SetTitle(HistTitle.c_str());
799 
800  SamDet->MCHist = new TH2Poly();
801  SamDet->MCHist->SetName(("h" + HistTitle).c_str());
802  SamDet->MCHist->SetTitle(HistTitle.c_str());
803 
804  SamDet->W2Hist = new TH2Poly();
805  SamDet->W2Hist->SetName(("w" + HistTitle).c_str());
806  SamDet->W2Hist->SetTitle(HistTitle.c_str());
807 
808  // Add bins to each
809  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->DataHist), Binning->GetNonUniformBins(iSample));
810  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->MCHist), Binning->GetNonUniformBins(iSample));
811  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->W2Hist), Binning->GetNonUniformBins(iSample));
812  }
813 
814  // Set all titles so most of projections don't have empty titles...
815  SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
816  SamDet->DataHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
817  SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
818  SamDet->MCHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
819  SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
820  SamDet->W2Hist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
821  } else {
822  int nbins = Binning->GetNBins(iSample);
823  SamDet->DataHist = new TH1D(("d" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
824  SamDet->MCHist = new TH1D(("h" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
825  SamDet->W2Hist = new TH1D(("w" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
826 
827  for(int iBin = 0; iBin < nbins; iBin++) {
828  auto BinName = Binning->GetBinName(iSample, iBin);
829  SamDet->DataHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
830  SamDet->MCHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
831  SamDet->W2Hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
832  }
833 
834  // Set all titles so most of projections don't have empty titles...
835  SamDet->DataHist->GetYaxis()->SetTitle("Events");
836  SamDet->MCHist->GetYaxis()->SetTitle("Events");
837  SamDet->W2Hist->GetYaxis()->SetTitle("Events");
838  }
839 
840  SamDet->DataHist->SetDirectory(nullptr);
841  SamDet->MCHist->SetDirectory(nullptr);
842  SamDet->W2Hist->SetDirectory(nullptr);
843  }
844 
845  //Set the number of X and Y bins now
848 }
void SetupReweightArrays()
Initialise data, MC and W2 histograms.

◆ SetSplinePointers()

void SampleHandlerBase::SetSplinePointers ( )
protected

Set pointers for each event to appropriate weights, for unbinned based on event number while for binned based on other kinematical properties.

Definition at line 1228 of file SampleHandlerBase.cpp.

1228  {
1229 // ************************************************
1230  //Now loop over events and get the spline bin for each event
1231  if (auto BinnedSpline = dynamic_cast<BinnedSplineHandler*>(SplineHandler.get())) {
1232  bool ThrowCrititcal = true;
1234  for (unsigned int j = 0; j < GetNEvents(); ++j) {
1235  auto EventSplines = GetSplineBins(j, BinnedSpline, ThrowCrititcal);
1236  const int NSplines = static_cast<int>(EventSplines.size());
1237  if(NSplines == 0) continue;
1238  auto& w_pointers = MCEvents[j].total_weight_pointers;
1239  w_pointers.reserve(w_pointers.size() + NSplines);
1240 
1241  for(int spline = 0; spline < NSplines; spline++) {
1242  int SystIndex = EventSplines[spline][2];
1243 
1244  bool IsSelected = PassesSelection(SplineParsVec[SystIndex], j);
1245  // Need to then break the event loop
1246  if(!IsSelected){
1247  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", j, SplineParsVec[SystIndex].name);
1248  continue;
1249  }
1250  //Event Splines indexed as: sample name, oscillation channel, syst, mode, etrue, var1, var2 (var2 is a dummy 0 for 1D splines)
1251  w_pointers.push_back(BinnedSpline->RetPointer(EventSplines[spline][0], EventSplines[spline][1],
1252  EventSplines[spline][2], EventSplines[spline][3],
1253  EventSplines[spline][4], EventSplines[spline][5],
1254  EventSplines[spline][6]));
1255  } // end loop over splines
1256  w_pointers.shrink_to_fit();
1257  } // end loop over events
1258  } else if (auto UnbinnedSpline = dynamic_cast<UnbinnedSplineHandler*>(SplineHandler.get())) {
1259  for (unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent) {
1260  MCEvents[iEvent].total_weight_pointers.push_back(UnbinnedSpline->RetPointer(iEvent));
1261  }
1262  } else {
1263  MACH3LOG_ERROR("Not supported splines");
1264  throw MaCh3Exception(__FILE__, __LINE__);
1265  }
1266 }
const std::vector< SplineParameter > GetSplineParsFromSampleName(const std::string &SampleName) const
KS: Grab the Spline parameters for the relevant SampleName.
std::vector< std::vector< int > > GetSplineBins(int Event, BinnedSplineHandler *BinnedSpline, bool &ThrowCrititcal) const
Retrieve the spline bin indices associated with a given event.

◆ SetupExperimentMC()

virtual int SampleHandlerBase::SetupExperimentMC ( )
protectedpure virtual

Experiment specific setup, returns the number of events which were loaded.

Implemented in PySampleHandlerBase.

◆ SetupFunctionalParameters()

void SampleHandlerBase::SetupFunctionalParameters ( )
protectedvirtual

ETA - a function to setup and pass values to functional parameters where you need to pass a value to some custom reweight calc or engine.

Todo:
KS: Instead of clearing it they should not be class members, so we must fix it in future

Definition at line 488 of file SampleHandlerBase.cpp.

488  {
489 // **************************************************
490  funcParsGrid.resize(GetNEvents());
491  if(ParHandler == nullptr) return;
493  // RegisterFunctionalParameters is implemented in experiment-specific code,
494  // which calls RegisterIndividualFuncPar to populate funcParsNamesMap, funcParsNamesVec, and funcParsFuncMap
496  funcParsMap.resize(funcParsNamesMap.size());
497 
498  // For every functional parameter in XsecCov that matches the name in funcParsNames, add it to the map
499  for (FunctionalParameter& fp : funcParsVec) {
500  auto it = funcParsNamesMap.find(fp.name);
501  // If we don't find a match, we need to throw an error
502  if (it == funcParsNamesMap.end()) {
503  MACH3LOG_ERROR("Functional parameter {} not found, did you define it in RegisterFunctionalParameters()?", fp.name);
504  throw MaCh3Exception(__FILE__, __LINE__);
505  }
506  const std::size_t key = static_cast<std::size_t>(it->second);
507  MACH3LOG_INFO("Adding functional parameter: {} to funcParsMap with key: {}",fp.name, key);
508 
509  const int ikey = it->second;
510  fp.funcPtr = &funcParsFuncMap[ikey];
511 
512  funcParsMap[key].valuePtr = fp.valuePtr;
513  funcParsMap[key].funcPtr = fp.funcPtr;
514  }
515 
516  // Mostly the same as CalcNormsBins
517  // For each event, make a vector of pointers to the functional parameters
518  for (std::size_t iEvent = 0; iEvent < static_cast<std::size_t>(GetNEvents()); ++iEvent) {
519  // Now loop over the functional parameters and get a vector of enums corresponding to the functional parameters
520  for (std::vector<FunctionalParameter>::iterator it = funcParsVec.begin(); it != funcParsVec.end(); ++it) {
521  // Check whether the interaction modes match
522  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", static_cast<int>(iEvent))));
523  bool ModeMatch = MatchCondition(it->modes, Mode);
524  if (!ModeMatch) {
525  MACH3LOG_TRACE("Event {}, missed Mode check ({}) for dial {}", iEvent, Mode, it->name);
526  continue;
527  }
528  // Now check whether within kinematic bounds
529  bool IsSelected = PassesSelection((*it), iEvent);
530  // Need to then break the event loop
531  if(!IsSelected){
532  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", iEvent, it->name);
533  continue;
534  }
535  const std::size_t key = static_cast<std::size_t>(funcParsNamesMap[it->name]);
536  funcParsGrid[iEvent].push_back(&funcParsMap[key]);
537  }
538  }
539  MACH3LOG_INFO("Finished setting up functional parameters");
540 
543 
544  funcParsNamesMap.clear();
545  funcParsNamesMap.rehash(0);
546 }
void CleanVector(T &)
Base case: do nothing for non-vector types.
const std::vector< FunctionalParameter > GetFunctionalParametersFromSampleName(const std::string &SampleName) const
HH Get functional parameters for the relevant SampleName.
std::vector< FunctionalShifter > funcParsMap
HH - a map that relates the funcpar enum to pointer of FuncPars struct HH - Changed to a vector of po...
virtual void RegisterFunctionalParameters()=0
HH - a experiment-specific function where the maps to actual functions are set up.
std::vector< FunctionalParameter > funcParsVec
HH - a vector that stores all the FuncPars struct.
HH - Functional parameters Carrier for whether you want to apply a systematic to an event or not.

◆ SetupKinematicMap()

void SampleHandlerBase::SetupKinematicMap ( )
protected

Ensure Kinematic Map is setup and make sure it is initialised correctly.

Definition at line 208 of file SampleHandlerBase.cpp.

208  {
209 // ************************************************
210  if(KinematicParameters == nullptr || ReversedKinematicParameters == nullptr) {
211  MACH3LOG_ERROR("Map KinematicParameters or ReversedKinematicParameters hasn't been initialised");
212  throw MaCh3Exception(__FILE__, __LINE__);
213  }
214  // KS: Ensure maps exist correctly
215  for (const auto& pair : *KinematicParameters) {
216  const auto& key = pair.first;
217  const auto& value = pair.second;
218 
219  auto it = ReversedKinematicParameters->find(value);
220  if (it == ReversedKinematicParameters->end() || it->second != key) {
221  MACH3LOG_ERROR("Mismatch found: {} -> {} but {} -> {}",
222  key, value, value, (it != ReversedKinematicParameters->end() ? it->second : "NOT FOUND"));
223  throw MaCh3Exception(__FILE__, __LINE__);
224  }
225  }
226  // KS: Ensure some MaCh3 specific variables are defined
227  std::vector<std::string> Vars = {"Mode", "OscillationChannel", "TargetNucleus"};
228  for(size_t iVar = 0; iVar < Vars.size(); iVar++) {
229  try {
231  } catch (const MaCh3Exception&) {
232  MACH3LOG_ERROR("MaCh3 expected variable: {} not found in KinematicParameters.", Vars[iVar]);
233  MACH3LOG_ERROR("All keys in KinematicParameters:");
234  for (const auto& pair : *KinematicParameters) {
235  MACH3LOG_ERROR("Key: {}", pair.first);
236  }
237  throw MaCh3Exception(__FILE__, __LINE__);
238  }
239  }
240 }

◆ SetupMC()

virtual void SampleHandlerBase::SetupMC ( )
protectedpure virtual

Function which translates experiment struct into core struct.

Implemented in PySampleHandlerBase.

◆ SetupNormParameters()

void SampleHandlerBase::SetupNormParameters ( )
protected

Setup the norm parameters by assigning each event with bin.

Definition at line 628 of file SampleHandlerBase.cpp.

628  {
629 // ***************************************************************************
630  if(ParHandler == nullptr) return;
631  std::vector< std::vector< int > > norms_bins(GetNEvents());
632 
633  std::vector<NormParameter> norm_parameters = ParHandler->GetNormParsFromSampleName(GetName());
634 
635  if(!ParHandler) {
636  MACH3LOG_ERROR("ParHandler is not setup!");
637  throw MaCh3Exception(__FILE__ , __LINE__ );
638  }
639 
640  // Assign norm bins in MCEvents tree
641  CalcNormsBins(norm_parameters, norms_bins);
642 
643  //DB Attempt at reducing impact of SystematicHandlerGeneric::calcReweight()
644  for (unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent) {
645  int counter = 0;
646  const size_t offset = MCEvents[iEvent].total_weight_pointers.size();
647  const size_t addSize = norms_bins[iEvent].size();
648  MCEvents[iEvent].total_weight_pointers.resize(offset + addSize);
649  for(auto const & norm_bin: norms_bins[iEvent]) {
650  MCEvents[iEvent].total_weight_pointers[offset + counter] = ParHandler->RetPointer(norm_bin);
651  counter += 1;
652  }
653  }
654 }
const M3::float_t * RetPointer(const int iParam)
DB Pointer return to param position.
const std::vector< NormParameter > GetNormParsFromSampleName(const std::string &SampleName) const
DB Get norm/func parameters depending on given SampleName.
void CalcNormsBins(std::vector< NormParameter > &norm_parameters, std::vector< std::vector< int > > &norms_bins)
Check whether a normalisation systematic affects an event or not.

◆ SetupNuOscillatorPointers()

void SampleHandlerBase::SetupNuOscillatorPointers ( )
protected

Initialise pointer to oscillation weight to NuOscillator object.

Definition at line 1105 of file SampleHandlerBase.cpp.

1105  {
1106 // ************************************************
1107  auto AddOscPointer = GetFromManager<bool>(SampleManager->raw()["NuOsc"]["AddOscPointer"], true, __FILE__ , __LINE__);
1108  // Sometimes we don't want to add osc pointer to allow for some experiment specific handling of osc weight, like for example being able to shift osc weigh
1109  if(!AddOscPointer) {
1110  return;
1111  }
1112  for (unsigned int iEvent=0;iEvent<GetNEvents();iEvent++) {
1113  const M3::float_t* osc_w_pointer = GetNuOscillatorPointers(iEvent);
1114 
1115  // KS: Do not add unity
1116  if (osc_w_pointer != &M3::Unity) {
1117  MCEvents[iEvent].total_weight_pointers.push_back(osc_w_pointer);
1118  }
1119  }
1120 }
const M3::float_t * GetNuOscillatorPointers(const int iEvent) const

◆ SetupOscParameters()

void SampleHandlerBase::SetupOscParameters ( )
protected

Setup the osc parameters.

Definition at line 589 of file SampleHandlerBase.cpp.

589  {
590 // ***************************************************************************
591  // KS: Only make sense to setup osc if you have ParHandler
592  if(ParHandler == nullptr ) return;
593 
595  if (OscParams.size() > 0) {
596  MACH3LOG_INFO("Setting up NuOscillator..");
597  if (Oscillator != nullptr) {
598  MACH3LOG_INFO("You have passed an OscillatorBase object through the constructor of a SampleHandlerFD object - this will be used for all oscillation channels");
599  if(Oscillator->isEqualBinningPerOscChannel() != true) {
600  MACH3LOG_ERROR("Trying to run shared NuOscillator without EqualBinningPerOscChannel, this will not work");
601  throw MaCh3Exception(__FILE__, __LINE__);
602  }
603 
604  if(OscParams.size() != Oscillator->GetOscParamsSize()){
605  MACH3LOG_ERROR("SampleHandler {} has {} osc params, while shared NuOsc has {} osc params", GetName(),
606  OscParams.size(), Oscillator->GetOscParamsSize());
607  MACH3LOG_ERROR("This indicate misconfiguration in your Osc yaml");
608  throw MaCh3Exception(__FILE__, __LINE__);
609  }
610  } else {
612  }
614  } else{
615  MACH3LOG_WARN("Didn't find any oscillation params, thus will not enable oscillations");
616  if(CheckNodeExists(SampleManager->raw(), "NuOsc")){
617  MACH3LOG_ERROR("However config for SampleHandler {} has 'NuOsc' field", GetName());
618  MACH3LOG_ERROR("This may indicate misconfiguration");
619  MACH3LOG_ERROR("Either remove 'NuOsc' field from SampleHandler config or check your model.yaml and include oscillation for sample");
620  throw MaCh3Exception(__FILE__, __LINE__);
621  }
622  }
623 }
void InitialiseNuOscillatorObjects()
including Dan's magic NuOscillator
void SetupNuOscillatorPointers()
Initialise pointer to oscillation weight to NuOscillator object.

◆ SetupReweightArrays()

void SampleHandlerBase::SetupReweightArrays ( )
protected

Initialise data, MC and W2 histograms.

Definition at line 742 of file SampleHandlerBase.cpp.

742  {
743 // ************************************************
744  SampleHandler_array = std::vector<double>(Binning->GetNBins(),0);
745  SampleHandler_array_w2 = std::vector<double>(Binning->GetNBins(),0);
746  SampleHandler_data = std::vector<double>(Binning->GetNBins(),0);
747 }

◆ SetupSplines()

virtual void SampleHandlerBase::SetupSplines ( )
protectedpure virtual

initialise your splineXX object and then use InitialiseSplineObject to conviently setup everything up

Todo:
abstract the spline initialisation completely to core

Implemented in PySampleHandlerBase.

Member Data Documentation

◆ _modeNomWeightMap

std::unordered_map<std::string, double> SampleHandlerBase::_modeNomWeightMap
protected

Definition at line 400 of file SampleHandlerBase.h.

◆ Binning

std::unique_ptr<BinningHandler> SampleHandlerBase::Binning
protected

KS: This stores binning information, in future could be come vector to store binning for every used sample.

Definition at line 347 of file SampleHandlerBase.h.

◆ FileToFinalPDGMap

std::unordered_map<std::string, NuPDG> SampleHandlerBase::FileToFinalPDGMap
private

Definition at line 424 of file SampleHandlerBase.h.

◆ FileToInitPDGMap

std::unordered_map<std::string, NuPDG> SampleHandlerBase::FileToInitPDGMap
private

Definition at line 423 of file SampleHandlerBase.h.

◆ FirstTimeW2

bool SampleHandlerBase::FirstTimeW2
protected

KS:Super hacky to update W2 or not.

Definition at line 408 of file SampleHandlerBase.h.

◆ funcParsFuncMap

std::unordered_map<int, FuncParFuncType> SampleHandlerBase::funcParsFuncMap
protected

HH - a map that relates the funcpar enum to pointer of the actual function.

Definition at line 279 of file SampleHandlerBase.h.

◆ funcParsGrid

std::vector<std::vector<FunctionalShifter*> > SampleHandlerBase::funcParsGrid
protected

HH - a grid of vectors of enums for each sample and event.

Definition at line 262 of file SampleHandlerBase.h.

◆ funcParsMap

std::vector<FunctionalShifter> SampleHandlerBase::funcParsMap
protected

HH - a map that relates the funcpar enum to pointer of FuncPars struct HH - Changed to a vector of pointers since it's faster than unordered_map and we are using ints as keys.

Definition at line 267 of file SampleHandlerBase.h.

◆ funcParsNamesMap

std::unordered_map<std::string, int> SampleHandlerBase::funcParsNamesMap
protected

HH - a map that relates the name of the functional parameter to funcpar enum.

Definition at line 276 of file SampleHandlerBase.h.

◆ funcParsNamesVec

std::vector<std::string> SampleHandlerBase::funcParsNamesVec = {}
protected

HH - a vector of string names for each functional parameter.

Definition at line 281 of file SampleHandlerBase.h.

◆ funcParsVec

std::vector<FunctionalParameter> SampleHandlerBase::funcParsVec
protected

HH - a vector that stores all the FuncPars struct.

Todo:
KS: Below functional variables are used only on setup, thus we should refactor them in such a way that they are removed as class members but this would be breaking change thus keep it for the time being.

Definition at line 273 of file SampleHandlerBase.h.

◆ KinematicParameters

const std::unordered_map<std::string, int>* SampleHandlerBase::KinematicParameters
protected

Mapping between string and kinematic enum.

Definition at line 387 of file SampleHandlerBase.h.

◆ KinematicVectors

const std::unordered_map<std::string, int>* SampleHandlerBase::KinematicVectors
protected

Definition at line 392 of file SampleHandlerBase.h.

◆ MCEvents

std::vector<EventInfo> SampleHandlerBase::MCEvents
protected

Stores information about every MC event.

Definition at line 358 of file SampleHandlerBase.h.

◆ Oscillator

std::shared_ptr<OscillationHandler> SampleHandlerBase::Oscillator
protected

Contains oscillator handling calculating oscillation probabilities.

Definition at line 219 of file SampleHandlerBase.h.

◆ ParHandler

ParameterHandlerGeneric* SampleHandlerBase::ParHandler = nullptr
protected

ETA - All experiments will need an xsec, det and osc cov.

Definition at line 366 of file SampleHandlerBase.h.

◆ ReversedKinematicParameters

const std::unordered_map<int, std::string>* SampleHandlerBase::ReversedKinematicParameters
protected

Mapping between kinematic enum and string.

Definition at line 389 of file SampleHandlerBase.h.

◆ ReversedKinematicVectors

const std::unordered_map<int, std::string>* SampleHandlerBase::ReversedKinematicVectors
protected

Definition at line 393 of file SampleHandlerBase.h.

◆ SampleDetails

std::vector<SampleInfo> SampleHandlerBase::SampleDetails
protected

Stores info about currently initialised sample.

Definition at line 360 of file SampleHandlerBase.h.

◆ SampleHandler_array

std::vector<double> SampleHandlerBase::SampleHandler_array
protected

DB Array to be filled after reweighting.

Definition at line 349 of file SampleHandlerBase.h.

◆ SampleHandler_array_w2

std::vector<double> SampleHandlerBase::SampleHandler_array_w2
protected

KS Array used for MC stat.

Definition at line 351 of file SampleHandlerBase.h.

◆ SampleHandler_data

std::vector<double> SampleHandlerBase::SampleHandler_data
protected

DB Array to be filled in AddData.

Definition at line 353 of file SampleHandlerBase.h.

◆ SampleHandlerName

std::string SampleHandlerBase::SampleHandlerName
protected

A unique ID for each sample based on which we can define what systematic should be applied.

Definition at line 370 of file SampleHandlerBase.h.

◆ SampleManager

std::unique_ptr<Manager> SampleHandlerBase::SampleManager
protected

The manager object used to read the sample yaml file.

Definition at line 397 of file SampleHandlerBase.h.

◆ Selection

std::vector< std::vector< KinematicCut > > SampleHandlerBase::Selection
protected

a way to store selection cuts which you may push back in the get1DVar functions most of the time this is just the same as StoredSelection

Definition at line 383 of file SampleHandlerBase.h.

◆ SplineHandler

std::unique_ptr<SplineBase> SampleHandlerBase::SplineHandler
protected

Contains all your splines (binned or unbinned) and handles the setup and the returning of weights from spline evaluations.

Definition at line 216 of file SampleHandlerBase.h.

◆ StoredSelection

std::vector< std::vector< KinematicCut > > SampleHandlerBase::StoredSelection
protected

What gets pulled from config options, these are constant after loading in this is of length 3: 0th index is the value, 1st is lower bound, 2nd is upper bound.

Definition at line 380 of file SampleHandlerBase.h.

◆ THStackLeg

TLegend* SampleHandlerBase::THStackLeg = nullptr
protected

DB Miscellaneous Variables.

Definition at line 404 of file SampleHandlerBase.h.

◆ UpdateW2

bool SampleHandlerBase::UpdateW2
protected

KS:Super hacky to update W2 or not.

Definition at line 410 of file SampleHandlerBase.h.


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