MaCh3  2.8.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 iSample) const final
 Get fancy title for specified samples. More...
 
std::string GetSampleName (const int iSample) 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< 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 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...
 
MaCh3Modes * GetMaCh3Modes () 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_t * GetNuOscillatorPointers (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< SplineIndex > GetSplineBins (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 ()
 Function which does the core reweighting. This assumes that oscillation weights have already been calculated. More...
 
void ResetHistograms () _noexcept_
 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< SplineBase > SplineHandler
 Contains all your splines (binned or unbinned) and handles the setup and the returning of weights from spline evaluations. More...
 
std::shared_ptr< OscillationHandler > Oscillator
 Contains oscillator handling calculating oscillation probabilities. More...
 
std::unique_ptr< BinningHandler > Binning
 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< EventInfo > MCEvents
 Stores information about every MC event. More...
 
std::vector< SampleInfo > SampleDetails
 Stores info about currently initialised sample. More...
 
ParameterHandlerGeneric * ParHandler = 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< Manager > SampleManager
 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< MaCh3Modes > Modes
 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, NuPDG > FileToInitPDGMap
 Mapping from input file names to initial neutrino PDG codes. More...
 
std::unordered_map< std::string, NuPDG > FileToFinalPDGMap
 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 model parameter");
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 909 of file SampleHandlerBase.cpp.

909  {
910 // ************************************************
911  const int Start = Binning->GetSampleStartBin(Sample);
912  const int End = Binning->GetSampleEndBin(Sample);
913  const int ExpectedSize = End - Start;
914 
915  if (static_cast<int>(Data_Array.size()) != ExpectedSize) {
916  MACH3LOG_ERROR("Data_Array size mismatch for sample '{}'.", GetSampleTitle(Sample));
917  MACH3LOG_ERROR("Expected size: {}, received size: {}.", ExpectedSize, Data_Array.size());
918  MACH3LOG_ERROR("Start bin: {}, End bin: {}.", Start, End);
919  MACH3LOG_ERROR("This likely indicates a binning or sample slicing bug.");
920  throw MaCh3Exception(__FILE__, __LINE__);
921  }
922 
923  std::copy_n(Data_Array.begin(), End-Start, SampleHandler_data.begin() + Start);
924 
925  FillHist(Sample, SampleDetails[Sample].DataHist, SampleHandler_data);
926 }
#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::vector< double > SampleHandler_data
DB Array to be filled in AddData.
std::string GetSampleTitle(const int iSample) const final
Get fancy title for specified samples.

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

837  {
838 // ************************************************
839  int Dim = GetNDim(Sample);
840  MACH3LOG_INFO("Adding {}D data histogram: {} with {:.2f} events", Dim, Data->GetTitle(), Data->Integral());
841  // delete old histogram
842  delete SampleDetails[Sample].DataHist;
843  SampleDetails[Sample].DataHist = static_cast<TH1*>(Data->Clone());
844 
845  if(!SampleHandler_data.size()) {
846  MACH3LOG_ERROR("SampleHandler_data haven't been initialised yet");
847  throw MaCh3Exception(__FILE__, __LINE__);
848  }
849 
850  auto ChecHistType = [&](const std::string& Type, const int Dimen, const TH1* Hist,
851  const std::string& file, const int line) {
852  if (std::string(Hist->ClassName()) != Type) {
853  MACH3LOG_ERROR("Expected {} for {}D sample, got {}", Type, Dimen, Hist->ClassName());
854  throw MaCh3Exception(file, line);
855  }
856  };
857 
858  if (Dim == 1) {
859  // Ensure we really have a TH1D
860  ChecHistType("TH1D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
861  M3::CheckBinningMatch(static_cast<TH1D*>(SampleDetails[Sample].DataHist),
862  static_cast<TH1D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
863  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
864  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin});
865  // ROOT histograms are 1-based, so bin index + 1
866  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(xBin + 1);
867  }
868  SampleDetails[Sample].DataHist->GetXaxis()->SetTitle(GetKinVarName(Sample, 0).c_str());
869  SampleDetails[Sample].DataHist->GetYaxis()->SetTitle("Number of Events");
870  } else if (Dim == 2) {
871  if(Binning->IsUniform(Sample)) {
872  ChecHistType("TH2D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
873  M3::CheckBinningMatch(static_cast<TH2D*>(SampleDetails[Sample].DataHist),
874  static_cast<TH2D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
875  for (int yBin = 0; yBin < Binning->GetNAxisBins(Sample, 1); ++yBin) {
876  for (int xBin = 0; xBin < Binning->GetNAxisBins(Sample, 0); ++xBin) {
877  const int idx = Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
878  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
879  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(xBin + 1, yBin + 1);
880  }
881  }
882  } else{
883  ChecHistType("TH2Poly", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
884  M3::CheckBinningMatch(static_cast<TH2Poly*>(SampleDetails[Sample].DataHist),
885  static_cast<TH2Poly*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
886  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
887  const int idx = iBin + Binning->GetSampleStartBin(Sample);
888  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
889  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(iBin + 1);
890  }
891  }
892 
893  SampleDetails[Sample].DataHist->GetXaxis()->SetTitle(GetKinVarName(Sample, 0).c_str());
894  SampleDetails[Sample].DataHist->GetYaxis()->SetTitle(GetKinVarName(Sample, 1).c_str());
895  SampleDetails[Sample].DataHist->GetZaxis()->SetTitle("Number of Events");
896  } else {
897  ChecHistType("TH1D", Dim, SampleDetails[Sample].DataHist, __FILE__, __LINE__);
898  M3::CheckBinningMatch(static_cast<TH1D*>(SampleDetails[Sample].DataHist),
899  static_cast<TH1D*>(SampleDetails[Sample].MCHist), __FILE__, __LINE__);
900  for (int iBin = 0; iBin < Binning->GetNBins(Sample); ++iBin) {
901  const int idx = iBin + Binning->GetSampleStartBin(Sample);
902  //Need to do +1 for the bin, this is to be consistent with ROOTs binning scheme
903  SampleHandler_data[idx] = SampleDetails[Sample].DataHist->GetBinContent(iBin + 1);
904  }
905  }
906 }
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 453 of file SampleHandlerBase.cpp.

453  {
454 // ***************************************************************************
455  // KS: If there are no shifts then there is no point in resetting which can be costly.
456  if(!functional.event_shifts.size() || !functional.event_shifts[iEvent].size()) {
457  return;
458  }
459 
460  // Given a sample and event, apply the shifts to the event based on the vector of functional parameter enums
461  // First reset shifted array back to nominal values
462  ResetShifts(iEvent);
463 
464  for (auto const &iShift : functional.event_shifts[iEvent]) {
465  auto & shift = functional.shifts[iShift];
466  shift.apply(shift.par_vals, iEvent);
467  }
468 
469  FinaliseShifts(iEvent);
470 }
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 1372 of file SampleHandlerBase.cpp.

1373  {
1374 // ************************************************
1375  // Backup current selection
1376  auto originalSelection = Selection;
1377 
1378  //DB Add all the predefined selections to the selection vector which will be applied
1379  auto selectionToApply = Selection;
1380 
1381  //DB Add all requested cuts from the argument to the selection vector which will be applied
1382  for (const auto& cut : ExtraCuts) {
1383  selectionToApply[iSample].emplace_back(cut);
1384  }
1385 
1386  //DB Set the member variable to be the cuts to apply
1387  Selection = std::move(selectionToApply);
1388 
1389  return originalSelection;
1390 }
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
iSampleIndex of the sample.

Definition at line 1705 of file SampleHandlerBase.cpp.

1705  {
1706 // ************************************************
1707  bool fChannel;
1708  bool fMode;
1709 
1710  if (kChannelToFill != -1) {
1711  if (kChannelToFill > GetNOscChannels(iSample)) {
1712  MACH3LOG_ERROR("Required channel is not available. kChannelToFill should be between 0 and {}", GetNOscChannels(iSample));
1713  MACH3LOG_ERROR("kChannelToFill given:{}", kChannelToFill);
1714  MACH3LOG_ERROR("Exiting.");
1715  throw MaCh3Exception(__FILE__, __LINE__);
1716  }
1717  fChannel = true;
1718  } else {
1719  fChannel = false;
1720  }
1721 
1722  if (kModeToFill != -1) {
1723  if (!(kModeToFill >= 0) && (kModeToFill < Modes->GetNModes())) {
1724  MACH3LOG_ERROR("Required mode is not available. kModeToFill should be between 0 and {}", Modes->GetNModes());
1725  MACH3LOG_ERROR("kModeToFill given:{}", kModeToFill);
1726  MACH3LOG_ERROR("Exiting..");
1727  throw MaCh3Exception(__FILE__, __LINE__);
1728  }
1729  fMode = true;
1730  } else {
1731  fMode = false;
1732  }
1733 
1734  std::vector< KinematicCut > SelectionVec;
1735 
1736  if (fMode) {
1737  KinematicCut SelecMode;
1739  SelecMode.LowerBound = kModeToFill;
1740  SelecMode.UpperBound = kModeToFill+1;
1741  SelectionVec.push_back(SelecMode);
1742  }
1743 
1744  if (fChannel) {
1745  KinematicCut SelecChannel;
1746  SelecChannel.ParamToCutOnIt = ReturnKinematicParameterFromString("OscillationChannel");
1747  SelecChannel.LowerBound = kChannelToFill;
1748  SelecChannel.UpperBound = kChannelToFill+1;
1749  SelectionVec.push_back(SelecChannel);
1750  }
1751 
1752  return SelectionVec;
1753 }
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 563 of file SampleHandlerBase.cpp.

563  {
564 // ************************************************
565  for(unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent){
566  std::vector< int > NormBins = {};
567  if (ParHandler) {
568  const auto SampleId = MCEvents[iEvent].NominalSample;
569  auto& NormParam = norm_parameters[SampleId];
570  // Skip oscillated NC events
571  // Not strictly needed, but these events don't get included in oscillated predictions, so
572  // no need to waste our time calculating and storing information about xsec/flux etc. parameters
573  // that will never be used.
574  if (MCEvents[iEvent].isNC && (MCEvents[iEvent].nupdg != MCEvents[iEvent].nupdgUnosc) ) {
575  MACH3LOG_TRACE("Event {}, missed NC/signal check", iEvent);
576  continue;
577  } //DB Abstract check on MaCh3Modes to determine which apply to neutral current
578  for (std::vector<NormParameter>::iterator it = NormParam.begin(); it != NormParam.end(); ++it) {
579  //Now check that the target of an interaction matches with the normalisation parameters
580  const int Target = static_cast<int>(std::round(ReturnKinematicParameter("TargetNucleus", iEvent)));
581  bool TargetMatch = MatchCondition(it->targets, Target);
582  if (!TargetMatch) {
583  MACH3LOG_TRACE("Event {}, missed target check ({}) for dial {}", iEvent, Target, it->name);
584  continue;
585  }
586 
587  //Now check that the neutrino flavour in an interaction matches with the normalisation parameters
588  bool FlavourMatch = MatchCondition(it->pdgs, MCEvents[iEvent].nupdg);
589  if (!FlavourMatch) {
590  MACH3LOG_TRACE("Event {}, missed PDG check ({}) for dial {}", iEvent,MCEvents[iEvent].nupdg, it->name);
591  continue;
592  }
593 
594  //Now check that the unoscillated neutrino flavour in an interaction matches with the normalisation parameters
595  bool FlavourUnoscMatch = MatchCondition(it->preoscpdgs, MCEvents[iEvent].nupdgUnosc);
596  if (!FlavourUnoscMatch){
597  MACH3LOG_TRACE("Event {}, missed FlavourUnosc check ({}) for dial {}", iEvent,MCEvents[iEvent].nupdgUnosc, it->name);
598  continue;
599  }
600 
601  //Now check that the mode of an interaction matches with the normalisation parameters
602  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", iEvent)));
603  bool ModeMatch = MatchCondition(it->modes, Mode);
604  if (!ModeMatch) {
605  MACH3LOG_TRACE("Event {}, missed Mode check ({}) for dial {}", iEvent, Mode, it->name);
606  continue;
607  }
608 
609  //Now check whether the norm has kinematic bounds
610  //i.e. does it only apply to events in a particular kinematic region?
611  // Now check whether within kinematic bounds
612  bool IsSelected = PassesSelection((*it), iEvent);
613  // Need to then break the event loop
614  if(!IsSelected){
615  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", iEvent, it->name);
616  continue;
617  }
618  // Now set 'index bin' for each normalisation parameter
619  // All normalisations are just 1 bin for 2015, so bin = index (where index is just the bin for that normalisation)
620  int bin = it->index;
621 
622  NormBins.push_back(bin);
623  MACH3LOG_TRACE("Event {}, will be affected by dial {}", iEvent, it->name);
624  } // end iteration over norm_parameters
625  } // end if (ParHandler)
626  norms_bins[iEvent] = NormBins;
627  }//end loop over events
628 }
#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 335 of file SampleHandlerBase.h.

335 {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 474 of file SampleHandlerBase.cpp.

474  {
475 // ***************************************************************************
476  M3::float_t TotalWeight = 1.0;
477  const int TotalWeights = static_cast<int>(MCEvent->total_weight_pointers.size());
478  //DB Loop over stored pointers
479  #ifdef MULTITHREAD
480  #pragma omp simd reduction(*:TotalWeight)
481  #endif
482  for (int iWeight = 0; iWeight < TotalWeights; ++iWeight) {
483  TotalWeight *= *(MCEvent->total_weight_pointers[iWeight]);
484  }
485 
486  return TotalWeight;
487 }
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 2001 of file SampleHandlerBase.cpp.

2001  {
2002 // ***************************************************************************
2003  const auto TotalBins = Binning->GetNBins();
2004  int iCounter = 0;
2005  for(int iBin = 0; iBin < TotalBins; iBin++) {
2006  if(SampleHandler_array[iBin] == 0) {
2007  iCounter++;
2008  MACH3LOG_DEBUG("Bin {}, for sample {}, has 0 entries",
2009  Binning->GetBinName(iBin), GetSampleTitle(Binning->GetSampleIndex(iBin)));
2010  }
2011  }
2012 
2013  if(iCounter > 0){
2014  MACH3LOG_WARN("Found in total {} ({:.2f}%) empty bins for SampleHandler: {}",
2015  iCounter, 100.0 * static_cast<double>(iCounter) / TotalBins, GetName());
2016  }
2017 }
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 1437 of file SampleHandlerBase.cpp.

1438  {
1439 // ************************************************
1440  int ProjectionVar_Int = ReturnKinematicVectorFromString(ProjectionVar_Str);
1441 
1442  //JM Loop over all events
1443  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1444  const int EventSample = MCEvents[iEvent].NominalSample;
1445  if(EventSample != iSample) continue;
1446  if (IsEventSelected(EventSample, iEvent)) {
1447  double Weight = GetEventWeight(iEvent);
1448  if (WeightStyle == 1) {
1449  Weight = 1.;
1450  }
1451  std::vector<double> Vec = ReturnKinematicVector(ProjectionVar_Int,iEvent);
1452  size_t nsubevents = Vec.size();
1453  //JM Loop over all subevents in event
1454  for (unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1455  if (IsSubEventSelected(SubEventSelectionVec, iEvent, iSubEvent, nsubevents)) {
1456  double Var = Vec[iSubEvent];
1457  _h1DVar->Fill(Var,Weight);
1458  }
1459  }
1460  }
1461  }
1462 }
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 1521 of file SampleHandlerBase.cpp.

1525  {
1526 // ************************************************
1527  bool IsSubEventVarX = IsSubEventVarString(ProjectionVar_StrX);
1528  bool IsSubEventVarY = IsSubEventVarString(ProjectionVar_StrY);
1529 
1530  int ProjectionVar_IntX, ProjectionVar_IntY;
1531  if (IsSubEventVarX) ProjectionVar_IntX = ReturnKinematicVectorFromString(ProjectionVar_StrX);
1532  else ProjectionVar_IntX = ReturnKinematicParameterFromString(ProjectionVar_StrX);
1533  if (IsSubEventVarY) ProjectionVar_IntY = ReturnKinematicVectorFromString(ProjectionVar_StrY);
1534  else ProjectionVar_IntY = ReturnKinematicParameterFromString(ProjectionVar_StrY);
1535 
1536  //JM Loop over all events
1537  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1538  const int EventSample = MCEvents[iEvent].NominalSample;
1539  if(EventSample != iSample) continue;
1540  if (IsEventSelected(EventSample, iEvent)) {
1541  double Weight = GetEventWeight(iEvent);
1542  if (WeightStyle == 1) {
1543  Weight = 1.;
1544  }
1545  std::vector<double> VecX = {}, VecY = {};
1546  double VarX = M3::_BAD_DOUBLE_, VarY = M3::_BAD_DOUBLE_;
1547  size_t nsubevents = 0;
1548  // JM Three cases: subeventX vs eventY || eventX vs subeventY || subeventX vs subeventY
1549  if (IsSubEventVarX && !IsSubEventVarY) {
1550  VecX = ReturnKinematicVector(ProjectionVar_IntX, iEvent);
1551  VarY = ReturnKinematicParameter(ProjectionVar_IntY, iEvent);
1552  nsubevents = VecX.size();
1553  }
1554  else if (!IsSubEventVarX && IsSubEventVarY) {
1555  VecY = ReturnKinematicVector(ProjectionVar_IntY, iEvent);
1556  VarX = ReturnKinematicParameter(ProjectionVar_IntX, iEvent);
1557  nsubevents = VecY.size();
1558  }
1559  else {
1560  VecX = ReturnKinematicVector(ProjectionVar_IntX, iEvent);
1561  VecY = ReturnKinematicVector(ProjectionVar_IntY, iEvent);
1562  if (VecX.size() != VecY.size()) {
1563  MACH3LOG_ERROR("Cannot plot {} of size {} against {} of size {}", ProjectionVar_StrX, VecX.size(), ProjectionVar_StrY, VecY.size());
1564  throw MaCh3Exception(__FILE__, __LINE__);
1565  }
1566  nsubevents = VecX.size();
1567  }
1568  //JM Loop over all subevents in event
1569  for (unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1570  if (IsSubEventSelected(SubEventSelectionVec, iEvent, iSubEvent, nsubevents)) {
1571  if (IsSubEventVarX) VarX = VecX[iSubEvent];
1572  if (IsSubEventVarY) VarY = VecY[iSubEvent];
1573  _h2DVar->Fill(VarX,VarY,Weight);
1574  }
1575  }
1576  }
1577  }
1578 }
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. This assumes that oscillation weights have already been calculated.

Definition at line 377 of file SampleHandlerBase.cpp.

377  {
378 // ************************************************
379  //DB Reset which cuts to apply
381 
382  // NOTE comment below is left for historical reasons
383  //DB - Brain dump of speedup ideas
384  //
385  //Those relevant to reweighting
386  // 1. Don't bother storing and calculating NC signal events - Implemented and saves marginal s/step
387  // 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
388  // 3. Inline getDiscVar or somehow include that calculation inside the multi-threading - Implemented and saves about 0.01s/step
389  // 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
390  // 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
391  //
392  //Other aspects
393  // 1. Order minituples in Y-axis variable as this will *hopefully* reduce cache misses inside SampleHandler_array_class[yBin][xBin]
394  //
395  // We will hit <0.1 s/step eventually! :D
396  [[maybe_unused]] const auto TotalBins = Binning->GetNBins();
397  const unsigned int NumberOfEvents = GetNEvents();
398 
399  double* _restrict_ MC_Array_for_reduction = SampleHandler_array.data();
400  double* _restrict_ W2_array_for_reduction = SampleHandler_array_w2.data();
401  #ifdef MULTITHREAD
402  #pragma omp parallel for reduction(+:MC_Array_for_reduction[:TotalBins], W2_array_for_reduction[:TotalBins])
403  #endif
404  for (unsigned int iEvent = 0; iEvent < NumberOfEvents; ++iEvent) {
405  //ETA - generic functions to apply shifts to kinematic variables
406  // Apply this before IsEventSelected is called.
407  ApplyShifts(iEvent);
408 
409  const EventInfo* _restrict_ MCEvent = &MCEvents[iEvent];
410  //ETA - generic functions to apply shifts to kinematic variable
411  if(!IsEventSelected(MCEvent->NominalSample, iEvent)){
412  continue;
413  }
414 
415  // Virtual by default does nothing, has to happen before CalcWeightTotal
416  CalcWeightFunc(iEvent);
417 
418  const M3::float_t totalweight = CalcWeightTotal(MCEvent);
419  //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
420  if (totalweight <= 0.){
421  continue;
422  }
423 
424  //DB Find the relevant bin in the PDF for each event
425  const int GlobalBin = Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
426 
427  //ETA - we can probably remove this final if check on the -1?
428  //Maybe we can add an overflow bin to the array and assign any events to this bin?
429  //Might save us an extra if call?
430  //DB Fill relevant part of thread array
431  if (GlobalBin > M3::UnderOverFlowBin) {
432  MC_Array_for_reduction[GlobalBin] += totalweight;
433  if (FirstTimeW2) W2_array_for_reduction[GlobalBin] += totalweight*totalweight;
434  }
435  }
436 }
#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

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

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

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

315 {};

◆ FindNominalBinAndEdges()

void SampleHandlerBase::FindNominalBinAndEdges ( )
protected

Functions which find the nominal bin and bin edges.

Definition at line 740 of file SampleHandlerBase.cpp.

740  {
741 // ************************************************
742  for (unsigned int event_i = 0; event_i < GetNEvents(); event_i++) {
743  int Sample = MCEvents[event_i].NominalSample;
744  const int dim = GetNDim(Sample);
745  MCEvents[event_i].KinVar.resize(dim);
746  MCEvents[event_i].NomBin.resize(dim);
747 
748  auto SetNominalBin = [&](int bin, int max_bins, int& out_bin) {
749  if (bin >= 0 && bin < max_bins) {
750  out_bin = bin;
751  } else {
752  out_bin = M3::UnderOverFlowBin; // Out of bounds
753  }
754  };
755 
756  // Find nominal bin for each dimension
757  for(int iDim = 0; iDim < dim; iDim++) {
758  MCEvents[event_i].KinVar[iDim] = GetPointerToKinematicParameter(GetKinVarName(Sample, iDim), event_i);
759  if (std::isnan(*MCEvents[event_i].KinVar[iDim]) || std::isinf(*MCEvents[event_i].KinVar[iDim])) {
760  MACH3LOG_ERROR("Variable {} for sample {} and dimension {} is ill-defined and equal to {}",
761  GetKinVarName(Sample, iDim), GetSampleTitle(Sample), dim, *MCEvents[event_i].KinVar[iDim]);
762  throw MaCh3Exception(__FILE__, __LINE__);
763  }
764  const int bin = Binning->FindNominalBin(Sample, iDim, *MCEvents[event_i].KinVar[iDim]);
765  int NBins_i = static_cast<int>(Binning->GetBinEdges(Sample, iDim).size() - 1);
766  SetNominalBin(bin, NBins_i, MCEvents[event_i].NomBin[iDim]);
767  }
768  }
769 }
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 1394 of file SampleHandlerBase.cpp.

1397  {
1398 // ************************************************
1399  //DB Need to overwrite the Selection member variable so that IsEventSelected function operates correctly.
1400  // Consequently, store the selection cuts already saved in the sample, overwrite the Selection variable, then reset
1401  auto tmp_Selection = ApplyTemporarySelection(iSample, EventSelectionVec);
1402 
1403  //DB Define the histogram which will be returned
1404  std::vector<double> xBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_Str);
1405  auto _h1DVar = std::make_unique<TH1D>("", "", int(xBinEdges.size())-1, xBinEdges.data());
1406  _h1DVar->SetDirectory(nullptr);
1407  _h1DVar->GetXaxis()->SetTitle(ProjectionVar_Str.c_str());
1408  _h1DVar->GetYaxis()->SetTitle("Events");
1409 
1410  if (IsSubEventVarString(ProjectionVar_Str)) {
1411  Fill1DSubEventHist(iSample, _h1DVar.get(), ProjectionVar_Str, SubEventSelectionVec, WeightStyle);
1412  } else {
1413  //DB Grab the associated enum with the argument string
1414  int ProjectionVar_Int = ReturnKinematicParameterFromString(ProjectionVar_Str);
1415 
1416  //DB Loop over all events
1417  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1418  const int EventSample = MCEvents[iEvent].NominalSample;
1419  if(EventSample != iSample) continue;
1420  if (IsEventSelected(EventSample, iEvent)) {
1421  double Weight = GetEventWeight(iEvent);
1422  if (WeightStyle == 1) {
1423  Weight = 1.;
1424  }
1425  double Var = ReturnKinematicParameter(ProjectionVar_Int, iEvent);
1426  _h1DVar->Fill(Var, Weight);
1427  }
1428  }
1429  }
1430  //DB Reset the saved selection
1431  Selection = tmp_Selection;
1432 
1433  return _h1DVar;
1434 }
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 1756 of file SampleHandlerBase.cpp.

1757  {
1758 // ************************************************
1759  auto SelectionVec = BuildModeChannelSelection(iSample, kModeToFill, kChannelToFill);
1760  return Get1DVarHist(iSample, ProjectionVar_Str, SelectionVec, WeightStyle);
1761 }
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 1465 of file SampleHandlerBase.cpp.

1470  {
1471 // ************************************************
1472  //DB Need to overwrite the Selection member variable so that IsEventSelected function operates correctly.
1473  // Consequently, store the selection cuts already saved in the sample, overwrite the Selection variable, then reset
1474  auto tmp_Selection = ApplyTemporarySelection(iSample, EventSelectionVec);
1475 
1476  //DB Define the histogram which will be returned
1477  //KS: If we use 2D non uniform binning and wanting to plot fit variables use TH2Poly everything else uses TH2D with binning from config
1478  std::unique_ptr<TH2> _h2DVar;
1479  if(GetNDim(iSample) == 2 && !Binning->IsUniform(iSample) &&
1480  ProjectionVar_StrX == GetKinVarName(iSample, 0) && ProjectionVar_StrY == GetKinVarName(iSample, 1) ) {
1481  _h2DVar = std::unique_ptr<TH2>(static_cast<TH2*>(M3::Clone(GetMCHist(iSample)).release()));
1482  } else {
1483  std::vector<double> xBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_StrX);
1484  std::vector<double> yBinEdges = ReturnKinematicParameterBinning(iSample, ProjectionVar_StrY);
1485  _h2DVar = std::make_unique<TH2D>("", "", int(xBinEdges.size())-1, xBinEdges.data(), int(yBinEdges.size())-1, yBinEdges.data());
1486  }
1487  _h2DVar->SetDirectory(nullptr);
1488  _h2DVar->GetXaxis()->SetTitle(ProjectionVar_StrX.c_str());
1489  _h2DVar->GetYaxis()->SetTitle(ProjectionVar_StrY.c_str());
1490  _h2DVar->GetZaxis()->SetTitle("Events");
1491 
1492  bool IsSubEventHist = IsSubEventVarString(ProjectionVar_StrX) || IsSubEventVarString(ProjectionVar_StrY);
1493  if (IsSubEventHist) Fill2DSubEventHist(iSample, _h2DVar.get(), ProjectionVar_StrX, ProjectionVar_StrY, SubEventSelectionVec, WeightStyle);
1494  else {
1495  //DB Grab the associated enum with the argument string
1496  int ProjectionVar_IntX = ReturnKinematicParameterFromString(ProjectionVar_StrX);
1497  int ProjectionVar_IntY = ReturnKinematicParameterFromString(ProjectionVar_StrY);
1498 
1499  //DB Loop over all events
1500  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
1501  const int EventSample = MCEvents[iEvent].NominalSample;
1502  if(EventSample != iSample) continue;
1503  if (IsEventSelected(EventSample, iEvent)) {
1504  double Weight = GetEventWeight(iEvent);
1505  if (WeightStyle == 1) {
1506  Weight = 1.;
1507  }
1508  double VarX = ReturnKinematicParameter(ProjectionVar_IntX, iEvent);
1509  double VarY = ReturnKinematicParameter(ProjectionVar_IntY, iEvent);
1510  _h2DVar->Fill(VarX,VarY,Weight);
1511  }
1512  }
1513  }
1514  //DB Reset the saved selection
1515  Selection = tmp_Selection;
1516 
1517  return _h2DVar;
1518 }
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 1764 of file SampleHandlerBase.cpp.

