9 #pragma GCC diagnostic push
10 #pragma GCC diagnostic ignored "-Wuseless-cast"
11 #pragma GCC diagnostic ignored "-Wfloat-conversion"
12 #pragma GCC diagnostic ignored "-Wnull-dereference"
38 std::vector<M3::float_t>
xPts;
51 if(SplineGraph ==
nullptr){
52 MACH3LOG_ERROR(
"hmmm looks like you're trying to apply capping for spline parameter {} but it hasn't been set in SplineGraph yet",
62 for(
int knotId = 0; knotId < SplineGraph->GetN(); knotId++){
66 if(SplineGraph->GetPoint(knotId, x, y) == -1) {
74 SplineGraph->SetPoint(knotId, x, y);
79 for(
int knotId = 0; knotId < SplineGraph->GetN(); knotId++){
83 if(SplineGraph->GetPoint(knotId, x, y) == -1) {
87 if(std::abs(y - 1.0) > 1e-5)
isFlat =
false;
92 SplineGraph->SetPoint(0, 0.0, 1.0);
101 if(Spline ==
nullptr) {
102 MACH3LOG_ERROR(
"hmmm looks like you're trying to apply capping for spline parameter {} but it hasn't been set in Spline yet",
107 std::string oldName = Spline->GetName();
112 const int NValues = Spline->GetNp();
113 std::vector<double> XVals(NValues);
114 std::vector<double> YVals(NValues);
115 for(
int knotId = 0; knotId < NValues; knotId++){
118 Spline->GetKnot(knotId, x, y);
128 Spline =
new TSpline3(oldName.c_str(), XVals.data(), YVals.data(), NValues);
142 virtual double Eval(
const double var)
const =0;
162 if (
Par !=
nullptr) {
171 for (
int i = 0; i <
length; ++i) {
185 if (
Par !=
nullptr)
delete[]
Par;
187 for (
int i = 0; i <
length; ++i) {
195 inline double Eval(
const double var)
const override {
219 Par[Parameter] = Value;
225 MACH3LOG_ERROR(
"You requested parameter number {} but length is {} parameters", Parameter,
length);
229 return Par[Parameter];
240 inline void Print()
const override {
243 for (
int i = 0; i <
length; i++) {
249 inline TF1*
ConstructTF1(
const std::string&
function,
const int xmin,
const int xmax) {
250 TF1 *func =
new TF1(
"TF1",
function.c_str(), xmin, xmax);
251 for(
int i = 0; i <
length; ++i) {
252 func->SetParameter(i,
Par[i]);
284 SetFunc(spline, InterPolation);
296 for(
int j = 0; j < N; ++j){
304 if((
Par[j][0] == -999) | (
Par[j][1] ==-999) | (
Par[j][2] ==-999) | (
XPos[j] ==-999) | (
YResp[j] ==-999)){
305 MACH3LOG_ERROR(
"******************* Bad parameter values when constructing TSpline3_red *********************");
306 MACH3LOG_ERROR(
"Passed values (i, x, y, b, c, d): {}, {}, {}, {}, {}, {}", j, X[j], Y[j], P[j][0], P[j][1], P[j][2]);
307 MACH3LOG_ERROR(
"Set values (i, x, y, b, c, d): {}, {}, {}, {}, {}, {}", j,
XPos[j],
YResp[j],
Par[j][0],
Par[j][1],
Par[j][2]);
308 MACH3LOG_ERROR(
"*********************************************************************************************");
316 if (
Par !=
nullptr) {
317 for (
int i = 0; i <
nPoints; ++i) {
336 for (
int i = 0; i <
nPoints; ++i) {
339 double x = -999.99, y = -999.99, b = -999.99, c = -999.99, d = -999.99;
340 spline->GetCoeff(i, x, y, b, c, d);
356 for (
int k = 0; k <
nPoints; ++k) {
359 Double_t x1, y1, b1, c1, d1, x2, y2, b2, c2, d2 = 0;
360 spline->GetCoeff(k, x1, y1, b1, c1, d1);
366 spline->GetCoeff(k + 1, x2, y2, b2, c2, d2);
367 tempb = (y2-y1)/(x2-x1);
378 else if(InterPolation ==
kAkima)
381 for (
int i = 0; i <
nPoints; ++i) {
385 double x = -999.99, y = -999.99;
386 spline->GetKnot(i, x, y);
395 for (
int i = -2; i <=
nPoints; ++i) {
416 for(
int i = 2; i<=
nPoints+2; i++){
417 if (std::abs(mvals[i+1] - mvals[i]) + std::abs(mvals[i-1] - mvals[i-2]) != 0.0){
418 svals[i-2] = (std::abs(mvals[i+1] - mvals[i]) * mvals[i-1] + std::abs(mvals[i-1] - mvals[i-2]) *mvals[i]) / (std::abs(mvals[i+1] - mvals[i]) + std::abs(mvals[i-1] - mvals[i-2]));
420 else{svals[i-2] = mvals[i];}
424 for(
int i = 0; i <
nPoints; i++){
438 for(
int i = 0; i <
nPoints-1; i++){
439 double x = -999.99, y = -999.99, b = -999.99, c = -999.99, d = -999.99;
440 spline->GetCoeff(i, x, y, b, c, d);
442 if((c == 0.0 && d == 0.0)){
461 for (
int i = 0; i <
nPoints; ++i) {
465 double x = -999.99, y = -999.99;
466 spline->GetKnot(i, x, y);
488 for (
int i = 0; i <
nPoints-1; ++i) {
493 Tangents[0] = Secants[0];
500 for (
int i = 1; i <
nPoints-1; ++i) {
501 if ((Secants[i-1] >= 0.0 && Secants[i] >= 0.0) | (Secants[i-1] < 0.0 && Secants[i] < 0.0)){
502 Tangents[i] =
M3::float_t((Secants[i-1] + Secants[i]) /2.0);
507 for (
int i = 0; i <
nPoints-1; ++i) {
508 if (Secants[i] == 0.0){
513 alpha = Tangents[i] / Secants[i];
514 beta = Tangents[i+1] / Secants[i];
523 if (alpha * alpha + beta * beta >9.0){
525 Tangents[i] = tau * alpha * Secants[i];
526 Tangents[i+1] = tau * beta * Secants[i];
532 for(
int i = 0; i <
nPoints-1; i++){
536 b = Tangents[i] * dx;
541 Par[i][1] = c / (dx * dx);
542 Par[i][2] = d / (dx * dx * dx);
544 if((
Par[i][0] == -999) | (
Par[i][1] == -999) | (
Par[i][2] ==-999) | (
Par[i][0] == -999.999) | (
Par[i][1] == -999.999) | (
Par[i][2] ==-999.999)){
545 MACH3LOG_INFO(
"Bad spline parameters for segment {}: (b, c, d) = {}, {}, {}. This will cause problems with GPU.",
561 for(
int i = 0; i <
nPoints-1; i++){
562 double x = -999.99, y = -999.99, b = -999.99, c = -999.99, d = -999.99;
563 spline->GetCoeff(i, x, y, b, c, d);
565 if((c == 0.0 && d == 0.0)){
579 for (
int i = 0; i <
nPoints; ++i)
582 double x = -999.99, y = -999.99;
583 spline->GetKnot(i, x, y);
609 for (
int i = 1; i <
nPoints - 1; ++i)
614 M3::float_t term1 = (1.0 - T) * (1.0 + B) * (1.0 + C) * 0.5 * d0;
615 M3::float_t term2 = (1.0 - T) * (1.0 - B) * (1.0 - C) * 0.5 * d1;
617 Tangents[i] = term1 + term2;
625 for (
int i = 0; i <
nPoints - 1; ++i)
633 Par[i][1] = (3*dy/(dx*dx)) - (2*m0 + m1)/dx;
634 Par[i][2] = (m0 + m1 - 2*dy/dx) / (dx*dx);
637 i, dx, dy,
Par[i][0],
Par[i][1],
Par[i][2]);
648 MACH3LOG_ERROR(
"Unsupported interpolation type {}",
static_cast<int>(InterPolation));
659 for (
int i = 0; i <
nPoints; ++i) {
660 if (
Par[i] !=
nullptr) {
692 while (kHigh - segment > 1) {
694 kHalf = (segment + kHigh)/2;
696 if (x >
XPos[kHalf]) {
709 inline double Eval(
const double var)
const override {
711 int segment =
FindX(var);
717 double weight = y+dx*(b+dx*(c+d*dx));
742 #ifdef _LOW_MEMORY_STRUCTS_
743 std::vector<Double_t> xPosDoubles(
nPoints);
744 std::vector<Double_t> yPosDoubles(
nPoints);
745 for (Int_t i = 0; i <
nPoints; ++i) {
746 xPosDoubles[i] =
static_cast<Double_t
>(
XPos[i]);
747 yPosDoubles[i] =
static_cast<Double_t
>(
YResp[i]);
749 TSpline3 *spline =
new TSpline3(
"Spline", xPosDoubles.data(), yPosDoubles.data(),
static_cast<int>(
nPoints));
753 for (Int_t i = 0; i <
nPoints; ++i) {
754 spline->SetPointCoeff(i,
Par[i][0],
Par[i][1],
Par[i][2]);
761 inline void Print()
const override {
764 for (
int i = 0; i <
nPoints; ++i) {
786 int Np = spl->
GetNp();
791 for(
int i = 0; i < Np; i++) {
803 inline std::vector<std::vector<TSpline3_red*> >
ReduceTSpline3(std::vector<std::vector<TSpline3*> > &MasterSpline) {
805 std::vector<std::vector<TSpline3*> >::iterator OuterIt;
806 std::vector<TSpline3*>::iterator InnerIt;
809 std::vector<std::vector<TSpline3_red*> > ReducedVector;
810 ReducedVector.reserve(MasterSpline.size());
813 for (OuterIt = MasterSpline.begin(); OuterIt != MasterSpline.end(); ++OuterIt) {
815 std::vector<TSpline3_red*> TempVector;
816 TempVector.reserve(OuterIt->size());
818 for (InnerIt = OuterIt->begin(); InnerIt != OuterIt->end(); ++InnerIt) {
820 TSpline3 *spline = (*InnerIt);
823 if (spline !=
nullptr) {
828 TempVector.push_back(red);
830 ReducedVector.push_back(TempVector);
833 return ReducedVector;
839 inline std::vector<std::vector<TF1_red*> >
ReduceTF1(std::vector<std::vector<TF1*> > &MasterSpline) {
841 std::vector<std::vector<TF1*> >::iterator OuterIt;
842 std::vector<TF1*>::iterator InnerIt;
845 std::vector<std::vector<TF1_red*> > ReducedVector;
846 ReducedVector.reserve(MasterSpline.size());
849 for (OuterIt = MasterSpline.begin(); OuterIt != MasterSpline.end(); ++OuterIt) {
851 std::vector<TF1_red*> TempVector;
852 TempVector.reserve(OuterIt->size());
854 for (InnerIt = OuterIt->begin(); InnerIt != OuterIt->end(); ++InnerIt) {
856 TF1* spline = (*InnerIt);
859 if (spline !=
nullptr) {
864 TempVector.push_back(red);
866 ReducedVector.push_back(TempVector);
869 return ReducedVector;
881 const std::string& Title) {
885 if (graph && graph->GetN() > 1)
890 TSpline3* spline =
nullptr;
894 spline =
new TSpline3(Title.c_str(), graph);
895 spline->SetNameTitle(Title.c_str(), Title.c_str());
898 spline_red =
new TSpline3_red(spline, SplineInterpolationType);
900 RespFunc = spline_red;
902 else if(SplineRespFuncType ==
kTF1_red)
905 TF1 *Fitter =
nullptr;
908 if(graph->GetN() != 2) {
909 MACH3LOG_ERROR(
"Trying to make TF1 from more than 2 knots. Knots = {}", graph->GetN());
915 Fitter =
new TF1(Title.c_str(),
"([1]+[0]*x)", graph->GetX()[0], graph->GetX()[graph->GetN()-1]);
924 graph->Fit(Fitter,
"Q0");
943 #pragma GCC diagnostic pop
Definitions of generic parameter structs and utility templates for MaCh3.
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.
@ kKochanekBartels
KS: Kochanek-Bartels spline: allows local control of tension, continuity, and bias.
@ 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.
RespFuncType
Make an enum of the spline interpolation type.
@ kTF1_red
Uses TF1_red for interpolation.
@ kTSpline3_red
Uses TSpline3_red for interpolation.
TResponseFunction_red * CreateResponseFunction(TGraph *&graph, const RespFuncType SplineRespFuncType, const SplineInterpolation SplineInterpolationType, const std::string &Title)
KS: Create Response Function using TGraph.
std::vector< std::vector< TF1_red * > > ReduceTF1(std::vector< std::vector< TF1 * > > &MasterSpline)
CW: Reduced the TF1 to TF1_red.
void ApplyKnotWeightCap(TGraph *SplineGraph, const int splineParsIndex, ParameterHandlerGeneric *ParHandler)
EM: Apply capping to knot weight for specified spline parameter. SplineGraph needs to have been set i...
std::vector< std::vector< TSpline3_red * > > ReduceTSpline3(std::vector< std::vector< TSpline3 * > > &MasterSpline)
CW: Reduced the TSpline3 to TSpline3_red.
void ApplyKnotWeightCapTSpline3(TSpline3 *&Spline, const int splineParsIndex, ParameterHandlerGeneric *ParHandler)
EM: Apply capping to knot weight for specified spline parameter. param graph needs to have been set i...
bool isFlat(TSpline3_red *&spl)
CW: Helper function used in the constructor, tests to see if the spline is flat.
Custom exception class used throughout MaCh3.
std::string GetParFancyName(const int i) const
Get fancy name of the Parameter.
Class responsible for handling of systematic error parameters with different types defined in the con...
double GetParSplineKnotUpperBound(const int i) const
EM: value at which we cap spline knot weight.
double GetParSplineKnotLowerBound(const int i) const
EM: value at which we cap spline knot weight.
CW: A reduced TF1 class only. Only saves parameters for each TF1 and how many parameters each paramet...
double Eval(const double var) const override
Evaluate a variation.
double GetParameter(M3::int_t Parameter) const
Get a parameter value.
void SetSize(M3::int_t nSpline)
Set the size.
M3::int_t GetNp() const override
DL: Get number of points.
void SetFunc(TF1 *&Func)
Set the function.
TF1_red()
Empty constructor.
TF1 * ConstructTF1(const std::string &function, const int xmin, const int xmax)
KS: Make a TF1 from the reduced TF1.
TF1_red(TF1 *&Function)
The TF1 constructor with deep copy.
M3::float_t * Par
The parameters.
virtual ~TF1_red()
Empty destructor.
int GetSize() const
Get the size.
TF1_red(M3::int_t nSize, M3::float_t *Array)
The useful constructor with deep copy.
void SetParameter(M3::int_t Parameter, M3::float_t Value)
Set a parameter to a value.
void Print() const override
Print detailed info.
KS: A reduced ResponseFunction Generic function used for evaluating weight.
virtual double Eval(const double var) const =0
Evaluate a variation.
virtual ~TResponseFunction_red()
Empty destructor.
virtual void Print() const =0
KS: Printer.
TResponseFunction_red()
Empty constructor.
virtual M3::int_t GetNp() const =0
DL: Get number of points.
CW: Reduced TSpline3 class.
void GetKnot(int i, M3::float_t &xtmp, M3::float_t &ytmp) const
int FindX(double x) const
Find the segment relevant to this variation in x.
virtual ~TSpline3_red()
Empty destructor.
void Print() const override
Print detailed info.
M3::float_t ** Par
Always uses a third order polynomial, so hard-code the number of coefficients in implementation.
TSpline3_red(M3::float_t *X, M3::float_t *Y, M3::int_t N, M3::float_t **P)
constructor taking parameters
M3::int_t nPoints
Number of points/knot in TSpline3.
TSpline3_red(TSpline3 *&spline, SplineInterpolation InterPolation=kTSpline3)
The constructor that takes a TSpline3 pointer and copies in to memory.
TSpline3 * ConstructTSpline3()
CW: Make a TSpline3 from the reduced splines.
void SetFunc(TSpline3 *&spline, SplineInterpolation InterPolation=kTSpline3)
Set the function .
M3::float_t * XPos
Positions of each x for each knot.
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.
TSpline3_red()
Empty constructor.
double Eval(const double var) const override
CW: Evaluate the weight from a variation.
M3::float_t * YResp
y-value for each knot
constexpr static const double DefSplineKnotUpBound
Default value for spline knot capping, default mean not capping is being applied.
constexpr static const double DefSplineKnotLowBound
Default value for spline knot capping, default mean not capping is being applied.
CW: Add a struct to hold info about the splinified parameters and help with FindSplineSegment.
virtual ~FastSplineInfo()=default
Destructor.
const M3::float_t * splineParsPointer
Array of the knots positions.
std::vector< M3::float_t > xPts
Array of the knots positions.
M3::int_t CurrSegment
Array of what segment of spline we're currently interested in. Gets updated once per MCMC iteration.
FastSplineInfo()
Constructor.
M3::int_t nPts
Number of points in spline.