MINT2
Classes | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
RooCubicSplineKnot Class Reference

#include <RooCubicSplineKnot.h>

Classes

class  BoundaryConditions
 
class  S2_edge
 
class  S2_jk
 
class  S_edge
 
class  S_jk
 

Public Member Functions

 RooCubicSplineKnot (const double *array, int nEntries)
 
template<typename Iter >
 RooCubicSplineKnot (Iter begin, Iter end)
 
 RooCubicSplineKnot (const std::vector< double > &knots)
 
double u (int i) const
 
int size () const
 
double evaluate (double _u, const RooArgList &b) const
 
double analyticalIntegral (const RooArgList &b) const
 
void computeCoefficients (std::vector< double > &y, BoundaryConditions bc=BoundaryConditions()) const
 
void smooth (std::vector< double > &y, const std::vector< double > &dy, double lambda) const
 
const std::vector< double > & knots () const
 
RooCubicSplineKnot::S_jk S_jk_sum (int i, const RooArgList &b) const
 
RooCubicSplineKnot::S2_jk S2_jk_sum (int i, const RooArgList &b1, const RooArgList &b2) const
 
RooCubicSplineKnot::S_edge S_jk_edge (bool left, const RooArgList &b) const
 
RooCubicSplineKnot::S2_edge S2_jk_edge (bool left, const RooArgList &b1, const RooArgList &b2) const
 
double expIntegral (const TH1 *hist, double gamma, TVectorD &coefficients, TMatrixD &covarianceMatrix) const
 

Private Member Functions

int index (double u_) const
 
double A (double u_, int i) const
 
double B (double u_, int i) const
 
double C (double u_, int i) const
 
double D (double u_, int i) const
 
double ma (int i, bool bc[]) const
 
double mc (int i, bool bc[]) const
 
double mb (int i, bool bc[]) const
 
double P (int i) const
 
double Q (int i) const
 
double R (int i) const
 
double S (int i) const
 
void fillPQRS () const
 
double d (double u_, int j) const
 
double d (double u_, int i, int j, int k) const
 
double h (int i, int j) const
 
double h (int i) const
 
double r (int i) const
 
double f (int i) const
 
double p (int i) const
 

Static Private Member Functions

static double sqr (double x)
 
static double cub (double x)
 
static double qua (double x)
 

Private Attributes

std::vector< double > _u
 
std::vector< double > _PQRS
 
std::vector< double > _IABCD
 
std::vector< RooCubicSplineKnot::S_jk_S_jk
 
std::vector< RooCubicSplineKnot::S2_jk_S2_jk
 

Detailed Description

Definition at line 12 of file RooCubicSplineKnot.h.

Constructor & Destructor Documentation

◆ RooCubicSplineKnot() [1/3]

RooCubicSplineKnot::RooCubicSplineKnot ( const double *  array,
int  nEntries 
)
inline

Definition at line 26 of file RooCubicSplineKnot.h.

26 : _u( array, array+nEntries) {}
std::vector< double > _u

◆ RooCubicSplineKnot() [2/3]

template<typename Iter >
RooCubicSplineKnot::RooCubicSplineKnot ( Iter  begin,
Iter  end 
)
inline

Definition at line 27 of file RooCubicSplineKnot.h.

27 : _u(begin,end) {}
std::vector< double > _u

◆ RooCubicSplineKnot() [3/3]

RooCubicSplineKnot::RooCubicSplineKnot ( const std::vector< double > &  knots)
inline

Definition at line 28 of file RooCubicSplineKnot.h.

29  : _u(knots) {}
const std::vector< double > & knots() const
std::vector< double > _u

Member Function Documentation

◆ A()

double RooCubicSplineKnot::A ( double  u_,
int  i 
) const
inlineprivate

Definition at line 210 of file RooCubicSplineKnot.h.

210 { return -cub(d(u_,i+1))/P(i); }
static double cub(double x)
double d(double u_, int j) const
double P(int i) const

◆ analyticalIntegral()

double RooCubicSplineKnot::analyticalIntegral ( const RooArgList &  b) const

Definition at line 147 of file RooCubicSplineKnot.cpp.