1766  {
1767 // ************************************************
1768  auto SelectionVec = BuildModeChannelSelection(iSample, kModeToFill, kChannelToFill);
1769  return Get2DVarHist(iSample, ProjectionVar_StrX, ProjectionVar_StrY, SelectionVec, WeightStyle);
1770 }
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 2083 of file SampleHandlerBase.cpp.

2083  {
2084 // ***************************************************************************
2085  const int Start = Binning->GetSampleStartBin(Sample);
2086  const int End = Binning->GetSampleEndBin(Sample);
2087 
2088  return std::vector<double>(array.begin() + Start, array.begin() + End);
2089 }

◆ GetDataArray() [1/2]

auto SampleHandlerBase::GetDataArray ( ) const
inline

Return array storing data entries for every bin.

Definition at line 180 of file SampleHandlerBase.h.

180  {
181  return SampleHandler_data;
182  }

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

196  {
197  return GetArrayForSample(Sample, SampleHandler_data);
198  }
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 820 of file SampleHandlerBase.cpp.

820  {
821 // ************************************************
822  if(SampleDetails[Sample].DataHist == nullptr) {
823  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
824  throw MaCh3Exception(__FILE__, __LINE__);
825  }
826  return SampleDetails[Sample].DataHist;
827 }

◆ GetDataHist() [2/2]

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

