LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Public Types | Public Member Functions | Private Member Functions | List of all members
lsst::afw::math::detail::TautSpline Class Reference

#include <Spline.h>

Inheritance diagram for lsst::afw::math::detail::TautSpline:
lsst::afw::math::detail::Spline

Public Types

enum  Symmetry { Unknown, Odd, Even }
 

Public Member Functions

 TautSpline (std::vector< double > const &x, std::vector< double > const &y, double const gamma=0, Symmetry type=Unknown)
 
- Public Member Functions inherited from lsst::afw::math::detail::Spline
virtual ~Spline ()
 
void interpolate (std::vector< double > const &x, std::vector< double > &y) const
 
void derivative (std::vector< double > const &x, std::vector< double > &dydx) const
 
std::vector< double > roots (double const value, double const x0, double const x1) const
 

Private Member Functions

void calculateTautSpline (std::vector< double > const &x, std::vector< double > const &y, double const gamma0)
 
void calculateTautSplineEvenOdd (std::vector< double > const &x, std::vector< double > const &y, double const gamma0, bool even)
 

Additional Inherited Members

- Protected Member Functions inherited from lsst::afw::math::detail::Spline
 Spline ()
 
void _allocateSpline (int const nknot)
 
- Protected Attributes inherited from lsst::afw::math::detail::Spline
std::vector< double > _knots
 
std::vector< std::vector
< double > > 
_coeffs
 

Detailed Description

Definition at line 36 of file Spline.h.

Member Enumeration Documentation

Constructor & Destructor Documentation

lsst::afw::math::detail::TautSpline::TautSpline ( std::vector< double > const &  x,
std::vector< double > const &  y,
double const  gamma0 = 0,
Symmetry  type = Unknown 
)

Adapted from A Practical Guide to Splines by C. de Boor (N.Y. : Springer-Verlag, 1978) (His routine tautsp converted to C by Robert Lupton and then to C++ by an older and grayer Robert Lupton)

Construct cubic spline interpolant to given data.

If gamma .gt. 0., additional knots are introduced where needed to make the interpolant more flexible locally. this avoids extraneous inflection points typical of cubic spline interpolation at knots to rapidly changing data. Values for gamma are:

     = 0., no additional knots
     in (0.,3.), under certain conditions on the given data at
           points i-1, i, i+1, and i+2, a knot is added in the
           i-th interval, i=1,...,ntau-3. see description of method
           below. the interpolant gets rounded with increasing
           gamma. a value of  2.5  for gamma is typical.
     in (3.,6.), same , except that knots might also be added in
           intervals in which an inflection point would be permitted.
           a value of  5.5  for gamma is typical.

Returns: a SPLINE giving knots and coefficients, if all was OK NULL otherwise (and pushes message on error stack)