147  {
150  if (_IABCD.empty()) {
151  // the integrals of A,B,C,D from u(i) to u(i+1) only depend on the knot vector...
152  // so we create them 'on demand' and cache the result
153  _IABCD.reserve(4*size());
154  for (int j=0;j<size();++j) {
155  push_back(_IABCD, qua(h(j,j+1))/(4*P(j))
156  , - cub(h(j,j+1))*(3*u(j)-4*u(j-2)+u(j+1))/(12*P(j))
157  - sqr(h(j,j+1))*(3*sqr(u(j))-2*u(j-1)*u(j+1)+sqr(u(j+1))+u(j)*(-4*u(j-1)+2*u(j+1)-4*u(j+2)) +6*u(j-1)*u(j+2)-2*u(j+1)*u(j+2) )/(12*Q(j))
158  + sqr(h(j,j+1))*(3*sqr(u(j+1))+sqr(u(j ))+2*u(j)*u(j+1)-8*u(j+1)*u(j+2)-4*u(j )*u(j+2)+6*sqr(u(j+2)))/(12*R(j))
159  , sqr(h(j,j+1))*(3*sqr(u(j ))+sqr(u(j+1))+2*u(j+1)*u(j)-8*u(j )*u(j-1)-4*u(j-1)*u(j+1)+6*sqr(u(j-1)))/(12*Q(j))
160  - sqr(h(j,j+1))*(3*sqr(u(j+1))+sqr(u(j))-4*u(j-1)*u(j+1)+6*u(j-1)*u(j+2)-4*u(j+1)*u(j+2)-2*u(j)*(u(j-1)-u(j+1)+u(j+2)))/(12*R(j))
161  + cub(h(j,j+1))*(3*u(j+1)-4*u(j+3)+u(j))/(12*S(j))
162  , qua(h(j,j+1))/(4*S(j)) );
163  }
164  }
165  // FIXME: this assumes the integration range goes from first knot to last knot...
166  assert(b.getSize()-2==size());
167  double norm(0);
168  for (int i=0; i < size()-1; ++i) for (int k=0;k<4;++k) {
169  norm += get(b,i,k)*RooCubicSplineKnot_aux::get(_IABCD,i,k) ;
170  }
171  return norm;
172 }
double S(int i) const
static double cub(double x)
double Q(int i) const
double h(int i, int j) const
static double qua(double x)
static double sqr(double x)
double R(int i) const
double u(int i) const
double P(int i) const
void push_back(T &t, const typename T::value_type &a, const typename T::value_type &b, const typename T::value_type &c, const typename T::value_type &d)
Double_t get(const RooArgList &b, int i)
std::vector< double > _IABCD
T::const_reference get(const T &t, int i, int j)

◆ B()

double RooCubicSplineKnot::B ( double  u_,
int  i 
) const
inlineprivate

Definition at line 211 of file RooCubicSplineKnot.h.

211 { return sqr(d(u_,i+1))*d(u_,i-2)/P(i) + d(u_,i-1)*d(u_,i+2)*d(u_,i+1)/Q(i) + d(u_,i )*sqr(d(u_,i+2))/R(i); }
double Q(int i) const
static double sqr(double x)
double R(int i) const
double d(double u_, int j) const
double P(int i) const

◆ C()

double RooCubicSplineKnot::C ( double  u_,
int  i 
) const
inlineprivate

Definition at line 212 of file RooCubicSplineKnot.h.

212 { return -sqr(d(u_,i-1))*d(u_,i+1)/Q(i) - d(u_,i )*d(u_,i+2)*d(u_,i-1)/R(i) - d(u_,i+3)*sqr(d(u_,i ))/S(i); }
double S(int i) const
double Q(int i) const
static double sqr(double x)
double R(int i) const
double d(double u_, int j) const

◆ computeCoefficients()

void RooCubicSplineKnot::computeCoefficients ( std::vector< double > &  y,
BoundaryConditions  bc = BoundaryConditions() 
) const

Definition at line 84 of file RooCubicSplineKnot.cpp.

85 {
86  // see http://en.wikipedia.org/wiki/Spline_interpolation
87  // for the derivation of the linear system...
88  // see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
89  // for the O(N) algorithm to solve the relevant linear system...
90  int n = size();
91  assert(int(y.size())==size());
92 
93  // Weights of first and last spline are fully determined by values at knots
94  double bf = y.front();
95  double bb = y.back();
96 
97  // Set boundary conditions for linear system
98  y.front() = bc.value[0] - bf * ( bc.secondDerivative[0] ? ( double(6) / sqr(h(0)) ) : ( -double(3) / h(0) ) );
99  y.back() = bc.value[1] - bb * ( bc.secondDerivative[1] ? ( double(6) / sqr(h(n-2))) : ( double(3) / h(n-2) ) );
100 
101  // Solve linear system
102  std::vector<double> c; c.reserve(n);
103  c.push_back( mc(0, bc.secondDerivative) / mb(0, bc.secondDerivative) );
104  y[0] /= mb(0, bc.secondDerivative);
105  // TODO: rewrite the special cases i==1 and i==n-1 (move latter out of loop)
106  // so we can avoid 'if' statements in the loop body...
107  for (int i = 1; i < n; ++i) {
108  double m = double(1) / ( mb(i, bc.secondDerivative ) - ma(i, bc.secondDerivative) * c.back() );
109  c.push_back( mc(i,bc.secondDerivative) * m );
110  y[i] -= ma(i, bc.secondDerivative) * y[i - 1];
111  y[i] *= m;
112  }
113  for (int i = n-1 ; i-- > 0; ) y[i] -= c[i] * y[i + 1];
114  y.push_back(bb); y.insert(y.begin(),bf); // ouch... expensive!
115 }
double mb(int i, bool bc[]) const
double h(int i, int j) const
static double sqr(double x)
double mc(int i, bool bc[]) const
static const double m
double ma(int i, bool bc[]) const

◆ cub()

static double RooCubicSplineKnot::cub ( double  x)
inlinestaticprivate

Definition at line 252 of file RooCubicSplineKnot.h.

252 { return x*sqr(x); }
static double sqr(double x)

◆ D()

double RooCubicSplineKnot::D ( double  u_,
int  i 
) const
inlineprivate

Definition at line 213 of file RooCubicSplineKnot.h.