Get Data histogram by sample name.

Parameters
SampleSample title

Definition at line 830 of file SampleHandlerBase.cpp.

830  {
831 // ************************************************
832  int Index = GetSampleIndex(Sample);
833  return GetDataHist(Index);
834 }
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 1144 of file SampleHandlerBase.cpp.

1144  {
1145 // ************************************************
1147 
1148  // Virtual by default does nothing, has to happen before CalcWeightTotal
1149  CalcWeightFunc(iEntry);
1150 
1151  const EventInfo* _restrict_ MCEvent = &MCEvents[iEntry];
1152  M3::float_t totalweight = CalcWeightTotal(MCEvent);
1153 
1154  //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
1155  if (totalweight <= 0.){
1156  totalweight = 0.;
1157  }
1158  return totalweight;
1159 }

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

453 {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 110 of file SampleHandlerBase.h.

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

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

451 {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 2073 of file SampleHandlerBase.cpp.

2073  {
2074 // ***************************************************************************
2075  if(Dimension > GetNDim(iSample)) {
2076  MACH3LOG_ERROR("Asking for dimension {}, while sample: {} only has {}", Dimension, GetSampleTitle(iSample), GetNDim(iSample));
2077  throw MaCh3Exception(__FILE__, __LINE__);
2078  }
2079  return SampleDetails[iSample].VarStr[Dimension];
2080 }

◆ GetLikelihood()

double SampleHandlerBase::GetLikelihood ( ) const
overridevirtual

Return likelihood (-LogL) for all samples.

Implements SampleHandlerInterface.

Definition at line 1260 of file SampleHandlerBase.cpp.

1260  {
1261 // ************************************************
1262  double negLogL = 0.;
1263  #ifdef MULTITHREAD
1264  #pragma omp parallel for reduction(+:negLogL)
1265  #endif
1266  for (int idx = 0; idx < Binning->GetNBins(); ++idx)
1267  {
1268  double const &DataVal = SampleHandler_data[idx];
1269  double const &MCPred = SampleHandler_array[idx];
1270  double const &w2 = SampleHandler_array_w2[idx];
1271 
1272  //KS: Calculate likelihood using Barlow-Beeston Poisson or even IceCube
1273  negLogL += GetTestStatLLH(DataVal, MCPred, w2);
1274  }
1275  return negLogL;
1276 }
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 184 of file SampleHandlerBase.h.

184  {
185  return SampleHandler_array;
186  }

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

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

◆ GetMCHist() [1/2]

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

Get MC histogram.

Parameters
SampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 802 of file SampleHandlerBase.cpp.

802  {
803 // ************************************************
804  FillHist(Sample, SampleDetails[Sample].MCHist, SampleHandler_array);
805  if(SampleDetails[Sample].MCHist == nullptr) {
806  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
807  throw MaCh3Exception(__FILE__, __LINE__);
808  }
809  return SampleDetails[Sample].MCHist;
810 }

◆ GetMCHist() [2/2]

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

Get MC histogram by sample title.

Parameters
SampleSample name

Definition at line 813 of file SampleHandlerBase.cpp.

813  {
814 // ************************************************
815  const int Index = GetSampleIndex(Sample);
816  return GetMCHist(Index);
817 }

◆ GetName()

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

Get name for Sample Handler.

Implements SampleHandlerInterface.

Definition at line 1131 of file SampleHandlerBase.cpp.

1131  {
1132 // ************************************************
1133  //ETA - extra safety to make sure SampleHandlerName is actually set
1134  // probably unnecessary due to the requirement for it to be in the yaml config
1135  if(SampleHandlerName.length() == 0) {
1136  MACH3LOG_ERROR("No sample name provided");
1137  MACH3LOG_ERROR("Please provide a SampleHandlerName in your configuration file: {}", SampleManager->GetFileName());
1138  throw MaCh3Exception(__FILE__, __LINE__);
1139  }
1140  return SampleHandlerName;
1141 }

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

177 {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 108 of file SampleHandlerBase.h.

108 {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 1091 of file SampleHandlerBase.cpp.

1091  {
1092 // ************************************************
1093  const M3::float_t* osc_w_pointer = &M3::Unity;
1094  if (MCEvents[iEvent].isNC) {
1095  if (MCEvents[iEvent].nupdg != MCEvents[iEvent].nupdgUnosc) {
1096  osc_w_pointer = &M3::Zero;
1097  } else {
1098  osc_w_pointer = &M3::Unity;
1099  }
1100  } else {
1101  int InitFlav = M3::_BAD_INT_;
1102  int FinalFlav = M3::_BAD_INT_;
1103 
1104  InitFlav = M3::Utils::PDGToNuOscillatorFlavour(MCEvents[iEvent].nupdgUnosc);
1105  FinalFlav = M3::Utils::PDGToNuOscillatorFlavour(MCEvents[iEvent].nupdg);
1106 
1107  if (InitFlav == M3::_BAD_INT_ || FinalFlav == M3::_BAD_INT_) {
1108  MACH3LOG_ERROR("Something has gone wrong in the mapping between MCEvents.nutype and the enum used within NuOscillator");
1109  MACH3LOG_ERROR("MCEvents.nupdgUnosc: {}", MCEvents[iEvent].nupdgUnosc);
1110  MACH3LOG_ERROR("InitFlav: {}", InitFlav);
1111  MACH3LOG_ERROR("MCEvents.nupdg: {}", MCEvents[iEvent].nupdg);
1112  MACH3LOG_ERROR("FinalFlav: {}", FinalFlav);
1113  throw MaCh3Exception(__FILE__, __LINE__);
1114  }
1115  const int Sample = MCEvents[iEvent].NominalSample;
1116 
1117  const int OscIndex = GetOscChannel(SampleDetails[Sample].OscChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1118  //Can only happen if truecz has been initialised within the experiment specific code
1119  if (MCEvents[iEvent].coszenith_true != M3::_BAD_DOUBLE_) {
1120  //Atmospherics
1121  osc_w_pointer = Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(MCEvents[iEvent].enu_true), FLOAT_T(MCEvents[iEvent].coszenith_true));
1122  } else {
1123  //Beam
1124  osc_w_pointer = Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(MCEvents[iEvent].enu_true));
1125  }
1126  } // end if NC
1127  return osc_w_pointer;
1128 }
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 355 of file SampleHandlerBase.h.

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

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

1993  {
1994 // ************************************************
1995  auto& OscillationChannels = SampleDetails[MCEvents[iEvent].NominalSample].OscChannels;
1996  const int Channel = GetOscChannel(OscillationChannels, MCEvents[iEvent].nupdgUnosc, MCEvents[iEvent].nupdg);
1997  return &(OscillationChannels[Channel].ChannelIndex);
1998 }

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

1916  {
1917 // ************************************************
1918  switch (TypeEnum) {
1920  return Modes->GetNModes();
1921  break;
1923  return GetNOscChannels(iSample);
1924  break;
1925  default:
1926  MACH3LOG_ERROR("You've passed me a SamplePlotType with value {} which was not implemented.", static_cast<int>(TypeEnum));
1927  throw MaCh3Exception(__FILE__, __LINE__);
1928  }
1929 }
@ 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 772 of file SampleHandlerBase.cpp.

772  {
773 // ************************************************
774  for (M3::int_t iSample = 0; iSample < nSamples; ++iSample) {
775  if (SampleTitle == GetSampleTitle(iSample)) {
776  return iSample;
777  }
778  }
779  MACH3LOG_ERROR("Sample name not found: {}", SampleTitle);
780  throw MaCh3Exception(__FILE__, __LINE__);
781 }
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 1238 of file SampleHandlerBase.cpp.

1238  {
1239 // ************************************************
1240  const int Start = Binning->GetSampleStartBin(isample);
1241  const int End = Binning->GetSampleEndBin(isample);
1242 
1243  double negLogL = 0.;
1244  #ifdef MULTITHREAD
1245  #pragma omp parallel for reduction(+:negLogL)
1246  #endif
1247  for (int idx = Start; idx < End; ++idx)
1248  {
1249  double const &DataVal = SampleHandler_data[idx];
1250  double const &MCPred = SampleHandler_array[idx];
1251  double const &w2 = SampleHandler_array_w2[idx];
1252 
1253  //KS: Calculate likelihood using Barlow-Beeston Poisson or even IceCube
1254  negLogL += GetTestStatLLH(DataVal, MCPred, w2);
1255  }
1256  return negLogL;
1257 }

◆ GetSampleName()

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

Sample name tag used only for getting relevant uncertainties.

Parameters
iSampleIndex of the sample.

Definition at line 54 of file SampleHandlerBase.h.

54 {return SampleDetails[iSample].SampleName;}

◆ GetSampleTitle()

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

Get fancy title for specified samples.

Parameters
iSampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 51 of file SampleHandlerBase.h.

51 {return SampleDetails[iSample].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 1162 of file SampleHandlerBase.cpp.

1162  {
1163 // ************************************************
1164  const int SampleIndex = MCEvents[Event].NominalSample;
1165  const auto SampleTitle = GetSampleTitle(SampleIndex);
1166  bool NoOscChannels = false;
1167  if(Oscillator == nullptr && GetNOscChannels(SampleIndex) == 1) {
1168  MACH3LOG_DEBUG("Assuming there are no osc channels in {}", __func__);
1169  NoOscChannels = true;
1170  }
1171  const int OscIndex = NoOscChannels ? 0 : GetOscChannel(SampleDetails[SampleIndex].OscChannels,
1172  MCEvents[Event].nupdgUnosc, MCEvents[Event].nupdg);
1173  const int Mode = static_cast<int>(std::round(ReturnKinematicParameter("Mode", Event)));
1174  const double Etrue = MCEvents[Event].enu_true;
1175  std::vector< SplineIndex > EventSplines;
1176  switch(GetNDim(SampleIndex)) {
1177  case 1:
1178  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, {Etrue, *(MCEvents[Event].KinVar[0]), 0.});
1179  break;
1180  case 2:
1181  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, {Etrue, *(MCEvents[Event].KinVar[0]), *(MCEvents[Event].KinVar[1])});
1182  break;
1183  default:
1184  if(ThrowCrititcal) {
1185  MACH3LOG_CRITICAL("MaCh3 doesn't support binned splines for more than 2D while you use {}", GetNDim(SampleIndex));
1186  MACH3LOG_CRITICAL("Will use 2D like approach");
1187  ThrowCrititcal = false;
1188  }
1189  EventSplines = BinnedSpline->GetEventSplines(SampleTitle, OscIndex, Mode, {Etrue, *(MCEvents[Event].KinVar[0]), *(MCEvents[Event].KinVar[1])});
1190  break;
1191  }
1192  return EventSplines;
1193 }
std::vector< SplineIndex > GetEventSplines(const std::string &SampleTitle, int iOscChan, int EventMode, const std::vector< double > &VarVals)
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 188 of file SampleHandlerBase.h.

188  {
189  return SampleHandler_array_w2;
190  }

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

206  {
208  }

◆ GetW2Hist() [1/2]

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

Get W2 histogram.

Parameters
SampleSample enumerator

Implements SampleHandlerInterface.

Definition at line 784 of file SampleHandlerBase.cpp.

784  {
785 // ************************************************
786  FillHist(Sample, SampleDetails[Sample].W2Hist, SampleHandler_array_w2);
787  if(SampleDetails[Sample].W2Hist == nullptr) {
788  MACH3LOG_ERROR("Can't access {} for {}Dimensions", __func__, GetNDim(Sample));
789  throw MaCh3Exception(__FILE__, __LINE__);
790  }
791  return SampleDetails[Sample].W2Hist;
792 }

◆ GetW2Hist() [2/2]

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

Get W2 histogram by sample name.

Parameters
SampleSample title

Definition at line 795 of file SampleHandlerBase.cpp.

795  {
796 // ************************************************
797  const int Index = GetSampleIndex(Sample);
798  return GetW2Hist(Index);
799 }
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 197 of file SampleHandlerBase.cpp.

197  {
198 // ************************************************
199  TStopwatch clock;
200  clock.Start();
201 
202  //First grab all the information from your sample config via your manager
203  ReadConfig();
204 
205  //Now initialise all the variables you will need
206  Init();
207 
209  MCEvents.resize(nEvents);
210  SetupMC();
211 
212  MACH3LOG_INFO("=============================================");
213  MACH3LOG_INFO("Total number of events is: {}", GetNEvents());
215  MACH3LOG_INFO("Setting up Sample Binning..");
216  SetBinning();
217  MACH3LOG_INFO("Setting up Splines..");
218  SetupSplines();
219  MACH3LOG_INFO("Setting up Normalisation Pointers..");
221  MACH3LOG_INFO("Setting up Functional Pointers..");
223  MACH3LOG_INFO("Setting up Additional Weight Pointers..");
225  MACH3LOG_INFO("Setting up Kinematic Map..");
227  clock.Stop();
228  MACH3LOG_INFO("Finished loading MC for {}, it took {:.2f}s to finish", GetName(), clock.RealTime());
229  MACH3LOG_INFO("Initialising Data");
231  MACH3LOG_INFO("=======================================================");
232  CheckEmptyBins();
233 }
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 929 of file SampleHandlerBase.cpp.

929  {
930  // ************************************************
931  auto NuOscillatorConfigFile = Get<std::string>(SampleManager->raw()["NuOsc"]["NuOscConfigFile"], __FILE__ , __LINE__);
932  auto EqualBinningPerOscChannel = Get<bool>(SampleManager->raw()["NuOsc"]["EqualBinningPerOscChannel"], __FILE__ , __LINE__);
933 
934  // TN override the sample setting if not using binned oscillation
935  if (EqualBinningPerOscChannel) {
936  if (YAML::LoadFile(NuOscillatorConfigFile)["General"]["CalculationType"].as<std::string>() == "Unbinned") {
937  MACH3LOG_WARN("Tried using EqualBinningPerOscChannel while using Unbinned oscillation calculation, changing EqualBinningPerOscChannel to false");
938  EqualBinningPerOscChannel = false;
939  }
940  }
941 
942  std::vector<OscillationParameter> OscParams{};
943  for (int iSample = 0; iSample < GetNSamples(); iSample++) {
944  auto sample_osc_pars = ParHandler->GetOscParsFromSampleName(GetSampleName(iSample));
945  if (!iSample) {
946  if (sample_osc_pars.empty()) {
947  MACH3LOG_ERROR("OscParams is empty for SampleHandler/Sample {}/{}.", GetName(), GetSampleName(iSample));
948  MACH3LOG_ERROR("This indicates an error in your oscillation YAML configuration.");
949  throw MaCh3Exception(__FILE__, __LINE__);
950  }
951  OscParams = sample_osc_pars;
952  } else {
953  if (sample_osc_pars.size() != OscParams.size()) {
954  MACH3LOG_ERROR("SampleHandler/Sample {}/{} has {} osc params while Sample {} has {}",
955  GetName(), GetSampleName(iSample), sample_osc_pars.size(), 0, GetSampleName(0));
956  throw MaCh3Exception(__FILE__, __LINE__);
957  }
958  }
959  }
960 
961  std::vector<const M3::float_t*> OscParamsValues(OscParams.size());
962  std::vector<std::string> NuOscName(OscParams.size());
963  for(size_t ij = 0; ij < OscParams.size(); ij++){
964  OscParamsValues[ij] = ParHandler->RetPointer(OscParams[ij].index);
965  NuOscName[ij] = OscParams[ij].NuOscName;
966  }
967 
968  if (EqualBinningPerOscChannel) {
969  Oscillator = std::make_shared<OscillationHandler>(NuOscillatorConfigFile, EqualBinningPerOscChannel, OscParamsValues,
970  NuOscName, GetNOscChannels(0));
971  } else {
972  // aim is to build energy/cosz arrays per oscillation channel so that
973  // NuOscillator can decide on the binning
974  std::vector<std::map<std::pair<int, int>, std::vector<M3::float_t>>>
975  channel_energy_array(GetNSamples()),
976  channel_cosz_array(GetNSamples());
977  for (unsigned int iEvent = 0; iEvent < GetNEvents(); iEvent++) {
978  if (MCEvents[iEvent].NominalSample >= GetNSamples()) {
979  MACH3LOG_ERROR("Encountered Event with NominalSample: {}, but "
980  "SampleHandler {} only has {} samples.",
981  MCEvents[iEvent].NominalSample, GetName(),
982  GetNSamples());
983  throw MaCh3Exception(__FILE__, __LINE__);
984  }
985 
986  if (MCEvents[iEvent].isNC) { // skip NC events
987  continue;
988  }
989 #pragma GCC diagnostic push
990 #pragma GCC diagnostic ignored "-Wuseless-cast"
991  channel_energy_array[MCEvents[iEvent].NominalSample] // sample
992  [std::make_pair(MCEvents[iEvent].nupdgUnosc,
993  MCEvents[iEvent].nupdg)] // osc chan
994  .push_back(M3::float_t(MCEvents[iEvent].enu_true)); // energy
995 
996  // DB Atmospheric only part, can only happen if truecz has been
997  // initialised within the experiment specific code
998  if (MCEvents[0].coszenith_true != M3::_BAD_DOUBLE_) {
999  channel_cosz_array[MCEvents[iEvent].NominalSample] // sample
1000  [std::make_pair(MCEvents[iEvent].nupdgUnosc,
1001  MCEvents[iEvent].nupdg)] // osc chan
1002  .push_back(M3::float_t(MCEvents[iEvent].coszenith_true)); // cosz
1003  }
1004 #pragma GCC diagnostic pop
1005  }
1006 
1007  for (int iSample = 0; iSample < GetNSamples(); iSample++) {
1008  if (!channel_energy_array[iSample].size()) { // sample had no events
1009  continue;
1010  }
1011 
1012  // loop through channels and check they were defined in config, or add
1013  // them if not
1014  for (auto const &[osc_flavs, energies] : channel_energy_array[iSample]) {
1015  bool found = false;
1016  for (size_t i = 0; i < SampleDetails[iSample].OscChannels.size(); ++i) {
1017  if (osc_flavs.first == SampleDetails[iSample].OscChannels[i].InitPDG &&
1018  osc_flavs.second == SampleDetails[iSample].OscChannels[i].FinalPDG) {
1019  found = true;
1020  break;
1021  }
1022  }
1023  if(found) { // already have this channel defined.
1024  continue;
1025  }
1026 
1027  static const std::map<int, std::pair<std::string, std::string>> spec_defnames = {
1028  {12, {"nue", "#nu_{e}"}},
1029  {-12, {"nueb", "#bar{#nu}_{e}"}},
1030  {14, {"numu", "#nu_{#mu}"}},
1031  {-14, {"nuemub", "#bar{#nu}_{#mu}"}},
1032  {16, {"nutau", "#nu_{#tau}"}},
1033  {-16, {"nutaub", "#bar{#nu}_{#tau}"}},
1034  };
1035 
1036  OscChannelInfo oci;
1037  oci.InitPDG = osc_flavs.first;
1038  oci.FinalPDG = osc_flavs.second;
1039  oci.flavourName = fmt::format("{}_x_{}", spec_defnames.at(osc_flavs.first).first,
1040  spec_defnames.at(osc_flavs.second).first);
1041  oci.flavourName_Latex =
1042  fmt::format("{} #rightarrow {}", spec_defnames.at(osc_flavs.first).second,
1043  spec_defnames.at(osc_flavs.second).second);
1044  oci.ChannelIndex = double(SampleDetails[iSample].OscChannels.size());
1045 
1046  SampleDetails[iSample].OscChannels.push_back(oci);
1047  }
1048 
1049  // set up oscillator for this sample
1050  if (!Oscillator) {
1051  Oscillator = std::make_shared<OscillationHandler>(NuOscillatorConfigFile, EqualBinningPerOscChannel, OscParamsValues,
1052  NuOscName, GetNOscChannels(iSample));
1053  } else {
1054  Oscillator->AddSample(NuOscillatorConfigFile, GetNOscChannels(iSample));
1055  }
1056 
1057  // set oscillator binning
1058  for (auto &[osc_flavs, energies] : channel_energy_array[iSample]) {
1059  auto iChannel = GetOscChannel(SampleDetails[iSample].OscChannels,
1060  osc_flavs.first, osc_flavs.second);
1061 
1062  std::sort(energies.begin(), energies.end());
1063  std::sort(channel_cosz_array[iSample][osc_flavs].begin(),
1064  channel_cosz_array[iSample][osc_flavs].end());
1065  Oscillator->SetOscillatorBinning(iSample, iChannel, energies,
1066  channel_cosz_array[iSample][osc_flavs]);
1067  }
1068  } // end loop over samples
1069  } // end EqualBinningPerOscChannel
1070 }
const M3::float_t * RetPointer(const int iParam) const
DB Pointer return to param position.
const std::vector< OscillationParameter > GetOscParsFromSampleName(const std::string &SampleName) const
KS Grab the Osc parameters for the relevant SampleName.
std::string GetSampleName(const int iSample) const
Sample name tag used only for getting relevant uncertainties.
virtual M3::int_t GetNSamples()
returns total number of samples
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

◆ InitialiseSplineObject()

void SampleHandlerBase::InitialiseSplineObject ( )
protected

Setup spline handler (both binned or unbinned)

Definition at line 1325 of file SampleHandlerBase.cpp.

1325  {
1326 // ************************************************
1327  if(auto BinnedSplines = dynamic_cast<BinnedSplineHandler*>(SplineHandler.get())) {
1328  bool LoadSplineFile = GetFromManager<bool>(SampleManager->raw()["InputFiles"]["LoadSplineFile"], false, __FILE__, __LINE__);
1329  bool PrepSplineFile = GetFromManager<bool>(SampleManager->raw()["InputFiles"]["PrepSplineFile"], false, __FILE__, __LINE__);
1330  auto SplineFileName = GetFromManager<std::string>(SampleManager->raw()["InputFiles"]["SplineFileName"],
1331  (SampleHandlerName + "_SplineFile.root"), __FILE__, __LINE__);
1332  if(!LoadSplineFile) {
1333  for(int iSample = 0; iSample < GetNSamples(); iSample++) {
1334  std::vector<std::string> spline_filepaths = SampleDetails[iSample].spline_files;
1335 
1336  //Keep a track of the spline variables
1337  std::vector<std::string> SplineVarNames = {"TrueNeutrinoEnergy"};
1338  if (GetNDim(iSample) == 1) {
1339  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1340  } else if (GetNDim(iSample) == 2) {
1341  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1342  SplineVarNames.push_back(GetKinVarName(iSample, 1));
1343  } else {
1344  MACH3LOG_CRITICAL("{} Not implemented for dimension {}, will use 2D", __func__, GetNDim(iSample));
1345  SplineVarNames.push_back(GetKinVarName(iSample, 0));
1346  SplineVarNames.push_back(GetKinVarName(iSample, 1));
1347  }
1348  BinnedSplines->AddSample(GetSampleName(iSample), GetSampleTitle(iSample), spline_filepaths, SplineVarNames);
1349  }
1350  BinnedSplines->CountNumberOfLoadedSplines(false, 1);
1351  BinnedSplines->TransferToMonolith();
1352  if(PrepSplineFile) BinnedSplines->PrepareSplineFile(SplineFileName);
1353  } else {
1354  // KS: Skip default spline loading and use flattened spline format allowing to read stuff much faster
1355  BinnedSplines->LoadSplineFile(SplineFileName);
1356  }
1357  MACH3LOG_INFO("--------------------------------");
1358  MACH3LOG_INFO("Setup Far Detector splines");
1359 
1361 
1362  BinnedSplines->CleanUpMemory();
1363  } else if (dynamic_cast<UnbinnedSplineHandler*>(SplineHandler.get())) {
1365  } else {
1366  MACH3LOG_ERROR("Unsupported spline type encountered.");
1367  throw MaCh3Exception(__FILE__, __LINE__);
1368  }
1369 }
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 312 of file SampleHandlerBase.cpp.

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

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

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

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

1690  {
1691 // ************************************************
1692  if (KinematicVectors == nullptr) return false;
1693 
1694  if (KinematicVectors->count(VarStr)) {
1695  if (!KinematicParameters->count(VarStr)) return true;
1696  else {
1697  MACH3LOG_ERROR("Attempted to plot kinematic variable {}, but it appears in both KinematicVectors and KinematicParameters", VarStr);
1698  throw MaCh3Exception(__FILE__,__LINE__);
1699  }
1700  }
1701  return false;
1702 }

◆ 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  }
181  //Now grab the selection cuts from the manager
182  for ( auto const &SelectionCuts : SampleSettings["SelectionCuts"]) {
183  auto TempBoundsVec = GetBounds(SelectionCuts["Bounds"]);
184  KinematicCut CutObj;
185  CutObj.LowerBound = TempBoundsVec[0];
186  CutObj.UpperBound = TempBoundsVec[1];
187  CutObj.ParamToCutOnIt = ReturnKinematicParameterFromString(SelectionCuts["KinematicStr"].as<std::string>());
188  MACH3LOG_INFO("Adding cut on {} with bounds {} to {}", SelectionCuts["KinematicStr"].as<std::string>(), TempBoundsVec[0], TempBoundsVec[1]);
189  StoredSelection[iSample].emplace_back(CutObj);
190  }
193  SampleDetails[iSample] = std::move(SingleSample);
194 }
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)
Get content of config file if node is not found take default value specified.
Definition: YamlHelper.h:328
#define GetBounds(filename)
Definition: YamlHelper.h:590
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 272 of file SampleHandlerBase.h.