---— m e t h o d ---— on the i-th interval, (tau[i], tau[i+1]), the interpolant is of the form (*) f(u(x)) = a + b*u + c*h(u,z) + d*h(1-u,1-z) , with u = u(x) = (x - tau[i])/dtau[i]. Here, z = z(i) = addg(i+1)/(addg(i) + addg(i+1)) (= .5, in case the denominator vanishes). with ddg(j) = dg(j+1) - dg(j), addg(j) = abs(ddg(j)), dg(j) = divdif(j) = (gtau[j+1] - gtau[j])/dtau[j] and h(u,z) = alpha*u**3 + (1 - alpha)*(max(((u-zeta)/(1-zeta)),0)**3 with alpha(z) = (1-gamma/3)/zeta zeta(z) = 1 - gamma*min((1 - z), 1/3) thus, for 1/3 .le. z .le. 2/3, f is just a cubic polynomial on the interval i. otherwise, it has one additional knot, at tau[i] + zeta*dtau[i] . as z approaches 1, h(.,z) has an increasingly sharp bend near 1, thus allowing f to turn rapidly near the additional knot. in terms of f(j) = gtau[j] and fsecnd[j] = 2*derivative of f at tau[j], the coefficients for (*) are given as a = f(i) - d b = (f(i+1) - f(i)) - (c - d) c = fsecnd[i+1]*dtau[i]**2/hsecnd(1,z) d = fsecnd[i]*dtau[i]**2/hsecnd(1,1-z) hence can be computed once fsecnd[i],i=0,...,ntau-1, is fixed.

f is automatically continuous and has a continuous second derivat- ive (except when z = 0 or 1 for some i). we determine fscnd(.) from the requirement that also the first derivative of f be continuous. in addition, we require that the third derivative be continuous across tau[1] and across tau[ntau-2] . this leads to a strictly diagonally dominant tridiagonal linear system for the fsecnd[i] which we solve by gauss elimination without pivoting.

There must be at least 4 interpolation points for us to fit a taut cubic spline, but if you provide fewer we'll fit a quadratic or linear polynomial (but you must provide at least 2)

See also phSplineFindTautEven and phSplineFindTautOdd for splining functions with known symmetries

Parameters
xpoints where function's specified
yvalues of function at tau[]
gamma0control extra knots
typespecify the desired symmetry (e.g. Even)

Definition at line 178 of file Spline.cc.

183  {
184  if(x.size() != y.size()) {
185  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
186  (boost::format("TautSpline: x and y must have the same size; saw %d %d\n")
187  % x.size() % y.size()).str());
188  }
189 
190  int const ntau = x.size(); /* size of tau and gtau, must be >= 2*/
191  if(ntau < 2) {
192  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
193  (boost::format("TautSpline: ntau = %d, should be >= 2\n")
194  % ntau).str());
195  }
196 
197  switch (type) {
198  case Unknown:
199  calculateTautSpline(x, y, gamma0);
200  break;
201  case Even:
202  case Odd:
203  calculateTautSplineEvenOdd(x, y, gamma0, type == Even);
204  break;
205  }
206  }
void calculateTautSpline(std::vector< double > const &x, std::vector< double > const &y, double const gamma0)
Definition: Spline.cc:213
void calculateTautSplineEvenOdd(std::vector< double > const &x, std::vector< double > const &y, double const gamma0, bool even)
Definition: Spline.cc:1199
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46

Member Function Documentation

void lsst::afw::math::detail::TautSpline::calculateTautSpline ( std::vector< double > const &  x,
std::vector< double > const &  y,
double const  gamma0 
)
private

Here's the worker routine for the TautSpline ctor

Parameters
xpoints where function's specified
yvalues of function at tau[]
gamma0control extra knots

Definition at line 213 of file Spline.cc.