213 { return cub(d(u_,i ))/S(i); }
double S(int i) const
static double cub(double x)
double d(double u_, int j) const

◆ d() [1/2]

double RooCubicSplineKnot::d ( double  u_,
int  j 
) const
inlineprivate

Definition at line 254 of file RooCubicSplineKnot.h.

254 { return u_-u(j); }
double u(int i) const

◆ d() [2/2]

double RooCubicSplineKnot::d ( double  u_,
int  i,
int  j,
int  k 
) const
inlineprivate

Definition at line 255 of file RooCubicSplineKnot.h.

255 { return d(u_,i)*d(u_,j)*d(u_,k); }
double d(double u_, int j) const

◆ evaluate()

double RooCubicSplineKnot::evaluate ( double  _u,
const RooArgList &  b 
) const

Definition at line 133 of file RooCubicSplineKnot.cpp.

133  {
135  int i = index(x); // location in knot vector: index of last knot less than x...
136  assert(-1<=i && i<=size());
137  // we're a 'natural' spline. If beyond first/last knot, Extrapolate using the derivative at the first (last) knot
138  if (i==-1 ) { ++i; return get(b,i,0) - d(x,i)*r(i )*(get(b,i,0)-get(b,i,1)); }
139  if (i==size()) { --i; return get(b,i,2) + d(x,i)*r(i-1)*(get(b,i,2)-get(b,i,1)); }
140  assert( u(i) <= x && x<= u(i+1) );
141  return get(b,i,0)*A(x,i) // TODO: substitute A,B,C,D 'in situ'
142  + get(b,i,1)*B(x,i)
143  + get(b,i,2)*C(x,i)
144  + get(b,i,3)*D(x,i);
145 }
double D(double u_, int i) const
double C(double u_, int i) const
double B(double u_, int i) const
int index(double u_) const
double d(double u_, int j) const
double u(int i) const
double r(int i) const
Double_t get(const RooArgList &b, int i)
double A(double u_, int i) const
T::const_reference get(const T &t, int i, int j)

◆ expIntegral()

double RooCubicSplineKnot::expIntegral ( const TH1 *  hist,
double  gamma,
TVectorD coefficients,
TMatrixD &  covarianceMatrix 
) const

Definition at line 367 of file RooCubicSplineKnot.cpp.

367  {
368  assert(hist!=0);
369  int nknots = size();
370  int nsplines = nknots+2;
371  int nbins = hist->GetNbinsX();
372  TMatrixD matrix(nsplines,nbins); for (int i=0;i<nsplines;++i) for (int j=0;j<nbins;++j) { matrix(i,j)=0; }
373  TVectorD Y(nbins), DY(nbins);
374 
375  for (int i=0;i<nbins ;++i) {
376  Y(i) = hist->GetBinContent(1+i);
377  DY(i) = hist->GetBinError(1+i);
378 
379 
380  Y(i) /= DY(i)*DY(i);
381 
382  double lo = hist->GetBinLowEdge(1+i);
383  double hi = lo + hist->GetBinWidth(1+i);
384 
385  double Norm = (exp(-gamma*lo)-exp(-gamma*hi))/gamma;
386 
387  // go for flat parent distribution;
388  // Norm = hi-lo;
389 
390 #if 0
391  // compute contributions beyond the first and last knot...
392  if (lo < _u.front()) {
393  // b-spline 0: 1 - d(x,0)*r(0) // d(x,0) = x - u(0)
394  // b-spline 1: + d(x,0)*r(0)
395  matrix(0, 0) += eIn( lo,hi, 1., -r(0), u(0) )/Norm;
396  matrix(1, 0) += eIn( lo,hi, 0., +r(0), u(0) )/Norm;
397 
398  }
399  if (hi > _u.back()) {
400  // c + alpha * (x - x0)
401  matrix(nknots , nbins-1) += eIn( lo, hi, 0., -r(nknots-2), u(nknots-1) )/Norm;
402  matrix(nknots+1, nbins-1) += eIn( lo, hi, 1., +r(nknots-2), u(nknots-1) )/Norm;
403 
404  }
405 #else
406  // assume nothing beyond spline interval
407  assert( lo >= _u.front() && hi <= _u.back() );
408 #endif
409 
410  // this bit is by construction fully contained between the first and last knot
411  for (int j=0;j<nknots-1;++j) {
412  double l = std::max(lo,u(j));
413  double h = std::min(hi,u(j+1));
414  if (l>=h) continue;
415  // in the knot interval [ u(j), u(j+1) ], the splines j..j+3 contribute...
416  matrix(j ,i) += (-eI(l,h, u(j+1),u(j+1),u(j+1), gamma)/P(j) ) / Norm;
417  matrix(j+1,i) += ( eI(l,h, u(j-2),u(j+1),u(j+1), gamma)/P(j)
418  +eI(l,h, u(j-1),u(j+1),u(j+2), gamma)/Q(j)
419  +eI(l,h, u(j ),u(j+2),u(j+2), gamma)/R(j) ) / Norm;
420  matrix(j+2,i) += (-eI(l,h, u(j-1),u(j-1),u(j+1), gamma)/Q(j)
421  -eI(l,h, u(j-1),u(j ),u(j+2), gamma)/R(j)
422  -eI(l,h, u(j ),u(j ),u(j+3), gamma)/S(j) ) / Norm;
423  matrix(j+3,i) += ( eI(l,h, u(j ),u(j ),u(j ), gamma)/S(j) ) / Norm;
424  }
425 
426  }
427 
428  TMatrixDSym D(nsplines);
429  for (int i=0;i<nsplines;++i) for (int j=0;j<=i;++j) {
430  D(i,j) = 0;
431  for (int k=0;k<nbins;++k) D(i,j) += matrix(i,k)*matrix(j,k)/(DY(k)*DY(k));
432  if (i!=j) D(j,i) = D(i,j);
433  }
434  TDecompBK solver(D);
435 
436  Y *= matrix;
437  TVectorD YY = Y;
438 
439  bool ok;
440  coefficients.ResizeTo(nsplines);
441  coefficients = solver.Solve(Y,ok);
442  if (!ok) {
443  std::cout << "WARNING: bad linear system solution... " << std::endl;
444  return -1;
445  }
446 
447  D.Invert();
448  covarianceMatrix.ResizeTo(D);
449  covarianceMatrix = D;
450 
451  double chisq = 0;
452  for (int i=0;i<nbins;++i) {
453  double y = hist->GetBinContent(1+i);
454  double dy = hist->GetBinError(1+i);
455  double f = 0; for (int j=0;j<nsplines;++j) f+=matrix(j,i)*coefficients(j);
456  double c = sqr( (y-f)/dy );
457  // double lo = hist->GetBinLowEdge(1+i);
458  // double hi = lo + hist->GetBinWidth(1+i);
459  // std::cout << " bin " << i << " [ " << lo << " , " << hi << " ] y = " << y << " dy = " << dy << " f = " << f << " chi^2 = " << c << std::endl;
460  chisq+=c;
461  }
462 
463  return chisq;
464  // silence compiler warning about fI being unused
465  (void) fI;
466 }
double S(int i) const
double D(double u_, int i) const
double Q(int i) const
double f(int i) const
double h(int i, int j) const
static double sqr(double x)
double R(int i) const
double u(int i) const
std::vector< double > _u
double P(int i) const
double r(int i) const

