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(
75 afw::geom::LinearTransform::makeScaling(2.0 / bbox.getWidth(), 2.0 / bbox.getHeight()),
76 afw::geom::Extent2D(-(2.0 * bbox.getCenterX()) / bbox.getWidth(),
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) {}
100 afw::geom::Box2D
const &bbox)
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 PhotometryTransformChebyshev::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];
157 afw::geom::Point2D p = _toChebyshevRange(afw::geom::Point2D(x, y));
158 return evaluateFunction1d(RecursionArrayImitator(_coefficients, p.getX()), p.getY(),
159 _coefficients.getSize<0>());
163 double x,
double y, Eigen::Ref<Eigen::VectorXd> derivatives)
const {
164 afw::geom::Point2D p = _toChebyshevRange(afw::geom::Point2D(x, y));
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];
double integrateTn(int n)
Class for a simple mapping implementing a generic AstrometryTransform.
std::unique_ptr< SchemaItem< U > > result