15 MACH3LOG_INFO(
"-------------------------------------------------------------------");
20 MACH3LOG_WARN(
"You've passed me a nullptr ParameterHandler so I will not use any xsec parameters");
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");
30 MACH3LOG_CRITICAL(
"You've passed me a nullptr to ParamHandler while non null to Oscillator");
42 SampleManager = std::make_unique<Manager>(ConfigFileName.c_str());
43 Binning = std::make_unique<BinningHandler>();
57 auto ModeName = Get<std::string>(
SampleManager->raw()[
"MaCh3ModeConfig"], __FILE__ , __LINE__);
58 Modes = std::make_unique<MaCh3Modes>(getenv(
"MACH3")+std::string(
"/") + ModeName);
64 UpdateW2 = GetFromManager<bool>(
SampleManager->raw()[
"LikelihoodOptions"][
"UpdateW2"],
false, __FILE__ , __LINE__);
72 auto EnabledSasmples = Get<std::vector<std::string>>(
SampleManager->raw()[
"Samples"], __FILE__ , __LINE__);
82 for (
int iSample = 0; iSample <
nSamples; iSample++)
84 auto SampleSettings =
SampleManager->raw()[EnabledSasmples[iSample]];
89 for(
int iMode=0; iMode <
Modes->GetNModes(); iMode++ ) {
95 for(
int iMode=0; iMode<
Modes->GetNModes(); iMode++ ) {
96 std::string modeStr =
Modes->GetMaCh3ModeName(iMode);
98 double modeWeight =
SampleManager->raw()[
"NominalWeights"][modeStr].as<
double>();
106 for(
int iMode=0; iMode<
Modes->GetNModes(); iMode++ ) {
107 std::string modeStr =
Modes->GetMaCh3ModeName(iMode);
118 SingleSample.
SampleTitle = Get<std::string>(SampleSettings[
"SampleTitle"], __FILE__ , __LINE__);
120 SingleSample.
SampleName = GetFromManager<std::string>(SampleSettings[
"SampleName"],
GetName(), __FILE__ , __LINE__);
122 Binning->SetupSampleBinning(SampleSettings[
"Binning"], SingleSample);
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__);
129 int NChannels =
static_cast<M3::int_t>(SampleSettings[
"OscChannels"].size());
132 YAML::Node OscChannelsConfig;
134 if(SampleSettings[
"OscChannels"].IsScalar()) {
135 auto PredeterminedChannelsName = Get<std::string>(SampleSettings[
"OscChannels"], __FILE__, __LINE__);
137 MACH3LOG_ERROR(
"Trying to use Predetermined OscChannels however such field doesn't exist in config for SampleHandler: {}",
GetName());
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"]) {
148 OscChannelsConfig =
SampleManager->raw()[
"OscChannels"][PredeterminedChannelsName];
150 OscChannelsConfig = SampleSettings[
"OscChannels"];
152 int OscChannelCounter = 0;
153 for (
auto const &osc_channel : OscChannelsConfig) {
155 OscInfo.
flavourName = Get<std::string>(osc_channel[
"Name"], __FILE__ , __LINE__);
156 OscInfo.
flavourName_Latex = Get<std::string>(osc_channel[
"LatexName"], __FILE__ , __LINE__);
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 {}",
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;
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);
183 for (
auto const &SelectionCuts : SampleSettings[
"SelectionCuts"]) {
184 auto TempBoundsVec =
GetBounds(SelectionCuts[
"Bounds"]);
189 MACH3LOG_INFO(
"Adding cut on {} with bounds {} to {}", SelectionCuts[
"KinematicStr"].as<std::string>(), TempBoundsVec[0], TempBoundsVec[1]);
213 MACH3LOG_INFO(
"=============================================");
229 MACH3LOG_INFO(
"Finished loading MC for {}, it took {:.2f}s to finish",
GetName(), clock.RealTime());
232 MACH3LOG_INFO(
"=======================================================");
240 MACH3LOG_ERROR(
"Map KinematicParameters or ReversedKinematicParameters hasn't been initialised");
245 const auto& key = pair.first;
246 const auto& value = pair.second;
256 std::vector<std::string> Vars = {
"Mode",
"OscillationChannel",
"TargetNucleus"};
257 for(
size_t iVar = 0; iVar < Vars.size(); iVar++) {
261 MACH3LOG_ERROR(
"MaCh3 expected variable: {} not found in KinematicParameters.", Vars[iVar]);
271 #pragma GCC diagnostic push
272 #pragma GCC diagnostic ignored "-Wconversion"
276 int Dimension =
GetNDim(Sample);
281 for (
int xBin = 0; xBin <
Binning->GetNAxisBins(Sample, 0); ++xBin) {
282 const int idx =
Binning->GetGlobalBinSafe(Sample, {xBin});
283 Hist->SetBinContent(xBin + 1, Array[idx]);
285 }
else if (Dimension == 2) {
287 if(
Binning->IsUniform(Sample)) {
288 for (
int yBin = 0; yBin <
Binning->GetNAxisBins(Sample, 1); ++yBin) {
289 for (
int xBin = 0; xBin <
Binning->GetNAxisBins(Sample, 0); ++xBin) {
290 const int idx =
Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
291 Hist->SetBinContent(xBin + 1, yBin + 1, Array[idx]);
295 for (
int iBin = 0; iBin <
Binning->GetNBins(Sample); ++iBin) {
296 const int idx = iBin +
Binning->GetSampleStartBin(Sample);
298 Hist->SetBinContent(iBin + 1, Array[idx]);
302 for (
int iBin = 0; iBin <
Binning->GetNBins(Sample); ++iBin) {
303 const int idx = iBin +
Binning->GetSampleStartBin(Sample);
305 Hist->SetBinContent(iBin + 1, Array[idx]);
309 #pragma GCC diagnostic pop
315 const auto& SampleSelection = Selection[iSample];
316 const int SelectionSize =
static_cast<int>(SampleSelection.size());
317 for (
int iSelection = 0; iSelection < SelectionSize; ++iSelection) {
318 const auto& Cut = SampleSelection[iSelection];
319 const double Val = ReturnKinematicParameter(Cut.ParamToCutOnIt, iEvent);
320 if ((Val < Cut.LowerBound) || (Val >= Cut.UpperBound)) {
330 for (
unsigned int iSelection=0;iSelection < SubEventCuts.size() ;iSelection++) {
332 if (nsubevents != Vec.size()) {
333 MACH3LOG_ERROR(
"Cannot apply kinematic cut on {} as it is of different size to plotting variable");
336 const double Val = Vec[iSubEvent];
337 if ((Val < SubEventCuts[iSelection].LowerBound) || (Val >= SubEventCuts[iSelection].UpperBound)) {
391 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
404 if (totalweight <= 0.){
409 const int GlobalBin =
Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
420 #pragma GCC diagnostic push
421 #pragma GCC diagnostic ignored "-Walloca"
443 const auto TotalBins =
Binning->GetNBins();
444 const unsigned int NumberOfEvents =
GetNEvents();
449 #pragma omp parallel for reduction(+:MC_Array_for_reduction[:TotalBins], W2_array_for_reduction[:TotalBins])
450 for (
unsigned int iEvent = 0; iEvent < NumberOfEvents; ++iEvent) {
466 if (totalweight <= 0.){
471 const int GlobalBin =
Binning->FindGlobalBin(MCEvent->NominalSample, MCEvent->KinVar, MCEvent->NomBin);
478 MC_Array_for_reduction[GlobalBin] += totalweight;
479 if (
FirstTimeW2) W2_array_for_reduction[GlobalBin] += totalweight*totalweight;
483 #pragma GCC diagnostic pop
492 const int nBins =
Binning->GetNBins();
513 shift.apply(shift.par_vals, iEvent);
524 const int TotalWeights =
static_cast<int>(MCEvent->total_weight_pointers.size());
527 #pragma omp simd reduction(*:TotalWeight)
529 for (
int iWeight = 0; iWeight < TotalWeights; ++iWeight) {
530 TotalWeight *= *(MCEvent->total_weight_pointers[iWeight]);
544 if (OscParams.size() > 0) {
547 MACH3LOG_INFO(
"You have passed an OscillatorBase object through the constructor of a SampleHandlerFD object - this will be used for all oscillation channels");
548 if(
Oscillator->isEqualBinningPerOscChannel() !=
true) {
549 MACH3LOG_ERROR(
"Trying to run shared NuOscillator without EqualBinningPerOscChannel, this will not work");
553 if(OscParams.size() !=
Oscillator->GetOscParamsSize()){
554 MACH3LOG_ERROR(
"SampleHandler {} has {} osc params, while shared NuOsc has {} osc params",
GetName(),
555 OscParams.size(),
Oscillator->GetOscParamsSize());
556 MACH3LOG_ERROR(
"This indicate misconfiguration in your Osc yaml");
564 MACH3LOG_WARN(
"Didn't find any oscillation params, thus will not enable oscillations");
568 MACH3LOG_ERROR(
"Either remove 'NuOsc' field from SampleHandler config or check your model.yaml and include oscillation for sample");
580 std::vector< std::vector< int > > norms_bins(
GetNEvents());
582 std::vector< std::vector<NormParameter>> norm_parameters(
GetNSamples());
584 for (
int iSample = 0; iSample <
GetNSamples(); ++iSample) {
596 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); ++iEvent) {
598 const size_t offset =
MCEvents[iEvent].total_weight_pointers.size();
599 const size_t addSize = norms_bins[iEvent].size();
600 MCEvents[iEvent].total_weight_pointers.resize(offset + addSize);
601 for(
auto const & norm_bin: norms_bins[iEvent]) {
612 for(
unsigned int iEvent = 0; iEvent <
GetNEvents(); ++iEvent){
613 std::vector< int > NormBins = {};
615 const auto SampleId =
MCEvents[iEvent].NominalSample;
616 auto& NormParam = norm_parameters[SampleId];
625 for (std::vector<NormParameter>::iterator it = NormParam.begin(); it != NormParam.end(); ++it) {
630 MACH3LOG_TRACE(
"Event {}, missed target check ({}) for dial {}", iEvent, Target, it->name);
643 if (!FlavourUnoscMatch){
644 MACH3LOG_TRACE(
"Event {}, missed FlavourUnosc check ({}) for dial {}", iEvent,
MCEvents[iEvent].nupdgUnosc, it->name);
652 MACH3LOG_TRACE(
"Event {}, missed Mode check ({}) for dial {}", iEvent, Mode, it->name);
662 MACH3LOG_TRACE(
"Event {}, missed Kinematic var check for dial {}", iEvent, it->name);
669 NormBins.push_back(bin);
670 MACH3LOG_TRACE(
"Event {}, will be affected by dial {}", iEvent, it->name);
673 norms_bins[iEvent] = NormBins;
688 for(
int iSample = 0; iSample <
GetNSamples(); iSample++)
690 int Dimension =
GetNDim(iSample);
695 auto XVec =
Binning->GetBinEdges(iSample, 0);
696 SamDet->DataHist =
new TH1D((
"d" + HistTitle).c_str(), HistTitle.c_str(),
static_cast<int>(XVec.size()-1), XVec.data());
697 SamDet->MCHist =
new TH1D((
"h" + HistTitle).c_str(), HistTitle.c_str(),
static_cast<int>(XVec.size()-1), XVec.data());
698 SamDet->W2Hist =
new TH1D((
"w" + HistTitle).c_str(), HistTitle.c_str(),
static_cast<int>(XVec.size()-1), XVec.data());
701 SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
702 SamDet->DataHist->GetYaxis()->SetTitle(
"Events");
703 SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
704 SamDet->MCHist->GetYaxis()->SetTitle(
"Events");
705 SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
706 SamDet->W2Hist->GetYaxis()->SetTitle(
"Events");
707 }
else if (Dimension == 2){
708 if(
Binning->IsUniform(iSample)) {
709 auto XVec =
Binning->GetBinEdges(iSample, 0);
710 auto YVec =
Binning->GetBinEdges(iSample, 1);
711 int nX =
static_cast<int>(XVec.size() - 1);
712 int nY =
static_cast<int>(YVec.size() - 1);
714 SamDet->DataHist =
new TH2D((
"d" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
715 SamDet->MCHist =
new TH2D((
"h" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
716 SamDet->W2Hist =
new TH2D((
"w" + HistTitle).c_str(), HistTitle.c_str(), nX, XVec.data(), nY, YVec.data());
718 auto AddBinsToTH2Poly = [](TH2Poly* hist,
const std::vector<BinInfo>& bins) {
719 for (
const auto& bin : bins) {
720 double xLow = bin.Extent[0][0];
721 double xHigh = bin.Extent[0][1];
722 double yLow = bin.Extent[1][0];
723 double yHigh = bin.Extent[1][1];
725 double x[4] = {xLow, xHigh, xHigh, xLow};
726 double y[4] = {yLow, yLow, yHigh, yHigh};
728 hist->AddBin(4, x, y);
732 SamDet->DataHist =
new TH2Poly();
733 SamDet->DataHist->SetName((
"d" + HistTitle).c_str());
734 SamDet->DataHist->SetTitle(HistTitle.c_str());
736 SamDet->MCHist =
new TH2Poly();
737 SamDet->MCHist->SetName((
"h" + HistTitle).c_str());
738 SamDet->MCHist->SetTitle(HistTitle.c_str());
740 SamDet->W2Hist =
new TH2Poly();
741 SamDet->W2Hist->SetName((
"w" + HistTitle).c_str());
742 SamDet->W2Hist->SetTitle(HistTitle.c_str());
745 AddBinsToTH2Poly(
static_cast<TH2Poly*
>(SamDet->DataHist),
Binning->GetNonUniformBins(iSample));
746 AddBinsToTH2Poly(
static_cast<TH2Poly*
>(SamDet->MCHist),
Binning->GetNonUniformBins(iSample));
747 AddBinsToTH2Poly(
static_cast<TH2Poly*
>(SamDet->W2Hist),
Binning->GetNonUniformBins(iSample));
751 SamDet->DataHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
752 SamDet->DataHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
753 SamDet->MCHist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
754 SamDet->MCHist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
755 SamDet->W2Hist->GetXaxis()->SetTitle(SamDet->VarStr[0].c_str());
756 SamDet->W2Hist->GetYaxis()->SetTitle(SamDet->VarStr[1].c_str());
758 int nbins =
Binning->GetNBins(iSample);
759 SamDet->DataHist =
new TH1D((
"d" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
760 SamDet->MCHist =
new TH1D((
"h" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
761 SamDet->W2Hist =
new TH1D((
"w" + HistTitle).c_str(), HistTitle.c_str(), nbins, 0, nbins);
763 for(
int iBin = 0; iBin < nbins; iBin++) {
764 auto BinName =
Binning->GetBinName(iSample, iBin);
765 SamDet->DataHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
766 SamDet->MCHist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
767 SamDet->W2Hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
771 SamDet->DataHist->GetYaxis()->SetTitle(
"Events");
772 SamDet->MCHist->GetYaxis()->SetTitle(
"Events");
773 SamDet->W2Hist->GetYaxis()->SetTitle(
"Events");
776 SamDet->DataHist->SetDirectory(
nullptr);
777 SamDet->MCHist->SetDirectory(
nullptr);
778 SamDet->W2Hist->SetDirectory(
nullptr);
789 for (
unsigned int event_i = 0; event_i <
GetNEvents(); event_i++) {
790 int Sample =
MCEvents[event_i].NominalSample;
791 const int dim =
GetNDim(Sample);
792 MCEvents[event_i].KinVar.resize(dim);
793 MCEvents[event_i].NomBin.resize(dim);
795 auto SetNominalBin = [&](
int bin,
int max_bins,
int& out_bin) {
796 if (bin >= 0 && bin < max_bins) {
804 for(
int iDim = 0; iDim < dim; iDim++) {
806 if (std::isnan(*
MCEvents[event_i].KinVar[iDim]) || std::isinf(*
MCEvents[event_i].KinVar[iDim])) {
807 MACH3LOG_ERROR(
"Variable {} for sample {} and dimension {} is ill-defined and equal to {}",
811 const int bin =
Binning->FindNominalBin(Sample, iDim, *
MCEvents[event_i].KinVar[iDim]);
812 int NBins_i =
static_cast<int>(
Binning->GetBinEdges(Sample, iDim).size() - 1);
813 SetNominalBin(bin, NBins_i,
MCEvents[event_i].NomBin[iDim]);
887 MACH3LOG_INFO(
"Adding {}D data histogram: {} with {:.2f} events", Dim, Data->GetTitle(), Data->Integral());
890 SampleDetails[Sample].DataHist =
static_cast<TH1*
>(Data->Clone());
893 MACH3LOG_ERROR(
"SampleHandler_data haven't been initialised yet");
897 auto ChecHistType = [&](
const std::string& Type,
const int Dimen,
const TH1* Hist,
898 const std::string& file,
const int line) {
899 if (std::string(Hist->ClassName()) != Type) {
900 MACH3LOG_ERROR(
"Expected {} for {}D sample, got {}", Type, Dimen, Hist->ClassName());
907 ChecHistType(
"TH1D", Dim,
SampleDetails[Sample].DataHist, __FILE__, __LINE__);
909 static_cast<TH1D*
>(
SampleDetails[Sample].MCHist), __FILE__, __LINE__);
910 for (
int xBin = 0; xBin <
Binning->GetNAxisBins(Sample, 0); ++xBin) {
911 const int idx =
Binning->GetGlobalBinSafe(Sample, {xBin});
916 SampleDetails[Sample].DataHist->GetYaxis()->SetTitle(
"Number of Events");
917 }
else if (Dim == 2) {
918 if(
Binning->IsUniform(Sample)) {
919 ChecHistType(
"TH2D", Dim,
SampleDetails[Sample].DataHist, __FILE__, __LINE__);
921 static_cast<TH2D*
>(
SampleDetails[Sample].MCHist), __FILE__, __LINE__);
922 for (
int yBin = 0; yBin <
Binning->GetNAxisBins(Sample, 1); ++yBin) {
923 for (
int xBin = 0; xBin <
Binning->GetNAxisBins(Sample, 0); ++xBin) {
924 const int idx =
Binning->GetGlobalBinSafe(Sample, {xBin, yBin});
930 ChecHistType(
"TH2Poly", Dim,
SampleDetails[Sample].DataHist, __FILE__, __LINE__);
932 static_cast<TH2Poly*
>(
SampleDetails[Sample].MCHist), __FILE__, __LINE__);
933 for (
int iBin = 0; iBin <
Binning->GetNBins(Sample); ++iBin) {
934 const int idx = iBin +
Binning->GetSampleStartBin(Sample);
942 SampleDetails[Sample].DataHist->GetZaxis()->SetTitle(
"Number of Events");
944 ChecHistType(
"TH1D", Dim,
SampleDetails[Sample].DataHist, __FILE__, __LINE__);
946 static_cast<TH1D*
>(
SampleDetails[Sample].MCHist), __FILE__, __LINE__);
947 for (
int iBin = 0; iBin <
Binning->GetNBins(Sample); ++iBin) {
948 const int idx = iBin +
Binning->GetSampleStartBin(Sample);
958 const int Start =
Binning->GetSampleStartBin(Sample);
959 const int End =
Binning->GetSampleEndBin(Sample);
960 const int ExpectedSize = End - Start;
962 if (
static_cast<int>(Data_Array.size()) != ExpectedSize) {
964 MACH3LOG_ERROR(
"Expected size: {}, received size: {}.", ExpectedSize, Data_Array.size());
966 MACH3LOG_ERROR(
"This likely indicates a binning or sample slicing bug.");
978 auto NuOscillatorConfigFile = Get<std::string>(
SampleManager->raw()[
"NuOsc"][
"NuOscConfigFile"], __FILE__ , __LINE__);
979 auto EqualBinningPerOscChannel = Get<bool>(
SampleManager->raw()[
"NuOsc"][
"EqualBinningPerOscChannel"], __FILE__ , __LINE__);
982 if (EqualBinningPerOscChannel) {
983 if (YAML::LoadFile(NuOscillatorConfigFile)[
"General"][
"CalculationType"].as<std::string>() ==
"Unbinned") {
984 MACH3LOG_WARN(
"Tried using EqualBinningPerOscChannel while using Unbinned oscillation calculation, changing EqualBinningPerOscChannel to false");
985 EqualBinningPerOscChannel =
false;
990 if (OscParams.empty()) {
992 MACH3LOG_ERROR(
"This likely indicates an error in your oscillation YAML configuration.");
996 for(
int iSample = 1; iSample <
GetNSamples(); iSample++) {
998 if (OscParamsCrossCheck.size() != OscParams.size()) {
999 MACH3LOG_ERROR(
"Sample {} has {} osc params while sample {} has {}",
1004 Oscillator = std::make_shared<OscillationHandler>(NuOscillatorConfigFile, EqualBinningPerOscChannel, OscParams,
GetNOscChannels(0));
1006 if(!EqualBinningPerOscChannel) {
1008 for(
int iSample = 1; iSample <
GetNSamples(); iSample++) {
1011 for(
int iSample = 0; iSample <
GetNSamples(); iSample++) {
1012 for(
int iChannel = 0; iChannel <
GetNOscChannels(iSample); iChannel++) {
1013 std::vector<M3::float_t> EnergyArray;
1014 std::vector<M3::float_t> CosineZArray;
1016 #pragma GCC diagnostic push
1017 #pragma GCC diagnostic ignored "-Wuseless-cast"
1018 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1019 if(
MCEvents[iEvent].NominalSample != iSample)
continue;
1023 if (!
MCEvents[iEvent].isNC && Channel == iChannel) {
1027 std::sort(EnergyArray.begin(),EnergyArray.end());
1032 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1033 if(
MCEvents[iEvent].NominalSample != iSample)
continue;
1037 if (!
MCEvents[iEvent].isNC && Channel == iChannel) {
1041 std::sort(CosineZArray.begin(),CosineZArray.end());
1043 #pragma GCC diagnostic pop
1044 Oscillator->SetOscillatorBinning(iSample, iChannel, EnergyArray, CosineZArray);
1053 auto AddOscPointer = GetFromManager<bool>(
SampleManager->raw()[
"NuOsc"][
"AddOscPointer"],
true, __FILE__ , __LINE__);
1055 if(!AddOscPointer) {
1058 for (
unsigned int iEvent=0;iEvent<
GetNEvents();iEvent++) {
1063 MCEvents[iEvent].total_weight_pointers.push_back(osc_w_pointer);
1086 MACH3LOG_ERROR(
"Something has gone wrong in the mapping between MCEvents.nutype and the enum used within NuOscillator");
1093 const int Sample =
MCEvents[iEvent].NominalSample;
1099 osc_w_pointer =
Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(
MCEvents[iEvent].enu_true), FLOAT_T(
MCEvents[iEvent].coszenith_true));
1102 osc_w_pointer =
Oscillator->GetNuOscillatorPointers(Sample, OscIndex, InitFlav, FinalFlav, FLOAT_T(
MCEvents[iEvent].enu_true));
1105 return osc_w_pointer;
1133 if (totalweight <= 0.){
1142 const int SampleIndex =
MCEvents[Event].NominalSample;
1144 bool NoOscChannels =
false;
1146 MACH3LOG_DEBUG(
"Assuming there are no osc channels in {}", __func__);
1147 NoOscChannels =
true;
1152 const double Etrue =
MCEvents[Event].enu_true;
1153 std::vector< SplineIndex > EventSplines;
1154 switch(
GetNDim(SampleIndex)) {
1156 EventSplines = BinnedSpline->
GetEventSplines(SampleTitle, OscIndex, Mode, Etrue, *(
MCEvents[Event].KinVar[0]), 0.);
1162 if(ThrowCrititcal) {
1165 ThrowCrititcal =
false;
1170 return EventSplines;
1178 bool ThrowCrititcal =
true;
1180 std::vector< std::vector<SplineParameter> > SplineParsVec(
GetNSamples());
1181 for (
int iSample = 0; iSample <
GetNSamples(); ++iSample) {
1184 for (
unsigned int j = 0; j <
GetNEvents(); ++j) {
1185 auto EventSplines =
GetSplineBins(j, BinnedSpline, ThrowCrititcal);
1186 const int NSplines =
static_cast<int>(EventSplines.size());
1187 if(NSplines == 0)
continue;
1188 auto& w_pointers =
MCEvents[j].total_weight_pointers;
1189 w_pointers.reserve(w_pointers.size() + NSplines);
1190 const auto SampleId =
MCEvents[j].NominalSample;
1191 for(
int spline = 0; spline < NSplines; spline++) {
1192 int SystIndex = EventSplines[spline].iSyst;
1194 bool IsSelected =
PassesSelection(SplineParsVec[SampleId][SystIndex], j);
1197 MACH3LOG_TRACE(
"Event {}, missed Kinematic var check for dial {}", j, SplineParsVec[SampleId][SystIndex].name);
1201 w_pointers.push_back(BinnedSpline->RetPointer(EventSplines[spline]));
1203 w_pointers.shrink_to_fit();
1206 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); ++iEvent) {
1207 MCEvents[iEvent].total_weight_pointers.push_back(UnbinnedSpline->RetPointer(iEvent));
1218 const int Start =
Binning->GetSampleStartBin(isample);
1219 const int End =
Binning->GetSampleEndBin(isample);
1221 double negLogL = 0.;
1223 #pragma omp parallel for reduction(+:negLogL)
1225 for (
int idx = Start; idx < End; ++idx)
1240 double negLogL = 0.;
1242 #pragma omp parallel for reduction(+:negLogL)
1244 for (
int idx = 0; idx <
Binning->GetNBins(); ++idx)
1265 for(
int iSample = 0; iSample <
GetNSamples(); iSample++)
1267 std::unique_ptr<TH1> data_hist;
1271 data_hist->GetXaxis()->SetTitle(
GetKinVarName(iSample, 0).c_str());
1272 data_hist->GetYaxis()->SetTitle(
"Number of Events");
1273 }
else if (
GetNDim(iSample) == 2) {
1274 if(
Binning->IsUniform(iSample)) {
1279 data_hist->GetXaxis()->SetTitle(
GetKinVarName(iSample, 0).c_str());
1280 data_hist->GetYaxis()->SetTitle(
GetKinVarName(iSample, 1).c_str());
1281 data_hist->GetZaxis()->SetTitle(
"Number of Events");
1284 int nbins =
Binning->GetNBins(iSample);
1285 for(
int iBin = 0; iBin < nbins; iBin++) {
1286 auto BinName =
Binning->GetBinName(iSample, iBin);
1287 data_hist->GetXaxis()->SetBinLabel(iBin+1, BinName.c_str());
1289 data_hist->GetYaxis()->SetTitle(
"Number of Events");
1297 data_hist->SetTitle((
"data_" +
GetSampleTitle(iSample)).c_str());
1306 bool LoadSplineFile = GetFromManager<bool>(
SampleManager->raw()[
"InputFiles"][
"LoadSplineFile"],
false, __FILE__, __LINE__);
1307 bool PrepSplineFile = GetFromManager<bool>(
SampleManager->raw()[
"InputFiles"][
"PrepSplineFile"],
false, __FILE__, __LINE__);
1308 auto SplineFileName = GetFromManager<std::string>(
SampleManager->raw()[
"InputFiles"][
"SplineFileName"],
1310 if(!LoadSplineFile) {
1311 for(
int iSample = 0; iSample <
GetNSamples(); iSample++) {
1312 std::vector<std::string> spline_filepaths =
SampleDetails[iSample].spline_files;
1315 std::vector<std::string> SplineVarNames = {
"TrueNeutrinoEnergy"};
1318 }
else if (
GetNDim(iSample) == 2) {
1328 BinnedSplines->CountNumberOfLoadedSplines(
false, 1);
1329 BinnedSplines->TransferToMonolith();
1330 if(PrepSplineFile) BinnedSplines->PrepareSplineFile(SplineFileName);
1333 BinnedSplines->LoadSplineFile(SplineFileName);
1340 BinnedSplines->CleanUpMemory();
1342 (void) UnbinnedSpline;
1352 const std::vector<KinematicCut>& ExtraCuts) {
1361 for (
const auto& cut : ExtraCuts) {
1362 selectionToApply[iSample].emplace_back(cut);
1366 Selection = std::move(selectionToApply);
1368 return originalSelection;
1374 const std::vector< KinematicCut >& EventSelectionVec,
1375 const int WeightStyle,
1376 const std::vector< KinematicCut >& SubEventSelectionVec) {
1384 auto _h1DVar = std::make_unique<TH1D>(
"",
"",
int(xBinEdges.size())-1, xBinEdges.data());
1385 _h1DVar->SetDirectory(
nullptr);
1386 _h1DVar->GetXaxis()->SetTitle(ProjectionVar_Str.c_str());
1387 _h1DVar->GetYaxis()->SetTitle(
"Events");
1390 Fill1DSubEventHist(iSample, _h1DVar.get(), ProjectionVar_Str, SubEventSelectionVec, WeightStyle);
1396 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1397 const int EventSample =
MCEvents[iEvent].NominalSample;
1398 if(EventSample != iSample)
continue;
1401 if (WeightStyle == 1) {
1405 _h1DVar->Fill(Var, Weight);
1417 const std::vector< KinematicCut >& SubEventSelectionVec,
const int WeightStyle) {
1422 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1423 const int EventSample =
MCEvents[iEvent].NominalSample;
1424 if(EventSample != iSample)
continue;
1427 if (WeightStyle == 1) {
1431 size_t nsubevents = Vec.size();
1433 for (
unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1435 double Var = Vec[iSubEvent];
1436 _h1DVar->Fill(Var,Weight);
1445 const std::string& ProjectionVar_StrX,
1446 const std::string& ProjectionVar_StrY,
1447 const std::vector< KinematicCut >& EventSelectionVec,
1448 const int WeightStyle,
1449 const std::vector< KinematicCut >& SubEventSelectionVec) {
1457 std::unique_ptr<TH2> _h2DVar;
1460 _h2DVar = std::unique_ptr<TH2>(
static_cast<TH2*
>(
M3::Clone(
GetMCHist(iSample)).release()));
1464 _h2DVar = std::make_unique<TH2D>(
"",
"",
int(xBinEdges.size())-1, xBinEdges.data(),
int(yBinEdges.size())-1, yBinEdges.data());
1466 _h2DVar->SetDirectory(
nullptr);
1467 _h2DVar->GetXaxis()->SetTitle(ProjectionVar_StrX.c_str());
1468 _h2DVar->GetYaxis()->SetTitle(ProjectionVar_StrY.c_str());
1469 _h2DVar->GetZaxis()->SetTitle(
"Events");
1472 if (IsSubEventHist)
Fill2DSubEventHist(iSample, _h2DVar.get(), ProjectionVar_StrX, ProjectionVar_StrY, SubEventSelectionVec, WeightStyle);
1479 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1480 const int EventSample =
MCEvents[iEvent].NominalSample;
1481 if(EventSample != iSample)
continue;
1484 if (WeightStyle == 1) {
1489 _h2DVar->Fill(VarX,VarY,Weight);
1501 const std::string& ProjectionVar_StrX,
1502 const std::string& ProjectionVar_StrY,
1503 const std::vector< KinematicCut >& SubEventSelectionVec,
1509 int ProjectionVar_IntX, ProjectionVar_IntY;
1516 for (
unsigned int iEvent = 0; iEvent <
GetNEvents(); iEvent++) {
1517 const int EventSample =
MCEvents[iEvent].NominalSample;
1518 if(EventSample != iSample)
continue;
1521 if (WeightStyle == 1) {
1524 std::vector<double> VecX = {}, VecY = {};
1526 size_t nsubevents = 0;
1528 if (IsSubEventVarX && !IsSubEventVarY) {
1531 nsubevents = VecX.size();
1533 else if (!IsSubEventVarX && IsSubEventVarY) {
1536 nsubevents = VecY.size();
1541 if (VecX.size() != VecY.size()) {
1542 MACH3LOG_ERROR(
"Cannot plot {} of size {} against {} of size {}", ProjectionVar_StrX, VecX.size(), ProjectionVar_StrY, VecY.size());
1545 nsubevents = VecX.size();
1548 for (
unsigned int iSubEvent = 0; iSubEvent < nsubevents; iSubEvent++) {
1550 if (IsSubEventVarX) VarX = VecX[iSubEvent];
1551 if (IsSubEventVarY) VarY = VecY[iSubEvent];
1552 _h2DVar->Fill(VarX,VarY,Weight);
1565 MACH3LOG_ERROR(
"Did not recognise Kinematic Parameter type: {}", KinematicParameterStr);
1579 MACH3LOG_ERROR(
"Did not recognise Kinematic Parameter type: {}", KinematicParameter);
1592 MACH3LOG_ERROR(
"Did not recognise Kinematic Vector: {}", KinematicVectorStr);
1606 MACH3LOG_ERROR(
"Did not recognise Kinematic Vector: {}", KinematicVector);
1617 if(
Binning->IsUniform(Sample)) {
1618 for(
int iDim = 0; iDim <
GetNDim(Sample); iDim++) {
1620 return Binning->GetBinEdges(Sample, iDim);
1625 auto MakeBins = [](
int nBins) {
1626 std::vector<double> bins(nBins + 1);
1627 for (
int i = 0; i <= nBins; ++i)
1628 bins[i] =
static_cast<double>(i) - 0.5;
1632 if (KinematicParameter ==
"OscillationChannel") {
1634 }
else if (KinematicParameter ==
"Mode") {
1635 return MakeBins(
Modes->GetNModes());
1638 std::vector<double> BinningVect;
1641 bool found_range_specifier =
false;
1649 auto IsIncreasing = [](
const std::vector<double>& vec) {
1650 for (
size_t i = 1; i < vec.size(); ++i) {
1651 if (vec[i] <= vec[i-1]) {
1658 if (!IsIncreasing(BinningVect)) {
1659 MACH3LOG_ERROR(
"Binning for {} is not increasing [{}]", KinematicParameter, fmt::join(BinningVect,
", "));
1660 if(found_range_specifier){
1661 MACH3LOG_ERROR(
"A bin range specifier was found. Please carefully check the number of square brackets used.");
1676 MACH3LOG_ERROR(
"Attempted to plot kinematic variable {}, but it appears in both KinematicVectors and KinematicParameters", VarStr);
1689 if (kChannelToFill != -1) {
1701 if (kModeToFill != -1) {
1702 if (!(kModeToFill >= 0) && (kModeToFill < Modes->GetNModes())) {
1703 MACH3LOG_ERROR(
"Required mode is not available. kModeToFill should be between 0 and {}",
Modes->GetNModes());
1713 std::vector< KinematicCut > SelectionVec;
1720 SelectionVec.push_back(SelecMode);
1728 SelectionVec.push_back(SelecChannel);
1731 return SelectionVec;
1736 const int kModeToFill,
const int kChannelToFill,
const int WeightStyle) {
1739 return Get1DVarHist(iSample, ProjectionVar_Str, SelectionVec, WeightStyle);
1744 const std::string& ProjectionVar_StrY,
const int kModeToFill,
1745 const int kChannelToFill,
const int WeightStyle) {
1748 return Get2DVarHist(iSample, ProjectionVar_StrX, ProjectionVar_StrY, SelectionVec, WeightStyle);
1754 constexpr
int space = 14;
1756 bool printToFile=
false;
1757 if (OutputFileName.CompareTo(
"/dev/null")) {printToFile =
true;}
1759 bool printToCSV=
false;
1760 if(OutputCSVFileName.CompareTo(
"/dev/null")) printToCSV=
true;
1762 std::ofstream outfile;
1764 outfile.open(OutputFileName.Data(), std::ios_base::app);
1765 outfile.precision(7);
1768 std::ofstream outcsv;
1770 outcsv.open(OutputCSVFileName, std::ios_base::app);
1771 outcsv.precision(7);
1774 double PDFIntegral = 0.;
1776 std::vector< std::vector< std::unique_ptr<TH1> > > IntegralList;
1777 IntegralList.resize(
Modes->GetNModes());
1779 std::vector<double> ChannelIntegral;
1781 for (
unsigned int i=0;i<ChannelIntegral.size();i++) {ChannelIntegral[i] = 0.;}
1783 for (
int i=0;i<
Modes->GetNModes();i++) {
1792 MACH3LOG_INFO(
"-------------------------------------------------");
1795 outfile <<
"\\begin{table}[ht]" << std::endl;
1796 outfile <<
"\\begin{center}" << std::endl;
1797 outfile <<
"\\caption{Integral breakdown for sample: " <<
GetSampleTitle(iSample) <<
"}" << std::endl;
1798 outfile <<
"\\label{" <<
GetSampleTitle(iSample) <<
"-EventRate}" << std::endl;
1803 outfile <<
"\\begin{tabular}{|l" << nColumns.Data() <<
"}" << std::endl;
1804 outfile <<
"\\hline" << std::endl;
1809 outcsv<<
"Integral Breakdown for sample :"<<
GetSampleTitle(iSample)<<
"\n";
1815 if (printToFile) {outfile << std::setw(space) <<
"Mode:";}
1816 if(printToCSV) {outcsv<<
"Mode,";}
1818 std::string table_headings = fmt::format(
"| {:<8} |",
"Mode");
1819 std::string table_footline =
"------------";
1821 table_headings += fmt::format(
" {:<17} |",
GetFlavourName(iSample, i));
1822 table_footline +=
"--------------------";
1823 if (printToFile) {outfile <<
"&" << std::setw(space) <<
SampleDetails[iSample].OscChannels[i].flavourName_Latex <<
" ";}
1826 if (printToFile) {outfile <<
"&" << std::setw(space) <<
"Total:" <<
"\\\\ \\hline" << std::endl;}
1827 if (printToCSV) {outcsv <<
"Total\n";}
1828 table_headings += fmt::format(
" {:<10} |",
"Total");
1829 table_footline +=
"-------------";
1834 for (
unsigned int i=0;i<IntegralList.size();i++) {
1835 double ModeIntegral = 0;
1836 if (printToFile) {outfile << std::setw(space) <<
Modes->GetMaCh3ModeName(i);}
1837 if(printToCSV) {outcsv <<
Modes->GetMaCh3ModeName(i) <<
",";}
1839 table_headings = fmt::format(
"| {:<8} |",
Modes->GetMaCh3ModeName(i));
1841 for (
unsigned int j=0;j<IntegralList[i].size();j++) {
1842 double Integral = IntegralList[i][j]->Integral();
1844 if (Integral < 1e-100) {Integral=0;}
1846 ModeIntegral += Integral;
1847 ChannelIntegral[j] += Integral;
1848 PDFIntegral += Integral;
1850 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",Integral) <<
" ";}
1851 if (printToCSV) {outcsv << Form(
"%4.5f", Integral) <<
",";}
1853 table_headings += fmt::format(
" {:<17.4f} |", Integral);
1855 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",ModeIntegral) <<
" \\\\ \\hline" << std::endl;}
1856 if (printToCSV) {outcsv << Form(
"%4.5f", ModeIntegral) <<
"\n";}
1858 table_headings += fmt::format(
" {:<10.4f} |", ModeIntegral);
1863 if (printToFile) {outfile << std::setw(space) <<
"Total:";}
1864 if (printToCSV) {outcsv <<
"Total,";}
1867 table_headings = fmt::format(
"| {:<8} |",
"Total");
1868 for (
unsigned int i=0;i<ChannelIntegral.size();i++) {
1869 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",ChannelIntegral[i]) <<
" ";}
1870 if (printToCSV) {outcsv << Form(
"%4.5f", ChannelIntegral[i]) <<
",";}
1871 table_headings += fmt::format(
" {:<17.4f} |", ChannelIntegral[i]);
1873 if (printToFile) {outfile <<
"&" << std::setw(space) << Form(
"%4.5f",PDFIntegral) <<
" \\\\ \\hline" << std::endl;}
1874 if (printToCSV) {outcsv << Form(
"%4.5f", PDFIntegral) <<
"\n\n\n\n";}
1876 table_headings += fmt::format(
" {:<10.4f} |", PDFIntegral);
1881 outfile <<
"\\end{tabular}" << std::endl;
1882 outfile <<
"\\end{center}" << std::endl;
1883 outfile <<
"\\end{table}" << std::endl;
1889 outfile << std::endl;
1899 return Modes->GetNModes();
1905 MACH3LOG_ERROR(
"You've passed me a SamplePlotType with value {} which was not implemented.",
static_cast<int>(TypeEnum));
1912 const SamplePlotType Selection1,
const int Selection2,
const int WeightStyle) {
1914 std::vector<std::unique_ptr<TH1>> hHistList;
1915 std::string legendEntry;
1921 for (
int i=0;i<iMax;i++) {
1924 THStackLeg->AddEntry(hHistList[i].get(), (
Modes->GetMaCh3ModeName(i)+Form(
" : (%4.2f)",hHistList[i]->Integral())).c_str(),
"f");
1926 hHistList[i]->SetFillColor(
static_cast<Color_t
>(
Modes->GetMaCh3ModePlotColor(i)));
1927 hHistList[i]->SetLineColor(
static_cast<Color_t
>(
Modes->GetMaCh3ModePlotColor(i)));
1931 THStackLeg->AddEntry(hHistList[i].get(),(
GetFlavourName(iSample, i)+Form(
" | %4.2f",hHistList[i]->Integral())).c_str(),
"f");
1940 const std::string& KinematicProjectionY,
const SamplePlotType Selection1,
1941 const int Selection2,
const int WeightStyle) {
1943 std::vector<std::unique_ptr<TH2>> hHistList;
1946 for (
int i=0;i<iMax;i++) {
1960 const SamplePlotType Selection1,
int Selection2,
int WeightStyle) {
1963 auto StackHist = std::make_unique<THStack>((
GetSampleTitle(iSample)+
"_"+KinematicProjection+
"_Stack").c_str(),
"");
1965 for (
unsigned int i=0;i<HistList.size();i++) {
1966 StackHist->Add(HistList[i].release());
1976 return &(OscillationChannels[Channel].ChannelIndex);
1982 const auto TotalBins =
Binning->GetNBins();
1984 for(
int iBin = 0; iBin < TotalBins; iBin++) {
1993 MACH3LOG_WARN(
"Found in total {} ({:.2f}%) empty bins for SampleHandler: {}",
1994 iCounter, 100.0 *
static_cast<double>(iCounter) / TotalBins,
GetName());
2009 const std::string sep_full(81,
'-');
2011 MACH3LOG_INFO(
"{:<40}{:<15}{:<15}{:<10}|",
"Sample",
"Data",
"MC",
"-LLH");
2013 const std::string sep_data(56,
'-');
2018 double sumData = 0.0;
2020 double likelihood = 0.0;
2022 for (
int iSample = 0; iSample <
GetNSamples(); ++iSample) {
2025 double dataIntegral = std::accumulate(DataArray.begin(), DataArray.end(), 0.0);
2026 sumData += dataIntegral;
2028 std::vector<double> MCArray =
GetMCArray(iSample);
2029 double mcIntegral = std::accumulate(MCArray.begin(), MCArray.end(), 0.0);
2030 sumMC += mcIntegral;
2033 MACH3LOG_INFO(
"{:<40}{:<15.2f}{:<15.2f}{:<10.2f}|", name, dataIntegral, mcIntegral, likelihood);
2040 MACH3LOG_INFO(
"{:<40}{:<15.2f}{:<15.2f}{:<10.2f}|",
"Total", sumData, sumMC, likelihood);
2041 const std::string sep_full(81,
'-');
2045 const std::string sep_data(56,
'-');
2054 if(Dimension >
GetNDim(iSample)) {
2064 const int Start =
Binning->GetSampleStartBin(Sample);
2065 const int End =
Binning->GetSampleEndBin(Sample);
2067 return std::vector<double>(array.begin() + Start, array.begin() + End);
#define _noexcept_
KS: noexcept can help with performance but is terrible for debugging, this is meant to help easy way ...
#define _restrict_
KS: Using restrict limits the effects of pointer aliasing, aiding optimizations. While reading I foun...
std::vector< double > BuildBinEdgesFromNode(YAML::Node const &bin_edges_node, bool &found_range_specifier)
Builds a single dimension's bin edges from YAML::Node.
Defines the custom exception class used throughout MaCh3.
MaCh3 Logging utilities built on top of SPDLOG.
#define MACH3LOG_CRITICAL
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.
NuPDG
Enum to track the incoming neutrino species.
TestStatistic
Make an enum of the test statistic that we're using.
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Type GetFromManager(const YAML::Node &node, const Type defval, const std::string &File="", const int Line=1)
Get content of config file if node is not found take default value specified.
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)
Bin-by-bin class calculating response for spline parameters.
std::vector< SplineIndex > GetEventSplines(const std::string &SampleTitle, int iOscChan, int EventMode, double Var1Val, double Var2Val, double Var3Val)
Return the splines which affect a given event.
Custom exception class used throughout MaCh3.
const M3::float_t * RetPointer(const int iParam) const
DB Pointer return to param position.
Class responsible for handling of systematic error parameters with different types defined in the con...
const std::vector< NormParameter > GetNormParsFromSampleName(const std::string &SampleName) const
DB Get norm/func parameters depending on given SampleName.
std::vector< const M3::float_t * > GetOscParsFromSampleName(const std::string &SampleName) const
Get pointers to Osc params from Sample name.
const std::vector< SplineParameter > GetSplineParsFromSampleName(const std::string &SampleName) const
KS: Grab the Spline parameters for the relevant SampleName.
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
void InitialiseSplineObject()
Setup spline handler (both binned or unbinned)
virtual ~SampleHandlerBase()
destructor
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.
int GetNDim(const int Sample) const final
DB Get what dimensionality binning for given sample has.
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...
void SetBinning()
set the binning for 2D sample used for the likelihood calculation
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.
std::unique_ptr< Manager > SampleManager
The manager object used to read the sample yaml file.
std::string GetKinVarName(const int iSample, const int Dimension) const final
Return Kinematic Variable name for specified sample and dimension for example "Reconstructed_Neutrino...
bool PassesSelection(const ParT &Par, std::size_t iEvent)
bool IsSubEventVarString(const std::string &VarStr) const
JM: Check if a kinematic parameter string corresponds to a subevent-level variable.
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.
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.
const TH1 * GetW2Hist(const int Sample) final
Get W2 histogram.
void SetupKinematicMap()
Ensure Kinematic Map is setup and make sure it is initialised correctly.
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 Init()=0
Initialise any variables that your experiment specific SampleHandler needs.
const TH1 * GetDataHist(const int Sample) final
Get Data histogram.
SampleHandlerBase(std::string ConfigFileName, ParameterHandlerGeneric *_ParHandler, const std::shared_ptr< OscillationHandler > &OscillatorObj_=nullptr)
Constructor.
std::string GetFlavourName(const int iSample, const int iChannel) const final
Get the flavour name for a given sample and oscillation channel.
std::unordered_map< std::string, NuPDG > FileToFinalPDGMap
Mapping from input file names to final neutrino PDG codes.
std::vector< double > ReturnKinematicParameterBinning(const int Sample, const std::string &KinematicParameter) const final
Return the binning used to draw a kinematic parameter.
void InitialiseNuOscillatorObjects()
including Dan's magic NuOscillator
const std::unordered_map< std::string, int > * KinematicParameters
Mapping between string and kinematic enum.
std::unordered_map< std::string, double > _modeNomWeightMap
void FillArray_MP()
DB Nice new multi-threaded function which calculates the event weights and fills the relevant bins of...
void CheckEmptyBins() const
Loop over bins and checks if there are any which have 0 entries.
std::string ReturnStringFromKinematicVector(const int KinematicVariable) const
JM: Convert a kinematic vector integer ID to its corresponding name as a string.
bool IsEventSelected(const int iSample, const int iEvent) _noexcept_
DB Function which determines if an event is selected based on KinematicCut.
void SaveAdditionalInfo(TDirectory *Dir) final
Store additional info in a chain.
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)
virtual void PrepFunctionalParameters()
Update the functional parameter values to the latest proposed values. Needs to be called before every...
std::unordered_map< std::string, NuPDG > FileToInitPDGMap
Mapping from input file names to initial neutrino PDG codes.
void SetSplinePointers()
Set pointers for each event to appropriate weights, for unbinned based on event number while for binn...
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
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...
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 CalcWeightFunc([[maybe_unused]] const int iEvent)
Calculate weights for function parameters.
unsigned int GetNEvents() const
Return total number of events.
virtual void ApplyShifts(const int iEvent)
ETA - generic function applying shifts.
void Initialise()
Function which does a lot of the lifting regarding the workflow in creating different MC objects.
virtual void SetupSplines()=0
initialise your splineXX object and then use InitialiseSplineObject to conveniently setup everything ...
M3::detail::Functional functional
Helper object for storing/updating information related to functional shift parameters.
double GetSampleLikelihood(const int isample) const override
Get likelihood (-logL) for a single sample.
virtual void RegisterFunctionalParameters()
HH - a experiment-specific function where the maps to actual functions are set up.
void SetupReweightArrays()
Initialise data, MC and W2 histograms.
void ResetHistograms()
Helper function to reset histograms.
virtual void AddAdditionalWeightPointers()=0
DB Function to determine which weights apply to which types of samples.
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...
void FillHist(const int Sample, TH1 *Hist, std::vector< double > &Array)
Fill a histogram with the event-level information used in the fit.
virtual int SetupExperimentMC()=0
Experiment specific setup, returns the number of events which were loaded.
void FindNominalBinAndEdges()
Functions which find the nominal bin and bin edges.
std::string GetSampleName(const int Sample) const
Sample name tag used only for getting relevant uncertainties.
const M3::float_t * GetNuOscillatorPointers(const int iEvent) const
Get pointer to NuOscillator weight for a given event.
std::string GetName() const final
Get name for Sample Handler.
virtual void FinaliseShifts([[maybe_unused]] const int iEvent)
LP - Optionally calculate derived observables after all shifts have been applied.
std::vector< SplineIndex > GetSplineBins(int Event, BinnedSplineHandler *BinnedSpline, bool &ThrowCrititcal) const
Retrieve the spline bin indices associated with a given event.
virtual void ResetShifts([[maybe_unused]] const int iEvent)
HH - reset the shifted values to the original values.
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 ...
const double * GetPointerToOscChannel(const int iEvent) const
Get pointer to oscillation channel associated with given event. Osc channel is const.
const std::unordered_map< std::string, int > * KinematicVectors
int GetSampleIndex(const std::string &SampleTitle) const
Get index of sample based on name.
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...
TLegend * THStackLeg
DB: Legend associated with stacked histograms produced by this class.
void AddData(const int Sample, TH1 *Data)
DB: Add data for a given sample from a ROOT histogram.
void SetupNuOscillatorPointers()
Initialise pointer to oscillation weight to NuOscillator object.
double ReturnKinematicParameter(const std::string &KinematicParameter, int iEvent) const
Return the value of an associated kinematic parameter for an event.
std::unique_ptr< THStack > ReturnStackedHistBySelection1D(const int iSample, const std::string &KinematicProjection, const SamplePlotType Selection1, const int Selection2=-1, const int WeightStyle=0)
double GetLikelihood() const override
Return likelihood (-LogL) for all samples.
unsigned int nEvents
Number of MC events are there.
std::vector< EventInfo > MCEvents
Stores information about every MC event.
M3::float_t CalcWeightTotal(const EventInfo *_restrict_ MCEvent) const _noexcept_
Calculate the total weight weight for a given event.
auto GetDataArray() const
Return array storing data entries for every bin.
std::unique_ptr< SplineBase > SplineHandler
Contains all your splines (binned or unbinned) and handles the setup and the returning of weights fro...
std::vector< SampleInfo > SampleDetails
Stores info about currently initialised sample.
int GetNOscChannels(const int iSample) const final
Get number of oscillation channels for a single sample.
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::string GetSampleTitle(const int Sample) const final
Get fancy title for specified samples.
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.
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.
void LoadSingleSample(const int iSample, const YAML::Node &Settings)
Initialise single sample from config file.
std::vector< double > SampleHandler_data
DB Array to be filled in AddData.
std::vector< double > SampleHandler_array_w2
KS Array used for MC stat.
int GetRangeForPlotType(const SamplePlotType TypeEnum, const int iSample) const
KS: Return range for plot type, for example number of modes, osc channels etc.
void PrintRates(const bool DataOnly=false) final
Helper function to print rates for the samples with LLH.
void Reweight() override
main routine modifying MC prediction based on proposed parameter values
std::string ReturnStringFromKinematicParameter(const int KinematicVariable) const
ETA function to generically convert a kinematic type from param handler to a string.
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.
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)
void SetupOscParameters()
Setup the osc parameters.
int ReturnKinematicParameterFromString(const std::string &KinematicStr) const
ETA function to generically convert a string from param handler to a kinematic type.
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.
std::vector< double > GetArrayForSample(const int Sample, std::vector< double > const &array) const
Return a sub-array for a given sample.
const double * GetPointerToKinematicParameter(const std::string &KinematicParameter, int iEvent) const
std::vector< double > SampleHandler_array
DB Array to be filled after reweighting.
int ReturnKinematicVectorFromString(const std::string &KinematicStr) const
JM: Convert a kinematic vector name to its corresponding integer ID.
auto GetMCArray() const
Return array storing MC entries for every bin.
const TH1 * GetMCHist(const int Sample) final
Get MC histogram.
void FillArray()
Function which does the core reweighting, fills the SampleHandlerBase::SampleHandler_array vector wit...
bool FirstTimeW2
KS:Super hacky to update W2 or not.
Class responsible for handling implementation of samples used in analysis, reweighting and returning ...
TestStatistic fTestStatistic
Test statistic tells what kind of likelihood sample is using.
bool MatchCondition(const std::vector< T > &allowedValues, const T &value)
check if event is affected by following conditions, for example pdg, or modes etc
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....
M3::int_t nSamples
Contains how many samples we've got.
virtual M3::int_t GetNSamples()
returns total number of samples
std::unique_ptr< MaCh3Modes > Modes
Holds information about used Generator and MaCh3 modes.
Even-by-event class calculating response for spline parameters. It is possible to use GPU acceleratio...
int PDGToNuOscillatorFlavour(const int NuPdg)
Convert from PDG flavour to NuOscillator type beware that in the case of anti-neutrinos the NuOscilla...
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.
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.
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 UnderOverFlowBin
Mark bin which is overflow or underflow in MaCh3 binning.
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Stores info about each MC event used during reweighting routine.
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.
std::vector< Shift > shifts
std::vector< std::vector< int > > event_shifts
KS: Store info about used osc channels.
int InitPDG
PDG of initial flavour.
double ChannelIndex
In case experiment specific would like to have pointer to channel after using GetOscChannel,...
int FinalPDG
PDG of oscillated/final flavour.
std::string flavourName
Name of osc channel.
std::string flavourName_Latex
Fancy channel name (e.g., LaTeX formatted)
KS: Store info about MC sample.
std::string SampleName
tag for sample used to easily set by which uncertainties should be affected
std::vector< OscChannelInfo > OscChannels
Stores info about oscillation channel for a single sample.
std::string SampleTitle
the name of this sample e.g."muon-like" used for printing
std::vector< std::string > spline_files
names of spline files associated associated with this object
std::vector< std::vector< std::string > > mc_files
names of mc files associated associated with this object