◆ f()

double RooCubicSplineKnot::f ( int  i) const
inlineprivate

Definition at line 259 of file RooCubicSplineKnot.h.

259 { return -r(i-1)-r(i); }
double r(int i) const

◆ fillPQRS()

void RooCubicSplineKnot::fillPQRS ( ) const
private

Definition at line 120 of file RooCubicSplineKnot.cpp.

120  {
121  assert(_PQRS.empty());
122  // P,Q,R,S only depend on the knot vector, so build at construction, and cache them...
123  _PQRS.reserve(4*size());
124  for (int i=0;i<size();++i) {
125  _PQRS.push_back( h(i+1,i-2)*h(i+1,i-1)*h(i+1,i) );
126  _PQRS.push_back( h(i+1,i-1)*h(i+2,i-1)*h(i+1,i) );
127  _PQRS.push_back( h(i+2,i )*h(i+2,i-1)*h(i+1,i) );
128  _PQRS.push_back( h(i+2,i )*h(i+3,i )*h(i+1,i) );
129  }
130 
131 }
std::vector< double > _PQRS
double h(int i, int j) const

◆ h() [1/2]

double RooCubicSplineKnot::h ( int  i,
int  j 
) const
inlineprivate

Definition at line 256 of file RooCubicSplineKnot.h.

256 { return u(i)-u(j); }
double u(int i) const

◆ h() [2/2]

double RooCubicSplineKnot::h ( int  i) const
inlineprivate

Definition at line 257 of file RooCubicSplineKnot.h.

257 { return h(i+1,i); }
double h(int i, int j) const

◆ index()

int RooCubicSplineKnot::index ( double  u_) const
private

Definition at line 175 of file RooCubicSplineKnot.cpp.

176 {
177  if (u>_u.back()) return size();
178  std::vector<double>::const_iterator i = --std::upper_bound(_u.begin(),_u.end()-1,u);
179  return std::distance(_u.begin(),i);
180 }
double u(int i) const
std::vector< double > _u

◆ knots()

const std::vector<double>& RooCubicSplineKnot::knots ( ) const
inline

Definition at line 43 of file RooCubicSplineKnot.h.

43 { return _u; }
std::vector< double > _u

◆ ma()

double RooCubicSplineKnot::ma ( int  i,
bool  bc[] 
) const
inlineprivate

Definition at line 216 of file RooCubicSplineKnot.h.

216  { // subdiagonal
217 
218  return (i!=size()-1) ? A(u(i),i)
219  : (bc[1] ) ? double(6)/(h(i,i-2)*h(i-1))
220  : double(0) ;
221  }
double h(int i, int j) const
double u(int i) const
double A(double u_, int i) const

◆ mb()

double RooCubicSplineKnot::mb ( int  i,
bool  bc[] 
) const
inlineprivate

Definition at line 229 of file RooCubicSplineKnot.h.

229  { // diagonal
230  if (i!=0 && i!=size()-1) return B(u(i),i);
231 
232  if (i==0) {
233  return bc[0] ? -(double(6)/h(i)+double(6)/h(i+2,i))/h(i)
234  : double(3)/h(i);
235  } else {
236  return bc[1] ? -(double(6)/h(i-1)+double(6)/h(i,i-2))/h(i-1)
237  : - double(3)/h(i-1);
238  }
239  }
double B(double u_, int i) const
double h(int i, int j) const
double u(int i) const

