MaCh3  2.4.2
Reference Guide
BinningHandler.cpp
Go to the documentation of this file.
2 
3 // ************************************************
5 // ************************************************
6 }
7 
8 // ************************************************
9 // Function to setup the binning of your sample histograms and the underlying
10 // arrays that get handled in fillArray() and fillArray_MP().
11 // The Binning.XBinEdges are filled in the daughter class from the sample config file.
12 // This "passing" can be removed.
13 void BinningHandler::SetupSampleBinning(const YAML::Node& Settings, SampleInfo& SingleSample) {
14 // ************************************************
15  MACH3LOG_INFO("Setting up Sample Binning");
16  //Binning
17  SingleSample.VarStr = Get<std::vector<std::string>>(Settings["VarStr"], __FILE__ , __LINE__);
18  SingleSample.nDimensions = static_cast<int>(SingleSample.VarStr.size());
19 
20  SampleBinningInfo SingleBinning;
21  bool Uniform = Get<bool>(Settings["Uniform"], __FILE__ , __LINE__);
22  if(Uniform == false) {
23  auto Bins = Get<std::vector<std::vector<std::vector<double>>>>(Settings["Bins"], __FILE__, __LINE__);
24  SingleBinning.InitNonUniform(Bins);
25  } else {
26  auto Bin_Edges = Get<std::vector<std::vector<double>>>(Settings["VarBins"], __FILE__ , __LINE__);
27  SingleBinning.InitUniform(Bin_Edges);
28  }
29  if(SingleSample.VarStr.size() != SingleBinning.BinEdges.size()) {
30  MACH3LOG_ERROR("Number of variables ({}) does not match number of bin edge sets ({}) in sample config '{}'",
31  SingleSample.VarStr.size(), SingleBinning.BinEdges.size(),SingleSample.SampleTitle);
32  throw MaCh3Exception(__FILE__, __LINE__);
33  }
34 
35  SampleBinning.emplace_back(SingleBinning);
36 
37  // now setup global numbering
39 }
40 
41 // ************************************************
42 int BinningHandler::FindGlobalBin(const int NomSample,
43  const std::vector<const double*>& KinVar,
44  const std::vector<int>& NomBin) const {
45 // ************************************************
46  //DB Find the relevant bin in the PDF for each event
47  const int Dim = static_cast<int>(KinVar.size());
48  const SampleBinningInfo& _restrict_ Binning = SampleBinning[NomSample];
49  int GlobalBin = 0;
50 
51  for(int i = 0; i < Dim; ++i) {
52  const double Var = *KinVar[i];
53  const int Bin = Binning.FindBin(i, Var, NomBin[i]);
54  // KS: If we are outside of range in only one dimension this mean out of bounds, we can simply quickly finish
55  if(Bin < 0) return M3::UnderOverFlowBin;
56  // KS: inline GetBin computation to avoid any memory allocation, which in reweight loop is very costly
57  GlobalBin += Bin * Binning.Strides[i];
58  }
59 
60  if(Binning.Uniform) {
61  GlobalBin += static_cast<int>(Binning.GlobalOffset);
62  return GlobalBin;
63  } else {
64  const auto& _restrict_ BinMapping = Binning.BinGridMapping[GlobalBin];
65  const size_t nNonUniBins = BinMapping.size();
66  for(size_t iBin = 0; iBin < nNonUniBins; iBin++) {
67  const int BinNumber = BinMapping[iBin];
68  const auto& _restrict_ NonUniBin = Binning.Bins[BinNumber];
69  if(NonUniBin.IsEventInside(KinVar)){
70  return BinNumber + Binning.GlobalOffset;
71  }
72  }
73  MACH3LOG_DEBUG("Didn't find any bin so returning UnderOverFlowBin");
74  return M3::UnderOverFlowBin;
75  }
76 }
77 
78 // ************************************************
79 int BinningHandler::FindNominalBin(const int iSample,
80  const int iDim,
81  const double Var) const {
82 // ************************************************
83  const SampleBinningInfo& info = SampleBinning[iSample];
84 
85  const auto& edges = info.BinEdges[iDim];
86 
87  // Outside binning range
88  if (Var < edges.front() || Var >= edges.back()) {
89  return M3::UnderOverFlowBin;
90  }
91  return static_cast<int>(std::distance(edges.begin(), std::upper_bound(edges.begin(), edges.end(), Var)) - 1);
92 }
93 
94 // ************************************************
95 int BinningHandler::GetBinSafe(const int Sample, const std::vector<int>& Bins) const {
96 // ************************************************
97  const int GlobalBin = SampleBinning[Sample].GetBinSafe(Bins);
98  return GlobalBin;
99 }
100 
101 // ************************************************
102 int BinningHandler::GetGlobalBinSafe(const int Sample, const std::vector<int>& Bins) const {
103 // ************************************************
104  const int GlobalBin = SampleBinning[Sample].GetBinSafe(Bins) + static_cast<int>(SampleBinning[Sample].GlobalOffset);
105  return GlobalBin;
106 }
107 
108 // ************************************************
109 int BinningHandler::GetSampleStartBin(const int Sample) const {
110 // ************************************************
111  return static_cast<int>(SampleBinning[Sample].GlobalOffset);
112 }
113 
114 // ************************************************
115 int BinningHandler::GetSampleEndBin(const int Sample) const {
116 // ************************************************
117  if (Sample == static_cast<int>(SampleBinning.size()) - 1) {
118  return GetNBins();
119  } else {
120  return static_cast<int>(SampleBinning[Sample+1].GlobalOffset);
121  }
122 }
123 
124 // ************************************************
127 // ************************************************
128  if (SampleBinning.empty()) {
129  MACH3LOG_ERROR("No binning samples provided.");
130  throw MaCh3Exception(__FILE__, __LINE__);
131  }
132 
133  int GlobalOffsetCounter = 0;
134  for(size_t iSample = 0; iSample < SampleBinning.size(); iSample++){
135  SampleBinning[iSample].GlobalOffset = GlobalOffsetCounter;
136  GlobalOffsetCounter += SampleBinning[iSample].nBins;
137  }
138  // lastly modify total number of bins
139  TotalNumberOfBins = GlobalOffsetCounter;
140 }
141 
142 // ************************************************
143 // Get fancy name for a given bin, to help match it with global properties
144 std::string BinningHandler::GetBinName(const int iSample, const std::vector<int>& Bins) const {
145 // ************************************************
146  const auto& Binning = SampleBinning[iSample];
147  if(!Binning.Uniform) {
148  MACH3LOG_ERROR("When using Non-Uniform binning for sample {} please use One bin instead of Axis bins", iSample);
149  throw MaCh3Exception(__FILE__, __LINE__);
150  }
151  return GetBinName(iSample, GetBinSafe(iSample, Bins));
152 }
153 
154 // ************************************************
155 // Get fancy name for a given bin, to help match it with global properties
156 std::string BinningHandler::GetBinName(const int iSample, const int SampleBin) const {
157 // ************************************************
158  const auto& Binning = SampleBinning[iSample];
159 
160  // Safety checks
161  if (SampleBin < 0 || SampleBin >= static_cast<int>(Binning.nBins)) {
162  MACH3LOG_ERROR("Requested bin {} is out of range for sample {}", SampleBin, iSample);
163  throw MaCh3Exception(__FILE__, __LINE__);
164  }
165  std::string BinName;
166 
167  if(Binning.Uniform) {
168  int Dim = static_cast<int>(Binning.Strides.size());
169  std::vector<int> Bins(Dim, 0);
170  int Remaining = SampleBin;
171 
172  // Convert the flat/global bin index into per-dimension indices
173  // Dim0 is the fastest-changing axis, Dim1 the next, etc.
174  //
175  // For example (2D):
176  // x = bin % Nx
177  // y = bin / Nx
178  //
179  // For 3D:
180  // x = bin % Nx
181  // y = (bin / Nx) % Ny
182  // z = bin / (Nx * Ny)
183  for (int i = 0; i < Dim; ++i) {
184  const int nBinsDim = static_cast<int>(Binning.BinEdges[i].size()) - 1;
185  Bins[i] = Remaining % nBinsDim;
186  Remaining /= nBinsDim;
187  }
188 
189  for (int i = 0; i < Dim; ++i) {
190  if (i > 0) BinName += ", ";
191  const double min = Binning.BinEdges[i].at(Bins[i]);
192  const double max = Binning.BinEdges[i].at(Bins[i] + 1);
193  BinName += fmt::format("Dim{} ({:g}, {:g})", i, min, max);
194  }
195  } else{
196  const BinInfo& bin = Binning.Bins[SampleBin];
197  const int Dim = static_cast<int>(bin.Extent.size());
198 
199  for (int i = 0; i < Dim; ++i) {
200  if (i > 0) BinName += ", ";
201  const double min = bin.Extent[i][0];
202  const double max = bin.Extent[i][1];
203  BinName += fmt::format("Dim{} ({:g}, {:g})", i, min, max);
204  }
205  }
206  return BinName;
207 }
208 
209 // ************************************************
210 std::string BinningHandler::GetBinName(const int GlobalBin) const {
211 // ************************************************
212  int SampleBin = GetSampleFromGlobalBin(SampleBinning, GlobalBin);
213  int LocalBin = GetLocalBinFromGlobalBin(SampleBinning, GlobalBin);
214  return GetBinName(SampleBin, LocalBin);
215 }
216 
217 // ************************************************
218 int BinningHandler::GetNAxisBins(const int iSample, const int iDim) const {
219 // ************************************************
220  const auto& Binning = SampleBinning[iSample];
221  if(!Binning.Uniform) {
222  MACH3LOG_ERROR("When using Non-Uniform binning for sample {} please use global bin instead of {}", iSample, __func__);
223  throw MaCh3Exception(__FILE__, __LINE__);
224  } else{
225  return static_cast<int>(Binning.AxisNBins.at(iDim));
226  }
227 }
228 
229 // ************************************************
230 bool BinningHandler::IsUniform(const int iSample) const {
231 // ************************************************
232  const auto& Binning = SampleBinning[iSample];
233  return Binning.Uniform;
234 }
235 
236 // ************************************************
237 const std::vector<BinInfo> BinningHandler::GetNonUniformBins(const int iSample) const {
238 // ************************************************
239  const auto& Binning = SampleBinning[iSample];
240  if(!Binning.Uniform) {
241  return Binning.Bins;
242  } else{
243  MACH3LOG_ERROR("{} for sample {} will not work becasue binnin is unfiorm", __func__, iSample);
244  throw MaCh3Exception(__FILE__, __LINE__);
245  }
246 }
247 
#define _restrict_
KS: Using restrict limits the effects of pointer aliasing, aiding optimizations. While reading I foun...
Definition: Core.h:108
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
int GetSampleFromGlobalBin(const std::vector< SampleBinningInfo > &BinningInfo, const int GlobalBin)
Get the sample index corresponding to a global bin number.
int GetLocalBinFromGlobalBin(const std::vector< SampleBinningInfo > &BinningInfo, const int GlobalBin)
Get the local (sample) bin index from a global bin number.
const std::vector< BinInfo > GetNonUniformBins(const int iSample) const
Return NonUnifomr bins to for example check extent etc.
void SetGlobalBinNumbers()
Sets the GlobalOffset for each SampleBinningInfo to enable linearization of multiple 2D binning sampl...
int GetSampleStartBin(const int iSample) const
Get bin number corresponding to where given sample starts.
BinningHandler()
Constructor.
std::vector< SampleBinningInfo > SampleBinning
Binning info for individual sample.
int FindGlobalBin(const int iSample, const std::vector< const double * > &KinVar, const std::vector< int > &NomBin) const
Find Global bin including.
void SetupSampleBinning(const YAML::Node &Settings, SampleInfo &SingleSample)
Function to setup the binning of your sample histograms and the underlying arrays that get handled in...
int GetBinSafe(const int iSample, const std::vector< int > &Bins) const
Get gloabl bin based on sample, and dimension of each sample without any safety checks.
int GetNBins() const
Get total number of bins over all samples/kinematic bins etc.
std::string GetBinName(const int GlobalBin) const
Get fancy name for a given bin, to help match it with global properties.
int FindNominalBin(const int iSample, const int iDim, const double Var) const
Find the nominal bin for a given variable in a given sample and dimension.
int GetGlobalBinSafe(const int iSample, const std::vector< int > &Bins) const
Get gloabl bin based on sample, and dimension of each sample with additional checks.
bool IsUniform(const int iSample) const
Tells whether given sample is using unform binning.
int GetSampleEndBin(const int iSample) const
Get bin number corresponding to where given sample ends.
int TotalNumberOfBins
Total number of bins.
int GetNAxisBins(const int iSample, const int iDim) const
Get Number of N-axis bins for a given sample.
Custom exception class used throughout MaCh3.
constexpr static const int UnderOverFlowBin
Mark bin which is overflow or underflow in MaCh3 binning.
Definition: Core.h:91
KS: This hold bin extents in N-Dimensions allowing to check if Bin falls into.
std::vector< std::array< double, 2 > > Extent
KS: Struct storing all information required for sample binning.
void InitUniform(const std::vector< std::vector< double >> &InputEdges)
Initialise Uniform Binning.
void InitNonUniform(const std::vector< std::vector< std::vector< double >>> &InputBins)
Initialise Non-Uniform Binning.
std::vector< std::vector< double > > BinEdges
Vector to hold N-axis bin-edges.
KS: Store info about MC sample.
int nDimensions
Keep track of the dimensions of the sample binning.
std::vector< std::string > VarStr
the strings associated with the variables used for the binning e.g. "RecoNeutrinoEnergy"
std::string SampleTitle
the name of this sample e.g."muon-like"