MaCh3  2.8.0
Reference Guide
Public Member Functions | Private Member Functions | Private Attributes | List of all members
UnbinnedSplineHandler Class Reference

Even-by-event class calculating response for spline parameters. It is possible to use GPU acceleration. More...

#include <Splines/UnbinnedSplineHandler.h>

Inheritance diagram for UnbinnedSplineHandler:
[legend]
Collaboration diagram for UnbinnedSplineHandler:
[legend]

Public Member Functions

 UnbinnedSplineHandler (std::vector< std::vector< TResponseFunction_red * > > &MasterSpline, const std::vector< RespFuncType > &SplineType, const bool SaveFlatTree=false, const std::string &_FastSplineName="SplineFile.root", const bool Use_GPU=true)
 Constructor. More...
 
 UnbinnedSplineHandler (const std::string &FileName)
 Constructor where you pass path to preprocessed root FileName. More...
 
virtual ~UnbinnedSplineHandler ()
 Destructor for UnbinnedSplineHandler class. More...
 
void Evaluate () final
 CW: This Eval should be used when using two separate x,{y,a,b,c,d} arrays to store the weights; probably the best one here! Same thing but pass parameter spline segments instead of variations. More...
 
std::string GetName () const override
 Get class name. More...
 
const M3::float_t * RetPointer (const int event) const
 KS: Get pointer to total weight to make fit faster wrooom! More...
 
void SetSplinePointers (std::vector< const M3::float_t * > spline_ParsPointers)
 KS: Set pointers to spline params. More...
 
void PrepareSplineFile (std::string FileName) final
 KS: Prepare spline file that can be used for fast loading. More...
 
void LoadSplineFile (std::string FileName) final
 KS: Load preprocessed spline file. More...
 
- Public Member Functions inherited from SplineBase
 SplineBase (const bool Use_GPU=true)
 Constructor. More...
 
virtual ~SplineBase ()
 Destructor. More...
 
short int GetNParams () const
 Get number of spline parameters. More...
 
void SynchroniseMemTransfer () const
 KS: After calculations are done on GPU we copy memory to CPU. This operation is asynchronous meaning while memory is being copied some operations are being carried. Memory must be copied before actual reweight. This function make sure all has been copied. More...
 

Private Member Functions

void Initialise ()
 KS: Set everything to null etc. More...
 
void ScanMasterSpline (std::vector< std::vector< TResponseFunction_red * > > &MasterSpline, unsigned int &nEvents, short int &MaxPoints, short int &numParams, int &nSplines, unsigned int &NSplinesValid, unsigned int &numKnots, unsigned int &nTF1Valid, unsigned int &nTF1_coeff, const std::vector< RespFuncType > &SplineType)
 CW: Function to scan through the MasterSpline of TSpline3. More...
 
void PrepareForGPU (std::vector< std::vector< TResponseFunction_red * > > &MasterSpline, const std::vector< RespFuncType > &SplineType)
 CW: Prepare the TSpline3_red objects for the GPU. More...
 
void MoveToGPU ()
 CW: The shared initialiser from constructors of TResponseFunction_red. More...
 
void PrintInitialsiation () const
 KS: Print info about how much knots etc has been initialised. More...
 
void GetSplineCoeff_SepMany (TSpline3_red *&spl, int &nPoints, float *&xArray, float *&manyArray) const
 CW: This loads up coefficients into two arrays: one x array and one yabcd array. More...
 
void CalcSplineWeights () final
 CPU based code which eval weight for each spline. More...
 
void CalcTotalEventWeight ()
 Calc total event weight. More...
 

Private Attributes

unsigned int NEvents
 Number of events. More...
 
unsigned int NTF1_valid
 Number of valid TF1. More...
 
unsigned int nKnots
 Sum of all knots over all splines. More...
 
unsigned int nTF1coeff
 Sum of all coefficients over all TF1. More...
 
float * cpu_weights_spline_var
 CPU arrays to hold weight for each spline. More...
 
float * cpu_weights_tf1_var
 CPU arrays to hold weight for each TF1. More...
 
M3::float_t * cpu_total_weights
 KS: This holds the total CPU weights that gets read in SampleHandler. More...
 
std::vector< unsigned int > cpu_nParamPerEvent
 KS: CPU map keeping track how many parameters applies to each event, we keep two numbers here {number of splines per event, index where splines start for a given event}. More...
 
std::vector< unsigned int > cpu_nParamPerEvent_tf1
 KS: CPU map keeping track how many parameters applies to each event, we keep two numbers here {number of TF1 per event, index where TF1 start for a given event}. More...
 
SplineMonoStruct * cpu_monolith
 KS: Store info about Spline monolith, this allow to obtain better step time. As all necessary information for spline weight calculation are here meaning better cache hits. More...
 
std::vector< float > cpu_coeff_TF1_many
 CPU arrays to hold TF1 coefficients. More...
 
std::vector< short int > cpu_nPoints_arr
 CPU arrays to hold number of points. More...
 
std::vector< short int > cpu_paramNo_TF1_arr
 CW: CPU array with the number of points per spline (not per spline point!) More...
 
bool SaveSplineFile
 Flag telling whether we are saving spline monolith into handy root file. More...
 
std::string FastSplineName
 Name of Fast Spline to which will be saved. More...
 

Additional Inherited Members

- Protected Member Functions inherited from SplineBase
void FindSplineSegment ()
 CW:Code used in step by step reweighting, Find Spline Segment for each param. More...
 
void PrepareFastSplineInfoDir (std::unique_ptr< TFile > &SplineFile) const
 KS: Prepare Fast Spline Info within SplineFile. More...
 
void LoadFastSplineInfoDir (std::unique_ptr< TFile > &SplineFile)
 KS: Load preprocessed FastSplineInfo. More...
 
void GetTF1Coeff (TF1_red *&spl, int &nPoints, float *&coeffs) const
 CW: Gets the polynomial coefficients for TF1. More...
 
void SetupSegments ()
 Since we find segment before actual reweight and sometimes we want to copy it to GPU we have different functionality depending if GPU or CPU. More...
 
- Protected Attributes inherited from SplineBase
std::vector< FastSplineInfo > SplineInfoArray
 
short int * SplineSegments
 
float * ParamValues
 Store parameter values they are not in FastSplineInfo as in case of GPU we need to copy paste it to GPU. More...
 
short int nParams
 Number of parameters that have splines. More...
 
short int _max_knots
 Max knots for production. More...
 
unsigned int NSplines_valid
 Number of valid splines. More...
 
SplineMonolithGPU * gpu_monolith
 KS: Store info about Spline monolith, this allow to obtain better step time. As all necessary information for spline weight calculation are here meaning better cache hits. More...
 
bool useGPU
 Whether to use GPU or not. More...
 

Detailed Description

Even-by-event class calculating response for spline parameters. It is possible to use GPU acceleration.

Author
Clarence Wret
Kamil Skwarczynski

Definition at line 8 of file UnbinnedSplineHandler.h.

Constructor & Destructor Documentation

◆ UnbinnedSplineHandler() [1/2]

UnbinnedSplineHandler::UnbinnedSplineHandler ( std::vector< std::vector< TResponseFunction_red * > > &  MasterSpline,
const std::vector< RespFuncType > &  SplineType,
const bool  SaveFlatTree = false,
const std::string &  _FastSplineName = "SplineFile.root",
const bool  Use_GPU = true 
)

Constructor.

Parameters
MasterSplineVector of TSpline3 pointers which we strip back
SplineTypeWhether object is TSpline3 or TF1
SaveFlatTreeWhether we want to save monolith into speedy flat tree
_FastSplineNameName to which spline file will be saved