217  {
218  const double *tau = &x[0];
219  const double *gtau = &y[0];
220  int const ntau = x.size(); // size of tau and gtau, must be >= 2
221 
222  if(ntau < 4) { // use a single quadratic
223  int const nknot = ntau;
224 
225  _allocateSpline(nknot);
226 
227  _knots[0] = tau[0];
228  for (int i = 1; i < nknot;i++) {
229  _knots[i] = tau[i];
230  if(tau[i - 1] >= tau[i]) {
231  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
232  (boost::format("point %d and the next, %f %f, are out of order")
233  % (i - 1) % tau[i - 1] % tau[i]).str());
234  }
235  }
236 
237  if(ntau == 2) {
238  _coeffs[0][0] = gtau[0];
239  _coeffs[1][0] = (gtau[1] - gtau[0])/(tau[1] - tau[0]);
240  _coeffs[2][0] = _coeffs[3][0] = 0;
241 
242  _coeffs[0][1] = gtau[1];
243  _coeffs[1][1] = (gtau[1] - gtau[0])/(tau[1] - tau[0]);
244  _coeffs[2][1] = _coeffs[3][1] = 0;
245  } else { /* must be 3 */
246  double tmp = (tau[2]-tau[0])*(tau[2]-tau[1])*(tau[1]-tau[0]);
247  _coeffs[0][0] = gtau[0];
248  _coeffs[1][0] = ((gtau[1] - gtau[0])*pow(tau[2] - tau[0],2) -
249  (gtau[2] - gtau[0])*pow(tau[1] - tau[0],2))/tmp;
250  _coeffs[2][0] = -2*((gtau[1] - gtau[0])*(tau[2] - tau[0]) -
251  (gtau[2] - gtau[0])*(tau[1] - tau[0]))/tmp;
252  _coeffs[3][0] = 0;
253 
254  _coeffs[0][1] = gtau[1];
255  _coeffs[1][1] = _coeffs[1][0] + (tau[1] - tau[0])*_coeffs[2][0];
256  _coeffs[2][1] = _coeffs[2][0];
257  _coeffs[3][1] = 0;
258 
259  _coeffs[0][2] = gtau[2];
260  _coeffs[1][2] = _coeffs[1][0] + (tau[2] - tau[0])*_coeffs[2][0];
261  _coeffs[2][2] = _coeffs[2][0];
262  _coeffs[3][2] = 0;
263  }
264 
265  return;
266  }
267 /*
268  * Allocate scratch space
269  * s[0][...] = dtau = tau(.+1) - tau
270  * s[1][...] = diag = diagonal in linear system
271  * s[2][...] = u = upper diagonal in linear system
272  * s[3][...] = r = right side for linear system (initially)
273  * = fsecnd = solution of linear system , namely the second
274  * derivatives of interpolant at tau
275  * s[4][...] = z = indicator of additional knots
276  * s[5][...] = 1/hsecnd(1,x) with x = z or = 1-z. see below.
277  */
278  std::vector<std::vector<double> > s(6); // scratch space
279 
280  for (int i = 0; i != 6; i++) {
281  s[i].resize(ntau);
282  }
283 /*
284  * Construct delta tau and first and second (divided) differences of data
285  */
286 
287  for (int i = 0; i < ntau - 1; i++) {
288  s[0][i] = tau[i + 1] - tau[i];
289  if(s[0][i] <= 0.) {
290  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
291  (boost::format("point %d and the next, %f %f, are out of order")
292  % i % tau[i] % tau[i+1]).str());
293  }
294  s[3][i + 1] = (gtau[i + 1] - gtau[i])/s[0][i];
295  }
296  for (int i = 1; i < ntau - 1; ++i) {
297  s[3][i] = s[3][i + 1] - s[3][i];
298  }
299 /*
300  * Construct system of equations for second derivatives at tau. At each
301  * interior data point, there is one continuity equation, at the first
302  * and the last interior data point there is an additional one for a
303  * total of ntau equations in ntau unknowns.
304  */
305  s[1][1] = s[0][0]/3;
306 
307  int method;
308  double gamma = gamma0; // control the smoothing
309  if(gamma <= 0) {
310  method = 1;
311  } else if(gamma > 3) {
312  gamma -= 3;
313  method = 3;
314  } else {
315  method = 2;
316  }
317  double const onemg3 = 1 - gamma/3;
318 
319  int nknot = ntau; // count number of knots
320 /*
321  * Some compilers don't realise that the flow of control always initialises
322  * these variables; so initialise them to placate e.g. gcc
323  */
324  double zeta = 0.0;
325  double alpha = 0.0;
326  double ratio = 0.0;
327 
328  //double c, d;
329  //double z, denom, factr2;
330  //double onemzt, zt2, del;
331 
332 
333  double entry3 = 0.0;
334  double factor = 0.0;
335  double onemzt = 0;
336  double zt2 = 0;
337  double z_half = 0;
338 
339  for (int i = 1; i < ntau - 2; ++i) {
340  /*
341  * construct z[i] and zeta[i]
342  */
343  double z = .5;
344  if((method == 2 && s[3][i]*s[3][i + 1] >= 0) || method == 3) {
345  double const temp = fabs(s[3][i + 1]);
346  double const denom = fabs(s[3][i]) + temp;
347  if(denom != 0) {
348  z = temp/denom;
349  if (fabs(z - 0.5) <= 1.0/6.0) {
350  z = 0.5;
351  }
352  }
353  }
354 
355  s[4][i] = z;
356 /*
357  set up part of the i-th equation which depends on the i-th interval
358 */
359  z_half = z - 0.5;
360  if(z_half < 0) {
361  zeta = gamma*z;
362  onemzt = 1 - zeta;
363  zt2 = zeta*zeta;
364  double temp = onemg3/onemzt;
365  alpha = (temp < 1 ? temp : 1);
366  factor = zeta/(alpha*(zt2 - 1) + 1);
367  s[5][i] = zeta*factor/6;
368  s[1][i] += s[0][i]*((1 - alpha*onemzt)*factor/2 - s[5][i]);
369 /*
370  * if z = 0 and the previous z = 1, then d[i] = 0. Since then
371  * also u[i-1] = l[i+1] = 0, its value does not matter. Reset
372  * d[i] = 1 to insure nonzero pivot in elimination.
373  */
374  if (s[1][i] <= 0.) {
375  s[1][i] = 1;
376  }
377  s[2][i] = s[0][i]/6;
378 
379  if(z != 0) { /* we'll get a new knot */
380  nknot++;
381  }
382  } else if(z_half == 0) {
383  s[1][i] += s[0][i]/3;
384  s[2][i] = s[0][i]/6;
385  } else {
386  onemzt = gamma*(1 - z);
387  zeta = 1 - onemzt;
388  double const temp = onemg3/zeta;
389  alpha = (temp < 1 ? temp : 1);
390  factor = onemzt/(1 - alpha*zeta*(onemzt + 1));
391  s[5][i] = onemzt*factor/6;
392  s[1][i] += s[0][i]/3;
393  s[2][i] = s[5][i]*s[0][i];
394 
395  if(onemzt != 0) { /* we'll get a new knot */
396  nknot++;
397  }
398  }
399  if (i == 1) {
400  s[4][0] = 0.5;
401 /*
402  * the first two equations enforce continuity of the first and of
403  * the third derivative across tau[1].
404  */
405  s[1][0] = s[0][0]/6;
406  s[2][0] = s[1][1];
407  entry3 = s[2][1];
408  if(z_half < 0) {
409  const double factr2 = zeta*(alpha*(zt2 - 1.) + 1.)/(alpha*(zeta*zt2 - 1.) + 1.);
410  ratio = factr2*s[0][1]/s[1][0];
411  s[1][1] = factr2*s[0][1] + s[0][0];
412  s[2][1] = -factr2*s[0][0];
413  } else if (z_half == 0) {
414  ratio = s[0][1]/s[1][0];
415  s[1][1] = s[0][1] + s[0][0];
416  s[2][1] = -s[0][0];
417  } else {
418  ratio = s[0][1]/s[1][0];
419  s[1][1] = s[0][1] + s[0][0];
420  s[2][1] = -s[0][0]*6*alpha*s[5][1];
421  }
422 /*
423  * at this point, the first two equations read
424  * diag[0]*x0 + u[0]*x1 + entry3*x2 = r[1]
425  * -ratio*diag[0]*x0 + diag[1]*x1 + u[1]*x2 = 0
426  * set r[0] = r[1] and eliminate x1 from the second equation
427  */
428  s[3][0] = s[3][1];
429 
430  s[1][1] += ratio*s[2][0];
431  s[2][1] += ratio*entry3;
432  s[3][1] = ratio*s[3][1];
433  } else {
434 /*
435  * the i-th equation enforces continuity of the first derivative
436  * across tau[i]; it reads
437  * -ratio*diag[i-1]*x_{i-1} + diag[i]*x_i + u[i]*x_{i+1} = r[i]
438  * eliminate x_{i-1} from this equation
439  */
440  s[1][i] += ratio*s[2][i - 1];
441  s[3][i] += ratio*s[3][i - 1];
442  }
443 /*
444  * Set up the part of the next equation which depends on the i-th interval.
445  */
446  if(z_half < 0) {
447  ratio = -s[5][i]*s[0][i]/s[1][i];
448  s[1][i + 1] = s[0][i]/3;
449  } else if(z_half == 0) {
450  ratio = -(s[0][i]/6)/s[1][i];
451  s[1][i + 1] = s[0][i]/3;
452  } else {
453  ratio = -(s[0][i]/6)/s[1][i];
454  s[1][i + 1] = s[0][i]*((1 - zeta*alpha)*factor/2 - s[5][i]);
455  }
456  }
457 
458  s[4][ntau - 2] = 0.5;
459 /*
460  * last two equations, which enforce continuity of third derivative and
461  * of first derivative across tau[ntau - 2]
462  */
463  double const entry_ = ratio*s[2][ntau - 3] + s[1][ntau - 2] + s[0][ntau - 2]/3;
464  s[1][ntau - 1] = s[0][ntau - 2]/6;
465  s[3][ntau - 1] = ratio*s[3][ntau - 3] + s[3][ntau - 2];
466  if (z_half < 0) {
467  ratio = s[0][ntau - 2]*6*s[5][ntau - 3]*alpha/s[1][ntau - 3];
468  s[1][ntau - 2] = ratio*s[2][ntau - 3] + s[0][ntau - 2] + s[0][ntau - 3];
469  s[2][ntau - 2] = -s[0][ntau - 3];
470  } else if (z_half == 0) {
471  ratio = s[0][ntau - 2]/s[1][ntau - 3];
472  s[1][ntau - 2] = ratio*s[2][ntau - 3] + s[0][ntau - 2] + s[0][ntau - 3];
473  s[2][ntau - 2] = -s[0][ntau - 3];
474  } else {
475  const double factr2 = onemzt*(alpha*(onemzt*onemzt - 1) + 1)/(alpha*(onemzt*onemzt*onemzt - 1) + 1);
476  ratio = factr2*s[0][ntau - 2]/s[1][ntau - 3];
477  s[1][ntau - 2] = ratio*s[2][ntau - 3] + factr2*s[0][ntau - 3] + s[0][ntau - 2];
478  s[2][ntau - 2] = -factr2*s[0][ntau - 3];
479  }
480 /*
481  * at this point, the last two equations read
482  * diag[i]*x_i + u[i]*x_{i+1} = r[i]
483  * -ratio*diag[i]*x_i + diag[i+1]*x_{i+1} = r[i+1]
484  * eliminate x_i from last equation
485  */
486  s[3][ntau - 2] = ratio*s[3][ntau - 3];
487  ratio = -entry_/s[1][ntau - 2];
488  s[1][ntau - 1] += ratio*s[2][ntau - 2];
489  s[3][ntau - 1] += ratio*s[3][ntau - 2];
490 
491 /*
492  * back substitution
493  */
494  s[3][ntau - 1] /= s[1][ntau - 1];
495  for (int i = ntau - 2; i > 0; --i) {
496  s[3][i] = (s[3][i] - s[2][i]*s[3][i + 1])/s[1][i];
497  }
498 
499  s[3][0] = (s[3][0] - s[2][0]*s[3][1] - entry3*s[3][2])/s[1][0];
500 /*
501  * construct polynomial pieces; first allocate space for the coefficients
502  */
503 #if 1
504 /*
505  * Start by counting the knots
506  */
507  {
508  int const nknot0 = nknot;
509  int nknot = ntau;
510 
511  for (int i = 0; i < ntau - 1; ++i) {
512  double const z = s[4][i];
513  if((z < 0.5 && z != 0.0) || (z > 0.5 && (1 - z) != 0.0)) {
514  nknot++;
515  }
516  }
517  assert (nknot == nknot0);
518  }
519 #endif
520  _allocateSpline(nknot);
521 
522  _knots[0] = tau[0];
523  int j = 0;
524  for (int i = 0; i < ntau - 1; ++i) {
525  _coeffs[0][j] = gtau[i];
526  _coeffs[2][j] = s[3][i];
527  double const divdif = (gtau[i + 1] - gtau[i])/s[0][i];
528  double z = s[4][i];
529  double const z_half = z - 0.5;
530  if (z_half < 0) {
531  if (z == 0) {
532  _coeffs[1][j] = divdif;
533  _coeffs[2][j] = 0;
534  _coeffs[3][j] = 0;
535  } else {
536  zeta = gamma*z;
537  onemzt = 1 - zeta;
538  double const c = s[3][i + 1]/6;
539  double const d = s[3][i]*s[5][i];
540  j++;
541 
542  double const del = zeta*s[0][i];
543  _knots[j] = tau[i] + del;
544  zt2 = zeta*zeta;
545  double temp = onemg3/onemzt;
546  alpha = (temp < 1 ? temp : 1);
547  factor = onemzt*onemzt*alpha;
548  temp = s[0][i];
549  _coeffs[0][j] = gtau[i] + divdif*del + temp*temp*(d*onemzt*(factor - 1) + c*zeta*(zt2 - 1));
550  _coeffs[1][j] = divdif + s[0][i]*(d*(1 - 3*factor) + c*(3*zt2 - 1));
551  _coeffs[2][j] = (d*alpha*onemzt + c*zeta)*6;
552  _coeffs[3][j] = (c - d*alpha)*6/s[0][i];
553  if(del*zt2 == 0) {
554  _coeffs[1][j - 1] = 0; /* would be NaN in an */
555  _coeffs[3][j - 1] = 0; /* 0-length interval */
556  } else {
557  _coeffs[3][j - 1] = _coeffs[3][j] - d*6*(1 - alpha)/(del*zt2);
558  _coeffs[1][j - 1] = _coeffs[1][j] -
559  del*(_coeffs[2][j] - del/2*_coeffs[3][j - 1]);
560  }
561  }
562  } else if (z_half == 0) {
563  _coeffs[1][j] = divdif - s[0][i]*(s[3][i]*2 + s[3][i + 1])/6;
564  _coeffs[3][j] = (s[3][i + 1] - s[3][i])/s[0][i];
565  } else {
566  onemzt = gamma*(1 - z);
567  if (onemzt == 0) {
568  _coeffs[1][j] = divdif;
569  _coeffs[2][j] = 0;
570  _coeffs[3][j] = 0;
571  } else {
572  zeta = 1 - onemzt;
573  double const temp = onemg3/zeta;
574  alpha = (temp < 1 ? temp : 1);
575  double const c = s[3][i + 1]*s[5][i];
576  double const d = s[3][i]/6;
577  double const del = zeta*s[0][i];
578  _knots[j + 1] = tau[i] + del;
579  _coeffs[1][j] = divdif - s[0][i]*(2*d + c);
580  _coeffs[3][j] = (c*alpha - d)*6/s[0][i];
581  j++;
582 
583  _coeffs[3][j] = _coeffs[3][j - 1] +
584  (1 - alpha)*6*c/(s[0][i]*(onemzt*onemzt*onemzt));
585  _coeffs[2][j] = _coeffs[2][j - 1] + del*_coeffs[3][j - 1];
586  _coeffs[1][j] = _coeffs[1][j - 1] +
587  del*(_coeffs[2][j - 1] + del/2*_coeffs[3][j - 1]);
588  _coeffs[0][j] = _coeffs[0][j - 1] +
589  del*(_coeffs[1][j - 1] +
590  del/2*(_coeffs[2][j - 1] + del/3*_coeffs[3][j - 1]));
591  }
592  }
593 
594  j++;
595  _knots[j] = tau[i + 1];
596  }
597 /*
598  * If there are discontinuities some of the knots may be at the same
599  * position; in this case we generated some NaNs above. As they only
600  * occur for 0-length segments, it's safe to replace them by 0s
601  *
602  * Due to the not-a-knot condition, the last set of coefficients isn't
603  * needed (the last-but-one is equivalent), but it makes the book-keeping
604  * easier if we _do_ generate them
605  */
606  double const del = tau[ntau - 1] - _knots[nknot - 2];
607 
608  _coeffs[0][nknot - 1] = _coeffs[0][nknot - 2] +
609  del*(_coeffs[1][nknot - 2] + del*(_coeffs[2][nknot - 2]/2 +
610  del*_coeffs[3][nknot - 2]/6));
611  _coeffs[1][nknot - 1] = _coeffs[1][nknot - 2] +
612  del*(_coeffs[2][nknot - 2] + del*_coeffs[3][nknot - 2]/2);
613  _coeffs[2][nknot - 1] = _coeffs[2][nknot - 2] + del*_coeffs[3][nknot - 2];
614  _coeffs[3][nknot - 1] = _coeffs[3][nknot - 2];
615 
616  assert (j + 1 == nknot);
617 }
std::vector< std::vector< double > > _coeffs
Definition: Spline.h:33
std::vector< double > _knots
Definition: Spline.h:32
Matrix alpha
void _allocateSpline(int const nknot)
Definition: Spline.cc:25
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
void lsst::afw::math::detail::TautSpline::calculateTautSplineEvenOdd ( std::vector< double > const &  x,
std::vector< double > const &  y,
double const  gamma0,
bool  even 
)
private