272 {};

◆ 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.

Parameters
iSampleIndex of the sample.

Definition at line 1773 of file SampleHandlerBase.cpp.

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

2021  {
2022 // ***************************************************************************
2023  if (!SampleHandler_data.size()) {
2024  MACH3LOG_ERROR("Data sample is empty!");
2025  throw MaCh3Exception(__FILE__, __LINE__);
2026  }
2027  MACH3LOG_INFO("Printing for {}", GetName());
2028 
2029  if (!DataOnly) {
2030  const std::string sep_full(81, '-');
2031  MACH3LOG_INFO("{}", sep_full);
2032  MACH3LOG_INFO("{:<40}{:<15}{:<15}{:<10}|", "Sample", "Data", "MC", "-LLH");
2033  } else {
2034  const std::string sep_data(56, '-');
2035  MACH3LOG_INFO("{}", sep_data);
2036  MACH3LOG_INFO("{:<40}{:<15}|", "Sample", "Data");
2037  }
2038 
2039  double sumData = 0.0;
2040  double sumMC = 0.0;
2041  double likelihood = 0.0;
2042 
2043  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
2044  std::string name = GetSampleTitle(iSample);
2045  std::vector<double> DataArray = GetDataArray(iSample);
2046  double dataIntegral = std::accumulate(DataArray.begin(), DataArray.end(), 0.0);
2047  sumData += dataIntegral;
2048  if (!DataOnly) {
2049  std::vector<double> MCArray = GetMCArray(iSample);
2050  double mcIntegral = std::accumulate(MCArray.begin(), MCArray.end(), 0.0);
2051  sumMC += mcIntegral;
2052  likelihood = GetSampleLikelihood(iSample);
2053 
2054  MACH3LOG_INFO("{:<40}{:<15.2f}{:<15.2f}{:<10.2f}|", name, dataIntegral, mcIntegral, likelihood);
2055  } else {
2056  MACH3LOG_INFO("{:<40}{:<15.2f}|", name, dataIntegral);
2057  }
2058  }
2059  if (!DataOnly) {
2060  likelihood = GetLikelihood();
2061  MACH3LOG_INFO("{:<40}{:<15.2f}{:<15.2f}{:<10.2f}|", "Total", sumData, sumMC, likelihood);
2062  const std::string sep_full(81, '-');
2063  MACH3LOG_INFO("{}", sep_full);
2064  } else {
2065  MACH3LOG_INFO("{:<40}{:<20.2f}|", "Total", sumData);
2066  const std::string sep_data(56, '-');
2067  MACH3LOG_INFO("{}", sep_data);
2068  }
2069 }
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:59
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 270 of file SampleHandlerBase.h.

