[AstroPy] API question: Instantiating of time/coord and similar

David Berry d.berry at jach.hawaii.edu
Thu May 3 16:16:13 EDT 2012

On 3 May 2012 19:53, Wolfgang Kerzendorf <wkerzendorf at gmail.com> wrote:
> But AST doesn't handle unit conversion (e.g. from Kelvin to eV)

Glad you raised that, because AST *does* actually take account of
differences in units between two Frames.  See
http://www.starlink.rl.ac.uk/docs/sun210.htx/node81.html .

> which are
> also coordinate transformations, because it has a different focus (namely
> astronomical images and now spectra).

It handles all the units defined in FITS WCS paper II (or is it paper
III ?) including Kelvin and eV, both of which are useful astronomical
units (antenna temperature and spectral energy). As you say, they are
just another form of coordinate system and so follow many of the same
rules as other coordinate systems.

> For now, we have made the
> distinctions: time, celestial coordinates, SI units, world coordinate
> systems for array based data.

What about spectral coordinates? And compound coordinate systems for
spectral cubes, etc?

> That doesn't mean, we don't want them working together: you give a world
> coordinates system a pixel coordinate, it gives back a celestial coordinate
> (with units degrees) which I then can easily convert to galactic
> coordinates. For example
> mycoord = myimage.wcs.pix2world(200,300)
> mycoord.units is in degrees
> mycoord.to_galactic() will return the galactic coordinates.
> As I said it would be easiest to show your implementation on an example:
> One way we plan to do it is:
> mytime = time.from_jd(245423423423)
> mytime.to_utc -> will give back a datetime object
> mycoord = coord.from_equatorial(200, 20)
> mycoord.units  (is degrees).
> mycoord.to_galactic -> gives back a tuple with galactic coordinates in
> degrees
> How would this work in AST (pseudo code).

Don't forget, I agree I have gone well off the original topic, in that
AST is more aimed at people developing application code than at end
users. So what follows is maybe more verbose than a  user would like.

Firstly, I'm not 100% sure what your example is supposed to do. I'm
presuming you have a Julian Date in some unspecified time scale, and
convert it to something (another Julian Date?) in the UTC time scale.
Filling in the missing details,  to convert a Julian Date in (say) the
TT (Terrestrial Time) time scale to (say) an MJD in UTC time scale, it
would be like this:

frame_1 = new timeframe( system=JD, timescale=TT )
frame_2 = new timeframe( system=MJD, timescale=UTC )
mapping = frame_1.convert_to( frame_2 )
mjd = mapping.transform( 245423423423 )

So, create Frames (TimeFrames in this case) describing the two
coordinate systems, then get a Mapping that describes how to convert
between them, then use this mapping to transform the required axis
values. In this simple example, you may then delete the objects. But
in more complex cases, you would probably want to keep them around to
use for other purposes. TimeFrame has lots of other properties in
addition to System and Timescale, like units (days, year, seconds,
whatever), zero-points, local-time offset, etc. You can set as many of
these as you like when creating the TimeFrames (any unspecified
properties take default values), and the "convert_to" method will take
them all into account when working out the returned mapping. The
beauty is that the "convert_to" method is applicable to all classes of
Frame, and so is generic.

Your second example takes an (RA,Dec) position and converts to a
galactic position. The AST equivalent is basically the same as above,
here I've added some other properties for illustration like the
reference frame and equinox for the (RA,Dec):

frame_1 = new skyframe( system=FK4, equinox=1950, epoch=1967.34)
frame_2 = new skyframe( system=galactic )
mapping = frame_1.convert_to( frame_2 )
(l,b) = mapping.transform( 200, 20 )

Strictly, the "epoch" value could be omitted since it defaults to 1950
for FK4. AST supports sky coord in AZEL, ICRS, FK4 (with or without
E-terms), FK5, Galactic, super-galactic, Ecliptic, HelioEcliptic and
Geocentric apparent. All knowledge of these coordinate systems is
encapsulated in the one class "SkyFrame". Update your skyframe class
to support a new coordinate system, and - hey-presto - all your
application code supports the new system.

The same thing can be done for spectral coordinates in any common
system (wavelength, frequency, radio velocity, optical velocity,
energy, etc), in any common rest frame, in any common units (automatic
unit conversion is supported as I mentioned above). It even handles
dual-sideband spectral coordinate systems (i.e. two interrelated
spectral systems).

And it can be done for any combination of the above types of coordinates.

Another little nicety is that each sub-class of Frame knows how to
format axis values in a way that makes sense to the user. So for
instance, you could take the (ra,dec) values and convert them into
"h:m:s"/"d:m:s" format   for display as follows:

hms_string = frame_1.format( 200, axis=1 )
dms_string = frame_1.format( 20, axis=2 )

Similarly, the implementation of the Format method provided by the
TimeFrame class can format a numerical time value as a calendar date

And here's a trick. Say you read WCS from two FITS files and want to
find the pixel coords in the second FITS file that has the same
position on the sky as pixel (100,230) in the first FITS file (i.e.
align the FITS files on the sky):

frameset_1 = fits1.read_wcs()
frameset_2 = fits2.read_wcs()
mapping = frameset_1.convert_to( frameset_2 )
(px,py) = mapping.transform( 100, 230 )

Notice it's the same basic pattern as before - create objects
describing your coordinate systems, use the convert_to method to get a
mapping between them, then use the mapping to convert axis values. In
this case we use two FrameSets rather than two SkyFrames or
TimeFrames. A FrameSet is a collection of Frames connected together by
mappings, and includes a "pixel Frame" and all the WCS Frames included
in the FITS file, with appropriate mappings between them. The
convert_to method then searches the two FrameSets for any frames that
can be interrelated (like two SkyFrames or two TimeFrames etc), and
works out the total mapping from input pixel coords to output pixel
coord (this is a bit simplified - there are ways of controlling
exactly how the convert_to method aligns the two FrameSets).

But you see that handling WCS is the same basic pattern as for single

Hope this is not too long-winded or unclear!


More information about the AstroPy mailing list