Definition at line 27 of file UnbinnedSplineHandler.cpp.

31  : SplineBase(Use_GPU) {
32 // *****************************************
33  //KS: If true it will save spline monolith into huge ROOT file
34  SaveSplineFile = SaveFlatTree;
35  FastSplineName = _FastSplineName;
36  Initialise();
37 
38  // Convert the TSpline3 pointers to the reduced form and call the reduced constructor
39  PrepareForGPU(MasterSpline, SplineType);
40 }
SplineBase(const bool Use_GPU=true)
Constructor.
Definition: SplineBase.cpp:11
void PrepareForGPU(std::vector< std::vector< TResponseFunction_red * > > &MasterSpline, const std::vector< RespFuncType > &SplineType)
CW: Prepare the TSpline3_red objects for the GPU.
void Initialise()
KS: Set everything to null etc.
bool SaveSplineFile
Flag telling whether we are saving spline monolith into handy root file.
std::string FastSplineName
Name of Fast Spline to which will be saved.

◆ UnbinnedSplineHandler() [2/2]

UnbinnedSplineHandler::UnbinnedSplineHandler ( const std::string &  FileName)

Constructor where you pass path to preprocessed root FileName.

Parameters
FileNamepath to pre-processed root file containing stripped monolith info

Definition at line 424 of file UnbinnedSplineHandler.cpp.

425  : SplineBase() {
426 // *****************************************
427  Initialise();
428  MACH3LOG_INFO("-- GPUING WITH {X} and {Y,B,C,D} arrays and master spline containing TSpline3_red");
429  // Convert the TSpline3 pointers to the reduced form and call the reduced constructor
430  LoadSplineFile(FileName);
431 }
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
void LoadSplineFile(std::string FileName) final
KS: Load preprocessed spline file.

◆ ~UnbinnedSplineHandler()

UnbinnedSplineHandler::~UnbinnedSplineHandler ( )
virtual

Destructor for UnbinnedSplineHandler class.

Definition at line 593 of file UnbinnedSplineHandler.cpp.

593  {
594 // *****************************************
595  #ifdef MaCh3_CUDA
596  if(useGPU) {
597  //KS: Since we declared them using CUDA alloc we have to free memory using also cuda functions
599  delete gpu_monolith;
600  } else
601  #endif
602  {
603  if(SplineSegments != nullptr) delete[] SplineSegments;
604  if(ParamValues != nullptr) delete[] ParamValues;
605  if(cpu_total_weights != nullptr) delete[] cpu_total_weights;
606  }
607 
608  if(cpu_weights_spline_var != nullptr) delete[] cpu_weights_spline_var;
609  if(cpu_weights_tf1_var != nullptr) delete[] cpu_weights_tf1_var;
610 
611  if(cpu_monolith != nullptr) delete cpu_monolith;
612 }
SplineMonolithGPU * gpu_monolith
KS: Store info about Spline monolith, this allow to obtain better step time. As all necessary informa...
Definition: SplineBase.h:120
short int * SplineSegments
Definition: SplineBase.h:109
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:111
bool useGPU
Whether to use GPU or not.
Definition: SplineBase.h:123
__host__ void CleanupPinnedMemory(M3::float_t *cpu_total_weights, short int *segment, float *vals)
Clean up pinned variables at CPU.
float * cpu_weights_tf1_var
CPU arrays to hold weight for each TF1.
float * cpu_weights_spline_var
CPU arrays to hold weight for each spline.
SplineMonoStruct * cpu_monolith
KS: Store info about Spline monolith, this allow to obtain better step time. As all necessary informa...
M3::float_t * cpu_total_weights
KS: This holds the total CPU weights that gets read in SampleHandler.

Member Function Documentation

◆ CalcSplineWeights()

void UnbinnedSplineHandler::CalcSplineWeights ( )
finalprivatevirtual

CPU based code which eval weight for each spline.

Splines are stored using a flat monolithic structure. The monolith is organised as follows:

Spline 0
Segment 0: [ Y | B | C | D ]
Segment 1: [ Y | B | C | D ]
Segment 2: [ Y | B | C | D ]
Spline 1
Segment 0: [ Y | B | C | D ]
Segment 1: [ Y | B | C | D ]
Segment 2: [ Y | B | C | D ]
Spline 2
Segment 0: [ Y | B | C | D ]
Segment 1: [ Y | B | C | D ]
Segment 2: [ Y | B | C | D ]
...

Once coefficient are grabbed we calculate weight using:

weight = Y + B*dx + C*dx^2 + D*dx^3;

Implements SplineBase.

Definition at line 695 of file UnbinnedSplineHandler.cpp.

695  {
696 //*********************************************************
697  #ifdef MULTITHREAD
698  //KS: Open parallel region
699  #pragma omp parallel
700  {
701  #endif
702  //KS: First we calculate
703  #ifdef MULTITHREAD
704  #pragma omp for simd nowait
705  #endif
706  for (unsigned int splineNum = 0; splineNum < NSplines_valid; ++splineNum)
707  {
708  //CW: Which Parameter we are accessing
709  const short int Param = cpu_monolith->paramNo_arr[splineNum];
710 
711  //CW: Avoids doing costly binary search on GPU
712  const short int segment = SplineSegments[Param];
713 
714  //KS: Segment for coeff_x is simply parameter*max knots + segment as each parameters has the same spacing
715  const short int segment_X = short(Param*_max_knots+segment);
716 
717  //KS: Find knot position in out monolithical structure
718  const unsigned int CurrentKnotPos = (cpu_monolith->nKnots_arr[splineNum] + segment) * _nCoeff_;
719 
720  // We've read the segment straight from CPU and is saved in segment_gpu
721  // polynomial parameters from the monolithic splineMonolith
722  const float fY = cpu_monolith->coeff_many[CurrentKnotPos];
723  const float fB = cpu_monolith->coeff_many[CurrentKnotPos + 1];
724  const float fC = cpu_monolith->coeff_many[CurrentKnotPos + 2];
725  const float fD = cpu_monolith->coeff_many[CurrentKnotPos + 3];
726  // The is the variation itself (needed to evaluate variation - stored spline point = dx)
727  const float dx = ParamValues[Param] - cpu_monolith->coeff_x[segment_X];
728 
729  //CW: Wooow, let's use some fancy intrinsic and pull down the processing time by <1% from normal multiplication! HURRAY
730  cpu_weights_spline_var[splineNum] = fmaf(dx, fmaf(dx, fmaf(dx, fD, fC), fB), fY);
731  // Or for the more "easy to read" version:
732  //cpu_weights_spline_var[splineNum] = (fY+dx*(fB+dx*(fC+dx*fD)));
733  }
734 
735  #ifdef MULTITHREAD
736  #pragma omp for simd
737  #endif
738  for (unsigned int tf1Num = 0; tf1Num < NTF1_valid; ++tf1Num)
739  {
740  // The is the variation itself (needed to evaluate variation - stored spline point = dx)
741  const float x = ParamValues[cpu_paramNo_TF1_arr[tf1Num]];
742 
743  // Read the coefficients
744  const unsigned int TF1_Index = tf1Num * _nTF1Coeff_;
745  const float a = cpu_coeff_TF1_many[TF1_Index];
746  const float b = cpu_coeff_TF1_many[TF1_Index + 1];
747 
748  cpu_weights_tf1_var[tf1Num] = fmaf(a, x, b);
749  // cpu_weights_tf1_var[tf1Num] = a*x + b;
750  //cpu_weights_tf1_var[splineNum] = 1 + a*x + b*x*x + c*x*x*x + d*x*x*x*x + e*x*x*x*x*x;
751  }
752  #ifdef MULTITHREAD
753  //KS: End parallel region
754  }
755  #endif
756 }
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
constexpr int _nTF1Coeff_
KS: For TF1 we store at most 5 coefficients, we could make it more flexible but for now define it her...
Definition: SplineCommon.h:20
unsigned int NSplines_valid
Number of valid splines.
Definition: SplineBase.h:117
short int _max_knots
Max knots for production.
Definition: SplineBase.h:115
unsigned int NTF1_valid
Number of valid TF1.
std::vector< short int > cpu_paramNo_TF1_arr
CW: CPU array with the number of points per spline (not per spline point!)
std::vector< float > cpu_coeff_TF1_many
CPU arrays to hold TF1 coefficients.
std::vector< unsigned int > nKnots_arr
KS: CPU Number of knots per spline.
Definition: SplineCommon.h:73
std::vector< float > coeff_x
KS: CPU arrays to hold X coefficient.
Definition: SplineCommon.h:67
std::vector< float > coeff_many
CPU arrays to hold other coefficients.
Definition: SplineCommon.h:70
std::vector< short int > paramNo_arr
CW: CPU array with the number of points per spline (not per spline point!)
Definition: SplineCommon.h:76

