MaCh3  2.6.0
Reference Guide
Public Member Functions | Protected Member Functions | Protected Attributes | 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 *_ParHandler, 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 GetSampleName (const int Sample) const
 Sample name tag used only for getting relevant uncertainties. 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)
 DB: Add data for a given sample from a ROOT histogram. More...
 
void AddData (const int Sample, const std::vector< double > &Data_Array)
 ETA: Add data for a given sample from a raw array. More...
 
void PrintRates (const bool DataOnly=false) final
 Helper function to print rates for the samples with LLH. More...
 
double GetLikelihood () const override
 Return likelihood (-LogL) for all samples. More...
 
double GetSampleLikelihood (const int isample) const override
 Get likelihood (-logL) for a 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)
 Get Data histogram by sample name. More...
 
const TH1 * GetMCHist (const int Sample) final
 Get MC histogram. More...
 
const TH1 * GetMCHist (const std::string &Sample)
 Get MC histogram by sample title. More...
 
const TH1 * GetW2Hist (const int Sample) final
 Get W2 histogram. More...
 
const TH1 * GetW2Hist (const std::string &Sample)
 Get W2 histogram by sample name. More...
 
void Reweight () override
 main routine modifying MC prediction based on proposed parameter values More...
 
M3::float_t GetEventWeight (const int iEvent)
 Computes the total event weight for a given entry. More...
 
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
 Get the flavour name for a given sample and oscillation channel. More...
 
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
 Return 1D projection of MC into given 1D variable (doesn't have to be variable used in the fit) More...
 
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
 Build a 2D projection of MC events into specified variables. More...
 
std::vector< KinematicCutBuildModeChannelSelection (const int iSample, const int kModeToFill, const int kChannelToFill) const
 Construct vector of kinematic cuts that will be applied, on top of default cuts include stuff like cut on mode etc. More...
 
void Fill1DSubEventHist (const int iSample, TH1D *_h1DVar, const std::string &ProjectionVar, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
 Fill projection histogram by looping over all events, and skipping one which doesn't pass specified condition. More...
 
void Fill2DSubEventHist (const int iSample, TH2 *_h2DVar, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
 Fill projection histogram by looping over all events, and skipping one which doesn't pass specified condition. More...
 
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
 Build a 1D histogram for a given variable, optionally filtered by mode and channel. More...
 
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
 Build a 2D histogram for given variables, optionally filtered by mode and channel. More...
 
int GetRangeForPlotType (const SamplePlotType TypeEnum, const int iSample) const
 KS: Return range for plot type, for example number of modes, osc channels etc. More...
 
std::vector< std::unique_ptr< TH1 > > ReturnHistsBySelection1D (const int iSample, const std::string &KinematicProjection, const SamplePlotType 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 SamplePlotType Selection1, const int Selection2=-1, const int WeightStyle=0)
 
std::unique_ptr< THStack > ReturnStackedHistBySelection1D (const int iSample, const std::string &KinematicProjection, const SamplePlotType 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 param handler to a kinematic type. More...
 
std::string ReturnStringFromKinematicParameter (const int KinematicVariable) const
 ETA function to generically convert a kinematic type from param handler to a string. More...
 
void SaveAdditionalInfo (TDirectory *Dir) final
 Store additional info in a chain. 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...
 
unsigned int GetNEvents () const
 Return total number of events. 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...
 
void CheckEmptyBins () const
 Loop over bins and checks if there are any which have 0 entries. More...
 
- Public Member Functions inherited from SampleHandlerInterface
 SampleHandlerInterface ()
 The main constructor. More...
 
virtual ~SampleHandlerInterface ()
 destructor More...
 
virtual M3::int_t GetNSamples ()
 returns total number of samples More...
 
virtual void CleanMemoryBeforeFit ()=0
 Allow to clean not used memory before fit starts. More...
 
virtual void SaveAdditionalInfo ([[maybe_unused]] TDirectory *Dir)
 Store additional info in a chain. More...
 
MaCh3ModesGetMaCh3Modes () const
 Return pointer to MaCh3 modes. More...
 
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...
 
const M3::float_tGetNuOscillatorPointers (const int iEvent) const
 Get pointer to NuOscillator weight for a given event. 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 conveniently 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< SplineIndexGetSplineBins (int Event, BinnedSplineHandler *BinnedSpline, bool &ThrowCrititcal) const
 Retrieve the spline bin indices associated with a given event. More...
 
void FindNominalBinAndEdges ()
 Functions which find the nominal bin and bin edges. More...
 
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 RegisterFunctionalParameters ()
 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...
 
template<typename EventType , typename SFType >
void RegisterIndividualFunctionalParameter (std::vector< EventType > &ExptEvents, std::vector< std::string > const &par_names, SFType shift_func)
 LP - Registration template function for multi-dimensional functional shifts. More...
 
template<typename EventType , typename SFType >
void RegisterIndividualFunctionalParameter (std::vector< EventType > &ExptEvents, std::string const &par_name, SFType shift_func)
 LP - Registration template function for one-dimensional functional shifts. More...
 
virtual void ApplyShifts (const int iEvent)
 ETA - generic function applying shifts. More...
 
virtual void ResetShifts ([[maybe_unused]] const int iEvent)
 HH - reset the shifted values to the original values. More...
 
virtual void FinaliseShifts ([[maybe_unused]] const int iEvent)
 LP - Optionally calculate derived observables after all shifts have been applied. 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...
 
void CalcNormsBins (std::vector< 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 ([[maybe_unused]] 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
 Return the value of an associated kinematic parameter for an event. More...
 
std::vector< double > ReturnKinematicVector (const std::string &KinematicParameter, const int iEvent) const
 
virtual std::vector< double > ReturnKinematicVector ([[maybe_unused]] const int KinematicVariable, [[maybe_unused]] 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 ()
 Setup spline handler (both binned or unbinned) More...
 
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::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
 Identifier of this Sample Handler, mostly used for fancy printing in FitterBase. More...
 
std::vector< std::vector< KinematicCut > > StoredSelection
 DB Vectors to store which kinematic cuts we apply. Gets used in IsEventSelected Read in from sample yaml file. 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: Legend associated with stacked histograms produced by this class. 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...
 
std::unique_ptr< MaCh3ModesModes
 Holds information about used Generator and MaCh3 modes. More...
 

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
 Mapping from input file names to initial neutrino PDG codes. More...
 
std::unordered_map< std::string, NuPDGFileToFinalPDGMap
 Mapping from input file names to final neutrino PDG codes. More...
 
M3::detail::Functional functional
 Helper object for storing/updating information related to functional shift parameters. More...
 
unsigned int nEvents
 Number of MC events are there. More...
 

Detailed Description

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

This class manages samples used in the analysis. It supports event-by-event reweighting and allows kinematic shifts to be applied at the event level, which may cause migration between analysis bins.

The likelihood calculation is performed in binned space.

Author
Dan Barrow
Ed Atkin

Definition at line 35 of file SampleHandlerBase.h.

Constructor & Destructor Documentation

◆ SampleHandlerBase()

SampleHandlerBase::SampleHandlerBase ( std::string  ConfigFileName,
ParameterHandlerGeneric _ParHandler,
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 _ParHandler
19  if(!_ParHandler) {
20  MACH3LOG_WARN("You've passed me a nullptr ParameterHandler so I will not use any xsec parameters");
21  }
22  ParHandler = _ParHandler;
23  nEvents = 0;
24  nSamples = 0;
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
Identifier of this Sample Handler, mostly used for fancy printing in FitterBase.
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
unsigned int nEvents
Number of MC events are there.
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: Legend associated with stacked histograms produced by this class.

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 
)

ETA: Add data for a given sample from a raw array.

Parameters
SampleIndex of the sample.
Data_ArrayVector containing the data values.

Definition at line 956 of file SampleHandlerBase.cpp.

956  {
957 // ************************************************
958  const int Start = Binning->GetSampleStartBin(Sample);
959  const int End = Binning->GetSampleEndBin(Sample);
960  const int ExpectedSize = End - Start;
961 
962  if (static_cast<int>(Data_Array.size()) != ExpectedSize) {
963  MACH3LOG_ERROR("Data_Array size mismatch for sample '{}'.", GetSampleTitle(Sample));
964  MACH3LOG_ERROR("Expected size: {}, received size: {}.", ExpectedSize, Data_Array.size());
965  MACH3LOG_ERROR("Start bin: {}, End bin: {}.", Start, End);
966  MACH3LOG_ERROR("This likely indicates a binning or sample slicing bug.");
967  throw MaCh3Exception(__FILE__, __LINE__);
968  }
969 
970  std::copy_n(Data_Array.begin(), End-Start, SampleHandler_data.begin() + Start);
971 
972  FillHist(Sample, SampleDetails[Sample].DataHist, SampleHandler_data);
973 }
#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 
)

DB: Add data for a given sample from a ROOT histogram.

Parameters
SampleIndex of the sample.
DataPointer to a TH1 containing the data to be stored.

Definition at line 884 of file SampleHandlerBase.cpp.

884  {
885 // ************************************************
886  int Dim = GetNDim(Sample);
887  MACH3LOG_INFO("Adding {}D data histogram: {} with {:.2f} events", Dim, Data->GetTitle(), Data->Integral());
888  // delete old histogram
889  delete SampleDetails[Sample].DataHist;
890  SampleDetails[Sample].DataHist = static_cast<TH1*>(Data->Clone());
891 
892  if(!SampleHandler_data.size()) {
893  MACH3LOG_ERROR("SampleHandler_data haven't been initialised yet");
894  throw MaCh3Exception(__FILE__, __LINE__);
895  }
896 
897  auto ChecHistType = [&](const std::string& Type, const int Dimen, const TH1* Hist,
898  const std::string& file, const int line) {
899  if (std::string(Hist->ClassName()) != Type) {
900  MACH3LOG_ERROR("Expected {} for {}D sample, got {}", Type, Dimen, Hist->ClassName());
901  throw MaCh3Exception(file, line);
902  }
903  };
904 
905  if (Dim == 1) {
906  // Ensure we really have a TH1D
907  ChecHistType("TH1D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
908  M3::CheckBinningMatch(static_cast<TH1D*>(SampleDetails[Sample].DataHist),
909  static_cast<TH1D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
910  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
911  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin});
912  // ROOT histograms are 1-based, so bin index + 1
913  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(xBin + 1);
914  }
915  SampleDetails[Sample].DataHist->GetXaxis()->SetTitle(GetKinVarName(Sample, 0).c_str());
916  SampleDetails[Sample].DataHist->GetYaxis()->SetTitle("Number of Events");
917  } else if (Dim == 2) {
918  if(Binning->IsUniform(Sample)) {
919  ChecHistType("TH2D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
920  M3::CheckBinningMatch(static_cast<TH2D*>(SampleDetails[Sample].DataHist),
921  static_cast<TH2D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
922  for (int yBin = 0; yBin < Binning->GetNAxisBins(Sample, 1); ++yBin) {
923  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
924  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
925  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
926  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(xBin + 1, yBin + 1);
927  }
928  }
929  } else{
930  ChecHistType("TH2Poly", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
931  M3::CheckBinningMatch(static_cast<TH2Poly*>(SampleDetails[Sample].DataHist),
932  static_cast<TH2Poly*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
933  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
934  const int idx = iBin + Binning->GetSampleStartBin(Sample);
935  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
936  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(iBin + 1);
937  }
938  }
939 
940  SampleDetails[Sample].DataHist->GetXaxis()->SetTitle(GetKinVarName(Sample, 0).c_str());
941  SampleDetails[Sample].DataHist->GetYaxis()->SetTitle(GetKinVarName(Sample, 1).c_str());
942  SampleDetails[Sample].DataHist->GetZaxis()->SetTitle("Number of Events");
943  } else {
944  ChecHistType("TH1D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
945  M3::CheckBinningMatch(static_cast<TH1D*>(SampleDetails[Sample].DataHist),
946  static_cast<TH1D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
947  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
948  const int idx = iBin + Binning->GetSampleStartBin(Sample);
949  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
950  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(iBin + 1);
951  }
952  }
953 }
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.

Note
It is virtual so we can perform unorthodox shifts, ideally we should de-virtualise once we ensure we can support everything in core

Definition at line 500 of file SampleHandlerBase.cpp.

500  {
501 // ***************************************************************************
502  // KS: If there are no shifts then there is no point in resetting which can be costly.
503  if(!functional.event_shifts.size() || !functional.event_shifts[iEvent].size()) {
504  return;
505  }
506 
507  // Given a sample and event, apply the shifts to the event based on the vector of functional parameter enums
508  // First reset shifted array back to nominal values
509  ResetShifts(iEvent);
510 
511  for (auto const &iShift : functional.event_shifts[iEvent]) {
512  auto & shift = functional.shifts[iShift];
513  shift.apply(shift.par_vals, iEvent);
514  }
515 
516  FinaliseShifts(iEvent);
517 }
M3::detail::Functional functional
Helper object for storing/updating information related to functional shift parameters.
virtual void FinaliseShifts([[maybe_unused]] const int iEvent)
LP - Optionally calculate derived observables after all shifts have been applied.
virtual void ResetShifts([[maybe_unused]] const int iEvent)
HH - reset the shifted values to the original values.
std::vector< Shift > shifts
std::vector< std::vector< int > > event_shifts

◆ 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 1351 of file SampleHandlerBase.cpp.

1352  {
1353 // ************************************************
1354  // Backup current selection
1355  auto originalSelection = Selection;
1356 
1357  //DB Add all the predefined selections to the selection vector which will be applied
1358  auto selectionToApply = Selection;
1359 
1360  //DB Add all requested cuts from the argument to the selection vector which will be applied
1361  for (const auto& cut : ExtraCuts) {
1362  selectionToApply[iSample].emplace_back(cut);
1363  }
1364 
1365  //DB Set the member variable to be the cuts to apply
1366  Selection = std::move(selectionToApply);
1367 
1368  return originalSelection;
1369 }
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

Construct vector of kinematic cuts that will be applied, on top of default cuts include stuff like cut on mode etc.

Parameters
SampleIndex of the sample.

Definition at line 1684 of file SampleHandlerBase.cpp.

1684  {
1685 // ************************************************
1686  bool fChannel;
1687  bool fMode;
1688 
1689  if (kChannelToFill != -1) {
1690  if (kChannelToFill > GetNOscChannels(iSample)) {
1691  MACH3LOG_ERROR("Required channel is not available. kChannelToFill should be between 0 and {}", GetNOscChannels(iSample));
1692  MACH3LOG_ERROR("kChannelToFill given:{}", kChannelToFill);
1693  MACH3LOG_ERROR("Exiting.");
1694  throw MaCh3Exception(__FILE__, __LINE__);
1695  }
1696  fChannel = true;
1697  } else {
1698  fChannel = false;
1699  }
1700 
1701  if (kModeToFill != -1) {
1702  if (!(kModeToFill >= 0) && (kModeToFill < Modes->GetNModes())) {
1703  MACH3LOG_ERROR("Required mode is not available. kModeToFill should be between 0 and {}", Modes->GetNModes());
1704  MACH3LOG_ERROR("kModeToFill given:{}", kModeToFill);
1705  MACH3LOG_ERROR("Exiting..");
1706  throw MaCh3Exception(__FILE__, __LINE__);
1707  }
1708  fMode = true;
1709  } else {
1710  fMode = false;
1711  }
1712 
1713  std::vector< KinematicCut > SelectionVec;
1714 
1715  if (fMode) {
1716  KinematicCut SelecMode;
1718  SelecMode.LowerBound = kModeToFill;
1719  SelecMode.UpperBound = kModeToFill+1;
1720  SelectionVec.push_back(SelecMode);
1721  }
1722 
1723  if (fChannel) {
1724  KinematicCut SelecChannel;
1725  SelecChannel.ParamToCutOnIt = ReturnKinematicParameterFromString("OscillationChannel");
1726  SelecChannel.LowerBound = kChannelToFill;
1727  SelecChannel.UpperBound = kChannelToFill+1;
1728  SelectionVec.push_back(SelecChannel);
1729  }
1730 
1731  return SelectionVec;
1732 }
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 param handler 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< std::vector< NormParameter >> &  norm_parameters,
std::vector< std::vector< int > > &  norms_bins 
)
protected

Check whether a normalisation systematic affects an event or not.

Parameters
norm_parametersindexed [sample][param] describe norm params and associated kinematic cuts etc.

Definition at line 610 of file SampleHandlerBase.cpp.

610  {
611 // ************************************************
612  for(unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent){
613  std::vector< int > NormBins = {};
614  if (ParHandler) {
615  const auto SampleId = MCEvents[iEvent].NominalSample;
616  auto& NormParam = norm_parameters[SampleId];
617  // Skip oscillated NC events
618  // Not strictly needed, but these events don't get included in oscillated predictions, so
619  // no need to waste our time calculating and storing information about xsec parameters
620  // that will never be used.
621  if (MCEvents[iEvent].isNC && (MCEvents[iEvent].nupdg != MCEvents[iEvent].nupdgUnosc) ) {
622  MACH3LOG_TRACE("Event {}, missed NC/signal check", iEvent);
623  continue;
624  } //DB Abstract check on MaCh3Modes to determine which apply to neutral current
625  for (std::vector<NormParameter>::iterator it = NormParam.begin(); it != NormParam.end(); ++it) {
626  //Now check that the target of an interaction matches with the normalisation parameters
627  const int Target = static_cast<int>(std::round(ReturnKinematicParameter("TargetNucleus", iEvent)));
628  bool TargetMatch = MatchCondition(it->targets, Target);
629  if (!TargetMatch) {
630  MACH3LOG_TRACE("Event {}, missed target check ({}) for dial {}", iEvent, Target, it->name);
631  continue;
632  }
633 
634  //Now check that the neutrino flavour in an interaction matches with the normalisation parameters
635  bool FlavourMatch = MatchCondition(it->pdgs, MCEvents[iEvent].nupdg);
636  if (!FlavourMatch) {
637  MACH3LOG_TRACE("Event {}, missed PDG check ({}) for dial {}", iEvent,MCEvents[iEvent].nupdg, it->name);
638  continue;
639  }
640 
641  //Now check that the unoscillated neutrino flavour in an interaction matches with the normalisation parameters
642  bool FlavourUnoscMatch = MatchCondition(it->preoscpdgs, MCEvents[iEvent].nupdgUnosc);
643  if (!FlavourUnoscMatch){
644  MACH3LOG_TRACE("Event {}, missed FlavourUnosc check ({}) for dial {}", iEvent,MCEvents[iEvent].nupdgUnosc, it->name);
645  continue;
646  }
647 
648  //Now check that the mode of an interaction matches with the normalisation parameters
649  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", iEvent)));
650  bool ModeMatch = MatchCondition(it->modes, Mode);
651  if (!ModeMatch) {
652  MACH3LOG_TRACE("Event {}, missed Mode check ({}) for dial {}", iEvent, Mode, it->name);
653  continue;
654  }
655 
656  //Now check whether the norm has kinematic bounds
657  //i.e. does it only apply to events in a particular kinematic region?
658  // Now check whether within kinematic bounds
659  bool IsSelected = PassesSelection((*it), iEvent);
660  // Need to then break the event loop
661  if(!IsSelected){
662  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", iEvent, it->name);
663  continue;
664  }
665  // Now set 'index bin' for each normalisation parameter
666  // All normalisations are just 1 bin for 2015, so bin = index (where index is just the bin for that normalisation)
667  int bin = it->index;
668 
669  NormBins.push_back(bin);
670  MACH3LOG_TRACE("Event {}, will be affected by dial {}", iEvent, it->name);
671  } // end iteration over norm_parameters
672  } // end if (ParHandler)
673  norms_bins[iEvent] = NormBins;
674  }//end loop over events
675 }
#define MACH3LOG_TRACE
Definition: MaCh3Logger.h:33
bool PassesSelection(const ParT &Par, std::size_t iEvent)
unsigned int GetNEvents() const
Return total number of events.
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

◆ CalcWeightFunc()

virtual void SampleHandlerBase::CalcWeightFunc ( [[maybe_unused] ] 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 334 of file SampleHandlerBase.h.

334 {return;};

◆ CalcWeightTotal()

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

Calculate the total weight weight for a given event.

Definition at line 521 of file SampleHandlerBase.cpp.

521  {
522 // ***************************************************************************
523  M3::float_t TotalWeight = 1.0;
524  const int TotalWeights = static_cast<int>(MCEvent->total_weight_pointers.size());
525  //DB Loop over stored pointers
526  #ifdef MULTITHREAD
527  #pragma omp simd reduction(*:TotalWeight)
528  #endif
529  for (int iWeight = 0; iWeight < TotalWeights; ++iWeight) {
530  TotalWeight *= *(MCEvent->total_weight_pointers[iWeight]);
531  }
532 
533  return TotalWeight;
534 }
double float_t
Definition: Core.h:37
std::vector< const M3::float_t * > total_weight_pointers
Pointers to weights like oscillation spline, normalisation etc.
Definition: EventInfo.h:28

◆ CheckEmptyBins()

void SampleHandlerBase::CheckEmptyBins ( ) const

Loop over bins and checks if there are any which have 0 entries.

Definition at line 1980 of file SampleHandlerBase.cpp.

1980  {
1981 // ***************************************************************************
1982  const auto TotalBins = Binning->GetNBins();
1983  int iCounter = 0;
1984  for(int iBin = 0; iBin < TotalBins; iBin++) {
1985  if(SampleHandler_array[iBin] == 0) {
1986  iCounter++;
1987  MACH3LOG_DEBUG("Bin {}, for sample {}, has 0 entries",
1988  Binning->GetBinName(iBin), GetSampleTitle(Binning->GetSampleIndex(iBin)));
1989  }
1990  }
1991 
1992  if(iCounter > 0){
1993  MACH3LOG_WARN("Found in total {} ({:.2f}%) empty bins for SampleHandler: {}",
1994  iCounter, 100.0 * static_cast<double>(iCounter) / TotalBins, GetName());
1995  }
1996 }
std::string GetName() const final
Get name for Sample Handler.
std::vector< double > SampleHandler_array
DB Array to be filled after reweighting.

◆ Fill1DSubEventHist()

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

Fill projection histogram by looping over all events, and skipping one which doesn't pass specified condition.

Definition at line 1416 of file SampleHandlerBase.cpp.

1417  {
1418 // ************************************************
1419  int ProjectionVar_Int = ReturnKinematicVectorFromString(ProjectionVar_Str);
1420 
1421  //JM Loop over all events
1422  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1423  const int EventSample = MCEvents[iEvent].NominalSample;
1424  if(EventSample != iSample) continue;
1425  if (IsEventSelected(EventSample, iEvent)) {
1426  double Weight = GetEventWeight(iEvent);
1427  if (WeightStyle == 1) {
1428  Weight = 1.;
1429  }
1430  std::vector<double> Vec = ReturnKinematicVector(ProjectionVar_Int,iEvent);
1431  size_t nsubevents = Vec.size();
1432  //JM Loop over all subevents in event
1433  for (unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1434  if (IsSubEventSelected(SubEventSelectionVec, iEvent, iSubEvent, nsubevents)) {
1435  double Var = Vec[iSubEvent];
1436  _h1DVar->Fill(Var,Weight);
1437  }
1438  }
1439  }
1440  }
1441 }
M3::float_t GetEventWeight(const int iEvent)
Computes the total event weight for a given entry.
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.
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 
)

Fill projection histogram by looping over all events, and skipping one which doesn't pass specified condition.

Definition at line 1500 of file SampleHandlerBase.cpp.

1504  {
1505 // ************************************************
1506  bool IsSubEventVarX = IsSubEventVarString(ProjectionVar_StrX);
1507  bool IsSubEventVarY = IsSubEventVarString(ProjectionVar_StrY);
1508 
1509  int ProjectionVar_IntX, ProjectionVar_IntY;
1510  if (IsSubEventVarX) ProjectionVar_IntX = ReturnKinematicVectorFromString(ProjectionVar_StrX);
1511  else ProjectionVar_IntX = ReturnKinematicParameterFromString(ProjectionVar_StrX);
1512  if (IsSubEventVarY) ProjectionVar_IntY = ReturnKinematicVectorFromString(ProjectionVar_StrY);
1513  else ProjectionVar_IntY = ReturnKinematicParameterFromString(ProjectionVar_StrY);
1514 
1515  //JM Loop over all events
1516  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1517  const int EventSample = MCEvents[iEvent].NominalSample;
1518  if(EventSample != iSample) continue;
1519  if (IsEventSelected(EventSample, iEvent)) {
1520  double Weight = GetEventWeight(iEvent);
1521  if (WeightStyle == 1) {
1522  Weight = 1.;
1523  }
1524  std::vector<double> VecX = {}, VecY = {};
1525  double VarX = M3::_BAD_DOUBLE_, VarY = M3::_BAD_DOUBLE_;
1526  size_t nsubevents = 0;
1527  // JM Three cases: subeventX vs eventY || eventX vs subeventY || subeventX vs subeventY
1528  if (IsSubEventVarX && !IsSubEventVarY) {
1529  VecX = ReturnKinematicVector(ProjectionVar_IntX, iEvent);
1530  VarY = ReturnKinematicParameter(ProjectionVar_IntY, iEvent);
1531  nsubevents = VecX.size();
1532  }
1533  else if (!IsSubEventVarX && IsSubEventVarY) {
1534  VecY = ReturnKinematicVector(ProjectionVar_IntY, iEvent);
1535  VarX = ReturnKinematicParameter(ProjectionVar_IntX, iEvent);
1536  nsubevents = VecY.size();
1537  }
1538  else {
1539  VecX = ReturnKinematicVector(ProjectionVar_IntX, iEvent);
1540  VecY = ReturnKinematicVector(ProjectionVar_IntY, iEvent);
1541  if (VecX.size() != VecY.size()) {
1542  MACH3LOG_ERROR("Cannot plot {} of size {} against {} of size {}", ProjectionVar_StrX, VecX.size(), ProjectionVar_StrY, VecY.size());
1543  throw MaCh3Exception(__FILE__, __LINE__);
1544  }
1545  nsubevents = VecX.size();
1546  }
1547  //JM Loop over all subevents in event
1548  for (unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1549  if (IsSubEventSelected(SubEventSelectionVec, iEvent, iSubEvent, nsubevents)) {
1550  if (IsSubEventVarX) VarX = VecX[iSubEvent];
1551  if (IsSubEventVarY) VarY = VecY[iSubEvent];
1552  _h2DVar->Fill(VarX,VarY,Weight);
1553  }
1554  }
1555  }
1556  }
1557 }
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 386 of file SampleHandlerBase.cpp.

386  {
387 //************************************************
388  //DB Reset which cuts to apply
390 
391  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
392  ApplyShifts(iEvent);
393  const EventInfo* _restrict_ MCEvent = &MCEvents[iEvent];
394 
395  if (!IsEventSelected(MCEvent->NominalSample, iEvent)) {
396  continue;
397  }
398 
399  // Virtual by default does nothing, has to happen before CalcWeightTotal
400  CalcWeightFunc(iEvent);
401 
402  const M3::float_t totalweight = CalcWeightTotal(MCEvent);
403  //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
404  if (totalweight <= 0.){
405  continue;
406  }
407 
408  //DB Find the relevant bin in the PDF for each event
409  const int GlobalBin = Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
410 
411  //DB Fill relevant part of thread array
412  if (GlobalBin > M3::UnderOverFlowBin) {
413  SampleHandler_array[GlobalBin] += totalweight;
414  if (FirstTimeW2) SampleHandler_array_w2[GlobalBin] += totalweight*totalweight;
415  }
416  }
417 }
#define _restrict_
KS: Using restrict limits the effects of pointer aliasing, aiding optimizations. While reading I foun...
Definition: Core.h:108
std::vector< std::vector< KinematicCut > > StoredSelection
DB Vectors to store which kinematic cuts we apply. Gets used in IsEventSelected Read in from sample y...
virtual void CalcWeightFunc([[maybe_unused]] const int iEvent)
Calculate weights for function parameters.
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.
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.
Definition: EventInfo.h:13

◆ 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 424 of file SampleHandlerBase.cpp.

424  {
425 // ************************************************
426  //DB Reset which cuts to apply
428 
429  // NOTE comment below is left for historical reasons
430  //DB - Brain dump of speedup ideas
431  //
432  //Those relevant to reweighting
433  // 1. Don't bother storing and calculating NC signal events - Implemented and saves marginal s/step
434  // 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
435  // 3. Inline getDiscVar or somehow include that calculation inside the multi-threading - Implemented and saves about 0.01s/step
436  // 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
437  // 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
438  //
439  //Other aspects
440  // 1. Order minituples in Y-axis variable as this will *hopefully* reduce cache misses inside SampleHandler_array_class[yBin][xBin]
441  //
442  // We will hit <0.1 s/step eventually! :D
443  const auto TotalBins = Binning->GetNBins();
444  const unsigned int NumberOfEvents = GetNEvents();
445 
446  double* _restrict_ MC_Array_for_reduction = SampleHandler_array.data();
447  double* _restrict_ W2_array_for_reduction = SampleHandler_array_w2.data();
448 
449  #pragma omp parallel for reduction(+:MC_Array_for_reduction[:TotalBins], W2_array_for_reduction[:TotalBins])
450  for (unsigned int iEvent = 0; iEvent < NumberOfEvents; ++iEvent) {
451  //ETA - generic functions to apply shifts to kinematic variables
452  // Apply this before IsEventSelected is called.
453  ApplyShifts(iEvent);
454 
455  const EventInfo* _restrict_ MCEvent = &MCEvents[iEvent];
456  //ETA - generic functions to apply shifts to kinematic variable
457  if(!IsEventSelected(MCEvent->NominalSample, iEvent)){
458  continue;
459  }
460 
461  // Virtual by default does nothing, has to happen before CalcWeightTotal
462  CalcWeightFunc(iEvent);
463 
464  const M3::float_t totalweight = CalcWeightTotal(MCEvent);
465  //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
466  if (totalweight <= 0.){
467  continue;
468  }
469 
470  //DB Find the relevant bin in the PDF for each event
471  const int GlobalBin = Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
472 
473  //ETA - we can probably remove this final if check on the -1?
474  //Maybe we can add an overflow bin to the array and assign any events to this bin?
475  //Might save us an extra if call?
476  //DB Fill relevant part of thread array
477  if (GlobalBin > M3::UnderOverFlowBin) {
478  MC_Array_for_reduction[GlobalBin] += totalweight;
479  if (FirstTimeW2) W2_array_for_reduction[GlobalBin] += totalweight*totalweight;
480  }
481  }
482 }

◆ 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 274 of file SampleHandlerBase.cpp.

274  {
275 // ************************************************
276  int Dimension = GetNDim(Sample);
277  // DB Commented out by default - Code heading towards GetLikelihood using arrays instead of root objects
278  // Wouldn't actually need this for GetLikelihood as TH objects wouldn't be filled
279  if(Dimension == 1) {
280  Hist->Reset();
281  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
282  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin});
283  Hist->SetBinContent(xBin + 1, Array[idx]);
284  }
285  } else if (Dimension == 2) {
286  Hist->Reset();
287  if(Binning->IsUniform(Sample)) {
288  for (int yBin = 0; yBin < Binning->GetNAxisBins(Sample, 1); ++yBin) {
289  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
290  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
291  Hist->SetBinContent(xBin + 1, yBin + 1, Array[idx]);
292  }
293  }
294  } else {
295  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
296  const int idx = iBin + Binning->GetSampleStartBin(Sample);
297  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
298  Hist->SetBinContent(iBin + 1, Array[idx]);
299  }
300  }
301  } else {
302  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
303  const int idx = iBin + Binning->GetSampleStartBin(Sample);
304  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
305  Hist->SetBinContent(iBin + 1, Array[idx]);
306  }
307  }
308 }