Definition at line 1199 of file Spline.cc.

1204 {
1205  const double *tau = &_tau[0];
1206  const double *gtau = &_gtau[0];
1207  int const ntau = _tau.size(); // size of tau and gtau, must be >= 2
1208  std::vector<double> x, y; // tau and gtau, extended to -ve tau
1209 
1210  if(tau[0] == 0.0f) {
1211  int const np = 2*ntau - 1;
1212  x.resize(np);
1213  y.resize(np);
1214 
1215  x[ntau - 1] = tau[0]; y[ntau - 1] = gtau[0];
1216  for (int i = 1; i != ntau; ++i) {
1217  if (even) {
1218  x[ntau - 1 + i] = tau[i]; y[ntau - 1 + i] = gtau[i];
1219  x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = gtau[i];
1220  } else {
1221  x[ntau - 1 + i] = tau[i]; y[ntau - 1 + i] = gtau[i];
1222  x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = -gtau[i];
1223  }
1224  }
1225  } else {
1226  int const np = 2*ntau;
1227  x.resize(np);
1228  y.resize(np);
1229 
1230  for (int i = 0; i != ntau; ++i) {
1231  if (even) {
1232  x[ntau + i] = tau[i]; y[ntau + i] = gtau[i];
1233  x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = gtau[i];
1234  } else {
1235  x[ntau + i] = tau[i]; y[ntau + i] = gtau[i];
1236  x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = -gtau[i];
1237  }
1238  }
1239  }
1240 
1241  TautSpline sp(x, y, gamma); // fit a taut spline to x, y
1242 /*
1243  * Now repackage that spline to reflect the original points
1244  */
1245  int ii;
1246  for (ii = sp._knots.size() - 1; ii >= 0; --ii) {
1247  if(sp._knots[ii] < 0.0f) {
1248  break;
1249  }
1250  }
1251  int const i0 = ii + 1;
1252  int const nknot = sp._knots.size() - i0;
1253 
1254  _allocateSpline(nknot);
1255 
1256  for (int i = i0; i != static_cast<int>(sp._knots.size()); ++i) {
1257  _knots[i - i0] = sp._knots[i];
1258  for (int j = 0; j != 4; ++j) {
1259  _coeffs[j][i - i0] = sp._coeffs[j][i];
1260  }
1261  }
1262 }
int y
std::vector< std::vector< double > > _coeffs
Definition: Spline.h:33
std::vector< double > _knots
Definition: Spline.h:32
double x
void _allocateSpline(int const nknot)
Definition: Spline.cc:25
TautSpline(std::vector< double > const &x, std::vector< double > const &y, double const gamma=0, Symmetry type=Unknown)
Definition: Spline.cc:178

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