◆ CalcTotalEventWeight()

void UnbinnedSplineHandler::CalcTotalEventWeight ( )
private

Calc total event weight.

Definition at line 760 of file UnbinnedSplineHandler.cpp.

760  {
761 //*********************************************************
762  #ifdef MULTITHREAD
763  #pragma omp parallel for
764  #endif
765  for (unsigned int EventNum = 0; EventNum < NEvents; ++EventNum)
766  {
767  float totalWeight = 1.0f; // Initialize total weight for each event
768 
769  const unsigned int Offset = 2 * EventNum;
770 
771  // Extract the parameters for the current event
772  const unsigned int startIndex = cpu_nParamPerEvent[Offset + 1];
773  const unsigned int numParams = cpu_nParamPerEvent[Offset];
774 
775  // Compute total weight for the current event
776  #ifdef MULTITHREAD
777  #pragma omp simd reduction(*:totalWeight)
778  #endif
779  for (unsigned int id = 0; id < numParams; ++id) {
780  totalWeight *= cpu_weights_spline_var[startIndex + id];
781  }
782  //Now TF1
783  // Extract the parameters for the current event
784  const unsigned int startIndex_tf1 = cpu_nParamPerEvent_tf1[Offset + 1];
785  const unsigned int numParams_tf1 = cpu_nParamPerEvent_tf1[Offset];
786 
787  // Compute total weight for the current event
788  #ifdef MULTITHREAD
789  #pragma omp simd reduction(*:totalWeight)
790  #endif
791  for (unsigned int id = 0; id < numParams_tf1; ++id) {
792  totalWeight *= cpu_weights_tf1_var[startIndex_tf1 + id];
793  }
794 
795  // Store the total weight for the current event
796  cpu_total_weights[EventNum] = static_cast<M3::float_t>(totalWeight);
797  }
798 }
std::vector< unsigned int > cpu_nParamPerEvent
KS: CPU map keeping track how many parameters applies to each event, we keep two numbers here {number...
std::vector< unsigned int > cpu_nParamPerEvent_tf1
KS: CPU map keeping track how many parameters applies to each event, we keep two numbers here {number...
unsigned int NEvents
Number of events.
double float_t
Definition: Core.h:37

◆ Evaluate()

void UnbinnedSplineHandler::Evaluate ( )
finalvirtual

CW: This Eval should be used when using two separate x,{y,a,b,c,d} arrays to store the weights; probably the best one here! Same thing but pass parameter spline segments instead of variations.

Implements SplineBase.

Definition at line 670 of file UnbinnedSplineHandler.cpp.

670  {
671 // *****************************************
672  // There's a parameter mapping that goes from spline parameter to a global parameter index
673  // Find the spline segments
675  #ifdef MaCh3_CUDA
676  if (useGPU) { // GPU calculations
677  // The main call to the GPU
680  ParamValues,
682  } else
683  #endif
684  { // CPU-only calculations
685  //KS: Huge MP loop over all valid splines
687 
688  //KS: Huge MP loop over all events calculating total weight per event
690  }
691 }
void FindSplineSegment()
CW:Code used in step by step reweighting, Find Spline Segment for each param.
Definition: SplineBase.cpp:58
__host__ void RunGPU_SplineMonolith_Unbinned(M3::float_t *cpu_total_weights, float *vals, short int *segment)
Run the GPU code for the separate many arrays. As in separate {x}, {y,b,c,d} arrays Pass the segment ...
void CalcSplineWeights() final
CPU based code which eval weight for each spline.
void CalcTotalEventWeight()
Calc total event weight.

◆ GetName()

std::string UnbinnedSplineHandler::GetName ( ) const
inlineoverridevirtual

Get class name.

Reimplemented from SplineBase.

Definition at line 30 of file UnbinnedSplineHandler.h.

30 {return "SplineMonolith";};

◆ GetSplineCoeff_SepMany()

void UnbinnedSplineHandler::GetSplineCoeff_SepMany ( TSpline3_red *&  spl,
int &  nPoints,
float *&  xArray,
float *&  manyArray 
) const
private

CW: This loads up coefficients into two arrays: one x array and one yabcd array.

CW: This should maximize our cache hits!

Parameters
splpointer to TSpline3_red
nPointsnumber of knots
xArrayarray X value for each knot
manyArrayArray holding coefficients for each knot

Definition at line 618 of file UnbinnedSplineHandler.cpp.

618  {
619 // *****************************************
620  // Initialise all arrays to 1.0
621  for (int i = 0; i < _max_knots; ++i) {
622  xArray[i] = 1.0;
623  for (int j = 0; j < _nCoeff_; j++) {
624  manyArray[i*_nCoeff_+j] = 1.0;
625  }
626  }
627  // Get number of points in spline
628  int Np = spl->GetNp();
629  // If spline is flat, set number of knots to 1.0,
630  // This is used later to expedite the calculations for flat splines
631  // tmpArray[0] is number of knots
632  nPoints = Np;
633  if (Np > _max_knots) {
634  MACH3LOG_ERROR("Error, number of points is greater than saved {}", _max_knots);
635  MACH3LOG_ERROR("This _WILL_ cause problems with GPU splines and _SHOULD_ be fixed!");
636  MACH3LOG_ERROR("nPoints = {}, _max_knots = {}", nPoints, _max_knots);
637  throw MaCh3Exception(__FILE__ , __LINE__ );
638  }
639 
640  // The coefficients we're writing to
641  M3::float_t x, y, b, c, d;
642  // TSpline3 can only take doubles, not floats
643  // But our GPU is slow with doubles, so need to cast to float
644  for(int i = 0; i < Np; i++) {
645  // Get the coefficients from the TSpline3 object
646  spl->GetCoeff(i, x, y, b, c, d);
647  // Write the arrays
648  xArray[i] = float(x);
649  manyArray[i*_nCoeff_] = float(y); // 4 because manyArray stores y,b,c,d
650  manyArray[i*_nCoeff_+1] = float(b);
651  manyArray[i*_nCoeff_+2] = float(c);
652  manyArray[i*_nCoeff_+3] = float(d);
653  if((xArray[i] == -999) || (manyArray[i*_nCoeff_] == -999) || (manyArray[i*_nCoeff_ +1] == -999) || (manyArray[i*_nCoeff_+2] == -999) || (manyArray[i*_nCoeff_+3] == -999)){
654  MACH3LOG_ERROR("*********** Bad params in {} ************", __func__);
655  MACH3LOG_ERROR("pre cast to float (x, y, b, c, d) = {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}", x, y, b, c, d);
656  MACH3LOG_ERROR("pre cast to float (x, y, b, c, d) = {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}", xArray[i], manyArray[i*_nCoeff_], manyArray[i*_nCoeff_+1], manyArray[i*_nCoeff_+2], manyArray[i*_nCoeff_+3]);
657  MACH3LOG_ERROR("This will cause problems when preparing for GPU");
658  MACH3LOG_ERROR("***************************************************************");
659  }
660  }
661 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
Custom exception class used throughout MaCh3.
void GetCoeff(int segment, M3::float_t &x, M3::float_t &y, M3::float_t &b, M3::float_t &c, M3::float_t &d) const
CW: Get the coefficient of a given segment.
M3::int_t GetNp() const override
CW: Get the number of points.

◆ Initialise()

void UnbinnedSplineHandler::Initialise ( )
private

KS: Set everything to null etc.

Definition at line 11 of file UnbinnedSplineHandler.cpp.

11  {
12 // *****************************************
14 
15  nKnots = 0;
16  nTF1coeff = 0;
17  NEvents = 0;
18  NTF1_valid = 0;
19 
20  cpu_weights_spline_var = nullptr;
21  cpu_weights_tf1_var = nullptr;
22 
23  cpu_total_weights = nullptr;
24 }
unsigned int nTF1coeff
Sum of all coefficients over all TF1.
unsigned int nKnots
Sum of all knots over all splines.
KS: Struct storing information for spline monolith.
Definition: SplineCommon.h:61

◆ LoadSplineFile()

void UnbinnedSplineHandler::LoadSplineFile ( std::string  FileName)
finalvirtual

KS: Load preprocessed spline file.

Parameters
FileNamePath to ROOT file with predefined reduced Spline Monolith

Implements SplineBase.

Definition at line 435 of file UnbinnedSplineHandler.cpp.

435  {
436 // *****************************************
437  M3::AddPath(FileName);
438  auto SplineFile = std::make_unique<TFile>(FileName.c_str(), "OPEN");
439  TTree *Settings = SplineFile->Get<TTree>("Settings");
440  TTree *Monolith_TF1 = SplineFile->Get<TTree>("Monolith_TF1");
441  TTree *EventInfo = SplineFile->Get<TTree>("EventInfo");
442  TTree *SplineTree = SplineFile->Get<TTree>("SplineTree");
443 
444  unsigned int NEvents_temp;
445  short int nParams_temp;
446  int _max_knots_temp;
447  unsigned int nKnots_temp;
448  unsigned int NSplines_valid_temp;
449  unsigned int nTF1Valid_temp;
450  unsigned int nTF1coeff_temp;
451 
452  Settings->SetBranchAddress("NEvents", &NEvents_temp);
453  Settings->SetBranchAddress("nParams", &nParams_temp);
454  Settings->SetBranchAddress("_max_knots", &_max_knots_temp);
455  Settings->SetBranchAddress("nKnots", &nKnots_temp);
456  Settings->SetBranchAddress("NSplines_valid", &NSplines_valid_temp);
457  Settings->SetBranchAddress("NTF1_valid", &nTF1Valid_temp);
458  Settings->SetBranchAddress("nTF1coeff", &nTF1coeff_temp);
459 
460  Settings->GetEntry(0);
461 
462  NEvents = NEvents_temp;
463  nParams = nParams_temp;
464  _max_knots = static_cast<short int>(_max_knots_temp);
465  nKnots = nKnots_temp;
466  NSplines_valid = NSplines_valid_temp;
467  NTF1_valid = nTF1Valid_temp;
468  nTF1coeff = nTF1coeff_temp;
469 
470  cpu_nParamPerEvent.resize(2*NEvents);
473 
474  //KS: This is tricky as this variable use both by CPU and GPU, however if use CUDA we use cudaMallocHost
475  if (!useGPU) {
477  cpu_weights_spline_var = new float[NSplines_valid]();
478  cpu_weights_tf1_var = new float[NTF1_valid]();
479  }
480 
481  SplineTree->SetBranchAddress("SplineObject", &cpu_monolith);
482  SplineTree->GetEntry(0);
483 
484  float coeff_tf1 = 0.;
485  Monolith_TF1->SetBranchAddress("cpu_coeff_TF1_many", &coeff_tf1);
486  for(unsigned int i = 0; i < nTF1coeff; i++)
487  {
488  Monolith_TF1->GetEntry(i);
489  cpu_coeff_TF1_many[i] = coeff_tf1;
490  }
491 
492  unsigned int nParamPerEvent = 0;
493  unsigned int nParamPerEvent_tf1 = 0;
494 
495  EventInfo->SetBranchAddress("cpu_nParamPerEvent", &nParamPerEvent);
496  EventInfo->SetBranchAddress("cpu_nParamPerEvent_tf1", &nParamPerEvent_tf1);
497  for(unsigned int i = 0; i < 2*NEvents; i++)
498  {
499  EventInfo->GetEntry(i);
500  cpu_nParamPerEvent[i] = nParamPerEvent;
501  cpu_nParamPerEvent_tf1[i] = nParamPerEvent_tf1;
502  }
503 
504  LoadFastSplineInfoDir(SplineFile);
505 
506  SplineFile->Close();
507 
508  // Print some info; could probably make this to a separate function
510 
511  MoveToGPU();
512 
513  SetupSegments();
514 }
short int nParams
Number of parameters that have splines.
Definition: SplineBase.h:113
void LoadFastSplineInfoDir(std::unique_ptr< TFile > &SplineFile)
KS: Load preprocessed FastSplineInfo.
Definition: SplineBase.cpp:181
void SetupSegments()
Since we find segment before actual reweight and sometimes we want to copy it to GPU we have differen...
Definition: SplineBase.cpp:208
void PrintInitialsiation() const
KS: Print info about how much knots etc has been initialised.
void MoveToGPU()
CW: The shared initialiser from constructors of TResponseFunction_red.
void AddPath(std::string &FilePath)
Prepends the MACH3 environment path to FilePath if it is not already present.
Definition: Monitor.cpp:382
Stores info about each MC event used during reweighting routine.
Definition: EventInfo.h:13

◆ MoveToGPU()

void UnbinnedSplineHandler::MoveToGPU ( )
private

CW: The shared initialiser from constructors of TResponseFunction_red.

Definition at line 231 of file UnbinnedSplineHandler.cpp.

231  {
232 // *****************************************
233  #ifdef MaCh3_CUDA
234  if(!useGPU) return;
235  unsigned int event_size_max = _max_knots * nParams;
236  MACH3LOG_INFO("Total size = {:.2f} MB memory on CPU to move to GPU",
237  (double(sizeof(float) * nKnots * _nCoeff_) + double(sizeof(float) * event_size_max) / 1.E6 +
238  double(sizeof(short int) * NSplines_valid)) / 1.E6);
239  MACH3LOG_INFO("Total TF1 size = {:.2f} MB memory on CPU to move to GPU",
240  double(sizeof(float) * NTF1_valid * _nTF1Coeff_) / 1.E6);
241  MACH3LOG_INFO("GPU weight array (GPU->CPU every step) = {:.2f} MB", static_cast<double>(sizeof(float)) * (NSplines_valid + NTF1_valid) / 1.0e6);
242  MACH3LOG_INFO("Since you are running Total event weight mode then GPU weight array (GPU->CPU every step) = {:.2f} MB",
243  double(sizeof(float) * NEvents) / 1.E6);
244  MACH3LOG_INFO("Parameter value array (CPU->GPU every step) = {:.4f} MB", double(sizeof(float) * nParams) / 1.E6);
245  //CW: With the new set-up we have: 1 coefficient array of size coeff_array_size, all same size
246  // 1 coefficient array of size coeff_array_size*4, holding y,b,c,d in order (y11,b11,c11,d11; y12,b12,c12,d12;...) where ynm is n = spline number, m = spline point. Should really make array so that order is (y11,b11,c11,d11; y21,b21,c21,d21;...) because it will optimise cache hits I think; try this if you have time
247  // return gpu_weights
248 
250 
251  // The gpu_XY arrays don't actually need initialising, since they are only placeholders for what we'll move onto the GPU. As long as we cudaMalloc the size of the arrays correctly there shouldn't be any problems
252  // Can probably make this a bit prettier but will do for now
253  // Could be a lot smaller of a function...
255  nKnots, // How many entries in coefficient array (*4 for the "many" array)
256  NSplines_valid, // What's the number of splines we have (also number of entries in gpu_nPoints_arr)
257  NTF1_valid,
258  event_size_max //Knots times event number of unique splines
259  );
260 
263  NEvents
264  );
265 
266  // Move number of splines and spline size to constant GPU memory; every thread does not need a copy...
267  // The implementation lives in splines/gpuSplineUtils.cu
268  // The GPU splines don't actually need declaring but is good for demonstration, kind of
269  // fixed by passing const reference
271  cpu_monolith,
272 
273  // TFI related now
276  NEvents,
279  nParams,
281  _max_knots,
282  nKnots,
283  NTF1_valid);
284 
285  // Delete all the coefficient arrays from the CPU once they are on the GPU
290  delete cpu_monolith;
291  cpu_monolith = nullptr;
292  MACH3LOG_INFO("Good GPU loading");
293  #endif
294 }
void CleanVector(T &)
Base case: do nothing for non-vector types.
Class responsible for calculating spline weight on GPU.
__host__ void InitGPU_SplineMonolith(unsigned int total_nknots, unsigned int n_splines, unsigned int n_tf1, int Eve_size)
Allocate memory on gpu for spline monolith.
__host__ void CopyToGPU_SplineMonolith_Unbinned(const SplineMonoStruct *cpu_spline_handler, const std::vector< float > &cpu_many_array_TF1, const std::vector< short int > &cpu_paramNo_arr_TF1, const int n_events, const std::vector< unsigned int > &cpu_nParamPerEvent, const std::vector< unsigned int > &cpu_nParamPerEvent_TF1, const int n_params, const unsigned int n_splines, const short int spline_size, const unsigned int total_nknots, const unsigned int n_tf1)
Copies data from CPU to GPU for the spline monolith.
__host__ void InitGPU_Unbinned_SplineMonolith(M3::float_t **cpu_total_weights, int n_events)
Allocate memory on gpu for spline monolith.

