27 #include "lsst/afw/coord/Coord.h" 28 #include "lsst/afw/image/TanWcs.h" 31 namespace lsst {
namespace meas {
namespace astrom {
39 auto sInv = s.invert();
47 afw::geom::Point2D
const & pixelOrigin,
48 afw::geom::LinearTransform
const & cdMatrix
51 afw::geom::AffineTransform(cdMatrix.invert()),
54 afw::geom::AffineTransform(afw::geom::Extent2D(pixelOrigin))
60 forwardSipPoly._xCoeffs(1, 0) -= 1;
61 forwardSipPoly._yCoeffs(0, 1) -= 1;
67 afw::geom::Point2D
const & pixelOrigin,
68 afw::geom::LinearTransform
const & cdMatrix
74 scaled.
getInputScaling()*afw::geom::AffineTransform(afw::geom::Extent2D(pixelOrigin))
79 forwardSipPoly._xCoeffs(1, 0) -= 1;
80 forwardSipPoly._yCoeffs(0, 1) -= 1;
86 afw::geom::LinearTransform cdMatrix(scaled.
getInputScaling().getLinear().invert());
87 return convert(scaled, pixelOrigin, cdMatrix);
91 if (!wcs.hasDistortion()) {
93 pex::exceptions::LogicError,
94 "Constructing a SipForwardTransform from a TanWcs with no distortions is not implemented." 97 ndarray::Array<double,2,2> xCoeffs = ndarray::allocate(wcs.getSipA().rows(), wcs.getSipA().cols());
98 ndarray::Array<double,2,2> yCoeffs = ndarray::allocate(wcs.getSipB().rows(), wcs.getSipB().cols());
99 xCoeffs.asEigen() = wcs.getSipA();
100 yCoeffs.asEigen() = wcs.getSipB();
102 wcs.getPixelOrigin(),
103 afw::geom::LinearTransform(wcs.getCDMatrix()),
109 afw::geom::AffineTransform tail(-afw::geom::Extent2D(
getPixelOrigin()));
110 return afw::geom::AffineTransform(
_cdMatrix)
116 afw::geom::Point2D duv(uv - afw::geom::Extent2D(
getPixelOrigin()));
128 afw::geom::Point2D
const & pixelOrigin,
129 afw::geom::LinearTransform
const & cdMatrix
132 afw::geom::AffineTransform(-afw::geom::Extent2D(pixelOrigin)),
135 afw::geom::AffineTransform(cdMatrix)
140 reverseSipPoly._xCoeffs(1, 0) -= 1;
141 reverseSipPoly._yCoeffs(0, 1) -= 1;
147 afw::geom::Point2D
const & pixelOrigin,
148 afw::geom::LinearTransform
const & cdMatrix
151 afw::geom::AffineTransform(-afw::geom::Extent2D(pixelOrigin))
160 reverseSipPoly._xCoeffs(1, 0) -= 1;
161 reverseSipPoly._yCoeffs(0, 1) -= 1;
174 if (!wcs.hasDistortion()) {
176 pex::exceptions::LogicError,
177 "Constructing a SipReverseTransform from a TanWcs with no distortions is not implemented." 180 ndarray::Array<double,2,2> xCoeffs = ndarray::allocate(wcs.getSipAp().rows(), wcs.getSipAp().cols());
181 ndarray::Array<double,2,2> yCoeffs = ndarray::allocate(wcs.getSipBp().rows(), wcs.getSipBp().cols());
182 xCoeffs.asEigen() = wcs.getSipAp();
183 yCoeffs.asEigen() = wcs.getSipBp();
185 wcs.getPixelOrigin(),
186 afw::geom::LinearTransform(wcs.getCDMatrix()),
194 result._cdInverse = result.
_cdMatrix.invert();
199 return afw::geom::AffineTransform(afw::geom::Extent2D(
getPixelOrigin()))
200 * (afw::geom::AffineTransform() +
_poly.
linearize(_cdInverse(in)))
205 afw::geom::Point2D UV = _cdInverse(xy);
213 afw::coord::Coord
const & skyOrigin
216 std::ostringstream oss;
217 oss <<
"SIP forward and reverse transforms have inconsistent CRPIX: " 220 pex::exceptions::InvalidParameterError,
225 std::ostringstream oss;
226 oss <<
"SIP forward and reverse transforms have inconsistent CD matrix: " 229 pex::exceptions::InvalidParameterError,
239 std::string coordSys;
240 switch (skyOrigin.getCoordSystem()) {
241 case afw::coord::ICRS:
244 case afw::coord::FK5:
249 pex::exceptions::InvalidParameterError,
250 "Coordinate system not supported" 253 return std::make_shared<afw::image::TanWcs>(
254 skyOrigin.getPosition(afw::geom::degrees),
257 sipA, sipB, sipAP, sipBP,
258 skyOrigin.getEpoch(),
264 afw::image::TanWcs
const & wcs,
265 afw::geom::AffineTransform
const & s
267 if (wcs.hasDistortion()) {
270 return makeWcs(fwd, rev, *wcs.getSkyOrigin());
272 auto sInv = s.invert();
273 auto pixelOrigin = s.getLinear()(wcs.getPixelOrigin() - sInv.getTranslation());
274 Eigen::Matrix2d cdMatrix = wcs.getCDMatrix() * sInv.getLinear().getMatrix();
275 return std::make_shared<afw::image::TanWcs>(
276 wcs.getSkyOrigin()->toIcrs().getPosition(afw::geom::degrees),
286 afw::image::TanWcs
const & wcs,
288 afw::geom::Extent2I
const & dimensions
290 afw::geom::Extent2D offset;
291 switch(nQuarter % 4) {
293 offset = afw::geom::Extent2D(0, 0);
296 offset = afw::geom::Extent2D(dimensions.getY() - 1, 0);
299 offset = afw::geom::Extent2D(dimensions - afw::geom::Extent2I(1, 1));
302 offset = afw::geom::Extent2D(0, dimensions.getX() - 1);
305 auto rot = afw::geom::LinearTransform::makeRotation(nQuarter*90.0*afw::geom::degrees);
308 afw::geom::AffineTransform(rot, offset)
std::shared_ptr< afw::image::TanWcs > transformWcsPixels(afw::image::TanWcs const &wcs, afw::geom::AffineTransform const &s)
Create a new TanWcs whose pixel coordinate system has been transformed via an affine transform...
PolynomialTransform compose(afw::geom::AffineTransform const &t1, PolynomialTransform const &t2)
Return a PolynomialTransform that is equivalent to the composition t1(t2())
std::shared_ptr< afw::image::TanWcs > rotateWcsPixelsBy90(afw::image::TanWcs const &wcs, int nQuarter, afw::geom::Extent2I const &dimensions)
Return a new TanWcs that represents a rotation of the image it corresponds to about the image's cente...
std::shared_ptr< afw::image::TanWcs > makeWcs(SipForwardTransform const &sipForward, SipReverseTransform const &sipReverse, afw::coord::Coord const &skyOrigin)
Create a new TAN SIP Wcs from a pair of SIP transforms and the sky origin.