73 auto m_splines = m.def_submodule(
"splines");
75 "This is a Python binding of MaCh3s C++ based spline library.";
78 py::enum_<SplineInterpolation>(m_splines,
"InterpolationType")
81 .value(
"Cubic_TSpline3",
SplineInterpolation::kTSpline3,
"Use same coefficients as `ROOT's TSpline3 <https://root.cern.ch/doc/master/classTSpline3.html>`_ implementation")
82 .value(
"Cubic_Monotonic",
SplineInterpolation::kMonotonic,
"Coefficients are calculated such that the segments between knots are forced to be monotonic. The implementation we use is based on `this method <https://www.jstor.org/stable/2156610>`_ by Fritsch and Carlson.")
83 .value(
"Cubic_Akima",
SplineInterpolation::kAkima,
"The second derivative is not required to be continuous at the knots. This means that these splines are useful if the second derivative is rapidly varying. The implementation we used is based on `this paper <http://www.leg.ufpr.br/lib/exe/fetch.php/wiki:internas:biblioteca:akima.pdf>`_ by Akima.")
89 py::class_<TResponseFunction_red>(m_splines,
"_ResponseFunctionBase")
90 .doc() =
"Base class of the response function, this binding only exists for consistency with the inheritance structure of the c++ code. Just pretend it doesn't exist and don't worry about it...";
95 py::class_<TSpline3_red, TResponseFunction_red, std::unique_ptr<TSpline3_red, py::nodelete>>(m_splines,
"ResponseFunction")
104 if ( xVals.size() != yVals.size() )
106 throw MaCh3Exception(__FILE__, __LINE__,
"Different number of x values and y values!");
109 int length =
int(xVals.size());
116 std::vector<M3::float_t *> pars;
125 return new TSpline3_red(&xKnot, &yKnot, 1, pars.data());
128 TSpline3 *splineTmp =
new TSpline3(
"spline_tmp", xVals.data(), yVals.data(), length );
137 "Find the segment that a particular *value* lies in. \n"
138 ":param value: The value to test",
145 "Evaluate the response function at a particular *value*. \n"
146 ":param value: The value to evaluate at.",
151 py::class_<SMonolith, SplineBase>(m_splines,
"EventSplineMonolith")
154 [](std::vector<std::vector<TResponseFunction_red*>> &responseFns,
const bool saveFlatTree)
156 std::vector<RespFuncType> respFnTypes;
157 for(uint i = 0; i < responseFns[0].size(); i++)
166 return new SMonolith(responseFns, respFnTypes, saveFlatTree);
169 "Create an EventSplineMonolith \n"
170 ":param master_splines: These are the 'knot' values to make splines from. This should be an P x E 2D list where P is the number of parameters and E is the number of events. \n"
171 ":param save_flat_tree: Whether we want to save monolith into speedy flat tree",
172 py::arg(
"master_splines"),
173 py::arg(
"save_flat_tree") = false
177 py::init<std::string>(),
178 "Constructor where you pass path to preprocessed root FileName which is generated by creating an EventSplineMonolith with the `save_flat_tree` flag set to True. \n"
179 ":param file_name: The name of the file to read from.",
186 "Evaluate the splines at their current values."
192 "This is important when running on GPU. 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."
198 py::return_value_policy::reference,
199 "Get the weight of a particular event. \n"
200 ":param event: The index of the event whose weight you would like.",
205 "set_param_value_array",
208 [](
SMonolith &
self, py::array_t<double, py::array::c_style> &array)
210 py::buffer_info bufInfo = array.request();
212 if ( bufInfo.ndim != 1)
214 throw MaCh3Exception(__FILE__, __LINE__,
"Number of dimensions in parameter array must be one!");
217 if ( bufInfo.shape[0] !=
self.GetNParams() )
219 throw MaCh3Exception(__FILE__, __LINE__,
"Number of entries in parameter array must equal the number of parameters!");
222 std::vector<const double *> paramVec;
223 paramVec.resize(
self.GetNParams());
225 for(
int idx = 0; idx <
self.GetNParams(); idx++ )
228 paramVec[idx] = array.data() + idx;
231 self.setSplinePointers(paramVec);
233 "Set the array that the monolith should use to read parameter values from. \n"
234 "Usage of this might vary a bit from what you're used to in python. \n"
235 "Rather than just setting the values here, what you're really doing is setting pointers in the underlying c++ code. \n"
236 "What that means is that you pass an array to this function like:: \n"
237 "\n event_spline_monolith_instance.set_param_value_array(array) \n\n"
238 "Then when you set values in that array as normal, they will also be updated inside of the event_spline_monolith_instance.",
243 .doc() =
"This 'monolith' deals with event by event weighting using splines."
SplineInterpolation
Make an enum of the spline interpolation type.
@ kTSpline3
Default TSpline3 interpolation.
@ kMonotonic
EM: DOES NOT make the entire spline monotonic, only the segments.
@ kSplineInterpolations
This only enumerates.
@ kLinear
Linear interpolation between knots.
@ kLinearFunc
Liner interpolation using TF1 not spline.
@ kAkima
EM: Akima spline iis allowed to be discontinuous in 2nd derivative and coefficients in any segment.
@ kTSpline3_red
Uses TSpline3_red for interpolation.
Custom exception class used throughout MaCh3.
EW: As SplineBase is an abstract base class we have to do some gymnastics to get it to get it into py...
Even-by-event class calculating response for spline parameters. It is possible to use GPU acceleratio...
void SynchroniseMemTransfer() const override
KS: After calculations are done on GPU we copy memory to CPU. This operation is asynchronous meaning ...
void Evaluate() override
CW: This Eval should be used when using two separate x,{y,a,b,c,d} arrays to store the weights; proba...
const float * retPointer(const int event) const
KS: Get pointer to total weight to make fit faster wrooom!
Base class for calculating weight from spline.
CW: Reduced TSpline3 class.
double Eval(double var) override
CW: Evaluate the weight from a variation.
int FindX(double x)
Find the segment relevant to this variation in x.