270 {};

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

441  {
442 // **************************************************
443  // DB Reset values stored in PDF array to 0.
444  // Don't openMP this; no significant gain
445  const int nBins = Binning->GetNBins();
446  std::fill_n(SampleHandler_array.begin(), nBins, 0.0);
447  if (FirstTimeW2) {
448  std::fill_n(SampleHandler_array_w2.begin(), nBins, 0.0);
449  }
450 } // 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 310 of file SampleHandlerBase.h.

310 {};

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

1933  {
1934 // ************************************************
1935  std::vector<std::unique_ptr<TH1>> hHistList;
1936  std::string legendEntry;
1937 
1938  if (THStackLeg != nullptr) {delete THStackLeg;}
1939  THStackLeg = new TLegend(0.1,0.1,0.9,0.9);
1940 
1941  const int iMax = GetRangeForPlotType(Selection1, iSample);
1942  for (int i=0;i<iMax;i++) {
1943  if (Selection1 == SamplePlotType::kModePlot) {
1944  hHistList.push_back(Get1DVarHistByModeAndChannel(iSample, KinematicProjection,i,Selection2,WeightStyle));
1945  THStackLeg->AddEntry(hHistList[i].get(), (Modes->GetMaCh3ModeName(i)+Form(" : (%4.2f)",hHistList[i]->Integral())).c_str(),"f");
1946 
1947  hHistList[i]->SetFillColor(static_cast<Color_t>(Modes->GetMaCh3ModePlotColor(i)));
1948  hHistList[i]->SetLineColor(static_cast<Color_t>(Modes->GetMaCh3ModePlotColor(i)));
1949  }
1950  if (Selection1 == SamplePlotType::kOscChannelPlot) {
1951  hHistList.push_back(Get1DVarHistByModeAndChannel(iSample, KinematicProjection,Selection2,i,WeightStyle));
1952  THStackLeg->AddEntry(hHistList[i].get(),(GetFlavourName(iSample, i)+Form(" | %4.2f",hHistList[i]->Integral())).c_str(),"f");
1953  }
1954  }
1955 
1956  return hHistList;
1957 }
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 1960 of file SampleHandlerBase.cpp.