◆ mc()

double RooCubicSplineKnot::mc ( int  i,
bool  bc[] 
) const
inlineprivate

Definition at line 223 of file RooCubicSplineKnot.h.

223  { // superdiagonal
224  return (i!=0) ? C(u(i),i)
225  : bc[0] ? double(6)/(h(2,0)*h(0))
226  : double(0);
227  }
double C(double u_, int i) const
double h(int i, int j) const
double u(int i) const

◆ P()

double RooCubicSplineKnot::P ( int  i) const
inlineprivate

Definition at line 244 of file RooCubicSplineKnot.h.

244 { if (_PQRS.empty()) fillPQRS(); assert(4*i <int(_PQRS.size())); return _PQRS[4*i ]; }
std::vector< double > _PQRS

◆ p()

double RooCubicSplineKnot::p ( int  i) const
inlineprivate

Definition at line 260 of file RooCubicSplineKnot.h.

260 { return 2*h(i-1)+h(i); }
double h(int i, int j) const

◆ Q()

double RooCubicSplineKnot::Q ( int  i) const
inlineprivate

Definition at line 245 of file RooCubicSplineKnot.h.

245 { if (_PQRS.empty()) fillPQRS(); assert(4*i+1<int(_PQRS.size())); return _PQRS[4*i+1]; }
std::vector< double > _PQRS

◆ qua()

static double RooCubicSplineKnot::qua ( double  x)
inlinestaticprivate

Definition at line 253 of file RooCubicSplineKnot.h.

253 { return sqr(sqr(x)); }
static double sqr(double x)

◆ R()

double RooCubicSplineKnot::R ( int  i) const
inlineprivate

Definition at line 246 of file RooCubicSplineKnot.h.

246 { if (_PQRS.empty()) fillPQRS(); assert(4*i+2<int(_PQRS.size())); return _PQRS[4*i+2]; }
std::vector< double > _PQRS

◆ r()

double RooCubicSplineKnot::r ( int  i) const
inlineprivate

Definition at line 258 of file RooCubicSplineKnot.h.

258 { return double(3)/h(i); }
double h(int i, int j) const

◆ S()

double RooCubicSplineKnot::S ( int  i) const
inlineprivate

Definition at line 247 of file RooCubicSplineKnot.h.

247 { if (_PQRS.empty()) fillPQRS(); assert(4*i+3<int(_PQRS.size())); return _PQRS[4*i+3]; }
std::vector< double > _PQRS

◆ S2_jk_edge()

RooCubicSplineKnot::S2_edge RooCubicSplineKnot::S2_jk_edge ( bool  left,
const RooArgList &  b1,
const RooArgList &  b2 
) const

Definition at line 297 of file RooCubicSplineKnot.cpp.

297  {
299  if (left) {
300  double alpha1 = -r(0)*(get(b1,0,0)-get(b1,0,1));
301  double beta1 = evaluate(u(0),b1)-alpha1*u(0);
302  double alpha2 = -r(0)*(get(b2,0,0)-get(b2,0,1));
303  double beta2 = evaluate(u(0),b2)-alpha2*u(0);
304  return S2_edge(alpha1,beta1,alpha2,beta2);
305  } else {
306  int i = size()-1;
307  double alpha1 = r(i-1)*(get(b1,i,2)-get(b1,i,1));
308  double beta1 = evaluate(u(i),b1)-alpha1*u(i);
309  double alpha2 = r(i-1)*(get(b2,i,2)-get(b2,i,1));
310  double beta2 = evaluate(u(i),b2)-alpha2*u(i);
311  return S2_edge(alpha1,beta1,alpha2,beta2);
312  }
313 }
double u(int i) const
double evaluate(double _u, const RooArgList &b) const
double r(int i) const
Double_t get(const RooArgList &b, int i)
T::const_reference get(const T &t, int i, int j)

◆ S2_jk_sum()

RooCubicSplineKnot::S2_jk RooCubicSplineKnot::S2_jk_sum ( int  i,
const RooArgList &  b1,
const RooArgList &  b2 
) const

Definition at line 207 of file RooCubicSplineKnot.cpp.