◆ FinaliseShifts()

virtual void SampleHandlerBase::FinaliseShifts ( [[maybe_unused] ] const int  iEvent)
inlineprotectedvirtual

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

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

314 {};

◆ FindNominalBinAndEdges()

void SampleHandlerBase::FindNominalBinAndEdges ( )
protected

Functions which find the nominal bin and bin edges.

Definition at line 787 of file SampleHandlerBase.cpp.

787  {
788 // ************************************************
789  for (unsigned int event_i = 0; event_i < GetNEvents(); event_i++) {
790  int Sample = MCEvents[event_i].NominalSample;
791  const int dim = GetNDim(Sample);
792  MCEvents[event_i].KinVar.resize(dim);
793  MCEvents[event_i].NomBin.resize(dim);
794 
795  auto SetNominalBin = [&](int bin, int max_bins, int& out_bin) {
796  if (bin >= 0 && bin < max_bins) {
797  out_bin = bin;
798  } else {
799  out_bin = M3::UnderOverFlowBin; // Out of bounds
800  }
801  };
802 
803  // Find nominal bin for each dimension
804  for(int iDim = 0; iDim < dim; iDim++) {
805  MCEvents[event_i].KinVar[iDim] = GetPointerToKinematicParameter(GetKinVarName(Sample, iDim), event_i);
806  if (std::isnan(*MCEvents[event_i].KinVar[iDim]) || std::isinf(*MCEvents[event_i].KinVar[iDim])) {
807  MACH3LOG_ERROR("Variable {} for sample {} and dimension {} is ill-defined and equal to {}",
808  GetKinVarName(Sample, iDim), GetSampleTitle(Sample), dim, *MCEvents[event_i].KinVar[iDim]);
809  throw MaCh3Exception(__FILE__, __LINE__);
810  }
811  const int bin = Binning->FindNominalBin(Sample, iDim, *MCEvents[event_i].KinVar[iDim]);
812  int NBins_i = static_cast<int>(Binning->GetBinEdges(Sample, iDim).size() - 1);
813  SetNominalBin(bin, NBins_i, MCEvents[event_i].NomBin[iDim]);
814  }
815  }
816 }
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

