Shared Interface for World Coordinate System - APE 14¶
To improve interoperability between packages, the Astropy Project and other interested parties have collaboratively defined a standardized application programming interface (API) for world coordinate system objects to be used in Python. This API is described in the Astropy Proposal for Enhancements (APE) 14: A shared Python interface for World Coordinate Systems.
The shared interface makes a strong distinction betweek the low-level and high-level
and high-level objects. In APE 14 terminology, a low level object is something that
functions like an array such as a ndarray. In contrast, a high level object
is something that has rich metadata and methods associated with it, like an
SkyCoord.
Note
APE 14 does not address the concepts of the astropy Quantity
objects, which are essentially arrays with unit metadata attached to them.
astropy does its best to make Quantity act like
ndarray objects; however, the FITSWCS implementation of the shared
API in astropy does not support Quantity objects in the
low-level interface. Instead FITSWCS treats Quantity objects
as high-level objects.
GWCS is slightly more flexible in this regard with respect to its low-level
interface in that it supports Quantity objects as inputs in
the same way as ndarray objects. This only works if the transforms
used within the GWCS object are defined in a way that supports units.
The base classes that define the low- (BaseLowLevelWCS) and high-
(BaseHighLevelWCS) level APIs are in astropy.
GWCS implements both APIs. Once a GWCS object is created the API methods will be available.
It is recommended that applications use the Shared API to
ensure transparent use of GWCS and FITSWCS objects.
The example below illustrates the capabilities of the Shared API.
The High Level interface provides methods for transforming coordinates between the input
and the output frames, generating High Level Objects (HLO). HLOs are rich astropy objects,
like SkyCoord, SpectralCoord and StokesCoord, which provide additional functionality.
>>> from gwcs import examples
>>> wcsobj = examples.gwcs_3d_spatial_wave()
>>> result = wcsobj.pixel_to_world(1, 1, 1)
>>> print(result)
[<SkyCoord (ICRS): (ra, dec) in deg
(2., 3.)>, <SpectralCoord 2. m>]
>>> wcsobj.world_to_pixel(*result)
(1.0, 1.0, 1.0)
Two other methods in the High Level Interface, pixel_to_world_values and world_pixel_values
return the numerical results.
Note that there’s an implicit assumption in the names of the methods (pixel_to_world
and world_to_pixel) that the input is in pixels. However, this is only an unfortunate
naming choice. In reality the pixel_to_world method executes the forward_transform transform,
and world_to_pixel evaluates the backward_transform as defined in the WCS object.
It is possible to define the forward transform from sky to detector, in which case the output
of pixel_to_world will be in units of pixels.
The Low Level Interface, provides additional methods which may be useful in WCS introspections. We list some of them using the example WCS above:
>>> wcsobj.pixel_n_dim
3
>>> wcsobj.world_n_dim
3
>>> wcsobj.world_axis_names
('lon', 'lat', 'lambda')
>>> wcsobj.world_axis_physical_types
('pos.eq.ra', 'pos.eq.dec', 'em.wl')
>>> wcsobj.world_axis_units
('deg', 'deg', 'm')
A WCS object may not have a data array attached to it, as it represents a coordinate transformation. However, it is usually read in from a data file and in this case there’s a data array. The Low Level Interface can be used to find out the shape of the array. As discussed in Terminology and Conventions the WCS uses cartesian order of the coordinates, and hence there are two methods for the shape of the data array. Let’s assume a data array of shape (4, 5) is in a file with the WCS object above. The two methods will return respectively:
>>> wcsobj.pixel_shape
(5, 4)
>>> wcsobj.array_shape
(4, 5)
If the WCS object has a bounding_box, it can be accessed by
>>> wcsobj.bounding_box = ((2, 10), (3, 7), (.1, .7))
>>> wcsobj.pixel_bounds
((2, 10), (3, 7), (0.1, 0.7))