◆ PrepareForGPU()

void UnbinnedSplineHandler::PrepareForGPU ( std::vector< std::vector< TResponseFunction_red * > > &  MasterSpline,
const std::vector< RespFuncType > &  SplineType 
)
private

CW: Prepare the TSpline3_red objects for the GPU.

Parameters
MasterSplineVector of TResponseFunction_red pointers which we strip back

Definition at line 44 of file UnbinnedSplineHandler.cpp.

44  {
45 // *****************************************
46  // Scan for the max number of knots, the number of events (number of splines), and number of parameters
47  int maxnSplines = 0;
48  ScanMasterSpline(MasterSpline,
49  NEvents,
50  _max_knots,
51  nParams,
52  maxnSplines,
54  nKnots,
55  NTF1_valid,
56  nTF1coeff,
57  SplineType);
58 
59  MACH3LOG_INFO("Found {} events", NEvents);
60  MACH3LOG_INFO("Found {} knots at max", _max_knots);
61  MACH3LOG_INFO("Found {} parameters", nParams);
62  MACH3LOG_INFO("Found {} maximum number of splines in an event", maxnSplines);
63  MACH3LOG_INFO("Found total {} knots in all splines", nKnots);
64  MACH3LOG_INFO("Number of splines = {}", NSplines_valid);
65  MACH3LOG_INFO("Found total {} coeffs in all TF1", nTF1coeff);
66  MACH3LOG_INFO("Number of TF1 = {}", NTF1_valid);
67 
68  unsigned int event_size_max = _max_knots * nParams;
69  // Declare the {x}, {y,b,c,d} arrays for all possible splines which the event has
70  // We'll filter off the flat and "disabled" (e.g. CCQE event should not have MARES spline) ones in the next for loop, but need to declare these beasts here
71 
72  // Declare the {y,b,c,d} for each knot
73  // float because GPU precision (could change to double, but will incur significant speed reduction on GPU unless you're very rich!)
74  cpu_monolith->coeff_many.resize(nKnots*_nCoeff_); // *4 because we store y,b,c,d parameters in this array
75  //KS: For x coeff we assume that for given dial (MAQE) spacing is identical,
76  // here we are sloppy and assume each dial has the same number of knots, not a big problem
77  cpu_monolith->coeff_x.resize(event_size_max, -999);
78 
79  //CW: With TF1 we only save the coefficients and the order of the polynomial
80  // Makes most sense to have one large monolithic array, but then it becomes impossible to tell apart a coefficient from a "number of points". So have two arrays: one of coefficients and one of number of points
81  // Let's first assume all are of _max_knots size
82  // Now declare the arrays for each point in the valid splines which the event actually has (i.e. include the splines that the event undergoes)
83  // Also make array with the number of points per spline (not per spline point!)
84  // float because GPU precision (could change to double, but will incur significant speed reduction on GPU unless you're very rich!)
86  cpu_coeff_TF1_many.resize(nTF1coeff); // *5 because this array holds a,b,c,d,e parameters
87 
88  //KS: Map keeping track how many parameters applies to each event, we keep two numbers here {number of splines per event, index where splines start for a given event}
89  cpu_nParamPerEvent.resize(2 * NEvents, -1);
90  cpu_nParamPerEvent_tf1.resize(2 * NEvents, -1);
91 
92  // Make array with the number of points per spline (not per spline point!)
94  //KS: And array which tells where each spline stars in a big monolith array, sort of knot map
97 
98  // Temporary arrays to hold the coefficients for each spline
99  // We get one x, one y, one b,... for each point, so only need to be _max_knots big
100  //KS: Some params has less splines but this is all right main array will get proper number while this temp will be deleted
101  float *x_tmp = new float[_max_knots]();
102  float *many_tmp = new float[_max_knots*_nCoeff_]();
103  float *temp_coeffs = new float[_nTF1Coeff_]();
104 
105  // Count the number of events
106  unsigned int KnotCounter = 0;
107  unsigned int TF1PointsCounter = 0;
108  unsigned int NSplinesCounter = 0;
109  unsigned int TF1sCounter = 0;
110  int ParamCounter = 0;
111  int ParamCounterGlobal = 0;
112  int ParamCounter_TF1 = 0;
113  int ParamCounterGlobalTF1 = 0;
114  // Loop over events and extract the spline coefficients
115  for(unsigned int EventCounter = 0; EventCounter < MasterSpline.size(); ++EventCounter) {
116  // Structure of MasterSpline is std::vector<std::vector<TSpline3*>>
117  // A conventional iterator to count which parameter a given spline should be applied to
118  for(unsigned int ParamNumber = 0; ParamNumber < MasterSpline[EventCounter].size(); ++ParamNumber) {
119  // If nullptr we don't have this spline for the event, so move to next spline
120  if (MasterSpline[EventCounter][ParamNumber] == nullptr) continue;
121 
122  if(SplineType[ParamNumber] == kTSpline3_red)
123  {
124  //KS: how much knots each spline has
125  int nPoints_tmp = 0;
126  // Get a pointer to the current spline for this event
127  TResponseFunction_red* TespFunc = MasterSpline[EventCounter][ParamNumber];
128  TSpline3_red* CurrSpline = static_cast<TSpline3_red*>(TespFunc);
129 
130  // If the number of knots are greater than 2 the spline is not a dummy and we should extract coefficients to load onto the GPU
131  GetSplineCoeff_SepMany(CurrSpline, nPoints_tmp, x_tmp, many_tmp);
132 
133  //KS: One knot means flat spline so ignore
134  if (nPoints_tmp == 1) continue;
135  for (int j = 0; j < _max_knots; ++j) {
136  cpu_monolith->coeff_x[ParamNumber*_max_knots + j] = x_tmp[j];
137  }
138  //KS: Contrary to X coeff we keep for other coeff only filled knots, there is no much gain for doing so for x coeff
139  for (int j = 0; j < nPoints_tmp; ++j) {
140  for (int k = 0; k < _nCoeff_; k++) {
141  cpu_monolith->coeff_many[KnotCounter*_nCoeff_ + j*_nCoeff_ + k] = many_tmp[j*_nCoeff_+k];
142  }
143  }
144  // Set the parameter number for this spline
145  cpu_monolith->paramNo_arr[NSplinesCounter] = short(ParamNumber);
146  //KS: Fill map when each spline starts
147  cpu_monolith->nKnots_arr[NSplinesCounter] = KnotCounter;
148  KnotCounter += nPoints_tmp;
149 
150  ++ParamCounter;
151  // Increment the counter for the number of good splines we have
152  ++NSplinesCounter;
153  }
154  else if (SplineType[ParamNumber] == kTF1_red)
155  {
156  // Don't actually use this ever -- we give each spline the maximum number of points found in all splines
157  int nPoints_tmp = 0;
158  // Get a pointer to the current spline for this event
159  TF1_red* CurrSpline = dynamic_cast<TF1_red*>(MasterSpline[EventCounter][ParamNumber]);
160 
161  // If the number of knots are greater than 2 the spline is not a dummy and we should extract coefficients to load onto the GPU
162  GetTF1Coeff(CurrSpline, nPoints_tmp, temp_coeffs);
163  for (int j = 0; j < _nTF1Coeff_; ++j) {
164  cpu_coeff_TF1_many[TF1PointsCounter+j] = temp_coeffs[j];
165  }
166  // Save the number of points for this spline
167  cpu_nPoints_arr[TF1sCounter] = short(nPoints_tmp);
168 
169  TF1PointsCounter += nPoints_tmp;
170  // Set the parameter number for this spline
171  cpu_paramNo_TF1_arr[TF1sCounter] = short(ParamNumber);
172  ++ParamCounter_TF1;
173  // Increment the counter for the number of good splines we have
174  ++TF1sCounter;
175  }
176  //KS: Don't delete in debug
177  #ifndef MACH3_DEBUG
178  delete MasterSpline[EventCounter][ParamNumber];
179  MasterSpline[EventCounter][ParamNumber] = nullptr;
180  #endif
181  } // End the loop over the parameters in the MasterSpline
182  cpu_nParamPerEvent[2*EventCounter] = ParamCounter;
183  cpu_nParamPerEvent[2*EventCounter+1] = ParamCounterGlobal;
184  ParamCounterGlobal += ParamCounter;
185 
186  cpu_nParamPerEvent_tf1[2*EventCounter] = ParamCounter_TF1;
187  cpu_nParamPerEvent_tf1[2*EventCounter+1] = ParamCounterGlobalTF1;
188  ParamCounterGlobalTF1 += ParamCounter_TF1;
189 
190  ParamCounter = 0;
191  ParamCounter_TF1 = 0;
192  } // End the loop over the number of events
193  delete[] many_tmp;
194  delete[] x_tmp;
195  delete[] temp_coeffs;
196 
197  int BadXCounter = 0;
198  for (unsigned int j = 0; j < event_size_max; j++) {
199  if (cpu_monolith->coeff_x[j] == -999) BadXCounter++;
200  // Perform checks that all entries have been modified from initial values
201  if (cpu_monolith->coeff_x[j] == -999 && BadXCounter < 5) {
202  MACH3LOG_WARN("***** BAD X !! *****");
203  MACH3LOG_WARN("Indicates some parameter doesn't have a single spline");
204  MACH3LOG_WARN("j = {}", j);
205  //throw MaCh3Exception(__FILE__ , __LINE__ );
206  }
207  if(BadXCounter == 5) MACH3LOG_WARN("There is more unutilised knots although I will stop spamming");
208  }
209 
210  MACH3LOG_WARN("Found in total {} BAD X", BadXCounter);
211  //KS: This is tricky as this variable use both by CPU and GPU, however if use CUDA we use cudaMallocHost
212  if (!useGPU) {
214  cpu_weights_spline_var = new float[NSplines_valid]();
215  cpu_weights_tf1_var = new float[NTF1_valid]();
216  }
217 
218  // Print some info; could probably make this to a separate function
221 
222  MoveToGPU();
223 
224  // Can pass the spline segments to the GPU instead of the values
225  // Make these here and only refill them for each loop, avoiding unnecessary new/delete on each reconfigure
226  SetupSegments();
227 }
#define MACH3LOG_WARN
Definition: MaCh3Logger.h:36
@ kTF1_red
Uses TF1_red for interpolation.
@ kTSpline3_red
Uses TSpline3_red for interpolation.
void GetTF1Coeff(TF1_red *&spl, int &nPoints, float *&coeffs) const
CW: Gets the polynomial coefficients for TF1.
Definition: SplineBase.cpp:129
CW: A reduced TF1 class only. Only saves parameters for each TF1 and how many parameters each paramet...
KS: A reduced ResponseFunction Generic function used for evaluating weight.
CW: Reduced TSpline3 class.
void ScanMasterSpline(std::vector< std::vector< TResponseFunction_red * > > &MasterSpline, unsigned int &nEvents, short int &MaxPoints, short int &numParams, int &nSplines, unsigned int &NSplinesValid, unsigned int &numKnots, unsigned int &nTF1Valid, unsigned int &nTF1_coeff, const std::vector< RespFuncType > &SplineType)
CW: Function to scan through the MasterSpline of TSpline3.
void PrepareSplineFile(std::string FileName) final
KS: Prepare spline file that can be used for fast loading.
std::vector< short int > cpu_nPoints_arr
CPU arrays to hold number of points.
void GetSplineCoeff_SepMany(TSpline3_red *&spl, int &nPoints, float *&xArray, float *&manyArray) const
CW: This loads up coefficients into two arrays: one x array and one yabcd array.

