DMTN-005: Current LSST stack WCS usage

  • John Parejko

Latest Revision: 2016-01-18


This technical note was up-to-date as of 2016-01-18; changes in the stack since then are not reflected in its contents.

Current usage of WCS in the lsst stack

The products afw, ip_diffim, and meas_astrom each make extensive use of our Wcs implementation. In other packages, the use is mostly in tests or examples.



Doesn’t use wcs, but shouldn’t it?
makeWcs from metadata and make exposure with it.
prepareWcsData() converts from amp to ccd coordinates, calls [1] flipImage, [2] shiftReferencePixel. makeFocalPlaneWcs creates a basic px->mm Wcs via CR/CD/etc. and calling makeWcs.
mtv can take a wcs if you don’t pass an exposure, for display.
Output a WCS FITS image file descriptor for e.g. DS9.
drawCoaddInputs calls skyToPixel(pixelToSky) for every ccdCorner, for display.
mostly swig output
Compare Wcs in a grid. Loops over xyList calling pixelToSky, then skyToPixel.
getDistortedWcs() creates a DistortedTanWcs from a tanWcs+pixelsToTanPixels.
mostly swig output
Takes Wcs to convert between exposures. computeWarpedBBox() calls skyToPixel(pixelToSky) for the edges of the bounding box. Calls mathLib for the real work of warpExposure and warpImage.


detection/Footprint::transformPoint and Footprint::transform
Transform point x,y from one image to another via skyToPixel and pixelToSky, and use transformPoint to transform corners and loop over points. Should these be in here, or in image or math?
How to persist a wcs.
There’s afw::gpu, but it is only referenced in afw and the implemetation is several years old: should it be dropped? math::detail::cudaLanczosWrapper imports Wcs.h, but doesn’t seem to do anything with it.

DistoredTanWcs - mostly not implemented!,,, have utilities for reading/writing Wcs to FITS.

makeWcs - Produce a WCS object from a FITS header.

TanWcs - where the magic happens

Wcs - where the magic really happens

warpExposure extensive use of wcs for pixel position calculations/conversions
table reads/writes wcs and uses it to find whether a point is in the exposure. updateCoord uses pixelToSky on either the centroid or a given center.

Test several interpolation lengths, (one) scale factor, (one) arcsec offset, rotation angle and kernel name, making a Wcs and timing how long it takes to warp an exposure with it.
All wcs handling is managed internally Exposures.
Timing of GPU acceleration, calls warpImage with the Wcs’s.
Demo of outputting various computed values from a FITS file with a WCS.

Tests linearWcs vs. sipWcs.
Timings of gpu accelerations, plus some actual comparison tests between GPU and CPU.
Direct number comparisons of Wcs calculations.
Plenty of python tests.


Calls pixelToSky on an exposure’s center/corners and skyToPixel() on the sky corners.
imagePsfMatchTask.matchExposures only calls getWcs() while warping/making. Lots of assumptions about wcs, but little explicit. _validateWcs() compare if two exposures have same origin&extent. Used only in matchExposures to check if we need to warp the template to the science. Calls pxielToSky on bounding boxes.
aggregate() takes wcsresids, but it’s unclear what exactly those are (looks like a dict?)
uses exposure.getWcs to make an ExposureF.
printSkyDiffs calls pixelToSky to compute deltas, though the call signature looks odd. makeRegions uses for loop over sources to call pixelToSky if a wcs is given, else just the source coordinates directly. showSourcesSetSky uses for loop over sources to call skyToPixel to draw dots in ds9. plotWhisker uses pixelToSky to compute offsets between a set of astrometric matches.


No references to Wcs at all in src!


Several examples call warpExposure with exposure.getWcs() as the first arg, but that’s nicely abstracted.

Generate a fake WCS as a FITS header.
generates a fake WCS as a FITS header.


generates a fake WCS as a FITS header, which is what all the tests use to build their fake wcs.
generates a fake WCS as a FITS header, which is what all the tests use to build their fake wcs.