208 {
209  if (_S2_jk.empty()) {
210  _S2_jk.reserve(size()*10);
211  for(int j=0;j<size();++j) {
212  // This 'table' should be compatible with the definitions of A,B,C, and D...
213  _S2_jk.push_back( RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j+1),u(j+1),u(j+1)) / (P(j)*P(j)) ); // (A * A)
214 
215  _S2_jk.push_back( RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j-2),u(j+1),u(j+1)) / (P(j)*P(j))
216  +RooCubicSplineKnot::S2_jk(u(j-1),u(j+1),u(j+2),u(j-1),u(j+1),u(j+2)) / (Q(j)*Q(j))
217  +RooCubicSplineKnot::S2_jk(u(j ),u(j+2),u(j+2),u(j ),u(j+2),u(j+2)) / (R(j)*R(j))
218  +RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j-1),u(j+1),u(j+2)) / (P(j)*Q(j)) * 2.
219  +RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j ),u(j+2),u(j+2)) / (P(j)*R(j)) * 2.
220  +RooCubicSplineKnot::S2_jk(u(j-1),u(j+1),u(j+2),u(j ),u(j+2),u(j+2)) / (Q(j)*R(j)) * 2. ); // (B * B)
221 
222  _S2_jk.push_back( RooCubicSplineKnot::S2_jk(u(j-1),u(j-1),u(j+1),u(j-1),u(j-1),u(j+1)) / (Q(j)*Q(j))
223  +RooCubicSplineKnot::S2_jk(u(j-1),u(j ),u(j+2),u(j-1),u(j ),u(j+2)) / (R(j)*R(j))
224  +RooCubicSplineKnot::S2_jk(u(j ),u(j ),u(j+3),u(j ),u(j ),u(j+3)) / (S(j)*S(j))
225  +RooCubicSplineKnot::S2_jk(u(j-1),u(j-1),u(j+1),u(j-1),u(j ),u(j+2)) / (Q(j)*R(j)) * 2.
226  +RooCubicSplineKnot::S2_jk(u(j-1),u(j-1),u(j+1),u(j ),u(j ),u(j+3)) / (Q(j)*S(j)) * 2.
227  +RooCubicSplineKnot::S2_jk(u(j-1),u(j ),u(j+2),u(j ),u(j ),u(j+3)) / (R(j)*S(j)) * 2. ); // (C * C)
228 
229  _S2_jk.push_back( RooCubicSplineKnot::S2_jk(u(j ),u(j ),u(j ),u(j ),u(j ),u(j )) / (S(j)*S(j)) ); // (D * D)
230 
231 
232  _S2_jk.push_back( -RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j-2),u(j+1),u(j+1)) / (P(j)*P(j))
233  -RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j-1),u(j+1),u(j+2)) / (P(j)*Q(j))
234  -RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j ),u(j+2),u(j+2)) / (P(j)*R(j)) ); // (A * B)
235 
236  _S2_jk.push_back( RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j-1),u(j-1),u(j+1)) / (P(j)*Q(j))
237  +RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j-1),u(j ),u(j+2)) / (P(j)*R(j))
238  +RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j ),u(j ),u(j+3)) / (P(j)*S(j)) ); // (A * C)
239 
240  _S2_jk.push_back( -RooCubicSplineKnot::S2_jk(u(j+1),u(j+1),u(j+1),u(j ),u(j ),u(j )) / (P(j)*S(j)) ); // (A * D)
241 
242 
243  _S2_jk.push_back( -RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j-1),u(j-1),u(j+1)) / (P(j)*Q(j))
244  -RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j-1),u(j ),u(j+2)) / (P(j)*R(j))
245  -RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j ),u(j ),u(j+3)) / (P(j)*S(j))
246  -RooCubicSplineKnot::S2_jk(u(j-1),u(j+1),u(j+2),u(j-1),u(j-1),u(j+1)) / (Q(j)*Q(j))
247  -RooCubicSplineKnot::S2_jk(u(j-1),u(j+1),u(j+2),u(j-1),u(j ),u(j+2)) / (Q(j)*R(j))
248  -RooCubicSplineKnot::S2_jk(u(j-1),u(j+1),u(j+2),u(j ),u(j ),u(j+3)) / (Q(j)*S(j))
249  -RooCubicSplineKnot::S2_jk(u(j ),u(j+2),u(j+2),u(j-1),u(j-1),u(j+1)) / (R(j)*Q(j))
250  -RooCubicSplineKnot::S2_jk(u(j ),u(j+2),u(j+2),u(j-1),u(j ),u(j+2)) / (R(j)*R(j))
251  -RooCubicSplineKnot::S2_jk(u(j ),u(j+2),u(j+2),u(j ),u(j ),u(j+3)) / (R(j)*S(j)) ); // (B * C)
252 
253  _S2_jk.push_back( RooCubicSplineKnot::S2_jk(u(j-2),u(j+1),u(j+1),u(j ),u(j ),u(j )) / (P(j)*S(j))
254  +RooCubicSplineKnot::S2_jk(u(j-1),u(j+1),u(j+2),u(j ),u(j ),u(j )) / (Q(j)*S(j))
255  +RooCubicSplineKnot::S2_jk(u(j ),u(j+2),u(j+2),u(j ),u(j ),u(j )) / (R(j)*S(j)) ); // (B * D)
256 
257  _S2_jk.push_back( -RooCubicSplineKnot::S2_jk(u(j-1),u(j-1),u(j+1),u(j ),u(j ),u(j )) / (Q(j)*S(j))
258  -RooCubicSplineKnot::S2_jk(u(j-1),u(j ),u(j+2),u(j ),u(j ),u(j )) / (R(j)*S(j))
259  -RooCubicSplineKnot::S2_jk(u(j ),u(j ),u(j+3),u(j ),u(j ),u(j )) / (S(j)*S(j)) ); // (C * D)
260  }
261  }
264  return get2(_S2_jk,i,0)*get(b1,i,0)*get(b2,i,0)
265  + get2(_S2_jk,i,1)*get(b1,i,1)*get(b2,i,1)
266  + get2(_S2_jk,i,2)*get(b1,i,2)*get(b2,i,2)
267  + get2(_S2_jk,i,3)*get(b1,i,3)*get(b2,i,3)
268  + get2(_S2_jk,i,4)*(get(b1,i,0)*get(b2,i,1)+get(b1,i,1)*get(b2,i,0))
269  + get2(_S2_jk,i,5)*(get(b1,i,0)*get(b2,i,2)+get(b1,i,2)*get(b2,i,0))
270  + get2(_S2_jk,i,6)*(get(b1,i,0)*get(b2,i,3)+get(b1,i,3)*get(b2,i,0))
271  + get2(_S2_jk,i,7)*(get(b1,i,1)*get(b2,i,2)+get(b1,i,2)*get(b2,i,1))
272  + get2(_S2_jk,i,8)*(get(b1,i,1)*get(b2,i,3)+get(b1,i,3)*get(b2,i,1))
273  + get2(_S2_jk,i,9)*(get(b1,i,2)*get(b2,i,3)+get(b1,i,3)*get(b2,i,2));
274 }
double S(int i) const
double Q(int i) const
double R(int i) const
double u(int i) const
std::vector< RooCubicSplineKnot::S2_jk > _S2_jk
double P(int i) const
Double_t get(const RooArgList &b, int i)
T::const_reference get(const T &t, int i, int j)
T::const_reference get2(const T &t, int i, int j)

