Replacing Wcs and TanWcs with SkyWcs

The image::Wcs and image::TanWcs classes have gone away, replaced by geom::SkyWcs. This was merged 2018-02-16 from ticket DM-10765.

The primary reason for this change is to support more flexible models of WCS models than those supported by FITS. This will eventually be used by jointcal to provide a superior fit WCS. From the beginning it will also be used to add an initial distortion model to the WCS in raw images that is derived from camera geometry.

The internals of SkyWcs are implemented using AST. via the astshim package. This will rarely be visible to users, but code that does sophisticated things with WCS will have to know something about it.

Primary Changes in afw

  • image::makeWcs(crval, crpix, cd1_1, cd1_2, cd2_1, cd2_2) -> geom::makeSkyWcs(crpix, crval, cd, projection="TAN"), often with geom::makeCdMatrix to create the CD matrix. Note that crpix and crval are swapped; crpix is first because a WCS converts from pixels to sky in the forward direction in the contained transform. However, you may use named arguments in Python, and I have done so in all conversions.

  • SkyWcs is immutable. Thus any code that formerly modified Wcs in place now returns a new WCS, including:

    • image::Wcs.flipImage -> geom::makeFlippedWcs. I renamed it because I found the name confusing, especially since it is very different than afwMath.flipImage.
    • image::Wcs.shiftReferencePixel -> geom::SkyWcs.copyAtShiftedPixelOrigin. The name “pixel origin” matches the existing getPixelOrigin.
    • image::Wcs.rotateImageBy90 is gone, since it is not used anywhere. However, it could easily be added as geom::makeRotatedWcs. (Note that free function math::rotateImageBy90 also exists and is used.)
  • SkyWcs always works in ICRS coordinates with axis order RA, Dec. Images and exposures that use other coordinate systems or use Dec, RA axis order are normalized as they are read in. Note that use of coord::IcrsCoord is temporary, since we plan to replace all Coord classes with SkyCoord.

    This may result in your code computing different sky positions now, especially if it used a wcs without paying attention its coordinate system. Even FK5 J2000 has small differences from ICRS. Always working in ICRS is much simpler and safer, especially since all of our reference catalogs have ICRS positions.

  • SkyWcs.pixelToSky returns coord::IcrsCoord instead of std::shared_ptr<Coord>

  • SkyWcs has no default constructor.

  • Wcs.pixelScale() -> SkyWcs.getPixelScale() to standardize the name

  • Wcs.getCDMatrix() -> ScyWcs.getCdMatrix() to standardize the name

  • image::DistortedTanWcs(wcs, transform) -> geom::makeModifiedWcs(transform, wcs). Note the argument order change! This is to make the order clear, since the behavior is: newWcs.pixelsToSky = first transform in the forward direction, then apply oldWcs.pixelsToSky

  • geom::XYTransformFromWcsPair(dest, src) -> geom::makeWcsPairTransform(src, dest); note that the arguments are swapped, in order to make code eaiser to read. The result (as before) is: src.pixelsToSky then dest.skyToPixels

  • geom::warpImage(..., XYTransform srcToDest...) is gone; use geom::warpImage(..., TransformPoint2ToPoint2 srcToDest, ...) instead. Warning: I swapped the direction of the transform in the pre-existing Transform version in order to match the XYTransform version because the XYTransform version was much more widely used and its order seemed more natural.

Changes in ip_isr

  • IsrTask.addDistortionModel is a new method which adds a distortion model to the WCS using transforms found in the camera and the Detector.

  • IsrTask.run has a new argument: camera. This is needed by IsrTask.addDistortionModel.

  • IsrTaskConfig has a new entry: doAddDistortionModel which defaults to True. This allows IsrTask to apply a distortion model to the WCS. obs_decam changes the default to False because raw images have TPV terms and these presumably already model distortion. obs_sdss does not run the relevant code and continues to use the WCS as provided (though now normalized to ICRS RA, Dec).

Other Changes

  • The functions lsst.afw.table.updateRefCentroids and updateSourceCoords are now written in C++, for improved performance. Also the former now sets the hasCentroid field. These functions are the recommended ways to apply a WCS to a reference catalog or source catalog.

  • afw no longer depends on wcslib.

  • Polygon, Ellipse and Quadrupole are now available in lsst.afw.geom; formerly they had to be imported from lsst.afw.geom.ellipses in order to avoid a circular import. Note other symbols from lsst.afw.geom.ellipses, such as Axes, are not made available in lsst.afw.geom because they are potentially ambiguous.

  • You must manually import lsst.afw.coord in Python code in order to use SkyWcs.pixelToSky. This nuisance will go away when the Coord classes go away.

  • WCS no longer uses LTV1, LTV2 for XY0; it now matches Image and MaskedImage in using CRVAL1A, CRVAL2A

  • New pybind11 wrapper function for table persistable objects: addPersistableMethods; this replaces declarePersistableFacade, which is now deprecated. Thanks to Jim Bosch for suggesting this.