11 const std::shared_ptr<OscillationHandler>& OscillatorObj_) :
SampleHandlerBase() {
13 MACH3LOG_INFO(
"-------------------------------------------------------------------");
18 MACH3LOG_ERROR(
"You've passed me a nullptr to a SystematicHandlerGeneric... I need this to setup splines!");
25 if (OscillatorObj_ !=
nullptr) {
26 MACH3LOG_WARN(
"You have passed an Oscillator object through the constructor of a SampleHandlerFD object - this will be used for all oscillation channels");
39 SampleManager = std::make_unique<manager>(ConfigFileName.c_str());
59 auto ModeName = Get<std::string>(
SampleManager->raw()[
"MaCh3ModeConfig"], __FILE__ , __LINE__);
60 Modes = std::make_unique<MaCh3Modes>(ModeName);
75 if (!std::is_sorted(edgesx.begin(), edgesx.end())) {
76 MACH3LOG_ERROR(
"XVarBins must be in increasing order in sample config {}\n XVarBins: [{}]",
77 GetTitle(), fmt::join(edgesx,
", "));
90 if (!std::is_sorted(edgesy.begin(), edgesy.end())) {
91 MACH3LOG_ERROR(
"YBinEdges must be in increasing order in sample config {}\n YBinEdges: [{}]",
92 GetTitle(), fmt::join(edgesy,
", "));
97 MACH3LOG_ERROR(
"Please specify an X-variable string in sample config {}. I won't work only with a Y-variable",
SampleManager->GetFileName());
106 MACH3LOG_ERROR(
"Check that an XVarStr has been given in the sample config");
114 MACH3LOG_ERROR(
"No binning specified for either X or Y of sample binning, please add some binning to the sample config {}",
SampleManager->GetFileName());
119 MACH3LOG_ERROR(
"BinningFile not given in for sample {}, ReturnKinematicParameterBinning will not work",
GetTitle());
123 auto mtupleprefix = Get<std::string>(
SampleManager->raw()[
"InputFiles"][
"mtupleprefix"], __FILE__, __LINE__);
124 auto mtuplesuffix = Get<std::string>(
SampleManager->raw()[
"InputFiles"][
"mtuplesuffix"], __FILE__, __LINE__);
125 auto splineprefix = Get<std::string>(
SampleManager->raw()[
"InputFiles"][
"splineprefix"], __FILE__, __LINE__);
126 auto splinesuffix = Get<std::string>(
SampleManager->raw()[
"InputFiles"][
"splinesuffix"], __FILE__, __LINE__);
131 for (
auto const &osc_channel :
SampleManager->raw()[
"SubSamples"]) {
132 std::string MTupleFileName = mtupleprefix+osc_channel[
"mtuplefile"].as<std::string>()+mtuplesuffix;
135 OscInfo.
flavourName = osc_channel[
"Name"].as<std::string>();
136 OscInfo.flavourName_Latex = osc_channel[
"LatexName"].as<std::string>();
137 OscInfo.InitPDG =
static_cast<NuPDG>(osc_channel[
"nutype"].as<
int>());
138 OscInfo.FinalPDG =
static_cast<NuPDG>(osc_channel[
"oscnutype"].as<
int>());
147 spline_files.push_back(splineprefix+osc_channel[
"splinefile"].as<std::string>()+splinesuffix);
151 for (
auto const &SelectionCuts :
SampleManager->raw()[
"SelectionCuts"]) {
152 auto TempBoundsVec =
GetBounds(SelectionCuts[
"Bounds"]);
157 MACH3LOG_INFO(
"Adding cut on {} with bounds {} to {}", SelectionCuts[
"KinematicStr"].as<std::string>(), TempBoundsVec[0], TempBoundsVec[1]);
162 for(
int iMode=0; iMode <
Modes->GetNModes(); iMode++ ) {
168 for(
int iMode=0; iMode<
Modes->GetNModes(); iMode++ ) {
169 std::string modeStr =
Modes->GetMaCh3ModeName(iMode);
171 double modeWeight =
SampleManager->raw()[
"NominalWeights"][modeStr].as<
double>();
179 for(
int iMode=0; iMode<
Modes->GetNModes(); iMode++ ) {
180 std::string modeStr =
Modes->GetMaCh3ModeName(iMode);
197 MACH3LOG_INFO(
"=============================================");
201 if (OscParams.size() > 0) {
204 MACH3LOG_INFO(
"You have passed an OscillatorBase object through the constructor of a SampleHandlerFD object - this will be used for all oscillation channels");
205 if(
Oscillator->isEqualBinningPerOscChannel() !=
true) {
206 MACH3LOG_ERROR(
"Trying to run shared NuOscillator without EqualBinningPerOscChannel, this will not work");
210 if(OscParams.size() !=
Oscillator->GetOscParamsSize()){
212 OscParams.size(),
Oscillator->GetOscParamsSize());
213 MACH3LOG_ERROR(
"This indicate misconfiguration in your Osc yaml");
221 MACH3LOG_WARN(
"Didn't find any oscillation params, thus will not enable oscillations");
236 MACH3LOG_INFO(
"=======================================================");
243 MACH3LOG_INFO(
"Map KinematicParameters or ReversedKinematicParameters hasn't been initialised");
248 const auto& key = pair.first;
249 const auto& value = pair.second;
260 #pragma GCC diagnostic push
261 #pragma GCC diagnostic ignored "-Wconversion"
275 }
else if (Dimension == 2) {
284 MACH3LOG_ERROR(
"Asking for {} with N Dimension = {}. This is not implemented", __func__, Dimension);
288 #pragma GCC diagnostic pop
300 std::string XBinEdgesStr =
"";
301 std::string YBinEdgesStr =
"";
304 XBinEdgesStr += std::to_string(XBinEdge);
305 XBinEdgesStr +=
", ";
312 YBinEdgesStr += std::to_string(YBinEdge);
313 YBinEdgesStr +=
", ";
328 MACH3LOG_ERROR(
"Number of dimensions is not 1 or 2, this is unsupported at the moment");
336 const int SelectionSize =
static_cast<int>(
Selection.size());
337 for (
int iSelection = 0; iSelection < SelectionSize; ++iSelection) {
340 if ((Val < Cut.LowerBound) || (Val >= Cut.UpperBound)) {
350 for (
unsigned int iSelection=0;iSelection < SubEventCuts.size() ;iSelection++) {
352 if (nsubevents != Vec.size()) {
353 MACH3LOG_ERROR(
"Cannot apply kinematic cut on {} as it is of different size to plotting variable");
356 const double Val = Vec[iSubEvent];
357 if ((Val < SubEventCuts[iSelection].LowerBound) || (Val >= SubEventCuts[iSelection].UpperBound)) {
405 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
415 if (splineweight <= 0.){
426 MCEvent->
xsec_w = splineweight*normweight;
431 if (totalweight <= 0.){
437 const double XVar = *(MCEvent->
x_var);
441 const int YBinToFill = MCEvent->
NomYBin;
444 if (XBinToFill != -1 && YBinToFill != -1) {
445 const int GlobalBin =
Binning.
GetBin(XBinToFill, YBinToFill);
455 void SampleHandlerFD::FillArray_MP() {
463 double* SampleHandlerFD_array_private =
nullptr;
464 double* SampleHandlerFD_array_private_w2 =
nullptr;
467 #pragma omp parallel private(SampleHandlerFD_array_private, SampleHandlerFD_array_private_w2)
471 SampleHandlerFD_array_private =
new double[
Binning.
nBins];
472 SampleHandlerFD_array_private_w2 =
new double[
Binning.
nBins];
474 std::fill_n(SampleHandlerFD_array_private,
Binning.
nBins, 0.0);
475 std::fill_n(SampleHandlerFD_array_private_w2,
Binning.
nBins, 0.0);
491 const unsigned int NumberOfEvents =
GetNEvents();
493 for (
unsigned int iEvent = 0; iEvent < NumberOfEvents; ++iEvent) {
510 if (splineweight <= 0.){
520 MCEvent->
xsec_w = splineweight*normweight;
525 if (totalweight <= 0.){
532 const double XVar = (*(MCEvent->
x_var));
536 const int YBinToFill = MCEvent->
NomYBin;
542 if (XBinToFill != -1 && YBinToFill != -1) {
543 const int GlobalBin =
Binning.
GetBin(XBinToFill, YBinToFill);
544 SampleHandlerFD_array_private[GlobalBin] += totalweight;
545 SampleHandlerFD_array_private_w2[GlobalBin] += totalweight*totalweight;
560 delete[] SampleHandlerFD_array_private;
561 delete[] SampleHandlerFD_array_private_w2;
588 MACH3LOG_ERROR(
"Functional parameter {} already in funcParsNamesVec", fpName);
592 MACH3LOG_ERROR(
"Functional parameter enum {} already registered in funcParsFuncMap", fpEnum);
611 if (fp.name == name) {
620 MACH3LOG_ERROR(
"Functional parameter {} not found, did you define it in RegisterFunctionalParameters()?", fp.name);
627 for (std::size_t iEvent = 0; iEvent < static_cast<std::size_t>(
GetNEvents()); ++iEvent) {
629 for (std::vector<FunctionalParameter>::iterator it =
funcParsVec.begin(); it !=
funcParsVec.end(); ++it) {
637 bool IsSelected =
true;
638 if ((*it).hasKinBounds) {
639 const auto& kinVars = (*it).KinematicVarStr;
640 const auto& selection = (*it).Selection;
642 for (std::size_t iKinPar = 0; iKinPar < kinVars.size(); ++iKinPar) {
645 bool passedAnyBound =
false;
646 const auto& boundsList = selection[iKinPar];
648 for (
const auto& bounds : boundsList) {
649 if (kinVal > bounds[0] && kinVal <= bounds[1]) {
650 passedAnyBound =
true;
655 if (!passedAnyBound) {
656 MACH3LOG_TRACE(
"Event {}, missed kinematic check ({}) for dial {}",
657 iEvent, kinVars[iKinPar], (*it).name);
665 MACH3LOG_TRACE(
"Event {}, missed Kinematic var check for dial {}", iEvent, (*it).name);
681 const std::size_t nShifts = fpEnums.size();
683 for (std::size_t i = 0; i < nShifts; ++i) {
684 const int fpEnum = fpEnums[i];
707 for (
int iSpline = 0; iSpline < nSplines; ++iSpline) {
710 return spline_weight;
723 for (
int iParam = 0; iParam < nNorms; ++iParam)
725 #pragma GCC diagnostic push
726 #pragma GCC diagnostic ignored "-Wuseless-cast"
728 #pragma GCC diagnostic pop
730 if (std::isnan(xsecw))
MACH3LOG_WARN(
"iParam= {} xsecweight=nan from norms", iParam);
740 std::vector< std::vector< int > > xsec_norms_bins(
GetNEvents());
754 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); ++iEvent) {
757 MCSamples[iEvent].xsec_norm_pointers.resize(xsec_norms_bins[iEvent].
size());
758 for(
auto const & norm_bin: xsec_norms_bins[iEvent]) {
770 std::vector<int> VerboseCounter(norm_parameters.size(), 0);
772 for(
unsigned int iEvent = 0; iEvent <
GetNEvents(); ++iEvent){
773 std::vector< int > NormBins = {};
783 for (std::vector<NormParameter>::iterator it = norm_parameters.begin(); it != norm_parameters.end(); ++it) {
787 MACH3LOG_TRACE(
"Event {}, missed target check ({}) for dial {}", iEvent, *(
MCSamples[iEvent].Target), (*it).name);
800 if (!FlavourUnoscMatch){
801 MACH3LOG_TRACE(
"Event {}, missed FlavourUnosc check ({}) for dial {}", iEvent,(*
MCSamples[iEvent].nupdgUnosc), (*it).name);
815 bool IsSelected =
true;
816 if ((*it).hasKinBounds) {
817 const auto& kinVars = (*it).KinematicVarStr;
818 const auto& selection = (*it).Selection;
820 for (std::size_t iKinPar = 0; iKinPar < kinVars.size(); ++iKinPar) {
823 bool passedAnyBound =
false;
824 const auto& boundsList = selection[iKinPar];
826 for (
const auto& bounds : boundsList) {
827 if (kinVal > bounds[0] && kinVal <= bounds[1]) {
828 passedAnyBound =
true;
833 if (!passedAnyBound) {
834 MACH3LOG_TRACE(
"Event {}, missed kinematic check ({}) for dial {}",
835 iEvent, kinVars[iKinPar], (*it).name);
843 MACH3LOG_TRACE(
"Event {}, missed Kinematic var check for dial {}", iEvent, (*it).name);
848 int bin = (*it).index;
850 NormBins.push_back(bin);
851 MACH3LOG_TRACE(
"Event {}, will be affected by dial {}", iEvent, (*it).name);
853 VerboseCounter[std::distance(norm_parameters.begin(), it)]++;
858 xsec_norms_bins[iEvent] = NormBins;
861 MACH3LOG_DEBUG(
"┌──────────────────────────────────────────────────────────┐");
862 for (std::size_t i = 0; i < norm_parameters.size(); ++i) {
863 const auto& norm = norm_parameters[i];
864 double eventRatio =
static_cast<double>(VerboseCounter[i]) /
static_cast<double>(
GetNEvents());
866 MACH3LOG_DEBUG(
"│ Param {:<15}, affects {:<8} events ({:>6.2f}%) │",
869 MACH3LOG_DEBUG(
"└──────────────────────────────────────────────────────────┘");
918 for(
unsigned int event_i = 0; event_i <
GetNEvents(); event_i++){
948 SampleDetails.
_hPDF2D->SetBins(
static_cast<int>(nbins1),boundaries1,
static_cast<int>(nbins2),boundaries2);
949 SampleDetails.
dathist2d->SetBins(
static_cast<int>(nbins1),boundaries1,
static_cast<int>(nbins2),boundaries2);
960 for(
unsigned int event_i = 0 ; event_i <
GetNEvents(); event_i++) {
992 #pragma GCC diagnostic push
993 #pragma GCC diagnostic ignored "-Wconversion"
1012 }
else if(Dimension == 2) {
1027 MACH3LOG_ERROR(
"Asking for {} with N Dimension = {}. This is not implemented", __func__, Dimension);
1031 #pragma GCC diagnostic pop
1038 if(Dimension == 1) {
1040 }
else if(Dimension == 2) {
1043 MACH3LOG_ERROR(
"Asking for {} with N Dimension = {}. This is not implemented", __func__, Dimension);
1051 if(Dimension == 1) {
1053 }
else if(Dimension == 2) {
1056 MACH3LOG_ERROR(
"Asdking for {} with N Dimension = {}. This is not implemented", __func__, Dimension);
1071 MACH3LOG_ERROR(
"Trying to set a 1D 'data' histogram when the number of dimensions for this sample is {}",
GetNDim());
1072 MACH3LOG_ERROR(
"This won't work, please specify the correct dimensions in your sample config with the X and Y variables");
1076 for (
auto const& data_point : data){
1081 MACH3LOG_ERROR(
"SampleHandlerFD_data haven't been initialised yet");
1091 #pragma GCC diagnostic push
1092 #pragma GCC diagnostic ignored "-Wconversion"
1103 MACH3LOG_ERROR(
"Trying to set a 2D 'data' histogram when the number of dimensions for this sample is {}",
GetNDim());
1104 MACH3LOG_ERROR(
"This won't work, please specify the correct dimensions in your sample config with the X and Y variables");
1111 for (
int i = 0; i < int(data.size()); i++) {
1116 MACH3LOG_ERROR(
"SampleHandlerFD_data haven't been initialised yet");
1130 MACH3LOG_INFO(
"Adding 1D data histogram: {} with {:.2f} events", Data->GetTitle(), Data->Integral());
1138 MACH3LOG_ERROR(
"Trying to set a 1D 'data' histogram in a 2D sample - Quitting");
1144 MACH3LOG_ERROR(
"SampleHandlerFD_data haven't been initialised yet");
1155 MACH3LOG_INFO(
"Adding 2D data histogram: {} with {:.2f} events", Data->GetTitle(), Data->Integral());
1163 MACH3LOG_ERROR(
"Trying to set a 2D 'data' histogram in a 1D sample - Quitting");
1167 MACH3LOG_ERROR(
"SampleHandlerFD_data haven't been initialised yet");
1179 #pragma GCC diagnostic pop
1184 auto NuOscillatorConfigFile = Get<std::string>(
SampleManager->raw()[
"NuOsc"][
"NuOscConfigFile"], __FILE__ , __LINE__);
1185 auto EqualBinningPerOscChannel = Get<bool>(
SampleManager->raw()[
"NuOsc"][
"EqualBinningPerOscChannel"], __FILE__ , __LINE__);
1188 if (EqualBinningPerOscChannel) {
1189 if (YAML::LoadFile(NuOscillatorConfigFile)[
"General"][
"CalculationType"].as<std::string>() ==
"Unbinned") {
1190 MACH3LOG_WARN(
"Tried using EqualBinningPerOscChannel while using Unbinned oscillation calculation, changing EqualBinningPerOscChannel to false");
1191 EqualBinningPerOscChannel =
false;
1195 if (OscParams.empty()) {
1197 MACH3LOG_ERROR(
"This likely indicates an error in your oscillation YAML configuration.");
1200 Oscillator = std::make_shared<OscillationHandler>(NuOscillatorConfigFile, EqualBinningPerOscChannel, OscParams,
GetNOscChannels());
1202 if (!EqualBinningPerOscChannel) {
1204 std::vector<M3::float_t> EnergyArray;
1205 std::vector<M3::float_t> CosineZArray;
1207 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1211 if (!
MCSamples[iEvent].isNC && Channel == iChannel) {
1215 std::sort(EnergyArray.begin(),EnergyArray.end());
1220 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1224 if (!
MCSamples[iEvent].isNC && Channel == iChannel) {
1228 std::sort(CosineZArray.begin(),CosineZArray.end());
1230 Oscillator->SetOscillatorBinning(iChannel, EnergyArray, CosineZArray);
1236 for (
unsigned int iEvent=0;iEvent<
GetNEvents();iEvent++) {
1252 MACH3LOG_ERROR(
"Something has gone wrong in the mapping between MCSamples.nutype and the enum used within NuOscillator");
1264 MCSamples[iEvent].osc_w_pointer =
Oscillator->GetNuOscillatorPointers(OscIndex, InitFlav, FinalFlav, FLOAT_T(*(
MCSamples[iEvent].rw_etru)), FLOAT_T(*(
MCSamples[iEvent].rw_truecz)));
1267 MCSamples[iEvent].osc_w_pointer =
Oscillator->GetNuOscillatorPointers(OscIndex, InitFlav, FinalFlav, FLOAT_T(*(
MCSamples[iEvent].rw_etru)));
1289 const int nParams =
static_cast<int>(
MCSamples[iEntry].total_weight_pointers.size());
1293 for (
int iParam = 0; iParam < nParams; ++iParam) {
1294 totalweight *= *(
MCSamples[iEntry].total_weight_pointers[iParam]);
1304 for (
unsigned int j = 0; j <
GetNEvents(); ++j) {
1307 std::vector< std::vector<int> > EventSplines;
1317 MACH3LOG_ERROR(
"MaCh3 only supports splines binned in Etrue + the sample binning");
1318 MACH3LOG_ERROR(
"Please check the sample binning you specified in your sample config ");
1322 int NSplines = int(EventSplines.size());
1326 MCSamples[j].xsec_spline_pointers.resize(NSplines);
1327 for(
size_t spline = 0; spline <
MCSamples[j].xsec_spline_pointers.size(); spline++) {
1329 MCSamples[j].xsec_spline_pointers[spline] =
SplineHandler->retPointer(EventSplines[spline][0], EventSplines[spline][1],
1330 EventSplines[spline][2], EventSplines[spline][3],
1331 EventSplines[spline][4], EventSplines[spline][5],
1332 EventSplines[spline][6]);
1341 MACH3LOG_ERROR(
"Data sample is empty! Can't calculate a likelihood!");
1345 double negLogL = 0.;
1347 #pragma omp parallel for reduction(+:negLogL)
1375 std::unique_ptr<TH1> data_hist;
1380 data_hist->GetYaxis()->SetTitle(
"Number of Events");
1385 data_hist->GetZaxis()->SetTitle(
"Number of Events");
1396 data_hist->SetTitle((
"data_" +
GetTitle()).c_str());
1401 std::vector<std::string> spline_filepaths;
1407 std::vector<std::string> SplineVarNames = {
"TrueNeutrinoEnergy"};
1415 bool LoadSplineFile = GetFromManager<bool>(
SampleManager->raw()[
"InputFiles"][
"LoadSplineFile"],
false, __FILE__, __LINE__);
1416 bool PrepSplineFile = GetFromManager<bool>(
SampleManager->raw()[
"InputFiles"][
"PrepSplineFile"],
false, __FILE__, __LINE__);
1417 auto SplineFileName = GetFromManager<std::string>(
SampleManager->raw()[
"InputFiles"][
"SplineFileName"],
1418 (
SampleName +
"_SplineFile.root"), __FILE__, __LINE__);
1419 if(!LoadSplineFile) {
1423 if(PrepSplineFile)
SplineHandler->PrepareSplineFile(SplineFileName);
1438 int WeightStyle, TAxis* Axis,
const std::vector< KinematicCut >& SubEventSelectionVec) {
1441 std::vector< KinematicCut > tmp_Selection =
Selection;
1442 std::vector< KinematicCut > SelectionVecToApply;
1445 for (
size_t iSelec=0;iSelec<
Selection.size();iSelec++) {
1446 SelectionVecToApply.emplace_back(
Selection[iSelec]);
1450 for (
size_t iSelec=0;iSelec<EventSelectionVec.size();iSelec++) {
1451 SelectionVecToApply.emplace_back(EventSelectionVec[iSelec]);
1460 _h1DVar =
new TH1D(
"",
"",Axis->GetNbins(),Axis->GetXbins()->GetArray());
1463 _h1DVar =
new TH1D(
"",
"",
int(xBinEdges.size())-1, xBinEdges.data());
1465 _h1DVar->GetXaxis()->SetTitle(ProjectionVar_Str.c_str());
1474 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1477 if (WeightStyle == 1) {
1481 _h1DVar->Fill(Var,Weight);
1495 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1498 if (WeightStyle == 1) {
1502 size_t nsubevents = Vec.size();
1504 for (
unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1506 double Var = Vec[iSubEvent];
1507 _h1DVar->Fill(Var,Weight);
1516 const std::vector< KinematicCut >& EventSelectionVec,
int WeightStyle, TAxis* AxisX, TAxis* AxisY,
const std::vector< KinematicCut >& SubEventSelectionVec) {
1520 std::vector< KinematicCut > tmp_Selection =
Selection;
1521 std::vector< KinematicCut > SelectionVecToApply;
1524 for (
size_t iSelec=0;iSelec<
Selection.size();iSelec++) {
1525 SelectionVecToApply.emplace_back(
Selection[iSelec]);
1529 for (
size_t iSelec=0;iSelec<EventSelectionVec.size();iSelec++) {
1530 SelectionVecToApply.emplace_back(EventSelectionVec[iSelec]);
1538 if (AxisX && AxisY) {
1539 _h2DVar =
new TH2D(
"",
"",AxisX->GetNbins(),AxisX->GetXbins()->GetArray(),AxisY->GetNbins(),AxisY->GetXbins()->GetArray());
1543 _h2DVar =
new TH2D(
"",
"",
int(xBinEdges.size())-1, xBinEdges.data(),
int(yBinEdges.size())-1, yBinEdges.data());
1547 if (IsSubEventHist)
Fill2DSubEventHist(_h2DVar, ProjectionVar_StrX, ProjectionVar_StrY, SubEventSelectionVec, WeightStyle);
1554 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1557 if (WeightStyle == 1) {
1562 _h2DVar->Fill(VarX,VarY,Weight);
1573 const std::vector< KinematicCut >& SubEventSelectionVec,
int WeightStyle) {
1577 int ProjectionVar_IntX, ProjectionVar_IntY;
1584 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1587 if (WeightStyle == 1) {
1590 std::vector<double> VecX = {}, VecY = {};
1592 size_t nsubevents = 0;
1594 if (IsSubEventVarX && !IsSubEventVarY) {
1597 nsubevents = VecX.size();
1599 else if (!IsSubEventVarX && IsSubEventVarY) {
1602 nsubevents = VecY.size();
1607 if (VecX.size() != VecY.size()) {
1608 MACH3LOG_ERROR(
"Cannot plot {} of size {} against {} of size {}", ProjectionVar_StrX, VecX.size(), ProjectionVar_StrY, VecY.size());
1611 nsubevents = VecX.size();
1614 for (
unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1616 if (IsSubEventVarX) VarX = VecX[iSubEvent];
1617 if (IsSubEventVarY) VarY = VecY[iSubEvent];
1618 _h2DVar->Fill(VarX,VarY,Weight);
1632 MACH3LOG_ERROR(
"Did not recognise Kinematic Parameter type: {}", KinematicParameterStr);
1646 MACH3LOG_ERROR(
"Did not recognise Kinematic Parameter type: {}", KinematicParameter);
1659 MACH3LOG_ERROR(
"Did not recognise Kinematic Vector: {}", KinematicVectorStr);
1673 MACH3LOG_ERROR(
"Did not recognise Kinematic Vector: {}", KinematicVector);
1689 auto MakeBins = [](
int nBins) {
1690 std::vector<double> bins(
nBins + 1);
1691 for (
int i = 0; i <=
nBins; ++i)
1692 bins[i] =
static_cast<double>(i) - 0.5;
1696 if (KinematicParameter ==
"OscillationChannel") {
1698 }
else if (KinematicParameter ==
"Mode") {
1699 return MakeBins(
Modes->GetNModes());
1704 if(BinningConfig[
GetTitle()] && BinningConfig[
GetTitle()][KinematicParameter]){
1705 auto BinningVect = Get<std::vector<double>>(BinningConfig[
GetTitle()][KinematicParameter], __FILE__, __LINE__);
1708 auto BinningVect = Get<std::vector<double>>(BinningConfig[KinematicParameter], __FILE__, __LINE__);
1720 MACH3LOG_ERROR(
"Attempted to plot kinematic variable {}, but it appears in both KinematicVectors and KinematicParameters", VarStr);
1729 int kModeToFill,
int kChannelToFill,
int WeightStyle, TAxis* Axis) {
1733 if (kChannelToFill != -1) {
1745 if (kModeToFill!=-1) {
1746 if (!(kModeToFill >= 0) && (kModeToFill < Modes->GetNModes())) {
1747 MACH3LOG_ERROR(
"Required mode is not available. kModeToFill should be between 0 and {}",
Modes->GetNModes());
1757 std::vector< KinematicCut > SelectionVec;
1764 SelectionVec.push_back(SelecMode);
1772 SelectionVec.push_back(SelecChannel);
1775 return Get1DVarHist(ProjectionVar_Str,SelectionVec,WeightStyle,Axis);
1779 int kModeToFill,
int kChannelToFill,
int WeightStyle, TAxis* AxisX, TAxis* AxisY) {
1783 if (kChannelToFill!=-1) {
1795 if (kModeToFill!=-1) {
1796 if (!(kModeToFill >= 0) && (kModeToFill < Modes->GetNModes())) {
1797 MACH3LOG_ERROR(
"Required mode is not available. kModeToFill should be between 0 and {}",
Modes->GetNModes());
1807 std::vector< KinematicCut > SelectionVec;
1814 SelectionVec.push_back(SelecMode);
1822 SelectionVec.push_back(SelecChannel);
1825 return Get2DVarHist(ProjectionVar_StrX,ProjectionVar_StrY,SelectionVec,WeightStyle,AxisX,AxisY);
1829 constexpr
int space = 14;
1831 bool printToFile=
false;
1832 if (OutputFileName.CompareTo(
"/dev/null")) {printToFile =
true;}
1834 bool printToCSV=
false;
1835 if(OutputCSVFileName.CompareTo(
"/dev/null")) printToCSV=
true;
1837 std::ofstream outfile;
1839 outfile.open(OutputFileName.Data(), std::ios_base::app);
1840 outfile.precision(7);
1843 std::ofstream outcsv;
1845 outcsv.open(OutputCSVFileName, std::ios_base::app);
1846 outcsv.precision(7);
1849 double PDFIntegral = 0.;
1851 std::vector< std::vector< TH1* > > IntegralList;
1852 IntegralList.resize(
Modes->GetNModes());
1854 std::vector<double> ChannelIntegral;
1856 for (
unsigned int i=0;i<ChannelIntegral.size();i++) {ChannelIntegral[i] = 0.;}
1858 for (
int i=0;i<
Modes->GetNModes();i++) {
1866 MACH3LOG_INFO(
"-------------------------------------------------");
1869 outfile <<
"\\begin{table}[ht]" << std::endl;
1870 outfile <<
"\\begin{center}" << std::endl;
1871 outfile <<
"\\caption{Integral breakdown for sample: " <<
GetTitle() <<
"}" << std::endl;
1872 outfile <<
"\\label{" <<
GetTitle() <<
"-EventRate}" << std::endl;
1877 outfile <<
"\\begin{tabular}{|l" << nColumns.Data() <<
"}" << std::endl;
1878 outfile <<
"\\hline" << std::endl;
1883 outcsv<<
"Integral Breakdown for sample :"<<
GetTitle()<<
"\n";
1889 if (printToFile) {outfile << std::setw(space) <<
"Mode:";}
1890 if(printToCSV) {outcsv<<
"Mode,";}
1892 std::string table_headings = fmt::format(
"| {:<8} |",
"Mode");
1893 std::string table_footline =
"------------";
1896 table_footline +=
"--------------------";
1897 if (printToFile) {outfile <<
"&" << std::setw(space) <<
OscChannels[i].flavourName_Latex <<
" ";}
1900 if (printToFile) {outfile <<
"&" << std::setw(space) <<
"Total:" <<
"\\\\ \\hline" << std::endl;}
1901 if (printToCSV) {outcsv <<
"Total\n";}
1902 table_headings += fmt::format(
" {:<10} |",
"Total");
1903 table_footline +=
"-------------";
1908 for (
unsigned int i=0;i<IntegralList.size();i++) {
1909 double ModeIntegral = 0;
1910 if (printToFile) {outfile << std::setw(space) <<
Modes->GetMaCh3ModeName(i);}
1911 if(printToCSV) {outcsv <<
Modes->GetMaCh3ModeName(i) <<
",";}
1913 table_headings = fmt::format(
"| {:<8} |",
Modes->GetMaCh3ModeName(i));
1915 for (
unsigned int j=0;j<IntegralList[i].size();j++) {
1916 double Integral = IntegralList[i][j]->Integral();
1918 if (Integral<1e-100) {Integral=0;}
1920 ModeIntegral += Integral;
1921 ChannelIntegral[j] += Integral;
1922 PDFIntegral += Integral;
1924 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",Integral) <<
" ";}
1925 if (printToCSV) {outcsv << Form(
"%4.5f", Integral) <<
",";}
1927 table_headings += fmt::format(
" {:<17.4f} |", Integral);
1929 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",ModeIntegral) <<
" \\\\ \\hline" << std::endl;}
1930 if (printToCSV) {outcsv << Form(
"%4.5f", ModeIntegral) <<
"\n";}
1932 table_headings += fmt::format(
" {:<10.4f} |", ModeIntegral);
1937 if (printToFile) {outfile << std::setw(space) <<
"Total:";}
1938 if (printToCSV) {outcsv <<
"Total,";}
1941 table_headings = fmt::format(
"| {:<8} |",
"Total");
1942 for (
unsigned int i=0;i<ChannelIntegral.size();i++) {
1943 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",ChannelIntegral[i]) <<
" ";}
1944 if (printToCSV) {outcsv << Form(
"%4.5f", ChannelIntegral[i]) <<
",";}
1945 table_headings += fmt::format(
" {:<17.4f} |", ChannelIntegral[i]);
1947 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",PDFIntegral) <<
" \\\\ \\hline" << std::endl;}
1948 if (printToCSV) {outcsv << Form(
"%4.5f", PDFIntegral) <<
"\n\n\n\n";}
1950 table_headings += fmt::format(
" {:<10.4f} |", PDFIntegral);
1955 outfile <<
"\\end{tabular}" << std::endl;
1956 outfile <<
"\\end{center}" << std::endl;
1957 outfile <<
"\\end{table}" << std::endl;
1963 outfile << std::endl;
1971 std::vector<TH1*> hHistList;
1972 std::string legendEntry;
1978 if (Selection1 == FDPlotType::kModePlot) {
1979 iMax =
Modes->GetNModes();
1981 if (Selection1 == FDPlotType::kOscChannelPlot) {
1985 MACH3LOG_ERROR(
"You've passed me a Selection1 which was not implemented in ReturnHistsBySelection1D. Selection1 and Selection2 are counters for different indexable quantities");
1989 for (
int i=0;i<iMax;i++) {
1990 if (Selection1 == FDPlotType::kModePlot) {
1992 THStackLeg->AddEntry(hHistList[i],(
Modes->GetMaCh3ModeName(i)+Form(
" : (%4.2f)",hHistList[i]->Integral())).c_str(),
"f");
1994 hHistList[i]->SetFillColor(
static_cast<Color_t
>(
Modes->GetMaCh3ModePlotColor(i)));
1995 hHistList[i]->SetLineColor(
static_cast<Color_t
>(
Modes->GetMaCh3ModePlotColor(i)));
1997 if (Selection1 == FDPlotType::kOscChannelPlot) {
2007 int Selection1,
int Selection2,
int WeightStyle,
2008 TAxis* XAxis, TAxis* YAxis) {
2010 std::vector<TH2*> hHistList;
2013 if (Selection1 == FDPlotType::kModePlot) {
2014 iMax =
Modes->GetNModes();
2016 if (Selection1 == FDPlotType::kOscChannelPlot) {
2020 MACH3LOG_ERROR(
"You've passed me a Selection1 which was not implemented in ReturnHistsBySelection1D. Selection1 and Selection2 are counters for different indexable quantities");
2024 for (
int i=0;i<iMax;i++) {
2025 if (Selection1 == FDPlotType::kModePlot) {
2028 if (Selection1 == FDPlotType::kOscChannelPlot) {
2037 std::vector<TH1*> HistList =
ReturnHistsBySelection1D(KinematicProjection, Selection1, Selection2, WeightStyle, XAxis);
2038 THStack* StackHist =
new THStack((
GetTitle()+
"_"+KinematicProjection+
"_Stack").c_str(),
"");
2039 for (
unsigned int i=0;i<HistList.size();i++) {
2040 StackHist->Add(HistList[i]);
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.
KS: Based on this https://github.com/gabime/spdlog/blob/a2b4262090fd3f005c2315dcb5be2f0f1774a005/incl...
std::function< void(const double *, std::size_t)> FuncParFuncType
void CleanContainer(std::vector< T * > &container)
Generic cleanup function.
NuPDG
Enum to track the incoming neutrino species.
TestStatistic
Make an enum of the test statistic that we're using.
Type GetFromManager(const YAML::Node &node, Type defval, const std::string File="", const int Line=1)
Get content of config file if node is not found take default value specified.
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
bool CheckNodeExists(const YAML::Node &node, Args... args)
KS: Wrapper function to call the recursive helper.
#define M3OpenConfig(filename)
Macro to simplify calling LoadYaml with file and line info.
#define GetBounds(filename)
Custom exception class for MaCh3 errors.
const double * RetPointer(const int iParam)
DB Pointer return to param position.
Class responsible for handling of systematic error parameters with different types defined in the con...
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
std::unique_ptr< MaCh3Modes > Modes
Holds information about used Generator and MaCh3 modes.
TestStatistic fTestStatistic
Test statistic tells what kind of likelihood sample is using.
M3::int_t nSamples
Contains how many samples we've got.
unsigned int nEvents
Number of MC events are there.
bool MatchCondition(const std::vector< T > &allowedValues, const T &value)
check if event is affected by following conditions, for example pdg, or modes etc
std::vector< std::vector< int > > funcParsGrid
HH - a grid of vectors of enums for each sample and event.
void CalcNormsBins(std::vector< NormParameter > &norm_parameters, std::vector< std::vector< int > > &xsec_norms_bins)
Check whether a normalisation systematic affects an event or not.
std::vector< FunctionalParameter > funcParsVec
HH - a vector that stores all the FuncPars struct.
virtual void resetShifts(int iEvent)
HH - reset the shifted values to the original values.
std::vector< FunctionalParameter * > funcParsMap
HH - a map that relates the funcpar enum to pointer of FuncPars struct HH - Changed to a vector of po...
virtual void Init()=0
Initialise any variables that your experiment specific SampleHandler needs.
std::string ReturnStringFromKinematicVector(const int KinematicVariable) const
std::vector< double > ReturnKinematicParameterBinning(const std::string &KinematicParameter)
Return the binning used to draw a kinematic parameter.
std::unique_ptr< BinnedSplineHandler > SplineHandler
Contains all your binned splines and handles the setup and the returning of weights from spline evalu...
virtual void CalcWeightFunc(int iEvent)
Calculate weights for function parameters.
SampleBinningInfo Binning
KS: This stores binning information, in future could be come vector to store binning for every used s...
void PrintIntegral(const TString &OutputName="/dev/null", const int WeightStyle=0, const TString &OutputCSVName="/dev/null")
virtual void SetupSplines()=0
initialise your splineXX object and then use InitialiseSplineObject to conviently setup everything up
SampleInfo SampleDetails
Stores info about currently initialised sample.
bool IsEventSelected(const int iEvent)
DB Function which determines if an event is selected, where Selection double looks like {{ND280Kinema...
ParameterHandlerGeneric * ParHandler
bool FirstTimeW2
KS:Super hacky to update W2 or not.
std::unordered_map< std::string, NuPDG > FileToInitPDGMap
void InitialiseSplineObject()
std::vector< KinematicCut > Selection
a way to store selection cuts which you may push back in the get1DVar functions most of the time this...
double * SampleHandlerFD_data
DB Array to be filled in AddData.
virtual int SetupExperimentMC()=0
Experiment specific setup, returns the number of events which were loaded.
const std::unordered_map< int, std::string > * ReversedKinematicVectors
void FillMCHist(const int Dimension)
Fill a histogram with the event-level information used in the fit.
std::vector< KinematicCut > StoredSelection
What gets pulled from config options, these are constant after loading in this is of length 3: 0th in...
std::vector< std::string > spline_files
names of spline files associated associated with this object
double GetLikelihood() override
DB Multi-threaded GetLikelihood.
std::unordered_map< std::string, NuPDG > FileToFinalPDGMap
std::unordered_map< int, FuncParFuncType > funcParsFuncMap
HH - a map that relates the funcpar enum to pointer of the actual function.
const double * GetPointerToOscChannel(const int iEvent) const
Get pointer to oscillation channel associated with given event. Osc channel is const.
std::vector< OscChannelInfo > OscChannels
Stores info about oscillation channel for a single sample.
void FindNominalBinAndEdges2D()
const std::unordered_map< std::string, int > * KinematicVectors
void SetupNormParameters()
Setup the norm parameters by assigning each event with bin.
void SetupKinematicMap()
Ensure Kinematic Map is setup and make sure it is initialised correctly.
void FillSplineBins()
Finds the binned spline that an event should apply to and stored them in a a vector for easy evaluati...
virtual void PrepFunctionalParameters()
Update the functional parameter values to the latest proposed values. Needs to be called before every...
SampleHandlerFD(std::string ConfigFileName, ParameterHandlerGeneric *xsec_cov, const std::shared_ptr< OscillationHandler > &OscillatorObj_=nullptr)
Constructor.
void Fill2DSubEventHist(TH2D *_h2DVar, const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &SubEventSelectionVec=std::vector< KinematicCut >(), int WeightStyle=0)
void Initialise()
Function which does a lot of the lifting regarding the workflow in creating different MC objects.
virtual ~SampleHandlerFD()
destructor
void FindNominalBinAndEdges1D()
double * SampleHandlerFD_array
DB Array to be filled after reweighting.
std::vector< std::string > funcParsNamesVec
HH - a vector of string names for each functional parameter.
virtual const double * GetPointerToKinematicParameter(std::string KinematicParamter, int iEvent)=0
virtual void SetupFDMC()=0
Function which translates experiment struct into core struct.
void SaveAdditionalInfo(TDirectory *Dir) override
Store additional info in a chan.
std::unique_ptr< manager > SampleManager
The manager object used to read the sample yaml file.
M3::float_t GetEventWeight(const int iEntry) const
void InitialiseNuOscillatorObjects()
including Dan's magic NuOscillator
void RegisterIndividualFunctionalParameter(const std::string &fpName, int fpEnum, FuncParFuncType fpFunc)
HH - a helper function for RegisterFunctionalParameter.
M3::float_t CalcWeightNorm(const FarDetectorCoreInfo *MCEvent) const
Calculate the norm weight for a given event.
bool UpdateW2
KS:Super hacky to update W2 or not.
std::shared_ptr< OscillationHandler > Oscillator
Contains all your binned splines and handles the setup and the returning of weights from spline evalu...
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.
const std::unordered_map< std::string, int > * KinematicParameters
Mapping between string and kinematic enum.
void Set2DBinning(size_t nbins1, double *boundaries1, size_t nbins2, double *boundaries2)
set the binning for 2D sample used for the likelihood calculation
void InitialiseSingleFDMCObject()
function to create the member of the FarDetectorInfo struct so they are the appropriate size.
TH2 * Get2DVarHist(const std::string &ProjectionVarX, const std::string &ProjectionVarY, const std::vector< KinematicCut > &EventSelectionVec=std::vector< KinematicCut >(), int WeightStyle=0, TAxis *AxisX=nullptr, TAxis *AxisY=nullptr, const std::vector< KinematicCut > &SubEventSelectionVec=std::vector< KinematicCut >())
virtual void RegisterFunctionalParameters()=0
HH - a experiment-specific function where the maps to actual functions are set up.
M3::float_t CalcWeightSpline(const FarDetectorCoreInfo *MCEvent) const
Calculate the spline weight for a given event.
std::vector< std::string > mc_files
names of mc files associated associated with this object
void ResetHistograms()
Helper function to reset histograms.
virtual double ReturnKinematicParameter(std::string KinematicParamter, int iEvent)=0
Return the value of an associated kinematic parameter for an event.
bool IsSubEventVarString(const std::string &VarStr)
JM Check if a kinematic parameter string corresponds to a subevent-level variable.
virtual void ApplyShifts(int iEvent)
ETA - generic function applying shifts.
std::unordered_map< std::string, double > _modeNomWeightMap
const std::unordered_map< int, std::string > * ReversedKinematicParameters
Mapping between kinematic enum and string.
int ReturnKinematicVectorFromString(const std::string &KinematicStr) const
virtual void SetupWeightPointers()=0
DB Function to determine which weights apply to which types of samples pure virtual!...
void SetupSampleBinning()
Function to setup the binning of your sample histograms and the underlying arrays that get handled in...
void SetupNuOscillatorPointers()
virtual std::vector< double > ReturnKinematicVector(std::string KinematicParameter, int iEvent)
virtual void SetupFunctionalParameters()
ETA - a function to setup and pass values to functional parameters where you need to pass a value to ...
void FillArray()
DB Nice new multi-threaded function which calculates the event weights and fills the relevant bins of...
double * SampleHandlerFD_array_w2
KS Array used for MC stat.
TLegend * THStackLeg
DB Miscellaneous Variables.
std::vector< FarDetectorCoreInfo > MCSamples
Stores information about every MC event.
void SetupReweightArrays(const size_t numberXBins, const size_t numberYBins)
Initialise data, MC and W2 histograms.
std::unordered_map< std::string, int > funcParsNamesMap
HH - a map that relates the name of the functional parameter to funcpar enum.
void Set1DBinning(size_t nbins, double *boundaries)
sets the binning used for the likelihood calculation, used for both data and MC
std::string SampleName
A unique ID for each sample based on which we can define what systematic should be applied.
const std::vector< NormParameter > GetNormParsFromSampleName(const std::string &SampleName) const
DB Get norm/func parameters depending on given SampleName.
std::string GetParFancyName(const int i) const
Get fancy name of the Parameter.
const std::vector< FunctionalParameter > GetFunctionalParametersFromSampleName(const std::string &SampleName) const
HH Get functional parameters for the relevant SampleName.
std::vector< const double * > GetOscParsFromSampleName(const std::string &SampleName)
Get pointers to Osc params from Sample name.
std::string GetXBinVarName() const
std::string GetYBinVarName() const
TH1 * Get1DVarHist(const std::string &ProjectionVar, const std::vector< KinematicCut > &EventSelectionVec=std::vector< KinematicCut >(), int WeightStyle=0, TAxis *Axis=nullptr, const std::vector< KinematicCut > &SubEventSelectionVec=std::vector< KinematicCut >())
std::string ReturnStringFromKinematicParameter(const int KinematicVariable) const
ETA function to generically convert a kinematic type from xsec cov to a string.
std::string GetSampleName(int iSample=0) const override
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....
void Fill1DSubEventHist(TH1D *_h1DVar, const std::string &ProjectionVar, const std::vector< KinematicCut > &SubEventSelectionVec=std::vector< KinematicCut >(), int WeightStyle=0)
int GetNDim() const
DB Function to differentiate 1D or 2D binning.
unsigned int GetNEvents() const
std::vector< TH2 * > ReturnHistsBySelection2D(std::string KinematicProjectionX, std::string KinematicProjectionY, int Selection1, int Selection2=-1, int WeightStyle=0, TAxis *XAxis=0, TAxis *YAxis=0)
std::string GetTitle() const override
std::string GetFlavourName(const int iChannel)
int GetNOscChannels() override
TH2 * Get2DVarHistByModeAndChannel(const std::string &ProjectionVar_StrX, const std::string &ProjectionVar_StrY, int kModeToFill=-1, int kChannelToFill=-1, int WeightStyle=0, TAxis *AxisX=nullptr, TAxis *AxisY=nullptr)
TH1 * GetW2Hist(const int Dimension)
Get W2 histogram.
TH1 * Get1DVarHistByModeAndChannel(const std::string &ProjectionVar_Str, int kModeToFill=-1, int kChannelToFill=-1, int WeightStyle=0, TAxis *Axis=nullptr)
TH1 * GetMCHist(const int Dimension)
Get MC histogram.
std::vector< TH1 * > ReturnHistsBySelection1D(std::string KinematicProjection, int Selection1, int Selection2=-1, int WeightStyle=0, TAxis *Axis=0)
int ReturnKinematicParameterFromString(const std::string &KinematicStr) const
ETA function to generically convert a string from xsec cov to a kinematic type.
TH1 * GetDataHist(const int Dimension)
Get Data histogram.
THStack * ReturnStackedHistBySelection1D(std::string KinematicProjection, int Selection1, int Selection2=-1, int WeightStyle=0, TAxis *Axis=0)
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
constexpr static const float_t Unity
constexpr static const float_t Zero
constexpr static const int _BAD_INT_
Default value used for int initialisation.
int PDGToNuOscillatorFlavour(const int NuPdg)
Convert from PDG flavour to NuOscillator type beware that in the case of anti-neutrinos the NuOscilla...
constructors are same for all three so put in here
std::vector< const double * > xsec_norm_pointers
Pointers to normalisation weights which are being taken from Parameter Handler.
M3::float_t xsec_w
Total weight of norm and spline parameters.
std::vector< const M3::float_t * > xsec_spline_pointers
Pointers to spline weights which are being calculated by Splines Handler.
HH - Functional parameters Carrier for whether you want to apply a systematic to an event or not.
const double * valuePtr
Parameter value pointer.
FuncParFuncType * funcPtr
Function pointer.
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.
KS: Store info about used osc channels.
std::string flavourName
Name of osc channel.
int GetBin(const int xBin, const int yBin) const
Get linear bin index from 2D bin indices.
void InitialiseBinMigrationLookUp()
Initialise special lookup arrays allowing to more efficiently perform bin-migration These arrays stor...
std::vector< double > YBinEdges
Vector to hold y-axis bin-edges.
size_t nXBins
Number of X axis bins in the histogram used for likelihood calculation.
size_t nYBins
Number of Y axis bins in the histogram used for likelihood calculation.
int GetBinSafe(const int xBin, const int yBin) const
Get linear bin index from 2D bin indices with additional checks.
size_t GlobalOffset
If you have binning for multiple samples and trying to define 1D vector let's.
std::vector< double > XBinEdges
Vector to hold x-axis bin-edges.
size_t nBins
Number of total bins.
int FindXBin(const double XVar, const int NomXBin) const
DB Find the relevant bin in the PDF for each event.
TH1D * _hPDF1D
histogram used for plotting storing 1D MC distribution
void InitialiseHistograms()
Initialise histograms used for plotting.
TH2D * _hPDF2D
histogram used for plotting storing 2D MC distribution
int nDimensions
Keep track of the dimensions of the sample binning.
std::string XVarStr
the strings associated with the variables used for the X binning e.g. "RecoNeutrinoEnergy"
std::string SampleTitle
the name of this sample e.g."muon-like"
TH2D * dathist2d
histogram used for plotting storing 2D data distribution
TH1D * dathist
histogram used for plotting storing 1D data distribution
std::string YVarStr
the strings associated with the variables used for the Y binning e.g. "RecoNeutrinoEnergy"