uses hasDistortion(), shiftReferencePixel(), skyToPixel(), pixelToSky() and calls makeCreateWcsWithSip()
Uses updateCoord(wcs) to update a source catalog. Also calls pixelScale(), pixelToSky(), isFlipped(), linearizePixelToSky(), skyToPixel(), getFitsMetadata(), shiftReferencePixel().
Either calls getSkyOrigin(), getPixelOrigin(), and getCDMatrix to then use makeWcs() to generate a tanWcs, or just uses a tan wcs directly. Calls makeCreateWcsWithSip() on said tanWcs.
Calls pixelToSky(). Defaults to using fitTanSipWcsTask to do the fit.
Calls skyToPixel() and pixelToSky(). Instantiates afwImage.Wcs from coordinates.
All the work happens in the src lib, though there is one call to pixelScale().
Calls skyToPixel, though appears to be broken? Only applies to X array.

makeMatchStatisticsInPixels/makeMatchStatisticsInRadians statistics of on- sky/detector given a wcs and a list of matches. Use skyToPixel and pixelToSky, respectively.
Several functions that call skyToPixel/pixelToSky, e.g. between tangent and distorted Wcs’s. matchOptimisticB() uses wcs.hasDistortion() to check and build a tanWcs using wcs.getCDMatrix() on the distorted one.
Computes SIP distortion between catalogue and image, given the matches and a linear Wcs from image pixels to catalog RA/Dec. Instantiates afw::image::Wcs and afw::image::TanWcs. Depends on getPixelOrigin, getCDMatrix, skyToIntermediateWorldCoord, undistortPixel, getSkyOrigin. Claims to use Wcs to to convert xy <->ra/dec to find common objects between
source and image lists. Appears to do this via image->updateCoord(wcs), as the wcs is not used elsewhere.

makeCcdMosaic() creates a wcs from FITS metadata. showStandards() gets a wcs from an image and uses skyToPixel to check whether standards are in the image. setRaDec() calls pixelToSky to set ra/dec for each source in a list.
Creates a TanWcs from the Wcs of a calexp, and plots them with wcsPlots. and
Creates a wcs from determineWcs and writes it to a fits file via wcs.gtFitsMetadata(). NOTE: the ‘_’ version is nearly a superset of the ‘-‘ version, but not entirely...
Why isn’t this a test? Creates a few Wcs and calls their skyToPixels().
Used by some of the above to plot matches, using skyToPixel()

Calls pixelToSky() and skyToPixel(). Some commented out FITS code, and an updateCoord call.
testDetermineWcs and testUseKnownWcs don’t actually test anything, but call a function 3+ times each! The OpenFilesTest docstring claims this is intended behavior...
Instantiates afwImage.TanWcs from FITS metadata, to build an image and afwImage.Instantiates DistortedTanWcs in the test.
Instantiates afwImage.TanWcs from FITS metadata. Instantiates DistortedTanWcs in tests, and has code to plot the Wcs.
Makes a tanWcs from raw numbers and its pixelToSky(), skyToPixel(). Also has plotting code.
Instantiates afwImage.Wcs from FITS metadata and uses its pixelToSky()
Instantiates afwImage.TanWcs from FITS metadata.
Calls afwImage.makeWcs from FITS metadata. Calls skyToPixel() and pixelToSky(). Instantiates afwImage.DistortedTanWcs() in a test.
Calls afwImage.makeWcs from raw numbers and its pixelToSky().
Calls afwImage.makeWcs from values in files and their pixelToSky(), skyToPixel().


  • many examples in the docs.
  • uses it in an example
  • coaddBase uses it in SelectDataIdContainer.makeDataRefList
  • mockObservation builds simple WCSs
  • testRegister does a bunch of wcs things
  • wcsSelectImages does a bunch of wcs stuff, but it might all be tests.

Other uses

used to make an ExposureFromImage
used in several tests
wcs get built in psfex for ds9 display
makes wcs for XY transforms (one wcs to another) in
obs_lsstSim uses it to convert an image to a polygon
A few things use it for image conversions/parsing (all python)
All of the BaseSkyMap-derived python classes use it.
coadd_chisquared class takes an lsst.afw.math.Wcs; refers to afw__image__*Wcs stuff.
coadd_utils refers to afw__image__*Wcs stuff; class takes an lsst.afw.math.Wcs
ip_isr gets/sets wcs from exposures.

Other notes

So I don’t lose other things I’ve found that may be relevant later:

Examples of the “standard” FITS projections, as implemented in astropy:

The papers describing those transforms: