7 #include "RooAbsReal.h" 14 Double_t
get(
const RooArgList& b,
int i) {
return ((RooAbsReal&)b[i]).getVal() ; }
17 template <
typename T>
typename T::const_reference
get(
const T& t,
int i,
int j) {
return t[4*i+j]; }
18 template <
typename T>
typename T::const_reference
get2(
const T& t,
int i,
int j) {
return t[10*i+j];}
19 template <
typename T>
void push_back(T& t,
const typename T::value_type& a,
20 const typename T::value_type& b,
21 const typename T::value_type& c,
22 const typename T::value_type& d) { t.push_back(a); t.push_back(b); t.push_back(c); t.push_back(d) ; }
31 vector<double> uu(n-2),vv(n-3),ww(n-4), q(n-2);
32 assert( dy.size()==y.size());
36 throw std::string(
"RooCubicSplineKnot::smooth: smoothing parameter must be in range [0,1)");
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]) );
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]));
45 ww[i] = mu*r(i+1)*r(i+2)*sqr(dy[i+2]);
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];
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]);
65 for (
int i=2;i<n-2;++i) q[i] -= vv[i-1]*q[i-1]+ww[i-2]*q[i-2];
67 for (
int i=0;i<n-2;++i) { q[i] /= uu[i] ; }
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];
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]);
91 assert(
int(y.size())==size());
94 double bf = y.front();
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) ) );
102 std::vector<double> c; c.reserve(n);
107 for (
int i = 1; i < n; ++i) {
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);
121 assert(_PQRS.empty());
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) );
136 assert(-1<=i && i<=size());
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)
150 if (_IABCD.empty()) {
153 _IABCD.reserve(4*size());
154 for (
int j=0;j<size();++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)) );
166 assert(b.getSize()-2==size());
168 for (
int i=0; i < size()-1; ++i)
for (
int k=0;k<4;++k) {
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);
186 _S_jk.reserve(size()*4);
187 for(
int j=0;j<size();++j) {
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);
209 if (_S2_jk.empty()) {
210 _S2_jk.reserve(size()*10);
211 for(
int j=0;j<size();++j) {
264 return get2(_S2_jk,i,0)*
get(b1,i,0)*
get(b2,i,0)
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));
277 alpha(other.alpha), beta(other.beta + offset * other.alpha * 2)
285 double alpha = -
r(0)*(
get(b,0,0)-
get(b,0,1));
287 return S_edge( alpha, beta );
290 double alpha =
r(i-1)*(
get(b,i,2)-
get(b,i,1));
292 return S_edge(alpha,beta);
300 double alpha1 = -
r(0)*(
get(b1,0,0)-
get(b1,0,1));
302 double alpha2 = -
r(0)*(
get(b2,0,0)-
get(b2,0,1));
304 return S2_edge(alpha1,beta1,alpha2,beta2);
307 double alpha1 =
r(i-1)*(
get(b1,i,2)-
get(b1,i,1));
309 double alpha2 =
r(i-1)*(
get(b2,i,2)-
get(b2,i,1));
311 return S2_edge(alpha1,beta1,alpha2,beta2);
317 double eI(
double lo,
double hi,
double a,
double b,
double c,
double gamma) {
320 a*=gamma;b*=gamma;c*=gamma;
322 double result = -a*b*c *(TMath::Gamma(1,hi) - TMath::Gamma(1,lo))*TMath::Gamma(1)
323 + (b*c+a*c+a*b)*(TMath::Gamma(2,hi) - TMath::Gamma(2,lo))*TMath::Gamma(2)
324 - (a+b+c) *(TMath::Gamma(3,hi) - TMath::Gamma(3,lo))*TMath::Gamma(3)
325 + (TMath::Gamma(4,hi) - TMath::Gamma(4,lo))*TMath::Gamma(4);
327 return result / TMath::Power(gamma,4);
330 double fI(
double lo,
double hi,
double a,
double b,
double c,
double ) {
333 double result = -a*b*c *( hi - lo )
334 + (b*c+a*c+a*b)*( hi*hi - lo*lo ) / 2.
335 - (a+b+c) *( hi*hi*hi - lo*lo*lo )/ 3.
336 + ( hi*hi*hi*hi - lo*lo*lo*lo) / 4. ;
344 double eIn(
double lo,
double hi,
double c,
double slope,
double offset,
double gamma) {
347 double a = c - slope*offset;
353 return result / TMath::Power(gamma,4);
359 #include "TMatrixD.h" 360 #include "TVectorD.h" 361 #include "TDecompBK.h" 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; }
375 for (
int i=0;i<nbins ;++i) {
376 Y(i) = hist->GetBinContent(1+i);
377 DY(i) = hist->GetBinError(1+i);
382 double lo = hist->GetBinLowEdge(1+i);
383 double hi = lo + hist->GetBinWidth(1+i);
385 double Norm = (exp(-gamma*lo)-exp(-gamma*hi))/gamma;
392 if (lo <
_u.front()) {
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;
399 if (hi >
_u.back()) {
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;
407 assert( lo >=
_u.front() && hi <=
_u.back() );
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));
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;
428 TMatrixDSym
D(nsplines);
429 for (
int i=0;i<nsplines;++i)
for (
int j=0;j<=i;++j) {
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);
440 coefficients.ResizeTo(nsplines);
441 coefficients = solver.Solve(Y,ok);
443 std::cout <<
"WARNING: bad linear system solution... " << std::endl;
448 covarianceMatrix.ResizeTo(
D);
449 covarianceMatrix =
D;
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 );
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
double D(double u_, int i) const
RooCubicSplineKnot::S2_edge S2_jk_edge(bool left, const RooArgList &b1, const RooArgList &b2) const
S_edge(double a, double b)
int index(double u_) const
RooCubicSplineKnot::S_edge S_jk_edge(bool left, const RooArgList &b) const
double h(int i, int j) const
static double sqr(double x)
void smooth(std::vector< double > &y, const std::vector< double > &dy, double lambda) const
double analyticalIntegral(const RooArgList &b) const
double expIntegral(const TH1 *hist, double gamma, TVectorD &coefficients, TMatrixD &covarianceMatrix) const
void computeCoefficients(std::vector< double > &y, BoundaryConditions bc=BoundaryConditions()) const
double evaluate(double _u, const RooArgList &b) const
double lambda(double x, double y, double z)
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)
T::const_reference get(const T &t, int i, int j)
Double_t Q(double M, double m1, double m2)
T::const_reference get2(const T &t, int i, int j)