Return 1D projection of MC into given 1D variable (doesn't have to be variable used in the fit)

Parameters
iSampleIndex of the sample.
ProjectionVarname of variable
EventSelectionVecVector of additional cuts like cut on interaction mode
WeightStyleAlow to modify weight for example if equal to 1 all weights are set to 1
SubEventSelectionVecVector of additional cuts for sub event (particle, ring etc.)

Implements SampleHandlerInterface.

Definition at line 1373 of file SampleHandlerBase.cpp.

1376  {
1377 // ************************************************
1378  //DB Need to overwrite the Selection member variable so that IsEventSelected function operates correctly.
1379  // Consequently, store the selection cuts already saved in the sample, overwrite the Selection variable, then reset
1380  auto tmp_Selection = ApplyTemporarySelection(iSample, EventSelectionVec);
1381 
1382  //DB Define the histogram which will be returned
1383  std::vector<double> xBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_Str);
1384  auto _h1DVar = std::make_unique<TH1D>("", "", int(xBinEdges.size())-1, xBinEdges.data());
1385  _h1DVar->SetDirectory(nullptr);
1386  _h1DVar->GetXaxis()->SetTitle(ProjectionVar_Str.c_str());
1387  _h1DVar->GetYaxis()->SetTitle("Events");
1388 
1389  if (IsSubEventVarString(ProjectionVar_Str)) {
1390  Fill1DSubEventHist(iSample, _h1DVar.get(), ProjectionVar_Str, SubEventSelectionVec, WeightStyle);
1391  } else {
1392  //DB Grab the associated enum with the argument string
1393  int ProjectionVar_Int = ReturnKinematicParameterFromString(ProjectionVar_Str);
1394 
1395  //DB Loop over all events
1396  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1397  const int EventSample = MCEvents[iEvent].NominalSample;
1398  if(EventSample != iSample) continue;
1399  if (IsEventSelected(EventSample, iEvent)) {
1400  double Weight = GetEventWeight(iEvent);
1401  if (WeightStyle == 1) {
1402  Weight = 1.;
1403  }
1404  double Var = ReturnKinematicParameter(ProjectionVar_Int, iEvent);
1405  _h1DVar->Fill(Var, Weight);
1406  }
1407  }
1408  }
1409  //DB Reset the saved selection
1410  Selection = tmp_Selection;
1411 
1412  return _h1DVar;
1413 }
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)
Fill projection histogram by looping over all events, and skipping one which doesn't pass specified c...
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

Build a 1D histogram for a given variable, optionally filtered by mode and channel.

Parameters
iSampleIndex of the sample.
ProjectionVar_StrName of the variable to project onto.
kModeToFillInteraction mode to select (-1 means all modes).
kChannelToFillOscillation channel to select (-1 means all channels).
WeightStyleWeighting scheme (e.g. 0 = nominal weights, 1 = unit weights).

Implements SampleHandlerInterface.

Definition at line 1735 of file SampleHandlerBase.cpp.

1736  {
1737 // ************************************************
1738  auto SelectionVec = BuildModeChannelSelection(iSample, kModeToFill, kChannelToFill);
1739  return Get1DVarHist(iSample, ProjectionVar_Str, SelectionVec, WeightStyle);
1740 }
std::vector< KinematicCut > BuildModeChannelSelection(const int iSample, const int kModeToFill, const int kChannelToFill) const
Construct vector of kinematic cuts that will be applied, on top of default cuts include stuff like cu...
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
Return 1D projection of MC into given 1D variable (doesn't have to be variable used in the fit)

◆ 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

Build a 2D projection of MC events into specified variables.

Parameters
iSampleIndex of the sample.
ProjectionVarXName of the variable for the X axis.
ProjectionVarYName of the variable for the Y axis.
EventSelectionVecVector of event-level selection cuts.
WeightStyleWeighting scheme (e.g. 0 = nominal weights, 1 = unit weights).
SubEventSelectionVecVector of sub-event selection cuts.

Implements SampleHandlerInterface.

Definition at line 1444 of file SampleHandlerBase.cpp.

1449  {
1450 // ************************************************
1451  //DB Need to overwrite the Selection member variable so that IsEventSelected function operates correctly.
1452  // Consequently, store the selection cuts already saved in the sample, overwrite the Selection variable, then reset
1453  auto tmp_Selection = ApplyTemporarySelection(iSample, EventSelectionVec);
1454 
1455  //DB Define the histogram which will be returned
1456  //KS: If we use 2D non uniform binning and wanting to plot fit variables use TH2Poly everything else uses TH2D with binning from config
1457  std::unique_ptr<TH2> _h2DVar;
1458  if(GetNDim(iSample) == 2 && !Binning->IsUniform(iSample) &&
1459  ProjectionVar_StrX == GetKinVarName(iSample, 0) && ProjectionVar_StrY == GetKinVarName(iSample, 1) ) {
1460  _h2DVar = std::unique_ptr<TH2>(static_cast<TH2*>(M3::Clone(GetMCHist(iSample)).release()));
1461  } else {
1462  std::vector<double> xBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_StrX);
1463  std::vector<double> yBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_StrY);
1464  _h2DVar = std::make_unique<TH2D>("", "", int(xBinEdges.size())-1, xBinEdges.data(), int(yBinEdges.size())-1, yBinEdges.data());
1465  }
1466  _h2DVar->SetDirectory(nullptr);
1467  _h2DVar->GetXaxis()->SetTitle(ProjectionVar_StrX.c_str());
1468  _h2DVar->GetYaxis()->SetTitle(ProjectionVar_StrY.c_str());
1469  _h2DVar->GetZaxis()->SetTitle("Events");
1470 
1471  bool IsSubEventHist = IsSubEventVarString(ProjectionVar_StrX) || IsSubEventVarString(ProjectionVar_StrY);
1472  if (IsSubEventHist) Fill2DSubEventHist(iSample, _h2DVar.get(), ProjectionVar_StrX, ProjectionVar_StrY, SubEventSelectionVec, WeightStyle);
1473  else {
1474  //DB Grab the associated enum with the argument string
1475  int ProjectionVar_IntX = ReturnKinematicParameterFromString(ProjectionVar_StrX);
1476  int ProjectionVar_IntY = ReturnKinematicParameterFromString(ProjectionVar_StrY);
1477 
1478  //DB Loop over all events
1479  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1480  const int EventSample = MCEvents[iEvent].NominalSample;
1481  if(EventSample != iSample) continue;
1482  if (IsEventSelected(EventSample, iEvent)) {
1483  double Weight = GetEventWeight(iEvent);
1484  if (WeightStyle == 1) {
1485  Weight = 1.;
1486  }
1487  double VarX = ReturnKinematicParameter(ProjectionVar_IntX, iEvent);
1488  double VarY = ReturnKinematicParameter(ProjectionVar_IntY, iEvent);
1489  _h2DVar->Fill(VarX,VarY,Weight);
1490  }
1491  }
1492  }
1493  //DB Reset the saved selection
1494  Selection = tmp_Selection;
1495 
1496  return _h2DVar;
1497 }
void Fill2DSubEventHist(const int iSample, TH2 *_h2DVar, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &SubEventSelectionVec={}, int WeightStyle=0)
Fill projection histogram by looping over all events, and skipping one which doesn't pass specified c...
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

Build a 2D histogram for given variables, optionally filtered by mode and channel.

Parameters
iSampleIndex of the sample.
ProjectionVar_StrXName of the variable for the X axis.
ProjectionVar_StrYName of the variable for the Y axis.
kModeToFillInteraction mode to select (-1 means all modes).
kChannelToFillOscillation channel to select (-1 means all channels).
WeightStyleWeighting scheme (e.g. 0 = nominal weights, 1 = unit weights).

Implements SampleHandlerInterface.

Definition at line 1743 of file SampleHandlerBase.cpp.

1745  {
1746 // ************************************************
1747  auto SelectionVec = BuildModeChannelSelection(iSample, kModeToFill, kChannelToFill);
1748  return Get2DVarHist(iSample, ProjectionVar_StrX, ProjectionVar_StrY, SelectionVec, WeightStyle);
1749 }
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
Build a 2D projection of MC events into specified variables.

◆ 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 2062 of file SampleHandlerBase.cpp.

2062  {
2063 // ***************************************************************************
2064  const int Start = Binning->GetSampleStartBin(Sample);
2065  const int End = Binning->GetSampleEndBin(Sample);
2066 
2067  return std::vector<double>(array.begin() + Start, array.begin() + End);
2068 }

◆ GetDataArray() [1/2]

auto SampleHandlerBase::GetDataArray ( ) const
inline

Return array storing data entries for every bin.

Definition at line 179 of file SampleHandlerBase.h.

179  {
180  return SampleHandler_data;
181  }

◆ GetDataArray() [2/2]

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

Return array storing data entries for every bin.

Parameters
SampleSample index

Definition at line 195 of file SampleHandlerBase.h.

195  {
196  return GetArrayForSample(Sample, SampleHandler_data);
197  }
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.

Parameters
SampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 867 of file SampleHandlerBase.cpp.

867  {
868 // ************************************************
869  if(SampleDetails[Sample].DataHist == nullptr) {
870  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
871  throw MaCh3Exception(__FILE__, __LINE__);
872  }
873  return SampleDetails[Sample].DataHist;
874 }

◆ GetDataHist() [2/2]

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

Get Data histogram by sample name.

Parameters
SampleSample title

Definition at line 877 of file SampleHandlerBase.cpp.

877  {
878 // ************************************************
879  int Index = GetSampleIndex(Sample);
880  return GetDataHist(Index);
881 }
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  iEvent)

Computes the total event weight for a given entry.

Parameters
iEventEvent enumerator

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 1122 of file SampleHandlerBase.cpp.

1122  {
1123 // ************************************************
1125 
1126  // Virtual by default does nothing, has to happen before CalcWeightTotal
1127  CalcWeightFunc(iEntry);
1128 
1129  const EventInfo* _restrict_ MCEvent = &MCEvents[iEntry];
1130  M3::float_t totalweight = CalcWeightTotal(MCEvent);
1131 
1132  //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
1133  if (totalweight <= 0.){
1134  totalweight = 0.;
1135  }
1136  return totalweight;
1137 }

◆ 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 458 of file SampleHandlerBase.h.

458 {return FileToFinalPDGMap.at(FileName);}
std::unordered_map< std::string, NuPDG > FileToFinalPDGMap
Mapping from input file names to final neutrino PDG codes.

◆ GetFlavourName()

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

Get the flavour name for a given sample and oscillation channel.

Parameters
iSampleIndex of the sample.
iChannelIndex of the oscillation channel within the sample.

Implements SampleHandlerInterface.

Definition at line 109 of file SampleHandlerBase.h.

109  {
110  if (iChannel < 0 || iChannel > GetNOscChannels(iSample)) {
111  MACH3LOG_ERROR("Invalid Channel Requested: {}", iChannel);
112  throw MaCh3Exception(__FILE__ , __LINE__);
113  }
114  return SampleDetails[iSample].OscChannels[iChannel].flavourName;
115  }

◆ 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 456 of file SampleHandlerBase.h.

456 {return FileToInitPDGMap.at(FileName);}
std::unordered_map< std::string, NuPDG > FileToInitPDGMap
Mapping from input file names to initial neutrino PDG codes.

◆ 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 2052 of file SampleHandlerBase.cpp.