◆ S_jk_edge()

RooCubicSplineKnot::S_edge RooCubicSplineKnot::S_jk_edge ( bool  left,
const RooArgList &  b 
) const

Definition at line 281 of file RooCubicSplineKnot.cpp.

281  {
283  if (left) {
284  // efficiency = return evaluate(u(0),b) - d(x,0)*r(0)*(get(b,0,0)-get(b,0,1));
285  double alpha = -r(0)*(get(b,0,0)-get(b,0,1));
286  double beta = evaluate(u(0),b)-alpha*u(0);
287  return S_edge( alpha, beta );
288  } else {
289  int i = size()-1;
290  double alpha = r(i-1)*(get(b,i,2)-get(b,i,1));
291  double beta = evaluate(u(i),b)-alpha*u(i);
292  return S_edge(alpha,beta);
293  }
294 }
double u(int i) const
double evaluate(double _u, const RooArgList &b) const
double r(int i) const
Double_t get(const RooArgList &b, int i)
T::const_reference get(const T &t, int i, int j)

◆ S_jk_sum()

RooCubicSplineKnot::S_jk RooCubicSplineKnot::S_jk_sum ( int  i,
const RooArgList &  b 
) const

Definition at line 183 of file RooCubicSplineKnot.cpp.

184 {
185  if (_S_jk.empty()) {
186  _S_jk.reserve(size()*4);
187  for(int j=0;j<size();++j) {
188  // This 'table' should be compatible with the definitions of A,B,C, and D...
189  _S_jk.push_back( -RooCubicSplineKnot::S_jk(u(j+1),u(j+1),u(j+1))/P(j) ); // A
190  _S_jk.push_back( RooCubicSplineKnot::S_jk(u(j-2),u(j+1),u(j+1))/P(j)
191  +RooCubicSplineKnot::S_jk(u(j-1),u(j+1),u(j+2))/Q(j)
192  +RooCubicSplineKnot::S_jk(u(j ),u(j+2),u(j+2))/R(j) ); // B
193  _S_jk.push_back( -RooCubicSplineKnot::S_jk(u(j-1),u(j-1),u(j+1))/Q(j)
194  -RooCubicSplineKnot::S_jk(u(j-1),u(j ),u(j+2))/R(j)
195  -RooCubicSplineKnot::S_jk(u(j ),u(j ),u(j+3))/S(j) ); // C
196  _S_jk.push_back( RooCubicSplineKnot::S_jk(u(j ),u(j ),u(j ))/S(j) ); // D
197  }
198  }
200  return get(_S_jk,i,0)*get(b,i,0)
201  + get(_S_jk,i,1)*get(b,i,1)
202  + get(_S_jk,i,2)*get(b,i,2)
203  + get(_S_jk,i,3)*get(b,i,3);
204 }
double S(int i) const
std::vector< RooCubicSplineKnot::S_jk > _S_jk
double Q(int i) const
double R(int i) const
double u(int i) const
double P(int i) const
Double_t get(const RooArgList &b, int i)
T::const_reference get(const T &t, int i, int j)

◆ size()

int RooCubicSplineKnot::size ( ) const
inline

Definition at line 36 of file RooCubicSplineKnot.h.

36 { return _u.size(); }
std::vector< double > _u

◆ smooth()

void RooCubicSplineKnot::smooth ( std::vector< double > &  y,
const std::vector< double > &  dy,
double  lambda 
) const

Definition at line 26 of file RooCubicSplineKnot.cpp.

