25 #ifndef LSST_AFW_MATH_FUNCTIONLIBRARY_H
26 #define LSST_AFW_MATH_FUNCTIONLIBRARY_H
51 template <
typename ReturnT>
69 ReturnT
operator()(
double x)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
70 return static_cast<ReturnT
>(
x == _xo);
75 os <<
"IntegerDeltaFunction1 [" << _xo <<
"]: ";
76 os << Function1<ReturnT>::toString(
prefix);
98 template <
typename ReturnT>
116 ReturnT
operator()(
double x,
double y)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
117 return static_cast<ReturnT
>((
x == _xo) && (
y == _yo));
122 os <<
"IntegerDeltaFunction2 [" << _xo <<
", " << _yo <<
"]: ";
123 os << Function2<ReturnT>::toString(
prefix);
146 template <
typename ReturnT>
166 ReturnT
operator()(
double x)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
167 return static_cast<ReturnT
>((_multFac / this->
_params[0]) *
173 os <<
"GaussianFunction1 [" << _multFac <<
"]: ";
174 os << Function1<ReturnT>::toString(
prefix);
179 const double _multFac;
200 template <
typename ReturnT>
227 ReturnT
operator()(
double x,
double y)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
228 if (_angle != this->
_params[2]) {
231 double pos1 = (_cosAngle *
x) + (_sinAngle *
y);
232 double pos2 = (-_sinAngle *
x) + (_cosAngle *
y);
233 return static_cast<ReturnT
>((_multFac / (this->
_params[0] * this->
_params[1])) *
235 ((pos2 * pos2) / (2.0 * this->_params[1] * this->_params[1]))));
240 os <<
"GaussianFunction2: ";
241 os << Function2<ReturnT>::toString(
prefix);
270 void _updateCache() const noexcept {
275 const double _multFac;
276 mutable double _angle;
277 mutable double _sinAngle;
278 mutable double _cosAngle;
304 template <
typename ReturnT>
331 ReturnT
operator()(
double x,
double y)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
332 double radSq = (
x *
x) + (
y *
y);
334 double sigma2Sq = this->_params[1] * this->_params[1];
335 double b = this->_params[2];
336 return static_cast<ReturnT
>(
337 (_multFac / (sigma1Sq + (
b * sigma2Sq))) *
338 (
std::exp(-radSq / (2.0 * sigma1Sq)) + (
b *
std::exp(-radSq / (2.0 * sigma2Sq)))));
343 os <<
"DoubleGaussianFunction2 [" << _multFac <<
"]: ";
344 os << Function2<ReturnT>::toString(
prefix);
356 const double _multFac;
370 template <
typename ReturnT>
390 if (params.
size() < 1) {
392 "PolynomialFunction1 called with empty vector");
408 ReturnT
operator()(
double x)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
409 int const order =
static_cast<int>(this->
_params.
size()) - 1;
410 double retVal = this->
_params[order];
411 for (
int ii = order - 1; ii >= 0; --ii) {
412 retVal = (retVal *
x) + this->
_params[ii];
414 return static_cast<ReturnT
>(retVal);
424 os <<
"PolynomialFunction1 []: ";
425 os << Function1<ReturnT>::toString(
prefix);
448 template <
typename ReturnT>
486 ReturnT
operator()(
double x,
double y)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
501 const int maxXCoeffInd = this->
_order;
506 int paramInd =
static_cast<int>(this->
_params.
size()) - 1;
510 for (
int xCoeffInd = 0; xCoeffInd <= maxXCoeffInd; ++xCoeffInd, --paramInd) {
511 _xCoeffs[xCoeffInd] = this->
_params[paramInd];
515 for (
int xCoeffInd = 0, endXCoeffInd = maxXCoeffInd; paramInd >= 0; --paramInd) {
516 _xCoeffs[xCoeffInd] = (_xCoeffs[xCoeffInd] *
y) + this->
_params[paramInd];
518 if (xCoeffInd >= endXCoeffInd) {
529 double retVal = _xCoeffs[maxXCoeffInd];
530 for (
int xCoeffInd = maxXCoeffInd - 1; xCoeffInd >= 0; --xCoeffInd) {
531 retVal = (retVal *
x) + _xCoeffs[xCoeffInd];
533 return static_cast<ReturnT
>(retVal);
544 os <<
"PolynomialFunction2 [" << this->
_order <<
"]: ";
545 os << Function2<ReturnT>::toString(
prefix);
557 mutable double _oldY;
581 template <
typename ReturnT>
593 _initialize(minX, maxX);
607 if (params.
size() < 1) {
609 "Chebyshev1Function1 called with empty vector");
611 _initialize(minX, maxX);
627 double getMinX() const noexcept {
return _minX; };
632 double getMaxX() const noexcept {
return _maxX; };
642 double xPrime = (
x + _offset) * _scale;
646 int const order = _order;
649 }
else if (order == 1) {
652 double cshPrev = this->
_params[order];
653 double csh = (2 * xPrime * this->
_params[order]) + this->
_params[order - 1];
654 for (
int i = order - 2; i > 0; --i) {
655 double cshNext = (2 * xPrime * csh) + this->
_params[i] - cshPrev;
659 return (xPrime * csh) + this->
_params[0] - cshPrev;
664 os <<
"Chebyshev1Function1 [" << _minX <<
", " << _maxX <<
"]: ";
665 os << Function1<ReturnT>::toString(
prefix);
679 void _initialize(
double minX,
double maxX) {
682 _scale = 2.0 / (_maxX - _minX);
683 _offset = -(_minX + _maxX) * 0.5;
690 :
Function1<ReturnT>(1), _minX(0.0), _maxX(0.0), _scale(1.0), _offset(0.0), _order(0) {}
718 template <
typename ReturnT>
732 _yCheby(this->
_order + 1),
733 _xCoeffs(this->
_order + 1) {
734 _initialize(xyRange);
751 _yCheby(this->
_order + 1),
752 _xCoeffs(this->
_order + 1) {
753 _initialize(xyRange);
781 if (truncOrder > this->
_order) {
783 os <<
"truncated order=" << truncOrder <<
" must be <= original order=" << this->
_order;
805 double const xPrime = (
x + _offsetX) * _scaleX;
806 double const yPrime = (
y + _offsetY) * _scaleY;
808 const int nParams =
static_cast<int>(this->
_params.
size());
809 const int order = this->
_order;
819 for (
int chebyInd = 2; chebyInd <= order; chebyInd++) {
820 _yCheby[chebyInd] = (2 * yPrime * _yCheby[chebyInd - 1]) - _yCheby[chebyInd - 2];
823 for (
int coeffInd = 0; coeffInd <= order; coeffInd++) {
824 _xCoeffs[coeffInd] = 0;
826 for (
int coeffInd = 0, endCoeffInd = 0, paramInd = 0; paramInd < nParams; paramInd++) {
827 _xCoeffs[coeffInd] += this->
_params[paramInd] * _yCheby[endCoeffInd];
831 coeffInd = endCoeffInd;
843 return _xCoeffs[0] + (_xCoeffs[1] * xPrime);
845 double cshPrev = _xCoeffs[order];
846 double csh = (2 * xPrime * _xCoeffs[order]) + _xCoeffs[order - 1];
847 for (
int i = order - 2; i > 0; --i) {
848 double cshNext = (2 * xPrime * csh) + _xCoeffs[i] - cshPrev;
852 return (xPrime * csh) + _xCoeffs[0] - cshPrev;
857 os <<
"Chebyshev1Function2 [";
859 os << Function2<ReturnT>::toString(
prefix);
871 mutable double _oldYPrime;
891 _scaleX = 2.0 / (_maxX - _minX);
892 _scaleY = 2.0 / (_maxY - _minY);
893 _offsetX = -(_minX + _maxX) * 0.5;
894 _offsetY = -(_minY + _maxY) * 0.5;
926 template <
typename ReturnT>
933 double xOffset = 0.0)
934 :
Function1<ReturnT>(1), _invN(1.0 / static_cast<double>(n)) {
948 ReturnT
operator()(
double x)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
950 double xArg2 = xArg1 * _invN;
952 return static_cast<ReturnT
>(
std::sin(xArg1) *
std::sin(xArg2) / (xArg1 * xArg2));
954 return static_cast<ReturnT
>(1);
961 unsigned int getOrder() const noexcept {
return static_cast<unsigned int>(0.5 + (1.0 / _invN)); };
965 os <<
"LanczosFunction1 [" << this->
getOrder() <<
"]: ";
967 os << Function1<ReturnT>::toString(
prefix);
991 template <
typename ReturnT>
998 double xOffset = 0.0,
999 double yOffset = 0.0)
1000 :
Function2<ReturnT>(2), _invN(1.0 / static_cast<double>(n)) {
1016 ReturnT
operator()(
double x,
double y)
const noexcept(IS_NOTHROW_INIT<ReturnT>)
override {
1018 double xArg2 = xArg1 * _invN;
1024 double yArg2 = yArg1 * _invN;
1029 return static_cast<ReturnT
>(xFunc * yFunc);
1035 unsigned int getOrder() const noexcept {
return static_cast<unsigned int>(0.5 + (1.0 / _invN)); };
1039 os <<
"LanczosFunction2 [" << this->
getOrder() <<
"]: ";
1041 os << Function2<ReturnT>::toString(
prefix);
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
table::Key< double > angle
table::Key< double > ampl2
table::Key< double > sigma2
table::Key< double > sigma1
afw::table::Key< double > sigma
Base class for 2-dimensional polynomials of the form:
int _order
order of polynomial
static int nParametersFromOrder(int order)
Compute number of parameters from polynomial order.
1-dimensional weighted sum of Chebyshev polynomials of the first kind.
double getMinX() const noexcept
Get minimum allowed x.
Chebyshev1Function1(std::vector< double > params, double minX=-1, double maxX=1)
Construct a Chebyshev polynomial with specified parameters and range.
Chebyshev1Function1 & operator=(Chebyshev1Function1 const &)=default
unsigned int getOrder() const noexcept
Get the polynomial order.
bool isLinearCombination() const noexcept override
Is the function a linear combination of its parameters?
Chebyshev1Function1(Chebyshev1Function1 const &)=default
Chebyshev1Function1(Chebyshev1Function1 &&)=default
ReturnT operator()(double x) const override
Chebyshev1Function1(unsigned int order, double minX=-1, double maxX=1)
Construct a Chebyshev polynomial of specified order and range.
double getMaxX() const noexcept
Get maximum allowed x.
~Chebyshev1Function1() noexcept override=default
std::shared_ptr< Function1< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
Chebyshev1Function1 & operator=(Chebyshev1Function1 &&)=default
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
2-dimensional weighted sum of Chebyshev polynomials of the first kind.
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
Chebyshev1Function2 & operator=(Chebyshev1Function2 const &)=default
ReturnT operator()(double x, double y) const override
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
std::shared_ptr< Function2< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
Chebyshev1Function2(unsigned int order, lsst::geom::Box2D const &xyRange=lsst::geom::Box2D(lsst::geom::Point2D(-1.0, -1.0), lsst::geom::Point2D(1.0, 1.0)))
Construct a Chebyshev polynomial of specified order and range.
Chebyshev1Function2(Chebyshev1Function2 const &)=default
~Chebyshev1Function2() noexcept override=default
lsst::geom::Box2D getXYRange() const noexcept
Get x,y range.
Chebyshev1Function2 & operator=(Chebyshev1Function2 &&)=default
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
virtual Chebyshev1Function2 truncate(int truncOrder) const
Return a truncated copy of lower (or equal) order.
void write(afw::table::io::OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Chebyshev1Function2(Chebyshev1Function2 &&)=default
Chebyshev1Function2(std::vector< double > params, lsst::geom::Box2D const &xyRange=lsst::geom::Box2D(lsst::geom::Point2D(-1.0, -1.0), lsst::geom::Point2D(1.0, 1.0)))
Construct a Chebyshev polynomial with specified parameters and range.
double Guassian (sum of two Gaussians)
void write(afw::table::io::OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
~DoubleGaussianFunction2() noexcept override=default
DoubleGaussianFunction2(double sigma1, double sigma2=0, double ampl2=0)
Construct a Gaussian function with specified x and y sigma.
DoubleGaussianFunction2 & operator=(DoubleGaussianFunction2 const &)=default
std::shared_ptr< Function2< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
DoubleGaussianFunction2(DoubleGaussianFunction2 &&)=default
DoubleGaussianFunction2(DoubleGaussianFunction2 const &)=default
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
ReturnT operator()(double x, double y) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
DoubleGaussianFunction2 & operator=(DoubleGaussianFunction2 &&)=default
DoubleGaussianFunction2()
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
A Function taking one argument.
A Function taking two arguments.
std::vector< double > _params
unsigned int getNParameters() const noexcept
Return the number of function parameters.
~GaussianFunction1() noexcept override=default
GaussianFunction1(GaussianFunction1 &&)=default
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
GaussianFunction1 & operator=(GaussianFunction1 &&)=default
GaussianFunction1(GaussianFunction1 const &)=default
GaussianFunction1(double sigma)
Construct a Gaussian function with specified sigma.
GaussianFunction1 & operator=(GaussianFunction1 const &)=default
std::shared_ptr< Function1< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
ReturnT operator()(double x) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
GaussianFunction2(double sigma1, double sigma2, double angle=0.0)
Construct a 2-dimensional Gaussian function.
GaussianFunction2(GaussianFunction2 &&)=default
GaussianFunction2(GaussianFunction2 const &)=default
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
~GaussianFunction2() noexcept override=default
void write(afw::table::io::OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
GaussianFunction2 & operator=(GaussianFunction2 const &)=default
GaussianFunction2 & operator=(GaussianFunction2 &&)=default
ReturnT operator()(double x, double y) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
std::shared_ptr< Function2< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
1-dimensional integer delta function.
~IntegerDeltaFunction1() noexcept override=default
IntegerDeltaFunction1(IntegerDeltaFunction1 const &)=default
ReturnT operator()(double x) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
IntegerDeltaFunction1 & operator=(IntegerDeltaFunction1 const &)=default
IntegerDeltaFunction1(double xo)
Construct an integer delta function with specified xo.
IntegerDeltaFunction1 & operator=(IntegerDeltaFunction1 &&)=default
IntegerDeltaFunction1(IntegerDeltaFunction1 &&)=default
std::string toString(std::string const &prefix="") const override
Return a string representation of the function.
std::shared_ptr< Function1< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
2-dimensional integer delta function.
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
IntegerDeltaFunction2(IntegerDeltaFunction2 const &)=default
IntegerDeltaFunction2 & operator=(IntegerDeltaFunction2 const &)=default
ReturnT operator()(double x, double y) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
~IntegerDeltaFunction2() noexcept override=default
IntegerDeltaFunction2(double xo, double yo)
Construct an integer delta function with specified xo, yo.
IntegerDeltaFunction2 & operator=(IntegerDeltaFunction2 &&)=default
IntegerDeltaFunction2(IntegerDeltaFunction2 &&)=default
std::shared_ptr< Function2< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
1-dimensional Lanczos function
LanczosFunction1(unsigned int n, double xOffset=0.0)
Construct a Lanczos function of specified order and x,y offset.
~LanczosFunction1() noexcept override=default
LanczosFunction1 & operator=(LanczosFunction1 &&)=default
LanczosFunction1(LanczosFunction1 &&)=default
std::shared_ptr< Function1< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
LanczosFunction1(LanczosFunction1 const &)=default
ReturnT operator()(double x) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
LanczosFunction1 & operator=(LanczosFunction1 const &)=default
unsigned int getOrder() const noexcept
Get the order of the Lanczos function.
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
2-dimensional separable Lanczos function
std::shared_ptr< Function2< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
~LanczosFunction2() noexcept override=default
LanczosFunction2 & operator=(LanczosFunction2 &&)=default
LanczosFunction2(LanczosFunction2 &&)=default
LanczosFunction2(LanczosFunction2 const &)=default
LanczosFunction2(unsigned int n, double xOffset=0.0, double yOffset=0.0)
Construct a Lanczos function of specified order and x,y offset.
ReturnT operator()(double x, double y) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
unsigned int getOrder() const noexcept
Get the order of Lanczos function.
LanczosFunction2 & operator=(LanczosFunction2 const &)=default
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
1-dimensional polynomial function.
unsigned int getOrder() const noexcept
Get the polynomial order.
PolynomialFunction1 & operator=(PolynomialFunction1 &&)=default
std::shared_ptr< Function1< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
bool isLinearCombination() const noexcept override
Is the function a linear combination of its parameters?
PolynomialFunction1(std::vector< double > params)
Construct a polynomial function with the specified parameters.
PolynomialFunction1 & operator=(PolynomialFunction1 const &)=default
PolynomialFunction1(PolynomialFunction1 &&)=default
PolynomialFunction1(unsigned int order)
Construct a polynomial function of the specified order.
PolynomialFunction1(PolynomialFunction1 const &)=default
ReturnT operator()(double x) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
~PolynomialFunction1() noexcept override=default
2-dimensional polynomial function with cross terms
PolynomialFunction2(std::vector< double > params)
Construct a polynomial function with specified parameters.
PolynomialFunction2 & operator=(PolynomialFunction2 const &)=default
PolynomialFunction2(unsigned int order)
Construct a polynomial function of specified order.
PolynomialFunction2 & operator=(PolynomialFunction2 &&)=default
std::string toString(std::string const &prefix) const override
Return a string representation of the function.
PolynomialFunction2(PolynomialFunction2 const &)=default
std::shared_ptr< Function2< ReturnT > > clone() const override
Return a pointer to a deep copy of this function.
~PolynomialFunction2() noexcept override=default
std::vector< double > getDFuncDParameters(double x, double y) const override
Return the coefficients of the Function's parameters, evaluated at (x, y) I.e.
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
ReturnT operator()(double x, double y) const noexcept(IS_NOTHROW_INIT< ReturnT >) override
PolynomialFunction2(PolynomialFunction2 &&)=default
void write(afw::table::io::OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
An object passed to Persistable::write to allow it to persist itself.
A floating-point coordinate rectangle geometry.
double getMaxY() const noexcept
double getMaxX() const noexcept
double getMinY() const noexcept
double getMinX() const noexcept
Reports invalid arguments.
constexpr double PI
The ratio of a circle's circumference to diameter.
A base class for image defects.