2052  {
2053 // ***************************************************************************
2054  if(Dimension > GetNDim(iSample)) {
2055  MACH3LOG_ERROR("Asking for dimension {}, while sample: {} only has {}", Dimension, GetSampleTitle(iSample), GetNDim(iSample));
2056  throw MaCh3Exception(__FILE__, __LINE__);
2057  }
2058  return SampleDetails[iSample].VarStr[Dimension];
2059 }

◆ GetLikelihood()

double SampleHandlerBase::GetLikelihood ( ) const
overridevirtual

Return likelihood (-LogL) for all samples.

Implements SampleHandlerInterface.

Definition at line 1238 of file SampleHandlerBase.cpp.

1238  {
1239 // ************************************************
1240  double negLogL = 0.;
1241  #ifdef MULTITHREAD
1242  #pragma omp parallel for reduction(+:negLogL)
1243  #endif
1244  for (int idx = 0; idx < Binning->GetNBins(); ++idx)
1245  {
1246  double const &DataVal = SampleHandler_data[idx];
1247  double const &MCPred = SampleHandler_array[idx];
1248  double const &w2 = SampleHandler_array_w2[idx];
1249 
1250  //KS: Calculate likelihood using Barlow-Beeston Poisson or even IceCube
1251  negLogL += GetTestStatLLH(DataVal, MCPred, w2);
1252  }
1253  return negLogL;
1254 }
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 183 of file SampleHandlerBase.h.

183  {
184  return SampleHandler_array;
185  }

◆ GetMCArray() [2/2]

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

Return array storing MC entries for every bin.

Parameters
SampleSample index

Definition at line 200 of file SampleHandlerBase.h.

200  {
201  return GetArrayForSample(Sample, SampleHandler_array);
202  }

◆ GetMCHist() [1/2]

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

Get MC histogram.

Parameters
SampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 849 of file SampleHandlerBase.cpp.

849  {
850 // ************************************************
851  FillHist(Sample, SampleDetails[Sample].MCHist, SampleHandler_array);
852  if(SampleDetails[Sample].MCHist == nullptr) {
853  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
854  throw MaCh3Exception(__FILE__, __LINE__);
855  }
856  return SampleDetails[Sample].MCHist;
857 }

◆ GetMCHist() [2/2]

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

Get MC histogram by sample title.

Parameters
SampleSample name

Definition at line 860 of file SampleHandlerBase.cpp.

860  {
861 // ************************************************
862  const int Index = GetSampleIndex(Sample);
863  return GetMCHist(Index);
864 }

◆ GetName()

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

Get name for Sample Handler.

Implements SampleHandlerInterface.

Definition at line 1109 of file SampleHandlerBase.cpp.

1109  {
1110 // ************************************************
1111  //ETA - extra safety to make sure SampleHandlerName is actually set
1112  // probably unnecessary due to the requirement for it to be in the yaml config
1113  if(SampleHandlerName.length() == 0) {
1114  MACH3LOG_ERROR("No sample name provided");
1115  MACH3LOG_ERROR("Please provide a SampleHandlerName in your configuration file: {}", SampleManager->GetFileName());
1116  throw MaCh3Exception(__FILE__, __LINE__);
1117  }
1118  return SampleHandlerName;
1119 }

◆ 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 47 of file SampleHandlerBase.h.

47 { return SampleDetails[Sample].nDimensions; }

◆ GetNEvents()

unsigned int SampleHandlerBase::GetNEvents ( ) const
inline

Return total number of events.

Definition at line 176 of file SampleHandlerBase.h.

176 {return nEvents;}

◆ GetNOscChannels()

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

Get number of oscillation channels for a single sample.

Parameters
iSampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 107 of file SampleHandlerBase.h.

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

◆ GetNuOscillatorPointers()

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

Get pointer to NuOscillator weight for a given event.

Parameters
iEventEvent enumerator

Definition at line 1069 of file SampleHandlerBase.cpp.

1069  {
1070 // ************************************************
1071  const M3::float_t* osc_w_pointer = &M3::Unity;
1072  if (MCEvents[iEvent].isNC) {
1073  if (MCEvents[iEvent].nupdg != MCEvents[iEvent].nupdgUnosc) {
1074  osc_w_pointer = &M3::Zero;
1075  } else {
1076  osc_w_pointer = &M3::Unity;
1077  }
1078  } else {
1079  int InitFlav = M3::_BAD_INT_;
1080  int FinalFlav = M3::_BAD_INT_;
1081 
1082  InitFlav = M3::Utils::PDGToNuOscillatorFlavour(MCEvents[iEvent].nupdgUnosc);
1083  FinalFlav = M3::Utils::PDGToNuOscillatorFlavour(MCEvents[iEvent].nupdg);
1084 
1085  if (InitFlav == M3::_BAD_INT_ || FinalFlav == M3::_BAD_INT_) {
1086  MACH3LOG_ERROR("Something has gone wrong in the mapping between MCEvents.nutype and the enum used within NuOscillator");
1087  MACH3LOG_ERROR("MCEvents.nupdgUnosc: {}", MCEvents[iEvent].nupdgUnosc);
1088  MACH3LOG_ERROR("InitFlav: {}", InitFlav);
1089  MACH3LOG_ERROR("MCEvents.nupdg: {}", MCEvents[iEvent].nupdg);
1090  MACH3LOG_ERROR("FinalFlav: {}", FinalFlav);
1091  throw MaCh3Exception(__FILE__, __LINE__);
1092  }
1093  const int Sample = MCEvents[iEvent].NominalSample;
1094 
1095  const int OscIndex = GetOscChannel(SampleDetails[Sample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1096  //Can only happen if truecz has been initialised within the experiment specific code
1097  if (MCEvents[iEvent].coszenith_true != M3::_BAD_DOUBLE_) {
1098  //Atmospherics
1099  osc_w_pointer = Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(MCEvents[iEvent].enu_true), FLOAT_T(MCEvents[iEvent].coszenith_true));
1100  } else {
1101  //Beam
1102  osc_w_pointer = Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(MCEvents[iEvent].enu_true));
1103  }
1104  } // end if NC
1105  return osc_w_pointer;
1106 }
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.
Definition: SampleInfo.h:28
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 354 of file SampleHandlerBase.h.

354  {
355  return GetPointerToKinematicParameter(ReturnKinematicParameterFromString(KinematicParameter), iEvent);
356  }

◆ 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 1972 of file SampleHandlerBase.cpp.

1972  {
1973 // ************************************************
1974  auto& OscillationChannels = SampleDetails[MCEvents[iEvent].NominalSample].OscChannels;
1975  const int Channel = GetOscChannel(OscillationChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1976  return &(OscillationChannels[Channel].ChannelIndex);
1977 }

◆ GetRangeForPlotType()

int SampleHandlerBase::GetRangeForPlotType ( const SamplePlotType  TypeEnum,
const int  iSample 
) const

KS: Return range for plot type, for example number of modes, osc channels etc.

Parameters
TypeEnumPlot type enumerator see SamplePlotType
iSampleSample enumerator

Definition at line 1895 of file SampleHandlerBase.cpp.

1895  {
1896 // ************************************************
1897  switch (TypeEnum) {
1899  return Modes->GetNModes();
1900  break;
1902  return GetNOscChannels(iSample);
1903  break;
1904  default:
1905  MACH3LOG_ERROR("You've passed me a SamplePlotType with value {} which was not implemented.", static_cast<int>(TypeEnum));
1906  throw MaCh3Exception(__FILE__, __LINE__);
1907  }
1908 }
@ kOscChannelPlot
@ kModePlot

◆ 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 819 of file SampleHandlerBase.cpp.

819  {
820 // ************************************************
821  for (M3::int_t iSample = 0; iSample < nSamples; ++iSample) {
822  if (SampleTitle == GetSampleTitle(iSample)) {
823  return iSample;
824  }
825  }
826  MACH3LOG_ERROR("Sample name not found: {}", SampleTitle);
827  throw MaCh3Exception(__FILE__, __LINE__);
828 }
int int_t
Definition: Core.h:38

◆ GetSampleLikelihood()

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

Get likelihood (-logL) for a single sample.

Parameters
iSampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 1216 of file SampleHandlerBase.cpp.

1216  {
1217 // ************************************************
1218  const int Start = Binning->GetSampleStartBin(isample);
1219  const int End = Binning->GetSampleEndBin(isample);
1220 
1221  double negLogL = 0.;
1222  #ifdef MULTITHREAD
1223  #pragma omp parallel for reduction(+:negLogL)
1224  #endif
1225  for (int idx = Start; idx < End; ++idx)
1226  {
1227  double const &DataVal = SampleHandler_data[idx];
1228  double const &MCPred = SampleHandler_array[idx];
1229  double const &w2 = SampleHandler_array_w2[idx];
1230 
1231  //KS: Calculate likelihood using Barlow-Beeston Poisson or even IceCube
1232  negLogL += GetTestStatLLH(DataVal, MCPred, w2);
1233  }
1234  return negLogL;
1235 }

◆ GetSampleName()

std::string SampleHandlerBase::GetSampleName ( const int  Sample) const
inline

Sample name tag used only for getting relevant uncertainties.

Parameters
SampleIndex of the sample.

Definition at line 54 of file SampleHandlerBase.h.

54 {return SampleDetails[Sample].SampleName;}

◆ GetSampleTitle()

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

Get fancy title for specified samples.

Parameters
iSampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 51 of file SampleHandlerBase.h.

51 {return SampleDetails[Sample].SampleTitle;}

◆ GetSplineBins()

std::vector< SplineIndex > 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 1140 of file SampleHandlerBase.cpp.

1140  {
1141 // ************************************************
1142  const int SampleIndex = MCEvents[Event].NominalSample;
1143  const auto SampleTitle = GetSampleTitle(SampleIndex);
1144  bool NoOscChannels = false;
1145  if(Oscillator == nullptr && GetNOscChannels(SampleIndex) == 1) {
1146  MACH3LOG_DEBUG("Assuming there are no osc channels in {}", __func__);
1147  NoOscChannels = true;
1148  }
1149  const int OscIndex = NoOscChannels ? 0 : GetOscChannel(SampleDetails[SampleIndex].OscChannels,
1150  MCEvents[Event].nupdgUnosc, MCEvents[Event].nupdg);
1151  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", Event)));
1152  const double Etrue = MCEvents[Event].enu_true;
1153  std::vector< SplineIndex > EventSplines;
1154  switch(GetNDim(SampleIndex)) {
1155  case 1:
1156  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(MCEvents[Event].KinVar[0]), 0.);
1157  break;
1158  case 2:
1159  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(MCEvents[Event].KinVar[0]), *(MCEvents[Event].KinVar[1]));
1160  break;
1161  default:
1162  if(ThrowCrititcal) {
1163  MACH3LOG_CRITICAL("MaCh3 doesn't support binned splines for more than 2D while you use {}", GetNDim(SampleIndex));
1164  MACH3LOG_CRITICAL("Will use 2D like approach");
1165  ThrowCrititcal = false;
1166  }
1167  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(MCEvents[Event].KinVar[0]), *(MCEvents[Event].KinVar[1]));
1168  break;
1169  }
1170  return EventSplines;
1171 }
std::vector< SplineIndex > 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 187 of file SampleHandlerBase.h.

187  {
188  return SampleHandler_array_w2;
189  }

◆ GetW2Array() [2/2]

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

Return array storing W2 entries for single sample.

Parameters
SampleSample index

Definition at line 205 of file SampleHandlerBase.h.

205  {
207  }

◆ GetW2Hist() [1/2]

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

Get W2 histogram.

Parameters
SampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 831 of file SampleHandlerBase.cpp.

831  {
832 // ************************************************
833  FillHist(Sample, SampleDetails[Sample].W2Hist, SampleHandler_array_w2);
834  if(SampleDetails[Sample].W2Hist == nullptr) {
835  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
836  throw MaCh3Exception(__FILE__, __LINE__);
837  }
838  return SampleDetails[Sample].W2Hist;
839 }

◆ GetW2Hist() [2/2]

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

Get W2 histogram by sample name.

Parameters
SampleSample title

Definition at line 842 of file SampleHandlerBase.cpp.

842  {
843 // ************************************************
844  const int Index = GetSampleIndex(Sample);
845  return GetW2Hist(Index);
846 }
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 198 of file SampleHandlerBase.cpp.

198  {
199 // ************************************************
200  TStopwatch clock;
201  clock.Start();
202 
203  //First grab all the information from your sample config via your manager
204  ReadConfig();
205 
206  //Now initialise all the variables you will need
207  Init();
208 
210  MCEvents.resize(nEvents);
211  SetupMC();
212 
213  MACH3LOG_INFO("=============================================");
214  MACH3LOG_INFO("Total number of events is: {}", GetNEvents());
216  MACH3LOG_INFO("Setting up Sample Binning..");
217  SetBinning();
218  MACH3LOG_INFO("Setting up Splines..");
219  SetupSplines();
220  MACH3LOG_INFO("Setting up Normalisation Pointers..");
222  MACH3LOG_INFO("Setting up Functional Pointers..");
224  MACH3LOG_INFO("Setting up Additional Weight Pointers..");
226  MACH3LOG_INFO("Setting up Kinematic Map..");
228  clock.Stop();
229  MACH3LOG_INFO("Finished loading MC for {}, it took {:.2f}s to finish", GetName(), clock.RealTime());
230  MACH3LOG_INFO("Initialising Data");
232  MACH3LOG_INFO("=======================================================");
233  CheckEmptyBins();
234 }
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.
void CheckEmptyBins() const
Loop over bins and checks if there are any which have 0 entries.
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 conveniently setup everything ...
virtual void RegisterFunctionalParameters()
HH - a experiment-specific function where the maps to actual functions are set 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.
void SetupOscParameters()
Setup the osc parameters.

◆ InitialiseNuOscillatorObjects()

void SampleHandlerBase::InitialiseNuOscillatorObjects ( )
protected

including Dan's magic NuOscillator

Definition at line 976 of file SampleHandlerBase.cpp.

