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
FunctionLibrary.h
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
25 #ifndef LSST_AFW_MATH_FUNCTIONLIBRARY_H
26 #define LSST_AFW_MATH_FUNCTIONLIBRARY_H
27 
36 #include <algorithm>
37 #include <cmath>
38 
39 #include "lsst/afw/geom.h"
40 #include "lsst/afw/math/Function.h"
41 #include "lsst/afw/geom/Angle.h"
42 
43 namespace lsst {
44 namespace afw {
45 namespace math {
46 
47 #ifndef SWIG
48 using boost::serialization::make_nvp;
49 #endif
50 
61  template<typename ReturnT>
62  class IntegerDeltaFunction1: public Function1<ReturnT> {
63  public:
65 
70  double xo)
71  :
72  Function1<ReturnT>(0),
73  _xo(xo)
74  {}
75 
76  virtual ~IntegerDeltaFunction1() {};
77 
78  virtual Function1Ptr clone() const {
80  }
81 
82  virtual ReturnT operator() (double x, double y) const {
83  return static_cast<ReturnT>(x == _xo);
84  }
85 
86  virtual std::string toString(std::string const& prefix="") const {
87  std::ostringstream os;
88  os << "IntegerDeltaFunction1 [" << _xo << "]: ";
89  os << Function1<ReturnT>::toString(prefix);
90  return os.str();
91  };
92 
93  private:
94  double _xo;
95 
96  protected:
97  /* Default constructor: intended only for serialization */
98  explicit IntegerDeltaFunction1() : Function1<ReturnT>(0), _xo(0.0) {}
99 
100  private:
102  template <class Archive>
103  void serialize(Archive& ar, unsigned int const version) {
104  ar & make_nvp("fn1", boost::serialization::base_object<Function1<ReturnT> >(*this));
105  ar & make_nvp("xo", this->_xo);
106  }
107  };
108 
119  template<typename ReturnT>
120  class IntegerDeltaFunction2: public Function2<ReturnT> {
121  public:
123 
128  double xo,
129  double yo)
130  :
131  Function2<ReturnT>(0),
132  _xo(xo),
133  _yo(yo)
134  {}
135 
137 
138  virtual Function2Ptr clone() const {
140  }
141 
142  virtual ReturnT operator() (double x, double y) const {
143  return static_cast<ReturnT>((x == _xo) && (y == _yo));
144  }
145 
146  virtual std::string toString(std::string const& prefix) const {
147  std::ostringstream os;
148  os << "IntegerDeltaFunction2 [" << _xo << ", " << _yo << "]: ";
149  os << Function2<ReturnT>::toString(prefix);
150  return os.str();
151  }
152 
153  private:
154  double _xo;
155  double _yo;
156 
157  protected:
158  /* Default constructor: intended only for serialization */
159  explicit IntegerDeltaFunction2() : Function2<ReturnT>(0), _xo(0.0), _yo(0.0) {}
160 
161  private:
163  template <class Archive>
164  void serialize(Archive& ar, unsigned int const version) {
165  ar & make_nvp("fn2", boost::serialization::base_object<Function2<ReturnT> >(*this));
166  ar & make_nvp("xo", this->_xo);
167  ar & make_nvp("yo", this->_yo);
168  }
169  };
170 
181  template<typename ReturnT>
182  class GaussianFunction1: public Function1<ReturnT> {
183  public:
185 
190  double sigma)
191  :
192  Function1<ReturnT>(1),
193  _multFac(1.0 / std::sqrt(lsst::afw::geom::TWOPI))
194  {
195  this->_params[0] = sigma;
196  }
197  virtual ~GaussianFunction1() {}
198 
199  virtual Function1Ptr clone() const {
200  return Function1Ptr(new GaussianFunction1(this->_params[0]));
201  }
202 
203  virtual ReturnT operator() (double x) const {
204  return static_cast<ReturnT> (
205  (_multFac / this->_params[0]) *
206  std::exp(- (x * x) / (2.0 * this->_params[0] * this->_params[0])));
207  }
208 
209  virtual std::string toString(std::string const& prefix) const {
210  std::ostringstream os;
211  os << "GaussianFunction1 [" << _multFac << "]: ";
212  os << Function1<ReturnT>::toString(prefix);
213  return os.str();
214  }
215 
216  private:
217  const double _multFac;
218 
219  protected:
220  /* Default constructor: intended only for serialization */
221  explicit GaussianFunction1() : Function1<ReturnT>(1), _multFac(1.0 / std::sqrt(lsst::afw::geom::TWOPI)) {}
222 
223  private:
225  template <class Archive>
226  void serialize(Archive& ar, unsigned int const version) {
227  ar & make_nvp("fn1", boost::serialization::base_object<Function1<ReturnT> >(*this));
228  }
229  };
230 
245  template<typename ReturnT>
246  class GaussianFunction2: public Function2<ReturnT> {
247  public:
249 
254  double sigma1,
255  double sigma2,
256  double angle = 0.0)
257  :
258  Function2<ReturnT>(3),
259  _multFac(1.0 / (lsst::afw::geom::TWOPI))
260  {
261  this->_params[0] = sigma1;
262  this->_params[1] = sigma2;
263  this->_params[2] = angle;
264  _updateCache();
265  }
266 
267  virtual ~GaussianFunction2() {}
268 
269  virtual Function2Ptr clone() const {
270  return Function2Ptr(new GaussianFunction2(this->_params[0], this->_params[1], this->_params[2]));
271  }
272 
273  virtual ReturnT operator() (double x, double y) const {
274  if (_angle != this->_params[2]) {
275  _updateCache();
276  }
277  double pos1 = ( _cosAngle * x) + (_sinAngle * y);
278  double pos2 = (-_sinAngle * x) + (_cosAngle * y);
279  return static_cast<ReturnT> (
280  (_multFac / (this->_params[0] * this->_params[1])) *
281  std::exp(- ((pos1 * pos1) / (2.0 * this->_params[0] * this->_params[0]))
282  - ((pos2 * pos2) / (2.0 * this->_params[1] * this->_params[1]))));
283  }
284 
285  virtual std::string toString(std::string const& prefix) const {
286  std::ostringstream os;
287  os << "GaussianFunction2: ";
288  os << Function2<ReturnT>::toString(prefix);
289  return os.str();
290  }
291 
292  virtual bool isPersistable() const { return true; }
293 
294  protected:
295 
296  virtual std::string getPersistenceName() const;
297 
298  virtual void write(afw::table::io::OutputArchiveHandle & handle) const;
299 
300  private:
318  void _updateCache() const {
319  _angle = this->_params[2];
320  _sinAngle = std::sin(_angle);
321  _cosAngle = std::cos(_angle);
322  }
323  const double _multFac;
324  mutable double _angle;
325  mutable double _sinAngle;
326  mutable double _cosAngle;
327 
328  protected:
329  /* Default constructor: intended only for serialization */
330  explicit GaussianFunction2() : Function2<ReturnT>(3), _multFac(1.0 / (lsst::afw::geom::TWOPI)), _angle(0.0),
331  _sinAngle(0.0), _cosAngle(1.0) {}
332 
333  private:
335  template <class Archive>
336  void serialize(Archive& ar, unsigned int const version) {
337  ar & make_nvp("fn2", boost::serialization::base_object<Function2<ReturnT> >(*this));
338  ar & make_nvp("angle", this->_angle);
339  ar & make_nvp("sinAngle", this->_sinAngle);
340  ar & make_nvp("cosAngle", this->_cosAngle);
341  }
342  };
343 
358  template<typename ReturnT>
359  class DoubleGaussianFunction2: public Function2<ReturnT> {
360  public:
362 
367  double sigma1,
368  double sigma2 = 0,
369  double ampl2 = 0)
370  :
371  Function2<ReturnT>(3),
372  _multFac(1.0 / (lsst::afw::geom::TWOPI))
373  {
374  this->_params[0] = sigma1;
375  this->_params[1] = sigma2;
376  this->_params[2] = ampl2;
377  }
378 
380 
381  virtual Function2Ptr clone() const {
382  return Function2Ptr(
383  new DoubleGaussianFunction2(this->_params[0], this->_params[1], this->_params[2]));
384  }
385 
386  virtual ReturnT operator() (double x, double y) const {
387  double radSq = (x * x) + (y * y);
388  double sigma1Sq = this->_params[0] * this->_params[0];
389  double sigma2Sq = this->_params[1] * this->_params[1];
390  double b = this->_params[2];
391  return static_cast<ReturnT> (
392  (_multFac / (sigma1Sq + (b * sigma2Sq))) *
393  (std::exp(-radSq / (2.0 * sigma1Sq))
394  + (b * std::exp(-radSq / (2.0 * sigma2Sq)))));
395  }
396 
397  virtual std::string toString(std::string const& prefix) const {
398  std::ostringstream os;
399  os << "DoubleGaussianFunction2 [" << _multFac << "]: ";
400  os << Function2<ReturnT>::toString(prefix);
401  return os.str();
402  }
403 
404  virtual bool isPersistable() const { return true; }
405 
406  protected:
407 
408  virtual std::string getPersistenceName() const;
409 
410  virtual void write(afw::table::io::OutputArchiveHandle & handle) const;
411 
412  private:
413  const double _multFac;
414 
415  protected:
416  /* Default constructor: intended only for serialization */
417  explicit DoubleGaussianFunction2() : Function2<ReturnT>(3), _multFac(1.0 / (lsst::afw::geom::TWOPI)) {}
418 
419  private:
421  template <class Archive>
422  void serialize(Archive& ar, unsigned int const version) {
423  ar & make_nvp("fn2", boost::serialization::base_object<Function2<ReturnT> >(*this));
424  }
425  };
426 
434  template<typename ReturnT>
435  class PolynomialFunction1: public Function1<ReturnT> {
436  public:
438 
445  unsigned int order)
446  :
447  Function1<ReturnT>(order+1) {
448  }
449 
458  std::vector<double> params)
459  :
460  Function1<ReturnT>(params)
461  {
462  if (params.size() < 1) {
463  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
464  "PolynomialFunction1 called with empty vector");
465  }
466  }
467 
468  virtual ~PolynomialFunction1() {}
469 
470  virtual Function1Ptr clone() const {
471  return Function1Ptr(new PolynomialFunction1(this->_params));
472  }
473 
474  virtual bool isLinearCombination() const { return true; };
475 
476  virtual ReturnT operator() (double x) const {
477  int const order = static_cast<int>(this->_params.size()) - 1;
478  double retVal = this->_params[order];
479  for (int ii = order-1; ii >= 0; --ii) {
480  retVal = (retVal * x) + this->_params[ii];
481  }
482  return static_cast<ReturnT>(retVal);
483  }
484 
488  unsigned int getOrder() const { return this->getNParameters() - 1; };
489 
490  virtual std::string toString(std::string const& prefix) const {
491  std::ostringstream os;
492  os << "PolynomialFunction1 []: ";
493  os << Function1<ReturnT>::toString(prefix);
494  return os.str();
495  }
496 
497  protected:
498  /* Default constructor: intended only for serialization */
499  explicit PolynomialFunction1() : Function1<ReturnT>(1) {}
500 
501  private:
503  template <class Archive>
504  void serialize(Archive& ar, unsigned int const version) {
505  ar & make_nvp("fn1", boost::serialization::base_object<Function1<ReturnT> >(*this));
506  }
507  };
508 
523  template<typename ReturnT>
525  public:
527 
536  unsigned int order)
537  :
538  BasePolynomialFunction2<ReturnT>(order),
539  _oldY(0),
540  _xCoeffs(this->_order + 1)
541  {}
542 
554  std::vector<double> params)
555  :
557  BasePolynomialFunction2<ReturnT>(params),
558  _oldY(0),
559  _xCoeffs(this->_order + 1)
560  {}
561 
562  virtual ~PolynomialFunction2() {}
563 
564  virtual Function2Ptr clone() const {
565  return Function2Ptr(new PolynomialFunction2(this->_params));
566  }
567 
568  virtual ReturnT operator() (double x, double y) const {
569  /* Solve as follows:
570  - f(x,y) = Cx0 + Cx1 x + Cx2 x^2 + Cx3 x^3 + ...
571  where:
572  Cx0 = P0 + P2 y + P5 y^2 + P9 y^3 + ...
573  Cx1 = P1 + P4 y + P8 y2 + ...
574  Cx2 = P3 + P7 y + ...
575  Cx3 = P6 + ...
576  ...
577 
578  Compute Cx0, Cx1...Cxn by solving 1-d polynomials in y in the usual way.
579  These values are cached and only recomputed for new values of Y or if the parameters change.
580 
581  Then compute f(x,y) by solving the 1-d polynomial in x in the usual way.
582  */
583  const int maxXCoeffInd = this->_order;
584 
585  if ((y != _oldY) || !this->_isCacheValid) {
586  // update _xCoeffs cache
587  // note: paramInd is decremented in both of the following loops
588  int paramInd = static_cast<int>(this->_params.size()) - 1;
589 
590  // initialize _xCoeffs to coeffs for pure y^n; e.g. for 3rd order:
591  // _xCoeffs[0] = _params[9], _xCoeffs[1] = _params[8], ... _xCoeffs[3] = _params[6]
592  for (int xCoeffInd = 0; xCoeffInd <= maxXCoeffInd; ++xCoeffInd, --paramInd) {
593  _xCoeffs[xCoeffInd] = this->_params[paramInd];
594  }
595 
596  // finish computing _xCoeffs
597  for (int xCoeffInd = 0, endXCoeffInd = maxXCoeffInd; paramInd >= 0; --paramInd) {
598  _xCoeffs[xCoeffInd] = (_xCoeffs[xCoeffInd] * y) + this->_params[paramInd];
599  ++xCoeffInd;
600  if (xCoeffInd >= endXCoeffInd) {
601  xCoeffInd = 0;
602  --endXCoeffInd;
603  }
604  }
605 
606  _oldY = y;
607  this->_isCacheValid = true;
608  }
609 
610  // use _xCoeffs to compute result
611  double retVal = _xCoeffs[maxXCoeffInd];
612  for (int xCoeffInd = maxXCoeffInd - 1; xCoeffInd >= 0; --xCoeffInd) {
613  retVal = (retVal * x) + _xCoeffs[xCoeffInd];
614  }
615  return static_cast<ReturnT>(retVal);
616  }
617 
618  virtual std::vector<double> getDFuncDParameters(double x, double y) const;
619 
620  virtual std::string toString(std::string const& prefix) const {
621  std::ostringstream os;
622  os << "PolynomialFunction2 [" << this->_order << "]: ";
623  os << Function2<ReturnT>::toString(prefix);
624  return os.str();
625  }
626 
627  virtual bool isPersistable() const { return true; }
628 
629  protected:
630 
631  virtual std::string getPersistenceName() const;
632 
633  virtual void write(afw::table::io::OutputArchiveHandle & handle) const;
634 
635  private:
636  mutable double _oldY;
637  mutable std::vector<double> _xCoeffs;
638 
639  protected:
640  /* Default constructor: intended only for serialization */
641  explicit PolynomialFunction2() : BasePolynomialFunction2<ReturnT>(), _oldY(0), _xCoeffs(0) {}
642 
643  private:
645  template <class Archive>
646  void serialize(Archive& ar, unsigned int const version) {
647  ar & make_nvp("fn2", boost::serialization::base_object<BasePolynomialFunction2<ReturnT> >(*this));
648  ar & make_nvp("yCoeffs", this->_xCoeffs); // sets size of _xCoeffs; name is historical
649  }
650  };
651 
668  template<typename ReturnT>
669  class Chebyshev1Function1: public Function1<ReturnT> {
670  public:
672 
679  unsigned int order,
680  double minX = -1,
681  double maxX = 1)
682  :
683  Function1<ReturnT>(order + 1)
684  {
685  _initialize(minX, maxX);
686  }
687 
696  std::vector<double> params,
697  double minX = -1,
698  double maxX = 1)
699  :
700  Function1<ReturnT>(params)
701  {
702  if (params.size() < 1) {
703  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
704  "Chebyshev1Function1 called with empty vector");
705  }
706  _initialize(minX, maxX);
707  }
708 
709  virtual ~Chebyshev1Function1() {}
710 
711  virtual Function1Ptr clone() const {
712  return Function1Ptr(new Chebyshev1Function1(this->_params, _minX, _maxX));
713  }
714 
718  double getMinX() const { return _minX; };
719 
723  double getMaxX() const { return _maxX; };
724 
728  unsigned int getOrder() const { return this->getNParameters() - 1; };
729 
730  virtual bool isLinearCombination() const { return true; };
731 
732  virtual ReturnT operator() (double x) const {
733  double xPrime = (x + _offset) * _scale;
734 
735  // Clenshaw function for solving the Chebyshev polynomial
736  // Non-recursive version from Kresimir Cosic
737  int const order = _order;
738  if (order == 0) {
739  return this->_params[0];
740  } else if (order == 1) {
741  return this->_params[0] + (this->_params[1] * xPrime);
742  }
743  double cshPrev = this->_params[order];
744  double csh = (2 * xPrime * this->_params[order]) + this->_params[order-1];
745  for (int i = order - 2; i > 0; --i) {
746  double cshNext = (2 * xPrime * csh) + this->_params[i] - cshPrev;
747  cshPrev = csh;
748  csh = cshNext;
749  }
750  return (xPrime * csh) + this->_params[0] - cshPrev;
751  }
752 
753  virtual std::string toString(std::string const& prefix) const {
754  std::ostringstream os;
755  os << "Chebyshev1Function1 [" << _minX << ", " << _maxX << "]: ";
756  os << Function1<ReturnT>::toString(prefix);
757  return os.str();
758  }
759 
760  private:
761  double _minX;
762  double _maxX;
763  double _scale;
764  double _offset;
765  unsigned int _order;
766 
770  void _initialize(double minX, double maxX) {
771  _minX = minX;
772  _maxX = maxX;
773  _scale = 2.0 / (_maxX - _minX);
774  _offset = -(_minX + _maxX) * 0.5;
775  _order = this->getNParameters() - 1;
776  }
777 
778  protected:
779  /* Default constructor: intended only for serialization */
780  explicit Chebyshev1Function1() : Function1<ReturnT>(1),
781  _minX(0.0), _maxX(0.0), _scale(1.0), _offset(0.0), _order(0) {}
782 
783  private:
785  template <class Archive>
786  void serialize(Archive& ar, unsigned int const) {
787  ar & make_nvp("fn1", boost::serialization::base_object<Function1<ReturnT> >(*this));
788  ar & make_nvp("minX", this->_minX);
789  ar & make_nvp("minX", this->_minX);
790  ar & make_nvp("maxX", this->_maxX);
791  ar & make_nvp("scale", this->_scale);
792  ar & make_nvp("offset", this->_offset);
793  ar & make_nvp("maxInd", this->_order);
794  }
795  };
796 
822  template<typename ReturnT>
824  public:
826 
833  unsigned int order,
834  lsst::afw::geom::Box2D const &xyRange =
836  lsst::afw::geom::Point2D( 1.0, 1.0)))
837  :
838  BasePolynomialFunction2<ReturnT>(order),
839  _oldYPrime(0),
840  _yCheby(this->_order + 1),
841  _xCoeffs(this->_order + 1)
842  {
843  _initialize(xyRange);
844  }
845 
854  std::vector<double> params,
855  lsst::afw::geom::Box2D const &xyRange =
858  lsst::afw::geom::Point2D( 1.0, 1.0)))
859  :
860  BasePolynomialFunction2<ReturnT>(params),
861  _oldYPrime(0),
862  _yCheby(this->_order + 1),
863  _xCoeffs(this->_order + 1)
864  {
865  _initialize(xyRange);
866  }
867 
868  virtual ~Chebyshev1Function2() {}
869 
870  virtual Function2Ptr clone() const {
871  return Function2Ptr(new Chebyshev1Function2(this->_params, this->getXYRange()));
872  }
873 
880  };
881 
888  int truncOrder
889  ) const {
890  if (truncOrder > this->_order) {
891  std::ostringstream os;
892  os << "truncated order=" << truncOrder << " must be <= original order=" << this->_order;
893  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, os.str());
894  }
895  int truncNParams = this->nParametersFromOrder(truncOrder);
896  std::vector<double> truncParams(this->_params.begin(), this->_params.begin() + truncNParams);
897  return Chebyshev1Function2(truncParams, this->getXYRange());
898  }
899 
900  virtual ReturnT operator() (double x, double y) const {
901  /* Solve as follows:
902  - f(x,y) = Cy0 T0(y') + Cy1 T1(y') + Cy2 T2(y') + Cy3 T3(y') + ...
903  where:
904  Cy0 = P0 T0(x') + P1 T1(x') + P3 T2(x') + P6 T3(x') + ...
905  Cy1 = P2 T0(x') + P4 T1(x') + P7 T2(x') + ...
906  Cy2 = P5 T0(x') + P8 T1(x') + ...
907  Cy3 = P9 T0(x') + ...
908  ...
909 
910  First compute Tn(x') for each n
911  Then use that to compute Cy0, Cy1, ...Cyn
912  Then solve the y Chebyshev polynomial using the Clenshaw algorithm
913  */
914  double const xPrime = (x + _offsetX) * _scaleX;
915  double const yPrime = (y + _offsetY) * _scaleY;
916 
917  const int nParams = static_cast<int>(this->_params.size());
918  const int order = this->_order;
919 
920  if (order == 0) {
921  return this->_params[0]; // No caching required
922  }
923 
924  if ((yPrime != _oldYPrime) || !this->_isCacheValid) {
925  // update cached _yCheby and _xCoeffs
926  _yCheby[0] = 1.0;
927  _yCheby[1] = yPrime;
928  for (int chebyInd = 2; chebyInd <= order; chebyInd++) {
929  _yCheby[chebyInd] = (2 * yPrime * _yCheby[chebyInd-1]) - _yCheby[chebyInd-2];
930  }
931 
932  for (int coeffInd=0; coeffInd <= order; coeffInd++) {
933  _xCoeffs[coeffInd] = 0;
934  }
935  for (int coeffInd = 0, endCoeffInd = 0, paramInd = 0; paramInd < nParams; paramInd++) {
936  _xCoeffs[coeffInd] += this->_params[paramInd] * _yCheby[endCoeffInd];
937  --coeffInd;
938  ++endCoeffInd;
939  if (coeffInd < 0) {
940  coeffInd = endCoeffInd;
941  endCoeffInd = 0;
942  }
943  }
944 
945  _oldYPrime = yPrime;
946  this->_isCacheValid = true;
947  }
948 
949  // Clenshaw function for solving the Chebyshev polynomial
950  // Non-recursive version from Kresimir Cosic
951  if (order == 1) {
952  return _xCoeffs[0] + (_xCoeffs[1] * xPrime);
953  }
954  double cshPrev = _xCoeffs[order];
955  double csh = (2 * xPrime * _xCoeffs[order]) + _xCoeffs[order-1];
956  for (int i = order - 2; i > 0; --i) {
957  double cshNext = (2 * xPrime * csh) + _xCoeffs[i] - cshPrev;
958  cshPrev = csh;
959  csh = cshNext;
960  }
961  return (xPrime * csh) + _xCoeffs[0] - cshPrev;
962  }
963 
964  virtual std::string toString(std::string const& prefix) const {
965  std::ostringstream os;
966  os << "Chebyshev1Function2 [";
967  os << this->_order << ", " << this->getXYRange() << "]";
968  os << Function2<ReturnT>::toString(prefix);
969  return os.str();
970  }
971 
972  virtual bool isPersistable() const { return true; }
973 
974  protected:
975 
976  virtual std::string getPersistenceName() const;
977 
978  virtual void write(afw::table::io::OutputArchiveHandle & handle) const;
979 
980  private:
981  mutable double _oldYPrime;
982  mutable std::vector<double> _yCheby;
983  mutable std::vector<double> _xCoeffs;
984  double _minX;
985  double _minY;
986  double _maxX;
987  double _maxY;
988  double _scaleX;
989  double _scaleY;
990  double _offsetX;
991  double _offsetY;
992 
996  void _initialize(lsst::afw::geom::Box2D const &xyRange) {
997  _minX = xyRange.getMinX();
998  _minY = xyRange.getMinY();
999  _maxX = xyRange.getMaxX();
1000  _maxY = xyRange.getMaxY();
1001  _scaleX = 2.0 / (_maxX - _minX);
1002  _scaleY = 2.0 / (_maxY - _minY);
1003  _offsetX = -(_minX + _maxX) * 0.5;
1004  _offsetY = -(_minY + _maxY) * 0.5;
1005  }
1006 
1007  protected:
1008  /* Default constructor: intended only for serialization */
1010  _oldYPrime(0),
1011  _yCheby(0),
1012  _xCoeffs(0),
1013  _minX(0.0), _minY(0.0),
1014  _maxX(0.0), _maxY(0.0),
1015  _scaleX(1.0), _scaleY(1.0),
1016  _offsetX(0.0), _offsetY(0.0) {}
1017 
1018  private:
1020  template <class Archive>
1021  void serialize(Archive& ar, unsigned int const version) {
1022  ar & make_nvp("fn2", boost::serialization::base_object<BasePolynomialFunction2<ReturnT> >(*this));
1023  ar & make_nvp("minX", this->_minX);
1024  ar & make_nvp("minY", this->_minY);
1025  ar & make_nvp("maxX", this->_maxX);
1026  ar & make_nvp("maxY", this->_maxY);
1027  ar & make_nvp("scaleX", this->_scaleX);
1028  ar & make_nvp("scaleY", this->_scaleY);
1029  ar & make_nvp("offsetX", this->_offsetX);
1030  ar & make_nvp("offsetY", this->_offsetY);
1031  ar & make_nvp("xCheby", this->_yCheby); // sets size of _yCheby; name is historical
1032  _xCoeffs.resize(_yCheby.size());
1033  }
1034  };
1035 
1048  template<typename ReturnT>
1049  class LanczosFunction1: public Function1<ReturnT> {
1050  public:
1052 
1057  unsigned int n,
1058  double xOffset = 0.0)
1059  :
1060  Function1<ReturnT>(1),
1061  _invN(1.0/static_cast<double>(n))
1062  {
1063  this->_params[0] = xOffset;
1064  }
1065 
1066  virtual ~LanczosFunction1() {}
1067 
1068  virtual Function1Ptr clone() const {
1069  return Function1Ptr(new LanczosFunction1(this->getOrder(), this->_params[0]));
1070  }
1071 
1072  virtual ReturnT operator() (double x) const {
1073  double xArg1 = (x - this->_params[0]) * lsst::afw::geom::PI;
1074  double xArg2 = xArg1 * _invN;
1075  if (std::fabs(xArg1) > 1.0e-5) {
1076  return static_cast<ReturnT>(std::sin(xArg1) * std::sin(xArg2) / (xArg1 * xArg2));
1077  } else {
1078  return static_cast<ReturnT>(1);
1079  }
1080  }
1081 
1085  unsigned int getOrder() const {
1086  return static_cast<unsigned int>(0.5 + (1.0 / _invN));
1087  };
1088 
1089  virtual std::string toString(std::string const& prefix) const {
1090  std::ostringstream os;
1091  os << "LanczosFunction1 [" << this->getOrder() << "]: ";;
1092  os << Function1<ReturnT>::toString(prefix);
1093  return os.str();
1094  }
1095 
1096  private:
1097  double _invN; // == 1/n
1098 
1099  protected:
1100  /* Default constructor: intended only for serialization */
1101  explicit LanczosFunction1() : Function1<ReturnT>(1), _invN(1.0) {}
1102 
1103  private:
1105  template <class Archive>
1106  void serialize(Archive& ar, unsigned int const version) {
1107  ar & make_nvp("fn1", boost::serialization::base_object<Function1<ReturnT> >(*this));
1108  ar & make_nvp("invN", this->_invN);
1109  }
1110  };
1111 
1124  template<typename ReturnT>
1125  class LanczosFunction2: public Function2<ReturnT> {
1126  public:
1128 
1133  unsigned int n,
1134  double xOffset = 0.0,
1135  double yOffset = 0.0)
1136  :
1137  Function2<ReturnT>(2),
1138  _invN(1.0 / static_cast<double>(n))
1139  {
1140  this->_params[0] = xOffset;
1141  this->_params[1] = yOffset;
1142  }
1143 
1144  virtual ~LanczosFunction2() {}
1145 
1146  virtual Function2Ptr clone() const {
1147  return Function2Ptr(new LanczosFunction2(this->getOrder(), this->_params[0], this->_params[1]));
1148  }
1149 
1150  virtual ReturnT operator() (double x, double y) const {
1151  double xArg1 = (x - this->_params[0]) * lsst::afw::geom::PI;
1152  double xArg2 = xArg1 * _invN;
1153  double xFunc = 1;
1154  if (std::fabs(xArg1) > 1.0e-5) {
1155  xFunc = std::sin(xArg1) * std::sin(xArg2) / (xArg1 * xArg2);
1156  }
1157  double yArg1 = (y - this->_params[1]) * lsst::afw::geom::PI;
1158  double yArg2 = yArg1 * _invN;
1159  double yFunc = 1;
1160  if (std::fabs(yArg1) > 1.0e-5) {
1161  yFunc = std::sin(yArg1) * std::sin(yArg2) / (yArg1 * yArg2);
1162  }
1163  return static_cast<ReturnT>(xFunc * yFunc);
1164  }
1165 
1169  unsigned int getOrder() const {
1170  return static_cast<unsigned int>(0.5 + (1.0 / _invN));
1171  };
1172 
1173  virtual std::string toString(std::string const& prefix) const {
1174  std::ostringstream os;
1175  os << "LanczosFunction2 [" << this->getOrder() << "]: ";;
1176  os << Function2<ReturnT>::toString(prefix);
1177  return os.str();
1178  }
1179 
1180  private:
1181  double _invN;
1182 
1183  protected:
1184  /* Default constructor: intended only for serialization */
1185  explicit LanczosFunction2() : Function2<ReturnT>(2), _invN(1.0) {}
1186 
1187  private:
1189  template <class Archive>
1190  void serialize(Archive& ar, unsigned int const version) {
1191  ar & make_nvp("fn2", boost::serialization::base_object<Function2<ReturnT> >(*this));
1192  ar & make_nvp("invN", this->_invN);
1193  }
1194  };
1195 
1196 }}} // lsst::afw::math
1197 
1198 #endif // #ifndef LSST_AFW_MATH_FUNCTIONLIBRARY_H
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
int y
virtual bool isLinearCombination() const
Is the function a linear combination of its parameters?
2-dimensional weighted sum of Chebyshev polynomials of the first kind.
void serialize(Archive &ar, unsigned int const version)
friend class boost::serialization::access
double _scaleY
y&#39; = (y + _offsetY) * _scaleY
An include file to include the header files for lsst::afw::geom.
int _order
order of polynomial
Definition: Function.h:492
virtual bool isLinearCombination() const
Is the function a linear combination of its parameters?
PolynomialFunction1(unsigned int order)
Construct a polynomial function of the specified order.
virtual ReturnT operator()(double x) const
friend class boost::serialization::access
std::vector< double > _yCheby
working vector: value of Tn(y&#39;)
PolynomialFunction2(unsigned int order)
Construct a polynomial function of specified order.
double getMinY() const
Definition: Box.h:345
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
double getMaxX() const
Get maximum allowed x.
Function2< ReturnT >::Ptr Function2Ptr
Definition: Function.h:386
1-dimensional Lanczos function
double Guassian (sum of two Gaussians)
virtual ReturnT operator()(double x) const
virtual bool isPersistable() const
Return true if this particular object can be persisted using afw::table::io.
An object passed to Persistable::write to allow it to persist itself.
double _scaleX
x&#39; = (x + _offsetX) * _scaleX
virtual ReturnT operator()(double x, double y) const
GaussianFunction1(double sigma)
Construct a Gaussian function with specified sigma.
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
Function2< ReturnT >::Ptr Function2Ptr
Chebyshev1Function1(std::vector< double > params, double minX=-1, double maxX=1)
Construct a Chebyshev polynomial with specified parameters and range.
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
friend class boost::serialization::access
const double _multFac
precomputed scale factor
virtual Function1Ptr clone() const
Return a pointer to a deep copy of this function.
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
2-dimensional polynomial function with cross terms
double _oldY
value of y for which _xCoeffs is valid
PolynomialFunction1(std::vector< double > params)
Construct a polynomial function with the specified parameters.
double getMinX() const
Get minimum allowed x.
1-dimensional weighted sum of Chebyshev polynomials of the first kind.
virtual Function2Ptr clone() const
Return a pointer to a deep copy of this function.
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
Chebyshev1Function1(unsigned int order, double minX=-1, double maxX=1)
Construct a Chebyshev polynomial of specified order and range.
2-dimensional integer delta function.
virtual ReturnT operator()(double x, double y) const
IntegerDeltaFunction1(double xo)
Construct an integer delta function with specified xo, yo.
virtual std::vector< double > getDFuncDParameters(double x, double y) const
Definition: Function.cc:36
std::vector< double > _xCoeffs
working vector: transformed coeffs of x polynomial
virtual void write(afw::table::io::OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
Function1< ReturnT >::Ptr Function1Ptr
void serialize(Archive &ar, unsigned int const version)
LanczosFunction2(unsigned int n, double xOffset=0.0, double yOffset=0.0)
Construct a Lanczos function of specified order and x,y offset.
Function2< ReturnT >::Ptr Function2Ptr
double getMaxX() const
Definition: Box.h:348
2-dimensional separable Lanczos function
A Function taking two arguments.
Definition: Function.h:300
friend class boost::serialization::access
friend class boost::serialization::access
friend class boost::serialization::access
unsigned int _order
polynomial order
virtual ReturnT operator()(double x, double y) const
const double _multFac
precomputed scale factor
Base class for 2-dimensional polynomials of the form:
Definition: Function.h:384
afw::table::Key< double > sigma
Definition: GaussianPsf.cc:43
static int nParametersFromOrder(int order)
Compute number of parameters from polynomial order.
Definition: Function.h:431
void _initialize(double minX, double maxX)
initialize private constants
virtual Function1Ptr clone() const
Return a pointer to a deep copy of this function.
Function1< ReturnT >::Ptr Function1Ptr
unsigned int getOrder() const
Get the polynomial order.
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
void serialize(Archive &ar, unsigned int const version)
std::vector< double > _xCoeffs
working vector
std::vector< double > _params
Definition: Function.h:204
virtual void write(afw::table::io::OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
virtual ReturnT operator()(double x, double y) const
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
void serialize(Archive &ar, unsigned int const version)
double const PI
The ratio of a circle&#39;s circumference to diameter.
Definition: Angle.h:18
virtual bool isPersistable() const
Return true if this particular object can be persisted using afw::table::io.
IntegerDeltaFunction2(double xo, double yo)
Construct an integer delta function with specified xo, yo.
1-dimensional integer delta function.
friend class boost::serialization::access
virtual ReturnT operator()(double x, double y) const
void serialize(Archive &ar, unsigned int const version)
friend class boost::serialization::access
void serialize(Archive &ar, unsigned int const version)
virtual Chebyshev1Function2 truncate(int truncOrder) const
Return a truncated copy of lower (or equal) order.
Chebyshev1Function2(std::vector< double > params, lsst::afw::geom::Box2D const &xyRange=lsst::afw::geom::Box2D(lsst::afw::geom::Point2D(-1.0,-1.0), lsst::afw::geom::Point2D(1.0, 1.0)))
Construct a Chebyshev polynomial with specified parameters and range.
boost::shared_ptr< Function2< ReturnT > > Ptr
Definition: Function.h:304
lsst::afw::geom::Box2D getXYRange() const
Get x,y range.
Function2< ReturnT >::Ptr Function2Ptr
virtual Function2Ptr clone() const
Return a pointer to a deep copy of this function.
A Function taking one argument.
Definition: Function.h:229
void _initialize(lsst::afw::geom::Box2D const &xyRange)
initialize private constants
double _scale
x&#39; = (x + _offset) * _scale
void serialize(Archive &ar, unsigned int const version)
void _updateCache() const
Update cached values.
PolynomialFunction2(std::vector< double > params)
Construct a polynomial function with specified parameters.
const double _multFac
precomputed scale factor
double x
double _offsetX
x&#39; = (x + _offsetX) * _scaleX
virtual ReturnT operator()(double x, double y) const
virtual ReturnT operator()(double x) const
double const TWOPI
Definition: Angle.h:19
virtual void write(afw::table::io::OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
double _sinAngle
cached sin(angle)
Chebyshev1Function2(unsigned int order, lsst::afw::geom::Box2D const &xyRange=lsst::afw::geom::Box2D(lsst::afw::geom::Point2D(-1.0,-1.0), lsst::afw::geom::Point2D(1.0, 1.0)))
Construct a Chebyshev polynomial of specified order and range.
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
friend class boost::serialization::access
unsigned int getNParameters() const
Return the number of function parameters.
Definition: Function.h:125
Function1< ReturnT >::Ptr Function1Ptr
DoubleGaussianFunction2(double sigma1, double sigma2=0, double ampl2=0)
Construct a Gaussian function with specified x and y sigma.
Function1< ReturnT >::Ptr Function1Ptr
virtual ReturnT operator()(double x) const
void serialize(Archive &ar, unsigned int const version)
Function2< ReturnT >::Ptr Function2Ptr
unsigned int getOrder() const
Get the order of Lanczos function.
afw::table::Key< double > sigma1
unsigned int getOrder() const
Get the order of the Lanczos function.
double _offsetY
y&#39; = (y + _offsetY) * _scaleY
friend class boost::serialization::access
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
virtual Function2Ptr clone() const
Return a pointer to a deep copy of this function.
unsigned int getOrder() const
Get the polynomial order.
double _cosAngle
cached cos(angle)
virtual bool isPersistable() const
Return true if this particular object can be persisted using afw::table::io.
boost::shared_ptr< Function1< ReturnT > > Ptr
Definition: Function.h:233
Define the basic Function classes.
double getMinX() const
Definition: Box.h:344
afw::table::Key< double > b
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
virtual std::string toString(std::string const &prefix="") const
Return a string representation of the function.
virtual Function2Ptr clone() const
Return a pointer to a deep copy of this function.
void serialize(Archive &ar, unsigned int const version)
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
double _offset
x&#39; = (x + _offset) * _scale
void serialize(Archive &ar, unsigned int const version)
virtual Function1Ptr clone() const
Return a pointer to a deep copy of this function.
GaussianFunction2(double sigma1, double sigma2, double angle=0.0)
Construct a 2-dimensional Gaussian function.
friend class boost::serialization::access
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
virtual Function1Ptr clone() const
Return a pointer to a deep copy of this function.
afw::table::Key< double > sigma2
Function1< ReturnT >::Ptr Function1Ptr
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
Function2< ReturnT >::Ptr Function2Ptr
virtual Function2Ptr clone() const
Return a pointer to a deep copy of this function.
Function2< ReturnT >::Ptr Function2Ptr
virtual ReturnT operator()(double x, double y) const
void serialize(Archive &ar, unsigned int const)
virtual void write(afw::table::io::OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
virtual std::string toString(std::string const &prefix) const
Return a string representation of the function.
virtual Function2Ptr clone() const
Return a pointer to a deep copy of this function.
virtual bool isPersistable() const
Return true if this particular object can be persisted using afw::table::io.
1-dimensional polynomial function.
double getMaxY() const
Definition: Box.h:349
LanczosFunction1(unsigned int n, double xOffset=0.0)
Construct a Lanczos function of specified order and x,y offset.
virtual Function1Ptr clone() const
Return a pointer to a deep copy of this function.