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(
51 afw::geom::LinearTransform::makeScaling(2.0 / bbox.getWidth(), 2.0 / bbox.getHeight()),
52 afw::geom::Extent2D(-(2.0 * bbox.getCenterX()) / bbox.getWidth(),
53 -(2.0 * bbox.getCenterY()) / bbox.getHeight()));
57 ndarray::Array<double, 2, 2> _initializeChebyshev(
size_t order,
bool identity) {
58 ndarray::Array<double, 2, 2> coeffs = ndarray::allocate(ndarray::makeVector(order + 1, order + 1));
70 _toChebyshevRange(makeChebyshevRangeTransform(bbox)),
71 _coefficients(_initializeChebyshev(order, identity)),
73 _nParameters((order + 1) * (order + 2) / 2) {}
76 afw::geom::Box2D
const &bbox)
78 _toChebyshevRange(makeChebyshevRangeTransform(bbox)),
79 _coefficients(coefficients),
80 _order(coefficients.size() - 1),
81 _nParameters((_order + 1) * (_order + 2) / 2) {}
85 Eigen::VectorXd::Index k = 0;
86 for (ndarray::Size j = 0; j <= _order; ++j) {
87 ndarray::Size
const iMax = _order - j;
88 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
89 _coefficients[j][i] -= delta[k];
101 return 2.0 / (1.0 -
static_cast<double>(n * n));
105 double PhotometryTransfoChebyshev::integrate()
const {
107 double determinant = _bbox.getArea() / 4.0;
108 for (ndarray::Size j = 0; j < _coefficients.getSize<0>(); j++) {
109 for (ndarray::Size i = 0; i < _coefficients.getSize<1>(); i++) {
113 return result * determinant;
119 Eigen::VectorXd parameters(_nParameters);
121 Eigen::VectorXd::Index k = 0;
122 for (ndarray::Size j = 0; j <= _order; ++j) {
123 ndarray::Size
const iMax = _order - j;
124 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
125 parameters[k] = _coefficients[j][i];
133 afw::geom::Point2D p = _toChebyshevRange(afw::geom::Point2D(x, y));
134 return evaluateFunction1d(RecursionArrayImitator(_coefficients, p.getX()), p.getY(),
135 _coefficients.getSize<0>());
139 Eigen::Ref<Eigen::VectorXd> derivatives)
const {
140 afw::geom::Point2D p = _toChebyshevRange(afw::geom::Point2D(x, y));
143 Eigen::VectorXd Tnx(_order + 1);
144 Eigen::VectorXd Tmy(_order + 1);
151 for (ndarray::Size i = 2; i <= _order; ++i) {
152 Tnx[i] = 2 * p.getX() * Tnx[i - 1] - Tnx[i - 2];
153 Tmy[i] = 2 * p.getY() * Tmy[i - 1] - Tmy[i - 2];
157 Eigen::VectorXd::Index k = 0;
158 for (ndarray::Size j = 0; j <= _order; ++j) {
159 ndarray::Size
const iMax = _order - j;
160 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
161 derivatives[k] = Tmy[j] * Tnx[i];
Eigen::VectorXd getParameters() const override
Get a copy of the parameters of this model, in the same order as offsetParams.
double integrateTn(int n)
Class for a simple mapping implementing a generic Gtransfo.
std::unique_ptr< SchemaItem< U > > result
PhotometryTransfoChebyshev(size_t order, afw::geom::Box2D const &bbox, bool identity)
Create a Chebyshev transfo with terms up to order in (x*y).
void offsetParams(Eigen::VectorXd const &delta) override
Offset the parameters by some (negative) amount during fitting.
ndarray::Array< double const, 2, 2 > coefficients
void computeChebyshevDerivatives(double x, double y, Eigen::Ref< Eigen::VectorXd > derivatives) const
Set the derivatives of this polynomial at x,y.
double computeChebyshev(double x, double y) const
Return the value of this polynomial at x,y.