29 namespace lsst {
namespace meas {
namespace astrom {
43 poly._xCoeffs(1, 0) += 1;
44 poly._yCoeffs(0, 1) += 1;
58 poly._xCoeffs(1, 0) += 1;
59 poly._yCoeffs(0, 1) += 1;
78 "PolynomialTransform order must be >= 0" 82 _xCoeffs.reset(ndarray::Array<double,2,2>(ndarray::allocate(order + 1, order + 1)));
83 _yCoeffs.reset(ndarray::Array<double,2,2>(ndarray::allocate(order + 1, order + 1)));
86 _u = Eigen::VectorXd(order + 1);
87 _v = Eigen::VectorXd(order + 1);
91 ndarray::Array<double const,2,0>
const & xCoeffs,
92 ndarray::Array<double const,2,0>
const & yCoeffs
93 ) : _xCoeffs(
ndarray::copy(xCoeffs)),
94 _yCoeffs(
ndarray::copy(yCoeffs)),
98 if (xCoeffs.getShape() != yCoeffs.getShape()) {
102 "X and Y coefficient matrices must have the same shape: " 103 " (%d,%d) != (%d,%d)" 104 ) % xCoeffs.getSize<0>() % xCoeffs.getSize<1>()
105 % yCoeffs.getSize<0>() % yCoeffs.getSize<1>()
109 if (_xCoeffs.cols() != _xCoeffs.rows()) {
113 "Coefficient matrices must be triangular, not trapezoidal: " 115 ) % _xCoeffs.rows() % _xCoeffs.cols()
138 if (&other !=
this) {
146 if (&other !=
this) {
153 _xCoeffs.swap(other._xCoeffs);
154 _yCoeffs.swap(other._yCoeffs);
160 double xu = 0.0, xv = 0.0, yu = 0.0, yv = 0.0,
x = 0.0, y = 0.0;
164 for (
int p = 0; p <= order; ++p) {
165 for (
int q = 0; q <= order; ++q) {
167 xu += _xCoeffs(p, q) * p * _u[p - 1] * _v[q];
168 yu += _yCoeffs(p, q) * p * _u[p - 1] * _v[q];
171 xv += _xCoeffs(p, q) * q * _u[p] * _v[q - 1];
172 yv += _yCoeffs(p, q) * q * _u[p] * _v[q - 1];
174 x += _xCoeffs(p, q) * _u[p] * _v[q];
175 y += _yCoeffs(p, q) * _u[p] * _v[q];
193 for (
int p = 0; p <= order; ++p) {
194 for (
int q = 0; q <= order; ++q) {
195 x += _xCoeffs(p, q) * _u[p] * _v[q];
196 y += _yCoeffs(p, q) * _u[p] * _v[q];
214 result._poly._xCoeffs(1, 0) += 1;
215 result._poly._yCoeffs(0, 1) += 1;
225 result._poly._xCoeffs(1, 0) += 1;
226 result._poly._yCoeffs(0, 1) += 1;
236 _inputScaling(inputScaling),
237 _outputScalingInverse(outputScalingInverse)
241 _poly.
swap(other._poly);
242 std::swap(_inputScaling, other._inputScaling);
243 std::swap(_outputScalingInverse, other._outputScalingInverse);
247 return _outputScalingInverse*_poly.
linearize(_inputScaling(in))*_inputScaling;
251 return _outputScalingInverse(_poly(_inputScaling(in)));
257 result._xCoeffs = t2._xCoeffs*t1[AT::XX] + t2._yCoeffs*t1[AT::XY];
258 result._yCoeffs = t2._xCoeffs*t1[AT::YX] + t2._yCoeffs*t1[AT::YY];
259 result._xCoeffs(0, 0) += t1[AT::X];
260 result._yCoeffs(0, 0) += t1[AT::Y];
269 t1a._xCoeffs(0, 0) = t1._xCoeffs(0, 0);
270 t1a._yCoeffs(0, 0) = t1._yCoeffs(0, 0);
282 for (
int p = 0; p <= order; ++p) {
283 for (
int m = 0;
m <= p; ++
m) {
284 for (
int j = 0; j <=
m; ++j) {
285 for (
int q = 0; p + q <= order; ++q) {
286 for (
int n = 0; n <= q; ++n) {
287 for (
int k = 0; k <= n; ++k) {
288 double z = binomial(p,
m) * t2u[p-
m] * binomial(
m,j) * t2uu[j] * t2uv[
m-j] *
289 binomial(q,n) * t2v[q-n] * binomial(n,k) * t2vu[k] * t2vv[n-k];
290 result._xCoeffs(j + k,
m + n - j - k) += t1._xCoeffs(p, q) * z;
291 result._yCoeffs(j + k,
m + n - j - k) += t1._yCoeffs(p, q) * z;
A class that computes binomial coefficients up to a certain power.
PolynomialTransform compose(afw::geom::AffineTransform const &t1, PolynomialTransform const &t2)
Return a PolynomialTransform that is equivalent to the composition t1(t2())
Point< double, 2 > Point2D
#define LSST_EXCEPT(type,...)
void computePowers(Eigen::VectorXd &r, double x)
Fill an array with integer powers of x, so .