◆ PrepareSplineFile()

void UnbinnedSplineHandler::PrepareSplineFile ( std::string  FileName)
finalvirtual

KS: Prepare spline file that can be used for fast loading.

Implements SplineBase.

Definition at line 518 of file UnbinnedSplineHandler.cpp.

518  {
519 // *****************************************
520  M3::AddPath(FileName);
521 
522  auto SplineFile = std::make_unique<TFile>(FileName.c_str(), "recreate");
523  TTree *Settings = new TTree("Settings", "Settings");
524  TTree *Monolith_TF1 = new TTree("Monolith_TF1", "Monolith_TF1");
525  TTree *XKnots = new TTree("XKnots", "XKnots");
526  TTree *EventInfo = new TTree("EventInfo", "EventInfo");
527 
528  unsigned int NEvents_temp = NEvents;
529  short int nParams_temp = nParams;
530  int _max_knots_temp = _max_knots;
531  unsigned int nKnots_temp = nKnots;
532  unsigned int NSplines_valid_temp = NSplines_valid;
533  unsigned int nTF1Valid_temp = NTF1_valid;
534  unsigned int nTF1coeff_temp = nTF1coeff;
535 
536  Settings->Branch("NEvents", &NEvents_temp, "NEvents/i");
537  Settings->Branch("nParams", &nParams_temp, "nParams/S");
538  Settings->Branch("_max_knots", &_max_knots_temp, "_max_knots/I");
539  Settings->Branch("nKnots", &nKnots_temp, "nKnots/i");
540  Settings->Branch("NSplines_valid", &NSplines_valid_temp, "NSplines_valid/i");
541  Settings->Branch("NTF1_valid", &nTF1Valid_temp, "NTF1_valid/i");
542  Settings->Branch("nTF1coeff", &nTF1coeff_temp, "nTF1coeff/i");
543 
544  Settings->Fill();
545 
546  SplineFile->cd();
547  Settings->Write();
548 
549  TTree *SplineTree = new TTree("SplineTree", "SplineTree");
550  // Create a branch for the SplineMonoStruct object
551  SplineTree->Branch("SplineObject", &cpu_monolith);
552  SplineTree->Fill();
553  SplineTree->Write();
554  delete SplineTree;
555 
556  float coeff_tf1 = 0.;
557  Monolith_TF1->Branch("cpu_coeff_TF1_many", &coeff_tf1, "cpu_coeff_TF1_many/F");
558  for(unsigned int i = 0; i < nTF1coeff; i++)
559  {
560  coeff_tf1 = cpu_coeff_TF1_many[i];
561  Monolith_TF1->Fill();
562  }
563  SplineFile->cd();
564  Monolith_TF1->Write();
565 
566  unsigned int nParamPerEvent = 0;
567  unsigned int nParamPerEvent_tf1 = 0;
568 
569  EventInfo->Branch("cpu_nParamPerEvent", &nParamPerEvent, "cpu_nParamPerEvent/i");
570  EventInfo->Branch("cpu_nParamPerEvent_tf1", &nParamPerEvent_tf1, "cpu_nParamPerEvent_tf1/i");
571 
572  for(unsigned int i = 0; i < 2*NEvents; i++)
573  {
574  nParamPerEvent = cpu_nParamPerEvent[i];
575  nParamPerEvent_tf1 = cpu_nParamPerEvent_tf1[i];
576  EventInfo->Fill();
577  }
578  SplineFile->cd();
579  EventInfo->Write();
580 
581  PrepareFastSplineInfoDir(SplineFile);
582 
583  delete Settings;
584  delete Monolith_TF1;
585  delete XKnots;
586  delete EventInfo;
587  SplineFile->Close();
588 }
void PrepareFastSplineInfoDir(std::unique_ptr< TFile > &SplineFile) const
KS: Prepare Fast Spline Info within SplineFile.
Definition: SplineBase.cpp:153