26  {
27 // implementation as described in D.S.G. Pollock, Smoothing Splines"
28 // see http://r.789695.n4.nabble.com/file/n905996/SPLINES.PDF
29  using namespace std;
30  int n = y.size();
31  vector<double> uu(n-2),vv(n-3),ww(n-4), q(n-2);
32  assert( dy.size()==y.size());
33  assert( size()==n);
34  // lambda = 0 : no smoothing ; lambda -> 1: straight line (the ultimate smooth curve)
35  if (lambda<0|| !(lambda<1)) {
36  throw std::string("RooCubicSplineKnot::smooth: smoothing parameter must be in range [0,1)");
37  }
38  double mu =2*lambda/(3*(1-lambda));
39  for (int i=0;i<n-2;++i) {
40  q[i] = r(i)*(y[i]-y[i+1])-r(i+1)*(y[i+1]-y[i+2]);
41  uu[i] = p(i+1)+mu*(sqr(r(i)*dy[i])+sqr(f(i+1)*dy[i+1])+sqr(r(i+1)*dy[i+2]) );
42  if (i>n-4) continue;
43  vv[i] = h(i+1)+mu*(f(i+1)*r(i+1)*sqr(dy[i+1]) + f(i+1)*r(i+2)*sqr(dy[i+2]));
44  if (i>n-5) continue ;
45  ww[i] = mu*r(i+1)*r(i+2)*sqr(dy[i+2]);
46  }
47 
48  // Solve A b = q with A(i,i)=uu(i), A(i+1,i)=A(i,i+1) = vv(i), A(i+2,i),A(i,i+2)=ww(i)
49  // start with factorization: A -> L D LT
50  vv[0] /= uu[0]; ww[0] /= uu[0];
51  uu[1] -= uu[0]*sqr(vv[0]);
52  vv[1] -= uu[0]*vv[0]*ww[0];
53  vv[1] /= uu[1]; ww[1] /= uu[1];
54  for (int i=2;i<n-4;++i) {
55  uu[i] -= uu[i-1]*sqr(vv[i-1])+uu[i-2]*sqr(ww[i-2]);
56  vv[i] -= uu[i-1]*vv[i-1]*ww[i-1]; vv[i] /= uu[i];
57  ww[i] /= uu[i];
58  }
59  uu[n-4] -= uu[n-5]*sqr(vv[n-5])+uu[n-6]*sqr(ww[n-6]);
60  vv[n-4] -= uu[n-5]*vv[n-5]*ww[n-5]; vv[n-4] /= uu[n-4];
61  uu[n-3] -= uu[n-4]*sqr(vv[n-4])+uu[n-5]*sqr(ww[n-5]);
62 
63  // forward substitution (i.e. solve L ( D LT b ) = q for D LT b -> q
64  q[1] -= vv[0 ]*q[0 ];
65  for (int i=2;i<n-2;++i) q[i] -= vv[i-1]*q[i-1]+ww[i-2]*q[i-2];
66  // rescale (i.e. solve D (LT b ) = q for LT b
67  for (int i=0;i<n-2;++i) { q[i] /= uu[i] ; }
68  // backward substitution (i.e. solve LT b = q for b -> q )
69  q[n-4] -= vv[n-4]*q[n-3];
70  for (int i=n-5;i>=0;--i) q[i ] -= vv[i ]*q[i+1]+ww[i]*q[i+2];
71  // solve for y...
72  int i=0;
73  y[i] -=mu*sqr(dy[i])*(r(i)*q[i] ); ++i;
74  y[i] -=mu*sqr(dy[i])*(r(i)*q[i]+f(i)*q[i-1] ); ++i;
75  for (;i<n-2;++i) y[i]-=mu*sqr(dy[i])*(r(i)*q[i]+f(i)*q[i-1]+r(i-1)*q[i-2]);
76  y[i] -=mu*sqr(dy[i])*( f(i)*q[i-1]+r(i-1)*q[i-2]); ++i;
77  y[i] -=mu*sqr(dy[i])*( r(i-1)*q[i-2]);
78 
79 }
double f(int i) const
double h(int i, int j) const
static double sqr(double x)
double r(int i) const
double lambda(double x, double y, double z)
Definition: lambda.h:8
double p(int i) const

◆ sqr()

static double RooCubicSplineKnot::sqr ( double  x)
inlinestaticprivate

Definition at line 251 of file RooCubicSplineKnot.h.

251 { return x*x; }

◆ u()

double RooCubicSplineKnot::u ( int  i) const
inline

Definition at line 31 of file RooCubicSplineKnot.h.

31  {
32  assert(size());
33  assert(i>-3);
34  assert(i<size()+3);
35  return _u[std::min(std::max(0,i),size()-1)]; }
std::vector< double > _u

Member Data Documentation

◆ _IABCD

std::vector<double> RooCubicSplineKnot::_IABCD
mutableprivate

Definition at line 264 of file RooCubicSplineKnot.h.

◆ _PQRS

std::vector<double> RooCubicSplineKnot::_PQRS
mutableprivate

Definition at line 263 of file RooCubicSplineKnot.h.

◆ _S2_jk

std::vector<RooCubicSplineKnot::S2_jk> RooCubicSplineKnot::_S2_jk
mutableprivate

Definition at line 266 of file RooCubicSplineKnot.h.

◆ _S_jk

std::vector<RooCubicSplineKnot::S_jk> RooCubicSplineKnot::_S_jk
mutableprivate

Definition at line 265 of file RooCubicSplineKnot.h.

◆ _u

std::vector<double> RooCubicSplineKnot::_u
private

Definition at line 262 of file RooCubicSplineKnot.h.


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