1962  {
1963 // ************************************************
1964  std::vector<std::unique_ptr<TH2>> hHistList;
1965 
1966  const int iMax = GetRangeForPlotType(Selection1, iSample);
1967  for (int i=0;i<iMax;i++) {
1968  if (Selection1 == SamplePlotType::kModePlot) {
1969  hHistList.push_back(Get2DVarHistByModeAndChannel(iSample, KinematicProjectionX,KinematicProjectionY,i,Selection2,WeightStyle));
1970  }
1971  if (Selection1 == SamplePlotType::kOscChannelPlot) {
1972  hHistList.push_back(Get2DVarHistByModeAndChannel(iSample, KinematicProjectionX,KinematicProjectionY,Selection2,i,WeightStyle));
1973  }
1974  }
1975 
1976  return hHistList;
1977 }
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 338 of file SampleHandlerBase.h.

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

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

1634  {
1635 // ************************************************
1636  // If any of fit based variables return them
1638  if(Binning->IsUniform(Sample)) {
1639  for(int iDim = 0; iDim < GetNDim(Sample); iDim++) {
1640  if(KinematicParameter == GetKinVarName(Sample, iDim)) {
1641  return Binning->GetBinEdges(Sample, iDim);
1642  }
1643  } // end loop over Dimension
1644  } // end loop over IsUniform
1645 
1646  auto MakeBins = [](int nBins) {
1647  std::vector<double> bins(nBins + 1);
1648  for (int i = 0; i <= nBins; ++i)
1649  bins[i] = static_cast<double>(i) - 0.5;
1650  return bins;
1651  };
1652 
1653  if (KinematicParameter == "OscillationChannel") {
1654  return MakeBins(GetNOscChannels(Sample));
1655  } else if (KinematicParameter == "Mode") {
1656  return MakeBins(Modes->GetNModes());
1657  }
1658 
1659  std::vector<double> BinningVect;
1660  // We first check if binning for a sample has been specified
1661  auto BinningConfig = M3OpenConfig(SampleManager->raw()["BinningFile"].as<std::string>());
1662  bool found_range_specifier = false;
1663  if(BinningConfig[GetSampleTitle(Sample)] && BinningConfig[GetSampleTitle(Sample)][KinematicParameter]){
1664  BinningVect = BuildBinEdgesFromNode(BinningConfig[GetSampleTitle(Sample)][KinematicParameter], found_range_specifier);
1665  } else {
1666  BinningVect = BuildBinEdgesFromNode(BinningConfig[KinematicParameter], found_range_specifier);
1667  }
1668 
1669  // Ensure binning is increasing
1670  auto IsIncreasing = [](const std::vector<double>& vec) {
1671  for (size_t i = 1; i < vec.size(); ++i) {
1672  if (vec[i] <= vec[i-1]) {
1673  return false;
1674  }
1675  }
1676  return true;
1677  };
1678 
1679  if (!IsIncreasing(BinningVect)) {
1680  MACH3LOG_ERROR("Binning for {} is not increasing [{}]", KinematicParameter, fmt::join(BinningVect, ", "));
1681  if(found_range_specifier){
1682  MACH3LOG_ERROR("A bin range specifier was found. Please carefully check the number of square brackets used.");
1683  }
1684  throw MaCh3Exception(__FILE__, __LINE__);
1685  }
1686  return BinningVect;
1687 }
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
std::string join(const Container &values, std::string_view separator=" ")
Join all values in a container into a single string.
Definition: TablePrinter.h:36

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