◆ PrintInitialsiation()

void UnbinnedSplineHandler::PrintInitialsiation ( ) const
private

KS: Print info about how much knots etc has been initialised.

Definition at line 802 of file UnbinnedSplineHandler.cpp.

802  {
803 //*********************************************************
804  unsigned int event_size_max = _max_knots * nParams;
805 
806  MACH3LOG_INFO("--- INITIALISED Spline Monolith ---");
807  MACH3LOG_INFO("{} events with {} splines", NEvents, NSplines_valid);
808  MACH3LOG_INFO("On average {:.2f} splines per event ({}/{})", float(NSplines_valid)/float(NEvents), NSplines_valid, NEvents);
809  MACH3LOG_INFO("Size of x array = {:.4f} MB", double(sizeof(float)*event_size_max)/1.E6);
810  MACH3LOG_INFO("Size of coefficient (y,b,c,d) array = {:.2f} MB", double(sizeof(float)*nKnots*_nCoeff_)/1.E6);
811  MACH3LOG_INFO("Size of parameter # array = {:.2f} MB", double(sizeof(short int)*NSplines_valid)/1.E6);
812 
813  MACH3LOG_INFO("On average {:.2f} TF1 per event ({}/{})", float(NTF1_valid)/float(NEvents), NTF1_valid, NEvents);
814  MACH3LOG_INFO("Size of TF1 coefficient (a,b,c,d,e) array = {:.2f} MB", double(sizeof(float)*NTF1_valid*_nTF1Coeff_)/1.E6);
815 }

