20 template <
typename CoeffGetter>
21 double evaluateFunction1d(CoeffGetter g,
double x,
int size) {
22 double b_kp2 = 0.0, b_kp1 = 0.0;
23 for (
int k = (size - 1); k > 0; --k) {
24 double b_k = g[k] + 2 * x * b_kp1 - b_kp2;
28 return g[0] + x * b_kp1 - b_kp2;
36 struct RecursionArrayImitator {
37 double operator[](
int i)
const {
41 RecursionArrayImitator(ndarray::Array<double const, 2, 2>
const &coefficients_,
double x_)
49 afw::geom::AffineTransform makeChebyshevRangeTransform(afw::geom::Box2D
const &
bbox) {
50 return afw::geom::AffineTransform(
53 -(2.0 * bbox.getCenterY()) / bbox.getHeight()));
57 ndarray::Array<double, 2, 2> _identityChebyshev(
size_t degree) {
58 ndarray::Array<double, 2, 2> coeffs = ndarray::allocate(ndarray::makeVector(degree + 1, degree + 1));
67 _toChebyshevRange(makeChebyshevRangeTransform(bbox)),
68 _coefficients(_identityChebyshev(degree)),
70 _nParameters((degree + 1) * (degree + 2) / 2) {}
77 _degree(coefficients.size() - 1),
82 return instFlux * evaluateFunction1d(RecursionArrayImitator(
_coefficients, p.getX()), p.getY(),
88 Eigen::VectorXd::Index k = 0;
89 for (ndarray::Size j = 0; j <=
_degree; ++j) {
90 ndarray::Size
const iMax =
_degree - j;
91 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
104 return 2.0 / (1.0 -
static_cast<double>(n * n));
111 for (ndarray::Size j = 0; j <
_coefficients.getSize<0>(); j++) {
112 for (ndarray::Size i = 0; i <
_coefficients.getSize<1>(); i++) {
116 return result * determinant;
122 Eigen::Ref<Eigen::VectorXd> derivatives)
const {
126 Eigen::VectorXd Tnx(
_degree + 1);
127 Eigen::VectorXd Tmy(
_degree + 1);
134 for (ndarray::Size i = 2; i <=
_degree; ++i) {
135 Tnx[i] = 2 * p.getX() * Tnx[i - 1] - Tnx[i - 2];
136 Tmy[i] = 2 * p.getY() * Tmy[i - 1] - Tmy[i - 2];
140 Eigen::VectorXd::Index k = 0;
141 for (ndarray::Size j = 0; j <=
_degree; ++j) {
142 ndarray::Size
const iMax =
_degree - j;
143 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
144 derivatives[k] = instFlux * Tmy[j] * Tnx[i];
152 Eigen::VectorXd::Index k = 0;
153 for (ndarray::Size j = 0; j <=
_degree; ++j) {
154 for (ndarray::Size i = 0; i + j <=
_degree; ++i, ++k) {
Eigen::VectorXd getParameters() const override
Get a copy of the parameters of this model, in the same order as offsetParams.
Extent< double, 2 > Extent2D
double integrateTn(int n)
ndarray::Array< double, 2, 2 > _coefficients
table::Key< table::Array< int > > degree
A base class for image defects.
geom::Box2I const & _bbox
afw::geom::AffineTransform _toChebyshevRange
void computeParameterDerivatives(double x, double y, double instFlux, Eigen::Ref< Eigen::VectorXd > derivatives) const override
Compute the derivatives with respect to the parameters (i.e.
void offsetParams(Eigen::VectorXd const &delta) override
Offset the parameters by some (negative) amount during fitting.
ndarray::Array< double const, 2, 2 > coefficients
ndarray::Size _nParameters
A floating-point coordinate rectangle geometry.
PhotometryTransfoChebyshev(size_t degree, afw::geom::Box2D const &bbox)
Create an identity (a_0,0==1) Chebyshev transfo with terms up to degree in (x*y). ...
double transform(double x, double y, double instFlux) const override
Apply the transform to instFlux at (x,y), put result in flux.