1581  {
1582 // ************************************************
1583  auto it = KinematicParameters->find(KinematicParameterStr);
1584  if (it != KinematicParameters->end()) return it->second;
1585 
1586  MACH3LOG_ERROR("Did not recognise Kinematic Parameter type: {}", KinematicParameterStr);
1587  throw MaCh3Exception(__FILE__, __LINE__);
1588 
1589  return M3::_BAD_INT_;
1590 }

◆ ReturnKinematicVector() [1/2]

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

Definition at line 348 of file SampleHandlerBase.h.

349  {return {};};

◆ ReturnKinematicVector() [2/2]

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

Definition at line 345 of file SampleHandlerBase.h.

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

◆ ReturnKinematicVectorFromString()

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

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

Definition at line 1608 of file SampleHandlerBase.cpp.

1608  {
1609 // ************************************************
1610  auto it = KinematicVectors->find(KinematicVectorStr);
1611  if (it != KinematicVectors->end()) return it->second;
1612 
1613  MACH3LOG_ERROR("Did not recognise Kinematic Vector: {}", KinematicVectorStr);
1614  throw MaCh3Exception(__FILE__, __LINE__);
1615 
1616  return M3::_BAD_INT_;
1617 }

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

1981  {
1982 // ************************************************
1983  auto HistList = ReturnHistsBySelection1D(iSample, KinematicProjection, Selection1, Selection2, WeightStyle);
1984  auto StackHist = std::make_unique<THStack>((GetSampleTitle(iSample)+"_"+KinematicProjection+"_Stack").c_str(),"");
1985  // Note: we use .release() to transfer ownership of each TH1 to THStack.
1986  for (unsigned int i=0;i<HistList.size();i++) {
1987  StackHist->Add(HistList[i].release());
1988  }
1989  return StackHist;
1990 }

◆ ReturnStackHistLegend()

const TLegend* SampleHandlerBase::ReturnStackHistLegend ( ) const
inline

Return the legend used for stacked histograms with sample info.

Definition at line 159 of file SampleHandlerBase.h.