◆ RetPointer()

const M3::float_t* UnbinnedSplineHandler::RetPointer ( const int  event) const
inline

KS: Get pointer to total weight to make fit faster wrooom!

Parameters
eventName event number in used MC
Returns
Pointer to the total weight

Definition at line 35 of file UnbinnedSplineHandler.h.

35 {return &cpu_total_weights[event];}

◆ ScanMasterSpline()

void UnbinnedSplineHandler::ScanMasterSpline ( std::vector< std::vector< TResponseFunction_red * > > &  MasterSpline,
unsigned int &  nEvents,
short int &  MaxPoints,
short int &  numParams,
int &  nSplines,
unsigned int &  NSplinesValid,
unsigned int &  numKnots,
unsigned int &  nTF1Valid,
unsigned int &  nTF1_coeff,
const std::vector< RespFuncType > &  SplineType 
)
private

CW: Function to scan through the MasterSpline of TSpline3.

Parameters
MasterSplineVector of TSpline3_red pointers which we strip back
NEventsNumber of MC events
MaxPointsMaximal number of knots per splines
numParamsTotal number of parameters
numKnotsTotal number of knots, which is sum of individual knots per each spline
nTF1_coeffNumber of TF1 coefficients in all TF1 objects
SplineTypeWhether object is TSpline3 or TF1
NSplinesValidTotal number of valid (not null) TSpline3
nTF1ValidTotal number of valid (not null) TF1

Definition at line 299 of file UnbinnedSplineHandler.cpp.

