MaCh3  2.5.0
Reference Guide
BinnedSplineHandler.cpp
Go to the documentation of this file.
1 #include "BinnedSplineHandler.h"
2 #include <memory>
3 
4 #pragma GCC diagnostic ignored "-Wuseless-cast"
5 #pragma GCC diagnostic ignored "-Wfloat-conversion"
6 
8 #include "TROOT.h"
9 #include "TKey.h"
10 #include "TH3F.h"
12 
13 //****************************************
15 //****************************************
16  if (!ParHandler_) {
17  MACH3LOG_ERROR("Trying to create BinnedSplineHandler with uninitialized covariance object");
18  throw MaCh3Exception(__FILE__, __LINE__);
19  }
20  ParHandler = ParHandler_;
21 
22  if (!Modes_) {
23  MACH3LOG_ERROR("Trying to create BinnedSplineHandler with uninitialized MaCh3Modes object");
24  throw MaCh3Exception(__FILE__, __LINE__);
25  }
26  Modes = Modes_;
27 
28  // Keep these in class scope, important for using 1 monolith/sample!
29  MonolithIndex = 0; //Keeps track of the monolith index we're on when filling arrays (declared here so we can have multiple FillSampleArray calls)
30  CoeffIndex = 0; //Keeps track of our indexing the coefficient arrays [x, ybcd]
31  isflatarray = nullptr;
32 }
33 
34 //****************************************
36 //****************************************
37  if(manycoeff_arr != nullptr) delete[] manycoeff_arr;
38  if(xcoeff_arr != nullptr) delete[] xcoeff_arr;
39  if(SplineSegments != nullptr) delete[] SplineSegments;
40  if(ParamValues != nullptr) delete[] ParamValues;
41 }
42 //****************************************
44 //****************************************
45  //Call once everything's been allocated in SampleHandlerFDBase, cleans up junk from memory!
46  //Not a huge saving but it's better than leaving everything up to the compiler
47  MACH3LOG_INFO("Cleaning up spline memory");
63  if(isflatarray) delete [] isflatarray;
64 }
65 
66 //****************************************
67 void BinnedSplineHandler::AddSample(const std::string& SampleName,
68  const std::string& SampleTitle,
69  const std::vector<std::string>& OscChanFileNames,
70  const std::vector<std::string>& SplineVarNames)
71 //Adds samples to the large array
72 //****************************************
73 {
74  SampleNames.push_back(SampleName);
75  SampleTitles.push_back(SampleTitle);
76  Dimensions.push_back(static_cast<int>(SplineVarNames.size()));
77  DimensionLabels.push_back(SplineVarNames);
78 
79  int nSplineParam = ParHandler->GetNumParamsFromSampleName(SampleName, SystType::kSpline);
80  nSplineParams.push_back(nSplineParam);
81 
82  //This holds the global index of the spline i.e. 0 -> _fNumPar
83  std::vector<int> GlobalSystIndex_Sample = ParHandler->GetGlobalSystIndexFromSampleName(SampleName, SystType::kSpline);
84  //Keep track of this for all the samples
85  GlobalSystIndex.push_back(GlobalSystIndex_Sample);
86 
87  std::vector<SplineInterpolation> SplineInterpolation_Sample = ParHandler->GetSplineInterpolationFromSampleName(SampleName);
88  // Keep track of this for all samples
89  SplineInterpolationTypes.push_back(SplineInterpolation_Sample);
90 
91  std::vector<std::string> SplineFileParPrefixNames_Sample = ParHandler->GetSplineParsNamesFromSampleName(SampleName);
92  SplineFileParPrefixNames.push_back(SplineFileParPrefixNames_Sample);
93 
94  MACH3LOG_INFO("Create SplineModeVecs_Sample");
95  std::vector<std::vector<int>> SplineModeVecs_Sample = StripDuplicatedModes(ParHandler->GetSplineModeVecFromSampleName(SampleName));
96  MACH3LOG_INFO("SplineModeVecs_Sample is of size {}", SplineModeVecs_Sample.size());
97  SplineModeVecs.push_back(SplineModeVecs_Sample);
98 
99  MACH3LOG_INFO("SplineModeVecs is of size {}", SplineModeVecs.size());
100 
101  int nOscChan = int(OscChanFileNames.size());
102  nOscChans.push_back(nOscChan);
103 
104  PrintSampleDetails(SampleTitle);
105 
106  std::vector<std::vector<TAxis *>> SampleBinning(nOscChan);
107  for (int iOscChan = 0; iOscChan < nOscChan; iOscChan++)
108  {
109  SampleBinning[iOscChan] = FindSplineBinning(OscChanFileNames[iOscChan], SampleTitle);
110  }
111  MACH3LOG_INFO("#----------------------------------------------------------------------------------------------------------------------------------#");
112  SplineBinning.push_back(SampleBinning);
113 
114  BuildSampleIndexingArray(SampleTitle);
115  PrintArrayDetails(SampleTitle);
116  MACH3LOG_INFO("#----------------------------------------------------------------------------------------------------------------------------------#");
117 
118  FillSampleArray(SampleTitle, OscChanFileNames);
119  MACH3LOG_INFO("#----------------------------------------------------------------------------------------------------------------------------------#");
120 }
121 
122 //****************************************
124 //****************************************
125  // Map: iSample → iSyst → modeSuffix → {totalSplines, zeroCount}
126  std::map<unsigned int, std::map<unsigned int, std::map<std::string, std::pair<unsigned int, unsigned int>>>> systZeroCounts;
127 
128  for (unsigned int iSample = 0; iSample < indexvec.size(); iSample++) {
129  std::string SampleName = SampleNames[iSample];
130 
131  // Get list of systematic names for this sample
132  std::vector<std::string> SplineFileParPrefixNames_Sample =
134 
135  for (unsigned int iOscChan = 0; iOscChan < indexvec[iSample].size(); iOscChan++) {
136  for (unsigned int iSyst = 0; iSyst < indexvec[iSample][iOscChan].size(); iSyst++) {
137  unsigned int zeroCount = 0;
138  unsigned int totalSplines = 0;
139 
140  for (unsigned int iMode = 0; iMode < indexvec[iSample][iOscChan][iSyst].size(); iMode++) {
141  // Get the mode suffix string
142  std::string modeSuffix =
143  Modes->GetSplineSuffixFromMaCh3Mode(SplineModeVecs[iSample][iSyst][iMode]);
144 
145  for (unsigned int iVar1 = 0; iVar1 < indexvec[iSample][iOscChan][iSyst][iMode].size(); iVar1++) {
146  for (unsigned int iVar2 = 0; iVar2 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1].size(); iVar2++) {
147  for (unsigned int iVar3 = 0; iVar3 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2].size(); iVar3++) {
148  totalSplines++;
149  if (indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2][iVar3] == 0) {
150  zeroCount++;
151  if(zeroCount > 1){
152  systZeroCounts[iSample][iSyst][modeSuffix] = {totalSplines, zeroCount};
153  }
155  "Sample '{}' | OscChan {} | Syst '{}' | Mode '{}' | Var1 {} | Var2 {} | Var3 {} => Value: {}",
156  SampleTitles[iSample],
157  iOscChan,
158  SplineFileParPrefixNames_Sample[iSyst],
159  modeSuffix,
160  iVar1,
161  iVar2,
162  iVar3,
163  indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2][iVar3]
164  );
165  }
166  }
167  }
168  }
169  }
170  }
171  }
172  }
173 
174  // KS: Let's print this atrocious mess...
175  for (const auto& samplePair : systZeroCounts) {
176  unsigned int iSample = samplePair.first;
177  std::vector<std::string> SplineFileParPrefixNames_Sample = ParHandler->GetParsNamesFromSampleName(SampleNames[iSample], kSpline);
178  for (const auto& systPair : samplePair.second) {
179  unsigned int iSyst = systPair.first;
180  const auto& systName = SplineFileParPrefixNames_Sample[iSyst];
181  for (const auto& modePair : systPair.second) {
182  const auto& modeSuffix = modePair.first;
183  const auto& counts = modePair.second;
185  "Sample '{}': Systematic '{}' has missing splines in mode '{}'. Expected Splines: {}, Missing Splines: {}",
186  SampleTitles[iSample],
187  systName,
188  modeSuffix,
189  counts.first,
190  counts.second
191  );
192  }
193  }
194  }
195 }
196 
197 //****************************************
199 //****************************************
200  PrepForReweight();
202 
205  MACH3LOG_ERROR("Something's gone wrong when we tried to get the size of your monolith");
206  MACH3LOG_ERROR("MonolithSize is {}", MonolithSize);
207  MACH3LOG_ERROR("MonolithIndex is {}", MonolithIndex);
208  throw MaCh3Exception(__FILE__ , __LINE__ );
209  }
210 
211  MACH3LOG_INFO("Now transferring splines to a monolith if size {}", MonolithSize);
212 
215  isflatarray = new bool[MonolithSize];
216 
219 
220  for (unsigned int iSample = 0; iSample < indexvec.size(); iSample++)
221  { // Loop over sample
222  for (unsigned int iOscChan = 0; iOscChan < indexvec[iSample].size(); iOscChan++)
223  { // Loop over oscillation channels
224  for (unsigned int iSyst = 0; iSyst < indexvec[iSample][iOscChan].size(); iSyst++)
225  { // Loop over systematics
226  for (unsigned int iMode = 0; iMode < indexvec[iSample][iOscChan][iSyst].size(); iMode++)
227  { // Loop over modes
228  for (unsigned int iVar1 = 0; iVar1 < indexvec[iSample][iOscChan][iSyst][iMode].size(); iVar1++)
229  { // Loop over first dimension
230  for (unsigned int iVar2 = 0; iVar2 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1].size(); iVar2++)
231  { // Loop over second dimension
232  for (unsigned int iVar3 = 0; iVar3 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2].size(); iVar3++)
233  {
234  int splineindex=indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2][iVar3];
235  weightvec_Monolith[splineindex] = 1.0;
236 
237  bool foundUniqueSpline = false;
238  for (int iUniqueSyst = 0; iUniqueSyst < nParams; iUniqueSyst++)
239  {
240  if (SplineFileParPrefixNames[iSample][iSyst] == UniqueSystNames[iUniqueSyst])
241  {
242  uniquesplinevec_Monolith[splineindex] = iUniqueSyst;
243  foundUniqueSpline = true;
244  }
245  }//unique syst loop end
246 
247  if (!foundUniqueSpline)
248  {
249  MACH3LOG_ERROR("Unique spline index not found");
250  MACH3LOG_ERROR("For Spline {}", SplineFileParPrefixNames[iSample][iSyst]);
251  MACH3LOG_ERROR("Couldn't match {} with any of the following {} systs:", SplineFileParPrefixNames[iSample][iSyst], nParams);
252  for (int iUniqueSyst = 0; iUniqueSyst < nParams; iUniqueSyst++)
253  {
254  MACH3LOG_ERROR("{},", UniqueSystNames.at(iUniqueSyst));
255  }//unique syst loop end
256  throw MaCh3Exception(__FILE__ , __LINE__ );
257  }
258 
259  int splineKnots;
260  if(splinevec_Monolith[splineindex]){
261  isflatarray[splineindex]=false;
262  splineKnots=splinevec_Monolith[splineindex]->GetNp();
263 
264  //Now to fill up our coefficient arrayss
265  M3::float_t* tmpXCoeffArr = new M3::float_t[splineKnots];
266  M3::float_t* tmpManyCoeffArr = new M3::float_t[splineKnots*_nCoeff_];
267 
268  int iCoeff=coeffindexvec[splineindex];
269  getSplineCoeff_SepMany(splineindex, tmpXCoeffArr, tmpManyCoeffArr);
270 
271  for(int i = 0; i < splineKnots; i++){
272  xcoeff_arr[iCoeff+i]=tmpXCoeffArr[i];
273 
274  for(int j = 0; j < _nCoeff_; j++){
275  manycoeff_arr[(iCoeff+i)*_nCoeff_+j]=tmpManyCoeffArr[i*_nCoeff_+j];
276  }
277  }
278  delete[] tmpXCoeffArr;
279  delete[] tmpManyCoeffArr;
280  }
281  else {
282  isflatarray[splineindex]=true;
283  }
284  }//3d loop end
285  }//2d loop end
286  }//1d loop end
287  }//mode loop end
288  }//syst2 loop end
289  }//osc loop end
290  }//syst1 loop end
291 }
292 
293 // *****************************************
295 // *****************************************
296  // There's a parameter mapping that goes from spline parameter to a global parameter index
297  // Find the spline segments
299 
300  //KS: Huge MP loop over all valid splines
302 }
303 
304 //****************************************
306 //****************************************
307  #ifdef MULTITHREAD
308  #pragma omp parallel for simd
309  #endif
310  for (size_t iCoeff = 0; iCoeff < uniquecoeffindices.size(); ++iCoeff)
311  {
312  const int iSpline = uniquecoeffindices[iCoeff];
313  const short int uniqueIndex = short(uniquesplinevec_Monolith[iSpline]);
314  const short int currentsegment = short(SplineSegments[uniqueIndex]);
315 
316  const int segCoeff = coeffindexvec[iSpline]+currentsegment;
317  const int coeffOffset = segCoeff * _nCoeff_;
318  // These are what we can extract from the TSpline3
319  const M3::float_t y = manycoeff_arr[coeffOffset+kCoeffY];
320  const M3::float_t b = manycoeff_arr[coeffOffset+kCoeffB];
321  const M3::float_t c = manycoeff_arr[coeffOffset+kCoeffC];
322  const M3::float_t d = manycoeff_arr[coeffOffset+kCoeffD];
323 
324  // Get the variation for this reconfigure for the ith parameter
326  const M3::float_t xvar = (*SplineInfoArray[uniqueIndex].splineParsPointer);
327  // The Delta(x) = xvar - x
328  const M3::float_t dx = xvar - xcoeff_arr[segCoeff];
329 
330  //Speedy 1% time boost https://en.cppreference.com/w/c/numeric/math/fma (see ND code!)
331  M3::float_t weight = M3::fmaf_t(dx, M3::fmaf_t(dx, M3::fmaf_t(dx, d, c), b), y);
332  //This is the speedy version of writing dx^3+b*dx^2+c*dx+d
333 
334  //ETA - do we need this? We check later for negative weights and I wonder if this is even
335  //possible with the fmaf line above?
336  if(weight < 0){weight = 0.;} //Stops is getting negative weights
337 
338  weightvec_Monolith[iSpline] = weight;
339  }
340 }
341 
342 //****************************************
343 //Creates an array to be filled with monolith indexes for each sample (allows for indexing between 7D binning and 1D Vector)
344 //Only need 1 indexing array everything else interfaces with this to get binning properties
345 void BinnedSplineHandler::BuildSampleIndexingArray(const std::string& SampleTitle) {
346 //****************************************
347  int iSample = GetSampleIndex(SampleTitle);
348  int nSplineSysts = nSplineParams[iSample];
349  int nOscChannels = nOscChans[iSample];
350 
351  // Resize the main indexing structure
352  indexvec.emplace_back(nOscChannels);
353 
354  for (int iOscChan = 0; iOscChan < nOscChannels; ++iOscChan)
355  {
356  indexvec.back()[iOscChan].resize(nSplineSysts);
357  for (int iSyst = 0; iSyst < nSplineSysts; ++iSyst)
358  {
359  int nModesInSyst = static_cast<int>(SplineModeVecs[iSample][iSyst].size());
360  indexvec.back()[iOscChan][iSyst].resize(nModesInSyst);
361 
362  for (int iMode = 0; iMode < nModesInSyst; ++iMode)
363  {
364  const int nBins1 = SplineBinning[iSample][iOscChan][0]->GetNbins();
365  const int nBins2 = SplineBinning[iSample][iOscChan][1]->GetNbins();
366  const int nBins3 = SplineBinning[iSample][iOscChan][2]->GetNbins();
367 
368  indexvec.back()[iOscChan][iSyst][iMode]
369  .resize(nBins1,std::vector<std::vector<int>>(nBins2, std::vector<int>(nBins3, 0)));
370  }
371  } // end of iSyst loop
372  } // end of iOscChan loop
373 }
374 
375 //****************************************
376 std::vector<TAxis *> BinnedSplineHandler::FindSplineBinning(const std::string& FileName, const std::string& SampleTitle) {
377 //****************************************
378  int iSample = GetSampleIndex(SampleTitle);
379 
380  //Try declaring these outside of TFile so they aren't owned by File
381  constexpr int nDummyBins = 1;
382  constexpr double DummyEdges[2] = {-1e15, 1e15};
383  TAxis* DummyAxis = new TAxis(nDummyBins, DummyEdges);
384  TH2F* Hist2D = nullptr;
385  TH3F* Hist3D = nullptr;
386 
387  auto File = std::unique_ptr<TFile>(TFile::Open(FileName.c_str(), "READ"));
388  if (!File || File->IsZombie())
389  {
390  MACH3LOG_ERROR("File {} not found", FileName);
391  MACH3LOG_ERROR("This is caused by something here! {} : {}", __FILE__, __LINE__);
392  throw MaCh3Exception(__FILE__ , __LINE__ );
393  }
394 
395  MACH3LOG_INFO("Finding binning for:");
396  MACH3LOG_INFO("{}", FileName);
397 
398  std::string TemplateName = "dev_tmp_0_0";
399  TObject *Obj = File->Get(TemplateName.c_str());
400  //If you can't find dev_tmp_0_0 then this will cause a problem
401  if (!Obj)
402  {
403  TemplateName = "dev_tmp.0.0";
404  Obj = File->Get(TemplateName.c_str());
405  if (!Obj)
406  {
407  MACH3LOG_ERROR("Could not find dev_tmp_0_0 in spline file. Spline binning cannot be set!");
408  MACH3LOG_ERROR("FileName: {}", FileName);
409  throw MaCh3Exception(__FILE__ , __LINE__ );
410  }
411  }
412 
413  //Now check if dev_tmp_0_0 is a TH2 i.e. specifying the dimensions of the splines is 2D
414  bool isHist2D = Obj->IsA() == TH2F::Class();
415  //For T2K annoyingly all objects are TH3Fs
416  bool isHist3D = Obj->IsA() == TH3F::Class();
417  if (!isHist2D && !isHist3D)
418  {
419  MACH3LOG_ERROR("Object doesn't inherit from either TH2D and TH3D - Odd A");
420  throw MaCh3Exception(__FILE__ , __LINE__ );
421  }
422 
423  if (isHist2D)
424  {
425  if (Dimensions[iSample] != 2)
426  {
427  MACH3LOG_ERROR("Trying to load a 2D spline template when nDim={}", Dimensions[iSample]);
428  throw MaCh3Exception(__FILE__, __LINE__);
429  }
430  Hist2D = File->Get<TH2F>(TemplateName.c_str());
431  }
432 
433  if (isHist3D)
434  {
435  Hist3D = File->Get<TH3F>((TemplateName.c_str()));
436 
437  if (Dimensions[iSample] != 3 && Hist3D->GetZaxis()->GetNbins() != 1)
438  {
439  MACH3LOG_ERROR("Trying to load a 3D spline template when nDim={}", Dimensions[iSample]);
440  throw MaCh3Exception(__FILE__ , __LINE__ );
441  }
442  Hist3D = File->Get<TH3F>(TemplateName.c_str());
443  }
444 
445  std::vector<TAxis*> ReturnVec;
446  // KS: Resize to reduce impact of push back and memory fragmentation
447  ReturnVec.resize(3);
448  if (Dimensions[iSample] == 2) {
449  if (isHist2D) {
450  ReturnVec[0] = static_cast<TAxis*>(Hist2D->GetXaxis()->Clone());
451  ReturnVec[1] = static_cast<TAxis*>(Hist2D->GetYaxis()->Clone());
452  ReturnVec[2] = static_cast<TAxis*>(DummyAxis->Clone());
453  } else if (isHist3D) {
454  ReturnVec[0] = static_cast<TAxis*>(Hist3D->GetXaxis()->Clone());
455  ReturnVec[1] = static_cast<TAxis*>(Hist3D->GetYaxis()->Clone());
456  ReturnVec[2] = static_cast<TAxis*>(DummyAxis->Clone());
457  }
458  } else if (Dimensions[iSample] == 3) {
459  ReturnVec[0] = static_cast<TAxis*>(Hist3D->GetXaxis()->Clone());
460  ReturnVec[1] = static_cast<TAxis*>(Hist3D->GetYaxis()->Clone());
461  ReturnVec[2] = static_cast<TAxis*>(Hist3D->GetZaxis()->Clone());
462  } else {
463  MACH3LOG_ERROR("Number of dimensions not valid! Given: {}", Dimensions[iSample]);
464  throw MaCh3Exception(__FILE__, __LINE__);
465  }
466 
467  for (unsigned int iAxis = 0; iAxis < ReturnVec.size(); ++iAxis) {
468  PrintBinning(ReturnVec[iAxis]);
469  }
470 
471  MACH3LOG_INFO("Left PrintBinning now tidying up");
472  delete DummyAxis;
473 
474  return ReturnVec;
475 }
476 
477 //****************************************
478 int BinnedSplineHandler::CountNumberOfLoadedSplines(bool NonFlat, int Verbosity) {
479 //****************************************
480  int SampleCounter_NonFlat = 0;
481  int SampleCounter_All = 0;
482  int FullCounter_NonFlat = 0;
483  int FullCounter_All = 0;
484 
485  for (unsigned int iSample = 0; iSample < indexvec.size(); iSample++)
486  { // Loop over systematics
487  SampleCounter_NonFlat = 0;
488  SampleCounter_All = 0;
489  std::string SampleTitle = SampleTitles[iSample];
490  for (unsigned int iOscChan = 0; iOscChan < indexvec[iSample].size(); iOscChan++)
491  { // Loop over oscillation channels
492  for (unsigned int iSyst = 0; iSyst < indexvec[iSample][iOscChan].size(); iSyst++)
493  { // Loop over systematics
494  for (unsigned int iMode = 0; iMode < indexvec[iSample][iOscChan][iSyst].size(); iMode++)
495  { // Loop over modes
496  for (unsigned int iVar1 = 0; iVar1 < indexvec[iSample][iOscChan][iSyst][iMode].size(); iVar1++)
497  { // Loop over first dimension
498  for (unsigned int iVar2 = 0; iVar2 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1].size(); iVar2++)
499  { // Loop over second dimension
500  for (unsigned int iVar3 = 0; iVar3 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2].size(); iVar3++)
501  { // Loop over third dimension
502  if (isValidSplineIndex(SampleTitle, iOscChan, iSyst, iMode, iVar1, iVar2, iVar3))
503  {
504  int splineindex = indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2][iVar3];
505  if (splinevec_Monolith[splineindex])
506  {
507  SampleCounter_NonFlat += 1;
508  }
509  SampleCounter_All += 1;
510  }
511  }
512  }
513  }
514  }
515  }
516  }
517  MACH3LOG_DEBUG("{:<10} has {:<10} splines, of which {:<10} are not flat", SampleTitles[iSample], SampleCounter_All, SampleCounter_NonFlat);
518 
519  FullCounter_NonFlat += SampleCounter_NonFlat;
520  FullCounter_All += SampleCounter_All;
521  }
522 
523  if (Verbosity > 0)
524  {
525  MACH3LOG_INFO("Total number of splines loaded: {}", FullCounter_All);
526  MACH3LOG_INFO("Total number of non-flat splines loaded: {}", FullCounter_NonFlat);
527  }
528 
529  if (NonFlat) {
530  return FullCounter_NonFlat;
531  } else {
532  return FullCounter_All;
533  }
534 }
535 
536 //****************************************
538 //****************************************
539  std::vector<TSpline3_red*> UniqueSystSplines;
540 
541  // DB Find all the Unique systs across each sample and oscillation channel
542  // This assumes that each occurence of the same systematic spline has the same knot spacing
543  // Which is a reasonable assumption for the current implementation of spline evaluations
544  for (unsigned int iSample = 0; iSample < indexvec.size(); iSample++)
545  { // Loop over systematics
546  for (unsigned int iSyst = 0; iSyst < indexvec[iSample][0].size(); iSyst++)
547  { // Loop over systematics
548  std::string SystName = SplineFileParPrefixNames[iSample][iSyst];
549  bool FoundSyst = false;
550 
551  //ETA - this always seems to be empty to begin with??
552  //so this loop never gets used?
553  for (unsigned int iFoundSyst = 0; iFoundSyst < UniqueSystNames.size(); iFoundSyst++)
554  {
555  if (SystName == UniqueSystNames[iFoundSyst])
556  {
557  FoundSyst = true;
558  }
559  }
560  if (!FoundSyst)
561  {
562  bool FoundNonFlatSpline = false;
563  //This is all basically to check that you have some resposne from a spline
564  //systematic somewhere
565  for (unsigned int iOscChan = 0; iOscChan < indexvec[iSample].size(); iOscChan++)
566  { // Loop over oscillation channels
567  for (unsigned int iMode = 0; iMode < indexvec[iSample][iOscChan][iSyst].size(); iMode++)
568  { // Loop over modes
569  for (unsigned int iVar1 = 0; iVar1 < indexvec[iSample][iOscChan][iSyst][iMode].size(); iVar1++)
570  { // Loop over first dimension
571  for (unsigned int iVar2 = 0; iVar2 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1].size(); iVar2++)
572  { // Loop over second dimension
573  for (unsigned int iVar3 = 0; iVar3 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2].size(); iVar3++)
574  { // Loop over third dimension
575  int splineindex=indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2][iVar3];
576  if (splinevec_Monolith[splineindex])
577  {
578  UniqueSystSplines.push_back(splinevec_Monolith[splineindex]);
579  UniqueSystIndices.push_back(GlobalSystIndex[iSample][iSyst]);
580  FoundNonFlatSpline = true;
581  }
582  if (FoundNonFlatSpline) { break;}
583  }//3D loop end
584  if (FoundNonFlatSpline) { break;}
585  }//2D loop end
586  if (FoundNonFlatSpline){ break; }
587  }//1D loop end
588  if (FoundNonFlatSpline){ break; }
589  }//mode loop end
590  if (FoundNonFlatSpline) { break; }
591  }//osc loop end
592  //ETA - only push back unique name if a non-flat response has been found
593  if(FoundNonFlatSpline){
594  UniqueSystNames.push_back(SystName);
595  }
596 
597  if (!FoundNonFlatSpline)
598  {
599  MACH3LOG_INFO("{} syst has no response in sample {}", SystName, iSample);
600  MACH3LOG_INFO("Whilst this isn't necessarily a problem, it seems odd");
601  continue;
602  }
603  }
604  }//Syst loop end
605  }
606 
607  nParams = static_cast<short int>(UniqueSystSplines.size());
608 
609  // DB Find the number of splines knots which assumes each instance of the syst has the same number of knots
610  SplineSegments = new short int[nParams]();
611  ParamValues = new float[nParams]();
612  SplineInfoArray.resize(nParams);
613  for (int iSpline = 0; iSpline < nParams; iSpline++)
614  {
615  SplineInfoArray[iSpline].nPts = static_cast<M3::int_t>(UniqueSystSplines[iSpline]->GetNp());
616  SplineInfoArray[iSpline].xPts.resize(SplineInfoArray[iSpline].nPts);
617  SplineInfoArray[iSpline].splineParsPointer = ParHandler->RetPointer(UniqueSystIndices[iSpline]);
618  for (int iKnot = 0; iKnot < SplineInfoArray[iSpline].nPts; iKnot++)
619  {
620  M3::float_t xPoint;
621  M3::float_t yPoint;
622  UniqueSystSplines[iSpline]->GetKnot(iKnot, xPoint, yPoint);
623  SplineInfoArray[iSpline].xPts[iKnot] = xPoint;
624  }
625  //ETA - let this just be set as the first segment by default
626  SplineSegments[iSpline] = 0;
627  ParamValues[iSpline] = 0.;
628  }
629 
630  MACH3LOG_INFO("nUniqueSysts: {}", nParams);
631  MACH3LOG_INFO("{:<15} | {:<20} | {:<6}", "Spline Index", "Syst Name", "nKnots");
632  for (int iUniqueSyst = 0; iUniqueSyst < nParams; iUniqueSyst++)
633  {
634  MACH3LOG_INFO("{:<15} | {:<20} | {:<6}", iUniqueSyst, UniqueSystNames[iUniqueSyst], SplineInfoArray[iUniqueSyst].nPts);
635  }
636 
637  //ETA
638  //Isn't this just doing what CountNumberOfLoadedSplines() does?
639  int nCombinations_FlatSplines = 0;
640  int nCombinations_All = 0;
641  // DB Now actually loop over splines to determine which are all null i.e. flat
642  for (unsigned int iSample = 0; iSample < indexvec.size(); iSample++)
643  { // Loop over systematics
644  for (unsigned int iOscChan = 0; iOscChan < indexvec[iSample].size(); iOscChan++)
645  { // Loop over oscillation channels
646  for (unsigned int iSyst = 0; iSyst < indexvec[iSample][iOscChan].size(); iSyst++)
647  { // Loop over systematics
648  for (unsigned int iMode = 0; iMode < indexvec[iSample][iOscChan][iSyst].size(); iMode++)
649  { // Loop over modes
650  //bool isFlat = false;
651  for (unsigned int iVar1 = 0; iVar1 < indexvec[iSample][iOscChan][iSyst][iMode].size(); iVar1++)
652  { // Loop over first dimension
653  for (unsigned int iVar2 = 0; iVar2 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1].size(); iVar2++)
654  { // Loop over second dimension
655  for (unsigned int iVar3 = 0; iVar3 < indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2].size(); iVar3++)
656  { // Loop over third dimension
657  int splineindex=indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2][iVar3];
658  if (splinevec_Monolith[splineindex])
659  {
660  nCombinations_All += 1;
661  } else{
662  nCombinations_FlatSplines += 1;
663  nCombinations_All += 1;
664  }
665  }
666  }
667  }
668  }
669  }
670  }
671  }
672  // We need to grab the maximum number of knots
673  MACH3LOG_INFO("Number of combinations of Sample, OscChan, Syst and Mode which have entirely flat response: {} / {}", nCombinations_FlatSplines, nCombinations_All);
674 }
675 
676 //****************************************
677 // Rather work with spline coefficients in the splines, let's copy ND and use coefficient arrays
678 void BinnedSplineHandler::getSplineCoeff_SepMany(int splineindex, M3::float_t* &xArray, M3::float_t* &manyArray) {
679 //****************************************
680  //No point evaluating a flat spline
681  int nPoints = splinevec_Monolith[splineindex]->GetNp();
682 
683  for (int i = 0; i < nPoints; i++) {
684  xArray[i] = 1.0;
685  for (int j = 0; j < _nCoeff_; j++) {
686  manyArray[i*_nCoeff_+j] = 1.0;
687  }
688  }
689 
690  for(int i=0; i<nPoints; i++) {
691  M3::float_t x = M3::float_t(-999.99);
692  M3::float_t y = M3::float_t(-999.99);
693  M3::float_t b = M3::float_t(-999.99);
694  M3::float_t c = M3::float_t(-999.99);
695  M3::float_t d = M3::float_t(-999.99);
696  splinevec_Monolith[splineindex]->GetCoeff(i, x, y, b, c, d);
697 
698  // Store the coefficients for each knot contiguously in memory
699  // 4 because manyArray stores y,b,c,d
700  xArray[i] = x;
701  manyArray[i * _nCoeff_ + kCoeffY] = y;
702  manyArray[i * _nCoeff_ + kCoeffB] = b;
703  manyArray[i * _nCoeff_ + kCoeffC] = c;
704  manyArray[i * _nCoeff_ + kCoeffD] = d;
705  }
706 
707  //We now clean up the splines!
708  delete splinevec_Monolith[splineindex];
709  splinevec_Monolith[splineindex] = nullptr;
710 }
711 
712 //****************************************
713 //Equally though could just use KinematicVariable to map back
714 std::string BinnedSplineHandler::getDimLabel(const int iSample, const unsigned int Axis) const
715 //****************************************
716 {
717  if(Axis > DimensionLabels[iSample].size()){
718  MACH3LOG_ERROR("The spline Axis you are trying to get the label of is larger than the number of dimensions");
719  MACH3LOG_ERROR("You are trying to get axis {} but have only got {}", Axis, Dimensions[iSample]);
720  throw MaCh3Exception(__FILE__ , __LINE__ );
721  }
722  return DimensionLabels.at(iSample).at(Axis);
723 }
724 
725 //****************************************
726 //Returns sample index in
727 int BinnedSplineHandler::GetSampleIndex(const std::string& SampleTitle) const{
728 //****************************************
729  for (size_t iSample = 0; iSample < SampleTitles.size(); ++iSample) {
730  if (SampleTitle == SampleTitles[iSample]) {
731  return static_cast<int>(iSample);
732  }
733  }
734  MACH3LOG_ERROR("Sample name not found: {}", SampleTitle);
735  throw MaCh3Exception(__FILE__, __LINE__);
736 }
737 
738 //****************************************
739 void BinnedSplineHandler::PrintSampleDetails(const std::string& SampleTitle) const
740 //****************************************
741 {
742  const int iSample = GetSampleIndex(SampleTitle);
743 
744  MACH3LOG_INFO("Details about sample: {:<20}", SampleTitles[iSample]);
745  MACH3LOG_INFO("\t Dimension: {:<35}", Dimensions[iSample]);
746  MACH3LOG_INFO("\t nSplineParam: {:<35}", nSplineParams[iSample]);
747  MACH3LOG_INFO("\t nOscChan: {:<35}", nOscChans[iSample]);
748 }
749 
750 //****************************************
751 void BinnedSplineHandler::PrintArrayDetails(const std::string& SampleTitle) const
752 //****************************************
753 {
754  int iSample = GetSampleIndex(SampleTitle);
755  int nOscChannels = int(indexvec[iSample].size());
756  MACH3LOG_INFO("Sample {} has {} oscillation channels", SampleTitle, nOscChannels);
757 
758  for (int iOscChan = 0; iOscChan < nOscChannels; iOscChan++)
759  {
760  int nSysts = int(indexvec[iSample][iOscChan].size());
761  MACH3LOG_INFO("Oscillation channel {} has {} systematics", iOscChan, nSysts);
762  }
763 
764  MACH3LOG_INFO("#----------------------------------------------------------------------------------------------------------------------------------#");
765  MACH3LOG_INFO("Printing no. of modes affected by each systematic for each oscillation channel");
766  for (unsigned int iOscChan = 0; iOscChan < indexvec[iSample].size(); iOscChan++) {
767  std::string modes = fmt::format("OscChan: {}\t", iOscChan);
768  for (unsigned int iSyst = 0; iSyst < indexvec[iSample][iOscChan].size(); iSyst++) {
769  modes += fmt::format("{} ", indexvec[iSample][iOscChan][iSyst].size());
770  }
771  MACH3LOG_INFO("{}", modes);
772  }
773  MACH3LOG_INFO("#----------------------------------------------------------------------------------------------------------------------------------#");
774 }
775 
776 //****************************************
777 bool BinnedSplineHandler::isValidSplineIndex(const std::string& SampleTitle, int iOscChan, int iSyst, int iMode, int iVar1, int iVar2, int iVar3) const
778 //****************************************
779 {
780  int iSample = GetSampleIndex(SampleTitle);
781  bool isValid = true;
782 
783  // Lambda to check if an index is valid for a specific dimension
784  auto checkIndex = [&isValid](int index, size_t size, const std::string& name) {
785  if (index < 0 || index >= int(size)) {
786  MACH3LOG_ERROR("{} index is invalid! 0 <= Index < {} ", name, size);
787  isValid = false;
788  }
789  };
790 
791  checkIndex(iSample, indexvec.size(), "Sample");
792  if (isValid) checkIndex(iOscChan, indexvec[iSample].size(), "OscChan");
793  if (isValid) checkIndex(iSyst, indexvec[iSample][iOscChan].size(), "Syst");
794  if (isValid) checkIndex(iMode, indexvec[iSample][iOscChan][iSyst].size(), "Mode");
795  if (isValid) checkIndex(iVar1, indexvec[iSample][iOscChan][iSyst][iMode].size(), "Var1");
796  if (isValid) checkIndex(iVar2, indexvec[iSample][iOscChan][iSyst][iMode][iVar1].size(), "Var2");
797  if (isValid) checkIndex(iVar3, indexvec[iSample][iOscChan][iSyst][iMode][iVar1][iVar2].size(), "Var3");
798 
799  if (!isValid)
800  {
801  MACH3LOG_ERROR("Given iSample: {}", iSample);
802  MACH3LOG_ERROR("Given iOscChan: {}", iOscChan);
803  MACH3LOG_ERROR("Given iSyst: {}", iSyst);
804  MACH3LOG_ERROR("Given iMode: {}", iMode);
805  MACH3LOG_ERROR("Given iVar1: {}", iVar1);
806  MACH3LOG_ERROR("Given iVar2: {}", iVar2);
807  MACH3LOG_ERROR("Given iVar3: {}", iVar3);
808  MACH3LOG_ERROR("Come visit me at : {} : {}", __FILE__, __LINE__);
809  throw MaCh3Exception(__FILE__, __LINE__);
810  }
811 
812  return true;
813 }
814 
815 //****************************************
816 void BinnedSplineHandler::PrintBinning(TAxis *Axis) const
817 //****************************************
818 {
819  const int NBins = Axis->GetNbins();
820  std::string text = "";
821  for (int iBin = 0; iBin <= NBins; iBin++) {
822  text += fmt::format("{} ", Axis->GetXbins()->GetAt(iBin));
823  }
824  MACH3LOG_INFO("{}", text);
825 }
826 
827 //****************************************
828 std::vector< std::vector<int> > BinnedSplineHandler::GetEventSplines(const std::string& SampleTitle, int iOscChan, int EventMode, double Var1Val, double Var2Val, double Var3Val) {
829 //****************************************
830  std::vector<std::vector<int>> ReturnVec;
831  int SampleIndex = GetSampleIndex(SampleTitle);
832  int nSplineSysts = static_cast<int>(indexvec[SampleIndex][iOscChan].size());
833 
834  int Mode = -1;
835  std::string SuffixForEventMode = Modes->GetSplineSuffixFromMaCh3Mode(EventMode);
836  for (int iMode=0;iMode<Modes->GetNModes();iMode++) {
837  if (SuffixForEventMode == Modes->GetSplineSuffixFromMaCh3Mode(iMode)) {
838  Mode = iMode;
839  break;
840  }
841  }
842  if (Mode == -1) {
843  return ReturnVec;
844  }
845 
846  std::vector<int> bins;
847  std::vector<double> vars = {Var1Val, Var2Val, Var3Val};
848  for (size_t i = 0; i < vars.size(); ++i) {
849  int bin = SplineBinning[SampleIndex][iOscChan][i]->FindBin(vars[i]) - 1;
850  if (bin < 0 || bin >= SplineBinning[SampleIndex][iOscChan][i]->GetNbins()) {
851  return ReturnVec;
852  }
853  bins.push_back(bin);
854  }
855  int Var1Bin = bins[0]; int Var2Bin = bins[1]; int Var3Bin = bins[2];
856 
857  for(int iSyst=0; iSyst<nSplineSysts; iSyst++){
858  std::vector<int> spline_modes = SplineModeVecs[SampleIndex][iSyst];
859  int nSampleModes = static_cast<int>(spline_modes.size());
860 
861  //ETA - look here at the length of spline_modes and what you're actually comparing against
862  for(int iMode = 0; iMode<nSampleModes; iMode++){
863  //Only consider if the event mode (Mode) matches ones of the spline modes
864  if (Mode == spline_modes[iMode]) {
865  int splineID=indexvec[SampleIndex][iOscChan][iSyst][iMode][Var1Bin][Var2Bin][Var3Bin];
866  //Also check that the spline isn't flat
867  if(!isflatarray[splineID]){
868  ReturnVec.push_back({SampleIndex, iOscChan, iSyst, iMode, Var1Bin, Var2Bin, Var3Bin});
869  }
870  }
871  }
872  }
873 
874  return ReturnVec;
875 }
876 
877 //****************************************
878 // checks if there are multiple modes with the same SplineSuffix
879 // (for example if CCRES and CCCoherent are treated as one spline mode)
880 std::vector< std::vector<int> > BinnedSplineHandler::StripDuplicatedModes(const std::vector< std::vector<int> >& InputVector) const {
881 //****************************************
882  //ETA - this is of size nPars from the syst model
883  size_t InputVectorSize = InputVector.size();
884  std::vector< std::vector<int> > ReturnVec(InputVectorSize);
885 
886  //ETA - loop over all systematics
887  for (size_t iSyst=0;iSyst<InputVectorSize;iSyst++) {
888  std::vector<int> TmpVec;
889  std::vector<std::string> TestVec;
890 
891  //Loop over the modes that we've listed in ParHandler
892  for (unsigned int iMode = 0 ; iMode < InputVector[iSyst].size() ; iMode++) {
893  int Mode = InputVector[iSyst][iMode];
894  std::string ModeName = Modes->GetSplineSuffixFromMaCh3Mode(Mode);
895 
896  bool IncludeMode = true;
897  for (auto TestString : TestVec) {
898  if (ModeName == TestString) {
899  IncludeMode = false;
900  break;
901  }
902  }
903 
904  if (IncludeMode) {
905  TmpVec.push_back(Mode);
906  TestVec.push_back(ModeName);
907  }
908  }
909 
910  ReturnVec[iSyst] = TmpVec;
911  }
912  return ReturnVec;
913 }
914 
915 void BinnedSplineHandler::FillSampleArray(const std::string& SampleTitle, const std::vector<std::string>& OscChanFileNames)
916 {
917  int iSample = GetSampleIndex(SampleTitle);
918  int nOscChannels = nOscChans[iSample];
919 
920  for (int iOscChan = 0; iOscChan < nOscChannels; iOscChan++) {
921  MACH3LOG_INFO("Processing: {}", OscChanFileNames[iOscChan]);
922  TSpline3* mySpline = nullptr;
923  TSpline3_red* Spline = nullptr;
924  TString Syst, Mode;
925  int nKnots, SystNum, ModeNum, Var1Bin, Var2Bin, Var3Bin = M3::_BAD_INT_;
926  double x,y = M3::_BAD_DOUBLE_;
927  bool isFlat = true;
928 
929  std::set<std::string> SplineFileNames;
930 
931  auto File = std::unique_ptr<TFile>(TFile::Open(OscChanFileNames[iOscChan].c_str()));
932 
933  if (!File || File->IsZombie()) {
934  MACH3LOG_ERROR("File {} not found", OscChanFileNames[iOscChan]);
935  throw MaCh3Exception(__FILE__, __LINE__);
936  }
937 
938  //This is the MC specific part of the code
939  //i.e. we always assume that the splines are just store in single TDirectory and they're all in there as single objects
940  for (auto k : *File->GetListOfKeys()) {
941  auto Key = static_cast<TKey*>(k);
942  TClass *Class = gROOT->GetClass(Key->GetClassName(), false);
943  if(!Class->InheritsFrom("TSpline3")) {
944  continue;
945  }
946 
947  std::string FullSplineName = std::string(Key->GetName());
948 
949  if (SplineFileNames.count(FullSplineName) > 0) {
950  MACH3LOG_CRITICAL("Skipping spline - Found a spline whose name has already been encountered before: {}", FullSplineName);
951  continue;
952  }
953  SplineFileNames.insert(FullSplineName);
954 
955  std::vector<std::string> Tokens = GetTokensFromSplineName(FullSplineName);
956 
957  if (Tokens.size() != kNTokens) {
958  MACH3LOG_ERROR("Invalid tokens from spline name - Expected {} tokens. Check implementation in GetTokensFromSplineName()", static_cast<int>(kNTokens));
959  throw MaCh3Exception(__FILE__, __LINE__);
960  }
961 
962  Syst = Tokens[kSystToken];
963  Mode = Tokens[kModeToken];
964  Var1Bin = std::stoi(Tokens[kVar1BinToken]);
965  Var2Bin = std::stoi(Tokens[kVar2BinToken]);
966  Var3Bin = std::stoi(Tokens[kVar3BinToken]);
967 
968  SystNum = -1;
969  for (unsigned iSyst = 0; iSyst < SplineFileParPrefixNames[iSample].size(); iSyst++) {
970  if (Syst == SplineFileParPrefixNames[iSample][iSyst]) {
971  SystNum = iSyst;
972  break;
973  }
974  }
975 
976  // If the syst doesn't match any of the spline names then skip it
977  if (SystNum == -1){
978  MACH3LOG_DEBUG("Couldn't match!!");
979  MACH3LOG_DEBUG("Couldn't Match any systematic name in ParameterHandler with spline name: {}" , FullSplineName);
980  continue;
981  }
982 
983  ModeNum = -1;
984  for (unsigned int iMode = 0; iMode < SplineModeVecs[iSample][SystNum].size(); iMode++) {
985  if (Mode == Modes->GetSplineSuffixFromMaCh3Mode(SplineModeVecs[iSample][SystNum][iMode])) {
986  ModeNum = iMode;
987  break;
988  }
989  }
990 
991  if (ModeNum == -1) {
992  //DB - If you have splines in the root file that you don't want to use (e.g. removing a mode from a syst), this will cause a throw
993  // Therefore include as debug warning and continue instead
994  MACH3LOG_DEBUG("Couldn't find mode for {} in {}. Problem Spline is : {} ", Mode, Syst, FullSplineName);
995  continue;
996  }
997 
998  mySpline = Key->ReadObject<TSpline3>();
999 
1000  if (isValidSplineIndex(SampleTitle, iOscChan, SystNum, ModeNum, Var1Bin, Var2Bin, Var3Bin)) { // loop over all the spline knots and check their value
1001  MACH3LOG_TRACE("Pushed back monolith for spline {}", FullSplineName);
1002  // if the value is 1 then set the flat bool to false
1003  nKnots = mySpline->GetNp();
1004  isFlat = true;
1005  for (int iKnot = 0; iKnot < nKnots; iKnot++) {
1006  mySpline->GetKnot(iKnot, x, y);
1007  if (y < 0.99999 || y > 1.00001)
1008  {
1009  isFlat = false;
1010  break;
1011  }
1012  }
1013 
1014  //Rather than keeping a mega vector of splines then converting, this should just keep everything nice in memory!
1015  indexvec[iSample][iOscChan][SystNum][ModeNum][Var1Bin][Var2Bin][Var3Bin]=MonolithIndex;
1016  coeffindexvec.push_back(CoeffIndex);
1017  // Should save memory rather saving [x_i_0 ,... x_i_maxknots] for every spline!
1018  if (isFlat) {
1019  splinevec_Monolith.push_back(nullptr);
1020  delete mySpline;
1021  } else {
1022  ApplyKnotWeightCapTSpline3(mySpline, SystNum, ParHandler);
1023  Spline = new TSpline3_red(mySpline, SplineInterpolationTypes[iSample][SystNum]);
1024  if(mySpline) delete mySpline;
1025 
1026  splinevec_Monolith.push_back(Spline);
1027  uniquecoeffindices.push_back(MonolithIndex); //So we can get the unique coefficients and skip flat splines later on!
1028  CoeffIndex+=nKnots;
1029  }
1030  //Incrementing MonolithIndex to keep track of number of valid spline indices
1031  MonolithIndex+=1;
1032  } else {
1033  //Potentially you are not a valid spline index
1034  delete mySpline;
1035  }
1036  }//End of loop over all TKeys in file
1037 
1038  //A bit of clean up
1039  File->Delete("*");
1040  File->Close();
1041  } //End of oscillation channel loop
1042 }
1043 
1044 // *****************************************
1045 // Load SplineMonolith from ROOT file
1046 void BinnedSplineHandler::LoadSplineFile(std::string FileName) {
1047 // *****************************************
1048  M3::AddPath(FileName);
1049 
1050  // Check for spaces in the filename
1051  size_t pos = FileName.find(' ');
1052  if (pos != std::string::npos) {
1053  MACH3LOG_WARN("Filename ({}) contains spaces. Replacing spaces with underscores.", FileName);
1054  while ((pos = FileName.find(' ')) != std::string::npos) {
1055  FileName[pos] = '_';
1056  }
1057  }
1058  auto SplineFile = std::make_unique<TFile>(FileName.c_str(), "OPEN");
1059 
1060  TMacro *ConfigCov = SplineFile->Get<TMacro>("ParameterHandler");
1061  // Config which was in MCMC from which we are starting
1062  YAML::Node CovSettings = TMacroToYAML(*ConfigCov);
1063  // Config from currently used cov object
1064  YAML::Node ConfigCurrent = ParHandler->GetConfig();
1065 
1066  if (!compareYAMLNodes(CovSettings, ConfigCurrent))
1067  {
1068  MACH3LOG_ERROR("Loading precomputed spline file, however encountered different YAML config, please regenerate input");
1069  throw MaCh3Exception(__FILE__ , __LINE__ );
1070  }
1071 
1072  LoadSettingsDir(SplineFile);
1073  LoadMonolithDir(SplineFile);
1074  LoadIndexDir(SplineFile);
1075  LoadFastSplineInfoDir(SplineFile);
1076 
1077  for (int iSpline = 0; iSpline < nParams; iSpline++) {
1078  SplineInfoArray[iSpline].splineParsPointer = ParHandler->RetPointer(UniqueSystIndices[iSpline]);
1079  }
1080  SplineFile->Close();
1081 }
1082 
1083 // *****************************************
1084 // KS: Prepare Fast Spline Info within SplineFile
1085 void BinnedSplineHandler::LoadSettingsDir(std::unique_ptr<TFile>& SplineFile) {
1086 // *****************************************
1087  TTree *Settings = SplineFile->Get<TTree>("Settings");
1088  int CoeffIndex_temp, MonolithSize_temp;
1089  short int nParams_temp;
1090  Settings->SetBranchAddress("CoeffIndex", &CoeffIndex_temp);
1091  Settings->SetBranchAddress("MonolithSize", &MonolithSize_temp);
1092  Settings->SetBranchAddress("nParams", &nParams_temp);
1093  int indexvec_sizes[7];
1094  for (int i = 0; i < 7; ++i) {
1095  Settings->SetBranchAddress(("indexvec_size" + std::to_string(i+1)).c_str(), &indexvec_sizes[i]);
1096  }
1097 
1098  int SplineBinning_size1, SplineBinning_size2, SplineBinning_size3;
1099  Settings->SetBranchAddress("SplineBinning_size1", &SplineBinning_size1);
1100  Settings->SetBranchAddress("SplineBinning_size2", &SplineBinning_size2);
1101  Settings->SetBranchAddress("SplineBinning_size3", &SplineBinning_size3);
1102  int SplineModeVecs_size1, SplineModeVecs_size2, SplineModeVecs_size3;
1103  Settings->SetBranchAddress("SplineModeVecs_size1", &SplineModeVecs_size1);
1104  Settings->SetBranchAddress("SplineModeVecs_size2", &SplineModeVecs_size2);
1105  Settings->SetBranchAddress("SplineModeVecs_size3", &SplineModeVecs_size3);
1106  std::vector<std::string>* SampleNames_temp = nullptr;
1107  Settings->SetBranchAddress("SampleNames", &SampleNames_temp);
1108  std::vector<std::string>* SampleTitles_temp = nullptr;
1109  Settings->SetBranchAddress("SampleTitles", &SampleTitles_temp);
1110  Settings->GetEntry(0);
1111 
1112  CoeffIndex = CoeffIndex_temp;
1113  MonolithSize = MonolithSize_temp;
1114  SampleNames = *SampleNames_temp;
1115  SampleTitles = *SampleTitles_temp;
1116 
1117  nParams = nParams_temp;
1118 
1119  SplineSegments = new short int[nParams]();
1120  ParamValues = new float[nParams]();
1121 
1122  // Resize indexvec according to saved dimensions
1123  indexvec.resize(indexvec_sizes[0]);
1124  for (int i = 0; i < indexvec_sizes[0]; ++i) {
1125  indexvec[i].resize(indexvec_sizes[1]);
1126  for (int j = 0; j < indexvec_sizes[1]; ++j) {
1127  indexvec[i][j].resize(indexvec_sizes[2]);
1128  for (int k = 0; k < indexvec_sizes[2]; ++k) {
1129  indexvec[i][j][k].resize(indexvec_sizes[3]);
1130  for (int l = 0; l < indexvec_sizes[3]; ++l) {
1131  indexvec[i][j][k][l].resize(indexvec_sizes[4]);
1132  for (int m = 0; m < indexvec_sizes[4]; ++m) {
1133  indexvec[i][j][k][l][m].resize(indexvec_sizes[5]);
1134  for (int n = 0; n < indexvec_sizes[5]; ++n) {
1135  indexvec[i][j][k][l][m][n].resize(indexvec_sizes[6]);
1136  }
1137  }
1138  }
1139  }
1140  }
1141  }
1142 
1143  auto Resize3D = [](auto& vec, int d1, int d2, int d3) {
1144  vec.resize(d1);
1145  for (int i = 0; i < d1; ++i) {
1146  vec[i].resize(d2);
1147  for (int j = 0; j < d2; ++j) {
1148  vec[i][j].resize(d3);
1149  }
1150  }
1151  };
1152 
1153  Resize3D(SplineBinning, SplineBinning_size1, SplineBinning_size2, SplineBinning_size3);
1154  Resize3D(SplineModeVecs, SplineModeVecs_size1, SplineModeVecs_size2, SplineModeVecs_size3);
1155 }
1156 
1157 // *****************************************
1158 // KS: Prepare Fast Spline Info within SplineFile
1159 void BinnedSplineHandler::LoadMonolithDir(std::unique_ptr<TFile>& SplineFile) {
1160 // *****************************************
1161  TTree *MonolithTree = SplineFile->Get<TTree>("MonolithTree");
1162 
1164  MonolithTree->SetBranchAddress("manycoeff", manycoeff_arr);
1165  isflatarray = new bool[MonolithSize];
1167  MonolithTree->SetBranchAddress("isflatarray", isflatarray);
1168 
1169  // Load vectors
1170  std::vector<int>* coeffindexvec_temp = nullptr;
1171  MonolithTree->SetBranchAddress("coeffindexvec", &coeffindexvec_temp);
1172  std::vector<int>* uniquecoeffindices_temp = nullptr;
1173  MonolithTree->SetBranchAddress("uniquecoeffindices", &uniquecoeffindices_temp);
1174  std::vector<int>* uniquesplinevec_Monolith_temp = nullptr;
1175  MonolithTree->SetBranchAddress("uniquesplinevec_Monolith", &uniquesplinevec_Monolith_temp);
1176  std::vector<int>* UniqueSystIndices_temp = nullptr;
1177  MonolithTree->SetBranchAddress("UniqueSystIndices", &UniqueSystIndices_temp);
1178 
1179  // Allocate and load xcoeff_arr
1181  MonolithTree->SetBranchAddress("xcoeff", xcoeff_arr);
1182 
1183  MonolithTree->GetEntry(0);
1184 
1185  coeffindexvec = *coeffindexvec_temp;
1186  uniquecoeffindices = *uniquecoeffindices_temp;
1187  uniquesplinevec_Monolith = *uniquesplinevec_Monolith_temp;
1188  UniqueSystIndices = *UniqueSystIndices_temp;
1189 }
1190 
1191 // *****************************************
1192 // KS: Prepare Fast Spline Info within SplineFile
1193 void BinnedSplineHandler::LoadIndexDir(std::unique_ptr<TFile>& SplineFile) {
1194 // *****************************************
1195  TTree *IndexTree = SplineFile->Get<TTree>("IndexVec");
1196 
1197  std::vector<int> Dim(7);
1198  int value;
1199  for (int d = 0; d < 7; ++d) {
1200  IndexTree->SetBranchAddress(Form("dim%d", d+1), &Dim[d]);
1201  }
1202  IndexTree->SetBranchAddress("value", &value);
1203 
1204  // Fill indexvec with data from IndexTree
1205  for (Long64_t i = 0; i < IndexTree->GetEntries(); ++i) {
1206  IndexTree->GetEntry(i);
1207  indexvec[Dim[0]][Dim[1]][Dim[2]][Dim[3]][Dim[4]][Dim[5]][Dim[6]] = value;
1208  }
1209 
1210  // Load SplineBinning data
1211  TTree *SplineBinningTree = SplineFile->Get<TTree>("SplineBinningTree");
1212  std::vector<int> indices(3);
1213  SplineBinningTree->SetBranchAddress("i", &indices[0]);
1214  SplineBinningTree->SetBranchAddress("j", &indices[1]);
1215  SplineBinningTree->SetBranchAddress("k", &indices[2]);
1216  TAxis* axis = nullptr;
1217  SplineBinningTree->SetBranchAddress("axis", &axis);
1218 
1219  // Reconstruct TAxis objects
1220  for (Long64_t entry = 0; entry < SplineBinningTree->GetEntries(); ++entry) {
1221  SplineBinningTree->GetEntry(entry);
1222  int i = indices[0];
1223  int j = indices[1];
1224  int k = indices[2];
1225  SplineBinning[i][j][k] = static_cast<TAxis*>(axis->Clone());
1226  }
1227 
1228  std::vector<int> indices_mode(3);
1229  int mode_value;
1230  TTree *SplineModeTree = SplineFile->Get<TTree>("SplineModeTree");
1231  SplineModeTree->SetBranchAddress("i", &indices_mode[0]);
1232  SplineModeTree->SetBranchAddress("j", &indices_mode[1]);
1233  SplineModeTree->SetBranchAddress("k", &indices_mode[2]);
1234  SplineModeTree->SetBranchAddress("value", &mode_value);
1235 
1236  // Fill SplineModeVecs with values from the tree
1237  for (Long64_t entry = 0; entry < SplineModeTree->GetEntries(); ++entry) {
1238  SplineModeTree->GetEntry(entry);
1239  int i = indices_mode[0];
1240  int j = indices_mode[1];
1241  int k = indices_mode[2];
1242  SplineModeVecs[i][j][k] = mode_value;
1243  }
1244 }
1245 
1246 // *****************************************
1247 // Save SplineMonolith into ROOT file
1248 void BinnedSplineHandler::PrepareSplineFile(std::string FileName) {
1249 // *****************************************
1250  M3::AddPath(FileName);
1251  // Check for spaces in the filename
1252  size_t pos = FileName.find(' ');
1253  if (pos != std::string::npos) {
1254  MACH3LOG_WARN("Filename ({}) contains spaces. Replacing spaces with underscores.", FileName);
1255  while ((pos = FileName.find(' ')) != std::string::npos) {
1256  FileName[pos] = '_';
1257  }
1258  }
1259  // Save ROOT File
1260  auto SplineFile = std::make_unique<TFile>(FileName.c_str(), "recreate");
1261  YAML::Node ConfigCurrent = ParHandler->GetConfig();
1262  TMacro ConfigSave = YAMLtoTMacro(ConfigCurrent, "ParameterHandler");
1263  ConfigSave.Write();
1264 
1265  PrepareSettingsDir(SplineFile);
1266  PrepareMonolithDir(SplineFile);
1267  PrepareIndexDir(SplineFile);
1268  PrepareOtherInfoDir(SplineFile);
1269  PrepareFastSplineInfoDir(SplineFile);
1270 
1271  SplineFile->Close();
1272 }
1273 
1274 // *****************************************
1275 void BinnedSplineHandler::PrepareSettingsDir(std::unique_ptr<TFile>& SplineFile) const {
1276 // *****************************************
1277  TTree *Settings = new TTree("Settings", "Settings");
1278  int CoeffIndex_temp = CoeffIndex;
1279  int MonolithSize_temp = MonolithSize;
1280  short int nParams_temp = nParams;
1281 
1282  Settings->Branch("CoeffIndex", &CoeffIndex_temp, "CoeffIndex/I");
1283  Settings->Branch("MonolithSize", &MonolithSize_temp, "MonolithSize/I");
1284  Settings->Branch("nParams", &nParams_temp, "nParams/S");
1285 
1286  int indexvec_sizes[7];
1287  indexvec_sizes[0] = static_cast<int>(indexvec.size());
1288  indexvec_sizes[1] = (indexvec_sizes[0] > 0) ? static_cast<int>(indexvec[0].size()) : 0;
1289  indexvec_sizes[2] = (indexvec_sizes[1] > 0) ? static_cast<int>(indexvec[0][0].size()) : 0;
1290  indexvec_sizes[3] = (indexvec_sizes[2] > 0) ? static_cast<int>(indexvec[0][0][0].size()) : 0;
1291  indexvec_sizes[4] = (indexvec_sizes[3] > 0) ? static_cast<int>(indexvec[0][0][0][0].size()) : 0;
1292  indexvec_sizes[5] = (indexvec_sizes[4] > 0) ? static_cast<int>(indexvec[0][0][0][0][0].size()) : 0;
1293  indexvec_sizes[6] = (indexvec_sizes[5] > 0) ? static_cast<int>(indexvec[0][0][0][0][0][0].size()) : 0;
1294 
1295  for (int i = 0; i < 7; ++i) {
1296  Settings->Branch(("indexvec_size" + std::to_string(i+1)).c_str(),
1297  &indexvec_sizes[i], ("indexvec_size" + std::to_string(i+1) + "/I").c_str());
1298  }
1299 
1300  int SplineBinning_size1 = static_cast<int>(SplineBinning.size());
1301  int SplineBinning_size2 = (SplineBinning_size1 > 0) ? static_cast<int>(SplineBinning[0].size()) : 0;
1302  int SplineBinning_size3 = (SplineBinning_size2 > 0) ? static_cast<int>(SplineBinning[0][0].size()) : 0;
1303 
1304  Settings->Branch("SplineBinning_size1", &SplineBinning_size1, "SplineBinning_size1/I");
1305  Settings->Branch("SplineBinning_size2", &SplineBinning_size2, "SplineBinning_size2/I");
1306  Settings->Branch("SplineBinning_size3", &SplineBinning_size3, "SplineBinning_size3/I");
1307 
1308  int SplineModeVecs_size1 = static_cast<int>(SplineModeVecs.size());
1309  int SplineModeVecs_size2 = (SplineModeVecs_size1 > 0) ? static_cast<int>(SplineModeVecs[0].size()) : 0;
1310  int SplineModeVecs_size3 = (SplineModeVecs_size2 > 0) ? static_cast<int>(SplineModeVecs[0][0].size()) : 0;
1311 
1312  Settings->Branch("SplineModeVecs_size1", &SplineModeVecs_size1, "SplineModeVecs_size1/I");
1313  Settings->Branch("SplineModeVecs_size2", &SplineModeVecs_size2, "SplineModeVecs_size2/I");
1314  Settings->Branch("SplineModeVecs_size3", &SplineModeVecs_size3, "SplineModeVecs_size3/I");
1315 
1316  std::vector<std::string> SampleNames_temp = SampleNames;
1317  Settings->Branch("SampleNames", &SampleNames_temp);
1318  std::vector<std::string> SampleTitles_temp = SampleTitles;
1319  Settings->Branch("SampleTitles", &SampleTitles_temp);
1320 
1321  Settings->Fill();
1322  SplineFile->cd();
1323  Settings->Write();
1324  delete Settings;
1325 }
1326 
1327 // *****************************************
1328 void BinnedSplineHandler::PrepareMonolithDir(std::unique_ptr<TFile>& SplineFile) const {
1329 // *****************************************
1330  TTree *MonolithTree = new TTree("MonolithTree", "MonolithTree");
1331  MonolithTree->Branch("manycoeff", manycoeff_arr, Form("manycoeff[%d]/%s", CoeffIndex * _nCoeff_, M3::float_t_str_repr));
1332  MonolithTree->Branch("isflatarray", isflatarray, Form("isflatarray[%d]/O", MonolithSize));
1333 
1334  std::vector<int> coeffindexvec_temp = coeffindexvec;
1335  MonolithTree->Branch("coeffindexvec", &coeffindexvec_temp);
1336  std::vector<int> uniquecoeffindices_temp = uniquecoeffindices;
1337  MonolithTree->Branch("uniquecoeffindices", &uniquecoeffindices_temp);
1338  std::vector<int> uniquesplinevec_Monolith_temp = uniquesplinevec_Monolith;
1339  MonolithTree->Branch("uniquesplinevec_Monolith", &uniquesplinevec_Monolith_temp);
1340  std::vector<int> UniqueSystIndices_temp = UniqueSystIndices;
1341  MonolithTree->Branch("UniqueSystIndices", &UniqueSystIndices_temp);
1342  MonolithTree->Branch("xcoeff", xcoeff_arr, Form("xcoeff[%d]/%s", CoeffIndex, M3::float_t_str_repr));
1343 
1344  MonolithTree->Fill();
1345  SplineFile->cd();
1346  MonolithTree->Write();
1347  delete MonolithTree;
1348 }
1349 
1350 // *****************************************
1351 void BinnedSplineHandler::PrepareIndexDir(std::unique_ptr<TFile>& SplineFile) const {
1352 // *****************************************
1353  // Create a TTree to store the data
1354  TTree *IndexTree = new TTree("IndexVec", "IndexVec");
1355 
1356  // Vector holding the 7 dims
1357  std::vector<int> Dim(7);
1358  int value;
1359 
1360  // Create branches for each dimension
1361  for (int d = 0; d < 7; ++d) {
1362  IndexTree->Branch(Form("dim%d", d+1), &Dim[d], Form("dim%d/I", d+1));
1363  }
1364  IndexTree->Branch("value", &value, "value/I");
1365 
1366  // Fill the tree
1367  for (size_t i = 0; i < indexvec.size(); ++i) {
1368  for (size_t j = 0; j < indexvec[i].size(); ++j) {
1369  for (size_t k = 0; k < indexvec[i][j].size(); ++k) {
1370  for (size_t l = 0; l < indexvec[i][j][k].size(); ++l) {
1371  for (size_t m = 0; m < indexvec[i][j][k][l].size(); ++m) {
1372  for (size_t n = 0; n < indexvec[i][j][k][l][m].size(); ++n) {
1373  for (size_t p = 0; p < indexvec[i][j][k][l][m][n].size(); ++p) {
1374  Dim[0] = static_cast<int>(i);
1375  Dim[1] = static_cast<int>(j);
1376  Dim[2] = static_cast<int>(k);
1377  Dim[3] = static_cast<int>(l);
1378  Dim[4] = static_cast<int>(m);
1379  Dim[5] = static_cast<int>(n);
1380  Dim[6] = static_cast<int>(p);
1381  value = static_cast<int>(indexvec[i][j][k][l][m][n][p]);
1382  IndexTree->Fill();
1383  }
1384  }
1385  }
1386  }
1387  }
1388  }
1389  }
1390 
1391  SplineFile->cd();
1392  // Write the tree to the file
1393  IndexTree->Write();
1394  delete IndexTree;
1395 }
1396 
1397 // *****************************************
1398 void BinnedSplineHandler::PrepareOtherInfoDir(std::unique_ptr<TFile>& SplineFile) const {
1399 // *****************************************
1400  // Create a new tree for SplineBinning data
1401  TTree *SplineBinningTree = new TTree("SplineBinningTree", "SplineBinningTree");
1402  std::vector<int> indices(3); // To store the 3D indices
1403  TAxis* axis = nullptr;
1404  SplineBinningTree->Branch("i", &indices[0], "i/I");
1405  SplineBinningTree->Branch("j", &indices[1], "j/I");
1406  SplineBinningTree->Branch("k", &indices[2], "k/I");
1407  SplineBinningTree->Branch("axis", "TAxis", &axis);
1408 
1409  // Fill the SplineBinningTree
1410  for (size_t i = 0; i < SplineBinning.size(); ++i) {
1411  for (size_t j = 0; j < SplineBinning[i].size(); ++j) {
1412  for (size_t k = 0; k < SplineBinning[i][j].size(); ++k) {
1413  axis = SplineBinning[i][j][k];
1414  indices[0] = static_cast<int>(i);
1415  indices[1] = static_cast<int>(j);
1416  indices[2] = static_cast<int>(k);
1417  SplineBinningTree->Fill();
1418  }
1419  }
1420  }
1421  SplineFile->cd();
1422  SplineBinningTree->Write();
1423  delete SplineBinningTree;
1424 
1425  std::vector<int> indices_mode(3); // to store 3D indices
1426  int mode_value;
1427 
1428  TTree *SplineModeTree = new TTree("SplineModeTree", "SplineModeTree");
1429  // Create branches for indices and value
1430  SplineModeTree->Branch("i", &indices_mode[0], "i/I");
1431  SplineModeTree->Branch("j", &indices_mode[1], "j/I");
1432  SplineModeTree->Branch("k", &indices_mode[2], "k/I");
1433  SplineModeTree->Branch("value", &mode_value, "value/I");
1434 
1435  // Fill the tree
1436  for (size_t i = 0; i < SplineModeVecs.size(); ++i) {
1437  for (size_t j = 0; j < SplineModeVecs[i].size(); ++j) {
1438  for (size_t k = 0; k < SplineModeVecs[i][j].size(); ++k) {
1439  indices_mode[0] = static_cast<int>(i);
1440  indices_mode[1] = static_cast<int>(j);
1441  indices_mode[2] = static_cast<int>(k);
1442  mode_value = SplineModeVecs[i][j][k];
1443  SplineModeTree->Fill();
1444  }
1445  }
1446  }
1447  // Write the tree to the file
1448  SplineFile->cd();
1449  SplineModeTree->Write();
1450  delete SplineModeTree;
1451 }
#define _MaCh3_Safe_Include_Start_
KS: Avoiding warning checking for headers.
Definition: Core.h:126
#define _MaCh3_Safe_Include_End_
KS: Restore warning checking after including external headers.
Definition: Core.h:141
#define MACH3LOG_CRITICAL
Definition: MaCh3Logger.h:38
#define MACH3LOG_DEBUG
Definition: MaCh3Logger.h:34
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
#define MACH3LOG_TRACE
Definition: MaCh3Logger.h:33
void CleanContainer(T &)
Base case: do nothing for non-pointer types.
void CleanVector(T &)
Base case: do nothing for non-vector types.
@ kSpline
For splined parameters (1D)
constexpr int _nCoeff_
KS: We store coefficients {y,b,c,d} in one array one by one, this is only to define it once rather th...
Definition: SplineCommon.h:18
@ kCoeffB
Coefficient B.
Definition: SplineCommon.h:26
@ kCoeffD
Coefficient D.
Definition: SplineCommon.h:28
@ kCoeffY
Coefficient Y.
Definition: SplineCommon.h:25
@ kCoeffC
Coefficient C.
Definition: SplineCommon.h:27
void ApplyKnotWeightCapTSpline3(TSpline3 *&Spline, const int splineParsIndex, ParameterHandlerGeneric *XsecCov)
EM: Apply capping to knot weight for specified spline parameter. param graph needs to have been set i...
Definition: SplineStructs.h:99
bool isFlat(TSpline3_red *&spl)
CW: Helper function used in the constructor, tests to see if the spline is flat.
TMacro YAMLtoTMacro(const YAML::Node &yaml_node, const std::string &name)
Convert a YAML node to a ROOT TMacro object.
Definition: YamlHelper.h:167
YAML::Node TMacroToYAML(const TMacro &macro)
KS: Convert a ROOT TMacro object to a YAML node.
Definition: YamlHelper.h:152
bool compareYAMLNodes(const YAML::Node &node1, const YAML::Node &node2, bool Mute=false)
Compare if yaml nodes are identical.
Definition: YamlHelper.h:186
void getSplineCoeff_SepMany(int splineindex, M3::float_t *&xArray, M3::float_t *&manyArray)
virtual void FillSampleArray(const std::string &SampleTitle, const std::vector< std::string > &OscChanFileNames)
Loads and processes splines from ROOT files for a given sample.
std::string getDimLabel(const int BinningOpt, const unsigned int Axis) const
bool * isflatarray
Need to keep track of which splines are flat and which aren't.
void LoadIndexDir(std::unique_ptr< TFile > &SplineFile)
KS: Load preprocessed Index.
int CountNumberOfLoadedSplines(bool NonFlat=false, int Verbosity=0)
std::vector< std::vector< std::vector< std::vector< std::vector< std::vector< std::vector< int > > > > > > > indexvec
Variables related to determined which modes have splines and which piggy-back of other modes.
ParameterHandlerGeneric * ParHandler
Pointer to covariance from which we get information about spline params.
void CalcSplineWeights() final
CPU based code which eval weight for each spline.
std::vector< std::vector< std::string > > SplineFileParPrefixNames
void LoadSettingsDir(std::unique_ptr< TFile > &SplineFile)
KS: Load preprocessed Settings.
std::vector< int > coeffindexvec
void cleanUpMemory()
Remove setup variables not needed for spline evaluations.
bool isValidSplineIndex(const std::string &SampleTitle, int iSyst, int iOscChan, int iMode, int iVar1, int iVar2, int iVar3) const
Ensure we have spline for a given bin.
void PrintBinning(TAxis *Axis) const
void PrepareSplineFile(std::string FileName) final
KS: Prepare spline file that can be used for fast loading.
void InvestigateMissingSplines() const
This function will find missing splines in file.
std::vector< int > nSplineParams
std::vector< std::vector< std::vector< int > > > SplineModeVecs
std::vector< int > nOscChans
M3::float_t * xcoeff_arr
x coefficients for each spline
std::vector< std::string > SampleTitles
void PrintSampleDetails(const std::string &SampleTitle) const
Print info like Sample ID of spline params etc.
std::vector< std::string > UniqueSystNames
name of each spline parameter
std::vector< std::vector< SplineInterpolation > > SplineInterpolationTypes
spline interpolation types for each sample. These vectors are from a call to GetSplineInterpolationFr...
std::vector< std::vector< int > > GetEventSplines(const std::string &SampleTitle, int iOscChan, int EventMode, double Var1Val, double Var2Val, double Var3Val)
Return the splines which affect a given event.
void Evaluate() final
CW: This Eval should be used when using two separate x,{y,a,b,c,d} arrays to store the weights; proba...
std::vector< int > Dimensions
std::vector< int > uniquesplinevec_Monolith
Maps single spline object with single parameter.
void PrepareIndexDir(std::unique_ptr< TFile > &SplineFile) const
KS: Prepare Index Info within SplineFile.
void BuildSampleIndexingArray(const std::string &SampleTitle)
std::vector< M3::float_t > weightvec_Monolith
Stores weight from spline evaluation for each single spline.
void AddSample(const std::string &SampleName, const std::string &SampleTitle, const std::vector< std::string > &OscChanFileNames, const std::vector< std::string > &SplineVarNames)
add oscillation channel to spline monolith
std::vector< TAxis * > FindSplineBinning(const std::string &FileName, const std::string &SampleTitle)
Grab histograms with spline binning.
std::vector< std::vector< std::string > > DimensionLabels
std::vector< std::vector< int > > StripDuplicatedModes(const std::vector< std::vector< int > > &InputVector) const
Check if there are any repeated modes. This is used to reduce the number of modes in case many intera...
void LoadSplineFile(std::string FileName) final
KS: Load preprocessed spline file.
void PrepareMonolithDir(std::unique_ptr< TFile > &SplineFile) const
KS: Prepare Monolith Info within SplineFile.
BinnedSplineHandler(ParameterHandlerGeneric *xsec_, MaCh3Modes *Modes_)
Constructor.
void LoadMonolithDir(std::unique_ptr< TFile > &SplineFile)
KS: Load preprocessed Monolith.
std::vector< std::vector< std::vector< TAxis * > > > SplineBinning
std::vector< TSpline3_red * > splinevec_Monolith
holds each spline object before stripping into coefficient monolith
std::vector< int > uniquecoeffindices
Unique coefficient indices.
void PrepareOtherInfoDir(std::unique_ptr< TFile > &SplineFile) const
KS: Prepare Other Info within SplineFile.
void PrepareSettingsDir(std::unique_ptr< TFile > &SplineFile) const
KS: Prepare Settings Info within SplineFile.
MaCh3Modes * Modes
pointer to MaCh3 Mode from which we get spline suffix
void PrintArrayDetails(const std::string &SampleTitle) const
std::vector< std::vector< int > > GlobalSystIndex
This holds the global spline index and is used to grab the current parameter value to evaluate spline...
virtual ~BinnedSplineHandler()
Destructor.
virtual std::vector< std::string > GetTokensFromSplineName(const std::string &FullSplineName)=0
std::vector< std::string > SampleNames
void TransferToMonolith()
flatten multidimensional spline array into proper monolith
std::vector< int > UniqueSystIndices
Global index of each spline param, it allows us to match spline ordering with global.
int GetSampleIndex(const std::string &SampleTitle) const
Get index of sample based on name.
M3::float_t * manycoeff_arr
ybcd coefficients for each spline
Custom exception class used throughout MaCh3.
KS: Class describing MaCh3 modes used in the analysis, it is being initialised from config.
Definition: MaCh3Modes.h:135
int GetNModes() const
KS: Get number of modes, keep in mind actual number is +1 greater due to unknown category.
Definition: MaCh3Modes.h:148
std::string GetSplineSuffixFromMaCh3Mode(const int Index)
DB: Get binned spline mode suffic from MaCh3 Mode.
Definition: MaCh3Modes.cpp:243
const M3::float_t * RetPointer(const int iParam)
DB Pointer return to param position.
YAML::Node GetConfig() const
Getter to return a copy of the YAML node.
Class responsible for handling of systematic error parameters with different types defined in the con...
const std::vector< int > GetGlobalSystIndexFromSampleName(const std::string &SampleName, const SystType Type)
DB Get spline parameters depending on given SampleName.
int GetNumParamsFromSampleName(const std::string &SampleName, const SystType Type)
DB Grab the number of parameters for the relevant SampleName.
const std::vector< std::string > GetParsNamesFromSampleName(const std::string &SampleName, const SystType Type)
DB Grab the parameter names for the relevant SampleName.
const std::vector< std::string > GetSplineParsNamesFromSampleName(const std::string &SampleName)
DB Get spline parameters depending on given SampleName.
const std::vector< SplineInterpolation > GetSplineInterpolationFromSampleName(const std::string &SampleName)
Get the interpolation types for splines affecting a particular SampleName.
const std::vector< std::vector< int > > GetSplineModeVecFromSampleName(const std::string &SampleName)
DB Grab the Spline Modes for the relevant SampleName.
Base class for calculating weight from spline.
Definition: SplineBase.h:27
short int nParams
Number of parameters that have splines.
Definition: SplineBase.h:81
void FindSplineSegment()
CW:Code used in step by step reweighting, Find Spline Segment for each param.
Definition: SplineBase.cpp:44
short int * SplineSegments
Definition: SplineBase.h:77
std::vector< FastSplineInfo > SplineInfoArray
Definition: SplineBase.h:74
float * ParamValues
Store parameter values they are not in FastSplineInfo as in case of GPU we need to copy paste it to G...
Definition: SplineBase.h:79
void LoadFastSplineInfoDir(std::unique_ptr< TFile > &SplineFile)
KS: Load preprocessed FastSplineInfo.
Definition: SplineBase.cpp:167
void PrepareFastSplineInfoDir(std::unique_ptr< TFile > &SplineFile) const
KS: Prepare Fast Spline Info within SplineFile.
Definition: SplineBase.cpp:139
CW: Reduced TSpline3 class.
constexpr static const double _BAD_DOUBLE_
Default value used for double initialisation.
Definition: Core.h:53
double float_t
Definition: Core.h:37
TFile * Open(const std::string &Name, const std::string &Type, const std::string &File, const int Line)
Opens a ROOT file with the given name and mode.
constexpr static const char * float_t_str_repr
Definition: Core.h:40
constexpr static const int _BAD_INT_
Default value used for int initialisation.
Definition: Core.h:55
constexpr T fmaf_t(T x, T y, T z)
Function template for fused multiply-add.
Definition: Core.h:45
void AddPath(std::string &FilePath)
Prepends the MACH3 environment path to FilePath if it is not already present.
Definition: Monitor.cpp:382
int int_t
Definition: Core.h:38