159 {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 1593 of file SampleHandlerBase.cpp.

1593  {
1594 // ************************************************
1595  auto it = ReversedKinematicParameters->find(KinematicParameter);
1596  if (it != ReversedKinematicParameters->end()) {
1597  return it->second;
1598  }
1599 
1600  MACH3LOG_ERROR("Did not recognise Kinematic Parameter type: {}", KinematicParameter);
1601  throw MaCh3Exception(__FILE__, __LINE__);
1602 
1603  return "";
1604 }

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

1620  {
1621 // ************************************************
1622  auto it = ReversedKinematicVectors->find(KinematicVector);
1623  if (it != ReversedKinematicVectors->end()) {
1624  return it->second;
1625  }
1626 
1627  MACH3LOG_ERROR("Did not recognise Kinematic Vector: {}", KinematicVector);
1628  throw MaCh3Exception(__FILE__, __LINE__);
1629 
1630  return "";
1631 }

◆ Reweight()

void SampleHandlerBase::Reweight ( )
overridevirtual

main routine modifying MC prediction based on proposed parameter values

Implements SampleHandlerInterface.

Definition at line 347 of file SampleHandlerBase.cpp.

347  {
348 //************************************************
349  //KS: Reset the histograms before reweight
350  ResetHistograms();
351 
352  //You only need to do these things if Oscillator has been initialised
353  //if not then you're not considering oscillations
354  if (Oscillator) Oscillator->Evaluate();
355 
356  // Calculate weight coming from all splines if we initialised handler
357  if(SplineHandler) SplineHandler->Evaluate();
358 
359  //update the list of parameter values passed to shift functionals
361  // Update the functional parameter values to the latest proposed values
363 
364  //KS: If using CPU this does nothing, if on GPU need to make sure we finished copying memory from
365  if(SplineHandler) SplineHandler->SynchroniseMemTransfer();
366 
367  // Here we fill weights to MC predictions weights for splines and osc already have been filled
368  FillArray();
369 
370  //KS: If you want to not update W2 wights then uncomment this line
371  if(!UpdateW2) FirstTimeW2 = false;
372 }
void ResetHistograms() _noexcept_
Helper function to reset histograms.
virtual void PrepFunctionalParameters()
Update the functional parameter values to the latest proposed values. Needs to be called before every...
void FillArray()
Function which does the core reweighting. This assumes that oscillation weights have already been cal...

◆ SaveAdditionalInfo()

void SampleHandlerBase::SaveAdditionalInfo ( TDirectory *  Dir)
final

Store additional info in a chain.

Parameters
Dirdirectory to which we save additional info

Definition at line 1279 of file SampleHandlerBase.cpp.

1279  {
1280 // ************************************************
1281  Dir->cd();
1282 
1283  YAML::Node Config = SampleManager->raw();
1284  TMacro ConfigSave = YAMLtoTMacro(Config, (std::string("Config_") + GetName()));
1285  ConfigSave.Write();
1286 
1287  for(int iSample = 0; iSample < GetNSamples(); iSample++)
1288  {
1289  std::unique_ptr<TH1> data_hist;
1290 
1291  if (GetNDim(iSample) == 1) {
1292  data_hist = M3::Clone<TH1D>(dynamic_cast<const TH1D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1293  data_hist->GetXaxis()->SetTitle(GetKinVarName(iSample, 0).c_str());
1294  data_hist->GetYaxis()->SetTitle("Number of Events");
1295  } else if (GetNDim(iSample) == 2) {
1296  if(Binning->IsUniform(iSample)) {
1297  data_hist = M3::Clone<TH2D>(dynamic_cast<const TH2D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1298  } else {
1299  data_hist = M3::Clone<TH2Poly>(dynamic_cast<const TH2Poly*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1300  }
1301  data_hist->GetXaxis()->SetTitle(GetKinVarName(iSample, 0).c_str());
1302  data_hist->GetYaxis()->SetTitle(GetKinVarName(iSample, 1).c_str());
1303  data_hist->GetZaxis()->SetTitle("Number of Events");
1304  } else {
1305  data_hist = M3::Clone<TH1D>(dynamic_cast<const TH1D*>(GetDataHist(iSample)), "data_" + GetSampleTitle(iSample));
1306  int nbins = Binning->GetNBins(iSample);
1307  for(int iBin = 0; iBin < nbins; iBin++) {
1308  auto BinName = Binning->GetBinName(iSample, iBin);
1309  data_hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
1310  }
1311  data_hist->GetYaxis()->SetTitle("Number of Events");
1312  }
1313 
1314  if (!data_hist) {
1315  MACH3LOG_ERROR("nullptr data hist :(");
1316  throw MaCh3Exception(__FILE__, __LINE__);
1317  }
1318 
1319  data_hist->SetTitle(("data_" + GetSampleTitle(iSample)).c_str());
1320  data_hist->Write();
1321  }
1322 }
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Definition: YamlHelper.h:166

◆ SetBinning()

void SampleHandlerBase::SetBinning ( )
protected

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

Definition at line 639 of file SampleHandlerBase.cpp.

639  {
640 // ************************************************
641  for(int iSample = 0; iSample < GetNSamples(); iSample++)
642  {
643  int Dimension = GetNDim(iSample);
644  std::string HistTitle = GetSampleTitle(iSample);
645 
646  auto* SamDet = &SampleDetails[iSample];
647  if(Dimension == 1) {
648  auto XVec = Binning->GetBinEdges(iSample, 0);
649  SamDet->DataHist = new TH1D(("d" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
650  SamDet->MCHist = new TH1D(("h" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
651  SamDet->W2Hist = new TH1D(("w" + HistTitle).c_str(), HistTitle.c_str(), static_cast<int>(XVec.size()-1), XVec.data());
652 
653  // Set all titles so most of projections don't have empty titles...
654  SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
655  SamDet->DataHist->GetYaxis()->SetTitle("Events");
656  SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
657  SamDet->MCHist->GetYaxis()->SetTitle("Events");
658  SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
659  SamDet->W2Hist->GetYaxis()->SetTitle("Events");
660  } else if (Dimension == 2){
661  if(Binning->IsUniform(iSample)) {
662  auto XVec = Binning->GetBinEdges(iSample, 0);
663  auto YVec = Binning->GetBinEdges(iSample, 1);
664  int nX = static_cast<int>(XVec.size() - 1);
665  int nY = static_cast<int>(YVec.size() - 1);
666 
667  SamDet->DataHist = new TH2D(("d" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
668  SamDet->MCHist = new TH2D(("h" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
669  SamDet->W2Hist = new TH2D(("w" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
670  } else {
671  auto AddBinsToTH2Poly = [](TH2Poly* hist, const std::vector<BinInfo>& bins) {
672  for (const auto& bin : bins) {
673  double xLow = bin.Extent[0][0];
674  double xHigh = bin.Extent[0][1];
675  double yLow = bin.Extent[1][0];
676  double yHigh = bin.Extent[1][1];
677 
678  double x[4] = {xLow, xHigh, xHigh, xLow};
679  double y[4] = {yLow, yLow, yHigh, yHigh};
680 
681  hist->AddBin(4, x, y);
682  }
683  };
684  // Create all three histograms
685  SamDet->DataHist = new TH2Poly();
686  SamDet->DataHist->SetName(("d" + HistTitle).c_str());
687  SamDet->DataHist->SetTitle(HistTitle.c_str());
688 
689  SamDet->MCHist = new TH2Poly();
690  SamDet->MCHist->SetName(("h" + HistTitle).c_str());
691  SamDet->MCHist->SetTitle(HistTitle.c_str());
692 
693  SamDet->W2Hist = new TH2Poly();
694  SamDet->W2Hist->SetName(("w" + HistTitle).c_str());
695  SamDet->W2Hist->SetTitle(HistTitle.c_str());
696 
697  // Add bins to each
698  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->DataHist), Binning->GetNonUniformBins(iSample));
699  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->MCHist), Binning->GetNonUniformBins(iSample));
700  AddBinsToTH2Poly(static_cast<TH2Poly*>(SamDet->W2Hist), Binning->GetNonUniformBins(iSample));
701  }
702 
703  // Set all titles so most of projections don't have empty titles...
704  SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
705  SamDet->DataHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
706  SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
707  SamDet->MCHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
708  SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
709  SamDet->W2Hist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
710  } else {
711  int nbins = Binning->GetNBins(iSample);
712  SamDet->DataHist = new TH1D(("d" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
713  SamDet->MCHist = new TH1D(("h" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
714  SamDet->W2Hist = new TH1D(("w" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
715 
716  for(int iBin = 0; iBin < nbins; iBin++) {
717  auto BinName = Binning->GetBinName(iSample, iBin);
718  SamDet->DataHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
719  SamDet->MCHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
720  SamDet->W2Hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
721  }
722 
723  // Set all titles so most of projections don't have empty titles...
724  SamDet->DataHist->GetYaxis()->SetTitle("Events");
725  SamDet->MCHist->GetYaxis()->SetTitle("Events");
726  SamDet->W2Hist->GetYaxis()->SetTitle("Events");
727  }
728 
729  SamDet->DataHist->SetDirectory(nullptr);
730  SamDet->MCHist->SetDirectory(nullptr);
731  SamDet->W2Hist->SetDirectory(nullptr);
732  }
733 
734  //Set the number of X and Y bins now
737 }
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 1196 of file SampleHandlerBase.cpp.

1196  {
1197 // ************************************************
1198  //Now loop over events and get the spline bin for each event
1199  if (auto BinnedSpline = dynamic_cast<BinnedSplineHandler*>(SplineHandler.get())) {
1200  bool ThrowCrititcal = true;
1201 
1202  std::vector< std::vector<SplineParameter> > SplineParsVec(GetNSamples());
1203  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
1204  SplineParsVec[iSample] = ParHandler->GetSplineParsFromSampleName(GetSampleName(iSample));
1205  }
1206  for (unsigned int j = 0; j < GetNEvents(); ++j) {
1207  auto EventSplines = GetSplineBins(j, BinnedSpline, ThrowCrititcal);
1208  const int NSplines = static_cast<int>(EventSplines.size());
1209  if(NSplines == 0) continue;
1210  auto& w_pointers = MCEvents[j].total_weight_pointers;
1211  w_pointers.reserve(w_pointers.size() + NSplines);
1212  const auto SampleId = MCEvents[j].NominalSample;
1213  for(int spline = 0; spline < NSplines; spline++) {
1214  int SystIndex = EventSplines[spline].iSyst;
1215 
1216  bool IsSelected = PassesSelection(SplineParsVec[SampleId][SystIndex], j);
1217  // Need to then break the event loop
1218  if(!IsSelected){
1219  MACH3LOG_TRACE("Event {}, missed Kinematic var check for dial {}", j, SplineParsVec[SampleId][SystIndex].name);
1220  continue;
1221  }
1222  //Event Splines indexed as: sample name, oscillation channel, syst, mode, etrue, var1, var2 (var2 is a dummy 0 for 1D splines)
1223  w_pointers.push_back(BinnedSpline->RetPointer(EventSplines[spline]));
1224  } // end loop over splines
1225  w_pointers.shrink_to_fit();
1226  } // end loop over events
1227  } else if (auto UnbinnedSpline = dynamic_cast<UnbinnedSplineHandler*>(SplineHandler.get())) {
1228  for (unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent) {
1229  MCEvents[iEvent].total_weight_pointers.push_back(UnbinnedSpline->RetPointer(iEvent));
1230  }
1231  } else {
1232  MACH3LOG_ERROR("Not supported splines");
1233  throw MaCh3Exception(__FILE__, __LINE__);
1234  }
1235 }
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 236 of file SampleHandlerBase.cpp.

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

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

530  {
531 // ***************************************************************************
532  if(ParHandler == nullptr) return;
533  std::vector< std::vector< int > > norms_bins(GetNEvents());
534 
535  std::vector< std::vector<NormParameter>> norm_parameters(GetNSamples());
536 
537  for (int iSample = 0; iSample < GetNSamples(); ++iSample) {
538  norm_parameters[iSample] = ParHandler->GetNormParsFromSampleName(GetSampleName(iSample));
539  }
540  if(!ParHandler) {
541  MACH3LOG_ERROR("ParHandler is not setup!");
542  throw MaCh3Exception(__FILE__ , __LINE__ );
543  }
544 
545  // Assign norm bins in MCEvents tree
546  CalcNormsBins(norm_parameters, norms_bins);
547 
548  //DB Attempt at reducing impact of SystematicHandlerGeneric::calcReweight()
549  for (unsigned int iEvent = 0; iEvent < GetNEvents(); ++iEvent) {
550  int counter = 0;
551  const size_t offset = MCEvents[iEvent].total_weight_pointers.size();
552  const size_t addSize = norms_bins[iEvent].size();
553  MCEvents[iEvent].total_weight_pointers.resize(offset + addSize);
554  for(auto const & norm_bin: norms_bins[iEvent]) {
555  MCEvents[iEvent].total_weight_pointers[offset + counter] = ParHandler->RetPointer(norm_bin);
556  counter += 1;
557  }
558  }
559 }
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 1073 of file SampleHandlerBase.cpp.

1073  {
1074 // ************************************************
1075  auto AddOscPointer = GetFromManager<bool>(SampleManager->raw()["NuOsc"]["AddOscPointer"], true, __FILE__ , __LINE__);
1076  // 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
1077  if(!AddOscPointer) {
1078  return;
1079  }
1080  for (unsigned int iEvent=0;iEvent<GetNEvents();iEvent++) {
1081  const M3::float_t* osc_w_pointer = GetNuOscillatorPointers(iEvent);
1082 
1083  // KS: Do not add unity
1084  if (osc_w_pointer != &M3::Unity) {
1085  MCEvents[iEvent].total_weight_pointers.push_back(osc_w_pointer);
1086  }
1087  }
1088 }
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 491 of file SampleHandlerBase.cpp.

491  {
492 // ***************************************************************************
493  // KS: Only make sense to setup osc if you have ParHandler
494  if(ParHandler == nullptr ) return;
495 
496  auto OscParams = ParHandler->GetOscParsFromSampleName(GetSampleName(0));
497  if (OscParams.size() > 0) {
498  MACH3LOG_INFO("Setting up NuOscillator..");
499  if (Oscillator != nullptr) {
500  MACH3LOG_INFO("You have passed an OscillatorBase object through the constructor of a SampleHandlerFD object - this will be used for all oscillation channels");
501  if(Oscillator->isEqualBinningPerOscChannel() != true) {
502  MACH3LOG_ERROR("Trying to run shared NuOscillator without EqualBinningPerOscChannel, this will not work");
503  throw MaCh3Exception(__FILE__, __LINE__);
504  }
505 
506  if(OscParams.size() != Oscillator->GetOscParamsSize()){
507  MACH3LOG_ERROR("SampleHandler {} has {} osc params, while shared NuOsc has {} osc params", GetName(),
508  OscParams.size(), Oscillator->GetOscParamsSize());
509  MACH3LOG_ERROR("This indicate misconfiguration in your Osc yaml");
510  throw MaCh3Exception(__FILE__, __LINE__);
511  }
512  } else {
514  }
516  } else{
517  MACH3LOG_WARN("Didn't find any oscillation params, thus will not enable oscillations");
518  if(CheckNodeExists(SampleManager->raw(), "NuOsc")){
519  MACH3LOG_ERROR("However config for SampleHandler {} has 'NuOsc' field", GetName());
520  MACH3LOG_ERROR("This may indicate misconfiguration");
521  MACH3LOG_ERROR("Either remove 'NuOsc' field from SampleHandler config or check your model.yaml and include oscillation for sample");
522  throw MaCh3Exception(__FILE__, __LINE__);
523  }
524  }
525 }
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 631 of file SampleHandlerBase.cpp.

631  {
632 // ************************************************
633  SampleHandler_array = std::vector<double>(Binning->GetNBins(),0);
634  SampleHandler_array_w2 = std::vector<double>(Binning->GetNBins(),0);
635  SampleHandler_data = std::vector<double>(Binning->GetNBins(),0);
636 }

◆ 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 439 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 391 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 463 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 461 of file SampleHandlerBase.h.

◆ FirstTimeW2

bool SampleHandlerBase::FirstTimeW2
protected

KS:Super hacky to update W2 or not.

Definition at line 446 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 466 of file SampleHandlerBase.h.

◆ KinematicParameters

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

Mapping between string and kinematic enum.

Definition at line 427 of file SampleHandlerBase.h.

◆ KinematicVectors

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

Definition at line 432 of file SampleHandlerBase.h.

◆ MCEvents

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

Stores information about every MC event.

Definition at line 402 of file SampleHandlerBase.h.

◆ nEvents

unsigned int SampleHandlerBase::nEvents
private

Number of MC events are there.

Definition at line 469 of file SampleHandlerBase.h.

◆ Oscillator

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

Contains oscillator handling calculating oscillation probabilities.

Definition at line 386 of file SampleHandlerBase.h.

◆ ParHandler

ParameterHandlerGeneric* SampleHandlerBase::ParHandler = nullptr
protected

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

Definition at line 410 of file SampleHandlerBase.h.

◆ ReversedKinematicParameters

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

Mapping between kinematic enum and string.

Definition at line 429 of file SampleHandlerBase.h.

◆ ReversedKinematicVectors

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

Definition at line 433 of file SampleHandlerBase.h.

◆ SampleDetails

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

Stores info about currently initialised sample.

Definition at line 404 of file SampleHandlerBase.h.

◆ SampleHandler_array

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

DB Array to be filled after reweighting.

Definition at line 393 of file SampleHandlerBase.h.

◆ SampleHandler_array_w2

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

KS Array used for MC stat.

Definition at line 395 of file SampleHandlerBase.h.

◆ SampleHandler_data

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

DB Array to be filled in AddData.

Definition at line 397 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 414 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 437 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 423 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 383 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 420 of file SampleHandlerBase.h.

◆ THStackLeg

TLegend* SampleHandlerBase::THStackLeg = nullptr
protected

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

Definition at line 443 of file SampleHandlerBase.h.

◆ UpdateW2

bool SampleHandlerBase::UpdateW2
protected

KS:Super hacky to update W2 or not.

Definition at line 448 of file SampleHandlerBase.h.


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