308  {
309 // *****************************************
310  // Need to extract: the total number of events
311  // number of parameters
312  // maximum number of knots
313  MaxPoints = 0;
314  nEvents = 0;
315  numParams = 0;
316  nSplines = 0;
317  numKnots = 0;
318  NSplinesValid = 0;
319  nTF1Valid = 0;
320  nTF1_coeff = 0;
321 
322  // Check the number of events
323  nEvents = int(MasterSpline.size());
324 
325  // Maximum number of splines one event can have (scan through and find this number)
326  int nMaxSplines_PerEvent = 0;
327 
328  //KS: We later check that each event has the same number of splines so this is fine
329  numParams = short(MasterSpline[0].size());
330  // Initialise
331  SplineInfoArray.resize(numParams);
332 
333  // Loop over each parameter
334  for(unsigned int EventCounter = 0; EventCounter < MasterSpline.size(); ++EventCounter) {
335  // Check that each event has each spline saved
336  if (numParams > 0) {
337  int TempSize = int(MasterSpline[EventCounter].size());
338  if (TempSize != numParams) {
339  MACH3LOG_ERROR("Found {} parameters for event {}", TempSize, EventCounter);
340  MACH3LOG_ERROR("but was expecting {} since that's what I found for the previous event", numParams);
341  MACH3LOG_ERROR("Somehow this event has a different number of spline parameters... Please study further!");
342  throw MaCh3Exception(__FILE__ , __LINE__ );
343  }
344  }
345  numParams = short(MasterSpline[EventCounter].size());
346 
347  int nSplines_SingleEvent = 0;
348  int nPoints = 0;
349  // Loop over each pointer
350  for(unsigned int ParamNumber = 0; ParamNumber < MasterSpline[EventCounter].size(); ++ParamNumber) {
351  if (MasterSpline[EventCounter][ParamNumber]) {
352  if(SplineType[ParamNumber] == kTSpline3_red)
353  {
354  TResponseFunction_red* TespFunc = MasterSpline[EventCounter][ParamNumber];
355  TSpline3_red* CurrSpline = dynamic_cast<TSpline3_red*>(TespFunc);
356  if(CurrSpline){
357  nPoints = CurrSpline->GetNp();
358  }
359 
360  if (nPoints > MaxPoints) {
361  MaxPoints = static_cast<short int>(nPoints);
362  }
363  numKnots += nPoints;
364  nSplines_SingleEvent++;
365 
366  // Fill the SplineInfoArray entries with information on each splinified parameter
367  if (SplineInfoArray[ParamNumber].xPts.size() == 0)
368  {
369  // Fill the number of points
370  SplineInfoArray[ParamNumber].nPts = CurrSpline->GetNp();
371 
372  // Fill the x points
373  SplineInfoArray[ParamNumber].xPts.resize(SplineInfoArray[ParamNumber].nPts);
374  for (M3::int_t k = 0; k < SplineInfoArray[ParamNumber].nPts; ++k)
375  {
376  M3::float_t xtemp = M3::float_t(-999.99);
377  M3::float_t ytemp = M3::float_t(-999.99);
378  CurrSpline->GetKnot(k, xtemp, ytemp);
379  SplineInfoArray[ParamNumber].xPts[k] = xtemp;
380  }
381  }
382  NSplinesValid++;
383  }
384  else if (SplineType[ParamNumber] == kTF1_red)
385  {
386  TResponseFunction_red* TespFunc = MasterSpline[EventCounter][ParamNumber];
387  TF1_red* CurrSpline = dynamic_cast<TF1_red*>(TespFunc);
388  nPoints = CurrSpline->GetSize();
389  nTF1_coeff += nPoints;
390  nTF1Valid++;
391  }
392  } else {
393  // If NULL we don't have this spline for the event, so move to next spline
394  continue;
395  }
396  }
397  if (nSplines_SingleEvent > nMaxSplines_PerEvent) nMaxSplines_PerEvent = nSplines_SingleEvent;
398  }
399  nSplines = nMaxSplines_PerEvent;
400 
401  int Counter = 0;
402  //KS: Sanity check that everything was set correctly
403  for (M3::int_t i = 0; i < numParams; ++i)
404  {
405  // KS: We don't find segment for TF1, so ignore this
406  if (SplineType[i] == kTF1_red) continue;
407 
408  const M3::int_t nPoints = SplineInfoArray[i].nPts;
409  const std::vector<M3::float_t>& xArray = SplineInfoArray[i].xPts;
410  if (nPoints == -999 || xArray.size() == 0) {
411  Counter++;
412  if(Counter < 5) {
413  MACH3LOG_WARN("SplineInfoArray[{}] isn't set yet", i);
414  }
415  continue;
416  //throw MaCh3Exception(__FILE__ , __LINE__ );
417  }
418  }
419  MACH3LOG_WARN("In total SplineInfoArray for {} hasn't been initialised", Counter);
420 }
std::vector< FastSplineInfo > SplineInfoArray
Definition: SplineBase.h:106
int GetSize() const
Get the size.
void GetKnot(int i, M3::float_t &xtmp, M3::float_t &ytmp) const
int int_t
Definition: Core.h:38

◆ SetSplinePointers()

void UnbinnedSplineHandler::SetSplinePointers ( std::vector< const M3::float_t * >  spline_ParsPointers)
inline

KS: Set pointers to spline params.

Parameters
spline_ParsPointersVector of pointers to spline params

Definition at line 39 of file UnbinnedSplineHandler.h.

39  {
40  for (M3::int_t i = 0; i < nParams; ++i) SplineInfoArray[i].splineParsPointer = spline_ParsPointers[i];
41  };

Member Data Documentation

◆ cpu_coeff_TF1_many

std::vector<float> UnbinnedSplineHandler::cpu_coeff_TF1_many
private

CPU arrays to hold TF1 coefficients.

Definition at line 120 of file UnbinnedSplineHandler.h.

◆ cpu_monolith

SplineMonoStruct* UnbinnedSplineHandler::cpu_monolith
private

KS: Store info about Spline monolith, this allow to obtain better step time. As all necessary information for spline weight calculation are here meaning better cache hits.

Definition at line 117 of file UnbinnedSplineHandler.h.

◆ cpu_nParamPerEvent

std::vector<unsigned int> UnbinnedSplineHandler::cpu_nParamPerEvent
private

KS: CPU map keeping track how many parameters applies to each event, we keep two numbers here {number of splines per event, index where splines start for a given event}.

Definition at line 111 of file UnbinnedSplineHandler.h.

◆ cpu_nParamPerEvent_tf1

std::vector<unsigned int> UnbinnedSplineHandler::cpu_nParamPerEvent_tf1
private

KS: CPU map keeping track how many parameters applies to each event, we keep two numbers here {number of TF1 per event, index where TF1 start for a given event}.

Definition at line 114 of file UnbinnedSplineHandler.h.

◆ cpu_nPoints_arr

std::vector<short int> UnbinnedSplineHandler::cpu_nPoints_arr
private

CPU arrays to hold number of points.

Definition at line 123 of file UnbinnedSplineHandler.h.

◆ cpu_paramNo_TF1_arr

std::vector<short int> UnbinnedSplineHandler::cpu_paramNo_TF1_arr
private

CW: CPU array with the number of points per spline (not per spline point!)

Definition at line 126 of file UnbinnedSplineHandler.h.

◆ cpu_total_weights

M3::float_t* UnbinnedSplineHandler::cpu_total_weights
private

KS: This holds the total CPU weights that gets read in SampleHandler.

Definition at line 108 of file UnbinnedSplineHandler.h.

◆ cpu_weights_spline_var

float* UnbinnedSplineHandler::cpu_weights_spline_var
private

CPU arrays to hold weight for each spline.

Definition at line 104 of file UnbinnedSplineHandler.h.

◆ cpu_weights_tf1_var

float* UnbinnedSplineHandler::cpu_weights_tf1_var
private

CPU arrays to hold weight for each TF1.

Definition at line 106 of file UnbinnedSplineHandler.h.

◆ FastSplineName

std::string UnbinnedSplineHandler::FastSplineName
private

Name of Fast Spline to which will be saved.

Definition at line 132 of file UnbinnedSplineHandler.h.

◆ NEvents

unsigned int UnbinnedSplineHandler::NEvents
private

Number of events.

Definition at line 93 of file UnbinnedSplineHandler.h.

◆ nKnots

unsigned int UnbinnedSplineHandler::nKnots
private

Sum of all knots over all splines.

Definition at line 99 of file UnbinnedSplineHandler.h.

◆ NTF1_valid

unsigned int UnbinnedSplineHandler::NTF1_valid
private

Number of valid TF1.

Definition at line 96 of file UnbinnedSplineHandler.h.

◆ nTF1coeff

unsigned int UnbinnedSplineHandler::nTF1coeff
private

Sum of all coefficients over all TF1.

Definition at line 101 of file UnbinnedSplineHandler.h.

◆ SaveSplineFile

bool UnbinnedSplineHandler::SaveSplineFile
private

Flag telling whether we are saving spline monolith into handy root file.

Definition at line 129 of file UnbinnedSplineHandler.h.


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