44 template <
typename CoeffGetter>
45 double evaluateFunction1d(CoeffGetter g,
double x,
int size) {
46 double b_kp2 = 0.0, b_kp1 = 0.0;
47 for (
int k = (size - 1); k > 0; --k) {
48 double b_k = g[k] + 2 * x * b_kp1 - b_kp2;
52 return g[0] + x * b_kp1 - b_kp2;
60 struct RecursionArrayImitator {
61 double operator[](
int i)
const {
65 RecursionArrayImitator(ndarray::Array<double const, 2, 2>
const &coefficients_,
double x_)
73 afw::geom::AffineTransform makeChebyshevRangeTransform(afw::geom::Box2D
const &
bbox) {
74 return afw::geom::AffineTransform(
77 -(2.0 * bbox.getCenterY()) / bbox.getHeight()));
81 ndarray::Array<double, 2, 2> _initializeChebyshev(
size_t order,
bool identity) {
82 ndarray::Array<double, 2, 2> coeffs = ndarray::allocate(ndarray::makeVector(order + 1, order + 1));
94 _toChebyshevRange(makeChebyshevRangeTransform(bbox)),
95 _coefficients(_initializeChebyshev(order, identity)),
97 _nParameters((order + 1) * (order + 2) / 2) {}
102 _toChebyshevRange(makeChebyshevRangeTransform(bbox)),
103 _coefficients(coefficients),
104 _order(coefficients.size() - 1),
105 _nParameters((_order + 1) * (_order + 2) / 2) {}
109 Eigen::VectorXd::Index k = 0;
110 for (ndarray::Size j = 0; j <= _order; ++j) {
111 ndarray::Size
const iMax = _order - j;
112 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
113 _coefficients[j][i] -= delta[k];
125 return 2.0 / (1.0 -
static_cast<double>(n * n));
129 double PhotometryTransfoChebyshev::integrate()
const {
131 double determinant = _bbox.
getArea() / 4.0;
132 for (ndarray::Size j = 0; j < _coefficients.getSize<0>(); j++) {
133 for (ndarray::Size i = 0; i < _coefficients.getSize<1>(); i++) {
137 return result * determinant;
143 Eigen::VectorXd parameters(_nParameters);
145 Eigen::VectorXd::Index k = 0;
146 for (ndarray::Size j = 0; j <= _order; ++j) {
147 ndarray::Size
const iMax = _order - j;
148 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
149 parameters[k] = _coefficients[j][i];
158 return evaluateFunction1d(RecursionArrayImitator(_coefficients, p.getX()), p.getY(),
159 _coefficients.getSize<0>());
163 Eigen::Ref<Eigen::VectorXd> derivatives)
const {
167 Eigen::VectorXd Tnx(_order + 1);
168 Eigen::VectorXd Tmy(_order + 1);
175 for (ndarray::Size i = 2; i <= _order; ++i) {
176 Tnx[i] = 2 * p.getX() * Tnx[i - 1] - Tnx[i - 2];
177 Tmy[i] = 2 * p.getY() * Tmy[i - 1] - Tmy[i - 2];
181 Eigen::VectorXd::Index k = 0;
182 for (ndarray::Size j = 0; j <= _order; ++j) {
183 ndarray::Size
const iMax = _order - j;
184 for (ndarray::Size i = 0; i <= iMax; ++i, ++k) {
185 derivatives[k] = Tmy[j] * Tnx[i];
ndarray::Array< double const, 2, 2 > coefficients
Eigen::VectorXd getParameters() const override
Get a copy of the parameters of this model, in the same order as offsetParams.
A floating-point coordinate rectangle geometry.
double integrateTn(int n)
A base class for image defects.
double getArea() const noexcept
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.
void computeChebyshevDerivatives(double x, double y, Eigen::Ref< Eigen::VectorXd > derivatives) const
Set the derivatives of this polynomial at x,y.
Extent< double, 2 > Extent2D
double computeChebyshev(double x, double y) const
Return the value of this polynomial at x,y.