976  {
977 // ************************************************
978  auto NuOscillatorConfigFile = Get<std::string>(SampleManager->raw()["NuOsc"]["NuOscConfigFile"], __FILE__ , __LINE__);
979  auto EqualBinningPerOscChannel = Get<bool>(SampleManager->raw()["NuOsc"]["EqualBinningPerOscChannel"], __FILE__ , __LINE__);
980 
981  // TN override the sample setting if not using binned oscillation
982  if (EqualBinningPerOscChannel) {
983  if (YAML::LoadFile(NuOscillatorConfigFile)["General"]["CalculationType"].as<std::string>() == "Unbinned") {
984  MACH3LOG_WARN("Tried using EqualBinningPerOscChannel while using Unbinned oscillation calculation, changing EqualBinningPerOscChannel to false");
985  EqualBinningPerOscChannel = false;
986  }
987  }
988  // get osc params for sample 0, later we check all have same number
989  std::vector<const M3::float_t*> OscParams = ParHandler->GetOscParsFromSampleName(GetSampleName(0));
990  if (OscParams.empty()) {
991  MACH3LOG_ERROR("OscParams is empty for sample '{}'.", GetName());
992  MACH3LOG_ERROR("This likely indicates an error in your oscillation YAML configuration.");
993  throw MaCh3Exception(__FILE__, __LINE__);
994  }
995 
996  for(int iSample = 1; iSample < GetNSamples(); iSample++) {
997  auto OscParamsCrossCheck = ParHandler->GetOscParsFromSampleName(GetSampleName(iSample));
998  if (OscParamsCrossCheck.size() != OscParams.size()) {
999  MACH3LOG_ERROR("Sample {} has {} osc params while sample {} has {}",
1000  GetSampleTitle(iSample), OscParamsCrossCheck.size(), 0, GetSampleTitle(0));
1001  throw MaCh3Exception(__FILE__, __LINE__);
1002  }
1003  }
1004  Oscillator = std::make_shared<OscillationHandler>(NuOscillatorConfigFile, EqualBinningPerOscChannel, OscParams, GetNOscChannels(0));
1005  // Add samples only if we don't use same binning
1006  if(!EqualBinningPerOscChannel) {
1007  // KS: Start from 1 because sample 0 already added
1008  for(int iSample = 1; iSample < GetNSamples(); iSample++) {
1009  Oscillator->AddSample(NuOscillatorConfigFile, GetNOscChannels(iSample));
1010  }
1011  for(int iSample = 0; iSample < GetNSamples(); iSample++) {
1012  for(int iChannel = 0; iChannel < GetNOscChannels(iSample); iChannel++) {
1013  std::vector<M3::float_t> EnergyArray;
1014  std::vector<M3::float_t> CosineZArray;
1015 
1016 #pragma GCC diagnostic push
1017 #pragma GCC diagnostic ignored "-Wuseless-cast"
1018  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1019  if(MCEvents[iEvent].NominalSample != iSample) continue;
1020  // 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
1021  const int Channel = GetOscChannel(SampleDetails[MCEvents[iEvent].NominalSample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1022  //DB Remove NC events from the arrays which are handed to the NuOscillator objects
1023  if (!MCEvents[iEvent].isNC && Channel == iChannel) {
1024  EnergyArray.push_back(M3::float_t(MCEvents[iEvent].enu_true));
1025  }
1026  }
1027  std::sort(EnergyArray.begin(),EnergyArray.end());
1028 
1029  //============================================================================
1030  //DB Atmospheric only part, can only happen if truecz has been initialised within the experiment specific code
1031  if (MCEvents[0].coszenith_true != M3::_BAD_DOUBLE_) {
1032  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1033  if(MCEvents[iEvent].NominalSample != iSample) continue;
1034  // 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
1035  const int Channel = GetOscChannel(SampleDetails[MCEvents[iEvent].NominalSample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1036  //DB Remove NC events from the arrays which are handed to the NuOscillator objects
1037  if (!MCEvents[iEvent].isNC && Channel == iChannel) {
1038  CosineZArray.push_back(M3::float_t(MCEvents[iEvent].coszenith_true));
1039  }
1040  }
1041  std::sort(CosineZArray.begin(),CosineZArray.end());
1042  }
1043 #pragma GCC diagnostic pop
1044  Oscillator->SetOscillatorBinning(iSample, iChannel, EnergyArray, CosineZArray);
1045  } // end loop over channels
1046  } // end loop over samples
1047  }
1048 }
std::vector< const M3::float_t * > GetOscParsFromSampleName(const std::string &SampleName) const
Get pointers to Osc params from Sample name.
std::string GetSampleName(const int Sample) const
Sample name tag used only for getting relevant uncertainties.
virtual M3::int_t GetNSamples()
returns total number of samples

◆ InitialiseSplineObject()

void SampleHandlerBase::InitialiseSplineObject ( )
protected

Setup spline handler (both binned or unbinned)

Definition at line 1303 of file SampleHandlerBase.cpp.

1303  {
1304 // ************************************************
1305  if(auto BinnedSplines = dynamic_cast<BinnedSplineHandler*>(SplineHandler.get())) {
1306  bool LoadSplineFile = GetFromManager<bool>(SampleManager->raw()["InputFiles"]["LoadSplineFile"], false, __FILE__, __LINE__);
1307  bool PrepSplineFile = GetFromManager<bool>(SampleManager->raw()["InputFiles"]["PrepSplineFile"], false, __FILE__, __LINE__);
1308  auto SplineFileName = GetFromManager<std::string>(SampleManager->raw()["InputFiles"]["SplineFileName"],
1309  (SampleHandlerName + "_SplineFile.root"), __FILE__, __LINE__);
1310  if(!LoadSplineFile) {
1311  for(int iSample = 0; iSample < GetNSamples(); iSample++) {
1312  std::vector<std::string> spline_filepaths = SampleDetails[iSample].spline_files;
1313 
1314  //Keep a track of the spline variables
1315  std::vector<std::string> SplineVarNames = {"TrueNeutrinoEnergy"};
1316  if (GetNDim(iSample) == 1) {
1317  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1318  } else if (GetNDim(iSample) == 2) {
1319  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1320  SplineVarNames.push_back(GetKinVarName(iSample, 1));
1321  } else {
1322  MACH3LOG_CRITICAL("{} Not implemented for dimension {}, will use 2D", __func__, GetNDim(iSample));
1323  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1324  SplineVarNames.push_back(GetKinVarName(iSample, 1));
1325  }
1326  BinnedSplines->AddSample(GetSampleName(iSample), GetSampleTitle(iSample), spline_filepaths, SplineVarNames);
1327  }
1328  BinnedSplines->CountNumberOfLoadedSplines(false, 1);
1329  BinnedSplines->TransferToMonolith();
1330  if(PrepSplineFile) BinnedSplines->PrepareSplineFile(SplineFileName);
1331  } else {
1332  // KS: Skip default spline loading and use flattened spline format allowing to read stuff much faster
1333  BinnedSplines->LoadSplineFile(SplineFileName);
1334  }
1335  MACH3LOG_INFO("--------------------------------");
1336  MACH3LOG_INFO("Setup Far Detector splines");
1337 
1339 
1340  BinnedSplines->CleanUpMemory();
1341  } else if (auto UnbinnedSpline = dynamic_cast<UnbinnedSplineHandler*>(SplineHandler.get())) {
1342  (void) UnbinnedSpline;
1344  } else {
1345  MACH3LOG_ERROR("Unsupported spline type encountered.");
1346  throw MaCh3Exception(__FILE__, __LINE__);
1347  }
1348 }
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 313 of file SampleHandlerBase.cpp.

313  {
314 // ************************************************
315  const auto& SampleSelection = Selection[iSample];
316  const int SelectionSize = static_cast<int>(SampleSelection.size());
317  for (int iSelection = 0; iSelection < SelectionSize; ++iSelection) {
318  const auto& Cut = SampleSelection[iSelection];
319  const double Val = ReturnKinematicParameter(Cut.ParamToCutOnIt, iEvent);
320  if ((Val < Cut.LowerBound) || (Val >= Cut.UpperBound)) {
321  return false;
322  }
323  }
324  //DB To avoid unnecessary checks, now return false rather than setting bool to true and continuing to check
325  return true;
326 }

◆ 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 329 of file SampleHandlerBase.cpp.

329  {
330  for (unsigned int iSelection=0;iSelection < SubEventCuts.size() ;iSelection++) {
331  std::vector<double> Vec = ReturnKinematicVector(SubEventCuts[iSelection].ParamToCutOnIt, iEvent);
332  if (nsubevents != Vec.size()) {
333  MACH3LOG_ERROR("Cannot apply kinematic cut on {} as it is of different size to plotting variable");
334  throw MaCh3Exception(__FILE__, __LINE__);
335  }
336  const double Val = Vec[iSubEvent];
337  if ((Val < SubEventCuts[iSelection].LowerBound) || (Val >= SubEventCuts[iSelection].UpperBound)) {
338  return false;
339  }
340  }
341  //DB To avoid unnecessary checks, now return false rather than setting bool to true and continuing to check
342  return true;
343 }

◆ 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 1669 of file SampleHandlerBase.cpp.

1669  {
1670 // ************************************************
1671  if (KinematicVectors == nullptr) return false;
1672 
1673  if (KinematicVectors->count(VarStr)) {
1674  if (!KinematicParameters->count(VarStr)) return true;
1675  else {
1676  MACH3LOG_ERROR("Attempted to plot kinematic variable {}, but it appears in both KinematicVectors and KinematicParameters", VarStr);
1677  throw MaCh3Exception(__FILE__,__LINE__);
1678  }
1679  }
1680  return false;
1681 }

◆ LoadSingleSample()

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

Initialise single sample from config file.

Add new sample

Definition at line 114 of file SampleHandlerBase.cpp.

114  {
115 // ************************************************
116  SampleInfo SingleSample;
117  //SampleTitle has to be provided in the sample yaml otherwise this will throw an exception
118  SingleSample.SampleTitle = Get<std::string>(SampleSettings["SampleTitle"], __FILE__ , __LINE__);
119  // Sample name used for defying syst uncertainties, if not specified use SampleHandler name
120  SingleSample.SampleName = GetFromManager<std::string>(SampleSettings["SampleName"], GetName(), __FILE__ , __LINE__);
121 
122  Binning->SetupSampleBinning(SampleSettings["Binning"], SingleSample);
123 
124  auto MCFilePrefix = Get<std::string>(SampleSettings["InputFiles"]["mtupleprefix"], __FILE__, __LINE__);
125  auto MCFileSuffix = Get<std::string>(SampleSettings["InputFiles"]["mtuplesuffix"], __FILE__, __LINE__);
126  auto SplinePrefix = Get<std::string>(SampleSettings["InputFiles"]["splineprefix"], __FILE__, __LINE__);
127  auto SplineSuffix = Get<std::string>(SampleSettings["InputFiles"]["splinesuffix"], __FILE__, __LINE__);
128 
129  int NChannels = static_cast<M3::int_t>(SampleSettings["OscChannels"].size());
130  SingleSample.OscChannels.reserve(NChannels);
131 
132  YAML::Node OscChannelsConfig;
133  // KS: We first check whether OscChannel are defined individually for this sample or taken from list
134  if(SampleSettings["OscChannels"].IsScalar()) {
135  auto PredeterminedChannelsName = Get<std::string>(SampleSettings["OscChannels"], __FILE__, __LINE__);
136  if(!SampleManager->raw()["OscChannels"]) {
137  MACH3LOG_ERROR("Trying to use Predetermined OscChannels however such field doesn't exist in config for SampleHandler: {}", GetName());
138  throw MaCh3Exception(__FILE__, __LINE__);
139  }
140  if(!SampleManager->raw()["OscChannels"][PredeterminedChannelsName]) {
141  MACH3LOG_ERROR("I didn't find PredeterminedChannelsName called: {}", PredeterminedChannelsName);
142  MACH3LOG_ERROR("However I have PredeterminedChannelsName known as:");
143  for (const auto& item : SampleManager->raw()["OscChannels"]) {
144  MACH3LOG_ERROR("{}", item.first.as<std::string>());
145  }
146  throw MaCh3Exception(__FILE__, __LINE__);
147  }
148  OscChannelsConfig = SampleManager->raw()["OscChannels"][PredeterminedChannelsName];
149  } else {
150  OscChannelsConfig = SampleSettings["OscChannels"];
151  }
152  int OscChannelCounter = 0;
153  for (auto const &osc_channel : OscChannelsConfig) {
154  OscChannelInfo OscInfo;
155  OscInfo.flavourName = Get<std::string>(osc_channel["Name"], __FILE__ , __LINE__);
156  OscInfo.flavourName_Latex = Get<std::string>(osc_channel["LatexName"], __FILE__ , __LINE__);
157  OscInfo.InitPDG = GetFromManager(osc_channel["nutype"], 0, __FILE__,__LINE__);
158  OscInfo.FinalPDG = GetFromManager(osc_channel["oscnutype"], 0, __FILE__,__LINE__);
159  OscInfo.ChannelIndex = OscChannelCounter;
160 
161  for (const auto& Existing : SingleSample.OscChannels) {
162  if (Existing.InitPDG == OscInfo.InitPDG && Existing.FinalPDG == OscInfo.FinalPDG) {
163  MACH3LOG_ERROR("Duplicate oscillation channel detected! InitPDG = {}, FinalPDG = {}"
164  "already defined in channel {} for sample {}",
165  OscInfo.InitPDG, OscInfo.FinalPDG, Existing.ChannelIndex, SingleSample.SampleTitle);
166  throw MaCh3Exception(__FILE__, __LINE__);
167  }
168  }
169  auto MCFileNames = Get<std::vector<std::string>>(osc_channel["mtuplefile"], __FILE__ , __LINE__);
170  for(size_t iFile = 0; iFile < MCFileNames.size(); iFile++){
171  std::string FileName = MCFilePrefix + MCFileNames[iFile] + MCFileSuffix;
172  MCFileNames[iFile] = FileName;
173  FileToInitPDGMap[FileName] = NuPDG(OscInfo.InitPDG);
174  FileToFinalPDGMap[FileName] = NuPDG(OscInfo.FinalPDG);
175  }
176 
177  SingleSample.OscChannels.push_back(std::move(OscInfo));
178  SingleSample.mc_files.push_back(MCFileNames);
179  SingleSample.spline_files.push_back(SplinePrefix+osc_channel["splinefile"].as<std::string>()+SplineSuffix);
180  OscChannelCounter++;
181  }
182  //Now grab the selection cuts from the manager
183  for ( auto const &SelectionCuts : SampleSettings["SelectionCuts"]) {
184  auto TempBoundsVec = GetBounds(SelectionCuts["Bounds"]);
185  KinematicCut CutObj;
186  CutObj.LowerBound = TempBoundsVec[0];
187  CutObj.UpperBound = TempBoundsVec[1];
188  CutObj.ParamToCutOnIt = ReturnKinematicParameterFromString(SelectionCuts["KinematicStr"].as<std::string>());
189  MACH3LOG_INFO("Adding cut on {} with bounds {} to {}", SelectionCuts["KinematicStr"].as<std::string>(), TempBoundsVec[0], TempBoundsVec[1]);
190  StoredSelection[iSample].emplace_back(CutObj);
191  }
194  SampleDetails[iSample] = std::move(SingleSample);
195 }
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.
Definition: SampleInfo.h:8
int InitPDG
PDG of initial flavour.
Definition: SampleInfo.h:15
double ChannelIndex
In case experiment specific would like to have pointer to channel after using GetOscChannel,...
Definition: SampleInfo.h:20
int FinalPDG
PDG of oscillated/final flavour.
Definition: SampleInfo.h:17
std::string flavourName
Name of osc channel.
Definition: SampleInfo.h:10
std::string flavourName_Latex
Fancy channel name (e.g., LaTeX formatted)
Definition: SampleInfo.h:12
KS: Store info about MC sample.
Definition: SampleInfo.h:40
std::string SampleName
tag for sample used to easily set by which uncertainties should be affected
Definition: SampleInfo.h:57
std::vector< OscChannelInfo > OscChannels
Stores info about oscillation channel for a single sample.
Definition: SampleInfo.h:68
std::string SampleTitle
the name of this sample e.g."muon-like" used for printing
Definition: SampleInfo.h:55
std::vector< std::string > spline_files
names of spline files associated associated with this object
Definition: SampleInfo.h:65
std::vector< std::vector< std::string > > mc_files
names of mc files associated associated with this object
Definition: SampleInfo.h:63

◆ PassesSelection()

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

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

271 {};

◆ 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 1752 of file SampleHandlerBase.cpp.

1752  {
1753 // ************************************************
1754  constexpr int space = 14;
1755 
1756  bool printToFile=false;
1757  if (OutputFileName.CompareTo("/dev/null")) {printToFile = true;}
1758 
1759  bool printToCSV=false;
1760  if(OutputCSVFileName.CompareTo("/dev/null")) printToCSV=true;
1761 
1762  std::ofstream outfile;
1763  if (printToFile) {
1764  outfile.open(OutputFileName.Data(), std::ios_base::app);
1765  outfile.precision(7);
1766  }
1767 
1768  std::ofstream outcsv;
1769  if(printToCSV){
1770  outcsv.open(OutputCSVFileName, std::ios_base::app); // Appened to CSV
1771  outcsv.precision(7);
1772  }
1773 
1774  double PDFIntegral = 0.;
1775 
1776  std::vector< std::vector< std::unique_ptr<TH1> > > IntegralList;
1777  IntegralList.resize(Modes->GetNModes());
1778 
1779  std::vector<double> ChannelIntegral;
1780  ChannelIntegral.resize(GetNOscChannels(iSample));
1781  for (unsigned int i=0;i<ChannelIntegral.size();i++) {ChannelIntegral[i] = 0.;}
1782 
1783  for (int i=0;i<Modes->GetNModes();i++) {
1784  if (GetNDim(iSample) == 1) {
1785  IntegralList[i] = ReturnHistsBySelection1D(iSample, GetKinVarName(iSample, 0), SamplePlotType::kOscChannelPlot, i, WeightStyle);
1786  } else {
1787  IntegralList[i] = CastVector<TH2, TH1>(ReturnHistsBySelection2D(iSample, GetKinVarName(iSample, 0), GetKinVarName(iSample, 1),
1788  SamplePlotType::kOscChannelPlot, i, WeightStyle));
1789  }
1790  }
1791 
1792  MACH3LOG_INFO("-------------------------------------------------");
1793 
1794  if (printToFile) {
1795  outfile << "\\begin{table}[ht]" << std::endl;
1796  outfile << "\\begin{center}" << std::endl;
1797  outfile << "\\caption{Integral breakdown for sample: " << GetSampleTitle(iSample) << "}" << std::endl;
1798  outfile << "\\label{" << GetSampleTitle(iSample) << "-EventRate}" << std::endl;
1799 
1800  TString nColumns;
1801  for (int i=0;i<GetNOscChannels(iSample);i++) {nColumns+="|c";}
1802  nColumns += "|c|";
1803  outfile << "\\begin{tabular}{|l" << nColumns.Data() << "}" << std::endl;
1804  outfile << "\\hline" << std::endl;
1805  }
1806 
1807  if(printToCSV){
1808  // HW Probably a better way but oh well, here I go making MaCh3 messy again
1809  outcsv<<"Integral Breakdown for sample :"<<GetSampleTitle(iSample)<<"\n";
1810  }
1811 
1812  MACH3LOG_INFO("Integral breakdown for sample: {}", GetSampleTitle(iSample));
1813  MACH3LOG_INFO("");
1814 
1815  if (printToFile) {outfile << std::setw(space) << "Mode:";}
1816  if(printToCSV) {outcsv<<"Mode,";}
1817 
1818  std::string table_headings = fmt::format("| {:<8} |", "Mode");
1819  std::string table_footline = "------------"; //Scalable table horizontal line
1820  for (int i = 0;i < GetNOscChannels(iSample); i++) {
1821  table_headings += fmt::format(" {:<17} |", GetFlavourName(iSample, i));
1822  table_footline += "--------------------";
1823  if (printToFile) {outfile << "&" << std::setw(space) << SampleDetails[iSample].OscChannels[i].flavourName_Latex << " ";}
1824  if (printToCSV) {outcsv << GetFlavourName(iSample, i) << ",";}
1825  }
1826  if (printToFile) {outfile << "&" << std::setw(space) << "Total:" << "\\\\ \\hline" << std::endl;}
1827  if (printToCSV) {outcsv <<"Total\n";}
1828  table_headings += fmt::format(" {:<10} |", "Total");
1829  table_footline += "-------------";
1830 
1831  MACH3LOG_INFO("{}", table_headings);
1832  MACH3LOG_INFO("{}", table_footline);
1833 
1834  for (unsigned int i=0;i<IntegralList.size();i++) {
1835  double ModeIntegral = 0;
1836  if (printToFile) {outfile << std::setw(space) << Modes->GetMaCh3ModeName(i);}
1837  if(printToCSV) {outcsv << Modes->GetMaCh3ModeName(i) << ",";}
1838 
1839  table_headings = fmt::format("| {:<8} |", Modes->GetMaCh3ModeName(i)); //Start string with mode name
1840 
1841  for (unsigned int j=0;j<IntegralList[i].size();j++) {
1842  double Integral = IntegralList[i][j]->Integral();
1843 
1844  if (Integral < 1e-100) {Integral=0;}
1845 
1846  ModeIntegral += Integral;
1847  ChannelIntegral[j] += Integral;
1848  PDFIntegral += Integral;
1849 
1850  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",Integral) << " ";}
1851  if (printToCSV) {outcsv << Form("%4.5f", Integral) << ",";}
1852 
1853  table_headings += fmt::format(" {:<17.4f} |", Integral);
1854  }
1855  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",ModeIntegral) << " \\\\ \\hline" << std::endl;}
1856  if (printToCSV) {outcsv << Form("%4.5f", ModeIntegral) << "\n";}
1857 
1858  table_headings += fmt::format(" {:<10.4f} |", ModeIntegral);
1859 
1860  MACH3LOG_INFO("{}", table_headings);
1861  }
1862 
1863  if (printToFile) {outfile << std::setw(space) << "Total:";}
1864  if (printToCSV) {outcsv << "Total,";}
1865 
1866  //Clear the table_headings to print last row of totals
1867  table_headings = fmt::format("| {:<8} |", "Total");
1868  for (unsigned int i=0;i<ChannelIntegral.size();i++) {
1869  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",ChannelIntegral[i]) << " ";}
1870  if (printToCSV) {outcsv << Form("%4.5f", ChannelIntegral[i]) << ",";}
1871  table_headings += fmt::format(" {:<17.4f} |", ChannelIntegral[i]);
1872  }
1873  if (printToFile) {outfile << "&" << std::setw(space) << Form("%4.5f",PDFIntegral) << " \\\\ \\hline" << std::endl;}
1874  if (printToCSV) {outcsv << Form("%4.5f", PDFIntegral) << "\n\n\n\n";} // Let's have a few new lines!
1875 
1876  table_headings += fmt::format(" {:<10.4f} |", PDFIntegral);
1877  MACH3LOG_INFO("{}", table_headings);
1878  MACH3LOG_INFO("{}", table_footline);
1879 
1880  if (printToFile) {
1881  outfile << "\\end{tabular}" << std::endl;
1882  outfile << "\\end{center}" << std::endl;
1883  outfile << "\\end{table}" << std::endl;
1884  }
1885 
1886  MACH3LOG_INFO("");
1887 
1888  if (printToFile) {
1889  outfile << std::endl;
1890  outfile.close();
1891  }
1892 }
std::string GetFlavourName(const int iSample, const int iChannel) const final
Get the flavour name for a given sample and oscillation channel.
std::vector< std::unique_ptr< TH2 > > ReturnHistsBySelection2D(const int iSample, const std::string &KinematicProjectionX, const std::string &KinematicProjectionY, const SamplePlotType Selection1, const int Selection2=-1, const int WeightStyle=0)
std::vector< std::unique_ptr< TH1 > > ReturnHistsBySelection1D(const int iSample, const std::string &KinematicProjection, const SamplePlotType 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 2000 of file SampleHandlerBase.cpp.

2000  {
2001 // ***************************************************************************
2002  if (!SampleHandler_data.size()) {
2003  MACH3LOG_ERROR("Data sample is empty!");
2004  throw MaCh3Exception(__FILE__, __LINE__);
2005  }
2006  MACH3LOG_INFO("Printing for {}", GetName());
2007 
2008  if (!DataOnly) {
2009  const std::string sep_full(81, '-');
2010  MACH3LOG_INFO("{}", sep_full);
2011  MACH3LOG_INFO("{:<40}{:<15}{:<15}{:<10}|", "Sample", "Data", "MC", "-LLH");
2012  } else {
2013  const std::string sep_data(56, '-');
2014  MACH3LOG_INFO("{}", sep_data);
2015  MACH3LOG_INFO("{:<40}{:<15}|", "Sample", "Data");
2016  }
2017 
2018  double sumData = 0.0;
2019  double sumMC = 0.0;
2020  double likelihood = 0.0;
2021 
2022  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
2023  std::string name = GetSampleTitle(iSample);
2024  std::vector<double> DataArray = GetDataArray(iSample);
2025  double dataIntegral = std::accumulate(DataArray.begin(), DataArray.end(), 0.0);
2026  sumData += dataIntegral;
2027  if (!DataOnly) {
2028  std::vector<double> MCArray = GetMCArray(iSample);
2029  double mcIntegral = std::accumulate(MCArray.begin(), MCArray.end(), 0.0);
2030  sumMC += mcIntegral;
2031  likelihood = GetSampleLikelihood(iSample);
2032 
2033  MACH3LOG_INFO("{:<40}{:<15.2f}{:<15.2f}{:<10.2f}|", name, dataIntegral, mcIntegral, likelihood);
2034  } else {
2035  MACH3LOG_INFO("{:<40}{:<15.2f}|", name, dataIntegral);
2036  }
2037  }
2038  if (!DataOnly) {
2039  likelihood = GetLikelihood();
2040  MACH3LOG_INFO("{:<40}{:<15.2f}{:<15.2f}{:<10.2f}|", "Total", sumData, sumMC, likelihood);
2041  const std::string sep_full(81, '-');
2042  MACH3LOG_INFO("{}", sep_full);
2043  } else {
2044  MACH3LOG_INFO("{:<40}{:<20.2f}|", "Total", sumData);
2045  const std::string sep_data(56, '-');
2046  MACH3LOG_INFO("{}", sep_data);
2047  }
2048 }
double GetSampleLikelihood(const int isample) const override
Get likelihood (-logL) for a single sample.
double GetLikelihood() const override
Return likelihood (-LogL) for all samples.
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 55 of file SampleHandlerBase.cpp.

55  {
56 // ************************************************
57  auto ModeName = Get<std::string>(SampleManager->raw()["MaCh3ModeConfig"], __FILE__ , __LINE__);
58  Modes = std::make_unique<MaCh3Modes>(getenv("MACH3")+std::string("/") + ModeName);
59  //SampleName has to be provided in the sample yaml otherwise this will throw an exception
60  SampleHandlerName = Get<std::string>(SampleManager->raw()["SampleHandlerName"], __FILE__ , __LINE__);
61 
62  fTestStatistic = static_cast<TestStatistic>(SampleManager->GetMCStatLLH());
63  if (CheckNodeExists(SampleManager->raw(), "LikelihoodOptions")) {
64  UpdateW2 = GetFromManager<bool>(SampleManager->raw()["LikelihoodOptions"]["UpdateW2"], false, __FILE__ , __LINE__);
65  }
66 
67  if (!CheckNodeExists(SampleManager->raw(), "BinningFile")){
68  MACH3LOG_ERROR("BinningFile not given in for sample handler {}, ReturnKinematicParameterBinning will not work", SampleHandlerName);
69  throw MaCh3Exception(__FILE__, __LINE__);
70  }
71 
72  auto EnabledSasmples = Get<std::vector<std::string>>(SampleManager->raw()["Samples"], __FILE__ , __LINE__);
73  // Get number of samples and resize relevant objects
74  nSamples = static_cast<M3::int_t>(EnabledSasmples.size());
75  if (nSamples == 0){
76  MACH3LOG_ERROR("No samples for Sample Handler {}, please double check sample config", GetName());
77  throw MaCh3Exception(__FILE__, __LINE__);
78  }
79 
80  SampleDetails.resize(nSamples);
81  StoredSelection.resize(nSamples);
82  for (int iSample = 0; iSample < nSamples; iSample++)
83  {
84  auto SampleSettings = SampleManager->raw()[EnabledSasmples[iSample]];
85  LoadSingleSample(iSample, SampleSettings);
86  } // end loop over enabling samples
87 
88  // EM: initialise the mode weight map
89  for( int iMode=0; iMode < Modes->GetNModes(); iMode++ ) {
90  _modeNomWeightMap[Modes->GetMaCh3ModeName(iMode)] = 1.0;
91  }
92 
93  // EM: multiply by the nominal weight specified in the sample config file
94  if ( SampleManager->raw()["NominalWeights"] ) {
95  for( int iMode=0; iMode<Modes->GetNModes(); iMode++ ) {
96  std::string modeStr = Modes->GetMaCh3ModeName(iMode);
97  if( SampleManager->raw()["NominalWeights"][modeStr] ) {
98  double modeWeight = SampleManager->raw()["NominalWeights"][modeStr].as<double>();
99  _modeNomWeightMap[Modes->GetMaCh3ModeName(iMode)] *= modeWeight;
100  }
101  }
102  }
103 
104  // EM: print em out
105  MACH3LOG_INFO(" Nominal mode weights to apply: ");
106  for(int iMode=0; iMode<Modes->GetNModes(); iMode++ ) {
107  std::string modeStr = Modes->GetMaCh3ModeName(iMode);
108  MACH3LOG_INFO(" - {}: {}", modeStr, _modeNomWeightMap.at(modeStr));
109  }
110 }
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 ( )
inlineprotectedvirtual

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

Reimplemented in PySampleHandlerBase.

Definition at line 269 of file SampleHandlerBase.h.

269 {};

◆ RegisterIndividualFunctionalParameter() [1/2]

template<typename EventType , typename SFType >
void SampleHandlerBase::RegisterIndividualFunctionalParameter ( std::vector< EventType > &  ExptEvents,
std::string const &  par_name,
SFType  shift_func 
)
protected

LP - Registration template function for one-dimensional functional shifts.

See above for more details on the call signature and usage.

◆ RegisterIndividualFunctionalParameter() [2/2]

template<typename EventType , typename SFType >
void SampleHandlerBase::RegisterIndividualFunctionalParameter ( std::vector< EventType > &  ExptEvents,
std::vector< std::string > const &  par_names,
SFType  shift_func 
)
protected

LP - Registration template function for multi-dimensional functional shifts.

This method is templated over the EventType and the response function type because the response function type is a function of the event type. The implementation checks via static assert that the passed function object has the correct call signature. The experiment class event vector is passed so that the function objects that are used to apply the shifts are able to access the full event information from the experiment class, rather than only being able to respond to event properties defined in Samples/EventInfo.h A vector of input parameter names that should be consumed by the functional shift is also passed. For a 1D version of this method, see below. This function might be used like below:

RegisterIndividualFunctionalParameter(ExptEventInfo, {"par1", "par2"}, [](std::vector<double> const & par_vals, ExptEventType & ev){ constexpr static const double a = 1.2345; ev.property += par_vals[0] * a + par_vals[1]; });

◆ ResetHistograms()

void SampleHandlerBase::ResetHistograms ( )
protected

Helper function to reset histograms.

Definition at line 488 of file SampleHandlerBase.cpp.

488  {
489 // **************************************************
490  // DB Reset values stored in PDF array to 0.
491  // Don't openMP this; no significant gain
492  const int nBins = Binning->GetNBins();
493  std::fill_n(SampleHandler_array.begin(), nBins, 0.0);
494  if (FirstTimeW2) {
495  std::fill_n(SampleHandler_array_w2.begin(), nBins, 0.0);
496  }
497 } // end function

◆ ResetShifts()

virtual void SampleHandlerBase::ResetShifts ( [[maybe_unused] ] const int  iEvent)
inlineprotectedvirtual

HH - reset the shifted values to the original values.

Definition at line 309 of file SampleHandlerBase.h.

309 {};

◆ ReturnHistsBySelection1D()

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

Definition at line 1911 of file SampleHandlerBase.cpp.

1912  {
1913 // ************************************************
1914  std::vector<std::unique_ptr<TH1>> hHistList;
1915  std::string legendEntry;
1916 
1917  if (THStackLeg != nullptr) {delete THStackLeg;}
1918  THStackLeg = new TLegend(0.1,0.1,0.9,0.9);
1919 
1920  const int iMax = GetRangeForPlotType(Selection1, iSample);
1921  for (int i=0;i<iMax;i++) {
1922  if (Selection1 == SamplePlotType::kModePlot) {
1923  hHistList.push_back(Get1DVarHistByModeAndChannel(iSample, KinematicProjection,i,Selection2,WeightStyle));
1924  THStackLeg->AddEntry(hHistList[i].get(), (Modes->GetMaCh3ModeName(i)+Form(" : (%4.2f)",hHistList[i]->Integral())).c_str(),"f");
1925 
1926  hHistList[i]->SetFillColor(static_cast<Color_t>(Modes->GetMaCh3ModePlotColor(i)));
1927  hHistList[i]->SetLineColor(static_cast<Color_t>(Modes->GetMaCh3ModePlotColor(i)));
1928  }
1929  if (Selection1 == SamplePlotType::kOscChannelPlot) {
1930  hHistList.push_back(Get1DVarHistByModeAndChannel(iSample, KinematicProjection,Selection2,i,WeightStyle));
1931  THStackLeg->AddEntry(hHistList[i].get(),(GetFlavourName(iSample, i)+Form(" | %4.2f",hHistList[i]->Integral())).c_str(),"f");
1932  }
1933  }
1934 
1935  return hHistList;
1936 }
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
Build a 1D histogram for a given variable, optionally filtered by mode and channel.
int GetRangeForPlotType(const SamplePlotType TypeEnum, const int iSample) const
KS: Return range for plot type, for example number of modes, osc channels etc.

◆ ReturnHistsBySelection2D()

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

Definition at line 1939 of file SampleHandlerBase.cpp.

1941  {
1942 // ************************************************
1943  std::vector<std::unique_ptr<TH2>> hHistList;
1944 
1945  const int iMax = GetRangeForPlotType(Selection1, iSample);
1946  for (int i=0;i<iMax;i++) {
1947  if (Selection1 == SamplePlotType::kModePlot) {
1948  hHistList.push_back(Get2DVarHistByModeAndChannel(iSample, KinematicProjectionX,KinematicProjectionY,i,Selection2,WeightStyle));
1949  }
1950  if (Selection1 == SamplePlotType::kOscChannelPlot) {
1951  hHistList.push_back(Get2DVarHistByModeAndChannel(iSample, KinematicProjectionX,KinematicProjectionY,Selection2,i,WeightStyle));
1952  }
1953  }
1954 
1955  return hHistList;
1956 }
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
Build a 2D histogram for given variables, optionally filtered by mode and channel.

◆ ReturnKinematicParameter() [1/2]

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

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

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 337 of file SampleHandlerBase.h.

337  {
338  return ReturnKinematicParameter(ReturnKinematicParameterFromString(KinematicParameter), iEvent);
339  }

◆ ReturnKinematicParameterBinning()

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

Return the binning used to draw a kinematic parameter.

Parameters
iSampleIndex of the sample.
KinematicParametername of variable
Todo:
might be useful to allow overwriting this

Implements SampleHandlerInterface.

Definition at line 1613 of file SampleHandlerBase.cpp.

1613  {
1614 // ************************************************
1615  // If any of fit based variables return them
1617  if(Binning->IsUniform(Sample)) {
1618  for(int iDim = 0; iDim < GetNDim(Sample); iDim++) {
1619  if(KinematicParameter == GetKinVarName(Sample, iDim)) {
1620  return Binning->GetBinEdges(Sample, iDim);
1621  }
1622  } // end loop over Dimension
1623  } // end loop over IsUniform
1624 
1625  auto MakeBins = [](int nBins) {
1626  std::vector<double> bins(nBins + 1);
1627  for (int i = 0; i <= nBins; ++i)
1628  bins[i] = static_cast<double>(i) - 0.5;
1629  return bins;
1630  };
1631 
1632  if (KinematicParameter == "OscillationChannel") {
1633  return MakeBins(GetNOscChannels(Sample));
1634  } else if (KinematicParameter == "Mode") {
1635  return MakeBins(Modes->GetNModes());
1636  }
1637 
1638  std::vector<double> BinningVect;
1639  // We first check if binning for a sample has been specified
1640  auto BinningConfig = M3OpenConfig(SampleManager->raw()["BinningFile"].as<std::string>());
1641  bool found_range_specifier = false;
1642  if(BinningConfig[GetSampleTitle(Sample)] && BinningConfig[GetSampleTitle(Sample)][KinematicParameter]){
1643  BinningVect = BuildBinEdgesFromNode(BinningConfig[GetSampleTitle(Sample)][KinematicParameter], found_range_specifier);
1644  } else {
1645  BinningVect = BuildBinEdgesFromNode(BinningConfig[KinematicParameter], found_range_specifier);
1646  }
1647 
1648  // Ensure binning is increasing
1649  auto IsIncreasing = [](const std::vector<double>& vec) {
1650  for (size_t i = 1; i < vec.size(); ++i) {
1651  if (vec[i] <= vec[i-1]) {
1652  return false;
1653  }
1654  }
1655  return true;
1656  };
1657 
1658  if (!IsIncreasing(BinningVect)) {
1659  MACH3LOG_ERROR("Binning for {} is not increasing [{}]", KinematicParameter, fmt::join(BinningVect, ", "));
1660  if(found_range_specifier){
1661  MACH3LOG_ERROR("A bin range specifier was found. Please carefully check the number of square brackets used.");
1662  }
1663  throw MaCh3Exception(__FILE__, __LINE__);
1664  }
1665  return BinningVect;
1666 }
std::vector< double > BuildBinEdgesFromNode(YAML::Node const &bin_edges_node, bool &found_range_specifier)
Builds a single dimension's bin edges from YAML::Node.
#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 param handler to a kinematic type.

Definition at line 1560 of file SampleHandlerBase.cpp.

1560  {
1561 // ************************************************
1562  auto it = KinematicParameters->find(KinematicParameterStr);
1563  if (it != KinematicParameters->end()) return it->second;
1564 
1565  MACH3LOG_ERROR("Did not recognise Kinematic Parameter type: {}", KinematicParameterStr);
1566  throw MaCh3Exception(__FILE__, __LINE__);
1567 
1568  return M3::_BAD_INT_;
1569 }

◆ ReturnKinematicVector() [1/2]

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

Definition at line 347 of file SampleHandlerBase.h.

348  {return {};};

◆ ReturnKinematicVector() [2/2]

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

Definition at line 344 of file SampleHandlerBase.h.

344  {
345  return ReturnKinematicVector(ReturnKinematicVectorFromString(KinematicParameter), iEvent);
346  }

◆ ReturnKinematicVectorFromString()

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

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

Definition at line 1587 of file SampleHandlerBase.cpp.

1587  {
1588 // ************************************************
1589  auto it = KinematicVectors->find(KinematicVectorStr);
1590  if (it != KinematicVectors->end()) return it->second;
1591 
1592  MACH3LOG_ERROR("Did not recognise Kinematic Vector: {}", KinematicVectorStr);
1593  throw MaCh3Exception(__FILE__, __LINE__);
1594 
1595  return M3::_BAD_INT_;
1596 }

◆ ReturnStackedHistBySelection1D()

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

Definition at line 1959 of file SampleHandlerBase.cpp.

1960  {
1961 // ************************************************
1962  auto HistList = ReturnHistsBySelection1D(iSample, KinematicProjection, Selection1, Selection2, WeightStyle);
1963  auto StackHist = std::make_unique<THStack>((GetSampleTitle(iSample)+"_"+KinematicProjection+"_Stack").c_str(),"");
1964  // Note: we use .release() to transfer ownership of each TH1 to THStack.
1965  for (unsigned int i=0;i<HistList.size();i++) {
1966  StackHist->Add(HistList[i].release());
1967  }
1968  return StackHist;
1969 }

◆ ReturnStackHistLegend()

const TLegend* SampleHandlerBase::ReturnStackHistLegend ( ) const
inline

Return the legend used for stacked histograms with sample info.

Definition at line 158 of file SampleHandlerBase.h.

158 {return THStackLeg;}

◆ ReturnStringFromKinematicParameter()

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

ETA function to generically convert a kinematic type from param handler to a string.

Definition at line 1572 of file SampleHandlerBase.cpp.

1572  {
1573 // ************************************************
1574  auto it = ReversedKinematicParameters->find(KinematicParameter);
1575  if (it != ReversedKinematicParameters->end()) {
1576  return it->second;
1577  }
1578 
1579  MACH3LOG_ERROR("Did not recognise Kinematic Parameter type: {}", KinematicParameter);
1580  throw MaCh3Exception(__FILE__, __LINE__);
1581 
1582  return "";
1583 }

◆ 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 1599 of file SampleHandlerBase.cpp.

1599  {
1600 // ************************************************
1601  auto it = ReversedKinematicVectors->find(KinematicVector);
1602  if (it != ReversedKinematicVectors->end()) {
1603  return it->second;
1604  }
1605 
1606  MACH3LOG_ERROR("Did not recognise Kinematic Vector: {}", KinematicVector);
1607  throw MaCh3Exception(__FILE__, __LINE__);
1608 
1609  return "";
1610 }

◆ Reweight()

void SampleHandlerBase::Reweight ( )
overridevirtual

main routine modifying MC prediction based on proposed parameter values

Implements SampleHandlerInterface.

Definition at line 348 of file SampleHandlerBase.cpp.

348  {
349 //************************************************
350  //KS: Reset the histograms before reweight
351  ResetHistograms();
352 
353  //You only need to do these things if Oscillator has been initialised
354  //if not then you're not considering oscillations
355  if (Oscillator) Oscillator->Evaluate();
356 
357  // Calculate weight coming from all splines if we initialised handler
358  if(SplineHandler) SplineHandler->Evaluate();
359 
360  //update the list of parameter values passed to shift functionals
362  // Update the functional parameter values to the latest proposed values
364 
365  //KS: If using CPU this does nothing, if on GPU need to make sure we finished copying memory from
366  if(SplineHandler) SplineHandler->SynchroniseMemTransfer();
367 
368  #ifdef MULTITHREAD
369  // Call entirely different routine if we're running with openMP
370  FillArray_MP();
371  #else
372  FillArray();
373  #endif
374 
375  //KS: If you want to not update W2 wights then uncomment this line
376  if(!UpdateW2) FirstTimeW2 = false;
377 }
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)
final

Store additional info in a chain.

Parameters
Dirdirectory to which we save additional info

Definition at line 1257 of file SampleHandlerBase.cpp.

1257  {
1258 // ************************************************
1259  Dir->cd();
1260 
1261  YAML::Node Config = SampleManager->raw();
1262  TMacro ConfigSave = YAMLtoTMacro(Config, (std::string("Config_") + GetName()));
1263  ConfigSave.Write();
1264 
1265  for(int iSample = 0; iSample < GetNSamples(); iSample++)
1266  {
1267  std::unique_ptr<TH1> data_hist;
1268 
1269  if (GetNDim(iSample) == 1) {
1270  data_hist = M3::Clone<TH1D>(dynamic_cast<const TH1D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1271  data_hist->GetXaxis()->SetTitle(GetKinVarName(iSample, 0).c_str());
1272  data_hist->GetYaxis()->SetTitle("Number of Events");
1273  } else if (GetNDim(iSample) == 2) {
1274  if(Binning->IsUniform(iSample)) {
1275  data_hist = M3::Clone<TH2D>(dynamic_cast<const TH2D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1276  } else {
1277  data_hist = M3::Clone<TH2Poly>(dynamic_cast<const TH2Poly*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1278  }
1279  data_hist->GetXaxis()->SetTitle(GetKinVarName(iSample, 0).c_str());
1280  data_hist->GetYaxis()->SetTitle(GetKinVarName(iSample, 1).c_str());
1281  data_hist->GetZaxis()->SetTitle("Number of Events");
1282  } else {
1283  data_hist = M3::Clone<TH1D>(dynamic_cast<const TH1D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1284  int nbins = Binning->GetNBins(iSample);
1285  for(int iBin = 0; iBin < nbins; iBin++) {
1286  auto BinName = Binning->GetBinName(iSample, iBin);
1287  data_hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
1288  }
1289  data_hist->GetYaxis()->SetTitle("Number of Events");
1290  }
1291 
1292  if (!data_hist) {
1293  MACH3LOG_ERROR("nullptr data hist :(");
1294  throw MaCh3Exception(__FILE__, __LINE__);
1295  }
1296 
1297  data_hist->SetTitle(("data_" + GetSampleTitle(iSample)).c_str());
1298  data_hist->Write();
1299  }
1300 }
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 686 of file SampleHandlerBase.cpp.

686  {
687 // ************************************************
688  for(int iSample = 0; iSample < GetNSamples(); iSample++)
689  {
690  int Dimension = GetNDim(iSample);
691  std::string HistTitle = GetSampleTitle(iSample);
692 
693  auto* SamDet = &SampleDetails[iSample];
694  if(Dimension == 1) {
695  auto XVec = Binning->GetBinEdges(iSample, 0);
696  SamDet->DataHist = new TH1D(("d" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
697  SamDet->MCHist = new TH1D(("h" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
698  SamDet->W2Hist = new TH1D(("w" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
699 
700  // Set all titles so most of projections don't have empty titles...
701  SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
702  SamDet->DataHist->GetYaxis()->SetTitle("Events");
703  SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
704  SamDet->MCHist->GetYaxis()->SetTitle("Events");
705  SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
706  SamDet->W2Hist->GetYaxis()->SetTitle("Events");
707  } else if (Dimension == 2){
708  if(Binning->IsUniform(iSample)) {
709  auto XVec = Binning->GetBinEdges(iSample, 0);
710  auto YVec = Binning->GetBinEdges(iSample, 1);
711  int nX = static_cast<int>(XVec.size() - 1);
712  int nY = static_cast<int>(YVec.size() - 1);
713 
714  SamDet->DataHist = new TH2D(("d" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
715  SamDet->MCHist = new TH2D(("h" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
716  SamDet->W2Hist = new TH2D(("w" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
717  } else {
718  auto AddBinsToTH2Poly = [](TH2Poly* hist, const std::vector<BinInfo>& bins) {
719  for (const auto& bin : bins) {
720  double xLow = bin.Extent[0][0];
721  double xHigh = bin.Extent[0][1];
722  double yLow = bin.Extent[1][0];
723  double yHigh = bin.Extent[1][1];
724 
725  double x[4] = {xLow, xHigh, xHigh, xLow};
726  double y[4] = {yLow, yLow, yHigh, yHigh};
727 
728  hist->AddBin(4, x, y);
729  }
730  };
731  // Create all three histograms
732  SamDet->DataHist = new TH2Poly();
733  SamDet->DataHist->SetName(("d" + HistTitle).c_str());
734  SamDet->DataHist->SetTitle(HistTitle.c_str());
735 
736  SamDet->MCHist = new TH2Poly();
737  SamDet->MCHist->SetName(("h" + HistTitle).c_str());
738  SamDet->MCHist->SetTitle(HistTitle.c_str());
739 
740  SamDet->W2Hist = new TH2Poly();
741  SamDet->W2Hist->SetName(("w" + HistTitle).c_str());
742  SamDet->W2Hist->SetTitle(HistTitle.c_str());
743 
744  // Add bins to each
745  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->DataHist), Binning->GetNonUniformBins(iSample));
746  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->MCHist), Binning->GetNonUniformBins(iSample));
747  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->W2Hist), Binning->GetNonUniformBins(iSample));
748  }
749 
750  // Set all titles so most of projections don't have empty titles...
751  SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
752  SamDet->DataHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
753  SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
754  SamDet->MCHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
755  SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
756  SamDet->W2Hist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
757  } else {
758  int nbins = Binning->GetNBins(iSample);
759  SamDet->DataHist = new TH1D(("d" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
760  SamDet->MCHist = new TH1D(("h" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
761  SamDet->W2Hist = new TH1D(("w" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
762 
763  for(int iBin = 0; iBin < nbins; iBin++) {
764  auto BinName = Binning->GetBinName(iSample, iBin);
765  SamDet->DataHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
766  SamDet->MCHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
767  SamDet->W2Hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
768  }
769 
770  // Set all titles so most of projections don't have empty titles...
771  SamDet->DataHist->GetYaxis()->SetTitle("Events");
772  SamDet->MCHist->GetYaxis()->SetTitle("Events");
773  SamDet->W2Hist->GetYaxis()->SetTitle("Events");
774  }
775 
776  SamDet->DataHist->SetDirectory(nullptr);
777  SamDet->MCHist->SetDirectory(nullptr);
778  SamDet->W2Hist->SetDirectory(nullptr);
779  }
780 
781  //Set the number of X and Y bins now
784 }
void SetupReweightArrays()
Initialise data, MC and W2 histograms.
void FindNominalBinAndEdges()
Functions which find the nominal bin and bin edges.

◆ 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 1174 of file SampleHandlerBase.cpp.

1174  {
1175 // ************************************************
1176  //Now loop over events and get the spline bin for each event
1177  if (auto BinnedSpline = dynamic_cast<BinnedSplineHandler*>(SplineHandler.get())) {
1178  bool ThrowCrititcal = true;
1179 
1180  std::vector< std::vector<SplineParameter> > SplineParsVec(GetNSamples());
1181  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
1182  SplineParsVec[iSample] = ParHandler->GetSplineParsFromSampleName(GetSampleName(iSample));
1183  }
1184  for (unsigned int j = 0; j < GetNEvents(); ++j) {
1185  auto EventSplines = GetSplineBins(j, BinnedSpline, ThrowCrititcal);
1186  const int NSplines = static_cast<int>(EventSplines.size());
1187  if(NSplines == 0) continue;
1188  auto& w_pointers = MCEvents[j].total_weight_pointers;
1189  w_pointers.reserve(w_pointers.size() + NSplines);
1190  const auto SampleId = MCEvents[j].NominalSample;
1191  for(int spline = 0; spline < NSplines; spline++) {
1192  int SystIndex = EventSplines[spline].iSyst;
1193 
1194  bool IsSelected = PassesSelection(SplineParsVec[SampleId][SystIndex], j);
1195  // Need to then break the event loop
1196  if(!IsSelected){
1197  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", j, SplineParsVec[SampleId][SystIndex].name);
1198  continue;
1199  }
1200  //Event Splines indexed as: sample name, oscillation channel, syst, mode, etrue, var1, var2 (var2 is a dummy 0 for 1D splines)
1201  w_pointers.push_back(BinnedSpline->RetPointer(EventSplines[spline]));
1202  } // end loop over splines
1203  w_pointers.shrink_to_fit();
1204  } // end loop over events
1205  } else if (auto UnbinnedSpline = dynamic_cast<UnbinnedSplineHandler*>(SplineHandler.get())) {
1206  for (unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent) {
1207  MCEvents[iEvent].total_weight_pointers.push_back(UnbinnedSpline->RetPointer(iEvent));
1208  }
1209  } else {
1210  MACH3LOG_ERROR("Not supported splines");
1211  throw MaCh3Exception(__FILE__, __LINE__);
1212  }
1213 }
const std::vector< SplineParameter > GetSplineParsFromSampleName(const std::string &SampleName) const
KS: Grab the Spline parameters for the relevant SampleName.
std::vector< SplineIndex > 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.

◆ SetupKinematicMap()

void SampleHandlerBase::SetupKinematicMap ( )
protected

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

Definition at line 237 of file SampleHandlerBase.cpp.

237  {
238 // ************************************************
239  if(KinematicParameters == nullptr || ReversedKinematicParameters == nullptr) {
240  MACH3LOG_ERROR("Map KinematicParameters or ReversedKinematicParameters hasn't been initialised");
241  throw MaCh3Exception(__FILE__, __LINE__);
242  }
243  // KS: Ensure maps exist correctly
244  for (const auto& pair : *KinematicParameters) {
245  const auto& key = pair.first;
246  const auto& value = pair.second;
247 
248  auto it = ReversedKinematicParameters->find(value);
249  if (it == ReversedKinematicParameters->end() || it->second != key) {
250  MACH3LOG_ERROR("Mismatch found: {} -> {} but {} -> {}",
251  key, value, value, (it != ReversedKinematicParameters->end() ? it->second : "NOT FOUND"));
252  throw MaCh3Exception(__FILE__, __LINE__);
253  }
254  }
255  // KS: Ensure some MaCh3 specific variables are defined
256  std::vector<std::string> Vars = {"Mode", "OscillationChannel", "TargetNucleus"};
257  for(size_t iVar = 0; iVar < Vars.size(); iVar++) {
258  try {
260  } catch (const MaCh3Exception&) {
261  MACH3LOG_ERROR("MaCh3 expected variable: {} not found in KinematicParameters.", Vars[iVar]);
262  MACH3LOG_ERROR("All keys in KinematicParameters:");
263  for (const auto& pair : *KinematicParameters) {
264  MACH3LOG_ERROR("Key: {}", pair.first);
265  }
266  throw MaCh3Exception(__FILE__, __LINE__);
267  }
268  }
269 }

◆ 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 577 of file SampleHandlerBase.cpp.

577  {
578 // ***************************************************************************
579  if(ParHandler == nullptr) return;
580  std::vector< std::vector< int > > norms_bins(GetNEvents());
581 
582  std::vector< std::vector<NormParameter>> norm_parameters(GetNSamples());
583 
584  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
585  norm_parameters[iSample] = ParHandler->GetNormParsFromSampleName(GetSampleName(iSample));
586  }
587  if(!ParHandler) {
588  MACH3LOG_ERROR("ParHandler is not setup!");
589  throw MaCh3Exception(__FILE__ , __LINE__ );
590  }
591 
592  // Assign norm bins in MCEvents tree
593  CalcNormsBins(norm_parameters, norms_bins);
594 
595  //DB Attempt at reducing impact of SystematicHandlerGeneric::calcReweight()
596  for (unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent) {
597  int counter = 0;
598  const size_t offset = MCEvents[iEvent].total_weight_pointers.size();
599  const size_t addSize = norms_bins[iEvent].size();
600  MCEvents[iEvent].total_weight_pointers.resize(offset + addSize);
601  for(auto const & norm_bin: norms_bins[iEvent]) {
602  MCEvents[iEvent].total_weight_pointers[offset + counter] = ParHandler->RetPointer(norm_bin);
603  counter += 1;
604  }
605  }
606 }
const M3::float_t * RetPointer(const int iParam) const
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< 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 1051 of file SampleHandlerBase.cpp.

1051  {
1052 // ************************************************
1053  auto AddOscPointer = GetFromManager<bool>(SampleManager->raw()["NuOsc"]["AddOscPointer"], true, __FILE__ , __LINE__);
1054  // 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
1055  if(!AddOscPointer) {
1056  return;
1057  }
1058  for (unsigned int iEvent=0;iEvent<GetNEvents();iEvent++) {
1059  const M3::float_t* osc_w_pointer = GetNuOscillatorPointers(iEvent);
1060 
1061  // KS: Do not add unity
1062  if (osc_w_pointer != &M3::Unity) {
1063  MCEvents[iEvent].total_weight_pointers.push_back(osc_w_pointer);
1064  }
1065  }
1066 }
const M3::float_t * GetNuOscillatorPointers(const int iEvent) const
Get pointer to NuOscillator weight for a given event.

◆ SetupOscParameters()

void SampleHandlerBase::SetupOscParameters ( )
protected

Setup the osc parameters.

Definition at line 538 of file SampleHandlerBase.cpp.

538  {
539 // ***************************************************************************
540  // KS: Only make sense to setup osc if you have ParHandler
541  if(ParHandler == nullptr ) return;
542 
543  auto OscParams = ParHandler->GetOscParsFromSampleName(GetSampleName(0));
544  if (OscParams.size() > 0) {
545  MACH3LOG_INFO("Setting up NuOscillator..");
546  if (Oscillator != nullptr) {
547  MACH3LOG_INFO("You have passed an OscillatorBase object through the constructor of a SampleHandlerFD object - this will be used for all oscillation channels");
548  if(Oscillator->isEqualBinningPerOscChannel() != true) {
549  MACH3LOG_ERROR("Trying to run shared NuOscillator without EqualBinningPerOscChannel, this will not work");
550  throw MaCh3Exception(__FILE__, __LINE__);
551  }
552 
553  if(OscParams.size() != Oscillator->GetOscParamsSize()){
554  MACH3LOG_ERROR("SampleHandler {} has {} osc params, while shared NuOsc has {} osc params", GetName(),
555  OscParams.size(), Oscillator->GetOscParamsSize());
556  MACH3LOG_ERROR("This indicate misconfiguration in your Osc yaml");
557  throw MaCh3Exception(__FILE__, __LINE__);
558  }
559  } else {
561  }
563  } else{
564  MACH3LOG_WARN("Didn't find any oscillation params, thus will not enable oscillations");
565  if(CheckNodeExists(SampleManager->raw(), "NuOsc")){
566  MACH3LOG_ERROR("However config for SampleHandler {} has 'NuOsc' field", GetName());
567  MACH3LOG_ERROR("This may indicate misconfiguration");
568  MACH3LOG_ERROR("Either remove 'NuOsc' field from SampleHandler config or check your model.yaml and include oscillation for sample");
569  throw MaCh3Exception(__FILE__, __LINE__);
570  }
571  }
572 }
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 678 of file SampleHandlerBase.cpp.

678  {
679 // ************************************************
680  SampleHandler_array = std::vector<double>(Binning->GetNBins(),0);
681  SampleHandler_array_w2 = std::vector<double>(Binning->GetNBins(),0);
682  SampleHandler_data = std::vector<double>(Binning->GetNBins(),0);
683 }

◆ SetupSplines()

virtual void SampleHandlerBase::SetupSplines ( )
protectedpure virtual

initialise your splineXX object and then use InitialiseSplineObject to conveniently 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 444 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 396 of file SampleHandlerBase.h.

◆ FileToFinalPDGMap

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

Mapping from input file names to final neutrino PDG codes.

Definition at line 468 of file SampleHandlerBase.h.

◆ FileToInitPDGMap

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

Mapping from input file names to initial neutrino PDG codes.

Definition at line 466 of file SampleHandlerBase.h.

◆ FirstTimeW2

bool SampleHandlerBase::FirstTimeW2
protected

KS:Super hacky to update W2 or not.

Definition at line 451 of file SampleHandlerBase.h.

◆ functional

M3::detail::Functional SampleHandlerBase::functional
private

Helper object for storing/updating information related to functional shift parameters.

Definition at line 471 of file SampleHandlerBase.h.

◆ KinematicParameters

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

Mapping between string and kinematic enum.

Definition at line 432 of file SampleHandlerBase.h.

◆ KinematicVectors

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

Definition at line 437 of file SampleHandlerBase.h.

◆ MCEvents

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

Stores information about every MC event.

Definition at line 407 of file SampleHandlerBase.h.

◆ nEvents

unsigned int SampleHandlerBase::nEvents
private

Number of MC events are there.

Definition at line 474 of file SampleHandlerBase.h.

◆ Oscillator

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

Contains oscillator handling calculating oscillation probabilities.

Definition at line 391 of file SampleHandlerBase.h.

◆ ParHandler

ParameterHandlerGeneric* SampleHandlerBase::ParHandler = nullptr
protected

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

Definition at line 415 of file SampleHandlerBase.h.

◆ ReversedKinematicParameters

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

Mapping between kinematic enum and string.

Definition at line 434 of file SampleHandlerBase.h.

◆ ReversedKinematicVectors

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

Definition at line 438 of file SampleHandlerBase.h.

◆ SampleDetails

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

Stores info about currently initialised sample.

Definition at line 409 of file SampleHandlerBase.h.

◆ SampleHandler_array

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

DB Array to be filled after reweighting.

Definition at line 398 of file SampleHandlerBase.h.

◆ SampleHandler_array_w2

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

KS Array used for MC stat.

Definition at line 400 of file SampleHandlerBase.h.

◆ SampleHandler_data

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

DB Array to be filled in AddData.

Definition at line 402 of file SampleHandlerBase.h.

◆ SampleHandlerName

std::string SampleHandlerBase::SampleHandlerName
protected

Identifier of this Sample Handler, mostly used for fancy printing in FitterBase.

Definition at line 419 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 442 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 428 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 388 of file SampleHandlerBase.h.

◆ StoredSelection

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

DB Vectors to store which kinematic cuts we apply. Gets used in IsEventSelected Read in from sample yaml file.

Definition at line 425 of file SampleHandlerBase.h.

◆ THStackLeg

TLegend* SampleHandlerBase::THStackLeg = nullptr
protected

DB: Legend associated with stacked histograms produced by this class.

Definition at line 448 of file SampleHandlerBase.h.

◆ UpdateW2

bool SampleHandlerBase::UpdateW2
protected

KS:Super hacky to update W2 or not.

Definition at line 453 of file SampleHandlerBase.h.


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