We saw in the previous section (§16) how to store and retrieve any kind of AST Object in a FITS header by using a FitsChan. To achieve this, we set the FitsChan’s Encoding attribute to NATIVE. However, the Objects we wrote could then only be read back by other programs that use AST.
In practice, we will also encounter FITS headers containing WCS information written by other software systems. We will probably also need to write FITS headers in a format that can be understood by these systems. Indeed, this interchange of data is one of the main reasons for the existence of FITS, so in this section we will examine how to accommodate these requirements.
As mentioned previously (§16.1), there are a number of conventions currently in use for storing WCS information in FITS headers, which we call encodings. Here, we are concerned with those encodings defined by software systems other than AST, which we term foreign encodings.
Currently, AST supports six foreign encodings, which may be selected by setting the Encoding attribute of a FitsChan to one of the following (character string) values:
However, the calibration model used (based on a polynomial fit) is not easily applicable to other types of data and creating the polynomial coefficients needed to calibrate your own images can prove difficult. For this reason, the DSS encoding is probably best viewed as a “read-only” format. It is possible, however, to read in WCS information using this encoding and then to write it back out again, so long as only minor changes have been made.
The conventions used are described in a series of papers by E.W. Greisen, M. Calabretta, et. al., often referred to as the “FITS-WCS papers”. They are described at http://fits.gsfc.nasa.gov/fits_wcs.html. Now that the first two papers in this series have been agreed, this encoding should be understood by any FITS-WCS compliant software and it is likely to be adopted widely for FITS data in future. For details of the coverage of these conventions provided by the FitsChan class, see Appendix G.
CDELTjkeywords to describe axis rotation and scaling. Versions of AST prior to V1.5 used this scheme for the FITS-WCS encoding. As of V1.5, FITS-WCS uses
CDi_jkeywords instead.27 The FITS-PC encoding is included in AST V1.5 only to allow FITS-WCS data created with previous versions to be read. It should not, in general, be used to create new data sets.
CDELTikeywords to describe axis rotation and scaling.
For more detail about the above encodings, see the description of the Encoding attribute in Appendix C.
The foreign encodings available for storing WCS information in FITS headers have a number of limitations when compared with the native encoding of AST Objects (§16). The main ones are:
The way in which a FrameSet is translated to and from the foreign encoding also follows from this correspondence. The FrameSet’s base Frame identifies the data grid coordinates of the associated FITS data. These are the same as FITS pixel coordinates, in which the first pixel (in 2 dimensions) has coordinates (1,1) at its centre. Similarly, the current Frame of the FrameSet identifies the FITS world coordinate system associated with the data.
This is mainly a consequence of the use of fixed FITS keywords by foreign encodings and the fact that you cannot, in general, have multiple FITS cards with the same keyword.
It should be understood that using foreign encodings to read and write information held in AST Objects is essentially a process of converting the data format. As such, it potentially suffers from the same problems faced by all such processes, i.e. differences between the AST data model and that of the foreign encoding may cause some information to be lost. Because the AST model is extremely flexible, however, any data loss can largely be eliminated when reading. Instead, this effect manifests itself in the form of the above encoding-dependent restrictions on the kind of AST Objects which may be written.
One of the aims of the AST library, of course, is to insulate you from the details of these foreign encodings and the restrictions they impose. We will see shortly, therefore, how AST provides a mechanism for determining whether your WCS information satisfies the necessary conditions and allows you to make an automatic choice of which encoding to use.
Let us now examine the practicalities of extracting WCS information from a set of FITS header cards which have been written by some other software system. We will pretend that our program does not know which encoding has been used for the WCS information and must discover this for itself. In order to have a concrete example, however, we will use the following set of cards. These use the FITS-AIPS encoding and contain a typical mix of other FITS cards which are irrelevant to the WCS information in which we are interested:
The first step is to create a FitsChan and insert these cards into it. If “cards” is an array of pointers to character strings holding the header cards and “ncards” is the number of cards, this could be done as follows:
Note that we have not initialised the Encoding attribute of the FitsChan as we did in §16.3 when we wanted to use the native encoding. This is because we are pretending not to know which encoding to use and want AST to determine this for us. By leaving the Encoding attribute un-set, its default value will adjust to whichever encoding AST considers to be most appropriate, according to the FITS header cards present. For details of how this choice is made, see the description of the Encoding attribute in Appendix C.
This approach has the obvious advantages of making our program simpler and more flexible and of freeing us from having to know about the different encodings available. As a bonus, it also means that the program will be able to read any new encodings that AST may support in future, without needing to be changed.
At this point, we could enquire the default value of the Encoding attribute, which indicates which encoding AST intends to use, as follows:
The result of this enquiry would be the string “FITS-AIPS”. Note that we could also have set the FitsChan’s Encoding attribute explicitly, such as when creating it:
If we tried to read information using this encoding (§17.4), but failed, we could then change the encoding and try again. This would allow our program to take control of how the optimum choice of encoding is arrived at. However, it would also involve using explicit knowledge of the encodings available and this is best avoided if possible.
Having stored a set of FITS header cards in a FitsChan and determined how the WCS information is encoded (§17.3), the next step is to read an AST Object from the FitsChan using astRead. We must also remember to rewind the FitsChan first, if necessary, such as by clearing its Card attribute, which defaults to 1:
If the pointer returned by astRead is not equal to AST__NULL, then an Object has been read successfully. Otherwise, there was either no information to read or the choice of FITS encoding (§17.3) was inappropriate.
At this point you might like to indulge in a little data validation along the lines described in §15.6, for example:
If a foreign encoding has definitely been used, then the Object will automatically be a FrameSet (§17.2), so this stage can be omitted. However, if the native encoding (§16.1) might have been employed, which is a possibility if you accept the FitsChan’s default Encoding value, then any class of Object might have been read and a quick check would be worthwhile.
If you used astShow (§4.4) to examine the FrameSet which results from reading our example FITS header (§17.3), you would find that its base Frame describes the image’s pixel coordinate system and that its current Frame is a SkyFrame representing galactic coordinates. These two Frames are inter-related by a Mapping (actually a CmpMap) which incorporates the effects of various rotations, scalings and a “zenithal equal area” sky projection, so that each pixel of the FITS image is mapped on to a corresponding sky position in galactic coordinates.
Because this FrameSet may be used both as a Mapping (§13.6) and as a Frame (§13.8), it may be employed directly to perform many useful operations without any need to decompose it into its component parts. These include:
If the FrameSet contains other Frames (apart from the base and current Frames), then you would also have access to information about other coordinate systems associated with the image.
It is instructive at this point to examine the contents of a FitsChan after we have read a FrameSet from it (§17.4). The following would rewind our FitsChan and display its contents:
The output, if we started with the example FITS header in §17.3, might look like this:
Comparing this with the original, you can see that all the FITS cards that represent WCS information have been removed. They have effectively been “sucked out” of the FitsChan by the destructive read that astRead performs and converted into an equivalent FrameSet. AST remembers where they were stored, however, so that if we later write WCS information back into the FitsChan (§17.7) they will, as far as possible, go back into their original locations. This helps to preserve the overall layout of the FITS header.
You can now see why astRead performs destructive reads. It is a mechanism for removing WCS information from a FITS header while insulating you, as a programmer, from the details of the encoding being used. It means you can ensure that all relevant header cards have been removed, giving you a clean slate, without having to know which FITS keywords any particular encoding uses.
Clearing this WCS information out of a FITS header is particularly important when considering how to write new WCS information back after processing (§17.7). If any relevant FITS cards are left over from the input dataset and find their way into the new processed header, they could interfere with the new information being written.29 The destructive read mechanism ensures that this doesn’t happen.
One of the purposes of AST is to make it feasible to propagate WCS information through successive stages of data processing, so that it remains consistent with the associated image data. As far as possible, this should happen regardless of the FITS encoding used to store the original WCS information.
If the data processing being performed does not change the relationship between image pixel and world coordinates (whatever these may be), then propagation of the WCS information is straightforward. You can simply copy the FITS header from input to output.
If this relationship changes, however, then the WCS information must be processed alongside the image data and a new FITS header generated to represent it. In this case, the sequence of operations within your program would probably be as follows:
In stage (2), the original WCS information will be removed from the FitsChan by a destructive read. Later, in stage (4), new WCS information is written to replace it. This is the process which we consider next (§17.7).
Before we can write processed WCS information held in a FrameSet back into a FitsChan in preparation for output, we must select the FITS encoding to use. Unfortunately, we cannot simply depend on the default value of the Encoding attribute, as we did when reading the input information (§17.3), because the destructive action of reading the WCS data (§17.5) will have altered the FitsChan’s contents. This, in turn, will have changed the choice of default encoding, probably causing it to revert to NATIVE.
We will return to the question of the optimum choice of encoding below. For now, let’s assume that we want to use the same encoding for output as we used for input. Since we enquired what that was before we read the input WCS data from the FitsChan (§17.3), we can now set that value explicitly. We can also set the FitsChan’s Card attribute back to 1 at the same time (because the write will fail if the FitsChan is not rewound). astWrite can then be used to write the output WCS information into the FitsChan:
The value returned by astWrite (assigned to “nobj”) indicates how many Objects were written. This will either be 1 or zero. A value of zero is used to indicate that the information could not be encoded in the form you requested. If this happens, nothing will have been written.
If your choice of encoding proves inadequate, the probable reason is that the changes you have made to the FrameSet have caused it to depart from the data model which the encoding assumes. AST knows about the data model used by each encoding and will attempt to simplify the FrameSet you provide so as to fit into that model, thus relieving you of the need to understand the details and limitations of each encoding yourself.30 When this attempt fails, however, you must consider what alternative encoding to use.
Ideally, you would probably want to try a sequence of alternative encodings, using an approach such as the following:
An alternative approach might be to encode the WCS information in several ways, since this gives the maximum chance that other software will be able to read it. This approach is only possible if there is no significant conflict between the FITS keywords used by the different encodings31. Adopting this approach would simply require multiple calls to astWrite, rewinding the FitsChan and changing its Encoding value before each one.
Unfortunately, however, there is a drawback to duplicating WCS information in the FITS header in this way, because any program which modifies one version of this information and simply copies the remainder of the header will risk producing two inconsistent sets of information. This could obviously be confusing to subsequent software. Whether you consider this a worthwhile risk probably depends on the use to which you expect your data to be put.
26Available by ftp from fits.cv.nrao.edu /fits/documents/wcs/wcs88.ps.Z
27There are many other differences between the previous and the current FITS-WCS encodings. The keywords to describe axis rotation and scaling is used purely as a label to identify the scheme.
28Available by ftp from fits.cv.nrao.edu /fits/documents/wcs/aips27.ps.Z
29This can happen if a particular keyword is present in the input header but is not used in the output header (whether particular keywords are used can depend on the WCS information being stored). In such a case, the original value would not be over-written by a new output value, so would remain erroneously present.
30Storing values in the FitsChan for FITS headers NAXIS1, NAXIS2, etc. (the grid dimensions in pixels), before invoking astWrite can sometimes help to produce a successful write.
31In practice, this means you should avoid mixing FITS-IRAF, FITS-WCS, FITS-AIPS, FITS-AIPS++ and FITS-PC encodings since they share many keywords.