diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-11-02 19:11:06 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-11-02 19:11:06 (GMT) |
commit | 33c55bd916dff8c4932b01c7db58f0103ac31c31 (patch) | |
tree | a4cdca3287dd2df5247ce8079c424ffa438b4c2e /ast/sun_master.tex | |
parent | 4121637f3d41d6dc23e6543a445b5a3aed9e6ddc (diff) | |
download | blt-33c55bd916dff8c4932b01c7db58f0103ac31c31.zip blt-33c55bd916dff8c4932b01c7db58f0103ac31c31.tar.gz blt-33c55bd916dff8c4932b01c7db58f0103ac31c31.tar.bz2 |
update ast
Diffstat (limited to 'ast/sun_master.tex')
-rw-r--r-- | ast/sun_master.tex | 21676 |
1 files changed, 0 insertions, 21676 deletions
diff --git a/ast/sun_master.tex b/ast/sun_master.tex deleted file mode 100644 index bcb55c8..0000000 --- a/ast/sun_master.tex +++ /dev/null @@ -1,21676 +0,0 @@ -\documentclass[twoside,11pt]{starlink} - -% ? Specify used packages -% ? End of specify used packages - -% ----------------------------------------------------------------------------- -% ? Document identification -% Fixed part -\stardoccategory {Starlink User Note} -\stardocinitials {SUN} -\stardocsource {sun\stardocnumber} - -% Variable part - replace [xxx] as appropriate. -c+ -\stardocnumber {211.27} -c- -f+ -\stardocnumber {210.27} -f- -\stardocauthors {R.F. Warren-Smith \& D.S. Berry} -\stardocdate {25th February 2013} -\stardoctitle {AST\linebreak% - A Library for Handling\linebreak% - World Coordinate Systems\linebreak% - in Astronomy} -\stardoccopyright {Copyright (C) 2014 Science \& Technology Facilities Council} -\stardocversion {V<VERSION_NUMBER>} -c+ -\stardocmanual {Programmer's Guide\\(C Version)} -\startitlepic{ - \includegraphics[width=0.25\textwidth]{sun211_figures/fronta}~~~~~\hfill - \includegraphics[width=0.25\textwidth]{sun211_figures/frontb}~~~~~\hfill - \includegraphics[width=0.25\textwidth]{sun211_figures/frontc} -} -c- -f+ -\stardocmanual {Programmer's Guide\\(Fortran Version)} -\startitlepic{ - \includegraphics[width=0.25\textwidth]{sun210_figures/fronta}~~~~~\hfill - \includegraphics[width=0.25\textwidth]{sun210_figures/frontb}~~~~~\hfill - \includegraphics[width=0.25\textwidth]{sun210_figures/frontc} -} -f- -\stardocabstract { -The AST library provides a comprehensive range of facilities for -attaching world coordinate systems to astronomical data, for -retrieving and interpreting that information in a variety of formats, -including FITS-WCS, and for generating graphical output based on it. - -This programmer's manual should be of interest to anyone writing -astronomical applications which need to manipulate coordinate system -data, especially celestial or spectral coordinate systems. AST is portable and -environment-independent. -} -% ? End of document identification -% ----------------------------------------------------------------------------- -% ? Document specific \providecommand or \newenvironment commands. - -\providecommand{\appref}[1]{Appendix~\ref{#1}} -\providecommand{\secref}[1]{\S\ref{#1}} - -\providecommand{\fitskey}[3]{{#1}&{#2}&{#3}\\} - -% Use {\tt ... } as \texttt{...} does not work if there are new lines in #1 -\providecommand{\sstsynopsis}[1]{\sstdiytopic{Synopsis}{\tt #1}} - -% Format the constructor section. -\providecommand{\sstconstructor}[1]{\sstdiytopic{Constructor Function}{#1}} - -% ? End of document specific commands -% ----------------------------------------------------------------------------- -% Title Page. -% =========== -\begin{document} -\scfrontmatter - -\begin{center} -c+ -\emph{This is the C version of this document.\\ - For the Fortran version, please see \xref{SUN/210}{sun210}{}.} -c- -f+ -\emph{This is the Fortran version of this document.\\ - For the C version, please see \xref{SUN/211}{sun211}{}.} -f- -\end{center} - -% Main text of document. -\vspace{7mm} -\section{Introduction} - -Welcome to the AST library. If you are writing software for astronomy -and need to use celestial coordinates (\emph{e.g.}\ RA and Dec), spectral -coordinates (\emph{e.g.}\ wavelength, frequency, \emph{etc.}), or -other coordinate system information, then this library should be of -interest. It provides solutions for most of the problems you will meet -and allows you to write robust and flexible software. It is able to read -and write WCS information in a variety of formats, including -\htmladdnormallink{FITS-WCS}{http://fits.gsfc.nasa.gov/fits_wcs.html}. - -%\subsection{TBW---What is a World Coordinate System?} - -\subsection{What Problems Does AST Tackle?} - -Here are some of the main problems you may face when handling world -coordinate system (WCS) information and the solutions that AST -provides: - -\begin{description} -\item[1. The Variety of Coordinate Systems]\mbox{}\\ -Astronomers use a wide range of differing coordinate systems to describe -positions within a variety of physical domains. For instance, there are a -large number of celestial coordinate systems in use within astronomy to -describe positions on the sky. Understanding these, and knowing how to -convert coordinates between them, can require considerable expertise. It -can also be difficult to decide which of them your software should support. -The same applies to coordinate systems describing other domains, such as -position within an electro-magnetic spectrum. - -\textbf{Solution.} AST has built-in knowledge of many coordinate systems -and allows you to convert freely between them without specialist -knowledge. This avoids the need to embed details of specific -coordinate systems in your software. You also benefit automatically -when new coordinate systems are added to AST. - -\item[2. Storing and Retrieving WCS Information]\mbox{}\\ -Storing coordinate system information in astronomical datasets and -retrieving it later can present a considerable challenge. Typically, -it requires knowledge of rather complex conventions -(\emph{e.g.}\ FITS) which are low-level, often mis-interpreted and may -be subject to change. Exchanging information with other software -systems is further complicated by the number of different conventions -in use. - -\textbf{Solution.} AST combines a unifying high-level description of WCS -information with the ability to save and restore this using a variety -of formats. Details of the formats, which include FITS, are handled -internally by AST. This frees you from the need to understand them or -embed the details in your software. Again, you benefit automatically -when new formats are added to AST. - -\item[3. Generating Graphical Output]\mbox{}\\ -Producing graphical displays involving curvilinear coordinate systems, -such as celestial coordinate grids, can be complicated. Particular -difficulties arise when handling large areas of sky, the polar regions -and discontinuous (\emph{e.g.}\ segmented) sky projections. Even just -numbering and labelling curvilinear axes is rarely straightforward. - -\textbf{Solution.} AST provides plotting facilities especially designed -for use with curvilinear coordinate systems. These include the -plotting of axes and complete labelled coordinate grids. A large -number of options are provided for tailoring the output to your -specific needs. Three dimensional coordinate grids can also be produced. - -\item[4. Aligning Data from Different Sources]\mbox{}\\ -One of the main uses of coordinate systems is to facilitate the -inter-comparison of data from different sources. A typical use might -be to plot (say) radio contours over an optical image. In practice, -however, different celestial coordinate systems may have been used, -making accurate alignment far from simple. - -\textbf{Solution} AST provides a one-step method of aligning datasets, -searching for all possible intermediate coordinate systems. This -makes it simple to directly inter-relate the pixel coordinates of -different datasets. - -\item[5. Handling Different Types of Coordinate System]\mbox{}\\ -Not all coordinate systems used in astronomy are celestial ones, so if -you are writing general-purpose software such as (say) a display tool, -you may also need to handle axes representing wavelength, distance, -time or whatever else comes along. Obviously, you would prefer not to -handle each one as a special case. - -\textbf{Solution} AST uses the same flexible high-level model to -describe all types of coordinate system. This allows you to write -software that handles different kinds of coordinate axis without -introducing special cases. -\end{description} - -\subsection{Other Design Objectives} - -As well as its scientific objectives, the AST library's design -includes a number of technical criteria intended to make it applicable -to as wide a range of projects as possible. The main considerations -are described here: - -\begin{enumerate} -\item {\bf{Minimum Software Dependencies.}} -The AST library depends on no other other software\footnote{It comes with -bundled copies of the ERFA and -\xref{Starlink PAL libraries}{sun268}{} which are built -at the same time as the other AST internal libraries. Alternatively, external -PAL and ERFA libraries may be used by specifying the ``\texttt{--with-external\_pal}'' option when configuring AST}. - -\item {\bf{Environment Independence.}} -AST is designed so that it can operate in a variety of ``programming -environments'' and is not tied to any particular one. To allow this, -it uses simple, flexible interfaces to obtain the following services: - -\begin{itemize} -\item {\bf{Data Storage.}} Data I/O operations are based on text -and/or FITS headers. This makes it easy to interface to a wide variety -of astronomical data formats in a machine-independent way. - -\item {\bf{Graphics.}} Graphical output is produced \emph{via} a -simple generic graphics interface, which may easily be re-implemented -over different graphics systems. AST provides a default implementation -based on the widely-used PGPLOT graphics system -(\xref{SUN/15}{sun15}{}). - -\item {\bf{Error Handling.}} Error messages are written to standard -error by default, but go through a simple generic interface similar to -that used for graphics (above). This permits error message delivery -\emph{via} other routes when necessary (\emph{e.g.} in a graphical -interface). -\end{itemize} - -\item {\bf{Multiple Language Support.}} -AST has been designed to be called from more than one language. -c+ -Both C and Fortran interfaces are available (see -\xref{SUN/210}{sun210}{} for the Fortran version) -c- -f+ -Both Fortran and C interfaces are available (see -\xref{SUN/211}{sun211}{} for the C version) -f- -and use from C$++$ is also straightforward if the C interface is -included using: - -\begin{small} -\begin{terminalv} -extern "C" { -#include "ast.h" -} -\end{terminalv} -\end{small} - -A JNI interface (known as ``JNIAST'' - see -\url{http://www.starlink.ac.uk/jniast/}) has also been developed by Starlink -which allows AST to be used from Java. - -\item {\bf{Object Oriented Design.}} -AST uses ``object oriented'' techniques internally in order to provide -a flexible and easily-extended programming model. A fairly -traditional calling interface is provided, however, so that the -library's facilities are easily accessible to programmers using -c+ -C and Fortran. -c- -f+ -Fortran and C. -f- - -\item {\bf{Portability.}} -AST is implemented entirely in ANSI standard C and, when called -\emph{via} its C interface, makes no explicit use of any -machine-dependent facilities. - -The Fortran interface is, unavoidably, machine dependent. However, the -potential for problems has been minimised by encapsulating the -interface layer in a compact set of C macros which facilitate its -transfer to other platforms. No Fortran compiler is needed to build -the library. - -Currently, AST is supported by Starlink on PC~Linux, Sun~Solaris and -Tru64~Unix (formerly DEC~UNIX) platforms. -\end{enumerate} - -\subsection{What Does ``AST'' Stand For?} - -The library name ``AST'' stands for ``ASTrometry Library''. The name -arose when it was thought that knowledge of ``astrometry'' -(\emph{i.e.}\ celestial coordinate systems) would form the bulk of the -library. In fact, it turns out that astrometry forms only a minor -component, but the name AST has stuck. - -\cleardoublepage -\section{Overview of AST Concepts} - -This section presents a brief overview of AST concepts. It is intended -as a basic orientation course before you move on to the more technical -considerations in subsequent sections. - -\subsection{\label{ss:mappingoverview}Relationships Between Coordinate Systems} - -The relationships between coordinate systems are represented in AST by -Objects called Mappings. A Mapping does not represent a coordinate -system itself, but merely the process by which you move from one -coordinate system to another related one. - - A convenient picture of a Mapping is as a ``black box'' - (Figure~\ref{fig:mapping}) into which you can feed sets of - coordinates. - \begin{figure}[bhtp] - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/mapping} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/mapping} -f- - \caption{A Mapping viewed as a ``black box'' for transforming coordinates.} - \label{fig:mapping} - \end{center} - \end{figure} - -For each set you feed in, the Mapping returns a corresponding set of -transformed coordinates. Since each set of coordinates represents a -point in a coordinate space, the Mapping acts to inter-relate -corresponding positions in the two spaces, although what these spaces -represent is unspecified. Notice that a Mapping need not have the -same number of input and output coordinates. That is, the two -coordinate spaces which it inter-relates need not have the same number -of dimensions. - -In many cases, the transformation can, in principle, be performed in -either direction: either from the \emph{input} coordinate space to the -\emph{output}, or \emph{vice versa}. The first of these is termed the -\emph{forward} transformation and the other the \emph{inverse} -transformation. - - -\textbf{Further reading:} For a more complete discussion of Mappings, -see~\secref{ss:mappings}. - -\subsection{\label{ss:mappingselection}Mappings Available} - -The basic concept of a Mapping (\secref{ss:mappingoverview}) is rather -generic and obviously it is necessary to have specific Mappings that -implement specific relationships between coordinate systems. AST -provides a range of these, to perform transformations such as the -following and, where appropriate, their inverses: - -\begin{itemize} -\item Conversions between various celestial coordinate systems (the -SlaMap). - -\item Conversions between various spectral coordinate systems (the -SpecMap and GrismMap). - -\item Conversions between various time systems (the TimeMap). - -\item Conversion between 2-dimensional spherical celestial coordinates -(longitude and latitude) and a 3-dimensional vectorial positions (the SphMap). - -\item Various projections of the celestial sphere on to 2-dimensional -coordinate spaces---\emph{i.e.}\ map projections (the DssMap and WcsMap). - -\item Permutation, introduction and elimination of coordinates (the -PermMap). - -\item Various linear coordinate transformations (the MatrixMap, WinMap, -ShiftMap and ZoomMap). - -\item General N-dimensional polynomial transformations (the PolyMap). - -\item Lookup tables (the LutMap). - -c+ -\item General-purpose transformations expressed using arithmetic -operations and functions similar to those available in C (the -MathMap). -c- -f+ -\item General-purpose transformations expressed using arithmetic -operations and functions similar to those available in Fortran (the -MathMap). -f- - -c+ -\item Transformations for internal use within a program, based on -private transformation functions which you write yourself in C (the -IntraMap). -c- -f+ -\item Transformations for internal use within a program, based on -private transformation routines which you write yourself in Fortran -(the IntraMap). -f- -\end{itemize} - -\textbf{Further reading:} For a more complete description of each of the -Mappings mentioned above, see its entry in -\appref{ss:classdescriptions}. In addition, see the discussion of the -PermMap in \secref{ss:permmapexample}, the UnitMap in -\secref{ss:unitmapexample} and the IntraMap in -\secref{ss:intramaps}. The ZoomMap is used as an example throughout -\secref{ss:primer}. - -\subsection{\label{ss:cmpmapoverview}Compound Mappings} - -The Mappings described in \secref{ss:mappingselection} provide a set -of basic building blocks from which more complex Mappings may be -constructed. The key to doing this is a type of Mapping called a -CmpMap, or compound Mapping. A CmpMap's role is, in principle, very -simple: it allows any other pair of Mappings to be joined together -into a single entity which behaves as if it were a single Mapping. A -CmpMap is therefore a container for another pair of Mappings. - - A pair of Mappings may be combined using a CmpMap in either of two - ways. The first of these, \emph{in series}, is illustrated in - Figure~\ref{fig:seriescmpmap}. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/series} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/series} -f- - \caption[A CmpMap composed of two component Mappings joined in series]{A CmpMap (compound Mapping) composed of two component - Mappings joined in series. The output coordinates of the first Mapping - feed into the input coordinates of the second one, so that the whole - entity behaves like a single Mapping.} - \label{fig:seriescmpmap} - \end{center} - \end{figure} - - - Here, the transformations implemented by each component Mapping are - performed one after the other, with the output from the first Mapping - feeding into the second. The second way, \emph{in parallel}, is shown in - Figure~\ref{fig:parallelcmpmap}. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.5\textwidth]{sun211_figures/parallel} -c- -f+ - \includegraphics[width=0.5\textwidth]{sun210_figures/parallel} -f- - \caption[A CmpMap composed of two Mappings joined in parallel.]{A CmpMap composed of two Mappings joined in parallel. Each - component Mapping acts on a complementary subset of the input and - output coordinates.} - \label{fig:parallelcmpmap} - \end{center} - \end{figure} - -In this case, each Mapping acts on a complementary subset of the -input and output coordinates.\footnote{A pair of Mappings can be combined -in a third way using a TranMap. A TranMap allows the forward -transformation of one Mapping to be combined with the inverse -transformation of another to produce a single Mapping.} - - The CmpMap forms the key to building arbitrarily complex Mappings - because it is itself a form of Mapping. This means that a CmpMap may - contain other CmpMaps as components - (\emph{e.g.}\ Figure~\ref{fig:complexcmpmap}). This nesting of CmpMaps - can be repeated indefinitely, so that complex Mappings may be built in - a hierarchical manner out of simper ones. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.65\textwidth]{sun211_figures/complex} -c- -f+ - \includegraphics[width=0.65\textwidth]{sun210_figures/complex} -f- - \caption[CmpMaps may be nested in order to - construct complex Mappings out of simpler building blocks.]{CmpMaps - (compound Mappings) may be nested in order to - construct complex Mappings out of simpler building blocks.} - \label{fig:complexcmpmap} - \end{center} - \end{figure} - This gives AST great flexibility in the coordinate transformations it - can describe. - -\textbf{Further reading:} For a more complete description of CmpMaps, -see \secref{ss:cmpmaps}. Also see the CmpMap entry in -\appref{ss:classdescriptions}. - -\subsection{Representing Coordinate Systems} - - While Mappings (\secref{ss:mappingoverview}) represent the - relationships between coordinate systems in AST, the coordinate - systems themselves are represented by Objects called Frames - (Figure~\ref{fig:frames}). - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.55\textwidth]{sun211_figures/frames} -c- -f+ - \includegraphics[width=0.55\textwidth]{sun210_figures/frames} -f- - \caption[Representing coordinate systems as Frames.]{(a) A basic Frame is used to represent a Cartesian coordinate - system, here 2-dimensional. (b) A SkyFrame represents a (spherical) - celestial coordinate system. (c) The axis order of any Frame may be - permuted to match the coordinate space it describes.} - \label{fig:frames} - \end{center} - \end{figure} - -A Frame is similar in concept to the frame you might draw around a -graph. It contains information about the labels which appear on the -axes, the axis units, a title, knowledge of how to format the -coordinate values on each axis, \emph{etc.} An AST Frame is not, -however, restricted to two dimensions and may have any number of axes. - -c+ -A basic Frame may be used to represent a Cartesian coordinate system -by setting values for its \emph{attributes} (all AST Objects have -values associated with them called attributes, which may be set and -enquired). Usually, this would involve setting appropriate axis -labels and units, for example. Functions are provided for use with -Frames to perform operations such as formatting coordinate values as -text, calculating distances between points, interchanging axes, -\emph{etc.} -c- -f+ -A basic Frame may be used to represent a Cartesian coordinate system -by setting values for its \emph{attributes} (all AST Objects have -values associated with them called attributes, which may be set and -enquired). Usually, this would involve setting appropriate axis -labels and units, for example. Routines are provided for use with -Frames to perform operations such as formatting coordinate values as -text, calculating distances between points, interchanging axes, -\emph{etc.} -f- - -There are several more specialised forms of Frame, which provide the -additional functionality required when handling coordinates within some -specific physical domain. This ranges from tasks such as formatting axis -values, to complex tasks such as determining the transformation between -any pair of related coordinate systems. For instance, the SkyFrame -(Figure~\ref{fig:frames}b,c), represents celestial coordinate systems, -the SpecFrame represents spectral coordinate systems, and the TimeFrame -represents time coordinate systems. All these provide a wide range of -different systems for describing positions within their associated physical -domain, and these may be selected by setting appropriate attributes. - - As with compound Mappings (\secref{ss:cmpmapoverview}), it is possible - to merge two Frames together to form a compound Frame, or CmpFrame, in - which both sets of axes are combined. One could, for example, have - celestial coordinates on two axes and an unrelated coordinate - (wavelength, perhaps) on a third (Figure~\ref{fig:cmpframe}). - Knowledge of the relationships between the axes is preserved - internally by the process of constructing the CmpFrame which - represents them. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.4\textwidth]{sun211_figures/cmpframe} -c- -f+ - \includegraphics[width=0.4\textwidth]{sun210_figures/cmpframe} -f- - \caption[A CmpFrame (compound Frame) formed by combining two simpler - Frames.]{A CmpFrame (compound Frame) formed by combining two simpler - Frames. Note how the special relationship which exists between the RA - and Dec axes is preserved within this data structure. As with compound - Mappings (Figure~\ref{fig:complexcmpmap}), CmpFrames may be nested in - order to build more complex Frames.} - \label{fig:cmpframe} - \end{center} - \end{figure} - -\textbf{Further reading:} For a more complete description of Frames see -\secref{ss:frames}, for SkyFrames see \secref{ss:skyframes} and for -SpecFrames see \secref{ss:specframes}. Also see the Frame, SkyFrame, -SpecFrame, TimeFrame and CmpFrame entries in \appref{ss:classdescriptions}. - -\subsection{Networks of Coordinate Systems} - - Mappings and Frames may be connected together to form networks called - FrameSets, which are used to represent sets of inter-related - coordinate systems (Figure~\ref{fig:frameset}). - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.65\textwidth]{sun211_figures/frameset} -c- -f+ - \includegraphics[width=0.65\textwidth]{sun210_figures/frameset} -f- - \caption[A FrameSet is a network of Frames.]{A FrameSet is a network of Frames inter-connected by Mappings - such that there is exactly one conversion path, \emph{via} Mappings, - between any pair of Frames.} - \label{fig:frameset} - \end{center} - \end{figure} - - -A FrameSet may be extended by adding a new Frame to it, together with -an associated Mapping which relates the new coordinate system to one -which is already present. This process ensures that there is always -exactly one path, \emph{via} Mappings, between any pair of Frames. A -function is provided for identifying this path and returning the -complete Mapping. - -One of the Frames in a FrameSet is termed its \emph{base} Frame. This -underlies the FrameSet's purpose, which is to calibrate datasets and -other entities by attaching coordinate systems to them. In this -context, the base Frame represents the ``native'' coordinate system -(for example, the pixel coordinates of an image). Similarly, one -Frame is termed the \emph{current} Frame and represents the -``currently-selected'' coordinates. It might, typically, be a -celestial or spectral coordinate system and would be used during -interactions with -a user, as when plotting axes on a graph or producing a table of -results. Other Frames within the FrameSet represent a library of -alternative coordinate systems which a software user can select by -making them current. - -\textbf{Further reading:} For a more complete description of -FrameSets, see \secref{ss:framesets} and \secref{ss:fshigher}. Also -see the FrameSet entry in \appref{ss:classdescriptions}. - -\subsection{Input/Output Facilities} - -AST allows you to convert any kind of Object into a stream of text -which contains a full description of that Object. This text may be -written out by one program and read back in by another, thus allowing -the original Object to be reconstructed. - -The filter which converts Objects into text and back again is itself a -kind of Object, called a Channel. A Channel provides a number of -options for controlling the information content of the text, such as -the addition of comments for human interpretation. It is also -possible to intercept the text being processed by a Channel so that it -may be redirected to/from any chosen external data store, such as a -text file, an astronomical dataset, or a network connection. - -The text format used by the basic Channel class is peculiar to the AST -library - no other software will understand it. However, more specialised -forms of Channel are provided which use text formats more widely -understood. - -To further facilitate the storage of coordinate system information in -astronomical datasets, a more specialised form of Channel called a -FitsChan is provided. Instead of using free-format text, a FitsChan -converts AST Objects to and from FITS header cards. It also allows the -information to be encoded in the FITS cards in a number of ways -(called \emph{encodings}), so that WCS information from a variety of -sources can be handled. - -Another sub-class of Channel, called XmlChan, is a specialised form of -Channel that stores the text in the form of XML markup. Currently, two -markup formats are provided by the XmlChan class, one is closely related -to the text format produced by the basic Channel class (currently, no -schema or DTD is available describing this format). The other is a subset -of an early draft of the IVOA Space-Time-Coordinates XML (STC-X) schema -(V1.20) described at -\url{http://www.ivoa.net/Documents/WD/STC/STC-20050225.html -}\footnote{XML documents which use only the subset of the STC schema -supported by AST can be read by the XmlChan class to produce -corresponding AST objects (subclasses of the Stc class). However, the -reverse is not possible. That is, AST objects can not currently be -written out in the form of STC documents.}. The version of STC-X that has -been adopted by the IVOA differs in several significant respects from -V1.20, and therefore this XmlChan format is of historical interest only. - -Finally, the StcsChan class provides facilities for reading and writing -IVOA STC-S region descriptions. STC-S (see -\url{http://www.ivoa.net/Documents/latest/STC-S.html}) is a linear string -syntax that allows simple specification of STC metadata. AST supports a -subset of the STC-S specification, allowing an STC-S description of a -region within an AST-supported astronomical coordinate system to be converted -into an equivalent AST Region object, and vice-versa. - -\textbf{Further reading:} For a more complete description of Channels -see \secref{ss:channels} and for FitsChans see \secref{ss:nativefits} -and \secref{ss:foreignfits}. Also see the Channel and FitsChan entries -in \appref{ss:classdescriptions} and the Encoding entry in -\appref{ss:attributedescriptions}. - -\subsection{Producing Graphical Output} - -Two dimensional graphical output is supported by a specialised form of -FrameSet called -a Plot, whose base Frame corresponds with the native coordinates of -the underlying graphics system. Plotting operations are specified in -\emph{physical coordinates} which correspond with the Plot's current -Frame. Typically, this might be a celestial coordinate system. - -Three dimensional plotting is also supported, via the Plot3D class - -sub-class of Plot. - -Operations, such as drawing lines, are automatically transformed from -physical to graphical coordinates before plotting, using an adaptive -algorithm which ensures smooth curves (because the transformation is -usually non-linear). ``Missing'' coordinates (\emph{e.g.}\ graphical -coordinates which do not project on to the celestial sphere), -discontinuities and generalised clipping are all consistently handled. -It is possible, for example, to plot in equatorial coordinates and -clip in galactic coordinates. The usual plotting operations are -provided (text, markers), but a geodesic curve replaces the primitive -straight line element. There is also a separate function for drawing -axis lines, since these are normally not geodesics. - -In addition to drawing coordinate grids over an area of the sky, another -common use of the Plot class is to produce line plots such as flux -against wavelength, displacement again time, \emph{etc}. For these -situations the current Frame of the Plot would be a compound Frame -(CmpFrame) containing a pair of 1-dimensional Frames - the first -representing the X axis quantity (wavelength, time, etc), and the second -representing the Y axis quantity (flux, displacement, etc). The Plot -class includes an option for axes to be plotted logarithmically. - - Perhaps the most useful graphics function available is for drawing - fully annotated coordinate grids (\emph{e.g.}\ Figure~\ref{fig:gridplot}). - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.6\textwidth]{sun211_figures/gridplot_bw} -c- -f+ - \includegraphics[width=0.6\textwidth]{sun210_figures/gridplot_bw} -f- - \caption[A labelled coordinate grid for an all-sky zenithal equal area - projection in ecliptic coordinates.]{A labelled coordinate grid for an all-sky zenithal equal area - projection in ecliptic coordinates. This was composed and drawn - \emph{via} a Plot using a -c+ - single function call.} -c- -f+ - single subroutine call.} -f- - \label{fig:gridplot} - \end{center} - \end{figure} - -This uses a general algorithm which does not depend on knowledge of -the coordinates being represented, so can also handle -programmer-defined coordinate systems. Grids for all-sky projections, -including polar regions, can be drawn and most aspects of the output -(colour, line style, \emph{etc.}) can be adjusted by setting -appropriate Plot attributes. - -\textbf{Further reading:} For a more complete description of -Plots and how to produce graphical output, see \secref{ss:plots}. Also -see the Plot entry in \appref{ss:classdescriptions}. - -\cleardoublepage -\section{\label{ss:howto}How To\ldots} - -For those of you with a plane to catch, this section provides some -instant templates and recipes for performing the most -commonly-required operations using AST, but without going into -detail. The examples given (sort of) follow on from each other, so you -should be able to construct a variety of programs by piecing them -together. Note that some of them appear longer than they actually -are, because we have included plenty of comments and a few options -that you probably won't need. - -If any of this material has you completely baffled, then you may want -to read the introduction to AST programming concepts in -\secref{ss:primer} first. Otherwise, references to more detailed -reading are given after each example, just in case they don't quite do -what you want. - -\subsection{\ldots Obtain and Install AST} -The AST library is available both as a stand-alone package and also as -part of the Starlink Software Collection\footnote{The Starlink Software -Collection can be downloaded from -\url{http://www.starlink.ac.uk/Download/}.}. If your site has the Starlink -Software Collection installed then AST should already be available. - -If not, you can download the AST library by itself from -\url{http://www.starlink.ac.uk/ast/}. - -\subsection{\ldots Structure an AST Program} - -An AST program normally has the following structure: - -c+ -\begin{small} -\begin{terminalv} -/* Include the interface to the AST library. */ -#include "ast.h" - -/* Main program (or could be any function). */ -main () { - <normal C declarations and statements> - -/* Enclose the parts which use AST between the astBegin and astEnd macros. */ - astBegin; - <C statements which use AST> - astEnd; - - <maybe more C statements> -} -\end{terminalv} -\end{small} -c- -f+ -\small -\begin{terminalv} -* Include the interface to the AST library. - INCLUDE 'AST_PAR' - -* Declare an integer status variable. - INTEGER STATUS - <maybe other declarations> - -* Initialise the status to zero. - STATUS = 0 - <maybe some Fortran statements> - -* Enclose the parts which use AST between AST_BEGIN and AST_END calls. - CALL AST_BEGIN( STATUS ) - <Fortran statements which use AST> - CALL AST_END( STATUS ) - - <maybe more Fortran statements> - END -\end{terminalv} -\normalsize -f- - -c+ -The use of astBegin and astEnd is optional, but has the effect of -tidying up after you have finished using AST, so is normally -recommended. For more details of this, see \secref{ss:contexts}. For -details of how to access the ``ast.h'' header file, see -\secref{ss:accessingheaderfile}. -c- -f+ -The use of AST\_BEGIN and AST\_END is optional, but has the effect of -tidying up after you have finished using AST, so is normally -recommended. For more details of this, see \secref{ss:contexts}. For -details of how to access the AST\_PAR include file, see -\secref{ss:accessingheaderfile}. -f- - -\subsection{\label{ss:howtobuild}\ldots Build an AST Program} - -To build a simple AST program that doesn't use graphics, use: - -c+ -\begin{small} -\begin{terminalv} -cc program.c -L/star/lib -I/star/include `ast_link` -o program -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} -f77 program.f -L/star/lib -I/star/include `ast_link` -o program -\end{terminalv} -\end{small} - -On Linux systems you should usually use \verb+g77 -fno-second-underscore+ in -place of \verb+f77+ - see \xref{``Software development on Linux''}{sun212} -{software_development_on_linux} in \xref{SUN/212}{sun212}{}. -f- - -To build a program which uses PGPLOT for graphics, use: - -c+ -\begin{small} -\begin{terminalv} -cc program.c -L/star/lib `ast_link -pgplot` -o program -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} -f77 program.f -L/star/lib `ast_link -pgplot` -o program -\end{terminalv} -\end{small} - -again using \verb+g77 -fno-second-underscore+ in place of \verb+f77+ -on Linux systems. -f- - -c+ -For more details about accessing the ``ast.h'' header file, see -\secref{ss:accessingheaderfile}. For more -details about linking programs, see \secref{ss:linking} and the -description of the ``ast\_link'' command in -\appref{ss:commanddescriptions}. -c- -f+ -For more details about accessing AST include files, see -\secref{ss:accessingheaderfile}. For more -details about linking programs, see \secref{ss:linking} and the -description of the ``ast\_link'' command in -\appref{ss:commanddescriptions}. -f- - -\subsection{\label{ss:howtoreadwcs}\ldots Read a WCS Calibration from a Dataset} - -c+ -Precisely how you extract world coordinate system (WCS) information -from a dataset obviously depends on what type of dataset it -is. Usually, however, you should be able to obtain a set of FITS -header cards which contain the WCS information (and probably much more -besides). Suppose that ``cards'' is a pointer to a string -containing a complete set of concatenated FITS header cards (such as -produced by the CFITSIO function fits\_hdr2str). Then proceed as follows: - -\begin{small} -\begin{terminalv} -fitsfile *fptr; -AstFitsChan *fitschan; -AstFrameSet *wcsinfo; -char *header; -int nkeys, status; - -... - -/* Obtain all the cards in the header concatenated into a single dynamically - allocated null-terminated character string. Note, we do not exclude - any cards since we may later modify the WCS information within the - header and consequently want to write the entire header out again. */ - if( fits_hdr2str( fptr, 0, NULL, 0, &header, &nkeys, &status ) ) - printf(" Error getting header\n"); - ... - -/* Header obtained succesfully... */ - } else { - -/* Create a FitsChan and fill it with FITS header cards. */ - fitschan = astFitsChan( NULL, NULL, "" ); - astPutCards( fitschan, header ); - -/* Free the memory holding the concatenated header cards. */ - header = free( header ); - -/* Read WCS information from the FitsChan. */ - wcsinfo = astRead( fitschan ); - - ... - -\end{terminalv} -\end{small} -c- - -f+ -Precisely how you extract world coordinate system (WCS) information -from a dataset obviously depends on what type of dataset it -is. Usually, however, you should be able to obtain a set of FITS -header cards which contain the WCS information (and probably much more -besides). Suppose that CARDS is an array of character strings -containing a complete set of FITS header cards and NCARD is the number -of cards. Then proceed as follows: - -\small -\begin{terminalv} - INTEGER FITSCHAN, ICARD, NCARD, WCSINFO - CHARACTER * ( 80 ) CARDS( NCARD ) - - ... - -* Create a FitsChan and fill it with FITS header cards. - FITSCHAN = AST_FITSCHAN( AST_NULL, AST_NULL, ' ', STATUS ) - DO 1 ICARD = 1, NCARD - CALL AST_PUTFITS( FITSCHAN, CARDS( ICARD ), .FALSE., STATUS ) - 1 CONTINUE - -* Rewind the FitsChan and read WCS information from it. - CALL AST_CLEAR( FITSCHAN, 'Card', STATUS ) - WCSINFO = AST_READ( FITSCHAN, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The result should be a pointer, ``wcsinfo'', to a FrameSet which -contains the WCS information. This pointer can now be used to perform -many useful tasks, some of which are illustrated in the following -recipes. -c- -f+ -The result should be a pointer, WCSINFO, to a FrameSet which contains -the WCS information. This pointer can now be used to perform many -useful tasks, some of which are illustrated in the following recipes. -f- - -c+ -Some datasets which do not easily yield FITS header cards may require -a different approach, possibly involving use of a Channel or XmlChan -(\secref{ss:channels}) rather than a FitsChan. In the case of the -Starlink NDF data format, for example, all the above may be replaced -by a single call to the function -\xref{ndfGtwcs}{sun33}{ndfGtwcs}---see \xref{SUN/33}{sun33}{}. The -whole process can probably be encapsulated in a similar way for -most data systems, whether they use FITS header cards or not. -c- -f+ -Some datasets which do not easily yield FITS header cards may require -a different approach, possibly involving use of a Channel or XmlChan -(\secref{ss:channels}) rather than a FitsChan. In the case of the -Starlink NDF data format, for example, all the above may be replaced -by a single call to the routine -\xref{NDF\_GTWCS}{sun33}{NDF_GTWCS}---see \xref{SUN/33}{sun33}{}. The -whole process can probably be encapsulated in a similar way for most -other data systems, whether they use FITS header cards or not. -f- - -For more details about reading WCS information from datasets, see -\secref{ss:identifyingfitsencoding} and -\secref{ss:readingforeignfits}. For a more general description of -FitsChans and their use with FITS header cards, see -\secref{ss:nativefits} and \secref{ss:foreignfits}. For more details -about FrameSets, see \secref{ss:framesets} and \secref{ss:fshigher}. - -\subsection{\ldots Validate WCS Information} - -Once you have read WCS information from a dataset, as in -\secref{ss:howtoreadwcs}, you may wish to check that you have been -successful. The following will detect and classify the things that -might possibly go wrong: - -c+ -\begin{small} -\begin{terminalv} -#include <string.h> - -... - -if ( !astOK ) { - <an error occurred (a message will have been issued)> -} else if ( wcsinfo == AST__NULL ) { - <there was no WCS information present> -} else if ( strcmp( astGetC( wcsinfo, "Class" ), "FrameSet" ) ) { - <something unexpected was read (i.e. not a FrameSet)> -} else { - <WCS information was read OK> -} -\end{terminalv} -\end{small} -c- -f+ -\small -\begin{terminalv} - IF ( STATUS .NE. 0 ) THEN - <an error occurred (a message will have been issued)> - ELSE IF ( WCSINFO .EQ. AST__NULL ) THEN - <there was no WCS information present> - ELSE IF ( AST_GETC( WCSINFO, 'Class', STATUS ) .NE. 'FrameSet' ) THEN - <something unexpected was read (i.e. not a FrameSet)> - ELSE - <WCS information was read OK> - END IF -\end{terminalv} -\normalsize -f- - -c+ -For more information about detecting errors in AST functions, see -\secref{ss:errordetection}. For details of how to validate input data -read by AST, see \secref{ss:validatinginput} and -\secref{ss:readingforeignfits}. -c- -f+ -For more information about detecting errors in AST routines, see -\secref{ss:errordetection}. For details of how to validate input data -read by AST, see \secref{ss:validatinginput} and -\secref{ss:readingforeignfits}. -f- - -\subsection{\ldots Display AST Data} - -If you have a pointer to any AST Object, you can display the data -stored in that Object in textual form as follows: - -c+ -\begin{small} -\begin{terminalv} -astShow( wcsinfo ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - CALL AST_SHOW( WCSINFO, STATUS ) -\end{terminalv} -\end{small} -f- - -Here, we have used a pointer to the FrameSet which we read earlier -(\secref{ss:howtoreadwcs}). The result is written to the program's -standard output stream. This can be very useful during debugging. - -c+ -For more details about using astShow, see -\secref{ss:displayingobjects}. For information about interpreting the -output, also see \secref{ss:textualoutputformat}. -c- -f+ -For more details about using AST\_SHOW, see -\secref{ss:displayingobjects}. For information about interpreting the -output, also see \secref{ss:textualoutputformat}. -f- - -\subsection{\label{ss:howtotransform}\ldots Convert Between Pixel and World Coordinates} - -You may use a pointer to a FrameSet, such as we read in -\secref{ss:howtoreadwcs}, to transform a set of points between the -pixel coordinates of an image and the associated world coordinates. If -you are working in two dimensions, proceed as follows: - -c+ -\begin{small} -\begin{terminalv} -double xpixel[ N ], ypixel[ N ]; -double xworld[ N ], yworld[ N ]; - -... - -astTran2( wcsinfo, N, xpixel, ypixel, 1, xworld, yworld ); -\end{terminalv} -\end{small} -c- -f+ -\small -\begin{terminalv} - INTEGER N - DOUBLE PRECISION XPIXEL( N ), YPIXEL( N ) - DOUBLE PRECISION XWORLD( N ), YWORLD( N ) - - ... - - CALL AST_TRAN2( WCSINFO, N, XPIXEL, YPIXEL, .TRUE., - : XWORLD, YWORLD, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, N is the number of points to be transformed, ``xpixel'' and -``ypixel'' hold the pixel coordinates, and ``xworld'' and ``yworld'' -receive the returned world coordinates.\footnote{By pixel coordinates, -we mean a coordinate system in which the first pixel in the image is -centred on (1,1) and each pixel is a unit square. Note that the world -coordinates will not necessarily be celestial coordinates, but if they -are, then they will be in radians.} To transform in the opposite -direction, interchange the two pairs of arrays (so that the world -coordinates are given as input) and change the fifth argument of -astTran2 to zero. -c- -f+ -Here, N is the number of points to be transformed, XPIXEL and YPIXEL -hold the pixel coordinates, and XWORLD and YWORLD receive the returned -world coordinates.\footnote{By pixel coordinates, we mean a coordinate -system in which the first pixel in the image is centred on (1,1) and -each pixel is a unit square. Note that the world coordinates will not -necessarily be celestial coordinates, but if they are, then they will -be in radians.} To transform in the opposite direction, interchange -the two pairs of arrays (so that the world coordinates are given as -input) and change the fifth argument of AST\_TRAN2 to .FALSE.. -f- - -c+ -To transform points in one dimension, use astTran1. In any other -number of dimensions (or if the number of dimensions is initially -unknown), use astTranN or astTranP. These functions are described in -\appref{ss:functiondescriptions}. -c- -f+ -To transform points in one dimension, use AST\_TRAN1. In any other -number of dimensions (or if the number of dimensions is initially -unknown), use AST\_TRANN. These routines are described in -\appref{ss:functiondescriptions}. -f- - -For more information about transforming coordinates, see -\secref{ss:transforming} and \secref{ss:framesetasmapping}. For -details of how to handle missing coordinates, see -\secref{ss:badcoordinates}. - -\subsection{\label{ss:howtotestforcelestial}\ldots Test if a WCS is a Celestial Coordinate System} - -The world coordinate system (WCS) currently associated with an image -may often be a celestial coordinate system, but this need not -necessarily be the case. For instance, instead of right ascension and -declination, an image might have a WCS with axes representing -wavelength and slit position, or maybe just plain old pixels. - -c+ -If you have obtained a WCS calibration for an image, as in -\secref{ss:howtoreadwcs}, in the form of a pointer ``wcsinfo'' to a -FrameSet, then you may determine if the current coordinate system is a -celestial one or not, as follows: -c- -f+ -If you have obtained a WCS calibration for an image, as in -\secref{ss:howtoreadwcs}, in the form of a pointer WCSINFO to a -FrameSet, then you may determine if the current coordinate system is a -celestial one or not, as follows: -f- - -c+ -\begin{small} -\begin{terminalv} -AstFrame *frame; -int issky; - -... - -/* Obtain a pointer to the current Frame and determine if it is a - SkyFrame. */ -frame = astGetFrame( wcsinfo, AST__CURRENT ); -issky = astIsASkyFrame( frame ); -frame = astAnnul( frame ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - INTEGER FRAME - LOGICAL ISSKY - - ... - -* Obtain a pointer to the current Frame and determine if it is a -* SkyFrame. - FRAME = AST_GETFRAME( WCSINFO, AST__CURRENT, STATUS ) - ISSKY = AST_ISASKYFRAME( FRAME, STATUS ) - CALL AST_ANNUL( FRAME, STATUS ) -\end{terminalv} -\end{small} -f- - -c+ -This will set ``issky'' to 1 if the WCS is a celestial coordinate -system, and to zero otherwise. -c- -f+ -This will set ISSKY to .TRUE.\ if the WCS is a celestial coordinate -system, and to .FALSE.\ otherwise. -f- - -\subsection{\label{ss:howtotestforspectral}\ldots Test if a WCS is a Spectral Coordinate System} -Testing for a spectral coordinate system is basically the same as testing -for a celestial coordinate system (see the previous section). The one -difference is that you use the -c+ -astIsASpecFrame function -c- -f+ -AST\_ISASPECFRAME routine -f- -in place of the -c+ -astIsASkyFrame function. -c- -f+ -AST\_ISASKYFRAME routine. -f- - -\subsection{\label{ss:howtoformatcoordinates}\ldots Format Coordinates for Display} - -c+ -Once you have converted pixel coordinates into world coordinates -(\secref{ss:howtotransform}), you may want to format them as text -before displaying them. Typically, this would convert from (say) -radians into something more comprehensible. Using the FrameSet pointer -``wcsinfo'' obtained in \secref{ss:howtoreadwcs} and a pair of world -coordinates ``xw'' and ``yw'' (\emph{e.g.}\ see -\secref{ss:howtotransform}), you could proceed as follows: -c- -f+ -Once you have converted pixel coordinates into world coordinates -(\secref{ss:howtotransform}), you may want to format them as text -before displaying them. Typically, this would convert from (say) -radians into something more comprehensible. Using the FrameSet pointer -WCSINFO obtained in \secref{ss:howtoreadwcs} and a pair of world -coordinates XW and YW (\emph{e.g.}\ see \secref{ss:howtotransform}), -you could proceed as follows: -f- - -c+ -\begin{small} -\begin{terminalv} -#include <stdio.h> -const char *xtext, *ytext; -double xw, yw; - -... - -xtext = astFormat( wcsinfo, 1, xw ); -ytext = astFormat( wcsinfo, 2, yw ); - -(void) printf( "Position = %s, %s\n", xtext, ytext ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - CHARACTER * ( 20 ) XTEXT, YTEXT - DOUBLE PRECISION XW, YW - - ... - - XTEXT = AST_FORMAT( WCSINFO, 1, XW, STATUS ) - YTEXT = AST_FORMAT( WCSINFO, 2, YW, STATUS ) - - WRITE ( *, 199 ) XTEXT, YTEXT - 199 FORMAT( 'Position = ', A, ', ', A ) -\end{terminalv} -\end{small} -f- - -c+ -Here, the second argument to astFormat is the axis number. -c- -f+ -Here, the second argument to AST\_FORMAT is the axis number. -f- - -With celestial coordinates, this will usually result in sexagesimal -notation, such as ``12:34:56.7''. However, the same method may be -applied to any type of coordinates and appropriate formatting will be -employed. - -For more information about formatting coordinate values and how to -control the style of formatting used, see -\secref{ss:formattingaxisvalues} and -\secref{ss:formattingskyaxisvalues}. If necessary, also see -\secref{ss:normalising} for details of how to ``normalise'' a set of -coordinates so that they lie within the standard range (\emph{e.g.}\ 0 -to 24 hours for right ascension and $\pm 90^\circ$ for -declination). - -\subsection{\ldots Display Coordinates as they are Transformed} - -c+ -In addition to formatting coordinates as part of a program's output, -you may also want to examine coordinate values while debugging your -program. To save time, you can ``eavesdrop'' on the coordinate values -being processed every time they are transformed. For example, when -using the FrameSet pointer ``wcsinfo'' obtained in -\secref{ss:howtoreadwcs} to transform coordinates -(\secref{ss:howtotransform}), you could inspect the coordinate values -as follows: -c- -f+ -In addition to formatting coordinates as part of a program's output, -you may also want to examine coordinate values while debugging your -program. To save time, you can ``eavesdrop'' on the coordinate values -being processed every time they are transformed. For example, when -using the FrameSet pointer WCSINFO obtained in -\secref{ss:howtoreadwcs} to transform coordinates -(\secref{ss:howtotransform}), you could inspect the coordinate values -as follows: -f- - -c+ -\begin{small} -\begin{terminalv} -astSet( wcsinfo, "Report=1" ); -astTran2( wcsinfo, N, xpixel, ypixel, 1, xworld, yworld ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - CALL AST_SET( WCSINFO, 'Report=1', STATUS ) - CALL AST_TRAN2( WCSINFO, N, XPIXEL, YPIXEL, .TRUE., - : XWORLD, YWORLD, STATUS ) -\end{terminalv} -\end{small} -f- - -By setting the FrameSet's Report attribute to 1, coordinate -transformations are automatically displayed on the program's standard -output stream, appropriately formatted, for example: - -\begin{terminalv} -(42.1087, 20.2717) --> (2:06:03.0, 34:22:39) -(43.0197, 21.1705) --> (2:08:20.6, 35:31:24) -(43.9295, 22.0716) --> (2:10:38.1, 36:40:09) -(44.8382, 22.9753) --> (2:12:55.6, 37:48:55) -(45.7459, 23.8814) --> (2:15:13.1, 38:57:40) -(46.6528, 24.7901) --> (2:17:30.6, 40:06:25) -(47.5589, 25.7013) --> (2:19:48.1, 41:15:11) -(48.4644, 26.6149) --> (2:22:05.6, 42:23:56) -(49.3695, 27.5311) --> (2:24:23.1, 43:32:41) -(50.2742, 28.4499) --> (2:26:40.6, 44:41:27) -\end{terminalv} - -For a complete description of the Report attribute, see its entry in -\appref{ss:attributedescriptions}. For further details of how to set -and enquire attribute values, see \secref{ss:settingattributes} and -\secref{ss:gettingattributes}. - -\subsection{\ldots Read Coordinates Entered by a User} - -In addition to writing out coordinate values generated by your program -(\secref{ss:howtoformatcoordinates}), you may also need to accept -coordinates entered by a user, or perhaps read from a file. In this -case, you will probably want to allow ``free-format'' input, so that -the user has some flexibility in the format that can be used. You will -probably also want to detect any typing errors. - -c+ -Let's assume that you want to read a number of lines of text, each -containing the world coordinates of a single point, and to split each -line into individual numerical coordinate values. Using the FrameSet -pointer ``wcsinfo'' obtained earlier (\secref{ss:howtoreadwcs}), you -could proceed as follows: -c- -f+ -Let's assume that you want to read a number of lines of text, each -containing the world coordinates of a single point, and to split each -line into individual numerical coordinate values. Using the FrameSet -pointer WCSINFO obtained earlier (\secref{ss:howtoreadwcs}), you could -proceed as follows: -f- - -c+ -\begin{small} -\begin{terminalv} -#include <stdio.h> -char *t; -char text[ MAXCHARS + 2 ]; -double coord[ 10 ]; -int iaxis, n, naxes; - -... - -/* Obtain the number of coordinate axes (if not already known). */ -naxes = astGetI( wcsinfo, "Naxes" ); - -/* Loop to read each line of input text, in this case from the - standard input stream (your programming environment will probably - provide a better way of reading text than this). Set the pointer - "t" to the start of each line read. */ -while ( t = fgets( text, MAXCHARS + 2, stdin ) ) { - -/* Attempt to read a coordinate for each axis. */ - for ( iaxis = 1; iaxis <= naxes; iaxis++ ) { - n = astUnformat( wcsinfo, iaxis, t, &coord[ iaxis - 1 ] ); - -/* If nothing was read and this is not the first axis or the - end-of-string, try stepping over a separator and reading again. */ - if ( !n && ( iaxis > 1 ) && *t ) - n = astUnformat( wcsinfo, iaxis, ++t, &coord[ iaxis - 1 ] ); - -/* Quit if nothing was read, otherwise move on to the next coordinate. */ - if ( !n ) break; - t += n; - } - -/* Test for the possible errors that may occur... */ - -/* Error detected by AST (a message will have been issued). */ - if ( !astOK ) { - break; - -/* Error in input data at character t[n]. */ - } else if ( *t || !n ) { - <handle the error, or report your own message here> - break; - - } else { - <coordinates were read OK> - } -} -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - CHARACTER TEXT * ( 80 ) - DOUBLE PRECISION COORD( 10 ) - INTEGER IAXIS, N, NAXES, T - - ... - -* Obtain the number of coordinate axes (if not already known). - NAXES = AST_GETI( WCSINFO, 'Naxes', STATUS ) - -* Loop to read each line of input text, in this case from the -* standard input channel (your programming environment will probably -* provide a better way of reading text than this). Set the index T to -* the start of each line read. - 2 CONTINUE - READ( *, '(A)', END=99 ) TEXT - T = 1 - -* Attempt to read a coordinate for each axis. - DO 3 IAXIS = 1, NAXES - N = AST_UNFORMAT( WCSINFO, IAXIS, TEXT( T : ), COORD( IAXIS ), - : STATUS ) - -* If nothing was read and this is not the first axis and the end of -* the text has not been reached, try stepping over a separator and -* reading again. - IF ( ( N .EQ. 0 ) .AND. ( IAXIS .GT. 1 ) .AND. - : ( T .LT. LEN( STRING ) ) ) THEN - T = T + 1 - N = AST_UNFORMAT( WCSINFO, IAXIS, TEXT( T : ), - COORD( IAXIS ), STATUS ) - END IF - -* Quit if nothing was read, otherwise move on to the next coordinate. - IF ( N .EQ. 0 ) GO TO 4 - T = T + N - 3 CONTINUE - 4 CONTINUE - -* Test for the possible errors that may occur... - -* Error detected by AST (a message will have been issued). - IF ( STATUS .NE. 0 ) THEN - GO TO 99 - -* Error in input data at character TEXT( T + N : T + N ). - ELSE IF ( ( T .LT. LEN( STRING ) ) .OR. ( N .EQ. 0 ) ) THEN - <handle the error, or report your own message here> - GO TO 99 - - ELSE - <coordinates were read OK> - END IF - -* Return to read the next input line. - GO TO 2 - 99 CONTINUE -\end{terminalv} -\end{small} -f- - -This algorithm has the advantage of accepting free-format input in -whatever style is appropriate for the world coordinates in use (under -the control of the FrameSet whose pointer you provide). For example, -wavelength values might be read as floating point numbers -(\emph{e.g.}\ ``1.047'' or ``4787''), whereas celestial positions -could be given in sexagesimal format (\emph{e.g.}\ ``12:34:56'' or -``12~34.5'') and would be converted into radians. Individual -coordinate values may be separated by white space and/or any -non-ambiguous separator character, such as a comma. - -c+ -For more information on reading coordinate values using the -astUnformat function, see \secref{ss:unformattingaxisvalues}. For -details of how sexagesimal formats are handled, and the forms of input -that may be used for celestial coordinates, see -\secref{ss:unformattingskyaxisvalues}. -c- -f+ -For more information on reading coordinate values using the -AST\_UNFORMAT function, see \secref{ss:unformattingaxisvalues}. For -details of how sexagesimal formats are handled, and the forms of input -that may be used for for celestial coordinates, see -\secref{ss:unformattingskyaxisvalues}. -f- - -\subsection{\label{ss:howtocreatenewwcs}\ldots Create a New WCS Calibration} - -This section describes how to add a WCS calibration to a data set which you -are creating from scratch, rather than modifying an existing data set. - -In most common cases, the simplest way to create a new WCS calibration -from scratch is probably to create a set of strings describing the -required calibration in terms of the keywords used by the FITS WCS -standard, and then convert these strings into an AST FrameSet describing -the calibration. This FrameSet can then be used for many other purposes, or -simply stored in the data set. - -The full FITS-WCS standard is quite involved, currently running to four -separate papers, but the basic kernel is quite simple, involving the -following keywords (all of which end with an integer axis index, -indicated below by $<i>$): - -\begin{description} -\item[CRPIX<i>]\mbox{}\\ -hold the pixel coordinates at a reference point -\item[CRVAL<i>]\mbox{}\\ -hold the corresponding WCS coordinates at the reference point -\item[CTYPE<i>]\mbox{}\\ -name the quantity represented by the WCS axes, together with the -projection algorithm used to convert the scaled and rotated pixel coordinates -to WCS coordinates. -\item[CD<i>\_<j>]\mbox{}\\ -a set of keywords which specify the elements of a matrix. This matrix scales -pixel offsets from the reference point into the offsets required as input -by the projection algorithm specified by the CTYPE keywords. This matrix -specifies the scale and rotation of the image. If there is no rotation -the off-diagonal elements of the matrix (\emph{e.g.} CD1\_2 and -CD2\_1) can be omitted. -\end{description} - -As an example consider the common case of a simple 2D image of the sky in -which north is parallel to the second pixel axis and east parallel to the -(negative) first pixel axis. The image scale is 1.2 arc-seconds per pixel -on both axes, and the image is presumed to have been obtained with a -tangent plane projection. Furthermore, it is known that pixel coordinates -(100.5,98.4) correspond to an RA of 11:00:10 and a Dec. of -23:26:02. -A suitable set of FITS-WCS header cards could be: - -\begin{small} -\begin{terminalv} -CTYPE1 = 'RA---TAN' / Axis 1 represents RA with a tan projection -CTYPE2 = 'DEC--TAN' / Axis 2 represents Dec with a tan projection -CRPIX1 = 100.5 / Pixel coordinates of reference point -CRPIX2 = 98.4 / Pixel coordinates of reference point -CRVAL1 = 165.04167 / Degrees equivalent of "11:00:10" hours -CRVAL2 = -23.433889 / Decimal equivalent of "-23:26:02" degrees -CD1_1 = -0.0003333333 / Decimal degrees equivalent of -1.2 arc-seconds -CD2_2 = 0.0003333333 / Decimal degrees equivalent of 1.2 arc-seconds -\end{terminalv} -\end{small} - -Notes: -\begin{itemize} -\item a FITS header card begins with the keyword name starting at column 1, -has an equals sign in column 9, and the keyword value in columns 11 to 80. -\item string values must be enclosed in single quotes. -\item celestial longitude and latitude must both be specified in decimal degrees. -\item the CD1\_1 value is negative to indicate that RA increases as the -first pixel axis decreases. -\item the (RA,Dec) coordinates will be taken as ICRS coordinates. For FK5 -you should add: - -\begin{small} -\begin{terminalv} -RADESYS = 'FK5' -EQUINOX = 2005.6 -\end{terminalv} -\end{small} - -The EQUINOX value defaults to J2000.0 if omitted. FK4 can also be used in -place of FK5, in which case EQUINOX defaults to B1950.0. - -\end{itemize} - -Once you have created these FITS-WCS header card strings, you should -store them in a FitsChan and then read the corresponding FrameSet from the -FitsChan. How to do this is described in \secref{ss:howtoreadwcs}. - -Having created the WCS calibration, you may want to store it in a data -file. How to do this is described in \secref{ss:howtowritewcs}).\footnote{If -you are writing the WCS calibration to a FITS file you obviously -have the choice of storing the FITS-WCS cards directly.} - -If the required WCS calibration cannot be described as a set of FITS-WCS -headers, then a different approach is necessary. In this case, you should -first create a Frame describing pixel coordinates, and store this Frame -in a new FrameSet. You should then create a new Frame describing the -world coordinate system. This Frame may be a specific subclass of Frame such -as a SkyFrame for celestial coordinates, a SpecFrame for spectral -coordinates, a Timeframe for time coordinates, or a CmpFrame for a combination -of different coordinates. -You also need to create a suitable Mapping which transforms pixel -coordinates into world coordinates. AST provides many different types of -Mappings, all of which can be combined together in arbitrary fashions to -create more complicated Mappings. The WCS Frame should then be added into -the FrameSet, using the Mapping to connect the WCS Frame with the pixel -Frame. - -\subsection{\label{ss:howtomodifywcs}\ldots Modify a WCS Calibration} - -The usual reason for wishing to modify the WCS calibration associated -with a dataset is that the data have been geometrically transformed in -some way (here, we will assume a 2-dimensional image dataset). This -causes the image features (stars, galaxies, \emph{etc.}) to move with -respect to the grid of pixels which they occupy, so that any -coordinate systems previously associated with the image become -invalid. - -To correct for this, it is necessary to set up a Mapping which -expresses the positions of image features in the new data grid in -terms of their positions in the old grid. In both cases, the grid -coordinates we use will have the first pixel centred at (1,1) with -each pixel being a unit square. - -c+ -AST allows you to correct for any type of geometrical transformation -in this way, so long as a suitable Mapping to describe it can be -constructed. For purposes of illustration, we will assume here that -the new image coordinates ``xnew'' and ``ynew'' can be expressed in -terms of the old coordinates ``xold'' and ``yold'' as follows: -c- -f+ -AST allows you to correct for any type of geometrical transformation -in this way, so long as a suitable Mapping to describe it can be -constructed. For purposes of illustration, we will assume here that -the new image coordinates XNEW and YNEW can be expressed in terms of -the old coordinates XOLD and YOLD as follows: -f- - -c+ -\begin{small} -\begin{terminalv} -double xnew, xold, ynew, yold; -double m[ 4 ], z[ 2 ]; - -... - -xnew = xold * m[ 0 ] + yold * m[ 1 ] + z[ 0 ]; -ynew = xold * m[ 2 ] + yold * m[ 3 ] + z[ 1 ]; -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - DOUBLE PRECISION XNEW, XOLD, YNEW, YOLD - DOUBLE PRECISION M( 4 ), Z( 2 ) - - ... - - XNEW = XOLD * M( 1 ) + YOLD * M( 2 ) + Z( 1 ) - YNEW = XOLD * M( 3 ) + YOLD * M( 4 ) + Z( 2 ) -\end{terminalv} -\end{small} -f- - -c+ -where ``m'' is a 2$\times$2 transformation matrix and ``z'' represents -a shift of origin. This is therefore a general linear coordinate -transformation which can represent displacement, rotation, -magnification and shear. -c- -f+ -where M is a 2$\times$2 transformation matrix and Z represents a shift -of origin. This is therefore a general linear coordinate -transformation which can represent displacement, rotation, -magnification and shear. -f- - -In AST, it can be represented by concatenating two Mappings. The first -is a MatrixMap, which implements the matrix multiplication. The second -is a WinMap, which linearly transforms one coordinate window on to -another, but will be used here simply to implement the shift of -origin (alternatively, a ShiftMap could have been used in place of a -WinMap). These Mappings may be constructed and concatenated as follows: - -c+ -\begin{small} -\begin{terminalv} -AstCmpMap *newmap; -AstMatrixMap *matrixmap; -AstWinMap *winmap; - -... - -/* The MatrixMap may be constructed directly from the matrix "m". */ -matrixmap = astMatrixMap( 2, 2, 0, m, "" ); - -/* For the WinMap, we set up the coordinates of the corners of a unit - square (window) and then the same square shifted by the required - amount. */ -{ - double ina[] = { 0.0, 0.0 }; - double inb[] = { 1.0, 1.0 }; - double outa[] = { z[ 0 ], z[ 1 ] }; - double outb[] = { 1.0 + z[ 0 ], 1.0 + z[ 1 ] }; - -/* The WinMap will then implement this shift. */ - winmap = astWinMap( 2, ina, inb, outa, outb, "" ); -} - -/* Join the two Mappings together, so that they are applied one after - the other. */ -newmap = astCmpMap( matrixmap, winmap, 1, "" ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - DOUBLE PRECISION INA( 2 ), INB( 2 ), OUTA( 2 ), OUTB( 2 ) - INTEGER MATRIXMAP, WINMAP - - ... - -* Set up the corners of a unit square. - DATA INA / 2 * 0.0D0 / - DATA INB / 2 * 1.0D0 / - -* The MatrixMap may be constructed directly from the matrix M. - MATRIXMAP = AST_MATRIXMAP( 2, 2, 0, M, ' ', STATUS ) - -* For the WinMap, we take the coordinates of the corners of a unit -* square (window) and then shift them by the required amounts. - OUTA( 1 ) = INA( 1 ) + Z( 1 ) - OUTA( 2 ) = INA( 2 ) + Z( 2 ) - OUTB( 1 ) = INB( 1 ) + Z( 1 ) - OUTB( 2 ) = INB( 2 ) + Z( 2 ) - -* The WinMap will then implement this shift. - WINMAP = AST_WINMAP( 2, INA, INB, OUTA, OUTB, ' ', STATUS ) - -* Join the two Mappings together, so that they are applied one after -* the other. - NEWMAP = AST_CMPMAP( MATRIXMAP, WINMAP, 1, ' ', STATUS ) -\end{terminalv} -\end{small} -f- - -You might, of course, create any other form of Mapping depending on -the type of geometrical transformation involved. For an overview of -the Mappings provided by AST, see \secref{ss:mappingselection}, and -for a description of the capabilities of each class of Mapping, see -its entry in \appref{ss:classdescriptions}. For an overview of how -individual Mappings may be combined, see \secref{ss:cmpmapoverview} -(\secref{ss:cmpmaps} gives more details). - -c+ -Assuming you have obtained a WCS calibration for your original image -in the form of a pointer to a FrameSet, ``wcsinfo1'' -(\secref{ss:howtoreadwcs}), the Mapping created above may be used to -produce a calibration for the new image as follows: -c- -f+ -Assuming you have obtained a WCS calibration for your original image -in the form of a pointer to a FrameSet, WCSINFO1 -(\secref{ss:howtoreadwcs}), the Mapping created above may be used to -produce a calibration for the new image as follows: -f- - -c+ -\begin{small} -\begin{terminalv} -AstFrameSet *wcsinfo1, *wcsinfo2; - -... - -/* If necessary, make a copy of the WCS calibration, since we are - about to alter it. */ -wcsinfo2 = astCopy( wcsinfo1 ); - -/* Re-map the base Frame so that it refers to the new data grid - instead of the old one. */ -astRemapFrame( wcsinfo2, AST__BASE, newmap ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - INTEGER WCSINFO1, WCSINFO2 - - ... - -* If necessary, make a copy of the WCS calibration, since we are -* about to alter it. - WCSINFO2 = AST_COPY( WCSINFO1, STATUS ) - -* Re-map the base Frame so that it refers to the new data grid -* instead of the old one. - CALL AST_REMAPFRAME( WCSINFO2, AST__BASE, NEWMAP, STATUS ) -\end{terminalv} -\end{small} -f- - -c+ -This will produce a pointer, ``wcsinfo2'', to a new FrameSet in which -all the coordinate systems associated with your original image are -modified so that they are correctly registered with the new image -instead. -c- -f+ -This will produce a pointer, WCSINFO2, to a new FrameSet in which all -the coordinate systems associated with the original image are modified -so that they are correctly registered with your new image instead. -f- - -For more information about re-mapping the Frames within a FrameSet, -see \secref{ss:remapframe}. Also see \secref{ss:wcsprocessingexample} -for a similar example to the above, applicable to the case of reducing -the size of an image by binning. - -\subsection{\label{ss:howtowritewcs}\ldots Write a Modified WCS Calibration to a Dataset} - -If you have modified the WCS calibration associated with a dataset, -such as in the example above (\secref{ss:howtomodifywcs}), then you -will need to write the modified version out along with any new data. - -In the same way as when reading a WCS calibration -(\secref{ss:howtoreadwcs}), how you do this will depend on your data -system, but we will assume that you wish to generate a set of FITS -header cards that can be stored with the data. You should usually make -preparations for doing this when you first read the WCS calibration -from your input dataset by modifying the example given in -\secref{ss:howtoreadwcs} as follows: - -c+ -\begin{small} -\begin{terminalv} -AstFitsChan *fitschan1; -AstFrameSet *wcsinfo1; -const char *encode; - -... - -/* Create an input FitsChan and fill it with FITS header cards. Note, - if you have all the header cards in a single string, use astPutCards in - place of astPutFits. */ -fitschan1 = astFitsChan( NULL, NULL, "" ); -for ( icard = 0; icard < ncard; icard++ ) astPutFits( fitschan1, cards[ icard ], 0 ); - -/* Note which encoding has been used for the WCS information. */ -encode = astGetC( fitschan1, "Encoding" ); - -/* Rewind the input FitsChan and read the WCS information from it. */ -astClear( fitschan1, "Card" ); -wcsinfo1 = astRead( fitschan1 ); -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} - INTEGER FITSCHAN1, WCSINFO1 - CHARACTER * ( 20 ) ENCODE - - ... - -* Create an input FitsChan and fill it with FITS header cards. Note, -* if you have all the header cards in a single string, use AST_PUTCARDS in -* place of AST_PUTFITS. - FITSCHAN1 = AST_FITSCHAN( AST_NULL, AST_NULL, ' ', STATUS ) - DO 1 ICARD = 1, NCARD - CALL AST_PUTFITS( FITSCHAN1, CARDS( ICARD ), .FALSE., STATUS ) - 1 CONTINUE - -* Note which encoding has been used for the WCS information. - ENCODE = AST_GETC( FITSCHAN1, 'Encoding', STATUS ); - -* Rewind the input FitsChan and read the WCS information from it. - CALL AST_CLEAR( FITSCHAN1, 'Card', STATUS ) - WCSINFO1 = AST_READ( FITSCHAN1, STATUS ) -\end{terminalv} -\end{small} -f- - -c+ -Note how we have added an enquiry to determine how the WCS information -is encoded in the input FITS cards, storing a pointer to the resulting -string in the ``encode'' variable. This must be done \textbf{before} -actually reading the WCS calibration. -c- -f+ -Note how we have added an enquiry to determine how the WCS information -is encoded in the input FITS cards, storing the resulting string in -the ENCODE variable. This must be done \textbf{before} actually reading -the WCS calibration. -f- - -c+ -\emph{(\textbf{N.B.}\ If you will be making extensive use of astGetC in -your program, then you should allocate a buffer and make a copy of -this string, because the pointer returned by astGetC will only remain -valid for 50 invocations of the function, and you will need to use the -Encoding value again later on.)} -c- - -c+ -Once you have produced a modified WCS calibration for the output -dataset (\emph{e.g.}\ \secref{ss:howtomodifywcs}), in the form of a -FrameSet identified by the pointer ``wcsinfo2'', you can produce a new -FitsChan containing the output FITS header cards as follows: -c- -f+ -Once you have produced a modified WCS calibration for the output -dataset (\emph{e.g.}\ \secref{ss:howtomodifywcs}), in the form of a -FrameSet identified by the pointer WCSINFO2, you can produce a new -FitsChan containing the output FITS header cards as follows: -f- - -c+ -\small -\begin{terminalv} -AstFitsChan *fitschan2; -AstFrameSet *wcsinfo2; - -... - -/* Make a copy of the input FitsChan, AFTER the WCS information has - been read from it. This will propagate all the input FITS header - cards, apart from those describing the input WCS calibration. */ -fitschan2 = astCopy( fitschan1 ); - -/* If necessary, make modifications to the cards in "fitschan2" - (e.g. you might need to change NAXIS1, NAXIS2, etc., to account for - a change in image size). You probably only need to do this if your - data system does not provide these facilities itself. */ -<details not shown - see below> - -/* Alternatively, if your data system handles the propagation of FITS - header cards to the output dataset for you, then simply create an - empty FitsChan to contain the output WCS information alone. -fitschan2 = astFitsChan( NULL, NULL, "" ); -*/ - -/* Rewind the new FitsChan (if necessary) and attempt to write the - output WCS information to it using the same encoding method as the - input dataset. */ -astSet( fitschan2, "Card=1, Encoding=%s", encode ); -if ( !astWrite( fitschan2, wcsinfo2 ) ) { - -/* If this didn't work (the WCS FrameSet has become too complex), then - use the native AST encoding instead. */ - astSet( fitschan2, "Encoding=NATIVE" ); - (void) astWrite( fitschan2, wcsinfo2 ); -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FITSCHAN2, JUNK, WCSINFO2 - - ... - -* Make a copy of the input FitsChan, AFTER the WCS information has -* been read from it. This will propagate all the input FITS header -* cards, apart from those describing the WCS calibration. - FITSCHAN2 = AST_COPY( FITSCHAN1, STATUS ) - -* If necessary, make modifications to the cards in FITSCHAN2 -* (e.g. you might need to change NAXIS1, NAXIS2, etc., to account for -* a change in image size). You probably only need to do this if your -* data system does not provide these facilities itself. - <details not shown - see below> - -* Alternatively, if your data system handles the propagation of FITS -* header cards to the output dataset for you, then simply create an -* empty FitsChan to contain the output WCS information alone. -* FITSCHAN2 = AST_FITSCHAN( AST_NULL, AST_NULL, ' ', STATUS ) - -* Rewind the new FitsChan (if necessary) and attempt to write the -* output WCS information to it using the same encoding method as the -* input dataset. - CALL AST_SET( FITSCHAN2, 'Card=1, Encoding=' // ENCODE, STATUS ) - IF ( AST_WRITE( FITSCHAN2, WCSINFO2, STATUS ) .EQ. 0 ) THEN - -* If this didn't work (the WCS FrameSet has become too complex), then -* use the native AST encoding instead. - CALL AST_SETC( FITSCHAN2, 'Encoding', 'NATIVE', STATUS ); - JUNK = AST_WRITE( FITSCHAN2, WCSINFO2, STATUS ); - END IF -\end{terminalv} -\normalsize -f- - -For details of how to modify the contents of the output FitsChan in -other ways, such as by adding, over-writing or deleting header cards, -see \secref{ss:addressingfitscards}, \secref{ss:addingmulticards}, \secref{ss:addingfitscards} and -\secref{ss:findingandchangingfits}. - -Once you have assembled the output FITS cards, you may retrieve them -from the FitsChan that contains them as follows: - -c+ -\small -\begin{terminalv} -#include <stdio.h> -char card[ 81 ]; - -... - -astClear( fitschan2, "Card" ); -while ( astFindFits( fitschan2, "%f", card, 1 ) ) (void) printf( "%s\n", card ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 80 ) CARD - - ... - - CALL AST_CLEAR( FITSCHAN2, 'Card', STATUS ) - 5 CONTINUE - IF ( AST_FINDFITS( FITSCHAN2, '%f', CARD, .TRUE., STATUS ) ) THEN - WRITE ( *, '(A)' ) CARD - GO TO 5 - END IF -\end{terminalv} -\normalsize -f- - -c+ -Here, we have simply written each card to the standard output stream, -but you would obviously replace this with a function invocation to -store the cards in your output dataset. -c- -f+ -Here, we have simply written each card to the standard output unit, -but you would obviously replace this with a subroutine call to store -the cards in your output dataset. -f- - -c+ -For data systems that do not use FITS header cards, a different -approach may be needed, possibly involving use of a Channel or XmlChan -(\secref{ss:channels}) rather than a FitsChan. In the case of the -Starlink NDF data format, for example, all of the above may be -replaced by a single call to the function -\xref{ndfPtwcs}{sun33}{ndfPtwcs}---see \xref{SUN/33}{sun33}{}. The -whole process can probably be encapsulated in a similar way for most -data systems, whether they use FITS header cards or not. -c- -f+ -For data systems that do not use FITS header cards, a different -approach may be needed, possibly involving use of a Channel or XmlChan -(\secref{ss:channels}) rather than a FitsChan. In the case of the -Starlink NDF data format, for example, all of the above may be -replaced by a single call to the routine -\xref{NDF\_PTWCS}{sun33}{NDF_PTWCS}---see \xref{SUN/33}{sun33}{}. The -whole process can probably be encapsulated in a similar way for most -other data systems, whether they use FITS header cards or not. -f- - -For an overview of how to propagate WCS information through data -processing steps, see \secref{ss:propagatingwcsinformation}. For more -information about writing WCS information to FitsChans, see -\secref{ss:writingnativefits} and \secref{ss:writingforeignfits}. For -information about the options for encoding WCS information in FITS -header cards, see \secref{ss:nativeencoding}, -\secref{ss:foreignencodings}, and the description of the Encoding -attribute in \appref{ss:attributedescriptions}. For a complete -understanding of FitsChans and their use with FITS header cards, you -should read \secref{ss:nativefits} and \secref{ss:foreignfits}. - -\subsection{\label{ss:howtoplotgrid}\ldots Display a Graphical Coordinate Grid} - - A common requirement when displaying image data is to plot an - associated coordinate grid (\emph{e.g.}\ Figure~\ref{fig:overgrid}) - over the displayed image. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/overgrid_bw} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/overgrid_bw} -f- - \caption[An example of a displayed image with a coordinate grid - plotted over it.]{An example of a displayed image with a coordinate grid - plotted over it.} - \label{fig:overgrid} - \end{center} - \end{figure} - -c+ -The use of AST in such circumstances is independent of the underlying -graphics system, so starting up the graphics system, setting up a -coordinate system, displaying the image, and closing down afterwards -can all be done using the graphics functions you would normally use. -c- -f+ -The use of AST in such circumstances is independent of the underlying -graphics system, so starting up the graphics system, setting up a -coordinate system, displaying the image, and closing down afterwards -can all be done using the graphics routines you would normally use. -f- - -c+ -However, displaying an image at a precise location can be a little -fiddly with some graphics systems, and obviously the grid drawn by AST -will not be accurately registered with the image unless this is done -correctly. In the following template, we therefore illustrate both -steps, basing the image display on the C interface to the PGPLOT -graphics package.\footnote{An interface is provided with AST that -allows it to use PGPLOT (\xref{SUN/15}{sun15}{}) for its graphics, -although interfaces to other graphics systems may also be written.} -Plotting a coordinate grid with AST then becomes a relatively minor -part of what is almost a complete graphics program. -c- -f+ -However, displaying an image at a precise location can be a little -fiddly with some graphics systems, and obviously the grid drawn by AST -will not be accurately registered with the image unless this is done -correctly. In the following template, we therefore illustrate both -steps, basing the image display on the PGPLOT graphics -package.\footnote{An interface is provided with AST that allows it to -use PGPLOT (\xref{SUN/15}{sun15}{}) for its graphics, although -interfaces to other graphics systems may also be written.} Plotting a -coordinate grid with AST then becomes a relatively minor part of what -is almost a complete graphics program. -f- - -c+ -Once again, we assume that a pointer, ``wcsinfo'', to a suitable -FrameSet associated with the image has already been obtained -(\secref{ss:howtoreadwcs}). -c- -f+ -Once again, we assume that a pointer, WCSINFO, to a suitable FrameSet -associated with the image has already been obtained -(\secref{ss:howtoreadwcs}). -f- - -c+ -\small -\begin{terminalv} -#include "cpgplot.h" -AstPlot *plot; -const float *data; -float hi, lo, scale, x1, x2, xleft, xright, xscale; -float y1, y2, ybottom, yscale, ytop; -int nx, ny; - -... - -/* Access the image data, which we assume has dimension sizes "nx" and - "ny", and will be accessed via the "data" pointer. Also derive - limits for scaling it, which we assign to the variables "hi" and - "lo". */ -<this stage depends on your data system, so is not shown> - -/* Open PGPLOT using the device given by environment variable - PGPLOT_DEV and check for success. */ -if( cpgbeg( 0, " ", 1, 1 ) == 1 ) { - -/* Clear the screen and ensure equal scales on both axes. */ - cpgpage(); - cpgwnad( 0.0f, 1.0f, 0.0f, 1.0f ); - -/* Obtain the extent of the plotting area (not strictly necessary for - PGPLOT, but possibly for other graphics systems). From this, derive - the display scale in graphics units per pixel so that the image - will fit within the display area. */ - cpgqwin( &x1, &x2, &y1, &y2 ); - xscale = ( x2 - x1 ) / nx; - yscale = ( y2 - y1 ) / ny; - scale = ( xscale < yscale ) ? xscale : yscale; - -/* Calculate the extent of the area in graphics units that the image - will occupy, so as to centre it within the display area. */ - xleft = 0.5f * ( x1 + x2 - nx * scale ); - xright = 0.5f * ( x1 + x2 + nx * scale ); - ybottom = 0.5f * ( y1 + y2 - ny * scale ); - ytop = 0.5f * ( y1 + y2 + ny * scale ); - -/* Set up a PGPLOT coordinate transformation matrix and display the - image data as a grey scale map (these details are specific to - PGPLOT). */ - { - float tr[] = { xleft - 0.5f * scale, scale, 0.0f, - ybottom - 0.5f * scale, 0.0f, scale }; - cpggray( data, nx, ny, 1, nx, 1, ny, hi, lo, tr ); - } - -/* BEGINNING OF AST BIT */ -/* ==================== */ -/* Store the locations of the bottom left and top right corners of the - region used to display the image, in graphics coordinates. */ - { - float gbox[] = { xleft, ybottom, xright, ytop }; - -/* Similarly, store the locations of the image's bottom left and top - right corners, in pixel coordinates -- with the first pixel centred - at (1,1). */ - double pbox[] = { 0.5, 0.5, nx + 0.5, ny + 0.5 }; - -/* Create a Plot, based on the FrameSet associated with the - image. This attaches the Plot to the graphics surface so that it - matches the displayed image. Specify that a complete set of grid - lines should be drawn (rather than just coordinate axes). */ - plot = astPlot( wcsinfo, gbox, pbox, "Grid=1" ); - } - -/* Optionally, we can now set other Plot attributes to control the - appearance of the grid. The values assigned here use the - colour/font indices defined by the underlying graphics system. */ - astSet( plot, "Colour(grid)=2, Font(textlab)=3" ); - -/* Use the Plot to draw the coordinate grid. */ - astGrid( plot ); - - <maybe some more AST graphics here> - -/* Annul the Plot when finished (or use the astBegin/astEnd technique - shown earlier). */ - plot = astAnnul( plot ); - -/* END OF AST BIT */ -/* ============== */ - -/* Close down the graphics system. */ - cpgend(); -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION BBOX( 4 ) - INTEGER NX, NY, PGBEG, PLOT - REAL DATA( NX, NY ), GBOX( 4 ), HI, LO, SCALE, TR( 6 ) - REAL X1, X2, XLEFT, XRIGHT, Y1, Y2, YBOTTOM, YTOP - - ... - -* Access the image data, which we assume will be stored in the real -* 2-dimensional array DATA with dimension sizes NX and NY. Also -* derive limits for scaling it, which we assign to the variables HI -* and LO. - <this stage depends on your data system, so is not shown> - -* Open PGPLOT using the device given by environment variable -* PGPLOT_DEV and check for success. - IF ( PGBEG( 0, ' ', 1, 1 ) .EQ. 1 ) THEN - -* Clear the screen and ensure equal scales on both axes. - CALL PGPAGE - CALL PGWNAD( 0.0, 1.0, 0.0, 1.0 ) - -* Obtain the extent of the plotting area (not strictly necessary for -* PGPLOT, but possibly for other graphics systems). From this, derive -* the display scale in graphics units per pixel so that the image -* will fit within the display area. - CALL PGQWIN( X1, X2, Y1, Y2 ) - SCALE = MIN( ( X2 - X1 ) / NX, ( Y2 - Y1 ) / NY ) - -* Calculate the extent of the area in graphics units that the image -* will occupy, so as to centre it within the display area. - XLEFT = 0.5 * ( X1 + X2 - NX * SCALE ) - XRIGHT = 0.5 * ( X1 + X2 + NX * SCALE ) - YBOTTOM = 0.5 * ( Y1 + Y2 - NY * SCALE ) - YTOP = 0.5 * ( Y1 + Y2 + NY * SCALE ) - -* Set up a PGPLOT coordinate transformation matrix and display the -* image data as a grey scale map (these details are specific to -* PGPLOT). - TR( 1 ) = XLEFT - 0.5 * SCALE - TR( 2 ) = SCALE - TR( 3 ) = 0.0 - TR( 4 ) = YBOTTOM - 0.5 * SCALE - TR( 5 ) = 0.0 - TR( 6 ) = SCALE - CALL PGGRAY( DATA, NX, NY, 1, NX, 1, NY, HI, LO, TR ) - -* BEGINNING OF AST BIT -* ==================== -* Store the locations of the bottom left and top right corners of the -* region used to display the image, in graphics coordinates. - GBOX( 1 ) = XLEFT - GBOX( 2 ) = YBOTTOM - GBOX( 3 ) = XRIGHT - GBOX( 4 ) = YTOP - -* Similarly, store the locations of the image's bottom left and top -* right corners, in pixel coordinates -- with the first pixel centred -* at (1,1). - BBOX( 1 ) = 0.5D0 - BBOX( 2 ) = 0.5D0 - BBOX( 3 ) = NX + 0.5D0 - BBOX( 4 ) = NY + 0.5D0 - -* Create a Plot, based on the FrameSet associated with the -* image. This attaches the Plot to the graphics surface so that it -* matches the displayed image. Specify that a complete set of grid -* lines should be drawn (rather than just coordinate axes). - PLOT = AST_PLOT( WCSINFO, GBOX, BBOX, 'Grid=1', STATUS ) - -* Optionally, we can now set other Plot attributes to control the -* appearance of the grid. The values assigned here use the -* colour/font indices defined by the underlying graphics system. - CALL AST_SET( PLOT, 'Colour(grid)=2, Font(textlab)=3', STATUS ) - -* Use the Plot to draw the coordinate grid. - CALL AST_GRID( PLOT, STATUS ) - - <maybe some more AST graphics here> - -* Annul the Plot when finished (or use the AST_BEGIN/AST_END -* technique shown earlier). - CALL AST_ANNUL( PLOT, STATUS ) - -* END OF AST BIT -* ============== - -* Close down the graphics system. - CALL PGEND - END IF -\end{terminalv} -\normalsize -f- - -Note that once you have set up a Plot which is aligned with a -displayed image, you may also use it to generate further graphical -output of your own, specified in the image's world coordinate system -(such as markers to represent astronomical objects, annotation, -\emph{etc.}). There is also a range of Plot attributes which gives -control over most aspects of the output's appearance. For details of -the facilities available, see \secref{ss:plots} and the description of -the Plot class in \appref{ss:classdescriptions}. - -For details of how to build a graphics program which uses PGPLOT, see -\secref{ss:howtobuild} and the description of the ast\_link command in -\appref{ss:commanddescriptions}. - -\subsection{\label{ss:howtoswitchgrid}\ldots Switch to Plot a Different Celestial Coordinate Grid} - -c+ -Once you have set up a Plot to draw a coordinate grid -(\secref{ss:howtoplotgrid}), it is a simple matter to change things so -that the grid represents a different celestial coordinate system. For -example, after creating the Plot with astPlot, you could use: -c- -f+ -Once you have set up a Plot to draw a coordinate grid -(\secref{ss:howtoplotgrid}), it is a simple matter to change things so -that the grid represents a different celestial coordinate system. For -example, after creating the Plot with AST\_PLOT, you could use: -f- - -c+ -\small -\begin{terminalv} -astSet( plot, "System=Galactic" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( PLOT, 'System=Galactic', STATUS ) -\end{terminalv} -\normalsize -f- -or: -c+ -\small -\begin{terminalv} -astSet( plot, "System=FK5, Equinox=J2010" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( PLOT, 'System=FK5, Equinox=J2010', STATUS ) -\end{terminalv} -\normalsize -f- - -and any axes and/or grid drawn subsequently would represent the new -celestial coordinate system you specified. Note, however, that this -will only work if the original grid represented celestial coordinates -of some kind (see \secref{ss:howtotestforcelestial} for how to -determine if this is the case\footnote{Note that the methods applied -to a FrameSet may be used equally well with a Plot.}). If it did not, -you will get an error message. - -For more information about the celestial coordinate systems available, -see the descriptions of the System, Equinox and Epoch attributes in -\appref{ss:attributedescriptions}. - -\subsection{\ldots Give a User Control Over the Appearance of a Plot} - -The idea of using a Plot's attributes to control the appearance of the -graphical output it produces (\secref{ss:howtoplotgrid} and -\secref{ss:howtoswitchgrid}) can easily be extended to allow the user -of a program complete control over such matters. - -For instance, if the file ``plot.config'' contains a series of -plotting options in the form of Plot attribute assignments (see below -for an example), then we could create a Plot and implement these -assignments before producing the graphical output as follows: - -c+ -\small -\begin{terminalv} -#include <stdio.h> -#define MAXCHARS 120 -FILE *stream; -char line[ MAXCHARS + 2 ]; -int base; - -... - -/* Create a Plot and define the default appearance of the graphical - output it will produce. */ -plot = astPlot( wcsinfo, gbox, pbox, - "Grid=1, Colour(grid)=2, Font(textlab)=3" ); - -/* Obtain the value of any Plot attributes we want to preserve. */ -base = astGetI( plot, "Base" ); - -/* Open the plot configuration file, if it exists. Read each line of - text and use it to set new Plot attribute values. Close the file - when done. */ -if ( stream = fopen( "plot.config", "r" ) ) { - while ( fgets( line, MAXCHARS + 2, stream ) ) astSet( plot, "%s", line ); - close( stream ); -} - -/* Restore any attribute values we are preserving. */ -astSetI( plot, "Base", base ); - -/* Produce the graphical output (e.g.). */ -astGrid( plot ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER LINE( 120 ) - INTEGER BASE - - ... - -* Create a Plot and define the default appearance of the graphical -* output it will produce. - PLOT = AST_PLOT( WCSINFO, GBOX, PBOX, - : 'Grid=1, Colour(grid)=2, Font(textlab)=3', - : STATUS ) - -* Obtain the value of any Plot attributes we want to preserve. - BASE = AST_GETI( PLOT, 'Base', STATUS ) - -* Open the plot configuration file, if it exists. - OPEN ( 1, FILE = 'plot.config', STATUS = 'OLD', ERR = 8 ) - -* Read each line of text and use it to set new Plot attribute -* values. Close the file when done. - 6 CONTINUE - READ ( 1, '(A)', END = 7 ) LINE - CALL AST_SET( PLOT, LINE, STATUS ) - GO TO 6 - 7 CLOSE ( 1 ) - 8 CONTINUE - -* Restore any attribute values we are preserving. - CALL AST_SETI( PLOT, 'Base', BASE, STATUS ) - -* Produce the graphical output (e.g.). - CALL AST_GRID( PLOT, STATUS ) -\end{terminalv} -\normalsize -f- - -Notice that we take care that the Plot's Base attribute is preserved -so that the user cannot change it. This is because graphical output -will not be produced successfully if the base Frame does not describe -the plotting surface to which we attached the Plot when we created it. - -The arrangement shown above allows the contents of the ``plot.config'' -file to control most aspects of the graphical output produced -(including the coordinate system used; the colour, line style, -thickness and font used for each component; the positioning of axes -and tick marks; the precision, format and positioning of labels; -\emph{etc.}) \emph{via} assignments of the form: - -\small -\begin{terminalv} -System=Galactic, Equinox = 2001 -Border = 1, Colour( border ) = 1 -Colour( grid ) = 2 -DrawAxes = 1 -Colour( axes ) = 3 -Digits = 8 -Labelling = Interior -\end{terminalv} -\normalsize - -For a more sophisticated interface, you could obviously perform -pre-processing on this input---for example, to translate words like -``red'', ``green'' and ``blue'' into colour indices, to permit -comments and blank lines, \emph{etc.} - -For a full list of the attributes that may be used to control the -appearance of graphical output, see the description of the Plot class -in \appref{ss:classdescriptions}. For a complete description of each -individual attribute (\emph{e.g.}\ those above), see the attribute's -entry in \appref{ss:attributedescriptions}. - -\cleardoublepage -\section{\label{ss:primer}An AST Object Primer} - -c+ -The AST library deals throughout with entities called Objects and a -basic understanding of how to handle these is needed before you can -use the library effectively. If you are already familiar with an -object-oriented language, such as C$++$, few of the concepts should -seem new to you. Be aware, however, that AST is designed to be used -\emph{via} fairly conventional C and Fortran interfaces, so some -things have to be done a little differently. -c- -f+ -The AST library deals throughout with entities called Objects and a -basic understanding of how to handle these is needed before you can -use the library effectively. If you are already familiar with an -object-oriented language, such as C$++$, few of the concepts should -seem new to you. Be aware, however, that AST is designed to be used -\emph{via} fairly conventional Fortran and C interfaces, so some -things have to be done a little differently. -f- - -c+ -If you are not already familiar with object-oriented programming, then -don't worry---we will not emphasise this aspect more than is necessary -and will not assume any background knowledge. Instead, this section -concentrates on presenting all the fundamental information you will -need, explaining how AST Objects behave and how to manipulate them -from conventional C programs. -c- -f+ -If you are not already familiar with object-oriented programming, then -don't worry---we will not emphasise this aspect more than is necessary -and will not assume any background knowledge. Instead, this section -concentrates on presenting all the fundamental information you will -need, explaining how AST Objects behave and how to manipulate them -from conventional Fortran programs. -f- - -If you like to read documents from cover to cover, then you can -consider this section as an introduction to the programming techniques -used in the rest of the document. Otherwise, you may prefer to skim -through it on a first reading and return to it later as reference -material. - -\subsection{AST Objects} - -An AST Object is an entity which is used to store information and -Objects come in various kinds, called \emph{classes}, according to the -sort of information they hold. Throughout this section, we will make -use of a simple Object belonging to the ``ZoomMap'' class to -illustrate many of the basic concepts. - -A ZoomMap is an Object that contains a recipe for converting -coordinates between two hypothetical coordinate systems. It does this -by multiplying all the coordinate values by a constant called the -\emph{Zoom factor}. A ZoomMap is a very simple Object which exists -mainly for use in examples. It allows us to illustrate the ways in -which Objects are manipulated and to introduce the concept of a -Mapping---a recipe for converting coordinates---which is fundamental -to the way the AST library works. - -\subsection{\label{ss:objectcreation}Object Creation and Pointers} - -Let us first consider how to create a ZoomMap. This is done very -simply as follows: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstZoomMap *zoommap; - -... - -zoommap = astZoomMap( 2, 5.0, "" ) -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER STATUS, ZOOMMAP - - STATUS = 0 - - ... - - ZOOMMAP = AST_ZOOMMAP( 2, 5.0D0, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The first step is to include the header file ``ast.h'' which declares -the interface to the AST library. We then declare a pointer of type -AstZoomMap$*$ to receive the result and invoke the function astZoomMap -to create the ZoomMap. The pattern is the same for all other classes -of AST Object---you simply prefix ``ast'' to the class name to obtain -the function that creates the Object and prefix ``Ast'' to obtain the -type of the returned pointer. -c- -f+ -The first step is to include the file AST\_PAR which defines the -interface to the AST library and, amongst other things, declares -AST\_ZOOMMAP to be an integer function. We then declare an integer -variable ZOOMMAP to receive the result and an integer STATUS variable -to hold the error status, which we initialise to zero. Next, we invoke -AST\_ZOOMMAP to create the ZoomMap. The pattern is the same for all -other classes of AST Object---you simply prefix ``AST\_'' to the class -name to obtain the function that creates the Object. -f- - -These functions are called \emph{constructor functions}, or simply -\emph{constructors} (you can find an individual description of all AST -functions in \appref{ss:functiondescriptions}) and the arguments -passed to the constructor are used to initialise the new Object. In -this case, we specify 2 as the number of coordinates (\emph{i.e.}\ we -are going to work in a 2-dimensional -c+ -space) and 5.0 as the Zoom factor to be applied. Note that this is a C -double value. We will return to the final argument, an empty string, -shortly (\secref{ss:attributeinitialisation}). -c- -f+ -space) and 5.0D0 as the Zoom factor to be applied. Note that this is a -Fortran double precision value. We will return to the final two -arguments, a blank string and the error status, shortly -(\secref{ss:attributeinitialisation} and \secref{ss:errordetection}). -f- - -c+ -The value returned by the constructor is termed an \emph{Object pointer} -or, in this case, a \emph{ZoomMap pointer} and is used to refer to the -Object. You perform all subsequent operations on the Object by -passing this pointer to other AST functions. -c- -f+ -The integer value returned by the constructor is termed an \emph{Object -pointer} or, in this case, a \emph{ZoomMap pointer}. This pointer is not -an Object itself, but is a value used to refer to the Object. You -should be careful not to modify any Object pointer yourself, as this -may render it invalid. Instead, you perform all subsequent operations -on the Object by passing this pointer to other AST routines. -f- - -\subsection{\label{ss:objecthierarchy}The Object Hierarchy} - -Now that we have created our first ZoomMap, let us examine how it -relates to other kinds of Object before investigating what we can do -with it. - -We have so far indicated that a ZoomMap is a kind of Object and have -also mentioned that it is a kind of Mapping as well. These statements -can be represented very simply using the following hierarchy: - -\small -\begin{terminalv} -Object - Mapping - ZoomMap -\end{terminalv} -\normalsize - -which is a way of stating that a ZoomMap is a special class of -Mapping, while a Mapping, in turn, is a special class of Object. This -is exactly like saying that an Oak is a special form of Tree, while a -Tree, in turn, is a special form of Plant. This may seem almost -trivial, but before you turn to read something less dull, be assured -that it is a very important idea to keep in mind in what follows. - -If we look at some of the other Objects used by the AST library, we -can see how these are all related in a similar way (don't worry about -what they do at this stage): -\label{ss:mappinghierarchy} - -\small -\begin{terminalv} -Object - Mapping - Frame - FrameSet - Plot - UnitMap - ZoomMap - Channel - FitsChan - XmlChan -\end{terminalv} -\normalsize - -Notice that there are several different types of Mapping available -(\emph{i.e.}\ there are classes of Object indented beneath the -``Mapping'' heading) and, in addition, other types of Object which are -not Mappings---Channels for instance (which are at the same -hierarchical level as Mappings). - -The most specialised Object we have shown here is the Plot (which we -will not discuss in detail until \secref{ss:plots}). As you can see, a -Plot is a FrameSet\ldots\ and a Frame\ldots\ and a Mapping\ldots\ and, -like everything else, ultimately an Object. - -What this means is that you can use a Plot not only for its own -specialised behaviour, but also whenever any of these other -less-specialised classes of Object is called for. The general rule is -that an Object of a particular class may substitute for any of the -classes appearing above it in this hierarchy. The Object is then said -to \emph{inherit} the behaviour of these higher classes. We can -therefore use our ZoomMap whenever a ZoomMap, a Mapping or an Object -is called for. - -Sometimes, this can lead to some spectacular short-cuts by avoiding -the need to break large Objects down in order to access their -components. With some practice and a little lateral thinking you -should soon be able to spot opportunities for this. - -You can find the full \emph{class hierarchy}, as this is called, for -the AST library in \appref{ss:classhierarchy} and you may need to -refer to it occasionally until you are familiar with the classes you -need to use. - -\subsection{\label{ss:displayingobjects}Displaying Objects} - -Let us now return to the ZoomMap that we created earlier -(\secref{ss:objectcreation}) and examine what it's made of. -c+ -There is a function for doing this, called astShow, which is provided -mainly for looking at Objects while you are debugging programs. -c- -f+ -There is a routine for doing this, called AST\_SHOW, which is provided -mainly for looking at Objects while you are debugging programs. -f- - -c+ -If you consult the description of astShow in -\appref{ss:functiondescriptions}, you will find that it takes a -pointer to an Object (of type AstObject$*$) as its argument. Although -we have only a ZoomMap pointer available, this is not a problem. If -you refer to the brief class hierarchy described above -(\secref{ss:mappinghierarchy}), you will see that a ZoomMap is an -Object, albeit a specialised one, so it inherits the properties of all -Objects and can be substituted wherever an Object is required. We can -therefore pass our ZoomMap pointer directly to astShow, as follows: -c- -f+ -If you consult the description of AST\_SHOW in -\appref{ss:functiondescriptions}, you will find that it takes a -pointer to an Object as its argument (in addition to the usual STATUS -argument). Although we have only a ZoomMap pointer available, -fortunately this is not a problem. If you refer to the brief class -hierarchy described above (\secref{ss:mappinghierarchy}), you will see -that a ZoomMap is an Object, albeit a specialised one, so it inherits -the properties of all Objects and can be substituted wherever an -Object is required. We can therefore pass our ZoomMap pointer -directly to AST\_SHOW, as follows: -f- - -c+ -\small -\begin{terminalv} -astShow( zoommap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SHOW( ZOOMMAP, STATUS ) -\end{terminalv} -\normalsize -f- - -The output from this will appear on the standard output stream and -should look like the following: - -\small -\begin{terminalv} -Begin ZoomMap - Nin = 2 -IsA Mapping - Zoom = 5 -End ZoomMap -\end{terminalv} -\normalsize - -Here, the ``Begin'' and ``End'' lines mark the beginning and end of -the ZoomMap, while the values 2 and 5 are simply the values we -supplied to initialise it (\secref{ss:objectcreation}). These have -been given simple names to make them easy to refer to. - -The line in the middle which says ``IsA~Mapping'' is a dividing line -between the two values. It indicates that the ``Nin'' value is a -property shared by all Mappings, so the ZoomMap has inherited this -from its \emph{parent class} (Mapping). The ``Zoom'' value, however, -is specific to a ZoomMap and isn't shared by other kinds of Mappings. - -\subsection{\label{ss:gettingattributes}Getting Attribute Values} - -We saw above (\secref{ss:displayingobjects}) how to display the -internal values of an Object, but what about accessing these values -from a program? Not all internal Object values are accessible in this -way, but many are. Those that are, are called \emph{attributes}. A -description of all the attributes used by the AST library can be found -in \appref{ss:attributedescriptions}. - -c+ -Attributes come in several data types (character string, integer, -boolean and floating point) and there is a standard way of obtaining -their values. As an example, consider obtaining the value of the Nin -attribute for the ZoomMap created earlier. This could be done as -follows: -c- -f+ -Attributes come in several data types (character string, integer, -boolean and floating point) and there is a standard way of obtaining -their values. As an example, consider obtaining the value of the Nin -attribute for the ZoomMap created earlier. This could be done as -follows: -f- - -c+ -\small -\begin{terminalv} -int nin; - -... - -nin = astGetI( zoommap, "Nin" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER NIN - - ... - - NIN = AST_GETI( ZOOMMAP, 'Nin', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, the function astGetI is used to extract the attribute value by -giving it the ZoomMap pointer and the attribute name (attribute names -are not case sensitive, but we have used consistent capitalisation in -this document in order to identify them). Remember to use the -``ast.h'' header file to include the function prototype. -c- -f+ -Here, the integer function AST\_GETI is used to extract the attribute -value by giving it the ZoomMap pointer and the attribute name -(attribute names are not case sensitive, but we have used consistent -capitalisation in this document in order to identify them). Remember -to use the AST\_PAR include file to save having to declare AST\_GETI -as integer yourself. -f- - -c+ -If we had wanted the value of the Zoom attribute, we would probably -have used astGetD instead, this being a double version of the same -function, for example: -c- -f+ -If we had wanted the value of the Zoom attribute, we would probably -have used AST\_GETD instead, this being a double precision version of -the same function, for example: -f- - -c+ -\small -\begin{terminalv} -double zoom; - -... - -zoom = astGetD( zoommap, "Zoom" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION ZOOM - - ... - - ZOOM = AST_GETD( ZOOMMAP, 'Zoom', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -However, we could equally well have read the Nin value as double, or -the Zoom value as an integer, or whatever we wanted. -c- -f+ -However, we could equally well have read the Nin value as double -precision, or the Zoom value as an integer, or whatever we wanted. -f- - -c+ -The data type you want returned is specified simply by replacing the -final character of the astGetX function name with C~(character -string), D~(double), F~(float), I~(int) or L~(long). If possible, the -value is converted to the type you want. If not, an error message will -result. Note that all floating point values are stored internally as -double, and all integer values as int. Boolean values are also stored -as integers, but only take the values 1 and 0 (for true/false). -c- -f+ -The data type you want returned is specified simply by replacing the -final character of the AST\_GETx function name with C~(character), -D~(double precision), I~(integer), L~(logical) or R~(real). If -possible, the value is converted to the type you want. If not, an -error message will result. In converting from integer to logical, zero -is regarded as .FALSE.\ and non-zero as .TRUE.. Note that all floating -point values are stored internally as double precision. Boolean values -are stored as integers, but only take the values 1 and 0 (for -true/false). -f- - -\subsection{\label{ss:settingattributes}Setting Attribute Values} - -Some attribute values are read-only and cannot be altered after an -Object has been created. The Nin attribute of a ZoomMap (describing -the number of coordinates) is like this. It is defined when the -ZoomMap is created, but cannot then be altered. - -Other attributes, however, can be modified whenever you want. A -ZoomMap's Zoom attribute is like this. If we wanted to change it, this -could be done simply as follows: - -c+ -\small -\begin{terminalv} -astSetD( zoommap, "Zoom", 99.6 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SETD( ZOOMMAP, 'Zoom', 99.6D0, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -which sets the value to 99.6. As when getting an attribute value -(\secref{ss:gettingattributes}), you have a choice of which data type -you will use to supply the new value. For instance, you could use an -integer value, as in: -c- -f+ -which sets the value to 99.6 (double precision). As when getting an -attribute value (\secref{ss:gettingattributes}), you have a choice of -which data type you will use to supply the new value. For instance, -you could use an integer value, as in: -f- - -c+ -\small -\begin{terminalv} -astSetI( zoommap, "Zoom", 99 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SETI( ZOOMMAP, 'Zoom', 99, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -and the necessary data conversion would occur. You specify the data -type you want to supply simply by replacing the final character of the -astSetX function name with C~(character string), D~(double), -F~(float), I~(int) or L~(long). Setting a boolean attribute to any -non-zero integer causes it to take the value 1. -c- -f+ -and the necessary data conversion would occur. You specify the data -type you want to supply simply by replacing the final character of the -AST\_SETx routine name with C~(character), D~(double precision), -I~(integer), L~(logical) or R~(real). Setting a boolean attribute to -any non-zero integer causes it to take the value 1. -f- - -c+ -An alternative way of setting attribute values for Objects is to use -the astSet function (\emph{i.e.}\ with no final character specifying a -data type). In this case, you supply the attribute values in a -character string. The big advantage of this method is that you can -assign values to several attributes at once, separating them with -commas. This also reads more naturally in programs. For example: -c- -f+ -An alternative way of setting attribute values for Objects is to use -the AST\_SET routine (\emph{i.e.}\ with no final character specifying -a data type). In this case, you supply the attribute values in a -character string. The big advantage of this method is that you can -assign values to several attributes at once, separating them with -commas. This also reads more naturally in programs. For example: -f- - -c+ -\small -\begin{terminalv} -astSet( zoommap, "Zoom=99.6, Report=1" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( ZOOMMAP, 'Zoom=99.6, Report=1', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -would set values for both the Zoom attribute and the Report attribute -(about which more shortly---\secref{ss:transforming}). You don't really -have to worry about data types with this method, as any character -representation will do. Note, when using astSet, a -literal comma may be included in an attribute value by enclosed the value in -quotation marks: -\small -\begin{terminalv} - astSet( skyframe, 'SkyRef="12:13:32,-23:12:44"' ); -\end{terminalv} -\normalsize -c- -f+ -would set values for both the Zoom attribute and the Report attribute -(about which more shortly---\secref{ss:transforming}). You don't really -have to worry about data types with this method, as any character -representation will do (although you must use 0/1 instead of -.TRUE./.FALSE., which are not supported). Note, when using AST\_SET, a -literal comma may be included in an attribute value by enclosed the value in -quotation marks: -\small -\begin{terminalv} - CALL AST_SET( SKYFRAME, 'SkyRef="12:13:32,-23:12:44"', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Another attractive feature of astSet is that you can build the -character string which contains the attribute settings in the same way -as when using the C run time library ``printf'' function. This is most -useful when the values you want to set are held in other -variables. For example: - -\small -\begin{terminalv} -double zoom = 99.6; -int report = 1; - -... - -astSet( zoommap, "Zoom=%g, Report=%d", zoom, report ); -\end{terminalv} -\normalsize - -would replace the ``\%'' conversion specifications by the values -supplied as additional arguments. Any number of additional arguments -may be supplied and the formatting rules are exactly the same as for -the C ``printf'' family of functions. This is a very flexible -technique, but does contain one pitfall: - -\begin{quote} -\textbf{Pitfall.} The default precision used by ``printf'' (and astSet) -for floating point values is only 6 decimal digits, corresponding -approximately to float on most machines, whereas the AST library -stores such values internally as doubles. You should be careful to -specify a larger precision (such as DBL\_DIG, as defined in -$<$float.h$>$) when necessary. For example: - -\small -\begin{terminalv} -#include <float.h> - -... - -astSet( zoommap, "Zoom=%.*g", DBL_DIG, double_value ); -\end{terminalv} -\normalsize -\end{quote} - -Substituted strings may contain commas and this is a useful way of -assigning such strings as attribute values without the comma being -interpreted as an assignment separator, for example: - -\small -\begin{terminalv} -astSet( object, "Attribute=%s", "A string, containing a comma" ); -\end{terminalv} -\normalsize - -This is equivalent to using astSetC and one of these two methods -should always be used when assigning string attribute values which -might potentially contain a comma (\emph{e.g.}\ strings obtained from -an external source). However, you should not attempt to use astSet to -substitute strings that contain newline characters, since these are -used internally as separators between adjacent attribute assignments. -c- -\label{ss:attributeinitialisation} - -c+ -Finally, a very convenient way of setting attribute values is to do so -at the same time as you create an Object. Every Object constructor -function has a final character string argument which allows you to do -this. Although you can simply supply an empty string, it is an ideal -opportunity to initialise the Object to have just the attributes you -want. For example, we might have created our original ZoomMap with: -c- -f+ -Finally, a very convenient way of setting attribute values is to do so -at the same time as you create an Object. Every Object constructor -function has a penultimate character argument which allows you to do -this. Although you can simply leave this blank, it is an ideal -opportunity to initialise the Object to have just the attributes you -want. For example, we might have created our original ZoomMap with: -f- - -c+ -\small -\begin{terminalv} -zoommap = astZoomMap( 2, 5.0, "Report=1" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - ZOOMMAP = AST_ZOOMMAP( 2, 5.0D0, 'Report=1', STATUS ) -\end{terminalv} -\normalsize -f- - -and it would then start life with its Report attribute set to 1. -c+ -The ``printf''-style substitution described above may also be used -here. -c- - -\subsection{\label{ss:defaultingattributes}Testing, Clearing and Defaulting Attributes} - -c+ -You can use the astGetX family of functions -(\secref{ss:gettingattributes}) to get a value for any Object attribute -at any time, regardless of whether a value has previously been set for -it. If no value has been set, the AST library will generate a suitable -default value. -c- -f+ -You can use the AST\_GETx family of routines -(\secref{ss:gettingattributes}) to get a value for any Object attribute -at any time, regardless of whether a value has previously been set for -it. If no value has been set, the AST library will generate a suitable -default value. -f- - -Often, the default value of an attribute will not simply be trivial -(zero or blank) but may involve considerable processing to -calculate. Wherever possible, defaults are designed to be real-life, -sensible values that convey information about the state of the -Object. In particular, they may often be based on the values of other -attributes, so their values may change in response to changes in these -other attributes. The ZoomMap class that we have studied so far is a -little too simple to show this behaviour, but we will meet it later -on. - -An attribute that returns a default value in this way is said to be -\emph{un-set}. Conversely, once an explicit value has been assigned to -an attribute, it becomes \emph{set} and will always return precisely -that value, never a default. - -c+ -The distinction between set and un-set attributes is important and -affects the behaviour of several key routines in the AST library. You -can test if an attribute is set using the function astTest, which -returns a boolean (integer) result, as in: -c- -f+ -The distinction between set and un-set attributes is important and -affects the behaviour of several key routines in the AST library. You -can test if an attribute is set using the logical function AST\_TEST, -as in: -f- - -c+ -\small -\begin{terminalv} -if ( astTest( zoommap, "Report" ) ) { - <the Report attribute is set> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - IF ( AST_TEST( ZOOMMAP, 'Report', STATUS ) ) THEN - <the Report attribute is set> - END IF -\end{terminalv} -\normalsize -f- - -f+ -(as usual, remember to include the AST\_PAR file to declare the -function as LOGICAL, or make this declaration yourself). -f- - -c+ -Once an attribute is set, you can return it to its un-set state using -astClear. The effect is as if it had never been set in the first -place. For example: -c- -f+ -Once an attribute is set, you can return it to its un-set state using -AST\_CLEAR. The effect is as if it had never been set in the first -place. For example: -f- - -c+ -\small -\begin{terminalv} -astClear( zoommap, "Report" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_CLEAR( ZOOMMAP, 'Report', STATUS ) -\end{terminalv} -\normalsize -f- - -would ensure that the default value of the Report attribute is used -subsequently. - -%\subsection{TBW--Handling Character Attributes} - -\subsection{\label{ss:transforming}Transforming Coordinates} - -We now have the necessary apparatus to start using our ZoomMap to show -what it is really for. Here, we will also encounter a routine that is -a little more fussy about the type of pointer it will accept. - -The purpose of a ZoomMap is to multiply coordinates by a constant zoom -factor. To witness this in action, we will first set the Report -attribute for our ZoomMap to a non-zero value: - -c+ -\small -\begin{terminalv} -astSet( zoommap, "Report=1" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( ZOOMMAP, 'Report=1', STATUS ) -\end{terminalv} -\normalsize -f- - -This boolean (integer) attribute, which is present in all Mappings -(and a ZoomMap is a Mapping), causes the automatic display of all -coordinate values that the Mapping converts. It is not a good idea to -leave this feature turned on in a finished program, but it can save a -lot of work during debugging. - -c+ -Our next step is to set up some coordinates for the ZoomMap to work -on, using two arrays ``xin'' and ``yin'', and two arrays to receive -the transformed coordinates, ``xout'' and ``yout''. Note that these -are arrays of double, as are all coordinate data processed by the AST -library: -c- -f+ -Our next step is to set up some coordinates for the ZoomMap to work -on, using two arrays XIN and YIN, and two arrays to receive the -transformed coordinates, XOUT and YOUT. Note that these arrays are -double precision, as are all coordinate data processed by the AST -library: -f- - -c+ -\small -\begin{terminalv} -double xin[ 10 ] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }; -double yin[ 10 ] = { 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0 }; -double xout[ 10 ]; -double yout[ 10 ]; -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION XIN( 10 ), YIN( 10 ), XOUT( 10 ), YOUT( 10 ) - DATA XIN / 0D0, 1D0, 2D0, 3D0, 4D0, 5D0, 6D0, 7D0, 8D0, 9D0 / - DATA YIN / 0D0, 2D0, 4D0, 6D0, 8D0, 10D0, 12D0, 14D0, 16D0, 18D0 / -\end{terminalv} -\normalsize -f- - -c+ -We will now use the function astTran2 to transform the input -coordinates. This is the most commonly-used (2-dimensional) coordinate -transformation function. If you look at its description in -\appref{ss:functiondescriptions}, you will see that it requires a -pointer to a Mapping, so we cannot supply just any old Object pointer, -as we could with the functions discussed previously. If we passed it a -pointer to an inappropriate Object, an error message would result. -c- -f+ -We will now use the routine AST\_TRAN2 to transform the input -coordinates. This is the most commonly-used (2-dimensional) coordinate -transformation routine. If you look at its description in -\appref{ss:functiondescriptions}, you will see that it requires a -pointer to a Mapping, so we cannot supply just any old Object pointer, -as we could with the routines discussed previously. If we passed it a -pointer to an inappropriate Object, an error message would result. -f- - -c+ -Fortunately, a ZoomMap is a Mapping (\appref{ss:classhierarchy}), so we -can use it with astTran2 to transform our coordinates, as follows: -c- -f+ -Fortunately, a ZoomMap is a Mapping (\appref{ss:classhierarchy}), so we -can use it with AST\_TRAN2 to transform our coordinates, as follows: -f- - -c+ -\small -\begin{terminalv} -astTran2( zoommap, 10, xin, yin, 1, xout, yout ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_TRAN2( ZOOMMAP, 10, XIN, YIN, .TRUE., XOUT, YOUT, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, 10 is the number of points we want to transform and the fifth -argument value of 1 indicates that we want to transform in the -\emph{forward} direction (from input to output). -c- -f+ -Here, 10 is the number of points we want to transform and the fifth -argument value of .TRUE.\ indicates that we want to transform in the -\emph{forward} direction (from input to output). -f- - -Because our ZoomMap's Report attribute is set to 1, this will cause -the effects of the ZoomMap on the coordinates to be displayed on the -standard output stream: - -\small -\begin{terminalv} -(0, 0) --> (0, 0) -(1, 2) --> (5, 10) -(2, 4) --> (10, 20) -(3, 6) --> (15, 30) -(4, 8) --> (20, 40) -(5, 10) --> (25, 50) -(6, 12) --> (30, 60) -(7, 14) --> (35, 70) -(8, 16) --> (40, 80) -(9, 18) --> (45, 90) -\end{terminalv} -\normalsize - -c+ -This shows the coordinate values of each point both before and after -the ZoomMap is applied. You can see that each coordinate value has -been multiplied by the factor 5 determined by the Zoom attribute -value. The transformed coordinates are now stored in the ``xout'' and -``yout'' arrays. -c- -f+ -This shows the coordinate values of each point both before and after -the ZoomMap is applied. You can see that each coordinate value has -been multiplied by the factor 5 determined by the Zoom attribute -value. The transformed coordinates are now stored in the XOUT and YOUT -arrays. -f- - -c+ -If we wanted to transform in the opposite direction, we need simply -change the fifth argument of astTran2 from 1 to 0. We can also feed -the output coordinates from the above back into the function: -c- -f+ -If we wanted to transform in the opposite direction, we need simply -change the fifth argument of AST\_TRAN2 from .TRUE. to .FALSE.. We can -also feed the output coordinates from the above back into the routine: -f- - -c+ -\small -\begin{terminalv} -astTran2( zoommap, 10, xout, yout, 0, xin, yin ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_TRAN2( ZOOMMAP, 10, XOUT, YOUT, .FALSE., XIN, YIN, STATUS ) -\end{terminalv} -\normalsize -f- - -The output would then look like: - -\small -\begin{terminalv} -(0, 0) --> (0, 0) -(5, 10) --> (1, 2) -(10, 20) --> (2, 4) -(15, 30) --> (3, 6) -(20, 40) --> (4, 8) -(25, 50) --> (5, 10) -(30, 60) --> (6, 12) -(35, 70) --> (7, 14) -(40, 80) --> (8, 16) -(45, 90) --> (9, 18) -\end{terminalv} -\normalsize - -This is termed the \emph{inverse} transformation (we have converted -from output to input) and you can see that the original coordinates -have been recovered by dividing by the Zoom factor. - -\subsection{\label{ss:annullingpointers}Managing Object Pointers} - -So far, we have looked at creating Objects and using them in various -simple ways but have not yet considered how to get rid of them again. - -c+ -Every Object consumes various computer resources (principally memory) -and should be disposed of when it is no longer required, so as to free -up these resources. One way of doing this (not necessarily the -best---\secref{ss:contexts}) is to \emph{annul} each Object pointer once -you have finished with it, using astAnnul. For example: -c- -f+ -Every Object consumes various computer resources (principally memory) -and should be disposed of when it is no longer required, so as to free -up these resources. One way of doing this (not necessarily the -best---\secref{ss:contexts}) is to \emph{annul} each Object pointer once -you have finished with it, using AST\_ANNUL. For example: -f- - -c+ -\small -\begin{terminalv} -zoommap = astAnnul( zoommap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_ANNUL( ZOOMMAP, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This indicates that you have finished with the pointer. Since astAnnul -always returns the null value AST\_\_NULL (as defined in ``ast.h''), -the recommended way of using it, as here, is to assign the returned -value to the pointer being annulled. This ensures that any attempt to -use the pointer again will generate an error message. -c- -f+ -This indicates that you have finished with the pointer and sets it to -the null value AST\_\_NULL (as defined in the AST\_PAR include file), -so that any attempt to use it again will generate an error message. -f- - -c+ -In general, this process may not delete the Object, because there may -still be other pointers associated with it. However, each Object -maintains a count of the number of pointers associated with it and -will be deleted if you annul the final pointer. Using astAnnul -consistently will therefore ensure that all Objects are disposed of at -the correct time. You can determine how many pointers are associated -with an Object by examining its (read-only) RefCount attribute. -c- -f+ -In general, this process may not delete the Object, because there may -still be other pointers associated with it. However, each Object -maintains a count of the number of pointers associated with it and -will be deleted if you annul the final pointer. Using AST\_ANNUL -consistently will therefore ensure that all Objects are disposed of at -the correct time. You can determine how many pointers are associated -with an Object by examining its (read-only) RefCount attribute. -f- - -c+ -\subsection{\label{ss:contexts}AST Pointer Contexts---Begin and End} -c- -f+ -\subsection{\label{ss:contexts}AST Pointer Contexts---Begin and End} -f- - -c+ -The use of astAnnul (\secref{ss:annullingpointers}) is not completely -foolproof, however. Consider the following: -c- -f+ -The use of AST\_ANNUL (\secref{ss:annullingpointers}) is not completely -foolproof, however. Consider the following: -f- - -c+ -\small -\begin{terminalv} -astShow( astZoomMap( 2, 5.0, "" ) ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SHOW( AST_ZOOMMAP( 2, 5.ODO, ' ', STATUS ), STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This creates a ZoomMap and displays it on standard output -(\secref{ss:displayingobjects}). Using function invocations as -arguments to other functions in this way is very convenient because it -avoids the need for intermediate pointer variables. However, the -pointer generated by astZoomMap is still active, and since we have not -stored its value, we cannot use astAnnul to annul it. The ZoomMap will -therefore stay around until the end of the program. -c- -f+ -This creates a ZoomMap and displays it on standard output -(\secref{ss:displayingobjects}). Using function invocations as -arguments to other routines in this way is very convenient because it -avoids the need for intermediate pointer variables. However, the -pointer generated by AST\_ZOOMMAP is still active, and since we have -not stored its value, we cannot use AST\_ANNUL to annul it. The -ZoomMap will therefore stay around until the end of the program. -f- - -c+ -A simple way to avoid this problem is to enclose all use of AST -functions between invocations of astBegin and astEnd, for example: -c- -f+ -A simple way to avoid this problem is to enclose all use of AST -routines between calls to AST\_BEGIN and AST\_END, for example: -f- - -c+ -\small -\begin{terminalv} -astBegin; -astShow( astZoomMap( 2, 5.0, "" ) ); -astEnd; -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_BEGIN( STATUS ) - CALL AST_SHOW( AST_ZOOMMAP( 2, 5.ODO, ' ', STATUS ), STATUS ) - CALL AST_END( STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -When the expansion of astEnd (which is a macro) executes, every Object -pointer created since the previous use of astBegin (also a macro) is -automatically annulled and any Objects left without pointers are -deleted. This provides a simple solution to managing Objects and their -pointers, and allows you to create Objects very freely without needing -to keep detailed track of each one. Because this is so convenient, we -implicitly assume that astBegin and astEnd are used in most of the -examples given in this document. Pointer management is not generally -shown explicitly unless it is particularly relevant to the point being -illustrated. -c- -f+ -When the AST\_END call executes, every Object pointer created since -the previous AST\_BEGIN call is automatically annulled and any Objects -left without pointers are deleted. This provides a simple solution to -managing Objects and their pointers, and allows you to create Objects -very freely without needing to keep detailed track of each one. -Because this is so convenient, we implicitly assume that AST\_BEGIN -and AST\_END are used in most of the examples given in this document. -Pointer management is not generally shown explicitly unless it is -particularly relevant to the point being illustrated. -f- - -c+ -If necessary, astBegin and astEnd may be nested, like blocks delimited -by ``\{\ldots\}'' in C, to define a series of AST pointer -contexts. Each use of astEnd will then annul only those Object -pointers created since the matching use of astBegin. -c- -f+ -If necessary, calls to AST\_BEGIN and AST\_END may be nested, like -IF\ldots ENDIF blocks in Fortran, to define a series of AST pointer -contexts. Each call to AST\_END will then annul only those Object -pointers created since the matching call to AST\_BEGIN. -f- - -\subsection{Exporting, Importing and Exempting AST Pointers} -c+ -The astExport function allows you to export particular pointers from -one AST context (\secref{ss:contexts}) to the next outer one, as -follows: -c- -f+ -The AST\_EXPORT routine allows you to export particular pointers from -one AST context (\secref{ss:contexts}) to the next outer one, as -follows: -f- - -c+ -\small -\begin{terminalv} -astExport( zoommap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_EXPORT( ZOOMMAP, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This would identify the pointer stored in ``zoommap'' as being required -after the end of the current AST context. It causes any pointers -nominated in this way to survive the next use of astEnd (but only one -such use) unscathed, so that they are available to the next outer -context. This facility is not needed often, but is invaluable when -the purpose of your astBegin\ldots astEnd block is basically to -generate an Object pointer. Without this, there is no way of getting -that pointer out. -c- -f+ -This would identify the pointer stored in ZOOMMAP as being required after -the end of the current AST context. It causes any pointers nominated -in this way to survive the next call to AST\_END (but only one such -call) unscathed, so that they are available to the next outer context. -This facility is not needed often, but is invaluable when the purpose -of your AST\_BEGIN\ldots AST\_END block is basically to generate an -Object pointer. Without this, there is no way of getting that pointer -out. -f- - -f+ -The AST\_IMPORT routine can be used in a similar manner to import a -pointer into the current context, so that it is deleted when the current -context is closed using AST\_END. -f- - -c+ -The astImport routine can be used in a similar manner to import a -pointer into the current context, so that it is deleted when the current -context is closed using astEnd. -c- - -c+ -Sometimes, you may also want to exempt a pointer from all the effects -of AST contexts. You should not need to do this often, but it will -prove essential if you ever need to write a library of functions that -stores AST pointers as part of its own internal data. Without some -form of exemption, the caller of your routines could cause the -pointers you have stored to be annulled---thus corrupting your -internal data---simply by using astEnd. To avoid this, you should use -astExempt on each pointer that you store, for example: -c- -f+ -Sometimes, you may also want to exempt a pointer from all the effects -of AST contexts. You should not need to do this often, but it will -prove essential if you ever need to write a library of routines that -stores AST pointers as part of its own internal data. Without some -form of exemption, the caller of your routines could cause the -pointers you have stored to be annulled---thus corrupting your -internal data---simply by using AST\_END. To avoid this, you should -use AST\_EXEMPT on each pointer that you store, for example: -f- - -c+ -\small -\begin{terminalv} -astExempt( zoommap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_EXEMPT( ZOOMMAP, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This will prevent the pointer being affected by any subsequent use of -astEnd. Of course, it then becomes your responsibility to annul this -pointer (using astAnnul) when it is no longer required. -c- -f+ -This will prevent the pointer being affected by any subsequent use of -AST\_END. Of course, it then becomes your responsibility to annul this -pointer (using AST\_ANNUL) when it is no longer required. -f- - - -c+ -\subsection{AST Objects within Multi-threaded Applications} - -When the AST library is built from source, the build process checks to -see if the POSIX threads library (``\texttt{pthreads}'') is available. If so, -appropriate \texttt{pthreads} calls are inserted into the AST source code to -ensure that AST is thread-safe, and the AST\_\_THREADSAFE macro (defined -in the ``ast.h'' header file) is set to ``\texttt{1}''. If the \texttt{pthreads} -library cannot be found when AST is built, a working version of the AST -library will still be created, but it will not be thread-safe. In this -case the AST\_\_THREADSAFE macro will be set to ``\texttt{0}'' in ast.h. The -rest of this section assumes that the thread-safe version of AST is being -used. - -Note, some AST functions call externally specified functions (\emph{e.g.} -the source and sink functions used by the Channel class or the graphics -primitives functions used by the Plot class). AST does not know whether -such functions are thread-safe or not. For this reason, invocations of these -functions within a multi-threaded environment are serialised using a mutex -in order to avoid two or more threads executing an external function -simultaneously. - -If an application uses more than one thread, the possibility arises that -an Object created by one thread may be accessed by another thread, potentially -simultaneously. If any of the threads modifies any aspect of the Object, -this could lead to serious problems within the other threads. For this -reason, some restrictions are placed on how Objects can be used in a -multi-threaded application. - -\subsubsection{Locking AST Objects for Exclusive Use} -The basic restriction is that a thread can only access Objects that it -has previously locked for its own exclusive use. If a thread attempts to -access any Object that it has not locked, an error is reported. - -The astAnnul function is the one exception to this restriction. Pointers -for Objects not currently locked by the calling thread can be annulled -succesfully using astAnnul. This means that a thread that has finished -with an Object pointer can unlock the Object by passing the pointer to -astUnlock (so that other threads can use the Object via their own cloned -pointers), and can then annul the pointer using astAnnul. Note, however, -that an error will be reported by astAnnul if the supplied pointer has -been locked by another thread using astLock. - -When an Object is created, it is initially locked by the calling thread. -Therefore a thread does not need to lock an Object explicitly if it was -created in the same thread. - -If the Object pointer is then passed to another thread, the first thread -must unlock the Object using astUnlock and the second thread must then lock -it using astLock. - -If a thread attempts to lock an Object that is already locked by another -thread, it can choose to report an error immediately or to wait until the -Object is available. - -The astThread function can be used to determine whether an Object is -locked by the running thread, locked by another thread, or unlocked. - -If two or more threads need simultaneous access to an Object, a deep copy -of the Object should be taken for each thread, using astCopy, and then -the copies should be unlocked and passed to the othe threads, which -should then lock them. Note, if a thread modifies the Object, the -modification will have no effect on the other threads, because the Object -copies are independent of each other. - -\subsubsection{AST Pointer Contexts} - -Each thread maintains its own set of nested AST contexts, so when astEnd -is called, only Objects that are locked by the current thread will -be annulled. - -If an Object is unlocked by a thread using astUnlock, it is exempted from -context handling so that subsequent invocations of astEnd will not cause it -to be annulled (this is similar to using astExempt on the Object). When the -Object is subsequently locked by another thread using astLock, it will be -imported into the context that was active when astLock was called. - -c- - - -\subsection{\label{ss:copyingobjects}Copying Objects} - -The AST library makes extensive use of pointers, not only for -accessing Objects directly, but also as a means of storing Objects -inside other Objects (a number of classes of Object are designed to -hold collections of other Objects). Rather than copy an Object in its -entirety, a pointer to the interior Object is simply stored in the -enclosing Object. - -This means that Objects may frequently not be completely independent -of each other because, for instance, they both contain pointers to the -same sub-Object. In this situation, changing one Object (say assigning -an attribute value) may affect the other one \emph{via} the common -Object. - -c+ -It is difficult to describe all cases where this may happen, so you -should always be alert to the possibility. Fortunately, there is a -simple solution. If you require two Objects to be independent, then -simply use astCopy to make a copy of one, \emph{e.g.}: -c- -f+ -It is difficult to describe all cases where this may happen, so you -should always be alert to the possibility. Fortunately, there is a -simple solution. If you require two Objects to be independent, then -simply use AST\_COPY to make a copy of one, \emph{e.g.}: -f- - -c+ -\small -\begin{terminalv} -AstZoomMap *zoommap1, *zoommap2; - -... - -zoommap2 = astCopy( zoommap1 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER ZOOMMAP1, ZOOMMAP2 - - ... - - ZOOMMAP2 = AST_COPY( ZOOMMAP1, STATUS ) -\end{terminalv} -\normalsize -f- - -This process will create a true copy of any Object and return a -pointer to the copy. This copy will not contain any pointers to any -component of the original Object (everything is duplicated), so you -can then modify it safely, without fear of affecting either the -original or any other Object. - -%\subsection{TBW - Inheritance} - -c+ -\subsection{C Pointer Types} - -At this point it is necessary to confess to a small amount of -deception. So far, we have been passing Object pointers to AST -functions in order to perform operations on those Objects. In fact, -however, what we were using were not true C functions at all, but -merely macros which invoke a related set of hidden functions with -essentially the same arguments. In practical terms, this makes very -little difference to how you use the functions, as we will continue to -call them.\footnote{About the only difference is that you cannot store -a pointer to an AST ``function'' in a variable and use the variable's -value to invoke that function again later.} - -The reason for this deception has to do with the rules for data typing -in C. Recall that most AST functions can be used to process Objects -from a range of different classes (\secref{ss:objecthierarchy}). In C, -this means passing different pointer types to the same function and -most C compilers will not permit this (at least, not without -grumbling) because it usually indicates a programming error. In AST, -however, it is perfectly safe if done properly. Some way is therefore -needed of circumventing the normal compiler checking. - -The normal way of doing this in C is with a cast. This approach -quickly becomes cumbersome, however, so we have adopted the strategy -of wrapping each function in a macro which applies the appropriate -cast for you. This means that you can pass pointers of any type to any -AST function. For example, in passing a ZoomMap pointer to astShow: - -\small -\begin{terminalv} -AstZoomMap *zoommap; - -... - -zoommap = astZoomMap( 2, 5.0, "" ); -astShow( zoommap ); -\end{terminalv} -\normalsize - -we are exploiting this mechanism to avoid a compiler warning, because -the notional type of astShow's parameter is AstObject$*$ (not -AstZoomMap$*$). - -We must still guard against programming errors, however, so every -pointer's type is checked by the enclosing macro immediately before -any AST function executes. This allows pointer mis-matches (in the -more liberal AST sense---\emph{i.e.}\ taking account of the class -hierarchy, rather than the stricter C sense) to be detected at -run-time and a suitable error message will be reported. This message -should also identify the line where the error occurs. - -A similar strategy is used when pointers are returned by AST functions -(\emph{i.e.}\ as the function result). In this case the pointer is -cast to void$*$, although we retain the notional pointer type in the -function's documentation -(\emph{e.g.}\ \appref{ss:functiondescriptions}). This allows you to -assign function results to pointer variables without using an explicit -cast. For example, the astRead function returns an Object pointer, but -might be used to read (say) a ZoomMap as follows: - -\small -\begin{terminalv} -AstChannel *channel; -AstZoomMap *zoommap; - -... - -zoommap = astRead( channel ); -\end{terminalv} -\normalsize - -Strictly, there is a C pointer mis-match here, but it is ignored -because the operation makes perfect sense to AST. - -\textbf{There is an important exception to this, however, in that -constructor functions always return strongly-typed pointers.} What -we mean by this is that the returned pointer is never implicitly cast -to void$*$. You must therefore match pointer types when you initially -create an Object using its constructor, such as in the following: - -\small -\begin{terminalv} -AstZoomMap *zoommap; - -... - -zoommap = astZoomMap( 2, 5.0, "" ); -\end{terminalv} -\normalsize - -If the variable receiving the pointer is of a different type, an -appropriate cast should be used, as in: - -\small -\begin{terminalv} -AstMapping *mapping; - -... - -mapping = (AstMapping *) astZoomMap( 2, 5.0, "" ); -\end{terminalv} -\normalsize - -This is an encouragement for you to declare your pointer types -consistently, since this is of great benefit to anyone trying to -understand your software. - -Finally, we should also make one more small confession---AST pointers -are not really pointers at all. Although they behave like pointers, -the actual ``values'' stored are not the addresses of C data -structures. This means that you cannot de-reference an AST pointer to -examine the data within (although you can use astShow -instead---\secref{ss:displayingobjects}). This is necessary so that AST -pointers can be made unique even although several of them might -reference the same Object. -c- - -\subsection{\label{ss:errordetection}Error Detection} - -c+ -If an error occurs in an AST function (for example, if you supply an -invalid argument, such as a pointer to the wrong class of Object), an -error message will be written to the standard error stream and the -function will immediately return. -c- -f+ -If an error occurs in an AST routine (for example, if you supply an -invalid argument, such as a pointer to the wrong class of Object), an -error message will be written to the standard error stream and the -function will immediately return. -f- - -c+ -To indicate than an error has occurred, an AST \emph{error status} -value is used. This integer value is stored internally by AST and is -initially clear (\emph{i.e.}\ set to zero\footnote{We will assume -throughout that the ``OK'' value is zero, as it currently is. However, -a different value could, in principle, be used if the environment in -which AST is running requires it. This is why a simple interface is -provided to isolate you from the actual value of the error status.} -to indicate no error). If an error occurs, it becomes set to a -different \emph{error value}, which allows you to detect the error, as -follows: -c- -f+ -To indicate that an error has occurred, each AST routine that can -potentially fail has a final integer \emph{error status} argument -called STATUS. This is both an input and an output argument. -Normally, you should declare a single error status variable and pass -it as the STATUS argument to every AST routine you invoke. This -variable must initially be cleared (\emph{i.e.}\ set to -zero\footnote{We will assume throughout that the ``OK'' value is zero, -as it currently is. However, a different value could, in principle, be -used if the environment in which AST is running requires it. To allow -for this possibility, you might prefer to use a parameter constant to -represent the value zero when testing for errors.} to indicate no -error). If an error occurs, the STATUS argument is returned set to a -different \emph{error value}, which allows you to detect the error, as -follows: -f- - -c+ -\small -\begin{terminalv} -zoommap = astZoomMap( 2, 5.0, "Title=My ZoomMap" ); -if ( !astOK ) { - <an error has occurred> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - STATUS = 0 - - ... - - ZOOMMAP = AST_ZOOMMAP( 2, 5.0D0, 'Title=My ZoomMap', STATUS ) - IF ( STATUS .NE. 0 ) THEN - <an error has occurred> - END IF -\end{terminalv} -\normalsize -f- - -c+ -The macro astOK is used to test whether the AST error status is still -OK. In this example it would not be, because we have attempted to set -a value for the Title attribute of a ZoomMap and a ZoomMap does not -have such an attribute. The actual value of the AST error status can -be obtained using the astStatus macro, as follows: - -\small -\begin{terminalv} -int status; - -... - - -status = astStatus; -\end{terminalv} -\normalsize -c- -f+ -In this example, an error would be detected because we have attempted -to set a value for the Title attribute of a ZoomMap and a ZoomMap does -not have such an attribute. -f- - -c+ -A consequence of the AST error status being set is that almost all AST -functions will subsequently cease to function and will instead simply -return without action. This means that you do not need to use astOK -to check for errors very frequently. Instead, you can usually simply -invoke a succession of AST functions. If an error occurs in any of -them, the following ones will do nothing and you can check for the -error at the end, for example: -c- -f+ -A consequence of the error status variable STATUS being set to an -error value is that almost all AST routines will subsequently cease to -function and will instead simply return without action. This means -that you do not need to check for errors very frequently. Instead, you -can usually simply invoke a succession of AST routines. If an error -occurs in any of them, the following ones will do nothing and you can -check for the error at the end, for example: -f- - -c+ -\small -\begin{terminalv} -astFunctionA( ... ); -astFunctionB( ... ); -astFunctionC( ... ); -if ( !astOK ) { - <an error has occurred> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - STATUS = 0 - - ... - - CALL AST_ROUTINEA( ... , STATUS ) - CALL AST_ROUTINEB( ... , STATUS ) - CALL AST_ROUTINEC( ... , STATUS ) - IF ( STATUS .NE. 0 ) THEN - <an error has occurred> - END IF -\end{terminalv} -\normalsize -f- - -c+ -There are, however, a few functions which do not adhere to this -general rule and which will attempt to execute if the AST error status -is set. These functions, such as astAnnul, are concerned with cleaning -up and recovering resources. For example, in the following: -c- -f+ -There are, however, a few routines which do not adhere to this general -rule and which will attempt to execute if their STATUS argument is -initially set. These routines, such as AST\_ANNUL, are concerned with -cleaning up and recovering resources. For example, in the following: -f- - -c+ -\small -\begin{terminalv} -zoommap = astZoomMap( 2, 5.0, "" ); - -astFunctionX( ... ); -astFunctionY( ... ); -astFunctionZ( ... ); - -zoommap = astAnnul( zoommap ); -if ( !astOK ) { - <an error has occurred> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - STATUS = 0 - - ... - - ZOOMMAP = AST_ZOOMMAP( 2, 5.0D0, ' ', STATUS ) - - CALL AST_ROUTINEX( ... , STATUS ) - CALL AST_ROUTINEY( ... , STATUS ) - CALL AST_ROUTINEZ( ... , STATUS ) - - CALL AST_ANNUL( ZOOMMAP, STATUS ) - IF ( STATUS .NE. 0 ) THEN - <an error has occurred> - END IF -\end{terminalv} -\normalsize -f- - -c+ -astAnnul will execute normally in order to recover the resources -associated with the ZoomMap that was created earlier, regardless of -whether an error has occurred in any of the intermediate functions. -Functions which behave in this way are noted in the relevant -descriptions in \appref{ss:functiondescriptions}. -c- -f+ -AST\_ANNUL will execute normally in order to recover the resources -associated with the ZoomMap that was created earlier, regardless of -whether an error has occurred in any of the intermediate routines. -Routines which behave in this way are noted in the relevant -descriptions in \appref{ss:functiondescriptions}. -f- - -c+ -If a serious error occurs, you will probably want to abort your -program, but sometimes you may want to recover and carry on. Because -very few AST functions will execute once the AST error status has been -set, you must first clear this status by using the astClearStatus -macro, as follows: -c- -f+ -If a serious error occurs, you will probably want to abort your -program, but sometimes you may want to recover and carry on. This is -simply done by resetting your error status variable to zero, whereupon -the AST routines you pass it to will execute normally again. -f- - -c+ -\small -\begin{terminalv} -astClearStatus; -\end{terminalv} -\normalsize -c- - -c+ -This will restore the AST error status to its OK value, so that AST -functions execute normally again. -c- - -c+ -Occasionally, you may also need to set the AST error status to an -explicit error value (see \secref{ss:channelsink} for an -example). This is done using astSetStatus and can be used to -communicate to AST that an error has occurred in some other item of -software, for example: -c- - -c+ -\small -\begin{terminalv} -int new_status; - -... - -astSetStatus( new_status ); -\end{terminalv} -\normalsize -c- - -c+ -The effect is that most AST routines will subsequently return without -action, just as if an error had occurred within the AST library -itself. -c- - -c+ -\subsection{Sharing the Error Status} - -In some software, it is usual to maintain a single integer error -status variable which is accessed by each function as it executes. If -an error occurs, this status variable is set and other functions can -detect this and take appropriate action. - -If you use AST in such a situation, it can be awkward to have a -separate internal error status used by AST functions alone. To remedy -this, AST is capable of sharing the error status variable used by any -other software, so long as they use the same conventions -(\emph{i.e.}\ a C int with the same ``OK'' value). To enable this -facility, you should pass the address of your status variable to -astWatch, as follows: - -\small -\begin{terminalv} -int my_status; -int *old_address; - -... - -old_address = astWatch( &my_status ); -\end{terminalv} -\normalsize - -Henceforth, instead of using its own internal error status variable, -AST will use the one you supply, so that it can detect errors flagged -by other parts of your software. The address of the original error -status variable is returned by astWatch, so you can restore the -original behaviour later if necessary. - -Note that this facility is not available \emph{via} the Fortran -interface to the AST library. -c- - -\cleardoublepage -\section{\label{ss:mappings}Inter-Relating Coordinate Systems (Mappings)} - -In \secref{ss:primer} we used the ZoomMap as an example of a -Mapping. We saw how it could be used to transform coordinates from its -input to its output and back again (\secref{ss:transforming}). We also -saw how its behaviour could be controlled by setting various -attributes, such as the Zoom factor and the Report attribute that made -it display coordinate values as it transformed them. - -In this section, we will look at Mappings a bit more thoroughly and -explore the behaviour which is common to all the Mappings provided by -AST. This is good background for what follows, because many of the -Objects we discuss later will also turn out to be Mappings in various -disguises. - -\subsection{\label{ss:mappingclass}The Mapping Class} - -Before we start, it is worth taking a quick look at the Mapping class -as a whole and some of the sub-classes it contains: - -\begin{terminalv} - Mapping - CmpMap - DssMap - GrismMap - IntraMap - LutMap - MathMap - MatrixMap - PermMap - PolyMap - SlaMap - SpecMap - TimeMap - UnitMap - WcsMap - ZoomMap - - Frame - <various types of Frame> -\end{terminalv} - -The Frame sub-class has been separated out here because it is covered -in detail in \secref{ss:frames}. We start by looking at the parent -class, Mapping. - -c+ -AST does not provide a function to create a basic Mapping -(\emph{i.e.}\ the astMapping constructor does not exist). This is -because the Mapping class itself is ``virtual'' and basic Mappings are -of no use in themselves. The Mapping class serves simply to contain -the various specialised Mappings that exist. -c- -f+ -AST does not provide a function to create a basic Mapping -(\emph{i.e.}\ the AST\_MAPPING constructor does not exist). This is -because the Mapping class itself is ``virtual'' and basic Mappings are -of no use in themselves. The Mapping class serves simply to contain -the various specialised Mappings that exist. -f- -However, it provides more than just a convenient heading for them -because it bestows all classes of Mapping with common properties -(\emph{e.g.}\ attributes) and behaviour. By examining the Mapping -class, we are therefore examining the things that all other Mappings -have in common. - -\subsection{The Mapping Model} - -The concept of a Mapping was illustrated in Figure~\ref{fig:mapping}. -It is a black box which you can supply with a set of coordinate values -in return for a set of transformed coordinates. The two sets are -termed \emph{input} and \emph{output} coordinates. You can also go -back the other way and transform output coordinates back into input -coordinates, as we saw in \secref{ss:transforming}. - -\subsection{Changing Attributes of a Mapping} - -Many classes of Mapping have attributes that provide values for parameter -used within the transformation. For instance, the ZoomMap class has an -attribute called ``Zoom'' that gives the scalar value by which each -coordinate is to be multiplied. These attribute values should be set when -the Mapping is created and should not be changed afterwards. Indeed, the -AST library will report an error if an attempt is made to change the -value of a Mapping attribute. This is because, once created, Mappings are -often later included within other objects such as FrameSets and CmpMaps. -This means that in general there could be many active references to a single -Mapping object within a program. Changing an attribute of the Mapping -via one particular reference (i.e pointer) would cause all the other -references to change too, with often undesirable or unpredictable -consequences. To avoid this, Mappings are considered \emph{immutable} in -most situations. The one exception is if the Mapping has not yet been -cloned or included in another Object (\emph{i.e.} it has a reference -couint of one) - changing the attributes of such a Mapping is allowed, -and will not generate an error. - -Note, the Invert attribute of a Mapping is not subject to this rule and -can be changed at any time. - -\subsection{Input and Output Coordinate Numbers} - -In general, the number of coordinates you feed into a Mapping to -represent a single point need not be the same as the number that comes -out. Often these numbers will be the same, and often they will both -equal 2 (because 2-dimensional coordinate systems are common), but -this needn't necessarily be the case. - -The number of coordinates required to specify an input point is -represented by the integer attribute Nin and the number required to -specify an output point is represented by Nout. These are read-only -attributes common to all Mappings. Generally, their values are fixed -when a Mapping is created. - -c+ -In \secref{ss:objectcreation}, we saw how the Nin attribute for a -ZoomMap was initialised by the call to the constructor function -astZoomMap which created it. In this case, the Nout attribute was not -needed and it implicitly took the same value as Nin, but we could -have enquired about its value had we wanted, as follows: -c- -f+ -In \secref{ss:objectcreation}, we saw how the Nin attribute for a -ZoomMap was initialised by the call to the constructor function -AST\_ZOOMMAP which created it. In this case, the Nout attribute was -not needed and it implicitly took the same value as Nout, but we could -have enquired about its value had we wanted, as follows: -f- - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstZoomMap *zoommap; -int nout; - -... - -nout = astGetI( zoommap, "Nout" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER NOUT, STATUS, ZOOMMAP - - STATUS = 0 - - ... - - NOUT = AST_GETI( ZOOMMAP, 'Nout', STATUS ) -\end{terminalv} -\normalsize -f- - -\subsection{Forward and Inverse Transformations} - -We stated earlier that a Mapping may be used to transform coordinates -either from input to output, or \emph{vice versa}. These are termed -its \emph{forward} and \emph{inverse} transformations. - -This statement was not quite accurate, however, because in general -Mappings are only \textbf{potentially} capable of working in both -directions. In practice, coordinate transformation may only be -feasible in one direction or the other because some functions are not -easily inverted (they may be multi-valued, for instance). Allowance -must be made for this, so each Mapping has two read-only boolean -(integer) attributes, TranForward and TranInverse, which indicate -whether each transformation is available. - -A transformation is available if the corresponding attribute is -non-zero, otherwise it is not.\footnote{Most of the Mappings provided -by the AST library work in both directions, although the LutMap can -behave otherwise.} If you enquire about the value of these attributes, -a value of 0 or 1 is returned. Attempting to use a Mapping to apply a -transformation which is not available will result in an error. - -\subsection{\label{ss:invertingmappings}Inverting Mappings} - -An important attribute, common to all Mappings, is the Invert -flag. This is a boolean (integer) attribute that can be assigned a new -value at any time. If it is non-zero, it has the effect of -interchanging the Mapping's input and output coordinates and the -Mapping is then said to be \emph{inverted}. By default, the Invert -attribute is zero. - -There is no magic in this. There is no fancy arithmetic involved in -inverting mathematical functions, for instance. The Invert flag is -simply a switch that interchanges a Mapping's input and output -ports. If it is non-zero, the Mapping's Nin and Nout attributes are -swapped, its TranForward and TranInverse attributes are swapped, and -when you ask for what was once the forward transformation you get the -inverse transformation instead (and \emph{vice versa}). When you -return the Invert attribute to zero, or clear it, the Mapping returns -to its original behaviour. - -c+ -Often, the actual value of the Invert attribute is unimportant and you -simply wish to invert its boolean sense, so that what was the -Mapping's input becomes its output and \emph{vice versa}. This is most -easily accomplished using astInvert, as follows: -c- -f+ -Often, the actual value of the Invert attribute is unimportant and you -simply wish to invert its boolean sense, so that what was the -Mapping's input becomes its output and \emph{vice versa}. This is most -easily accomplished using AST\_INVERT, as follows: -f- - -c+ -\small -\begin{terminalv} -AstMapping *mapping; - -... - -astInvert( mapping ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER MAPPING - - ... - - CALL AST_INVERT( MAPPING, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -If the Mapping you have happens to be the wrong way around, astInvert -allows you to correct the problem. -c- -f+ -If the Mapping you have happens to be the wrong way around, -AST\_INVERT allows you to correct the problem. -f- - -\subsection{Finding the Rate of Change of a Mapping Output} -The -c+ -astRate -c- -f+ -AST\_RATE -f- -function can be used to find the rate of change of any Mapping output -with respect to any Mapping input, at a given input position. The method -used produces good accuracy (typically a relative error of 10E-10 or -less) but may require the Mapping to be evaluated 100 or more times. -An estimate of the second derivative is also produced by this function. - - -\subsection{Reporting Coordinate Transformations} - -We have already seen (\secref{ss:transforming}) how the boolean -(integer) Report attribute of a Mapping works. If it is non-zero, the -operation of transforming a set of coordinates will result in a report -being written to standard output. This will display the coordinate -values before and after transformation. It can save considerable time -during program development by eliminating the need to add loops and -output statements to your program. - -c+ -In a finished program, however, you should be careful that the Report -attribute is not set to a non-zero value unless you want to see the -output (there may often be rather a lot of this!). To help prevent -unwanted output being produced by accident, the Report attribute is -unusual in that its value is not preserved when a Mapping is copied -using astCopy (\secref{ss:copyingobjects}). Instead, it reverts to its -default of zero (\emph{i.e.}\ un-set) in the copy. It also reverts to -zero when a Mapping is written out, \emph{e.g.}\ to a file using a -Channel (\secref{ss:channels}). -c- -f+ -In a finished program, however, you should be careful that the Report -attribute is not set to a non-zero value unless you want to see the -output (there may often be rather a lot of this!). To help prevent -unwanted output being produced by accident, the Report attribute is -unusual in that its value is not preserved when a Mapping is copied -using AST\_COPY (\secref{ss:copyingobjects}). Instead, it reverts to -its default of zero (\emph{i.e.}\ un-set) in the copy. It also reverts -to zero when a Mapping is written out, \emph{e.g.}\ to a file using a -Channel (\secref{ss:channels}). -f- - -%\subsection{TBW---More on Transforming Coordinates} - -\subsection{\label{ss:badcoordinates}Handling Missing (Bad) Coordinate Values} - -c+ -Even when coordinates can, in principle, be transformed in either -direction by a Mapping, there may still be instances where specific -coordinate values cannot be handled. For example, the Mapping may be -mathematically intractable (\emph{e.g.}\ singular) in certain places, -or it may map a subset of one space on to another, so that some points -in one space are not represented in the other. Sky projections often -show this behaviour, since it is quite common to project only half of -the celestial sphere on to two dimensions, omitting points on the -opposite side of the sky. There are many other examples. -c- -f+ -Even when coordinates can, in principle, be transformed in either -direction by a Mapping, there may still be instances where specific -coordinate values cannot be handled. For example, the Mapping may be -mathematically intractable (\emph{e.g.}\ singular) in certain places, -or it may map a subset of one space on to another, so that some points -in one space are not represented in the other. Sky projections often -show this behaviour, since it is quite common to project only half of -the celestial sphere on to two dimensions, omitting points on the -opposite side of the sky. There are many other examples. -f- - -c+ -To indicate when coordinates cannot be transformed, for whatever -reason, AST substitutes a special output coordinate value given by the -macro AST\_\_BAD (as defined in the ``ast.h'' header file). Before -making use of coordinates generated by any of the AST transformation -functions, therefore, you may need to check for the presence of this -value. -c- -f+ -To indicate when coordinates cannot be transformed, for whatever -reason, AST substitutes a special output coordinate value given by the -parameter constant AST\_\_BAD (as defined in the AST\_PAR include -file). Before making use of coordinates generated by any of the AST -transformation routines, therefore, you may need to check for the -presence of this value. -f- - -c+ -Because coordinates with the value AST\_\_BAD can be generated in this -way, all other AST functions are also capable of recognising this -value and handling it appropriately. The coordinate transformation -functions do this by propagating any missing input coordinate -information through to their output. This means that if you supply -coordinates with the value AST\_\_BAD, the returned coordinates are -also likely to contain this value. Here, for example, is what happens -if you use a ZoomMap (with Zoom factor 5) to transform such a set of -coordinates: -c- -f+ -Because coordinates with the value AST\_\_BAD can be generated in this -way, all other AST routines are also capable of recognising this value -and handling it appropriately. The coordinate transformation routines -do this by propagating any missing input coordinate information -through to their output. This means that if you supply coordinates -with the value AST\_\_BAD, the returned coordinates are also likely to -contain this value. Here, for example, is what happens if you use a -ZoomMap (with Zoom factor 5) to transform such a set of coordinates: -f- - -\small -\begin{terminalv} -(0, 0) --> (0, 0) -(<bad>, 2) --> (<bad>, 10) -(2, 4) --> (10, 20) -(3, 6) --> (15, 30) -(4, <bad>) --> (20, <bad>) -(5, 10) --> (25, 50) -(<bad>, <bad>) --> (<bad>, <bad>) -(7, 14) --> (35, 70) -(8, 16) --> (40, 80) -(9, 18) --> (45, 90) -\end{terminalv} -\normalsize - -The AST\_\_BAD value is represented by the string ``$<$bad$>$''. This -is a case of ``garbage in, garbage out'' but at least it's consistent -garbage that you can recognise! - -Note how the presence of the AST\_\_BAD value in one input dimension -does not necessarily result in the loss of information for all output -dimensions. Sometimes, such loss will be unavoidable, but in general -an attempt is made to preserve information as far as possible. The -exact behaviour will depend on the Mapping involved. - -\subsection{\label{ss:unitmapexample}Example---the UnitMap} - -The UnitMap is the simplest of Mappings. It is a null Mapping. Its -purpose is simply to copy coordinate values, unaltered, from its input -to its output and \emph{vice versa}. - -A UnitMap has no additional attributes beyond those of a basic -Mapping. Its Nin and Nout attributes are always equal and are -specified by the first argument supplied to its constructor. For -example: - -c+ -\small -\begin{terminalv} -AstUnitMap *unitmap; - -... - -unitmap = astUnitMap( 2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER UNITMAP - - ... - - UNITMAP = AST_UNITMAP( 2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -will create a UnitMap that copies 2-dimensional coordinates. Inverting -a UnitMap has no effect beyond changing the value of its Invert -attribute. - -c+ -The main use of a UnitMap is to allow a Mapping to be supplied when one -is required (as an argument to a function, for example) but you wish -it to leave coordinate values unchanged. -c- -f+ -The main use of a UnitMap is to allow a Mapping to be supplied when one -is required (as an argument to a routine, for example) but you wish -it to leave coordinate values unchanged. -f- - -\subsection{\label{ss:permmapexample}Example---the PermMap} - -The PermMap is a rather more complicated Mapping than we have met -previously. Its purpose is to change the order, or number, of -coordinates. It is also able to substitute fixed values for -coordinates. - -To illustrate its action, suppose our input coordinates are denoted by -($x_1,x_2,x_3,x_4$) in a 4-dimensional space and suppose our output -coordinates are to be ($x_4,x_1,x_2,x_3$). Our PermMap, therefore, -should rotate the coordinate values by one position. - -c+ -To create such a PermMap, we first set up two integer arrays. One of -these, ``outperm'', controls the selection of input coordinates for -use in the output and the other, ``inperm'', controls selection of -output coordinates for use in the input: -c- -f+ -To create such a PermMap, we first set up two integer arrays. One of -these, OUTPERM, controls the selection of input coordinates for use in -the output and the other, INPERM, controls selection of output -coordinates for use in the input: -f- - -c+ -\small -\begin{terminalv} -int outperm[ 4 ] = { 4, 1, 2, 3 }; -int inperm[ 4 ] = { 2, 3, 4, 1 }; -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER OUTPERM( 4 ), INPERM( 4 ) - DATA OUTPERM / 4, 1, 2, 3 / - DATA INPERM / 2, 3, 4, 1 / -\end{terminalv} -\normalsize -f- - -Note that the numbers we store in these arrays are the indices of the -coordinates that we want to select. We have chosen these so that the -forward and inverse transformations will perform complementary -permutations on the coordinates. - -The PermMap is then created by passing these arrays to its -constructor, as follows: - -c+ -\small -\begin{terminalv} -AstPermMap *permmap; - -... - -permmap = astPermMap( 4, inperm, 4, outperm, NULL, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER PERMMAP - DOUBLE PRECISION DUMMY( 1 ) - - ... - - PERMMAP = AST_PERMMAP( 4, INPERM, 4, OUTPERM, DUMMY, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -f+ -(the fifth argument is not being used, so a dummy array has been supplied). -f- -Note that we specify the number of input and output coordinates -separately, but set both to 4 in this example. The resulting PermMap -would have the following effect when used to transform coordinates: - -\begin{terminalv} -Forward: - (1, 2, 3, 4) --> (4, 1, 2, 3) - (2, 4, 6, 8) --> (8, 2, 4, 6) - (3, 6, 9, 12) --> (12, 3, 6, 9) - (4, 8, 12, 16) --> (16, 4, 8, 12) - (5, 10, 15, 20) --> (20, 5, 10, 15) - -Inverse: - (4, 1, 2, 3) --> (1, 2, 3, 4) - (8, 2, 4, 6) --> (2, 4, 6, 8) - (12, 3, 6, 9) --> (3, 6, 9, 12) - (16, 4, 8, 12) --> (4, 8, 12, 16) - (20, 5, 10, 15) --> (5, 10, 15, 20) -\end{terminalv} - -c+ -If the number of input and output coordinates are unequal so, also, -will be the size of the ``outperm'' and ``inperm'' arrays. This means, -however, that we cannot fill them with coordinate indices so that they -perform complementary permutations, because one transformation will -lose information (discard a coordinate) that the other cannot recover. -To give an example, consider the following: -c- -f+ -If the number of input and output coordinates are unequal so, also, -will be the size of the OUTPERM and INPERM arrays. This means, -however, that we cannot fill them with coordinate indices so that they -perform complementary permutations, because one transformation will -lose information (discard a coordinate) that the other cannot recover. -To give an example, consider the following: -f- - -c+ -\small -\begin{terminalv} -int outperm[ 3 ] = { 4, 3, 2 }; -int inperm[ 4 ] = { -1, 3, 2, 1 }; -double con[ 1 ] = { 99.004 }; -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER OUTPERM( 3 ), INPERM( 4 ) - DOUBLE PRECISION CONST( 1 ) - DATA OUTPERM / 4, 3, 2 / - DATA INPERM / -1, 3, 2, 1 / - DATA CONST / 99.004D0 / -\end{terminalv} -\normalsize -f- - -c+ -In this case, the forward transformation will change -($x_1,x_2,x_3,x_4$) into ($x_4,x_3,x_2$) and will discard $x_1$. The -inverse transformation restores the original coordinate order, but has -no value to assign to the first coordinate. In this case, the number -entered in the ``inperm'' array is $-$1. -c- -f+ -In this case, the forward transformation will change -($x_1,x_2,x_3,x_4$) into ($x_4,x_3,x_2$) and will discard $x_1$. The -inverse transformation restores the original coordinate order, but has -no value to assign to the first coordinate. In this case, the number -entered in the INPERM array is $-$1. -f- - -c+ -This negative value indicates that the coordinate value should be -obtained by addressing the first element of the ``con'' array -(\emph{i.e.}\ element zero). This array, ignored in the previous -example, may then be used to supply a value for the missing -coordinate. -c- -f+ -This negative value indicates that the coordinate value should be -obtained by addressing the CONST array using an index of 1 (the -absolute value). This array, ignored in the previous example, may then -be used to supply a value for the missing coordinate. -f- - -The constructor function: - -c+ -\small -\begin{terminalv} -permmap = astPermMap( 4, inperm, 3, outperm, con, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - PERMMAP = AST_PERMMAP( 4, INPERM, 3, OUTPERM, CONST, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -will then create a PermMap with the following effect when used to -transform coordinates: - -\begin{terminalv} -Forward: - (1, 2, 3, 4) --> (4, 3, 2) - (2, 4, 6, 8) --> (8, 6, 4) - (3, 6, 9, 12) --> (12, 9, 6) - (4, 8, 12, 16) --> (16, 12, 8) - (5, 10, 15, 20) --> (20, 15, 10) - -Inverse: - (4, 3, 2) --> (99.004, 2, 3, 4) - (8, 6, 4) --> (99.004, 4, 6, 8) - (12, 9, 6) --> (99.004, 6, 9, 12) - (16, 12, 8) --> (99.004, 8, 12, 16) - (20, 15, 10) --> (99.004, 10, 15, 20) -\end{terminalv} - -c+ -The ``con'' array may contain more than one value if necessary and may -be addressed by both the ``inperm'' and ``outperm'' arrays using -coordinate indices $-$1, $-$2, $-$3,~\emph{etc.}\ to refer to the -first, second, third,~\emph{etc.}\ elements. -c- -f+ -The CONST array may contain more than one value if necessary and may -be addressed by both the INPERM and OUTPERM arrays using coordinate -indices $-$1, $-$2, $-$3,~\emph{etc.}\ to refer to the first, second, -third,~\emph{etc.}\ elements. -f- - -c+ -If there is no suitable replacement value that can be supplied -\emph{via} the ``con'' array, a value of zero may be entered into the -``outperm'' and/or ``inperm'' arrays. This causes the value AST\_\_BAD -to be used for the affected coordinate (as defined in the ``ast.h'' -header file), thus indicating a missing coordinate value -(\secref{ss:badcoordinates}). -c- -f+ -If there is no suitable replacement value that can be supplied -\emph{via} the CONST array, a value of zero may be entered into the -OUTPERM and/or INPERM arrays. This causes the value AST\_\_BAD to be -used for the affected coordinate (as defined in the AST\_PAR include -file), thus indicating a missing coordinate value -(\secref{ss:badcoordinates}). -f- - -The principle use for a PermMap lies in matching a coordinate system -to a data array where there is a choice of storage order for the data. -PermMaps are also useful for discarding unwanted coordinates so as to -reduce the number of dimensions, such as when selecting a ``slice'' -from a multi-dimensional array. - -\cleardoublepage -\section{\label{ss:cmpmaps}Compound Mappings (CmpMaps)} - -We now turn to a rather special form of Mapping, the CmpMap. The -Mappings we have considered so far have been atomic, in the sense that -they perform pre-defined elementary transformations. A CmpMap, -however, is a compound Mapping. In essence, it is a framework for -containing other Mappings and its purpose is to allow those Mappings -to work together in various combinations while appearing as a single -Object. A CmpMap's behaviour is therefore not pre-defined, but is -determined by the other Mappings it contains. - -\subsection{\label{ss:seriescmpmap}Combining Mappings in Series} - -Consider a simple example based on two 2-dimensional coordinate -systems. Suppose that to convert from one to the other we must swap -the coordinate order and multiply both coordinates by 5, so that the -coordinates ($x_1,x_2$) transform into ($5x_2,5x_1$). This can be done -in two stages: - -\begin{enumerate} -\item Apply a PermMap (\secref{ss:permmapexample}) to swap the -coordinate order. - -\item Apply a ZoomMap (\secref{ss:transforming}) to multiply both -coordinate values by the constant 5. -\end{enumerate} - -The PermMap and ZoomMap are then said to operate \emph{in series}, -because they are applied sequentially -(\emph{c.f.}\ Figure~\ref{fig:seriescmpmap}). We can create a CmpMap -that applies these Mappings in series as follows: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstCmpMap *cmpmap; -AstPermMap *permmap; -AstZoomMap *zoommap; - -... - -/* Create the individual Mappings. */ -{ - int inperm[ 2 ] = { 2, 1 }; - int outperm[ 2 ] = { 2, 1 }; - permmap = astPermMap( 2, inperm, 2, outperm, NULL, "" ); -} -zoommap = astZoomMap( 2, 5.0, "" ) - -/* Combine them in series. */ -cmpmap = astCmpMap( permmap, zoommap, 1, "" ); - -/* Annul the individual Mapping pointers. */ -permmap = astAnnul( permmap ); -zoommap = astAnnul( zoommap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER CMPMAP, PERMMAP, STATUS, ZOOMMAP - INTEGER INPERM( 2 ), OUTPERM( 2 ), CONST( 1 ) - DATA INPERM / 1, 2 / - DATA OUTPERM / 1, 2 / - - STATUS = 0 - - ... - -* Create the individual Mappings. - PERMMAP = AST_PERMMAP( 2, INPERM, 2, OUTPERM, CONST, ' ', STATUS ) - ZOOMMAP = AST_ZOOMMAP( 2, 5.0D0, ' ', STATUS ) - -* Combine them in series. - CMPMAP = AST_CMPMAP( PERMMAP, ZOOMMAP, .TRUE., ' ', STATUS ) - -* Annul the individual Mapping pointers. - CALL AST_ANNUL( PERMMAP, STATUS ) - CALL AST_ANNUL( ZOOMMAP, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, the third argument (1) of the constructor function astCmpMap -indicates ``in series''. -c- -f+ -Here, the third argument (.TRUE.) of the constructor function -AST\_CMPMAP indicates ``in series''. -f- - -When used to transform coordinates in the forward direction, the -resulting CmpMap will apply the first component Mapping (the PermMap) -and then the second one (the ZoomMap). When transforming in the -inverse direction, it will apply the second one (in the inverse -direction) and then the first one (also in the inverse direction). In -general, although not in this particular example, the order in which -the two component Mappings are supplied is significant. Clearly, also, -the Nout attribute (number of output coordinates) for the first -Mapping must equal the Nin attribute (number of input coordinates) for -the second one. - -\subsection{Combining Mappings in Parallel} - -Connecting two Mappings in series (\secref{ss:seriescmpmap}) is not the -only way of combining them. The alternative, \emph{in parallel}, -involves applying the two Mappings at once but on different subsets of -the coordinate values. - -Consider, for example, a set of 3-dimensional coordinates and suppose -we wish to transform them by swapping the first two coordinate values -and multiplying the final one by 5, so that ($x_1,x_2,x_3$) transforms -into ($x_2,x_1,5x_3$). Again, we can perform each of these steps -individually using Mappings similar to the PermMap and ZoomMap used -earlier (\secref{ss:seriescmpmap}). In this case, however, the ZoomMap is -1-dimensional and the individual Mappings are applied in parallel -(\emph{c.f.}\ Figure~\ref{fig:parallelcmpmap}). - -Creating a CmpMap for this purpose is also very simple: - -c+ -\small -\begin{terminalv} -cmpmap = astCmpMap( permmap, zoommap, 0, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CMPMAP = AST_CMPMAP( PERMMAP, ZOOMMAP, .FALSE., ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The only difference is that the third argument of astCmpMap is now -zero, meaning ``in parallel''. -c- -f+ -The only difference is that the third argument of AST\_CMPMAP is now -.FALSE., meaning ``in parallel''. -f- - -As before, the order in which the two component Mappings are supplied -is significant. The first one acts on the lower-numbered input -coordinate values (however many it needs) and produces the -lower-numbered output coordinates, while the second Mapping acts on -the higher-numbered input coordinates (however many remain) and -generates the remaining higher-numbered output coordinates. When the -CmpMap transforms coordinates in the inverse direction, both component -Mappings are applied to the same coordinates, but in the inverse -direction. - -Note that the Nin and Nout attributes of the component Mappings -(\emph{i.e.}\ the numbers of input and output coordinates) will sum to -give the Nin and Nout attributes of the overall CmpMap. - -\subsection{\label{ss:cmpmapcomponents}The Component Mappings} - -c+ -A CmpMap does not store copies of its component Mappings, but simply -holds pointers to them. In the example above -(\secref{ss:seriescmpmap}), we were free to annul the individual -Mapping pointers after creating the CmpMap because the pointers held -internally by the CmpMap increased the reference count (RefCount -attribute) of each component Mapping by one. The individual components -are therefore not deleted by astAnnul, but retained until the CmpMap -itself is deleted and annuls the pointers it holds. Consistent use of -astAnnul (\secref{ss:annullingpointers}) and/or pointer contexts -(\secref{ss:contexts}) will therefore ensure that all Objects are -deleted at the appropriate time. -c- -f+ -A CmpMap does not store copies of its component Mappings, but simply -holds pointers to them. In th example above (\secref{ss:seriescmpmap}), -we were free to annul the individual Mapping pointers after creating -the CmpMap because the pointers held internally by the CmpMap -increased the reference count (RefCount attribute) of each component -Mapping by one. The individual components are therefore not deleted by -AST\_ANNUL, but retained until the CmpMap itself is deleted and annuls -the pointers it holds. Consistent use of AST\_ANNUL -(\secref{ss:annullingpointers}) and/or pointer contexts -(\secref{ss:contexts}) will therefore ensure that all Objects are -deleted at the appropriate time. -f- - -Note that access to a CmpMap's component Mappings is not generally -available unless pointers to them are retained when the CmpMap is -created. If such pointers are retained, then subsequent modifications -to the individual components can be used to indirectly modify the -behaviour of the overall CmpMap. - -There is an important exception to this, however, because a CmpMap -retains a copy of the initial Invert flag settings of each of its -components and uses these in order to ignore any subsequent external -changes. This means that you may invert either component Mapping -before inserting it into a CmpMap and need not worry if you un-invert -it again later. The CmpMap's behaviour will not be affected by the -later action. - -\subsection{\label{ss:complexcmpmap}Creating More Complex Mappings} - -c+ -Because a CmpMap is itself a Mapping, any existing CmpMap can -substitute (\secref{ss:objecthierarchy}) as a component Mapping when -constructing a new CmpMap using astCmpMap. This has the effect of -nesting one CmpMap inside another and opens up many new possibilities. -For example, combining three Mappings in series can be accomplished as -follows: -c- -f+ -Because a CmpMap is itself a Mapping, any existing CmpMap can -substitute (\secref{ss:objecthierarchy}) as a component Mapping when -constructing a new CmpMap using AST\_CMPMAP. This has the effect of -nesting one CmpMap inside another and opens up many new possibilities. -For example, combining three Mappings in series can be accomplished as -follows: -f- - -c+ -\small -\begin{terminalv} -AstMapping *map1, *map2, *map3; - -... - -cmpmap = astCmpMap( map1, astCmpMap( map2, map3, 1, "" ), 1, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER MAP1, MAP2, MAP3 - - ... - - CMPMAP = AST_CMPMAP( MAP1, AST_CMPMAP( MAP2, MAP3, .TRUE., ' ', STATUS ), - : .TRUE., ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -The way in which the individual component Mappings are grouped within -the nested CmpMaps is not usually important. - -A similar technique can be used to combine multiple Mappings in -parallel and, of course, mixed series and parallel combinations are -also possible (Figure~\ref{fig:complexcmpmap}). There is no built-in -limit to how many CmpMaps may be nested in this way, so this mechanism -provides an indefinitely extensible method of building complex -Mappings out of the elemental building blocks provided by AST. - -In practice, you might not need to construct such complex CmpMaps -yourself very frequently, but they will often be returned by AST -routines. Nested CmpMaps underlie the library's entire ability to -represent a wide range of different coordinate transformations. - -\subsection{\label{ss:cmpmapexample}Example---Transforming Between Two Calibrated Images} - -Consider, as a practical example of CmpMaps, two images of the -sky. Suppose that for each image we have a Mapping which converts from -pixel coordinates to a standard celestial coordinate system, say -FK5~(J2000.0). If we wish to inter-compare these images, we can do so -by using this celestial coordinate system to align them. That is, we -first convert from pixel coordinates in the first image into FK5 -coordinates and we then convert from FK5 coordinates into pixel -coordinates in the second image. - -c+ -If ``mapa'' and ``mapb'' are pointers to our two original Mappings, we -could form a CmpMap which transforms directly between the pixel -coordinates of the first and second images by combining these -Mappings, as follows: -c- -f+ -If MAPA and MAPB are pointers to our two original Mappings, we could -form a CmpMap which transforms directly between the pixel coordinates -of the first and second images by combining these Mappings, as -follows: -f- - -c+ -\small -\begin{terminalv} -AstCmpMap *alignmap; -AstMapping *mapa, *mapb; - -... - -astInvert( mapb ); -alignmap = astCmpMap( mapa, mapb, 1, "" ); -astInvert( mapb ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER ALIGNMAP, MAPA, MAPB - - ... - - CALL AST_INVERT( MAPB, STATUS ) - ALIGNMAP = AST_CMPMAP( MAPA, MAPB, .TRUE., ' ', STATUS ) - CALL AST_INVERT( MAPB, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, we have used astInvert (\secref{ss:invertingmappings}) to invert -``mapb'' before inserting it into the CmpMap because, as supplied, it -converted in the wrong direction. Afterwards, we invert it again to -return it to its original state. The CmpMap, however, will ignore this -subsequent change (\secref{ss:cmpmapcomponents}). -c- -f+ -Here, we have used AST\_INVERT (\secref{ss:invertingmappings}) to -invert MAPB before inserting it into the CmpMap because, as supplied, -it converted in the wrong direction. Afterwards, we invert it again to -return it to its original state. The CmpMap, however, will ignore this -subsequent change (\secref{ss:cmpmapcomponents}). -f- - -The forward transformation of the resulting CmpMap will now transform -from pixel coordinates in the first image to pixel coordinates in the -second image, while its inverse transformation will convert in the -opposite direction. - -\subsection{\label{ss:overcomplexcmpmaps}Over-Complex Compound Mappings} - -While a CmpMap provides a very flexible way of constructing -arbitrarily complex Mappings (\secref{ss:complexcmpmap}), it -unfortunately also provides an opportunity for representing simple -Mappings in complex ways. Sometimes, unnecessary complexity can be -difficult to avoid but can obscure important simplifications. - -Consider the example above (\secref{ss:cmpmapexample}), in which we -inter-related two images of the sky \emph{via} a CmpMap. If the two -images turned out to be simply offset from each other by a shift along -each pixel axis, then this approach would align them correctly, but it -would be inefficient. This is because it would introduce unnecessary -and expensive transformations to and from an intermediate celestial -coordinate system, whereas a simple shift of pixel origin would -suffice. - -Recognising that a simpler and more efficient solution exists -obviously requires a little more than simply joining two Mappings -end-to-end. We must also determine whether the resulting CmpMap is -more complex than it needs to be, \emph{i.e.}\ contains redundant -information. If it is, we then need a way to simplify it. - -The problem is not always just one of efficiency, however. Sometimes -we may also need to know something about the actual form a Mapping -takes---\emph{i.e.}\ the nature of the operations it performs. -Unnecessary complexity can obscure this, but such complexity can -easily accumulate during normal data processing. - -For example, a Mapping that transforms pixel coordinates into -positions on the sky might be repeatedly modified as changes are made -to the shape and size of the image. Typically, on each occasion, -another Mapping will be concatenated to reflect what has happened to -the image. This could soon make it difficult to discern the overall -nature of the transformation from the complex CmpMap that -accumulates. If only shifts of origin were involved on each occasion, -however, they could be combined into a single shift which could be -represented much more simply. - -Suppose we now wanted to represent our image's celestial coordinate -calibration using FITS conventions (\secref{ss:foreignfits}). This -requires AST to determine whether the Mapping which relates pixel -coordinate to sky positions conforms to the FITS model (for example, -whether it is equivalent to applying a single set of shifts and scale -factors followed by a map projection). Clearly, there is an important -use here for some means of simplifying the internal structure of a -CmpMap. - -\subsection{\label{ss:simplifyingcmpmaps}Simplifying Compound Mappings} - -c+ -The ability to simplify compound Mappings is provided by the -astSimplify function. This function encapsulates a number of -heuristics for converting Mappings, or combinations of Mappings within -a CmpMap, into simpler, equivalent ones. When applied to a CmpMap, -astSimplify tries to reduce the number of individual Mappings within -it by merging neighbouring component Mappings together. It will do -this with both series and parallel combinations of Mappings, or both, -and will handle CmpMaps nested to any depth -(\secref{ss:complexcmpmap}). -c- -f+ -The ability to simplify compound Mappings is provided by the -AST\_SIMPLIFY function. This function encapsulates a number of -heuristics for converting Mappings, or combinations of Mappings within -a CmpMap, into simpler, equivalent ones. When applied to a CmpMap, -AST\_SIMPLIFY tries to reduce the number of individual Mappings within -it by merging neighbouring component Mappings together. It will do -this with both series and parallel combinations of Mappings, or both, -and will handle CmpMaps nested to any depth -(\secref{ss:complexcmpmap}). -f- - -c+ - To illustrate how astSimplify works, consider the combination of - Mappings shown in Figure~\ref{fig:simplifyexample}. -c- -f+ - To illustrate how AST\_SIMPLIFY works, consider the combination of - Mappings shown in Figure~\ref{fig:simplifyexample}. -f- - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/simpexamp} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/simpexamp} -f- - \caption[An over-complex compound Mapping.]{An over-complex compound Mapping, consisting of PermMaps, - ZoomMaps and a UnitMap, which can be simplified to become a single - UnitMap. The enclosing nested CmpMaps have been omitted for clarity.} - \label{fig:simplifyexample} - \end{center} - \end{figure} - -If this were contained in a CmpMap, it could be simplified as follows: - -c+ -\small -\begin{terminalv} -AstMapping *simpler; - -... - -simpler = astSimplify( cmpmap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER SIMPLER - - ... - - SIMPLER = AST_SIMPLIFY( CMPMAP, STATUS ); -\end{terminalv} -\normalsize -f- - -c+ -In this case, the result would be a simple 3-dimensional UnitMap (the -identity Mapping). To reach this conclusion, astSimplify will have -made a number of deductions, roughly as follows: -c- -f+ -In this case, the result would be a simple 3-dimensional UnitMap (the -identity Mapping). To reach this conclusion, AST\_SIMPLIFY will have -made a number of deductions, roughly as follows: -f- - -\begin{enumerate} -\item The two 2-dimensional ZoomMaps in series are equivalent to a -single ZoomMap with a combined Zoom factor of unity. This, in turn, is -equivalent to a 2-dimensional UnitMap. - -\item This UnitMap in parallel with the other 1-dimensional UnitMap is -equivalent to a single 3-dimensional UnitMap. This UnitMap, sandwiched -between any other pair of Mappings, can then be eliminated. - -\item The remaining two PermMaps in series are equivalent to a single -3-dimensional PermMap. When these are combined, the resulting PermMap -is found to be equivalent to a 3-dimensional UnitMap. -\end{enumerate} - -c+ -This example is a little contrived, but illustrates how astSimplify -can deal with even quite complicated compound Mappings through a -series of incremental simplifications. Where possible, this will -result in either a simpler compound Mapping or, if feasible, an atomic -(non-compound) Mapping, as here. If no simplification is possible, -astSimplify will just return a pointer to the original Mapping. -c- -f+ -This example is a little contrived, but illustrates how AST\_SIMPLIFY -can deal with even quite complicated compound Mappings through a -series of incremental simplifications. Where possible, this will -result in either a simpler compound Mapping or, if feasible, an atomic -(non-compound) Mapping, as here. If no simplification is possible, -AST\_SIMPLIFY will just return a pointer to the original Mapping. -f- - -c+ -Although astSimplify cannot identify every simplification that is -theoretically possible, sufficient rules are included to deal with the -most common and important cases. -c- -f+ -Although AST\_SIMPLIFY cannot identify every simplification that is -theoretically possible, sufficient rules are included to deal with the -most common and important cases. -f- - -\cleardoublepage -\section{\label{ss:frames}Representing Coordinate Systems (Frames)} - -An AST Frame is an Object that is used to represent a coordinate -system. Contrast this with a Mapping (\secref{ss:mappings}), which is -used to describe how to convert between coordinate systems. The two -concepts are complementary and we will see how they work together in -\secref{ss:framesets}. - -In this section we will discuss only basic Frames, which represent -Cartesian coordinate systems. More specialised types of Frame -(\emph{e.g.}\ the SkyFrame, which represents celestial coordinate -systems, and the SpecFrame, which represents spectral coordinate -systems) are covered later (\secref{ss:skyframes} and \secref{ss:specframes}) -and, naturally, inherit the properties and behaviour of the simple Frames -discussed here. - -\subsection{The Frame Model} - -The best way to think about a Frame is like the frame that you would -plot around a graph. In two dimensions, you would have an ``$x$'' and -a ``$y$'' axis, a title on the graph and labels on the axes, together -with an indication of the physical units being plotted. The values -marked along each axis would be formatted in a human-readable way. The -frame around a graph therefore defines a coordinate space within which -you can locate points, draw lines, calculate distances, \emph{etc.} - -An AST Frame works in much the same way, embodying all of these -concepts and a few more. It also allows any number of axes, which -means that a Frame can represent coordinate systems with any number of -dimensions. You specify how many when you create it. - -Remember that the basic Frame we are considering here is completely -general. It knows nothing of celestial coordinates, for example, and -all its axes are equivalent. It can be adapted to describe any general -purpose Cartesian coordinate system by setting its attributes, such as -its Title and axis Labels, \emph{etc.}\ to appropriate values. - -\subsection{\label{ss:creatingframes}Creating a Frame} - -Creating a Frame is straightforward and follows the usual pattern: - -c+ -\small -\begin{terminalv} -#include "ast.h" -astFrame *frame; - -... - -frame = astFrame( 2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER FRAME, STATUS - - STATUS = 0 - - ... - - FRAME = AST_FRAME( 2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The first argument of the astFrame constructor function specifies the -number of axes which the Frame should have. -c- -f+ -The first argument of the AST\_FRAME constructor function specifies -the number of axes which the Frame should have. -f- - -\subsection{\label{ss:frameasmapping}Using a Frame as a Mapping} - -We should briefly point out that the Frame we created above -(\secref{ss:creatingframes}) is also a Mapping -(\secref{ss:mappingclass}) and therefore inherits the properties and -behaviour common to other Mappings. - -c+ -One way to see this is to set the Frame's Report attribute (inherited -from the Mapping class) to a non-zero value and pass the Frame pointer -to a coordinate transformation function, such as astTran2. -c- -f+ -One way to see this is to set the Frame's Report attribute (inherited -from the Mapping class) to a non-zero value and pass the Frame pointer -to a coordinate transformation routine, such as AST\_TRAN2. -f- - -c+ -\small -\begin{terminalv} -double xin[ 5 ] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 }; -double yin[ 5 ] = { 0.0, 2.0, 4.0, 6.0, 8.0, 10.0 }; -double xout[ 5 ]; -double yout[ 5 ]; - -... - -astSet( frame, "Report=1" ); -astTran2( frame, 5, xin, yin, 1, xout, yout ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION XIN( 5 ), YIN( 5 ), XOUT( 5 ), YOUT( 5 ) - DATA XIN / 0D0, 1D0, 2D0, 3D0, 4D0, 5D0 / - DATA YIN / 0D0, 2D0, 4D0, 6D0, 8D0, 10D0 / - - CALL AST_SET( FRAME, 'Report=1', STATUS ) - CALL AST_TRAN2( FRAME, 5, XIN, YIN, .TRUE., XOUT, YOUT, STATUS ) -\end{terminalv} -\normalsize -f- - -The resulting output might then look like this: - -\begin{terminalv} -(1, 2) --> (1, 2) -(2, 4) --> (2, 4) -(3, 6) --> (3, 6) -(4, 8) --> (4, 8) -(5, 10) --> (5, 10) -\end{terminalv} - -This is not very exciting because a Frame implements an identity -transformation just like a UnitMap -(\secref{ss:unitmapexample}). However, it illustrates that a Frame can -be used as a Mapping and that its Nin and Nout attributes are both -equal to the number of Frame axes. - -When we consider more specialised Frames -(\emph{e.g.}~\secref{ss:framesets}), we will see that using them as -Mappings can be very useful indeed. - -\subsection{\label{ss:frameaxisattributes}Frame Axis Attributes} - -Frames have a number of attributes which can take multiple values, one -for each axis. These separate values are identified by appending the -axis number in parentheses to the attribute name. For example, the -Label(1) attribute is a character string containing the label which -appears on the first axis. - -Axis attributes are accessed in the same way as all other attributes -(\secref{ss:gettingattributes}, \secref{ss:settingattributes} and -\secref{ss:defaultingattributes}). For example, the Label on the second -axis might be obtained as follows: - -c+ -\small -\begin{terminalv} -const char *label; - -... - -label = astGetC( frame, "Label(2)" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 70 ) LABEL - - ... - - LABEL = AST_GETC( FRAME, 'Label(2)', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Other attribute access functions (astSetX, astTest and astClear) may -also be applied to axis attributes in the same way. -c- -f+ -Other attribute access routines (AST\_SETx, AST\_TEST and AST\_CLEAR) -may also be applied to axis attributes in the same way. -f- - -If the axis number is stored in a program variable, then its value -must be formatted to generate a suitable attribute name before using -this to access the attribute itself. For example, the following will -print out the Label value for each axis of a Frame: - -c+ -\small -\begin{terminalv} -#include <stdio.h> -char name[ 18 ]; -int iaxis, naxes; - -... - -naxes = astGetI( frame, "Naxes" ); -for ( iaxis = 1; iaxis <= naxes; iaxis++ ) { - (void) sprintf( name, "Label(%d)", iaxis ); - label = astGetC( frame, name ); - (void) printf( "Label %2d: %s\n", iaxis, label ); -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 10 ) AXIS - INTEGER IAXIS - - ... - - DO 1 IAXIS = 1, AST_GETI( FRAME, 'Naxes', STATUS ) - WRITE ( AXIS, '( I10 )' ) IAXIS - LABEL = AST_GETC( FRAME, 'Label(' // AXIS // ')', STATUS ) - WRITE ( *, 199 ) IAXIS, LABEL - 199 FORMAT ( 'Label ', I2, ': ', A ) - 1 CONTINUE -\end{terminalv} -\normalsize -f- - -Note the use of the Naxes attribute to determine the number of Frame -axes. - -The output from this might look like the following: - -\begin{terminalv} -Label 1: Axis 1 -Label 2: Axis 2 -\end{terminalv} - -In this case, the Frame's default axis Labels have been revealed as -rather un-exciting. Normally, you would set much more useful values, -typically when you create the Frame---perhaps something like: - -c+ -\small -\begin{terminalv} -frame = astFrame( 2, "Label(1)=Offset from centre of field," - "Unit(1) =mm," - "Label(2)=Transmission coefficient," - "Unit(2) =%" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - FRAME = AST_FRAME( 2, 'Label(1)=Offset from centre of field,' // - 'Unit(1) =mm,' // - 'Label(2)=Transmission coefficient,' // - 'Unit(2) =%', STATUS ) -\end{terminalv} -\normalsize -f- - -Here, we have also set the (character string) Unit attribute for each -axis to describe the physical units represented on that axis. All the -attribute assignments have been combined into a single string, -separated by commas. - -\subsection{\label{ss:frameattributes}Frame Attributes} - -We will now briefly outline the various attributes associated with a -Frame (this is, of course, in addition to those inherited from the -Mapping class). We will not delve too deeply into the details of each -attribute, for which you should consult the appropriate description in -\appref{ss:attributedescriptions}. Instead, we aim simply to sketch -the range of facilities available: - -\begin{quote} -\begin{description} -\item[Naxes]\mbox{}\\ -A read-only integer giving the number of Frame axes. - -\item[Title]\mbox{}\\ -A string describing the coordinate system which the Frame represents. - -\item[Label(axis)]\mbox{}\\ -A label string for each axis. - -\item[Unit(axis)]\mbox{}\\ -A string describing the physical units on each axis. You can choose -whether to make this attribute ``active'' or ``passive'' (using -c+ -astSetActiveUnit -c- -f+ -AST\_SETACTIVEUNIT -f- -). If active, its value will be taken into account when finding the -Mapping between two Frames (\emph{e.g.} a scaling of 0.001 would be used -to connect two axis with units of ``km'' and ``m''). If passive, its value -is ignored. Its use is described in more detail in \secref{ss:frameunits}. - -\item[Symbol(axis)]\mbox{}\\ -A string containing a ``short form'' symbol (\emph{e.g.}\ like ``X'' -or ``Y'') used to represent the quantity plotted on each axis. - -\item[Digits/Digits(axis)]\mbox{}\\ -The preferred number of digits of precision to be used when formatting -values for display on each axis. - -\item[Format(axis)]\mbox{}\\ -A string containing a \emph{format specifier} which determines exactly -how values should be formatted for display on each axis -(\secref{ss:formattingaxisvalues}). If this attribute is un-set, the -formatting is based on the Digits value, otherwise the Format string -over-rides the Digits value. - -\item[Direction(axis)]\mbox{}\\ -A boolean (integer) value which indicates in which direction each axis -should be plotted. If it is non-zero (the default), the axis should be -plotted in the conventional direction---\emph{i.e.}\ increasing to the -right for the abscissa and increasing upwards for the ordinate. If it -is zero, the axis should be plotted in reverse. This attribute is -provided as a hint only and programs are free to ignore it if they -wish. - -\item[Domain]\mbox{}\\ -A character string which identifies the \emph{physical domain} to -which the Frame's coordinate system applies. The primary purpose of -this attribute is to prevent unwanted conversions from occurring -between coordinate systems which are not related. Its use is described -in more detail in \secref{ss:framedomains}. - -\item[System]\mbox{}\\ -A character string which identifies the specific coordinate system used -to describe positions within the physical domain represented by the Frame. -For a simple Frame, this attribute currently has a fixed value of -``Cartesian'', but could in principle be extended to include options such -as ``Polar'', ``Cylindrical'', \emph{etc}. More specialised Frames such -as the SkyFrame, TimeFrame and SpecFrame, re-define the allowed values to be -appropriate to the domain which they describe. For instance, the SkyFrame -allows values such as ``FK4'' and ``Galactic'', and the SpecFrame allows -values such as ``frequency'' and ``wavelength''. - -\item[Epoch]\mbox{}\\ -This value is used to qualify a coordinate system by giving the moment in -time when the coordinates are correct. Usually, this will be the date of -observation. The Epoch value is important in cases where coordinates -systems move with respect to each other over time. An example of two such -coordinate systems are the FK4 and FK5 celestial coordinate systems. - -\item[ObsLon]\mbox{}\\ -Specifies the longitude of the observer (assumed to be on the surface of -the earth). The basic Frame class does not use this value, but -specialised sub-classes may. For instance, the SpecFrame class uses it to -calculate the relative velocity of the observer and the centre of the -earth for use in converting between standards of rest. - -\item[ObsLat]\mbox{}\\ -Specifies the latitude of the observer. Use in conjunction with ObsLon. - -\end{description} -\end{quote} - -There are also some further Frame attributes, not described above, -which are important when Frames are used as templates to search for -other Frames. Their use goes beyond the present discussion. -%TBW---Add reference here. - -\subsection{\label{ss:formattingaxisvalues}Formatting Axis Values} - -c+ -The coordinate values associated with each axis of a Frame are stored -(\emph{e.g.}\ within your program) as double values. The Frame class -therefore provides a function, astFormat, to convert these values into -formatted strings for display: -c- -f+ -The coordinate values associated with each axis of a Frame are stored -(\emph{e.g.}\ within your program) as double precision values. The -Frame class therefore provides a function, AST\_FORMAT, to convert -these values into formatted strings for display: -f- - -c+ -\small -\begin{terminalv} -const char *string -double value; - -... - -string = astFormat( frame, iaxis, value ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 50 ) STRING - DOUBLE PRECISION VALUE - - ... - - STRING = AST_FORMAT( FRAME, IAXIS, VALUE, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, the astFormat function is passed a Frame pointer, the number of -an axis (``iaxis'') and a double precision value to format -(``value''). It returns a pointer to character string containing the -formatted value. -c- -f+ -Here, the AST\_FORMAT character function is passed a Frame pointer, -the number of an axis (IAXIS) and a double precision value to format -(VALUE). It returns a character string containing the formatted value. -f- -\label{ss:formattingwithdigits} - -c+ -By default, the formatting applied will be determined by the Frame's -Digits attribute and will normally display results with seven digits -of precision (corresponding approximately to the C ``float'' data type -on many machines). Setting a different Digits value, however, allows -you to adjust the precision as necessary to suit the accuracy of the -coordinate data you are processing. If finer control is needed, it is -also possible to set a Digits value for each individual axis by -appending an axis number to the attribute name -(\emph{e.g.}\ ``Digits(2)''). If this is done, it over-rides the -effect of the Frame's main Digits value for that axis. -c- -f+ -By default, the formatting applied will be determined by the Frame's -Digits attribute and will normally display results with seven digits -of precision (corresponding approximately to the Fortran REAL data -type on many machines). Setting a different Digits value, however, -allows you to adjust the precision as necessary to suit the accuracy -of the coordinate data you are processing. If finer control is -needed, it is also possible to set a Digits value for each individual -axis by appending an axis number to the attribute name -(\emph{e.g.}\ ``Digits(2)''). If this is done, it over-rides the -effect of the Frame's main Digits value for that axis. -f- - -c+ -Even finer control is possible by setting the (character string) Format -attribute for a Frame axis. The string given should contain a C -\emph{format specifier} which explicitly determines how the values on -that axis should be formatted. This will over-ride the effects of any -Digits value\footnote{The exception to this rule is that if the Format -value includes a precision of ``$.*$'', then Digits will be used to -determine the actual precision used.}. Any valid ``printf'' format -specifier may be used so long as it consumes exactly one double value. -c- -f+ -Even finer control is possible by setting the (character string) -Format attribute for a Frame axis. The string given should contain a -\emph{format specifier} which explicitly determines how the values on -that axis should be formatted. This will over-ride the effects of any -Digits value\footnote{The exception to this rule is that if the Format value -includes a precision of ``$.*$'', then Digits will be used to determine -the actual precision used.}. Unfortunately for Fortran programmers, this must -be a C language format specifier,\footnote{This is a consequence of -implementing the AST library in C.} so you might find the Digits -approach preferable. -f- - -c+ -When setting Format values, remember that the ``\%'' which appears in -the format specifier may need to be doubled to ``\%\%'' if you are -using a function (such as astSet) which interprets ``printf'' format -specifiers itself. -c- -f+ -The simplest type of format specifier takes the form ``\%m.nG'', where -``m'' and ``n'' are integers giving the minimum field width in characters -and the number of significant digits to display (\emph{e.g.}\ -``\%10.5G''). The ''n'' value may be replaced by an asterisk, in which -case the value of the Digits attribute is used to determine the number of -significant digits to display. Other formatting options are also possible -and if you need to use them you may wish to consult a book on C (see the -``printf'' function), remembering that you want to format a double -precision (C double) value. -f- - -c+ -It is recommended that you use astFormat whenever you display -formatted coordinate values, even although you could format them -yourself using ``sprintf''. This is because it puts the Frame in -control of formatting. When you start to handle more elaborate Frames -(representing, say, celestial coordinates), you will need different -formatting methods. This approach delivers them without any change to -your software. -c- -f+ -It is recommended that you use AST\_FORMAT whenever you display -formatted coordinate values, even although you could format them -yourself using a WRITE statement. This is because it puts the Frame in -control of formatting. When you start to handle more elaborate Frames -(representing, say, celestial coordinates), you will need different -formatting methods. This approach delivers them without any change to -your software. -f- - -c+ -You should also consider regularly using the astNorm function, -described below (\secref{ss:normalising}), for any values that will be -made visible to the user of your software. -c- -f+ -You should also consider regularly using the AST\_NORM routine, -described below (\secref{ss:normalising}), for any values that will be -made visible to the user of your software. -f- - -\subsection{\label{ss:normalising}Normalising Frame Coordinates} - -c+ -The function astNorm is provided to cope with the fact that some -coordinate systems do not extend indefinitely in all directions. Some -may have boundaries, outside which coordinates are meaningless, while -others wrap around on themselves, so that after a certain distance you -return to the beginning again (coordinate systems based on circles and -spheres, for instance). A basic Frame has no such complications, but -other more specialised Frames (such as SkyFrames, representing the -celestial sphere---\secref{ss:skyframes}) do. -c- -f+ -The routine AST\_NORM is provided to cope with the fact that some -coordinate systems do not extend indefinitely in all directions. Some -may have boundaries, outside which coordinates are meaningless, while -others wrap around on themselves, so that after a certain distance you -return to the beginning again (coordinate systems based on circles and -spheres, for instance). A basic Frame has no such complications, but -other more specialised Frames (such as SkyFrames, representing the -celestial sphere---\secref{ss:skyframes}) do. -f- - -c+ -The role played by astNorm is to \emph{normalise} any arbitrary set of -coordinates by converting them into a set which is ``within bounds'', -interpreted according to the particular Frame in question. For -example, on the celestial sphere, a right ascension value of 24~hours -or more can have a suitable multiple of 24~hours subtracted without -affecting its meaning and astNorm would perform this task. Similarly, -negative values of right ascension would have a multiple of 24~hours -added, so that the result lies in the range zero to 24~hours. The -coordinates in question are modified in place by astNorm, as follows: -c- -f+ -The role played by AST\_NORM is to \emph{normalise} any arbitrary set -of coordinates by converting them into a set which is ``within -bounds'', interpreted according to the particular Frame in -question. For example, on the celestial sphere, a right ascension -value of 24~hours or more can have a suitable multiple of 24~hours -subtracted without affecting its meaning and AST\_NORM would perform -this task. Similarly, negative values of right ascension would have a -multiple of 24~hours added, so that the result lies in the range zero -to 24~hours. The coordinates in question are modified in place by -AST\_NORM, as follows: -f- - -c+ -\small -\begin{terminalv} -double point[ 2 ]; - -... - -astNorm( frame, point ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION POINT( 2 ) - - ... - - CALL AST_NORM( FRAME, POINT, STATUS ) -\end{terminalv} -\normalsize -f- - -If the coordinates supplied are initially OK, as they would always be -with a basic Frame, then they are returned unchanged. - -c+ -Because the main purpose of astNorm is to convert coordinates into the -preferred range for human consumption, its use is almost always -appropriate immediately before formatting coordinate values for -display using astFormat (\secref{ss:formattingaxisvalues}). Even if -the Frame in question does not restrict the range of coordinates, so -that astNorm does nothing, using it will allow you to process other -more specialised Frames, where normalisation is important, without -changing your software. -c- -f+ -Because the main purpose of AST\_NORM is to convert coordinates into -the preferred range for human consumption, its use is almost always -appropriate immediately before formatting coordinate values for -display using AST\_FORMAT (\secref{ss:formattingaxisvalues}). Even if -the Frame in question does not restrict the range of coordinates, so -that AST\_NORM does nothing, using it will allow you to process other -more specialised Frames, where normalisation is important, without -changing your software. -f- - -\subsection{\label{ss:unformattingaxisvalues}Reading Formatted Axis Values} - -c+ -The process of converting a formatted coordinate value for a Frame -axis, such as might be produced by astFormat -(\secref{ss:formattingaxisvalues}), back into a numerical (double) -value ready for processing is performed by astUnformat. However, -although this process is essentially the inverse of that performed by -astFormat, there are a number of additional difficulties that must be -addressed in practice. -c- -f+ -The process of converting a formatted coordinate value for a Frame -axis, such as might be produced by AST\_FORMAT -(\secref{ss:formattingaxisvalues}), back into a numerical (double -precision) value ready for processing is performed by AST\_UNFORMAT. -However, although this process is essentially the inverse of that -performed by AST\_FORMAT, there are a number of additional difficulties -that must be addressed in practice. -f- - -c+ -The main use for astUnformat is in reading formatted coordinate values -which have been entered by the user of a program, or read from a -file. As such, we can rarely assume that the values are neatly -formatted in the way that astFormat would produce. Instead, it is -usually desirable to allow considerable flexibility in the form of -input that can be accommodated, so as to permit ``free-format'' data -input by the user. In addition, we may need to extract individual -coordinate values embedded in other textual data. -c- -f+ -The main use for AST\_UNFORMAT is in reading formatted coordinate -values which have been entered by the user of a program, or read from -a file. As such, we can rarely assume that the values are neatly -formatted in the way that AST\_FORMAT would produce. Instead, it is -usually desirable to allow considerable flexibility in the form of -input that can be accommodated, so as to permit ``free-format'' data -input by the user. In addition, we may need to extract individual -coordinate values embedded in other textual data. -f- - -c+ -Underlying these requirements is the root difficulty that the textual -format used to represent a coordinate value will depend on the class -of Frame we are considering. For example, for a basic Frame, -astUnformat may have to read a value like ``1.25e-6'', whereas for a -more specialised Frame representing celestial coordinates it may have -to handle a value like ``-07d~49m~13s''. Of course, the format might -also depend on which axis is being considered. -c- -f+ -Underlying these requirements is the root difficulty that the textual -format used to represent a coordinate value will depend on the class -of Frame we are considering. For example, for a basic Frame, -AST\_UNFORMAT may have to read a value like ``1.25E-6'', whereas a -more specialised Frame representing celestial coordinates may have to -handle a value like ``-07d~49m~13s''. Of course, the format might also -depend on which axis is being considered. -f- - -Ideally, we would like to write software that can handle any kind of -Frame. However, this makes it a little more difficult to analyse -textual input data to extract individual coordinate values, since we -cannot make assumptions about how the values are formatted. It would -not be safe, for example, simply to assume that the values being read -are separated by white space. This is not just because they might be -separated by some other character, but also because celestial -coordinate values might themselves contain spaces. In fact, to be -completely safe, we cannot make any assumptions about how a formatted -coordinate value is separated from the surrounding text, except that -it should be separated in some way which is not ambiguous. - -c+ -This is the very basic assumption upon which astUnformat works. It is -invoked as follows: -c- -f+ -This is the very basic assumption upon which AST\_UNFORMAT works. It is -invoked as follows: -f- - -c+ -\small -\begin{terminalv} -int n; - -... - -n = astUnformat( frame, iaxis, string, &value ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER N - - ... - - N = AST_UNFORMAT( FRAME, IAXIS, STRING, VALUE, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -It is supplied with a Frame pointer (``frame''), the number of an axis -(``iaxis'') and a character string to be read (``string''). If it -succeeds in reading a value, astUnformat returns the resulting -coordinate to the address supplied \emph{via} the final argument -(``\&value''). The returned function value indicates how many -characters were read from the string in order to obtain this result. -c- -f+ -It is supplied with a Frame pointer (FRAME), the number of an axis -(IAXIS) and a character string to be read (STRING). If it succeeds in -reading a value, AST\_UNFORMAT returns the resulting coordinate -\emph{via} its penultimate argument (VALUE). The returned function -value indicates how many characters were read from the string in order -to obtain this result. -f- - -The string is read as follows: - -\begin{enumerate} -\item Any white space at the start is skipped over. - -\item Further characters are considered, one at a time, until the next -character no longer matches any of the acceptable forms of input -(given the characters that precede it). The longest sequence of -characters which matches is then considered ``read''. - -\item If a suitable sequence of characters was read successfully, it -is converted into a coordinate value which is returned. Any white -space following this sequence is then skipped over and the total -number of characters consumed is returned as the function value. - -c+ -\item If the sequence of characters read is empty, or insufficient to -define a coordinate value, then the string does not contain a value to -read. In this case, the read is aborted and astUnformat returns a -function value of zero and no coordinate value. However, it returns -without error. -c- -f+ -\item If the sequence of characters read is empty, or insufficient to -define a coordinate value, then the string does not contain a value to -read. In this case, the read is aborted and AST\_UNFORMAT returns a -function value of zero and no coordinate value. However, it returns -without error. -f- -\end{enumerate} - -c+ -Note that failing to read a coordinate value does not constitute an -error, at least so far as astUnformat is concerned. However, an error -can occur if the sequence of characters read appears to have the -correct form but cannot be converted into a valid coordinate -value. Typically, this will be because it violates some constraint, -such as a limit on the value of one of its fields. The resulting error -message will give details. -c- -f+ -Note that failing to read a coordinate value does not constitute an -error, at least so far as AST\_UNFORMAT is concerned. However, an -error can occur if the sequence of characters read appears to have the -correct form but cannot be converted into a valid coordinate -value. Typically, this will be because it violates some constraint, -such as a limit on the value of one of its fields. The resulting error -message will give details. -f- - -c+ -For any given Frame axis, astUnformat does not necessarily always use -the same algorithm for converting the sequence of characters it reads -into a coordinate value. This is because some forms of input -(particularly free-format input) can be ambiguous and might be -interpreted in several ways depending on the context. For example, the -celestial longitude ``12:34:56.7'' could represent an angle in degrees -or a right ascension in hours. To decide which to use, astUnformat may -examine the Frame's attributes and, in particular, the appropriate -Format(axis) string which is used by astFormat when formatting -coordinate values (\secref{ss:formattingaxisvalues}). This is done in -order that astFormat and astUnformat should complement each other---so -that formatting a value and then un-formatting it will yield the -original value, subject to any rounding error. -c- -f+ -For any given Frame axis, AST\_UNFORMAT does not necessarily always -use the same algorithm for converting the sequence of characters it -reads into a coordinate value. This is because some forms of input -(particularly free-format input) can be ambiguous and might be -interpreted in several ways depending on the context. For example, the -celestial longitude ``12:34:56.7'' could represent an angle in degrees -or a right ascension in hours. To decide which to use, AST\_UNFORMAT -may examine the Frame's attributes and, in particular, the appropriate -Format(axis) string which is used by AST\_FORMAT when formatting -coordinate values (\secref{ss:formattingaxisvalues}). This is done in -order that AST\_FORMAT and AST\_UNFORMAT should complement each -other---so that formatting a value and then un-formatting it will -yield the original value, subject to any rounding error. -f- - -To give a simple (but crucially incomplete!) example, consider reading -a value for the axis of a basic Frame, as follows: - -c+ -\small -\begin{terminalv} -n = astUnformat( frame, iaxis, " 1.5e6 -99.0", &value ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - N = AST_UNFORMAT( FRAME, IAXIS, ' 1.5E6 -99.0', VALUE, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -astUnformat will skip over the initial space in the string supplied -and then examine each successive character. It will accept the -sequence ``1.5e6'' as input, but reject the space which follows -because it does not form part of the format of a floating point -number. It will then convert the characters ``1.5e6'' into a -coordinate value and skip over the three spaces which follow them. The -returned function value will therefore be 9, equal to the total number -of characters consumed. This result may be used to address the string -during a subsequent read, so as to commence reading at the start of -``-99.0''. -c- -f+ -AST\_UNFORMAT will skip over the initial space in the string supplied -and then examine each successive character. It will accept the -sequence ``1.5E6'' as input, but reject the space which follows -because it does not form part of the format of a floating point -number. It will then convert the characters ``1.5E6'' into a -coordinate value and skip over the three spaces which follow them. The -returned function value will therefore be 9, equal to the total number -of characters consumed. This result may be used to address the string -during a subsequent read, so as to commence reading at the start of -``-99.0''. -f- - -c+ -Most importantly, however, note that if the user of a program -mistakenly enters the string ``~1.5r6\ldots'' instead of -``~1.5e6\ldots'', a coordinate value of 1.5 and a function result of 4 -will be returned, because the ``r'' would prematurely terminate the -attempt to read the value. Because this sort of mistake does not -automatically result in an error but can produce incorrect results, it -is \textbf{vital} to check the returned function value to ensure that -the expected number of characters have been read.\footnote{Anyone who -seriously uses the C run time library ``scanf'' function will know -about the need for this check!} For example, if the string is -expected to contain exactly one value, and nothing else, then the -following would suffice: -c- -f+ -Most importantly, however, note that if the user of a program -mistakenly enters the string ``~1.5R6\ldots'' instead of -``~1.5E6\ldots'', a coordinate value of 1.5 and a function result of 4 -will be returned, because the ``R'' would prematurely terminate the -attempt to read the value. Because this sort of mistake does not -automatically result in an error but can produce incorrect results, it -is \textbf{vital} to check the returned function value to ensure that -the expected number of characters have been read. For example, if the -string is expected to contain exactly one value, and nothing else, -then the following would suffice: -f- - -c+ -\small -\begin{terminalv} -n = astUnformat( frame, iaxis, string, &value ); -if ( astOK ) { - if ( string[ n ] || !n ) { - <error in input data> - } else { - <value read correctly> - } -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - N = AST_UNFORMAT( FRAME, IAXIS, STRING, VALUE, STATUS ) - IF ( STATUS .EQ. 0 ) THEN - IF ( N .LT. LEN( STRING ) ) THEN - <error in input data> - ELSE - <value read correctly> - END IF - END IF -\end{terminalv} -\normalsize -f- - -c+ -If astUnformat does not detect an error itself, we check that it has -read to the end-of-string and consumed at least one character (which -traps the case of a zero-length input string). If this reveals an -error, the value of ``n'' indicates where it occurred. -c- -f+ -If AST\_UNFORMAT does not detect an error itself, we check that it has -read to the end of the string. If this reveals an error, the value of -N indicates where it occurred. -f- - -Another common requirement is to obtain a position by reading a list -of coordinates from a string which contains one value for each axis of -a Frame. We assume that the values are separated in some unambiguous -manner, perhaps using white space and/or some unspecified -single-character separator. The choice of separator is up to the data -supplier, who must choose it so as not to conflict with the format of -the coordinate values, but our software does not need to know what it -is. The following is a template algorithm for reading data in this -form: - -c+ -\small -\begin{terminalv} -const char *s; -double values[ 10 ]; - -... - -/* Initialise a string pointer. */ -s = string; - -/* Obtain the number of Frame axes and loop through them. */ -naxes = astGetI( frame, "Naxes" ); -for ( iaxis = 1; iaxis <= naxes; iaxis++ ) { - -/* Attempt to read a value for this axis. */ - n = astUnformat( frame, iaxis, s, &values[ iaxis - 1 ] ); - -/* If nothing was read and this is not the first axis or the - end-of-string, try stepping over a separator and reading again. */ - if ( !n && ( iaxis > 1 ) && *s ) - n = astUnformat( frame, iaxis, ++s, &values[ iaxis - 1 ] ); - -/* Quit if nothing was read, otherwise move on to the next value. */ - if ( !n ) break; - s += n; -} - -/* Check for possible errors. */ -if ( astOK ) { - if ( *s || !n ) { - <error in input data> - } else { - <values read correctly> - } -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER I - DOUBLE PRECISION VALUES( 10 ) - - ... - -* Initialise the string index. - I = 1 - -* Obtain the number of Frame axes and loop through them. - DO 1 IAXIS = 1, AST_GETI( FRAME, 'Naxes', STATUS ) - -* Attempt to read a value for this axis. - N = AST_UNFORMAT( FRAME, IAXIS, STRING( I : ), - : VALUES( IAXIS ), STATUS ) - -* If nothing was read and this is not the first axis and the end of -* the string has not been reached, try stepping over a separator and -* reading again. - IF ( ( N .EQ. 0 ) .AND. ( IAXIS .GT. 1 ) .AND. - : ( I .LT. LEN( STRING ) ) ) THEN - I = I + 1 - N = AST_UNFORMAT( FRAME, IAXIS, STRING( I : ), - : VALUES( IAXIS ), STATUS ) - END IF - -* Quit if nothing was read, otherwise move on to the next value. - IF ( N .EQ. 0 ) GO TO 2 - I = I + N - 1 CONTINUE - 2 CONTINUE - -* Check for possible errors. - IF ( STATUS .EQ. 0 ) THEN - IF ( ( I .LT. LEN( STRING ) ) .OR. ( N .EQ. 0 ) ) THEN - <error in input data> - ELSE - <values read correctly> - END IF - END IF -\end{terminalv} -\normalsize -f- - -c+ -In this case, ``s'' will point to the location of any input error. -c- -f+ -In this case, the value of I will indicate the location of any input error. -f- - -Note that this algorithm is insensitive to the precise format of the -data and will therefore work with any class of Frame and any -reasonably unambiguous input data. For example, here is a range of -suitable input data for a 3-dimensional basic Frame: - -\small -\begin{terminalv} -1 2.5 3 -3.1,3.2,3.3 -1.5, 2.6, -9.9e2 --1.1+0.4-1.8 - .1/.2/.3 - 44.0 ; 55.1 -14 -\end{terminalv} -\normalsize - -\subsection{\label{ss:permutingaxes}Permuting Frame Axes} - -Once a Frame has been created, it is not possible to change the number -of axes it contains, but it is possible to change the order in which -these axes occur. To do so, an integer \emph{permutation array} is -filled with the numbers of the axes so as to specify the new order, -\emph{e.g.:} - -c+ -\small -\begin{terminalv} -int perm[ 2 ] = { 2, 1 }; -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER PERM( 2 ) - DATA PERM / 2, 1 / -\end{terminalv} -\normalsize -f- - -c+ -In this case, the axes of a 2-dimensional Frame could be interchanged -by passing this permutation array to the astPermAxes function. That -is, an ($x_1,x_2$) coordinate system would be changed into an -($x_2,x_1$) coordinate system by: -c- -f+ -In this case, the axes of a 2-dimensional Frame could be interchanged -by passing this permutation array to the AST\_PERMAXES function. That -is, an ($x_1,x_2$) coordinate system would be changed into an -($x_2,x_1$) coordinate system by: -f- - -c+ -\small -\begin{terminalv} -astPermAxes( frame, perm ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_PERMAXES( FRAME, PERM, STATUS ) -\end{terminalv} -\normalsize -f- - -If the axes are permuted more than once, the effects are cumulative. -You are, of course, not restricted to Frames with only two axes. - -\subsection{Selecting Frame Axes} - -c+ -An alternative to changing the number of Frame axes, which is not -allowed, is to create a new Frame by selecting axes from an existing -one. The method of doing this is very similar to the way astPermAxes -is used (\secref{ss:permutingaxes}), in that we supply an integer -array filled with the numbers of the axes we want, in their new -order. In this case, however, the number of array elements need not -equal the number of Frame axes. -c- -f+ -An alternative to changing the number of Frame axes, which is not -allowed, is to create a new Frame by selecting axes from an existing -one. The method of doing this is very similar to the way AST\_PERMAXES -is used (\secref{ss:permutingaxes}), in that we supply an integer -array filled with the numbers of the axes we want, in their new -order. In this case, however, the number of array elements need not -equal the number of Frame axes. -f- - -For example, we could select axes 3 and 2 (in that order) from a -3-dimensional Frame as follows: - -c+ -\small -\begin{terminalv} -astFrame *frame1, *frame2; -astMapping *mapping; -int pick[ 2 ] = { 3, 2 }; - -... - -frame2 = astPickAxes( frame1, 2, pick, &mapping ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAME1, FRAME2, MAPPING, PICK( 2 ) - DATA PICK / 3, 2 / - - ... - - FRAME2 = AST_PICKAXES( FRAME1, 2, PICK, MAPPING, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This would return a pointer to a 2-dimensional Frame (``frame2'') -which contains the information associated with axes 3 and 2, in that -order, from the original Frame (``frame1''). The original Frame is not -altered by this process. Beware, however, that the axis information -may still be shared by both Frames, so if you wish to alter either of -them independently you may first need to use astCopy -(\secref{ss:copyingobjects}) to make an independent copy. -c- -f+ -This would return a pointer to a 2-dimensional Frame (FRAME2) which -contains the information associated with axes 3 and 2, in that order, -from the original Frame (FRAME1). The original Frame is not altered by -this process. Beware, however, that the axis information may still be -shared by both Frames, so if you wish to alter either of them -independently you may first need to use AST\_COPY -(\secref{ss:copyingobjects}) to make an independent copy. -f- - -c+ -In addition to the new Frame pointer, astPickAxes will also return a -pointer to a new Mapping \emph{via} its fourth argument (you may supply a -NULL pointer as an argument if you do not want this Mapping). This -Mapping will inter-relate the two Frames. By this we mean that its -forward transformation will convert coordinates originally in the -coordinate system represented by ``frame1'' into that represented by -``frame2'', while its inverse transformation will convert in the -opposite direction. In this particular case, the Mapping would be a -PermMap (\secref{ss:permmapexample}) and would implement the following -transformations: -c- -f+ -In addition to the new Frame pointer, AST\_PICKAXES will also return a -pointer to a new Mapping \emph{via} its fourth argument. This Mapping will -inter-relate the two Frames. By this we mean that its forward -transformation will convert coordinates originally in the coordinate -system represented by FRAME1 into that represented by FRAME2, while -its inverse transformation will convert in the opposite direction. In -this particular case, the Mapping would be a PermMap -(\secref{ss:permmapexample}) and would implement the following -transformations: -f- - -\begin{terminalv} -Forward: - (1, 2, 3) --> (3, 2) - (2, 4, 6) --> (6, 4) - (3, 6, 9) --> (9, 6) - (4, 8, 12) --> (12, 8) - (5, 10, 15) --> (15, 10) - -Inverse: - (3, 2) --> (<bad>, 2, 3) - (6, 4) --> (<bad>, 4, 6) - (9, 6) --> (<bad>, 6, 9) - (12, 8) --> (<bad>, 8, 12) - (15, 10) --> (<bad>, 10, 15) -\end{terminalv} - -This is our first introduction to the idea of inter-relating pairs of -Frames \emph{via} a Mapping, but this will assume a central role later on. - -c+ -Note that when using astPickAxes, it is also possible to request more -axes than there were in the original Frame. This will involve -selecting axes from the original Frame that do not exist. To do this, -the corresponding axis number (in the ``pick'' array) should be set to -zero and the effect is to introduce an additional new axis which is -not derived from the original Frame. This axis will have default -values for all its attributes. You will need to do this because -astPickAxes does not allow you to select any of the original axes more -than once.\footnote{It will probably not be obvious why this -restriction is necessary, but consider creating a Frame with one -longitude axis and two latitude axes. Which latitude axis should be -associated with the longitude axis?} -c- -f+ -Note that when using AST\_PICKAXES, it is also possible to request -more axes than there were in the original Frame. This will involve -selecting axes from the original Frame that do not exist. To do this, -the corresponding axis number (in the PICK array) should be set to -zero and the effect is to introduce an additional new axis which is -not derived from the original Frame. This axis will have default -values for all its attributes. You will need to do this because -AST\_PICKAXES does not allow you to select any of the original axes -more than once.\footnote{It will probably not be obvious why this -restriction is necessary, but consider creating a Frame with one -longitude axis and two latitude axes. Which latitude axis should be -associated with the longitude axis?} -f- - -\subsection{\label{ss:distanceandoffset}Calculating Distances, Angles and Offsets} -Some complementary -c+ -functions -c- -f+ -routines -f- -are provided for use with Frames to allow you to perform geometric -operations without needing to know the nature of the coordinate system -represented by the Frame. - -c+ -Functions -c- -f+ -Routines -f- -can be used to find the distance between two points, and to offset a -specified distance along a line joining two points, \emph{etc.} In essence, -these define the metric of the coordinate space which the Frame represents. In -the case of a basic Frame, this is a Cartesian metric. - -c+ -The first of these functions, astDistance, returns a double distance -value when supplied with the Frame coordinates of two points. For -example: -c- -f+ -The first of these routines, AST\_DISTANCE, returns a double precision -distance value when supplied with the Frame coordinates of two -points. For example: -f- - -c+ -\small -\begin{terminalv} -double dist; -double point1[ 2 ] = { 0.0, 0.0 }; -double point2[ 2 ] = { 1.0, 1.0 }; - -... - -dist = astDistance( frame, point1, point2 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION DIST, POINT1( 2 ), POINT2( 2 ) - DATA POINT1 / 0D0, 0D0 / - DATA POINT2 / 1D0, 1D0 / - - ... - - DIST = AST_DISTANCE( FRAME, POINT1, POINT2, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This calculates the distance between the origin (0,0) and a point at -position (1,1). In this case, the result, as you would expect, is -$\surd{2}$. However, this is only true for the Cartesian coordinate -system which a basic Frame represents. In general, astDistance will -calculate the geodesic distance between the two points, so that with a -more specialised Frame (such as a SkyFrame, representing the celestial -sphere) a great-circle distance might be returned. -c- -f+ -This calculates the distance between the origin (0,0) and a point at -position (1,1). In this case, the result, as you would expect, is -$\surd{2}$. However, this is only true for the Cartesian coordinate -system which a basic Frame represents. In general, AST\_DISTANCE will -calculate the geodesic distance between the two points, so that with a -more specialised Frame (such as a SkyFrame, representing the celestial -sphere) a great-circle distance might be returned. -f- - -c+ -The astOffset function is really the inverse of astDistance. Given two -points in a Frame, it calculates the coordinates of a third point -which is offset a specified distance away from the first point along -the geodesic joining it to the second one. For example: -c- -f+ -The AST\_OFFSET routine is really the inverse of AST\_DISTANCE. Given -two points in a Frame, it calculates the coordinates of a third point -which is offset a specified distance away from the first point along -the geodesic joining it to the second one. For example: -f- - -c+ -\small -\begin{terminalv} -double point1[ 2 ] = { 0.0, 0.0 }; -double point2[ 2 ] = { 1.0, 1.0 }; -double point3[ 2 ]; - -... - -astOffset( frame, point1. point2, 0.5, point3 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION POINT1( 2 ), POINT2( 2 ), POINT3( 2 ) - DATA POINT1 / 0D0, 0D0 / - DATA POINT2 / 1D0, 1D0 / - - ... - - CALL AST_OFFSET( FRAME, POINT1, POINT2, 0.5D0, POINT3, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -This would fill the ``point3'' array with the coordinates of a point -which is offset 0.5 units away from the origin (0,0) in the direction -of the position (1,1). Again, this is a simple result in a Cartesian -Frame, as varying the offset will trace out a straight line. On the -celestial sphere, however (\emph{e.g.}\ using a SkyFrame), it would -trace out a great circle. -c- -f+ -This would fill the POINT3 array with the coordinates of a point which -is offset 0.5 units away from the origin (0,0) in the direction of the -position (1,1). Again, this is a simple result in a Cartesian Frame, -as varying the offset will trace out a straight line. On the celestial -sphere, however (\emph{e.g.}\ using a SkyFrame), it would trace out a -great circle. -f- - -c+ -The functions astAxDistance and astAxOffset are similar to astDistance -and astOffset, except that the curves which they use as ``straight -lines'' are not geodesics, but curves parallel to a specified axis\footnote -{For instance, a line of constant Declination is not a geodesic}. One -reason for using these functions is to deal with the cyclic ambiguity of -longitude and latitude axes. -c- -f+ -The routines AST\_AXDISTANCE and AST\_AXOFFSET are similar to AST\_DISTANCE -and AST\_OFFSET, except that the curves which they use as ``straight -lines'' are not geodesics, but curves parallel to a specified axis\footnote -{For instance, a line of constant Declination is not a geodesic}. One -reason for using these routines is to deal with the cyclic ambiguity of -longitude and latitude axes. -f- - -c+ -The astOffset2 function is similar to astOffset, but instead of using the -c- -f+ -The AST\_OFFSET2 routine is similar to AST\_OFFSET, but instead of using the -f- -geodesic which passes through two positions, it uses the geodesic which -passes at a given position angle through the starting position. - -Position angles are always measured from the positive direction of the -second Frame axis to the required line, with positive angles being in the -same sense as rotation from the positive direction of the second axis to -the positive direction of the first Frame axis. This definition applies -to all classes of Frame, including SkyFrame. The default ordering of axes -in a SkyFrame makes the second axis equivalent to north, and so the -definition of position angle given above corresponds to the normal -astronomical usage, ``from north, through east''. However, it should be -remembered that it is possible to permute the axes of a SkyFrame (or -indeed any Frame), so that north becomes axis 1. In this case, an AST -``position angle'' would be the angle ``from east, through north''. -Always take the axis ordering into account when deriving an astronomical -position angle from an AST position angle. - -Within a Cartesian coordinate system, the position angle of a geodesic -(\emph{i.e.}\ a straight line) is constant along its entire length, but -this is not necessarily true of other coordinate systems. Within a -spherical coordinate system, for instance, the position angle of a geodesic -will vary along its length (except for the special cases of a meridian and -the equator). In addition to returning the required offset position, the -c+ -astOffset2 function -c- -f+ -AST\_OFFSET2 routine -f- -returns the position angle of the geodesic at the -offset position. This is useful if you want to trace out a path which -involves turning through specified angles. For instance, tracing out a -rectangle in which each side is a geodesic involves turning through 90 -c+ -degrees at the corners. To do this, use astOffset2 to calculate the -position of each corner, and then add (or subtract) 90 degrees from the -position angle returned by astOffset2. -c- -f+ -degrees at the corners. To do this, use AST\_OFFSET2 to calculate the -position of each corner, and then add (or subtract) 90 degrees from the -position angle returned by AST\_OFFSET2. -f- - -c+ -The astAngle function -c- -f+ -The AST\_ANGLE routine -f- -calculates the angle subtended by two points, at a third point. -If used with a 2-dimensional Frame the returned angle -is signed to indicate the sense of rotation (clockwise or anti-clockwise) -in taking the ``shortest route'' from the first point to the second. -If the Frame has more than 2 axes, the result is un-signed and is always -in the range zero to $\pi$. - -c+ -The astAxAngle function is similar to astAngle, -c- -f+ -The AST\_AXANGLE routine is similar to AST\_AXANGLE, -f- -but the ``reference direction'', from which angles are measured, is -a specified axis. - -c+ -The astResolve function -c- -f+ -The AST\_RESOLVE routine -f- -resolves a given displacement within a Frame into two components, parallel and -perpendicular to a given reference direction. - -The displacement is specified by two positions within the Frame; the -starting and ending positions. The reference direction is defined by the -geodesic curve passing through the starting position and a third specified -position. The lengths of the two components are returned, together with -the position on the reference geodesic which is closest to the third -supplied point. - -\subsection{\label{ss:framedomains}The Domain Attribute} - -The Domain attribute is one of the most important properties of a -Frame, although the concept it expresses can sometimes seem a little -subtle. We will introduce it here, but its true value will probably -not become apparent until later (\secref{ss:framesetconverting}). - -To understand the need for the Domain attribute, consider using -different Frames to represent the following different coordinate -systems associated with a CCD image: - -\begin{enumerate} -\item A coordinate system based on pixel numbers. - -\item Positions on the CCD chip, measured in $\mu$m. - -\item Positions in the focal plane of the telescope, measured in mm. - -\item A celestial coordinate system, measured in radians. -\end{enumerate} - -If we had two such CCD images, we might legitimately want to align -them pixel-for-pixel (\emph{i.e.}\ using the coordinate system based -on pixel numbers) in order to, say, divide by a flat-field exposure. -We might similarly consider aligning them using any of the other -coordinate systems so as to achieve different results. For example, we -might consider merging separate images from a CCD mosaic by using -focal plane positions. - -It would obviously not be legitimate, however, to directly compare -positions in one image measured in pixels with positions in the other -measured in mm, nor to equate chip positions in $\mu$m with sky -coordinates in radians. If we wanted to inter-compare these -coordinates, we would need to do it indirectly, using other -information based on the experimental set-up. For instance, we might -need to know the size of the pixels expressed in mm and the -orientation of the CCD chip in the focal plane. - -Note that it is not simply the difference in physical units which -prevents certain coordinates from being directly inter-compared -(because the appropriate unit scaling factors could be included -without any additional information). Neither is it the fact that -different coordinate systems are in use (because we could legitimately -inter-compare two different celestial coordinate systems without any -extra information). Instead, it is the different nature of the -coordinate spaces to which these coordinate systems have been applied. - -We normally express this by saying that the coordinate systems apply -to different \emph{physical domains}. Although we may establish -\emph{ad hoc} relationships between coordinates in different physical -domains, they are not intrinsically related to each other and we need -to supply extra information before we can convert coordinates between -them. - -In AST, the role of the (character string) Domain attribute is to -assign Frames to their respective physical domains. The way it -operates is as follows: - -\begin{itemize} -\item Coordinate systems which apply to the same physical domain -(\emph{i.e.}\ whose Frames have the same Domain value) can be directly -inter-compared. - -If the domain has several coordinate systems associated with it -(\emph{e.g.}\ the celestial sphere), then a coordinate conversion may -be involved. Otherwise, coordinate values may simply be equated. - -\item Coordinate systems which apply to different physical domains -(\emph{i.e.}\ whose Frames have different Domain values) cannot be -directly inter-compared. - -If any relationship does exist between such coordinate systems---and -it need not---then additional information must be supplied in order to -establish the relationship between them in any particular case. We -will see later (\secref{ss:framesets}) how to establish such -relationships between Frames in different domains. -\end{itemize} - -With the basic Frames we are considering here, each physical domain only -has a single (Cartesian) coordinate system associated with it, so that if -two such Frames have the same Domain value, their coordinate systems will -be identical and may simply be equated. With more specialised Frames, -however, more than one coordinate system may apply to each domain. In -such cases, a coordinate conversion may need to be performed. - -c+ -When a basic Frame is created, its Domain attribute defaults to an -empty string. This means that all such Frames belong to the same -(null) domain by default and therefore describe the same unspecified -physical coordinate space. In order to assign a Frame to a different -domain, you simply need to set its Domain value. This is normally most -conveniently done when it is created, as follows: -c- -f+ -When a basic Frame is created, its Domain attribute defaults to a -blank string. This means that all such Frames belong to the same -(null) domain by default and therefore describe the same unspecified -physical coordinate space. In order to assign a Frame to a different -domain, you simply need to set its Domain value. This is normally most -conveniently done when it is created, as follows: -f- - -c+ -\small -\begin{terminalv} -frame1 = astFrame( 2, "Domain=CCD_CHIP," - "Unit(1)=micron," - "Unit(2)=micron" ); -frame2 = astFrame( 2, "Domain=FOCAL_PLANE," - "Unit(1)=mm," - "Unit(2)=mm" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - FRAME1 = AST_FRAME( 2, 'Domain=CCD_CHIP,' // - 'Unit(1)=micron,' // - 'Unit(2)=micron', STATUS ) - FRAME2 = AST_FRAME( 2, 'Domain=FOCAL_PLANE,' // - 'Unit(1)=mm,' // - 'Unit(2)=mm', STATUS ) -\end{terminalv} -\normalsize -f- - -Here, we have created two Frames in different physical -domains. Although their coordinate values all have units of length, -they cannot be directly inter-compared (because their axes may be -rotated with respect to each other, for instance). - -All Domain values are automatically converted to upper case and white -space is removed, but there are no other restrictions on the names you -may use to label different physical domains. From a practical point of -view, however, it is worth following a few conventions -(\secref{ss:domainconventions}). - -\subsection{\label{ss:domainconventions}Conventions for Domain Names} - -When choosing a value for the Domain attribute of a Frame, it -obviously makes sense to avoid generic names which might clash with -those used for similar (but subtly different!) purposes by other -programmers. If you are developing software for an instrument, for -example, and want to identify an instrumental coordinate system, then -it is sensible to add a distinguishing prefix. For instance, you might -use $<$INST$>$\_FOCAL\_PLANE, where $<$INST$>$ (\emph{e.g.}\ an -acronym) identifies your instrument. - -For some purposes, however, a standard choice of Domain name is -desirable so that different items of software can communicate. For -this purpose, the following Domain names are reserved by AST and the -use recommended below should be carefully observed: - -\begin{quote} -\begin{description} -\item[GRAPHICS]\mbox{}\\ -Identifies the coordinate space used by an underlying computer -graphics system to specify plotting operations. Typically, when -performing graphical operations, AST is used to define additional -coordinate systems which are related to these ``native'' graphical -coordinates. Plotting may be carried out in any of these coordinate -systems, but the GRAPHICS domain identifies the native coordinates -through which AST communicates with the underlying graphics system. - -\item[GRID]\mbox{}\\ -Identifies the instantaneous \emph{data grid} used to store and handle -data, together with an associated coordinate system. In this -coordinate system, the first element stored in an array of data always -has a coordinate value of unity at its centre and all elements have -unit extent. This applies to all dimensions. - -If data are copied or transformed to a new data grid (by whatever -means), or a subset of the original grid is extracted, then the same -rules apply to the copy or subset. Its first element therefore has -GRID coordinate values of unity at its centre. Note that this means -that GRID coordinates remain attached to the first element of the data -grid and not to its data content (\emph{e.g.}\ the features in an -image). - -\item[PIXEL]\mbox{}\\ -Identifies an array of pixels and an associated \emph{pixel-based} -coordinate system which is related to the GRID coordinate system -(above) simply by a shift of origin along each axis. This shift may be -integral, fractional, positive, negative or zero. The data elements -retain their unit extent along each axis. - -Because the amount of shift is unspecified, the PIXEL domain is -distinct from the GRID domain. The relationship between them contains -a degree of uncertainty, such as typically arises from the different -conventions used by different software systems. For instance, in some -software the first pixel is regarded as being centred at (1,1), while -in other software it is at (0.5,0.5). In addition, some software -packages implement a ``pixel origin'' which allows pixel coordinates -to start at an arbitrary value. - -The GRID domain (which corresponds with the pixel-numbering convention -used by FITS) is a special case of the PIXEL domain and avoids this -uncertainty. In general, additional information is required in order -to convert from one to the other. - -\item[SKY]\mbox{}\\ -Identifies the domain which contains all equivalent celestial -coordinate systems. Because these are represented in AST by SkyFrames -(\secref{ss:skyframes}), it should be no surprise that the default -Domain value for a SkyFrame is SKY. Since there is only one sky, you -probably won't need to change this very often. - -\item[SPECTRUM]\mbox{}\\ -Identifies the domain used to describe positions within an -electro-magnetic spectrum. The AST SpecFrame (\secref{ss:specframes}) -class describes positions within this domain, allowing a wide range of -different coordinate systems to be used (frequency, wavelength, -\emph{etc}). The default Domain value for a SpecFrame is SPECTRUM. - -\item[TIME]\mbox{}\\ -Identifies the domain used to describe moments in time. The AST TimeFrame -class describes positions within this domain, allowing a wide range of -different coordinate systems and timescales to be used. The default Domain -value for a TimeFrame is TIME. - -\end{description} -\end{quote} - -Although we have drawn a necessary distinction here between the GRID -and PIXEL domains, we will continue to refer in general terms to image -``pixels'' and ``pixel coordinates'' whenever this distinction is not -important. This should not be taken to imply that the GRID convention -for numbering pixels is excluded---in fact, it is usually to be -preferred (at the level of data handling being discussed in this -document) and we recommend it. - -\subsection{\label{ss:frameunits}The Unit Attribute} -Each axis of a Frame has a Unit attribute which holds the physical units used -to describe positions on the axis. The index of the axis to which the -attribute refers should normally be placed in parentheses following the -attribute name (``Unit(2)'' for instance). However, if the Frame has only -a single axis, then the axis index can be omitted. - -In versions of AST prior to version 2.0, the Unit attribute was nothing -more than a descriptive string intended purely for human readers---no -part of the AST system used the Unit string for any purpose (other than -inclusion in axis labels produced by the Plot class). In particular, no -account was taken of the Unit attribute when finding the Mapping between -two Frames. Thus if the conversion between a pair of 1-dimensional Frames -representing velocity was found (using -c+ -astConvert -c- -f+ -AST\_CONVERT -f- -) the returned Mapping would always be a UnitMap, even if the Unit -attributes of the two Frames were ``km/h'' and ``m/s''. This behaviour is -referred to below as a \emph{passive} Unit attribute. - -As of AST version 2.0, a facility exists which allows the Unit attribute -to be \emph{active}; that is, differences in the -Unit attribute may be taken into account when finding the Mapping between -two Frames. In order to minimise the risk of breaking older software, the -\emph{default} behaviour of simple Frames and SkyFrames is unchanged from -previous versions (\emph{i.e.} they have passive Unit attributes). However, -the new -c+ -functions astSetActiveUnit and astGetActiveUnit -c- -f+ -routines AST\_SETACTIVEUNIT and AST\_GETACTIVEUNIT -f- -allow this default behaviour to be changed. The SpecFrame and TimeFrame -classes \emph{always} have an active Unit attribute (attempts to change this -are ignored). - -For instance, consider the above example of two 1-dimensional Frames -describing velocity. These Frames can be created as follows: - -c+ -\small -\begin{terminalv} -AstFrame *frame1, *frame2; -frame1 = astFrame( 1, "Domain=VELOCITY,Unit=km/h" ); -frame2 = astFrame( 1, "Domain=VELOCITY,Unit=m/s" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAME1, FRAME2 - - FRAME1 = AST_FRAME( 1, 'Domain=VELOCITY,Unit=km/h' ) - FRAME2 = AST_FRAME( 1, 'Domain=VELOCITY,Unit=m/s' ) - -\end{terminalv} -\normalsize -f- - -By default, these Frames have passive Unit attributes, and so an attempt -to find a Mapping between them would ignore the difference in their Unit -attributes and return a unit Mapping. To avoid this, we indicate that we -want these Frames to have \emph{active} Unit attributes, as follows: - -c+ -\small -\begin{terminalv} -astSetActiveUnit( frame1, 1 ); -astSetActiveUnit( frame2, 1 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SETACTIVEUNIT( FRAME1, .TRUE., STATUS ) - CALL AST_SETACTIVEUNIT( FRAME2, .TRUE., STATUS ) -\end{terminalv} -\normalsize -f- - -If we then find the Mapping between them as follows: - -c+ -\small -\begin{terminalv} -AstFrameSet *cvt; -... -cvt = astConvert( frame1, frame2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER CVT - ... - CVT = AST_CONVERT( FRAME1, FRAME2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -the Mapping contained within the FrameSet returned by -c+ -astConvert -c- -f+ -AST\_CONVERT -f- -will be a one-dimensional ZoomMap which simply scales its input (a -velocity in $km/h$) by a factor of 0.278 to create its output (a velocity -in $m/s$). - -c+ -In fact we need not have set the Unit attribute active in ``frame1'' -since the behaviour of astConvert is determined by its ``to'' Frame -(the second Frame parameter). -c- -f+ -In fact we need not have set the Unit attribute active in FRAME1 -since the behaviour of AST\_CONVERT is determined by its TO Frame -(the second Frame argument). -f- - -\subsubsection{\label{ss:unitsyntax}The Syntax for Unit Strings} -Conversion between units systems relies on the use of a specific syntax -for the Unit attribute. If the value of the Unit attribute does not -conform to this syntax, then an error will be reported if an attempt is -made to use it to determine an inter-unit Mapping (this will never happen -if the Unit attribute is \emph{passive}). - -The adopted syntax is that described in FITS-WCS paper I "Representation -of World Coordinate in FITS" by Greisen \& Calabretta. We distinguish -here between ``basic'' units and ``derived'' units: derived units are -defined in terms of other units (either derived or basic), whereas basic -units have no such definitions. Derived units may be represented by their -own \emph{symbol} (\emph{e.g.} ``Jy''---the Jansky) or by a -\emph{mathematical expression} which combines other symbols and constants -to form a definition of the unit (\emph{e.g.} ``km/s''---kilometres per -second). Unit symbols may be prefixed by a string representing a standard -multiple or sub-multiple. - -In addition to the unit symbols listed in FITS-WCS Paper I, any other -arbitrary unit symbol may be used, with the proviso that it will not be -possible to convert between Frames using such units. The exception to -this is if both Frames refer to the same unknown unit string. For instance, -an axis with unknown unit symbol "flop" \emph{could} be converted to an axis -with unit "Mflop" (Mega-flop). - -Unit symbols (optionally prefixed with a multiple or sub-multiple) can be -combined together using a limited range of mathematical operators and -functions, to produce new units. Such expressions may also contain -parentheses and numerical constants (these may optionally use -``scientific'' notation including an ``E'' character to represent the -power of 10). - -The following tables list the symbols for the basic and derived units which -may be included in a units string, the standard prefixes for multiples -and sub-multiples, and the strings which may be used to represent -mathematical operators and functions. - -\begin{table}[htbp] -\begin{center} -\begin{tabular}{|l|l|l|} -\hline -\multicolumn{3}{|c|}{{\large Basic units}} \\ \hline -\multicolumn{1}{|c|}{Quantity} & \multicolumn{1}{|c|}{Symbol} & -\multicolumn{1}{c|}{Full Name} \\ \hline -length & m & metre \\ -mass & g & gram \\ -time & s & second \\ -plane angle & rad & radian \\ -solid angle & sr & steradian \\ -temperature & K & Kelvin \\ -electric current & A & Ampere \\ -amount of substance & mol & mole \\ -luminous intensity & cd & candela \\ -\hline -\end{tabular} -\end{center} -\end{table} - -\begin{table}[htbp] -\begin{center} -\begin{small} -\begin{tabular}{|l|l|l|l|} -\hline -\multicolumn{4}{|c|}{{\large Derived units}} \\ \hline -\multicolumn{1}{|c|}{Quantity} & \multicolumn{1}{|c|}{Symbol} & -\multicolumn{1}{c|}{Full Name} & \multicolumn{1}{c|}{Definition} \\ \hline -area & barn & barn & 1.0E-28 m**2 \\ -area & pix & pixel & \\ -area & pixel & pixel & \\ -electric capacitance & F & Farad & C/V \\ -electric charge & C & Coulomb & A s \\ -electric conductance & S & Siemens & A/V \\ -electric potential & V & Volt & J/C \\ -electric resistance & Ohm & Ohm & V/A \\ -energy & J & Joule & N m \\ -energy & Ry & Rydberg & 13.605692 eV \\ -energy & eV & electron-Volt & 1.60217733E-19 J \\ -energy & erg & erg & 1.0E-7 J \\ -events & count & count & \\ -events & ct & count & \\ -events & ph & photon & \\ -events & photon & photon & \\ -flux density & Jy & Jansky & 1.0E-26 W /m**2 /Hz \\ -flux density & R & Rayleigh & 1.0E10/(4*PI) photon.m**-2 /s/sr \\ -flux density & mag & magnitude & \\ -force & N & Newton & kg m/s**2 \\ -frequency & Hz & Hertz & 1/s \\ -illuminance & lx & lux & lm/m**2 \\ -inductance & H & Henry & Wb/A \\ -length & AU & astronomical unit & 1.49598E11 m \\ -length & Angstrom & Angstrom & 1.0E-10 m \\ -length & lyr & light year & 9.460730E15 m \\ -length & pc & parsec & 3.0867E16 m \\ -length & solRad & solar radius & 6.9599E8 m \\ -luminosity & solLum & solar luminosity & 3.8268E26 W \\ -luminous flux & lm & lumen & cd sr \\ -magnetic field & G & Gauss & 1.0E-4 T \\ -magnetic flux & Wb & Weber & V s \\ -mass & solMass & solar mass & 1.9891E30 kg \\ -mass & u & unified atomic mass unit & 1.6605387E-27 kg \\ -magnetic flux density & T & Tesla & Wb/m**2 \\ -plane angle & arcmin & arc-minute & 1/60 deg \\ -plane angle & arcsec & arc-second & 1/3600 deg \\ -plane angle & mas & milli-arcsecond & 1/3600000 deg \\ -plane angle & deg & degree & pi/180 rad \\ -power & W & Watt & J/s \\ -pressure, stress & Pa & Pascal & N/m**2 \\ -time & a & year & 31557600 s \\ -time & d & day & 86400 s \\ -time & h & hour & 3600 s \\ -time & yr & year & 31557600 s \\ -time & min & minute & 60 s \\ - & D & Debye & 1.0E-29/3 C.m \\ -\hline -\end{tabular} -\end{small} -\end{center} -\end{table} - -\begin{table}[htbp] -\begin{center} -\begin{tabular}{|lll|lll|} -\hline -\multicolumn{6}{|c|}{{\large Prefixes for multiples \& -sub-multiples}} \\ \hline -\multicolumn{1}{|c}{Sub-multiple} & \multicolumn{1}{c}{Name} & -\multicolumn{1}{c|}{Prefix} & -\multicolumn{1}{|c}{Sub-multiple} & \multicolumn{1}{c}{Name} & -\multicolumn{1}{c|}{Prefix} \\ \hline -$10^{-1}$ & deci & d & $10$ & deca & da \\ -$10^{-2}$ & centi & c & $10^{2}$ & hecto & h \\ -$10^{-3}$ & milli & m & $10^{3}$ & kilo & k \\ -$10^{-6}$ & micro & u & $10^{6}$ & mega & M \\ -$10^{-9}$ & nano & n & $10^{9}$ & giga & G \\ -$10^{-12}$ & pico & p & $10^{12}$ & tera & T \\ -$10^{-15}$ & femto & f & $10^{15}$ & peta & P \\ -$10^{-18}$ & atto & a & $10^{18}$ & exa & E \\ -$10^{-21}$ & zepto & z & $10^{21}$ & zetta & Z \\ -$10^{-24}$ & yocto & y & $10^{24}$ & yotta & Y \\ -\hline -\end{tabular} -\end{center} -\end{table} - -\begin{table}[htbp] -\begin{center} -\begin{tabular}{|l|l|} -\hline -\multicolumn{2}{|c|}{{\large Mathematical operators \& functions}} \\ -\hline -\multicolumn{1}{|c|}{String} & \multicolumn{1}{|c|}{Meaning} \\ \hline -sym1 sym2 & multiplication (a space) \\ -sym1*sym2 & multiplication (an asterisk) \\ -sym1.sym2 & multiplication (a dot) \\ -sym1/sym2 & division \\ -sym1**y & exponentiation ($y$ must be a numerical constant)\\ -sym1\verb+^+y & exponentiation ($y$ must be a numerical constant)\\ -log(sym1) & common logarithm \\ -ln(sym1) & natural logarithm \\ -exp(sym1) & exponential \\ -sqrt(sym1) & square root \\ -\hline -\end{tabular} -\end{center} -\end{table} - -\subsubsection{Side-effects of Changing the Unit attribute} -If an Axis has an active Unit attribute, changing its value (either by -setting a new value or by clearing it so that the default value is -re-instated) may cause the Label and Symbol attributes to be changed -accordingly. For instance, if an Axis has Unit, Label and Symbol of ``Hz'', -``Frequency'' and ``nu'', then changing its Unit attribute to ``log(Hz)'' -will cause AST to change its Label and Symbol to ``log(Frequency)'' and -``Log(nu)''. These changes are only made if the Unit attribute is active, -and a Mapping can be found from the old units to the new units. On the other - hand, changing the Unit from ``Hz'' to ``MHz'' would not cause any change -to the Label or Symbol attributes. - -\cleardoublepage -\section{\label{ss:skyframes}Celestial Coordinate Systems (SkyFrames)} - -A Frame which is specialised for representing coordinate systems on -the celestial sphere is obviously of great importance in -astronomy. The SkyFrame is such a Frame. In this section we examine -the additional properties and behaviour of a SkyFrame that distinguish -it from a basic Frame (\secref{ss:frames}). - -\subsection{The SkyFrame Model} - -A SkyFrame is, of course, a Frame (\secref{ss:frames}) and also a -Mapping (\secref{ss:mappings}), so it inherits all the properties and -behaviour of these two ancestral classes. When used as a Mapping, a -SkyFrame implements a unit transformation, exactly like a basic Frame -(\secref{ss:frameasmapping}) or a UnitMap, so this aspect of its -behaviour is not of great importance. - -When used as a Frame, however, a SkyFrame represents a 2-dimensional -\emph{spherical} coordinate system, in which the shortest distance -between two points is a great circle. A SkyFrame therefore always has -exactly two axes which represent the longitude and latitude of a -coordinate system residing on the celestial sphere. Many such -coordinate systems can be represented by a SkyFrame, as we will see -shortly. - -A SkyFrame can represent any of the commonly used celestial coordinate -systems. Optionally, the origin of the longitude/latitude system can be -moved to any specified point in the standard celestial system, allowing -a SkyFrame to represent offsets from a specified sky position. - -c+ -When it is first created, a SkyFrame's axes are always in the order -(longitude,~latitude) but this can be changed, if required, by using the -astPermAxes function (\secref{ss:permutingaxes}). The order of the axes -can be determined at any time using the LatAxis and LonAxis attributes. A -SkyFrame's coordinate values are always stored as angles in (double -precision) radians, regardless of the setting of the Unit attribute -c- -f+ -When it is first created, a SkyFrame's axes are always in the order -(longitude,~latitude) but this can be changed, if required, by using the -AST\_PERMAXES routine (\secref{ss:permutingaxes}). The order of the axes -can be determined at any time using the LatAxis and LonAxis attributes. A -SkyFrame's coordinate values are always stored as angles in (double -precision) radians, regardless of the setting of the Unit attribute -f- -\footnote{The units used for the internal floating-point representation of an -axis value can be determined by examining the InternalUnit attribute of -the Frame. For most Frames, the Unit and InternalUnit attributes will be -equal, but InternalUnit is always set to ``\texttt{rad}'' for SkyFrames.}. - -\subsection{Creating a SkyFrame} - -The SkyFrame constructor function is particularly simple and a -SkyFrame with default attributes is created as follows: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstSkyFrame *skyframe; - -... - -skyframe = astSkyFrame( "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER SKYFRAME, STATUS - - STATUS = 0 - - ... - - SKYFRAME = AST_SKYFRAME( ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -Such a SkyFrame would represent the default celestial coordinate -system which, at present, is the ICRS system (the default was "FK5(J2000)" -in versions of AST prior to 3.0). - -\subsection{Specifying a Particular Celestial Coordinate System} - -For many purposes, the ICRS coordinate system is perfectly -adequate. In order to support conversion between a variety of -celestial coordinate systems, however, you can create SkyFrames that -represent any of these. - -Selection of a particular coordinate system is performed simply by -setting a value for the SkyFrame's (character string) System -attribute. This setting is most conveniently done when the SkyFrame is -created. For example, a SkyFrame representing the old FK4~(B1950.0) -coordinate system would be created by: - -c+ -\small -\begin{terminalv} -skyframe = astSkyFrame( "System=FK4" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SKYFRAME = AST_SKYFRAME( 'System=FK4', STATUS ) -\end{terminalv} -\normalsize -f- - -Note that specifying ``System$=$FK4'' also changes the associated -equinox (from J2000.0 to B1950.0). This is because the default value -of the SkyFrame's Equinox attribute (\secref{ss:equinoxitem}) depends -on the System attribute setting. - -You may change the System value at any time, although this is not -usually needed. The values supported are set out in the attribute's -description in \appref{ss:attributedescriptions} and include a variety -of equatorial coordinate systems, together with ecliptic and galactic -coordinates. - -General spherical coordinates are supported by specifying -``System$=$unknown''. You should note, though, that no Mapping can be -created to convert between ``unknown'' coordinates and any of the other -celestial coordinate systems (see \secref{ss:introducingconversion} ). - -\subsection{Attributes which Qualify Celestial Coordinate Systems} - -Many celestial coordinate systems have some additional free parameters -which serve to identify a particular coordinate system from amongst a -broader class of related coordinate systems. For example, the -FK5~(J2010.0) system is distinguished from the FK5~(J2000.0) -system by a different equinox---and the coordinates of a fixed -astronomical source would have different values when expressed in -these two systems. - -In AST, these free parameters are represented by additional SkyFrame -attributes, each of which has a default appropriate to -(\emph{i.e.}\ defined by) the setting of the main System -attribute. Each of these \emph{qualifying attributes} may, however, be -assigned an explicit value so as to select a particular coordinate -system. Note, it is usually best to assign explicit -values whenever possible rather than relying on defaults. Attribute -should only be left at their default value if you ``don't care'' what -value is used. In certain circumstances (particularly, when aligning two -Frames), a default value for an attribute may be replaced by the value -from another similar Frame. Such value replacement can be prevented by -assigning an explicit value to the attribute, rather than simply relying on -the default. - - -The main SkyFrame attributes which qualify the System attribute are: - -\begin{quote} -\begin{description} - -\item[\label{ss:epochitem}Epoch]\mbox{}\\ -This attribute is inherited from the Frame class. It gives the moment in -time when the coordinates are correct for the astronomical source -under study (usually the date of observation). - -\item[\label{ss:equinoxitem}Equinox]\mbox{}\\ -This value is used to qualify celestial coordinate systems that are -notionally based on the Earth's equator and/or the ecliptic (the plane -of the Earth's orbit around the Sun). The position of either of these -planes is difficult to specify precisely, so in practice a model -\emph{mean} equator and/or ecliptic are used instead. These, together -with the point on the sky that defines the coordinate origin (termed -the \emph{mean equinox}) move with time according to some model which -smoothes out the more rapid fluctuations. The SkyFrame class supports -both the old FK4 model and the newer FK5 one. - -Coordinates expressed in any of these systems vary with time due to -movement (by definition) of the coordinate system itself, and must -therefore be qualified by a moment in time (the \emph{epoch of the mean -equinox}, or ``equinox'' for short) which specifies the position of -the model coordinate system on the sky. This is the role of the -Equinox attribute. - -Note that it is quite valid and common to relate the position of a -source to an equinox other than the date of observation. Usually a -standard equinox such as J2000.0 is used, meaning that the coordinates -are referred to axes defined by where the model mean equator and -ecliptic would lie on the sky at the Julian epoch J2000.0. -\end{description} -\end{quote} - -For further details of these attributes you should consult their -descriptions in \appref{ss:attributedescriptions} and for details of -the System settings for which they are relevant, see the description -of the System attribute (also in \appref{ss:attributedescriptions}). -For the interested reader, an excellent overview of celestial -coordinate systems can also be found in the documentation for the -SLALIB library (\xref{SUN/67}{sun67}{}). - -The value of these qualifying attributes is most conveniently set at -the same time as the System value, \emph{e.g.}\ when a SkyFrame is -created. For instance: - -c+ -\small -\begin{terminalv} -skyframe = astSkyFrame( "System=Ecliptic, Equinox=J2005.5" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SKYFRAME = AST_SKYFRAME( 'System=Ecliptic, Equinox=J2005.5', STATUS ) -\end{terminalv} -\normalsize -f- - -would create a SkyFrame representing an ecliptic coordinate system -referred to the mean equinox and ecliptic of Julian epoch J2005.5. - -Note that it does no harm to assign values to qualifying attributes -which are not relevant to the main System value. Any such values are -stored, but are not used unless the System value is later set so that -they become relevant. - -\subsection{Using Default SkyFrame Attributes} - -c+ -The default values supplied for many SkyFrame attributes will depend -on the value of the SkyFrame's System attribute. In practice, this -means that there is usually little need to specify many of these -attributes explicitly unless you have some special requirement. This -can be illustrated by using astShow to examine a SkyFrame, as follows: -c- -f+ -The default values supplied for many SkyFrame attributes will depend -on the value of the SkyFrame's System attribute. In practice, this -means that there is usually little need to specify many of these -attributes explicitly unless you have some special requirement. This -can be illustrated by using AST\_SHOW to examine a SkyFrame, as -follows: -f- - -c+ -\small -\begin{terminalv} -astShow( astSkyFrame( "System=FK4-NO-E, Epoch=1958" ) ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SHOW( AST_SKYFRAME( 'System=FK4-NO-E, Epoch=1958', STATUS ), STATUS ) -\end{terminalv} -\normalsize -f- - -The output from this might look like the following: - -\begin{terminalv} - Begin SkyFrame # Description of celestial coordinate system -# Title = "FK4 equatorial coordinates; no E-terms; mean equinox B1950.0; -epoch B1958.0" # Title of coordinate system - Naxes = 2 # Number of coordinate axes -# Domain = "SKY" # Coordinate system domain - Epoch = 1958 # Besselian epoch of observation -# Lbl1 = "Right ascension" # Label for axis 1 -# Lbl2 = "Declination" # Label for axis 2 - System = "FK4-NO-E" # Coordinate system type -# Uni1 = "hh:mm:ss.s" # Units for axis 1 -# Uni2 = "ddd:mm:ss" # Units for axis 2 -# Dir1 = 0 # Plot axis 1 in reverse direction -# Bot2 = -1.5707963267949 # Lowest legal axis value -# Top2 = 1.5707963267949 # Highest legal axis value - Ax1 = # Axis number 1 - Begin SkyAxis # Celestial coordinate axis - End SkyAxis - Ax2 = # Axis number 2 - Begin SkyAxis # Celestial coordinate axis - End SkyAxis - IsA Frame # Coordinate system description -# Eqnox = 1950 # Besselian epoch of mean equinox - End SkyFrame -\end{terminalv} - -Note that the defaults (indicated by the ``\verb?#?'' comment -character at the start of the line) for attributes such as the Title, -axis Labels and Format specifiers are all set to values appropriate -for the particular equatorial coordinate system that the SkyFrame -represents. - -c+ -This means, for example, that if we were to use this SkyFrame to -format a right ascension value stored in radians using astFormat -(\secref{ss:formattingaxisvalues}), it would automatically result in a -string in sexagesimal notation (such as ``12:14:35.7'') suitable for -display. If we changed the value of the SkyFrame's Digits attribute -(which is inherited from the Frame class), the number of digits -appearing would also change accordingly. -c- -f+ -This means, for example, that if we were to use this SkyFrame to -format a right ascension value stored in radians using AST\_FORMAT -(\secref{ss:formattingaxisvalues}), it would automatically result in a -string in sexagesimal notation (such as ``12:14:35.7'') suitable for -display. If we changed the value of the SkyFrame's Digits attribute -(which is inherited from the Frame class), the number of digits -appearing would also change accordingly. -f- - -These choices would be appropriate for a System value of ``FK4-NO-E'', -but if a different System value were set, the defaults would be -correspondingly different. For example, ecliptic longitude is -traditionally expressed in degrees, so setting ``System=ecliptic'' -would result in coordinate values being formatted as degrees by -default. - -Of course, if you do not like any of these defaults, you may always -over-ride them by setting explicit attribute values yourself. - -\subsection{\label{ss:formattingskyaxisvalues}Formatting Celestial Coordinates} - -c+ -SkyFrames use astFormat for formatting coordinate values in the same -way as other Frames (\secref{ss:formattingaxisvalues}). However, they -offer a different set of formatting options more appropriate to -celestial coordinates. -c- -f+ -SkyFrames use AST\_FORMAT for formatting coordinate values in the same -way as other Frames (\secref{ss:formattingaxisvalues}). However, they -offer a different set of formatting options more appropriate to -celestial coordinates. -f- - -The Digits attribute of a SkyFrame behaves in essentially the same way -as for a basic Frame (\secref{ss:formattingwithdigits}), so the -precision with which celestial coordinates are displayed can also be -adjusted in this way. However, the range of format specifiers that can -be given for the Format(axis) attribute, and the default format -resulting from any particular Digits value, is different. - -The syntax of SkyFrame format specifiers is detailed under the -description of the Format(axis) attribute in -\appref{ss:attributedescriptions}. Briefly, however, it allows -celestial coordinates to be expressed either as angles or times and to -include one or more of the fields: - -\begin{quote} -\begin{itemize} -\item degrees or hours -\item arc-minutes or minutes -\item arc-seconds or seconds -\end{itemize} -\end{quote} - -with a specified number of decimal places for the final field. A range -of field separators is also available, as the following examples show: - -\begin{quote} -\begin{center} -\begin{tabular}{|l|l|} -\hline -\textbf{Format Specifier} & \textbf{Example Formatted Value}\\ -\hline \hline -{\tt{d}} & {\tt{219}}\\ -{\tt{d.3}} & {\tt{219.123}}\\ -{\tt{dm}} & {\tt{219:05}}\\ -{\tt{dm.2}} & {\tt{219:05.44}}\\ -{\tt{dms}} & {\tt{219:05:42}}\\ -{\tt{hms.1}} & {\tt{15:44:13.8}}\\ -{\tt{bdms.2}} & {\tt{219 05 42.81}}\\ -{\tt{lhms.3}} & {\tt{15h44m13.88s}}\\ -{\tt{+zlhms}} & {\tt{+06h10m44s}}\\ -{\tt{ms.1}} & {\tt{13145:42.8}}\\ -{\tt{lmst.3}} & {\tt{876m22.854s}}\\ -{\tt{s.2}} & {\tt{788742.81}}\\ -\hline -\end{tabular} -\end{center} -\end{quote} - -Note the following key points: - -\begin{itemize} -\item The required fields are specified using characters chosen from -either ``dms'' or ``hms'' according to whether the value is to be -formatted as an angle (in degrees) or a time (in hours). - -\item If no degrees or hours field is required, the distinction -between angle and time may be made by including ``t'' to request time. - -\item The number of decimal places (for the final field) is indicated -using ``\texttt{.}'' followed by an integer. An asterisk can be used in -place of an integer, in which case the number of decimal places is -chosen so that the total number of digits in the formatted value is equal -to the value of the Digits attribute. - -\item ``b'' causes fields to be separated by blanks, while ``l'' -causes them to be separated by the appropriate letters (the default -being a colon). - -\item ``z'' causes padding with leading zeros. - -\item ``+'' cause a plus sign to be prefixed to positive values -(negative values always have a minus sign). -\end{itemize} - -The formatting performed by a SkyFrame is also influenced by the -AsTime(axis) attribute, which has a boolean (integer) value for each -SkyFrame axis. It determines whether the default format specifier for -an axis will present values as angles (\emph{e.g.}\ in degrees) if it -is zero, or as times (\emph{e.g.}\ in hours) if it is non-zero. - -The default AsTime value depends on the celestial coordinate system -which the SkyFrame represents which, in turn, depends on its System -attribute value. For example, equatorial longitude values (right -ascension) are normally expressed in hours, whereas ecliptic -longitudes are normally expressed in degrees, so their default AsTime -values will reflect this difference. - -The value of the AsTime attribute may be set explicitly to over-ride -these defaults if required, with the formatting precision being -determined by the Digits/Digits(axis) value. Alternatively, the -Format(axis) attribute may be set explicitly to specify both the -format and precision required. Setting an explicit Format value always -over-rides the effects of both the Digits and AsTime attributes (unless -the Format value does not specify the required number of decimal places, -in which case Digits is used to determine the default number of decimal -places) - -\subsection{\label{ss:unformattingskyaxisvalues}Reading Formatted Celestial Coordinates} - -c+ -The process of converting formatted celestial coordinates, such as -might be produced by the astFormat function -(\secref{ss:formattingskyaxisvalues}), into numerical (double) -coordinate values is performed by using astUnformat -(\secref{ss:unformattingaxisvalues}) and passing it a pointer to a -SkyFrame. The use of a SkyFrame means that the range of input formats -accepted is appropriate to positions on the sky expressed as angles -and/or times, while the returned value is in radians. -c- -f+ -The process of converting formatted celestial coordinates, such as -might be produced by the AST\_FORMAT function -(\secref{ss:formattingskyaxisvalues}), into numerical (double -precision) coordinate values is performed by using AST\_UNFORMAT -(\secref{ss:unformattingaxisvalues}) and passing it a pointer to a -SkyFrame. The use of a SkyFrame means that the range of input formats -accepted is appropriate to positions on the sky expressed as angles -and/or times, while the returned value is in radians. -f- - -The following describes the forms of celestial coordinate which are -supported: - -\begin{itemize} -\item You may supply an optional sign, followed by between one and -three fields representing either degrees, arc-minutes, arc-seconds or -hours, minutes, seconds (\emph{e.g.}\ ``$-$12~42~03''). - -\item Each field should consist of a sequence of one or more digits, -which may include leading zeros. At most one field may contain a -decimal point, in which case it is taken to be the final field -(\emph{e.g.}\ decimal degrees might be given as ``124.707'', while -degrees and decimal arc-minutes might be given as ``$-$13~33.8''). - -\item The first field given may take any value, allowing angles and -times outside the conventional ranges to be represented. However, -subsequent fields must have values of less than 60 (\emph{e.g.} -``720~45~31'' is valid, whereas ``11~45~61'' is not). - -\item Fields may be separated by white space or by ``:'' (colon), but -the choice of separator must be used consistently throughout the -value. Additional white space may be present around fields and -separators (\emph{e.g.}\ ``$-$~2:~04~:~7.1''). - -\item The following field identification characters may be used as -separators to replace those above (or may be appended to the final -field), in order to identify the field to which they are appended: - -\begin{quote} -\begin{tabular}{lll} -d & -- & degrees \\ -h & -- & hours \\ -m & -- & minutes (of arc or time) \\ -s & -- & seconds (of arc or time) \\ -\texttt{'} & -- & arc-minutes \\ -\texttt{"} & -- & arc-seconds -\end{tabular} -\end{quote} - -Either lower or upper case may be used. Fields must be given in order -of decreasing significance -(\emph{e.g.}\ ``$-$11D~3\texttt{'}~14.4\texttt{"}'' or ``22h14m11.2s''). - -\item The presence of certain field identification characters -indicates whether the value is to be interpreted as an angle or a time -(with 24 hours corresponding to 360 degrees), as follows: - -\begin{quote} -\begin{tabular}{lll} -d & -- & angle \\ -\texttt{'} & -- & angle \\ -\texttt{"} & -- & angle \\ -h & -- & time -\end{tabular} -\end{quote} - -Incompatible angle/time identification characters may not be mixed -(\emph{e.g.}\ ``10h14\texttt{'}3\texttt{"}'' is not valid). The remaining -field identification characters and separators do not specify a -preference for an angle or a time and may be used with either. - -c+ -\item If no preference for an angle or a time is expressed anywhere -within the value, then it is interpreted as an angle if the Format -attribute string associated with the SkyFrame axis generates an angle -and as a time otherwise. This ensures that values produced by -astFormat (\secref{ss:formattingskyaxisvalues}) are correctly -interpreted by astUnformat. -c- -f+ -\item If no preference for an angle or a time is expressed anywhere -within the value, then it is interpreted as an angle if the Format -attribute string associated with the SkyFrame axis generates an angle -and as a time otherwise. This ensures that values produced by -AST\_FORMAT (\secref{ss:formattingskyaxisvalues}) are correctly -interpreted by AST\_UNFORMAT. -f- - -\item Fields may be omitted, in which case they default to zero. The -remaining fields may be identified by using appropriate field -identification characters (see above) and/or by adding extra colon -separators (e.g. ``$-$05m13s'' is equivalent to ``$-$:05:13''). If a field -is not identified explicitly, it is assumed that adjacent fields have -been given, after taking account of any extra separator -characters. For example: - -\begin{quote} -\begin{tabular}{lll} -10d & -- & degrees \\ -10d12 & -- & degrees and arc-minutes \\ -11:14\texttt{"} & -- & arc-minutes and arc-seconds \\ -9h13s & -- & hours and seconds of time \\ -:45:33 & -- & minutes and seconds (of arc or time) \\ -:55: & -- & minutes (of arc or time) \\ -::13 & -- & seconds (of arc or time) \\ -$-$6::2.5 & -- & degrees/hours and seconds (of arc or time) \\ -07m14 & -- & minutes and seconds (of arc or time) \\ -$-$8:14\texttt{'} & -- & degrees and arc-minutes \\ -$-$h3:14 & -- & minutes and seconds of time \\ -h:2.1 & -- & seconds of time -\end{tabular} -\end{quote} - -c+ -\item If fields are omitted in such a way that the remaining ones -cannot be identified uniquely (e.g. ``01:02''), then the first field -(either given explicitly or implied by an extra leading colon -separator) is taken to be the most significant field that astFormat -would produce when formatting a value (using the Format attribute -associated with the SkyFrame axis). By default, this means that the -first field will normally be interpreted as degrees or hours. However, -if this does not result in consistent field identification, then the -last field (either given explicitly or implied by an extra trailing -colon separator) is taken to to be the least significant field that -astFormat would produce. -c- -f+ -\item If fields are omitted in such a way that the remaining ones -cannot be identified uniquely (e.g. ``01:02''), then the first field -(either given explicitly or implied by an extra leading colon -separator) is taken to be the most significant field that AST\_FORMAT -would produce when formatting a value (using the Format attribute -associated with the SkyFrame axis). By default, this means that the -first field will normally be interpreted as degrees or hours. However, -if this does not result in consistent field identification, then the -last field (either given explicitly or implied by an extra trailing -colon separator) is taken to to be the least significant field that -AST\_FORMAT would produce. -f- - -\end{itemize} - -c+ -This final convention is intended to ensure that values formatted by -astFormat which contain less than three fields will be correctly -interpreted if read back using astUnformat, even if they do not -contain field identification characters. However, it also affects -other forms of input. For example, if the Format(axis) string were set -to ``mst.1'' (producing two fields representing minutes and seconds of -time), then formatted input would be interpreted by astUnformat as -follows: -c- -f+ -This final convention is intended to ensure that values formatted by -AST\_FORMAT which contain less than three fields will be correctly -interpreted if read back using AST\_UNFORMAT, even if they do not -contain field identification characters. However, it also affects -other forms of input. For example, if the Format(axis) string were set -to ``mst.1'' (producing two fields representing minutes and seconds of -time), then formatted input would be interpreted by AST\_UNFORMAT as -follows: -f- - -\begin{quote} -\begin{tabular}{lll} -12 13 & -- & minutes and seconds \\ -12 & -- & minutes \\ -:13 & -- & seconds \\ -$-$18: & -- & minutes \\ -12.8 & -- & minutes \\ -1 2 3 & -- & hours, minutes and seconds \\ -& & \\ -4\texttt{'} & -- & arc-minutes \\ -60::\texttt{"} & -- & degrees \\ -$-$23:\texttt{"} & -- & arc-minutes \\ -$-$33h & -- & hours -\end{tabular} -\end{quote} - -(in the last four cases, explicit field identification has been given -which overrides the implicit identification). - -c+ -Alternatively, if the Format(axis) string were set to ``s.3'' -(producing only an arc-seconds field), then formatted input would be -interpreted by astUnformat as follows: -c- -f+ -Alternatively, if the Format(axis) string were set to ``s.3'' -(producing only an arc-seconds field), then formatted input would be -interpreted by AST\_UNFORMAT as follows: -f- - -\begin{quote} -\begin{tabular}{lll} -12.8 & -- & arc-seconds \\ -12 13 & -- & arc-minutes and arc-seconds \\ -:12 & -- & arc-seconds \\ -13: & -- & arc-minutes \\ -1 2 3 & -- & degrees, arc-minutes and arc-seconds -\end{tabular} -\end{quote} - -In general, if you are preparing formatted input data containing -celestial coordinates and wish to omit certain fields, then you are -advised to identify clearly those that you do provide by using the -appropriate field identification characters and/or extra colon -separators. This prevents you depending on the implicit field -identification described above which, in turn, depends on an -appropriate Format(axis) string having been set. - -When writing software, it is also a good idea to set the Format(axis) -string so that data input will be as simple as possible for the -user. Unless some special effect is desired, this normally means that -it should contain ``d'' or ``h'' to ensure that the first field -entered by the user will be interpreted as degrees or hours, unless -otherwise identified. This is the normal behaviour unless an explicit -Format(axis) value has been set to override the default. - -\subsection{Representing Offsets from a Specified Sky Position} -A SkyFrame can be modified so that its longitude and latitude axes are -referred to an origin at any specified sky position. Such a coordinate -system is referred to as an ``offset'' coordinate system. First, the System -attribute should be set to represent the celestial coordinate system in -which the origin is to be specified. Then the SkyRef attribute should be -set to hold the coordinates of the origin within the selected celestial -coordinate system. - -By default, ``north'' in the new offset coordinate system is parallel to -north in the original celestial coordinate system. However, the direction -of north in the offset system can be controlled by assigning a value to -the SkyRefP attribute. This attribute should be assigned the celestial -coordinates of a point which is on the zero longitude meridian and which -has non-zero latitude. - -By default, the position given by the SkyRef attribute is used as the -origin of the new longitude/latitude system, but an option exists to use -it as the north pole of the system instead. This option is controlled by -the SkyRefIs attribute. The choice of value for SkyRefIs depends on what -sort of offset coordinate system you want. Setting SkyRefIs to -``Origin'' (the default) produces an offset coordinate system which is -approximately Cartesian close to the specified position. Setting SkyRefIs -to -``Pole'' produces an offset coordinate system which is approximately Polar -close to the specified position. - -\cleardoublepage -\section{\xlabel{ss_specframes}\label{ss:specframes}Spectral Coordinate Systems (SpecFrames)} - -The SpecFrame is a Frame which is specialised for representing coordinate -systems which describe a position within an electro-magnetic spectrum. -In this section we examine the additional properties and behaviour of a -SpecFrame that distinguish it from a basic Frame (\secref{ss:frames}). - -\subsection{The SpecFrame Model} - -As for a SkyFrame, a SpecFrame is a Frame (\secref{ss:frames}) and also a -Mapping (\secref{ss:mappings}), so it inherits all the properties and -behaviour of these two ancestral classes. When used as a Mapping, a -SpecFrame implements a unit transformation, exactly like a basic Frame -(\secref{ss:frameasmapping}) or a UnitMap, so this aspect of its -behaviour is not of great importance. - -When used as a Frame, however, a SpecFrame represents a wide range of -different 1-dimensional coordinate system which can be used to describe -positions within a spectrum. The options available largely mirror those -described in the FITS-WCS paper III \emph{Representations of spectral -coordinates in FITS} (Greisen, Valdes, Calabretta \& Allen). - -\subsection{Creating a SpecFrame} - -The SpecFrame constructor function is particularly simple and a -SpecFrame with default attributes is created as follows: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstSpecFrame *specframe; - -... - -specframe = astSpecFrame( "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER SPECFRAME, STATUS - - STATUS = 0 - - ... - - SPECFRAME = AST_SPECFRAME( ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -Such a SpecFrame would represent the default coordinate system which is -heliocentric wavelength in metres (i.e. wavelength corrected to take into -account the Doppler shift caused by the velocity of the observer around the -sun). - -\subsection{Specifying a Particular Spectral Coordinate System} - -Selection of a particular coordinate system is performed simply by -setting a value for the SpecFrame's (character string) System -attribute. This setting is most conveniently done when the SpecFrame is -created. For example, a SpecFrame representing Energy would be created by: - -c+ -\small -\begin{terminalv} -specframe = astSpecFrame( "System=Energy" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SPECFRAME = AST_SPECFRAME( 'System=Energy', STATUS ) -\end{terminalv} -\normalsize -f- - -Note that specifying ``System$=$Energy'' also changes the associated -Unit (from metres to Joules). This is because the default value -of the SpecFrame's Unit attribute depends on the System attribute setting. - -You may change the System value at any time, although this is not -usually needed. The values supported are set out in the attribute's -description in \appref{ss:attributedescriptions} and include a variety -of velocity systems, together with frequency, wavelength, energy, -wave-number, \emph{etc}. - -\subsection{Attributes which Qualify Spectral Coordinate Systems} - -Many spectral coordinate systems have some additional free parameters -which serve to identify a particular coordinate system from amongst a -broader class of related coordinate systems. For example, the -velocity systems are all parameterised by a rest frequency---the -frequency which defines zero velocity, and all coordinate systems -are qualified by a `standard of rest'' which indicates the rest frame to -which the values refer. - -In AST, these free parameters are represented by additional SpecFrame -attributes, each of which has a default appropriate to -(\emph{i.e.}\ defined by) the setting of the main System -attribute. Each of these \emph{qualifying attributes} may, however, be -assigned an explicit value so as to select a particular coordinate -system. Note, it is usually best to assign explicit -values whenever possible rather than relying on defaults. Attribute -should only be left at their default value if you ``don't care'' what -value is used. In certain circumstances (particularly, when aligning two -Frames), a default value for an attribute may be replaced by the value -from another similar Frame. Such value replacement can be prevented by -assigning an explicit value to the attribute, rather than simply relying on -the default. - - -The main SpecFrame attributes which qualify the System attribute are: - -\begin{quote} -\begin{description} - -\item[Epoch]\mbox{}\\ -This attribute is inherited from the Frame class. It gives the moment in -time when the coordinates are correct for the astronomical source -under study (usually the date of observation). It is needed in order to -calculate the Doppler shift produced by the velocity of the observer -relative to the centre of the earth, and of the earth relative to the sun. - -\item[StdOfRest]\mbox{}\\ -This specifies the rest frame in which the coordinates are correct. -Transforming between different standards of rest involves taking account -of the Doppler shift introduced by the relative motion of the two -standards of rest. - -\item[RestFreq]\mbox{}\\ -Specifies the frequency which correspond to zero velocity. When setting a -value for this attribute, the value may be supplied as a wavelength -(including an indication of the units being used, ``nm'' ``Angstrom'', -\emph{etc.}), which will be automatically be converted to a frequency. - -\item[RefRA]\mbox{}\\ -Specifies the RA (FK5 J2000) of the source. This is used when converting -between standards of rest. It specifies the direction along which the -component of the relative velocity of the two standards of rest is taken. - -\item[RefDec]\mbox{}\\ -Specifies the Dec (FK5 J2000) of the source. Used in conjunction with -REFRA. - -\item[SourceVel]\mbox{}\\ -This defines the ``source'' standard of rest. This is a rest frame which -is moving towards the position given by RefRA and RefDec, at a velocity -given by SourceVel. The velocity is stored internally as a heliocentric -velocity, but can be given in any of the other supported standards of rest. - -\end{description} -\end{quote} - -For further details of these attributes you should consult their -descriptions in \appref{ss:attributedescriptions} and for details of -the System settings for which they are relevant, see the description -of the System attribute (also in \appref{ss:attributedescriptions}). - -Note that it does no harm to assign values to qualifying attributes -which are not relevant to the main System value. Any such values are -stored, but are not used unless the System value is later set so that -they become relevant. - -\subsection{Using Default SpecFrame Attributes} - -c+ -The default values supplied for many SpecFrame attributes will depend -on the value of the SpecFrame's System attribute. In practice, this -means that there is usually little need to specify many of these -attributes explicitly unless you have some special requirement. This -can be illustrated by using astShow to examine a SpecFrame, as follows: -c- -f+ -The default values supplied for many SpecFrame attributes will depend -on the value of the SpecFrame's System attribute. In practice, this -means that there is usually little need to specify many of these -attributes explicitly unless you have some special requirement. This -can be illustrated by using AST\_SHOW to examine a SpecFrame, as -follows: -f- - -c+ -\small -\begin{terminalv} -astShow( astSpecFrame( "System=Vopt, RestFreq=250 GHz" ) ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SHOW( AST_SPECFRAME( 'System=Vopt, RestFreq=250 GHz', STATUS ), - : STATUS ) -\end{terminalv} -\normalsize -f- - -The output from this might look like the following: - -\begin{terminalv} - Begin SpecFrame # Description of spectral coordinate system -# Title = "Optical velocity, rest frequency = 250 GHz" # Title -of coordinate system - Naxes = 1 # Number of coordinate axes -# Domain = "SPECTRUM" # Coordinate system domain -# Epoch = 2000 # Julian epoch of observation -# Lbl1 = "Optical velocity" # Label for axis 1 - System = "VOPT" # Coordinate system type -# Uni1 = "km/s" # Units for axis 1 - Ax1 = # Axis number 1 - Begin Axis # Coordinate axis - End Axis - IsA Frame # Coordinate system description -# SoR = "Heliocentric" # Standard of rest - RstFrq = 250000000000 # Rest frequency (Hz) - End SpecFrame -\end{terminalv} - -Note that the defaults (indicated by the ``\verb?#?'' comment -character at the start of the line) for attributes such as the Title, -axis Labels and Unit specifiers are all set to values appropriate -for the particular velocity system that the SpecFrame represents. - -These choices would be appropriate for a System value of ``Vopt'', -but if a different System value were set, the defaults would be -correspondingly different. For example, by default frequency is measured in -units of GHz, not $km/s$, so setting ``System=freq'' -would change the appropriate line above from: - -\begin{terminalv} -# Uni1 = "km/s" # Units for axis 1 -\end{terminalv} - -to - -\begin{terminalv} -# Uni1 = "GHz" # Units for axis 1 -\end{terminalv} - -Of course, if you do not like any of these defaults, you may always -over-ride them by setting explicit attribute values yourself. For -instance, you may choose to have your frequency axis expressed in ``kHz'' -rather than ``GHz''. To do this simply set the attribute value as follows: - -c+ -\small -\begin{terminalv} -astSetC( specframe, "Unit", "kHz" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SETC( SPECFRAME, 'Unit', 'kHz', STATUS ) -\end{terminalv} -\normalsize -f- - -No error will be reported if you accidentally set an inappropriate Unit value -(say "J" - Joules)---after all, AST cannot tell what you are about to do, -and you \emph{may} be about to change the System value to ``Energy''. -However, an error \emph{will} be reported if you attempt to find a -conversion between two SpecFrames (for instance using -c+ -astConvert -c- -f+ -AST\_CONVERT -f- -) if either SpecFrame has a Unit value which is inappropriate for its -System value. - -SpecFrame attributes, like all other attributes, all have default -value. However, be aware that for some attributes these default values -can never be more than ``a legal numerical value'' and have no -astronomical significance. For instance, the RefRA and RefDec attributes -(which give the source position) both have a default value of zero. So -unless your source happens to be at that point (highly unlikely!) you will -need to set new values. Likewise, the RestFreq (rest frequency) attribute -has an arbitrary default value of 1.0E5 GHz. Some operations are not -affected by inappropriate values for these attributes (for instance, -converting from frequency to wavelength, changing axis units, \emph{etc}), -but some are. For instance, converting from frequency to velocity -requires a correct rest frequency, moving between different standards of -rest requires a correct source position. The moral is, always set explicit -values for as many attributes as possible. - -\subsection{\label{ss:creatingspectralcubes}Creating Spectral Cubes} -You can use a SpecFrame to describe the spectral axis in a data cube -containing two spatial axes and a spectral axis. To do this you would -create an appropriate SpecFrame, together with a 2-dimensional Frame -(often a SkyFrame) to describe the spatial axes. You would then combine -these two Frames together into a single CmpFrame. - -c+ -\small -\begin{terminalv} -AstSkyFrame *skyframe; -AstSpecFrame *specframe; -AstCmpFrame *cmpframe; -... -skyframe = astSkyFrame( "Epoch=J2002" ); -specframe = astSpecFrame( "System=Freq,StdOfRest=LSRK" ); -cmpframe = astCmpFrame( skyframe, specframe, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER SKYFRAME - INTEGER SPECFRAME - INTEGER CMPFRAME - ... - SKYFRAME = AST_SKYFRAME( 'Epoch=J2002', STATUS ) - SPECFRAME = AST_SPECFRAME( 'System=Freq,StdOfRest=LSRK', - : STATUS ) - CMPFRAME = AST_CMPFRAME( SKYFRAME, SPECFRAME, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -In the resulting CmpFrame, axis 1 will be RA, axis 2 will be Dec and axis -3 will be Frequency. If this is not the order you want, you can permute -the axes using -c+ -astPermAxes. -c- -f+ -AST\_PERMAXES. -f- - -There is one potential problem with this approach if you are interested in -unusually high accuracy. Conversion between different standards of rest -involves taking account of the Doppler shift caused by the relative -motion of the two standards of rest. At some point this involves finding -the component of the relative velocity in the direction of interest. -For a SpecFrame, this direction is always given by the RefRA and RefDec -attributes, even if the SpecFrame is embedded within a CmpFrame as above. -It would be more appropriate if this ``direction of interest'' was -specified by the values passed into the CmpFrame on the RA and DEC axes, -allowing each pixel within a data cube to have a slightly different -correction for Doppler shift. - -Unfortunately, the SpecFrame class cannot do this (since it is purely a -1-dimensional Frame), and so some small degree of error will be -introduced when converting between standards of rest, the size of the -error varying from pixel to pixel. It is hoped that at some point in the -future a sub-class of CmpFrame (a SpecCubeFrame) will be added to AST which -allows for this spatial variation in Doppler shift. - -The maximum velocity error introduced by this problem is of the order of -$V*SIN(FOV)$, where $FOV$ is the angular field of view, and $V$ is the -relative velocity of the two standards of rest. As an example, when -correcting from the observers rest frame (i.e. the topocentric rest -frame) to the kinematic local standard of rest the maximum value of $V$ -is about 20 $km/s$, so for 5 arc-minute field of view the maximum -velocity error introduced by the correction will be about 0.03 $km/s$. As -another example, the maximum error when correcting from the observers -rest frame to the local group is about 5 $km/s$ over a 1 degree field of -view. - -\subsection{\label{ss:handlingdualsidebandspectra}Handling Dual-Sideband Spectra} -Dual sideband super-heterodyne receivers produce spectra in which each channel -contains contributions from two different frequencies, referred to as the -``upper sideband frequency'' and the ``lower sideband frequency''. In the -rest frame of the observer (topocentric), these are related to each other as -follows: - -\begin{quote} -\begin{small} -\begin{equation} -\label{eqn:dsb} - f_{lsb} = 2.f_{LO} - f_{usb} -\end{equation} -\end{small} -\end{quote} - -where $f_{LO}$ is a fixed frequency known as the ``local oscillator -frequency''. In other words, the local oscillator frequency is always -mid-way between any pair of corresponding upper and lower sideband -frequencies\footnote{Note, this simple relationship only applies if all -frequencies are topocentric.}. If you want to describe the spectral axis -of such a spectrum using a SpecFrame you must choose whether you want the -SpecFrame to describe $f_{lsb}$ or $f_{usb}$ - a basic SpecFrame cannot -describe both sidebands simultaneously. However, there is a sub-class of -SpecFrame, called DSBSpecFrame, which overcomes this difficulty. - -A DSBSpecFrame has a SideBand attribute which indicates if the -DSBSpecFrame is currently being used to describe the upper or lower -sideband spectral axis. The value of this attribute can be changed at any -time. If you use the -c+ -astConvert -c- -f+ -AST\_CONVERT -f- -function to find the Mapping between two DSBSpecFrames, the setting for -the two SideBand attributes will be taken into account. Thus, if you take -a copy of a DSBSpecFrame, toggle its SideBand attribute, and then use -c+ -astConvert -c- -f+ -AST\_CONVERT -f- -to find a Mapping from the original to the modified copy, the resulting -Mapping will be of the form of equation \ref{eqn:dsb} (if the -DSBSpecFrame has its StdOfRest attribute set to ``Topocentric''). - -In general, when finding a Mapping between two arbitrary DSBSpecFrames, -the total Mapping is made of of three parts in series: - -\begin{enumerate} -\item A Mapping which converts the first DSBSpecFrame into its upper -sideband representation. If the DSBSpecFrame already represents its upper -sideband, this Mapping will be a UnitMap. -\item A Mapping which converts from the first to the second DSBSpecFrame, -treating them as if they were both basic SpecFrames. This takes account of -any difference in units, standard of rest, system, \emph{etc} between the -two DSBSpecFrames. -\item A Mapping which converts the second DSBSpecFrame from its upper -sideband representation to its current sideband. If the DSBSpecFrame -currently represents its upper sideband, this Mapping will be a UnitMap. -\end{enumerate} - -If an attempt is made to find the Mapping between a DSBSpecFrame and a -basic SpecFrame, then the DSBSpecFrame will be treated like a basic -SpecFrame. In other words, the returned Mapping will not be affected by -the setting of the SideBand attribute (or any of the other attributes -specific to the DSBSpecFrame class). - -In practice, the local oscillator frequency for a dual sideband -instrument may not be easily available to an observer. Instead, it is -common practice to specify the spectral position of some central feature -in the observation (commonly the centre of the instrument passband), -together with an ``intermediate frequency''. Together, these two values -allow the local oscillator frequency to be determined. The intermediate -frequency is the difference between the topocentric frequency at the -central spectral position and the topocentric frequency of the local -oscillator. So: - -\begin{quote} -\begin{small} -\begin{equation} -\label{eqn:dsb2} - f_{LO} = f_{central} + f_{if} -\end{equation} -\end{small} -\end{quote} - -The DSBSpecFrame class uses the DSBCentre attribute to specify the central -spectral position ($f_{central}$), and the IF attribute to specify the -intermediate frequency ($f_{if}$). The DSBCentre value is given and returned -in the spectral system described by the DSBSpecFrame (thus you do not need to -calculate the corresponding topocentric frequency yourself - this will be -done automatically by the DSBSpecFrame when you assign a new value to the -DSBCentre attribute). The value assigned to the IF attribute should -always be a topocentric frequency in units of Hz, however a negative -value may be given to indicate that the DSBCentre value is in the upper -sideband (that is, if $IF < 0$ then $f_{central} > f_{LO}$). A positive -value for IF indicates that the DSBCentre value is in the lower sideband -(that is, if $IF > 0$ then $f_{central} < f_{LO}$). - - -\cleardoublepage -\section{\xlabel{ss_timeframes}\label{ss:timeframes}Time Systems (TimeFrames)} - -The TimeFrame is a Frame which is specialised for representing moments in -time. In this section we examine the additional properties and behaviour of a -TimeFrame that distinguish it from a basic Frame (\secref{ss:frames}). - -\subsection{The TimeFrame Model} - -As for a SkyFrame, a TimeFrame is a Frame (\secref{ss:frames}) and also a -Mapping (\secref{ss:mappings}), so it inherits all the properties and -behaviour of these two ancestral classes. When used as a Mapping, a -TimeFrame implements a unit transformation, exactly like a basic Frame -(\secref{ss:frameasmapping}) or a UnitMap, so this aspect of its -behaviour is not of great importance. - -When used as a Frame, however, a TimeFrame represents a wide range of -different 1-dimensional coordinate system which can be used to describe -moments in time. Absolute times and relative (i.e. elapsed) times are -supported (attribute TimeOrigin), as are a range of different time scales -(attribute TimeScale). An absolute or relative value in any time scale can -be represented in different forms such as Modified Julian Date, Julian Epoch, -\emph{etc} (attribute System). AST extends the definition of these systems to -allow them to be used with any unit of time (attribute Unit). The TimeFrame -class also allows times to formatted as either a simple floating point value -or as a Gregorian date and time of day (attribute Format). - -\subsection{Creating a TimeFrame} - -The TimeFrame constructor function is particularly simple and a -TimeFrame with default attributes is created as follows: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstTimeFrame *timeframe; - -... - -timeframe = astTimeFrame( "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER TIMEFRAME, STATUS - - STATUS = 0 - - ... - - TIMEFRAME = AST_TIMEFRAME( ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -Such a TimeFrame would represent the default coordinate system which is -Modified Julian Date (with the usual units of days) in the International -Atomic Time (TAI) time scale. - -\subsection{Specifying a Particular Time System} -By setting the System attribute appropriately, the TimeFrame can represent -Julian Date, Modified Julian Date, Julian Epoch or Besselian Epoch (the -time scale is specified by a separate attribute called TimeScale). - -Selection of a particular coordinate system is performed simply by -setting a value for the TimeFrame's (character string) System -attribute. This setting is most conveniently done when the TimeFrame is -created. For example, a TimeFrame representing Julian Epoch would be created -by: - -c+ -\small -\begin{terminalv} -timeframe = astTimeFrame( "System=JEPOCH" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - TIMEFRAME = AST_TIMEFRAME( 'System=JEPOCH', STATUS ) -\end{terminalv} -\normalsize -f- - -Note that specifying ``System$=$JEPOCH'' also changes the associated -default Unit (from days to years). This is because the default value -of the TimeFrame's Unit attribute depends on the System attribute setting. - -You may change the System value at any time, although this is not -usually needed. The values supported are set out in the attribute's -description in \appref{ss:attributedescriptions}. - -\subsection{Attributes which Qualify Time Coordinate Systems} - -Time coordinate systems require some additional free parameters to identify -a particular coordinate system from amongst a broader class of related -coordinate systems. For example, all TimeFrames are qualified by the time -scale (that is, the physical process used to define the flow of time), -and some require the position of the observer's clock. - -In AST, these free parameters are represented by additional TimeFrame -attributes, each of which has a default appropriate to (\emph{i.e.}\ defined -by) the setting of the main System attribute. Each of these \emph{qualifying -attributes} may, however, be assigned an explicit value so as to select a -particular coordinate system. Note, it is usually best to assign explicit -values whenever possible rather than relying on defaults. Attribute -should only be left at their default value if you ``don't care'' what -value is used. In certain circumstances (particularly, when aligning two -Frames), a default value for an attribute may be replaced by the value -from another similar Frame. Such value replacement can be prevented by -assigning an explicit value to the attribute, rather than simply relying on -the default. - -The main TimeFrame attributes which qualify the System attribute are: - -\begin{quote} -\begin{description} - -\item[TimeScale]\mbox{}\\ -This specifies the time scale. - -\item[LTOffset]\mbox{}\\ -This specifies the offset from Local Time to UTC in hours (time zones -east of Greenwich have positive values). Note, AST uses the value as -supplied without making any correction for daylight saving. - -\item[TimeOrigin]\mbox{}\\ -This specifies the zero point from which time values are measured, within -the system specified by the System attribute. Thus, a value of zero (the -default) indicates that time values represent absolute times. Non-zero -values may be used to indicate that the TimeFrame represents elapsed time -since the specified origin. - -\end{description} -\end{quote} - -For further details of these attributes you should consult their -descriptions in \appref{ss:attributedescriptions} and for details of -the System settings for which they are relevant, see the description -of the System attribute (also in \appref{ss:attributedescriptions}). - -Note that it does no harm to assign values to qualifying attributes -which are not relevant to the main System or TimeScale value. Any such -values are stored, but are not used unless the System and/or TimeScale -value is later set so that they become relevant. - -\cleardoublepage -\section{\label{ss:cmpframes}Compound Frames (CmpFrames)} - -We now turn to a rather special form of Mapping, the CmpFrame. The -Frames we have considered so far have been atomic, in the sense that -they represent pre-defined elementary physical domains. A CmpFrame, -however, is a compound Frame. In essence, it is a structure for -containing other Frames and its purpose is to allow those Frames -to work together in various combinations while appearing as a single -Object. A CmpFrame's behaviour is therefore not pre-defined, but is -determined by the other Frames it contains (its ``component'' Frames). - -As with compound Mappings, compound Frames can be nested within each -other, forming arbitrarily complex Frames. - -\subsection{Creating a CmpFrame} -A very common use for a CmpFrame within astronomy is to represent a -``spectral cube''. This is a 3-dimensional Frame in which one of the axes -represents position within a spectrum, and the other two axes represent -position on the sky (or some other spatial domain such as the focal plane -of a telescope). As an example, we create such a CmpFrame in which axes -1 and 2 represent Right Ascension and Declination (ICRS), and axis 3 -represents wavelength (these are the default coordinate Systems -represented by a SkyFrame and a SpecFrame respectively): - -c+ -\small -\begin{terminalv} -AstSkyFrame *skyframe; -AstSpecFrame *specframe; -AstCmpFrame *cmpframe; -... -skyframe = astSkyFrame( "" ); -specframe = astSpecFrame( "" ); -cmpframe = astCmpFrame( skyframe, specframe, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER SKYFRAME - INTEGER SPECFRAME - INTEGER CMPFRAME - ... - SKYFRAME = AST_SKYFRAME( ' ', STATUS ) - SPECFRAME = AST_SPECFRAME( ' ', STATUS ) - CMPFRAME = AST_CMPFRAME( SKYFRAME, SPECFRAME, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -If it was desired to make RA and Dec correspond to axes 1 and 3, with -axis 2 being the spectral axis, then the axes of the CmpFrame created -above would need to be permuted as follows: - -c+ -\small -\begin{terminalv} -int perm[ 3 ]; -... - -perm[ 0 ] = 0; -perm[ 1 ] = 2; -perm[ 2 ] = 1; -astPermAxes( cmpframe, perm ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER PERM(3) - ... - - PERM( 1 ) = 1 - PERM( 2 ) = 3 - PERM( 3 ) = 2 - CALL AST_PERMAXES( CMPFRAME, PERM, STATUS ) -\end{terminalv} -\normalsize -f- - -\subsection{The Attributes of a CmpFrame} - -A CmpFrame \emph{is a} Frame and so has all the attributes of a Frame. -The default value for the Domain attribute for a CmpFrame is formed by -concatenating the Domains of the two component Frames, separated by a -minus sign (``-'').\footnote{If both component Frames have blank Domains, -then the default Domain for the CmpFrame is the string ``CMP''.} The (fixed) -value for its System attribute is ``Compound''.\footnote{Any attempt to -change the System value of a CmpFrame is ignored.} A CmpFrame has no -further attributes over and above those common to all Frames. However, -attributes of the two component Frames can be accessed as if they were -attributes of the CmpFrame, as described below. - -Frame attributes which are specific to individual axes (such as Label(2), -Format(1), \emph{etc}) simply mirror the corresponding axes of the -relevant component Frame. That is, if the ``Label(2)'' attribute of a -CmpFrame is accessed, the CmpFrame will forward the access request to the -component Frame which contains axis 2. Thus, default values for axis -attributes will be the same as those provided by the component Frames. - -An axis index can optionally be appended to the name of Frames attributes -which do not normally have such an index (System, Domain, Epoch, Title, -\emph{etc}). If this is done, the access request is forwarded to the -component Frame containing the indicated axis. For instance, if a -CmpFrame contains a SpecFrame and a SkyFrame in that order, and the axes -have not been permuted, then getting the value of attribute ``System'' will -return ``Compound'' as mentioned above (that is, the System value of the -CmpFrame as a whole), whereas getting the value of attribute -``System(1)'' will return ``Spectral''(that is, the System value of the -component Frame containing axis 1 --- the SpecFrame). - -This technique is not limited to attributes common to all Frames. For -instance, the SkyFrame class defines an attribute called Equinox which is -not held by other classes of Frames. To set a value for the Equinox -attribute of the SkyFrame contained within the above CmpFrame, assign the -value to the ``Equinox(2)'' attribute of the CmpFrame. Since the SkyFrame -defines both axes 2 and 3 of the CmpFrame, we could equivalently have set -a value for ``Equinox(3)'' since this would also result in the attribute -access being forwarded to the SkyFrame. - -Finally, if an attribute is not qualified by a axis index, attempts will -be made to access it using each of the CmpFrame axes in turn. Using the -above example of the spectral cube, if an attempt was made to get the -value of attribute ``Equinox'' (with no axis index), each axis in turn -would be used. Since axis 1 is contained within a SpecFrame, the first -attempt would fail since the SpecFrame class does not have an Equinox -attribute. However, the second attempt would succeed because axis 2 is -contained within a SkyFrame which \emph{does} have an Equinox attribute. Thus -the returned attribute value would be that obtained from the SkyFrame -containing axis 2. When getting or testing an attribute value, the -returned value is determined by the \emph{first} axis which recognises -the attribute. When setting an attribute value, \emph{all} axes -which recognises the attribute have the attribute value set to the given -value. Likewise, when clearing an attribute value, all axes -which recognises the attribute have the attribute value cleared. - -\cleardoublepage -\section{\label{ss:introducingconversion}An Introduction to Coordinate System Conversions} - -In this section, we start to look at techniques for converting between -different coordinate systems. At this stage, the tools we have available -are Frames (\secref{ss:frames}), SkyFrames (\secref{ss:skyframes}), -SpecFrames (\secref{ss:specframes}), TimeFrames (\secref{ss:timeframes}) and -various Mappings (\secref{ss:mappings}). These are sufficient to allow us to -begin examining the problem, but more sophisticated approaches will also emerge -later (\secref{ss:framesetconverting}). - -\subsection{\label{ss:convertingskyframes}Converting between Celestial Coordinate Systems} - -We begin by examining how to convert between two celestial coordinate -systems represented by SkyFrames, as this is both an illuminating and -practical example. Consider the problem of converting celestial -coordinates between: - -\begin{enumerate} -\item The old FK4 system, with no E terms, a Besselian epoch of -1958.0 and a Besselian equinox of 1960.0. - -\item An ecliptic coordinate system based on the mean equinox and -ecliptic of Julian epoch 2010.5. -\end{enumerate} - -This example is arbitrary but not completely unrealistic. Unless you -already have expertise with such conversions, you are unlikely to find -it straightforward. - -Using AST, we begin by creating two SkyFrames to represent these -coordinate systems, as follows: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstSkyFrame *skyframe1, *skyframe2; - -... - -skyframe1 = astSkyFrame( "System=FK4-NO-E, Epoch=B1958, Equinox=B1960" ); -skyframe2 = astSkyFrame( "System=Ecliptic, Equinox=J2010.5" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER SKYFRAME1, SKYFRAME2, STATUS - - STATUS = 0 - - ... - - SKYFRAME1 = AST_SKYFRAME( 'System=FK4-NO-E, Epoch=B1958, Equinox=B1960', STATUS ) - SKYFRAME2 = AST_SKYFRAME( 'System=Ecliptic, Equinox=J2010.5', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Note how specifying the coordinate systems consists simply of -initialising the attributes of each SkyFrame appropriately. The next -step is to find a way of converting between these SkyFrames. This is -done using astConvert, as follows: -c- -f+ -Note how specifying the coordinate systems consists simply of -initialising the attributes of each SkyFrame appropriately. The next -step is to find a way of converting between these SkyFrames. This is -done using AST\_CONVERT, as follows: -f- - -c+ -\small -\begin{terminalv} -AstFrameSet *cvt; - -... - -cvt = astConvert( skyframe1, skyframe2, "" ); -if ( cvt == AST__NULL ) { - <conversion is not possible> -} else { - <conversion is possible> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER CVT - - ... - - CVT = AST_CONVERT( SKYFRAME1, SKYFRAME2, ' ', STATUS ) - IF ( CVT .EQ. AST__NULL ) THEN - <conversion is not possible> - ELSE - <conversion is possible> - END IF -\end{terminalv} -\normalsize -f- - -c+ -The third argument of astConvert is not used here and should be an -empty string. -c- -f+ -The third argument of AST\_CONVERT is not used here and should be a -blank string. -f- - -c+ -astConvert will return a null result, AST\_\_NULL (as defined in the -``ast.h'' header file), if conversion is not possible. In this -example, conversion is possible, so it will return a pointer to a new -Object that describes the conversion. -c- -f+ -AST\_CONVERT will return a null result, AST\_\_NULL (as defined in the -AST\_PAR include file), if conversion is not possible. In this -example, conversion is possible, so it will return a pointer to a new -Object that describes the conversion. -f- - -The Object returned is called a FrameSet. We have not discussed -FrameSets yet (\secref{ss:framesets}), but for the present purposes we -can consider them simply as Objects that can behave both as Mappings -and as Frames. It is the FrameSet's behaviour as a Mapping in which we -are mainly interested here, because the Mapping it implements is the -one we require---\emph{i.e.}\ it converts between the two celestial -coordinate systems (\secref{ss:framesetsfromconvert}). - -c+ -For example, if ``alpha1'' and ``delta1'' are two arrays containing -the longitude and latitude, in radians, of N points on the sky in the -original coordinate system (corresponding to ``skyframe1''), then they -could be converted into the new coordinate system (represented by -``skyframe2'') as follows: -c- -f+ -For example, if ALPHA1 and DELTA1 are two arrays containing the -longitude and latitude, in radians, of N points on the sky in the -original coordinate system (corresponding to SKYFRAME1), then they -could be converted into the new coordinate system (represented by -SKYFRAME2) as follows: -f- - -c+ -\small -\begin{terminalv} -#define N 10 -double alpha1[ N ], delta1[ N ]; -double alpha2[ N ], delta2[ N ]; - -... - -astTran2( cvt, N, alpha1, delta1, 1, alpha2, delta2 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER N - DOUBLE PRECISION ALPHA1( N ), DELTA1( N ) - DOUBLE PRECISION ALPHA2( N ), DELTA2( N ) - - ... - - CALL AST_TRAN2( CVT, N, ALPHA1, DELTA1, .TRUE., ALPHA2, DELTA2, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The new coordinates are returned \emph{via} the ``alpha2'' and -``delta2'' arrays. To transform coordinates in the opposite -direction, we simply invert the 5th (boolean int) argument to -astTran2, as follows: -c- -f+ -The new coordinates are returned \emph{via} the ALPHA2 and DELTA2 -arrays. To transform coordinates in the opposite direction, we simply -invert the 5th (logical) argument to AST\_TRAN2, as follows: -f- - -c+ -\small -\begin{terminalv} -astTran2( cvt, N, alpha2, delta2, 0, alpha1, delta1 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_TRAN2( CVT, N, ALPHA2, DELTA2, .FALSE., ALPHA1, DELTA1, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The FrameSet returned by astConvert also contains information about -the SkyFrames used in the conversion -(\secref{ss:framesetsfromconvert}). As we mentioned above, a FrameSet -may be used as a Frame and in this case it behaves like the -``destination'' Frame used in the conversion (\emph{i.e.}\ like -``skyframe2''). We could therefore use the ``cvt'' FrameSet to -calculate the distance between two points (with coordinates in -radians) in the destination coordinate system, using astDistance: -c- -f+ -The FrameSet returned by AST\_CONVERT also contains information about -the SkyFrames used in the conversion -(\secref{ss:framesetsfromconvert}). As we mentioned above, a FrameSet -may be used as a Frame and in this case it behaves like the -``destination'' Frame used in the conversion (\emph{i.e.}\ like -SKYFRAME2). We could therefore use the CVT FrameSet to calculate the -distance between two points (with coordinates in radians) in the -destination coordinate system, using AST\_DISTANCE: -f- - -c+ -\small -\begin{terminalv} -double distance, point1[ 2 ], point2[ 2 ]; - -... - -distance = astDistance( cvt, point1, point2 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION DISTANCE, POINT1( 2 ), POINT2( 2 ) - - ... - - DISTANCE = AST_DISTANCE( CVT, POINT1, POINT2, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -and the result would be the same as if the ``skyframe2'' SkyFrame had -been used. -c- -f+ -and the result would be the same as if the SKYFRAME2 SkyFrame had been -used. -f- - -Another way to see how the FrameSet produced by astConvert retains -information about the coordinate systems involved is to set its Report -attribute (inherited from the Mapping class) so that it displays the -coordinates before and after conversion (\secref{ss:transforming}): - -c+ -\small -\begin{terminalv} -astSet( cvt, "Report=1" ); -astTran2( cvt, N, alpha1, delta1, 1, alpha2, delta2 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( CVT, 'Report=1', STATUS ) - CALL AST_TRAN2( CVT, N, ALPHA1, DELTA1, .TRUE., ALPHA2, DELTA2, STATUS ) -\end{terminalv} -\normalsize -f- - -The output from this might look like the following: - -\begin{terminalv} -(2:06:03.0, 34:22:39) --> (42.1087, 20.2717) -(2:08:20.6, 35:31:24) --> (43.0197, 21.1705) -(2:10:38.1, 36:40:09) --> (43.9295, 22.0716) -(2:12:55.6, 37:48:55) --> (44.8382, 22.9753) -(2:15:13.1, 38:57:40) --> (45.7459, 23.8814) -(2:17:30.6, 40:06:25) --> (46.6528, 24.7901) -(2:19:48.1, 41:15:11) --> (47.5589, 25.7013) -(2:22:05.6, 42:23:56) --> (48.4644, 26.6149) -(2:24:23.1, 43:32:41) --> (49.3695, 27.5311) -(2:26:40.6, 44:41:27) --> (50.2742, 28.4499) -\end{terminalv} - -Here, we see that the input FK4 equatorial coordinate values (given in -radians) have been formatted automatically in sexagesimal notation -using the conventional hours for right ascension and degrees for -declination. Conversely, the output ecliptic coordinates are shown in -decimal degrees, as is conventional for ecliptic coordinates. Both are -displayed using the default precision of 7 digits.\footnote{The -leading digit is zero and is therefore not seen in this particular -example.} - -c+ -In fact, the ``cvt'' FrameSet has access to all the information in the -original SkyFrames which were passed to astConvert. If you had set a -new Digits attribute value for either of these, the formatting above -would reflect the different precision you requested by displaying a -greater or smaller number of digits. -c- -f+ -In fact, the CVT FrameSet has access to all the information in the -original SkyFrames which were passed to AST\_CONVERT. If you had set a -new Digits attribute value for either of these, the formatting above -would reflect the different precision you requested by displaying a -greater or smaller number of digits. -f- - - -\subsection{\label{ss:convertingspecframes}Converting between Spectral Coordinate Systems} -The principles described in the previous section for converting between -celestial coordinate systems also apply to the task of converting between -spectral coordinate systems. As an example, let's look at how we might -convert between frequency measured in $GHz$ as measured in the rest frame -of the telescope, and radio velocity measured in $km/s$ measured with -respect the kinematic Local Standard of Rest. - -First we create a default SpecFrame, and then set its attributes to -describe the required radio velocity system (this is slightly more -convenient, given the relatively large number of attributes, than -specifying the attribute values in a single string such as would be -passed to the SpecFrame constructor). We then take a copy of this -SpecFrame, and change the attribute values so that the copy describes the -original frequency system (modifying a copy, rather than creating a new -SpecFrame from scratch, avoids the need to specify the epoch, reference -position, \emph{etc} a second time since they are all inherited by the copy): - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstSpecFrame *specframe1, *specframe2; - -... - -specframe1 = astSpecFrame( "" ); -astSet( specframe1, "System=vradio" ); -astSet( specframe1, "Unit=km/s" ); -astSet( specframe1, "Epoch=1996-Oct-2 12:13:56.985" ); -astSet( specframe1, "ObsLon=W155:28:18" ); -astSet( specframe1, "ObsLat=N19:49:34" ); -astSet( specframe1, "RefRA=18:14:50.6" ); -astSet( specframe1, "RefDec=-4:40:49" ); -astSet( specframe1, "RestFreq=230.538 GHz" ); -astSet( specframe1, "StdOfRest=LSRK" ); - -specframe2 = astCopy( specframe1 ); -astSet( specframe1, "System=freq" ); -astSet( specframe1, "Unit=GHz" ); -astSet( specframe1, "StdOfRest=Topocentric" ); - -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER SPECFRAME1, SPECFRAME2, STATUS - - STATUS = 0 - - ... - - SPECFRAME1 = AST_SPECFRAME( ' ', STATUS ) - CALL AST_SETC( SPECFRAME1, 'System=vradio', STATUS ) - CALL AST_SETC( SPECFRAME1, 'Unit=km/s', STATUS ) - CALL AST_SETC( SPECFRAME1, 'Epoch=1996-Oct-2 12:13:56.985', - : STATUS ) - CALL AST_SETC( SPECFRAME1, 'ObsLon=W155:28:18', STATUS ) - CALL AST_SETC( SPECFRAME1, 'ObsLat=N19:49:34', STATUS ) - CALL AST_SETC( SPECFRAME1, 'RefRA=18:14:50.6', STATUS ) - CALL AST_SETC( SPECFRAME1, 'RefDec=-4:40:49', STATUS ) - CALL AST_SETC( SPECFRAME1, 'RestFreq=230.538 GHz', STATUS ) - CALL AST_SETC( SPECFRAME1, 'StdOfRest=LSRK', STATUS ) - - SPECFRAME2 = AST_COPY( SPECFRAME1, STATUS ) - CALL AST_SETC( SPECFRAME1, 'System=freq', STATUS ) - CALL AST_SETC( SPECFRAME1, 'Unit=GHz', STATUS ) - CALL AST_SETC( SPECFRAME1, 'StdOfRest=Topocentric', STATUS ) - -\end{terminalv} -\normalsize -f- - -Note, the fact that a SpecFrame has only a single axis means that we were -able to refer to the Unit attribute without an axis index. The other -attributes are: the time of of observation (Epoch), the geographical -position of the telescope (ObsLat \& ObsLon), the position of the source -on the sky (RefRA \& RefDec), the rest frequency (RestFreq) and the -standard of rest (StdOfRest). - -The next step is to find a way of converting between these SpecFrames. We -use exactly the same code that we did in the previous section where we were -converting between celestial coordinate systems: - -c+ -\small -\begin{terminalv} -AstFrameSet *cvt; - -... - -cvt = astConvert( specframe1, specframe2, "" ); -if ( cvt == AST__NULL ) { - <conversion is not possible> -} else { - <conversion is possible> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER CVT - - ... - - CVT = AST_CONVERT( SPECFRAME1, SPECFRAME2, ' ', STATUS ) - IF ( CVT .EQ. AST__NULL ) THEN - <conversion is not possible> - ELSE - <conversion is possible> - END IF -\end{terminalv} -\normalsize -f- - -A before, this will give us a FrameSet (assuming conversion is possible, -which should always be the case for our example), and we can use the -FrameSet to convert between the two spectral coordinate systems. We use -c+ -astTran1 in place of astTran2 -c- -f+ -AST\_TRAN1 in place of AST\_TRAN2 -f- -since a SpecFrame has only one axis (unlike a SkyFrame which has two). - -c+ -For example, if ``frq'' is an array containing the observed frequency, in -GHz, of N spectral channels (describe by ``specframe1''), then they -could be converted into the new coordinate system (represented by -``specframe2'') as follows: -c- -f+ -For example, if FRQ is an array containing the observed frequency, in -GHz, of N spectral channels (describe by SPECFRAME1), then they -could be converted into the new coordinate system (represented by -SPECFRAME2) as follows: -f- - -c+ -\small -\begin{terminalv} -#define N 10 -double frq[ N ]; -double vel[ N ]; - -... - -astTran1( cvt, N, frq, 1, vel ); -\end{terminalv} -\normalsize - -The radio velocity values are returned in the ``vel'' array. - -c- -f+ -\small -\begin{terminalv} - INTEGER N - DOUBLE PRECISION FRQ( N ) - DOUBLE PRECISION VEL( N ) - - ... - - CALL AST_TRAN1( CVT, N, FRQ, .TRUE., VEL, STATUS ) -\end{terminalv} -\normalsize - -The radio velocity values are returned in the VEL array. -f- - -\subsection{Converting between Time Coordinate Systems} -All the principles outlined in the previous section about aligning -spectral cocordinate systems (SpecFrames) can be applied directly to the -problem of aligning time coordinate systems (TimeFrames). - -\subsection{\label{ss:convertingpermutedaxes}Handling SkyFrame Axis Permutations} - -c+ -We can illustrate an important point if we swap the axis order of -either SkyFrame in the example above (\secref{ss:convertingskyframes}) -before identifying the conversion. Let's assume we use astPermAxes -(\secref{ss:permutingaxes}) to do this to the second SkyFrame, before -applying astConvert, as follows: -c- -f+ -We can illustrate an important point if we swap the axis order of -either SkyFrame in the example above (\secref{ss:convertingskyframes}) -before identifying the conversion. Let's assume we use AST\_PERMAXES -(\secref{ss:permutingaxes}) to do this to the second SkyFrame, before -applying AST\_CONVERT, as follows: -f- - -c+ -\small -\begin{terminalv} -int perm[ 2 ] = { 2, 1 }; - -... - -astPermAxes( skyframe2, perm ); -cvt = astConvert( skyframe1, skyframe2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER PERM( 2 ) - DATA PERM / 2, 1 / - - ... - - CALL AST_PERMAXES( SKYFRAME2, PERM, STATUS ) - CVT = AST_CONVERT( SKYFRAME1, SKYFRAME2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -Now, the destination SkyFrame system no longer represents the -coordinate system: - -\begin{quote} -(ecliptic~longitude, ecliptic~latitude) -\end{quote} - -but instead represents the transposed system: - -\begin{quote} -(ecliptic~latitude, ecliptic~longitude) -\end{quote} - -c+ -As a consequence, when we use the FrameSet returned by astConvert to -apply a coordinate transformation, we obtain something like the -following: -c- -f+ -As a consequence, when we use the FrameSet returned by AST\_CONVERT to -apply a coordinate transformation, we obtain something like the -following: -f- - -\begin{terminalv} -(2:06:03.0, 34:22:39) --> (20.2717, 42.1087) -(2:08:20.6, 35:31:24) --> (21.1705, 43.0197) -(2:10:38.1, 36:40:09) --> (22.0716, 43.9295) -(2:12:55.6, 37:48:55) --> (22.9753, 44.8382) -(2:15:13.1, 38:57:40) --> (23.8814, 45.7459) -(2:17:30.6, 40:06:25) --> (24.7901, 46.6528) -(2:19:48.1, 41:15:11) --> (25.7013, 47.5589) -(2:22:05.6, 42:23:56) --> (26.6149, 48.4644) -(2:24:23.1, 43:32:41) --> (27.5311, 49.3695) -(2:26:40.6, 44:41:27) --> (28.4499, 50.2742) -\end{terminalv} - -When compared to the original (\secref{ss:convertingskyframes}), the -output coordinate order has been swapped to compensate for the -different destination SkyFrame axis order. - -c+ -In all, there are four possible axis combinations, corresponding to two -possible axis orders for each of the source and destination SkyFrames, -and astConvert will convert correctly between any of these. -c- -f+ -In all, there are four possible axis combinations, corresponding to two -possible axis orders for each of the source and destination SkyFrames, -and AST\_CONVERT will convert correctly between any of these. -f- -The point to note is that a SkyFrame contains knowledge about how to -convert to and from other SkyFrames. Since its two axes (longitude and -latitude) are distinguishable, the conversion is able to take account -of the axis order. - -If you need to identify the axes of a SkyFrame explicitly, taking into -account any axis permutations, the LatAxis and LonAxis attributes can be -used. These are read-only attributes which give the indices of the -latitude and longitude axes respectively. - -\subsection{\label{ss:convertingframes}Converting Between Frames} - -c+ -Having seen how clever SkyFrames are (\secref{ss:convertingskyframes} -and \secref{ss:convertingpermutedaxes}), we will next examine how dumb -a basic Frame can be in comparison. For example, if we create two -2-dimensional Frames and use astConvert to derive a conversion between -them, as follows: -c- -f+ -Having seen how clever SkyFrames are (\secref{ss:convertingskyframes} -and \secref{ss:convertingpermutedaxes}), we will next examine how dumb -a basic Frame can be in comparison. For example, if we create two -2-dimensional Frames and use AST\_CONVERT to derive a conversion -between them, as follows: -f- - -c+ -\small -\begin{terminalv} -AstFrame *frame1, *frame2; - -... - -frame1 = astFrame( 2, "" ); -frame2 = astFrame( 2, "" ); -cvt = astConvert( frame1, frame2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAME1, FRAME2 - - ... - - FRAME1 = AST_FRAME( 2, ' ', STATUS ) - FRAME2 = AST_FRAME( 2, ' ', STATUS ) - CVT = AST_CONVERT( FRAME1, FRAME2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -then the coordinate transformation which the ``cvt'' FrameSet performs -will be as follows: -c- -f+ -then the coordinate transformation which the ``cvt'' FrameSet performs -will be as follows: -f- - -\begin{terminalv} -(1, 2) --> (1, 2) -(2, 4) --> (2, 4) -(3, 6) --> (3, 6) -(4, 8) --> (4, 8) -(5, 10) --> (5, 10) -\end{terminalv} - -This is an identity transformation, exactly the same as a UnitMap -(\secref{ss:unitmapexample}). Even if we permute the axis order of our -Frames, as we did above (\secref{ss:convertingpermutedaxes}), we will -fare no better. The conversion between our two basic Frames will -always be an identity transformation. - -The reason for this is that, unlike a SkyFrame, all basic Frames start -life the same and have axes that are indistinguishable. Therefore, -permuting their axes doesn't make them look any different---they still -represent the same coordinate system. -%Actually, this behaviour isn't as dumb as it seems and can actually be -%very useful, as the following example illustrates. -% -%\subsection{Distinguishable and Indistinguishable Axes} -% -%c+ -%Imagine you have two Frames which represent the pixel coordinates of -%two 2-dimensional images. Let's call their axes ``X'' and ``Y''. -%Suppose you now transpose the second image and swap its Frame axes -%(with astPermAxes) to take account of this. -%c- -%f+ -%Imagine you have two Frames which represent the pixel coordinates of -%two 2-dimensional images. Let's call their axes ``X'' and ``Y''. -%Suppose you now transpose the second image and swap its Frame axes -%(with astPermAxes) to take account of this. -%f- -% -%Next, consider what happens if you want to subtract one image from the -%other. If you have a ``subtract'' program that is intelligent and -%tries to align the two images for you, one of two things could happen: -% -%\begin{enumerate} -%c+ -%\item If the axes are distinguishable, when your program invokes -%astConvert it will derive a transformation between the two images -%which swaps the X and Y coordinates (corresponding to the transposition -%you applied to the second image). However, in aligning X-with-X and -%Y-with-Y, this will completely undo the effects of your transposition! -%c- -%f+ -%\item If the axes are distinguishable, when your program invokes -%AST\_CONVERT it will derive a transformation between the two images -%which swaps the X and Y coordinates (corresponding to the transposition -%you applied to the second image). However, in aligning X-with-X and -%Y-with-Y, this will completely undo the effects of your transposition! -%f- -% -%\item If the axes are indistinguishable, the transformation between -%the two images will always be an identity -%(\secref{ss:convertingframes}). Therefore, your program will align -%X-with-Y and Y-with-X, so that you see the effects of your earlier -%transposition of the second image. -%\end{enumerate} -% -%Clearly, if we are considering pixel coordinates, the latter behaviour -%is preferable, since there would be no point in implementing an image -%transposition program if we could never see the effects of it. This -%indicates that a basic Frame, with is indistinguishable axes, is the -%correct type of Object to represent a pixel coordinate system, where -%this behaviour is necessary. -% -%Conversely, the former behaviour would be more useful if the axes we -%were considering were, say, wavelength (in nm) and slit position (in -%mm). In this case, we would expect our ``subtract'' program to -%subtract data at corresponding wavelengths and slit positions, not -%just at corresponding pixels. This case requires distinguishable axes, -%so that corresponding axes in the two images can be matched up, just -%as happens with a SkyFrame (\secref{ss:convertingpermutedaxes}). -% -%Of course, there may also be intermediate cases, where some axes are -%distinguishable and others aren't. - -\subsection{\label{ss:alignmentsystem}The Choice of Alignment System} - -In practice, when AST is asked to find a conversion between two Frames -describing two different coordinate systems on a given physical domain, -it uses an intermediate ``alignment'' system. Thus, when finding a -conversion from system A to system B, AST first finds the Mapping from -system A to some alignment system, system C, and then finds the Mapping -from this system C to the required system B. It finally concatenates -these two Mappings to get the Mapping from system A to system B. - -One advantage of this is that it cuts down the number of conversion -algorithms required. If there are $N$ different Systems which may be used -to describe positions within the Domain, then this approach requires -about $2*N$ conversion algorithms to be written. The alternative approach -of going directly from system A to system B would require about $N*N$ -conversion algorithms. - -In addition, the use of an intermediate alignment system highlights the -nature of the conversion process. What do we mean by saying that a -Mapping ``converts a position in one coordinate system into the -corresponding position in another''? In practice, it means that the input -and output coordinates correspond to the same coordinates \emph{in some -third coordinate system}. The choice of this third coordinate system, the -``alignment'' system, can completely alter the nature of the Mapping. The -Frame class has an attribute called AlignSystem which can be used to -specify the alignment system. - -As an example, consider the case of aligning two spectra calibrated in -radio velocity, but each with a different rest frequency (each spectrum -will be described by a SpecFrame). Since the rest frequencies differ, a -given velocity will correspond to different frequencies in the two -spectra. So when we come to ``align'' these two spectra (that is, find a -Mapping which converts positions in one SpecFrame to the corresponding -positions in the other), we have the choice of aligning the frequencies -or aligning the velocities. Different Mappings will be required to -describe these two forms of alignment. If we set AlignSystem to ``Freq'' -then the returned Mapping will align the frequencies described by the two -SpecFrames. On the other hand, if we set AlignSystem to ``Vradio'' -then the returned Mapping will align the velocities. - -Some choices of alignment system are redundant. For instance, in the -above example, changing the alignment system from frequency to wavelength -has no effect on the returned Mapping: if two spectra are aligned in -frequency they will also be aligned in wavelength (assuming the speed of -light doesn't change). - -The default value for AlignSystem depends on the class of Frame. For a -SpecFrame, the default is wavelength (or equivalently, frequency) -since this is the system in which observations are usually made. The -SpecFrame class also has an attribute called AlignStdOfRest which -allows the standard of rest of the alignment system to be specified. -Similarly, the TimeFrame class has an attribute called AlignTimeScale -which allows the time scale of the alignment system to be specified. -Currently, the SkyFrame uses ICRS as the default for AlignSystem, since -this is a close approximation to an inertial frame of rest. - -\cleardoublepage -\section{\label{ss:framesets}Coordinate System Networks (FrameSets)} - -c+ -We saw in \secref{ss:introducingconversion} how astConvert could be -used to find a Mapping that inter-relates a pair of coordinate systems -represented by Frames. There is a limitation to this, however, in that -it can only be applied to coordinate systems that are inter-related by -suitable conventions. In the case of celestial coordinates, the -relevant conventions are standards set out by the International -Astronomical Union, and others, that define what these coordinate -systems mean. In practice, however, the relationships between many -other coordinate systems are also of practical importance. -c- -f+ -We saw in \secref{ss:introducingconversion} how AST\_CONVERT could be -used to find a Mapping that inter-relates a pair of coordinate systems -represented by Frames. There is a limitation to this, however, in that -it can only be applied to coordinate systems that are inter-related by -suitable conventions. In the case of celestial coordinates, the -relevant conventions are standards set out by the International -Astronomical Union, and others, that define what these coordinate -systems mean. In practice, however, the relationships between many -other coordinate systems are also of practical importance. -f- - -Consider, for example, the focal plane of a telescope upon which an -image of the sky is falling. We could measure positions in this focal -plane in millimetres or, if there were a detector system such as a CCD -present, we could count pixels. We could also use celestial -coordinates of many different kinds. All of these systems are -equivalent in their effectiveness at specifying positions in the focal -plane, but some are more convenient than others for particular -purposes. - -Although we could, in principle, convert between all of these focal -plane coordinate systems, there is no pre-defined convention for doing -so. This is because the conversions required depend on where the -telescope is pointing and how the CCD is mounted in the focal -plane. Clearly, knowledge about this cannot be built into the AST -library and must be supplied in some other way. Note that this is -exactly the same problem as we met in \secref{ss:framedomains} when -discussing the Domain attribute---\emph{i.e.}\ coordinate systems that -apply to different physical domains require that extra information be -supplied before we can convert between them. - -What we need, therefore, is a general way to describe how coordinate -systems are inter-related, so that when there is no convention already -in place, we can define our own. We can then look forward to -converting, say, from pixels into galactic coordinates and {\emph{vice -versa.} In AST, the FrameSet class provides this capability. - -\subsection{The FrameSet Model} - -Consider a coordinate system (call it number 1) which is represented -by a Frame of some kind. Now consider a Mapping which, when applied to -the coordinates in system 1 yields coordinates in another system, -number 2. The Mapping therefore inter-relates coordinate systems 1 and -2. - -Now consider a second Mapping which inter-relates system 1 and a -further coordinate system, number 3. If we wanted to convert -coordinates between systems 2 and 3, we could do so by: - -\begin{enumerate} -\item Applying our first Mapping in reverse, so as to convert between -systems 2 and 1. - -\item Applying the second Mapping, as given, to convert between -systems 1 and 3. -\end{enumerate} - -We are not limited to three coordinate systems, of course. In fact, we -could continue to introduce any number of further coordinate systems, -so long as we have a suitable Mapping for each one which relates it to -one of the Frames already present. Continuing in this way, we can -build up a network in which Frames are inter-related by Mappings in -such a way that there is always a way of converting between any pair -of coordinate systems. - -The FrameSet (Figure~\ref{fig:frameset}) encapsulates these ideas. It -is a network composed of Frames and associated Mappings, in which -there is always exactly one path, \emph{via} Mappings, between any -pair of Frames. Since we assemble FrameSets ourselves, they can be -used to represent any coordinate systems we choose and to set up the -particular relationships between them that we want. - -\subsection{\label{ss:creatingaframeset}Creating a FrameSet} - -Before we can create a FrameSet, we must have a Frame of some kind to -put into it, so let's create a simple one: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstFrame *frame1; - -... - -frame1 = astFrame( 2, "Domain=A" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER FRAME1, STATUS - - STATUS = 0 - - ... - - FRAME1 = AST_FRAME( 2, 'Domain=A', STATUS ) -\end{terminalv} -\normalsize -f- - -We have set this Frame's Domain attribute (\secref{ss:framedomains}) to -A so that it will be distinct from the others we will be using. We can -now create a new FrameSet containing just this Frame, as follows: - -c+ -\small -\begin{terminalv} -AstFrameSet *frameset; - -... - -frameset = astFrameSet( frame1, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAMESET - - ... - - FRAMESET = AST_FRAMESET( FRAME1, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -So far, however, this Frame isn't related to any others. - -\subsection{\label{ss:addingframes}Adding New Frames to a FrameSet} - -We can now add further Frames to the FrameSet created above -(\secref{ss:creatingaframeset}). To do so, we must supply a new Frame -and an associated Mapping that relates it to any of the Frames that -are already present (there is only one present so far). To keep the -example simple, we will just use a ZoomMap that multiplies coordinates -by 10. The required Objects are created as follows: - -c+ -\small -\begin{terminalv} -AstFrame *frame2; -AstMapping *mapping12; - -... - -frame2 = astFrame( 2, "Domain=B" ); -mapping12 = astZoomMap( 2, 10.0, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAME2, MAPPING12 - - ... - - FRAME2 = AST_FRAME( 2, 'Domain=B', STATUS ) - MAPPING12 = AST_ZOOMMAP( 2, 10.0D0, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -To add the new Frame into our FrameSet, we use the astAddFrame -function: -c- -f+ -To add the new Frame into our FrameSet, we use the AST\_ADDFRAME -routine: -f- - -c+ -\small -\begin{terminalv} -astAddFrame( frameset, 1, mapping12, frame2 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_ADDFRAME( FRAMESET, 1, MAPPING12, FRAME2, STATUS ) -\end{terminalv} -\normalsize -f- - -Whenever a Frame is added to a FrameSet, it is assigned an integer -index. This index starts with 1 for the initial Frame used to create -the FrameSet (\secref{ss:creatingaframeset}) and increments by one -every time a new Frame is added. This index is the primary way of -identifying the Frames within a FrameSet. - -When a Frame is added, we also have to specify which of the existing -ones the new Frame is related to. Here, we chose number 1, the only -one present so far, and the new one we added became number 2. - -c+ -Note that a FrameSet does not make copies of the Frames and Mappings -that you insert into it. Instead, it holds pointers to them. This -means that if you retain the original pointers to these Objects and -alter them, you will indirectly be altering the FrameSet's -contents. You can, of course, always use astCopy -(\secref{ss:copyingobjects}) to make a separate copy of any Object if -you need to ensure its independence. -c- -f+ -Note that a FrameSet does not make copies of the Frames and Mappings -that you insert into it. Instead, it holds pointers to them. This -means that if you retain the original pointers to these Objects and -alter them, you will indirectly be altering the FrameSet's -contents. You can, of course, always use AST\_COPY -(\secref{ss:copyingobjects}) to make a separate copy of any Object if -you need to ensure its independence. -f- - -c+ -We could also add a third Frame into our FrameSet, this time defining -a coordinate system which is reached by multiplying the original -coordinates (of ``frame1'') by 5: -c- -f+ -We could also add a third Frame into our FrameSet, this time defining -a coordinate system which is reached by multiplying the original -coordinates (of FRAME1) by 5: -f- - -c+ -\small -\begin{terminalv} -astAddFrame( frameset, 1, astZoomMap( 2, 5.0, "" ), astFrame( 2, "Domain=C" ) ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_ADDFRAME( FRAMESET, 1, - : AST_ZOOMMAP( 2, 5.0D0, ' ', STATUS ), - : AST_FRAME( 2, 'Domain=C', STATUS ), - : STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, we have avoided storing unnecessary pointer values by using -function invocations directly as arguments for astAddFrame. This -assumes that we are using astBegin and astEnd (\secref{ss:contexts}) to -ensure that Objects are correctly deleted when no longer required. -c- -f+ -Here, we have avoided storing unnecessary pointer values by using -function invocations directly as arguments for AST\_ADDFRAME. This -assumes that we are using AST\_BEGIN and AST\_END -(\secref{ss:contexts}) to ensure that Objects are correctly deleted -when no longer required. -f- - - Our example FrameSet now contains three Frames and two Mappings with - the arrangement shown in Figure~\ref{fig:fsexample}. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/fsexample} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/fsexample} -f- - \caption[An example FrameSet.]{An example FrameSet, in which Frames~2 and 3 are related to - Frame~1 by multiplying its coordinates by factors of 10 and 5 - respectively. The FrameSet's Base attribute has the value 1 and its - Current attribute has the value 3. The transformation performed when - the FrameSet is used as a Mapping (\emph{i.e.}\ from its base to - its current Frame) is shown in bold.} - \label{fig:fsexample} - \end{center} - \end{figure} - The total number of Frames is given by its read-only Nframe attribute. - -\subsection{\label{ss:baseandcurrent}The Base and Current Frames} - -At all times, one of the Frames in a FrameSet is designated to be its -\emph{base} Frame and one to be its \emph{current} Frame -(Figure~\ref{fig:fsexample}). These Frames are identified by two -integer FrameSet attributes, Base and Current, which hold the indices -of the nominated Frames within the FrameSet. - -The existence of the base and current Frames reflects an important -application of FrameSets, which is to attach coordinate systems to -entities such as data arrays, data files, plotting surfaces (for -graphics), \emph{etc.} In this context, the base Frame represents the -``native'' coordinate system of the attached entity---for example, the -pixel coordinates of an image or the intrinsic coordinates of a -plotting surface. The other Frames within the FrameSet represent -alternative coordinate systems which may also be used to refer to -positions within that entity. The current Frame represents the -particular coordinate system which is currently selected for use. For -instance, if an image were being displayed, you would aim to label it -with coordinates corresponding to the current Frame. In order to see a -different coordinate system, a software user would arrange for a -different Frame to be made current. - -The choice of base and current Frames may be changed at any time, -simply by assigning new values to the FrameSet's Base and Current -attributes. For example, to make the Frame with index 3 become the -current Frame, you could use: - -c+ -\small -\begin{terminalv} -astSetI( frameset, "Current", 3 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SETI( FRAMESET, 'Current', 3, STATUS ) -\end{terminalv} -\normalsize -f- - -You can nominate the same Frame to be both the base and current Frame -if you wish. -\label{ss:baseandcurrentdefault} - -By default (\emph{i.e.}\ if the Base or Current attribute is un-set), -the first Frame added to a FrameSet becomes its base Frame and the -last one added becomes its current Frame.\footnote{Although this is -reversed if the FrameSet's Invert attribute is non-zero.} Whenever a -new Frame is added to a FrameSet, the Current attribute is modified so -that the new Frame becomes the current one. This behaviour is -reflected in the state of the example FrameSet in -Figure~\ref{fig:fsexample}. - -\subsection{\label{ss:astbaseandastcurrent}Referring to the Base and Current Frames} - -c+ -It is often necessary to refer to the base and current Frames -(\secref{ss:baseandcurrent}) within a FrameSet, but it can be -cumbersome having to obtain their indices from the Base and Current -attributes on each occasion. To make this easier, two macros, -AST\_\_BASE and AST\_\_CURRENT, are defined in the ``ast.h'' header -file and may be used to represent the indices of the base and current -Frames respectively. They may be used whenever a Frame index is -required. -c- -f+ -It is often necessary to refer to the base and current Frames -(\secref{ss:baseandcurrent}) within a FrameSet, but it can be -cumbersome having to obtain their indices from the Base and Current -attributes on each occasion. To make this easier, two parameter -constants, AST\_\_BASE and AST\_\_CURRENT, are defined in the AST\_PAR -include file and may be used to represent the indices of the base and -current Frames respectively. They may be used whenever a Frame index -is required. -f- - -For example, when adding a new Frame to a FrameSet -(\secref{ss:addingframes}), you could use the following to indicate -that the new Frame is related to the existing current Frame, whatever -its index happens to be: - -c+ -\small -\begin{terminalv} -AstFrame *frame; -AstMapping *mapping; - -... - -astAddFrame( frameset, AST__CURRENT, mapping, frame ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAME, MAPPING - - ... - - CALL AST_ADDFRAME( FRAMESET, AST__CURRENT, MAPPING, FRAME, STATUS ) -\end{terminalv} -\normalsize -f- - -Of course, the Frame you added would then become the new current -Frame. - -\subsection{\label{ss:framesetasmapping}Using a FrameSet as a Mapping} - -The FrameSet class inherits properties and behaviour from the Frame -class (\secref{ss:frames}) and, in turn, from the Mapping class -(\secref{ss:mappings}). Its behaviour when used as a Mapping is -particularly important. - -c+ -Consider, for instance, passing a FrameSet pointer to a coordinate -transformation function such as astTran2: -c- -f+ -Consider, for instance, passing a FrameSet pointer to a coordinate -transformation routine such as AST\_TRAN2: -f- - -c+ -\small -\begin{terminalv} -#define N 10 -double xin[ N ], yin[ N ], xout[ N ], yout[ N ]; - -... - -astTran2( frameset, N, xin, yin, 1, xout, yout ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER N - DOUBLE PRECISION XIN( N ), YIN( N ) - DOUBLE PRECISION XOUT( N ), YOUT( N ) - - ... - - CALL AST_TRAN2( FRAMESET, N, XIN, YIN, .TRUE., XOUT, YOUT, STATUS ) -\end{terminalv} -\normalsize -f- - -The coordinate transformation applied by this FrameSet would be the -one which converts between its base and current Frames. Using the -FrameSet in Figure~\ref{fig:fsexample}, for example, the coordinates -would be multiplied by a factor of 5. If we instead requested the -FrameSet's inverse transformation, we would be transforming from its -current Frame to its base Frame, so our example FrameSet would then -multiply by a factor of 0.2. - -Whenever the choice of base and current Frames changes, the -transformations which a FrameSet performs when used as a Mapping also -change to reflect this. The Nin and Nout attributes may also change in -consequence, because they are determined by the numbers of axes in the -FrameSet's base and current Frames respectively. These numbers need -not necessarily be equal, of course. - -c+ -Like any Mapping, a FrameSet may also be inverted by changing the -boolean sense of its Invert attribute, \emph{e.g.}\ using astInvert -(\secref{ss:invertingmappings}). If this is happens, the values of the -FrameSet's Base and Current attributes are interchanged, along with -its Nin and Nout attributes, so that its base and current Frames swap -places. When used as a Mapping, the FrameSet will therefore perform -the inverse transformation to that which it performed previously. -c- -f+ -Like any Mapping, a FrameSet may also be inverted by changing the -boolean sense of its Invert attribute, \emph{e.g.}\ using AST\_INVERT -(\secref{ss:invertingmappings}). If this is happens, the values of the -FrameSet's Base and Current attributes are interchanged, along with -its Nin and Nout attributes, so that its base and current Frames swap -places. When used as a Mapping, the FrameSet will therefore perform -the inverse transformation to that which it performed previously. -f- - -To summarise, a FrameSet may be used exactly like any other Mapping -which inter-relates the coordinate systems described by its base and -current Frames. - -\subsection{\label{ss:extractingamapping}Extracting a Mapping from a FrameSet} - -Although it is very convenient to use a FrameSet when a Mapping is -required (\secref{ss:framesetasmapping}), a FrameSet necessarily -contains additional information and sometimes this might cause -inefficiency or confusion. For example, if you wanted to use a -Mapping contained in one FrameSet and insert it into another, it would -probably not be efficient to insert the whole of the first FrameSet -into the second one, although it would work. - -c+ -In such a situation, the astGetMapping function allows you to extract -a Mapping from a FrameSet. You do this by specifying the two Frames -which the Mapping should inter-relate using their indices within the -FrameSet. For example: -c- -f+ -In such a situation, the AST\_GETMAPPING function allows you to -extract a Mapping from a FrameSet. You do this by specifying the two -Frames which the Mapping should inter-relate using their indices -within the FrameSet. For example: -f- - -c+ -\small -\begin{terminalv} -map = astGetMapping( frameset, 2, 3 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - MAP = AST_GETMAPPING( FRAMESET, 2, 3, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -would return a pointer to a Mapping that converted between Frames~2 -and 3 in the FrameSet. Its inverse transformation would then convert -in the opposite direction, \emph{i.e.}\ between Frames~3 and 2. Note -that this Mapping might not be independent of the Mappings contained -within the FrameSet---\emph{i.e.}\ they may share sub-Objects---so -astCopy should be used to make a copy if you need to guarantee -independence (\secref{ss:copyingobjects}). -c- -f+ -would return a pointer to a Mapping that converted between Frames~2 -and 3 in the FrameSet. Its inverse transformation would then convert -in the opposite direction, \emph{i.e.}\ between Frames~3 and 2. Note -that this Mapping might not be independent of the Mappings contained -within the FrameSet---\emph{i.e.}\ they may share sub-Objects---so -AST\_COPY should be used to make a copy if you need to guarantee -independence (\secref{ss:copyingobjects}). -f- - -c+ -Very often, the Mapping returned by astGetMapping will be a compound -Mapping, or CmpMap (\secref{ss:cmpmaps}). This reflects the fact that -conversion between the two Frames may need to be done \emph{via} an -intermediate coordinate system so that several stages may be involved. -You can, however, easily simplify this Mapping (where this is possible) -by using the astSimplify function (\secref{ss:simplifyingcmpmaps}) and -this is recommended if you plan to use it for transforming a large -amount of data. -c- -f+ -Very often, the Mapping returned by AST\_GETMAPPING will be a compound -Mapping, or CmpMap (\secref{ss:cmpmaps}). This reflects the fact that -conversion between the two Frames may need to be done \emph{via} an -intermediate coordinate system so that several stages may be involved. -You can, however, easily simplify this Mapping (where this is possible) -by using the AST\_SIMPLIFY function (\secref{ss:simplifyingcmpmaps}) -and this is recommended if you plan to use it for transforming a large -amount of data. -f- - -\subsection{\label{ss:framesetasframe}Using a FrameSet as a Frame} - -A FrameSet can also be used as a Frame, in which capacity it almost -always behaves as if its current Frame had been used instead. For -example, if you request the Title attribute of a FrameSet using: - -c+ -\small -\begin{terminalv} -const char *title; - -... - -title = astGetC( frameset, "Title" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 80 ) TITLE - - ... - - TITLE = AST_GETC( FRAMESET, 'Title', STATUS ) -\end{terminalv} -\normalsize -f- - -the result will be the Title of the current Frame, or a suitable -default if the current Frame's Title attribute is un-set. The same -also applies to other attribute operations---\emph{i.e.}\ setting, -clearing and testing attributes. Most attributes shared by both -Frames and FrameSets behave in this way, such as Naxes, Label(axis), -Format(axis), \emph{etc.} There are, however, a few exceptions: - -\begin{quote} -\begin{description} -\item[Class]\mbox{}\\ -Has the value ``FrameSet''. - -\item[ID]\mbox{}\\ -Identifies the particular FrameSet (not its current Frame). - -\item[Nin]\mbox{}\\ -Equals the number of axes in the FrameSet's base Frame. - -\item[Invert]\mbox{}\\ -Is independent of any of the Objects within the FrameSet. - -\item[Nobject]\mbox{}\\ -Counts the number of active FrameSets. - -\item[RefCount]\mbox{}\\ -Counts the number of active pointers to the FrameSet (not to its -current Frame). -\end{description} -\end{quote} - -Note that the set of attributes possessed by a FrameSet can vary, -depending on the nature of its current Frame. For example, if the -current Frame is a SkyFrame (\secref{ss:skyframes}), then the FrameSet -will acquire an Equinox attribute from it which can be set, enquired, -\emph{etc.} However, if the current Frame is changed to be a basic -Frame, which does not have an Equinox attribute, then this attribute -will be absent from the FrameSet as well. Any attempt to reference it -will then result in an error. - -\subsection{Extracting a Frame from a FrameSet} - -c+ -Although a FrameSet may be used in place of its current Frame in most -situations, it is sometimes convenient to have direct access to a -specified Frame within it. This may be obtained using the astGetFrame -function, as follows: -c- -f+ -Although a FrameSet may be used in place of its current Frame in most -situations, it is sometimes convenient to have direct access to a -specified Frame within it. This may be obtained using the -AST\_GETFRAME function, as follows: -f- - -c+ -\small -\begin{terminalv} -frame = astGetFrame( frameset, AST__BASE ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - FRAME = AST_GETFRAME( FRAMESET, AST__BASE, STATUS ) -\end{terminalv} -\normalsize -f- - -This would return a pointer (not a copy) to the base Frame within the -FrameSet. Note the use of AST\_\_BASE -(\secref{ss:astbaseandastcurrent}) as shorthand for the value of the -FrameSet's Base attribute, which gives the base Frame's index. - -\subsection{Removing a Frame from a FrameSet} - -c+ -Removing a Frame from a FrameSet is straightforward and is performed -using the astRemoveFrame function. You identify the Frame you wish to -remove in the usual way, by giving its index within the FrameSet. For -example, the following would remove the Frame with index 1: -c- -f+ -Removing a Frame from a FrameSet is straightforward and is performed -using the AST\_REMOVEFRAME routine. You identify the Frame you wish to -remove in the usual way, by giving its index within the FrameSet. For -example, the following would remove the Frame with index 1: -f- - -c+ -\small -\begin{terminalv} -astRemoveFrame( frameset, 1 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_REMOVEFRAME( FRAMESET, 1, STATUS ); -\end{terminalv} -\normalsize -f- - -The only restriction is that you cannot remove the last remaining -Frame because a FrameSet must always contain at least one Frame. When -a Frame is removed, the Frames which follow it are re-numbered -(\emph{i.e.}\ their indices are reduced by one) so as to preserve the -sequence of consecutive Frame indices. The FrameSet's Nframe -attribute is also decremented. - -c+ -If appropriate, astRemoveFrame will modify the FrameSet's Base and/or -Current attributes so that they continue to identify the same Frames -as previously. If either the base or current Frame is removed, -however, the corresponding attribute will become un-set, so that it -reverts to its default value (\secref{ss:baseandcurrentdefault}) and -therefore identifies an alternative Frame. -c- -f+ -If appropriate, AST\_REMOVEFRAME will modify the FrameSet's Base -and/or Current attributes so that they continue to identify the same -Frames as previously. If either the base or current Frame is removed, -however, the corresponding attribute will become un-set, so that it -reverts to its default value (\secref{ss:baseandcurrentdefault}) and -therefore identifies an alternative Frame. -f- - -Note that it is quite permissible to remove any Frame from a FrameSet, -even although other Frames may appear to depend on it. For example, in -Figure~\ref{fig:fsexample}, if Frame~1 were removed, the correct -relationship between Frames~2 and 3 would still be preserved, although -they would be re-numbered as Frames~1 and 2. - -\cleardoublepage -\section{\label{ss:fshigher}Higher Level Operations on FrameSets} - -c+ -\subsection{\label{ss:framesetsfromconvert}Creating FrameSets with astConvert} -c- -f+ -\subsection{\label{ss:framesetsfromconvert}Creating FrameSets with AST\_CONVERT} -f- - -c+ -Before considering the important subject of using FrameSets to convert -between coordinate systems (\secref{ss:framesetconverting}), let us -return briefly to reconsider the output generated by astConvert. We -used this function earlier (\secref{ss:introducingconversion}), when -converting between the coordinate systems represented by various kinds -of Frame, and indicated that it returns a FrameSet to represent the -coordinate conversion it identifies. We are now in a position to -examine the structure of this FrameSet. -c- -f+ -Before considering the important subject of using FrameSets to convert -between coordinate systems (\secref{ss:framesetconverting}), let us -return briefly to reconsider the output generated by AST\_CONVERT. We -used this function earlier (\secref{ss:introducingconversion}), when -converting between the coordinate systems represented by various kinds -of Frame, and indicated that it returns a FrameSet to represent the -coordinate conversion it identifies. We are now in a position to -examine the structure of this FrameSet. -f- - -Take our earlier example (\secref{ss:convertingskyframes}) of -converting between the celestial coordinate systems represented by two -SkyFrames: - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstFrameSet *cvt; -AstSkyFrame *skyframe1, *skyframe2; - -... - -skyframe1 = astSkyFrame( "System=FK4-NO-E, Epoch=B1958, Equinox=B1960" ); -skyframe2 = astSkyFrame( "System=Ecliptic, Equinox=J2010.5" ); - -cvt = astConvert( skyframe1, skyframe2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER SKYFRAME1, SKYFRAME2, STATUS - - STATUS = 0 - - ... - - SKYFRAME1 = AST_SKYFRAME( 'System=FK4-NO-E, Epoch=B1958, Equinox=B1960', STATUS ) - SKYFRAME2 = AST_SKYFRAME( 'System=Ecliptic, Equinox=J2010.5', STATUS ) - - CVT = AST_CONVERT( SKYFRAME1, SKYFRAME2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ - This will produce a pointer, ``cvt'', to the FrameSet shown in - Figure~\ref{fig:fsconvert}. -c- -f+ - This will produce a pointer, CVT, to the FrameSet shown in - Figure~\ref{fig:fsconvert}. -f- - \begin{figure}[bhtp] - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/fsconvert} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/fsconvert} -f- -c+ - \caption[FrameSet produced when converting between two SkyFrames.]{The FrameSet produced when astConvert is used to convert -c- -f+ - \caption[FrameSet produced when converting between two SkyFrames.]{The FrameSet produced when AST\_CONVERT is used to convert -f- - between the coordinate systems represented by two SkyFrames. The - source SkyFrame becomes the base Frame, while the destination SkyFrame - becomes the current Frame. The Mapping between them implements the - required conversion.} - \label{fig:fsconvert} - \end{center} - \end{figure} - -c+ -As can be seen, this FrameSet contains just two Frames. The source -Frame supplied to astConvert becomes its base Frame, while the -destination Frame becomes its current Frame. (The FrameSet, of course, -simply holds pointers to these Frames, rather than making copies.) The -Mapping which relates the base Frame to the current Frame is the one -which implements the required conversion. -c- -f+ -As can be seen, this FrameSet contains just two Frames. The source -Frame supplied to AST\_CONVERT becomes its base Frame, while the -destination Frame becomes its current Frame. (The FrameSet, of course, -simply holds pointers to these Frames, rather than making copies.) The -Mapping which relates the base Frame to the current Frame is the one -which implements the required conversion. -f- - -c+ -As we noted earlier (\secref{ss:convertingskyframes}), the FrameSet -returned by astConvert may be used both as a Mapping and as a Frame to -perform most of the functions you are likely to need. However, the -Mapping may be extracted for use on its own if necessary, using -astGetMapping (\secref{ss:extractingamapping}), for example: -c- -f+ -As we noted earlier (\secref{ss:convertingskyframes}), the FrameSet -returned by AST\_CONVERT may be used both as a Mapping and as a Frame -to perform most of the functions you are likely to need. However, the -Mapping may be extracted for use on its own if necessary, using -AST\_GETMAPPING (\secref{ss:extractingamapping}), for example: -f- - -c+ -\small -\begin{terminalv} -AstMapping *mapping; - -... - -mapping = astGetMapping( cvt, AST__BASE, AST__CURRENT ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER MAPPING - - ... - - MAPPING = AST_GETMAPPING( CVT, AST__BASE, AST__CURRENT, STATUS ) -\end{terminalv} -\normalsize -f- - -\subsection{\label{ss:framesetconverting}Converting between FrameSet Coordinate Systems} - - We now consider the process of converting between the coordinate - systems represented by two FrameSets. This is a most important - operation, as a subsequent example (\secref{ss:registeringimages}) - will show, and is illustrated in Figure~\ref{fig:fsalign}. - \begin{figure} - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/fsalign} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/fsalign} -f- - \caption[Conversion between two FrameSets is performed by establishin a link between a pair of Frames, one from each FrameSet.]{Conversion - between two FrameSets is performed by establishing - a link between a pair of Frames, one from each FrameSet. If conversion - between these two Frames is possible, then a route for converting - between the current Frames of both FrameSets can also be found. In - practice, there may be many ways of pairing Frames to find the - ``missing link'', so the Frames' Domain attribute may be used to - narrow the choice.} - \label{fig:fsalign} - \end{center} - \end{figure} - -c+ -Recalling (\secref{ss:framesetasframe}) that a FrameSet will behave -like its current Frame when necessary, conversion between two -FrameSets is performed using astConvert -(\secref{ss:convertingskyframes}), but supplying pointers to FrameSets -instead of Frames. The effect of this is to convert between the -coordinate systems represented by the current Frames of each FrameSet: -c- -f+ -Recalling (\secref{ss:framesetasframe}) that a FrameSet will behave -like its current Frame when necessary, conversion between two -FrameSets is performed using AST\_CONVERT -(\secref{ss:convertingskyframes}), but supplying pointers to FrameSets -instead of Frames. The effect of this is to convert between the -coordinate systems represented by the current Frames of each FrameSet: -f- - -c+ -\small -\begin{terminalv} -AstFrameSet *frameseta, *framesetb; - -... - -cvt = astConvert( frameseta, framesetb, "SKY" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAMESETA, FRAMESETB - - ... - - CVT = AST_CONVERT( FRAMESETA, FRAMESETB, 'SKY', STATUS ) -\end{terminalv} -\normalsize -f- - -When using FrameSets, we are presented with considerably more -conversion options than when using Frames alone. This is because each -current Frame is related to all the other Frames in its respective -FrameSet. Therefore, if we can establish a link between any pair of -Frames, one from each FrameSet, we can form a complete conversion path -between the two current Frames (Figure~\ref{fig:fsalign}). - -This expanded range of options is, of course, precisely the -intention. By connecting Frames together within a FrameSet, we have -extended the range of coordinate systems that can be reached from any -one of them. We are therefore no longer restricted to converting -between Frames with the same Domain value (\secref{ss:framedomains}), -but can go \emph{via} a range of intermediate coordinate systems in -order to make the connection we require. Transformation between -different domains has therefore become possible because, in assembling -the FrameSets, we provided the additional information needed to -inter-relate them. - -It is important to appreciate, however, that the choice of ``missing -link'' is crucial in determining the conversion that results. -Although each FrameSet may be perfectly self-consistent internally, -this does not mean that all conversion paths through the combined -network of Mappings are equivalent. Quite the contrary in fact: -everything depends on where the inter-connecting link between the two -FrameSets is made. In practice, there may be a large number of -possible pairings of Frames and hence of possible links. Other factors -must therefore be used to restrict the choice. These are: - -\begin{enumerate} -\item Not every possible pairing of Frames is legitimate. For example, -you cannot convert directly between a basic Frame and a SkyFrame which -belong to different classes, so such pairings will be ignored. - -\item In a similar way, you cannot convert directly between Frames -with different Domain values (\secref{ss:framedomains}). If the Domain -attribute is used consistently (typically only one Frame in each -FrameSet will have a particular Domain value), then this further -restricts the choice. - -c+ -\item The third argument of astConvert may then be used to specify -c- -f+ -\item The third argument of AST\_CONVERT may then be used to specify -f- -explicitly which Domain value the paired Frames should have. You may -also supply a comma-separated list of preferences here (see below). - -\item If the above steps fail to uniquely identify the link, then the -first suitable pairing of Frames is used, so that any ambiguity is -resolved by the order in which Frames are considered for pairing (see -c+ -the description of the astConvert function in -c- -f+ -the description of the AST\_CONVERT function in -f- -\appref{ss:functiondescriptions} for details of the search -order).\footnote{If you find that how this ambiguity is resolved -actually makes a difference to the conversion that results, then you -have probably constructed a FrameSet which lacks internal -self-consistency. For example, you might have two Frames representing -indistinguishable coordinate systems but inter-related by a non-null -Mapping.} -\end{enumerate} - -In the example above we supplied the string ``SKY'' as the third -c+ -argument of astConvert. This constitutes a request that a pair of -Frames with -c- -f+ -argument of AST\_CONVERT. This constitutes a request that a pair of -Frames with -f- -the Domain value SKY (\emph{i.e.}\ representing celestial coordinate -systems) should be used to inter-relate the two FrameSets. Note that -this does not specify which celestial coordinate system to use, but is -a general request that the two FrameSets be inter-related using -coordinates on the celestial sphere. - -Of course, it may be that this request cannot be met because there may -not be a celestial coordinate system in both FrameSets. If this is -likely to happen, we can supply a list of preferences, or a -\emph{domain search path}, -c+ -as the third argument to astConvert, such as -c- -f+ -as the third argument to AST\_CONVERT, such as -f- -the following: - -c+ -\small -\begin{terminalv} -cvt = astConvert( frameseta, framesetb, "SKY,PIXEL,GRID," ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CVT = AST_CONVERT( FRAMESETA, FRAMESETB, 'SKY,PIXEL,GRID,', STATUS ) -\end{terminalv} -\normalsize -f- - -Now, if the two FrameSets cannot be inter-related using the SKY domain, -c+ -astConvert will attempt to use the PIXEL domain instead. If this -c- -f+ -AST\_CONVERT will attempt to use the PIXEL domain instead. If this -f- -also fails, it will try the GRID domain. A blank field in the domain -search path (here indicated by the final comma) allows any Domain -value to be used. This can be employed as a last resort when all else -has failed. - -c+ -If astConvert succeeds in identifying a conversion, it will return a -c- -f+ -If astConvert succeeds in identifying a conversion, it will return a -f- -pointer to a FrameSet (\secref{ss:framesetsfromconvert}) in which the -source and destination Frames are inter-connected by the required -Mapping. In this case, of course, these Frames will be the current -Frames of the two FrameSets, but in all other respects the returned -FrameSet is the same as when converting between Frames. - -c+ -Very importantly, however, astConvert may modify the FrameSets you are -converting between. It does this, in order to indicate which pairing -of Frames was used to inter-relate them, by changing the Base -attribute for each FrameSet so that the Frame used in the pairing -becomes its base Frame (\secref{ss:baseandcurrent}). -c- -f+ -Very importantly, however, AST\_CONVERT may modify the FrameSets you -are converting between. It does this, in order to indicate which -pairing of Frames was used to inter-relate them, by changing the Base -attribute for each FrameSet so that the Frame used in the pairing -becomes its base Frame (\secref{ss:baseandcurrent}). -f- - -c+ -Finally, note that astConvert may also be used to convert between a -FrameSet and a Frame, or \emph{vice versa}. If a pointer to a Frame is -supplied for either the first or second argument, it will behave like -a FrameSet containing only a single Frame. -c- -f+ -Finally, note that AST\_CONVERT may also be used to convert between a -FrameSet and a Frame, or \emph{vice versa}. If a pointer to a Frame is -supplied for either the first or second argument, it will behave like -a FrameSet containing only a single Frame. -f- - -\subsection{\label{ss:registeringimages}Example---Registering Two Images} - -Consider two images which have been calibrated by attaching FrameSets -to them, such that the base Frame of each FrameSet corresponds to the -raw data grid coordinates of each image (the GRID domain of -\secref{ss:domainconventions}). Suppose, also, that these FrameSets -contain an unknown number of other Frames, representing alternative -world coordinate systems. What we wish to do is register these two -images, such that we can transform from a position in the data grid of -one into the corresponding position in the data grid of the other. -This is a very practical example because images will typically be -calibrated using FrameSets in precisely this way. - -c+ -The first step will probably involve making a copy of both FrameSets -(using astCopy---\secref{ss:copyingobjects}), since we will be -modifying them. Let ``frameseta'' and ``framesetb'' be pointers to -these copies. Since we want to convert between the base Frames of -these FrameSets (\emph{i.e.}\ their data grid coordinates), the next -step is to make these Frames current. This is simply done by inverting -both FrameSets, which interchanges their base and current -Frames. astInvert will perform this task: -c- -f+ -The first step will probably involve making a copy of both FrameSets -(using AST\_COPY---\secref{ss:copyingobjects}), since we will be -modifying them. Let ``frameseta'' and ``framesetb'' be pointers to -these copies. Since we want to convert between the base Frames of -these FrameSets (\emph{i.e.}\ their data grid coordinates), the next -step is to make these Frames current. This is simply done by inverting -both FrameSets, which interchanges their base and current -Frames. astInvert will perform this task: -f- - -c+ -\small -\begin{terminalv} -astInvert( frameseta ); -astInvert( framesetb ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_INVERT( FRAMESETA, STATUS ) - CALL AST_INVERT( FRAMESETB, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -To identify the required conversion, we now use astConvert, supplying -a suitable domain search path with which we would like our two images -to be registered: -c- -f+ -To identify the required conversion, we now use AST\_CONVERT, -supplying a suitable domain search path with which we would like our -two images to be registered: -f- - -c+ -\small -\begin{terminalv} -cvt = astConvert( frameseta, framesetb, "SKY,PIXEL,GRID" ); -if ( cvt == AST__NULL ) { - <no conversion was possible> -} else { - <conversion was possible> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CVT = AST_CONVERT( FRAMESETA, FRAMESETB, 'SKY,PIXEL,GRID', STATUS ) - IF ( CVT .EQ. AST__NULL ) THEN - <no conversion was possible> - ELSE - <conversion was possible> - END IF -\end{terminalv} -\normalsize -f- - -The effects of this are: - -\begin{enumerate} -c+ -\item astConvert first attempts to register the two images on the -c- -f+ -\item AST\_CONVERT first attempts to register the two images on the -f- -celestial sphere (\emph{i.e.}\ using the SKY domain). To do this, it -searches for a celestial coordinate system, although not necessarily -the same one, attached to each image. If it finds a suitable pair of -coordinate systems, it then registers the images by matching -corresponding positions on the sky. - -c+ -\item If this fails, astConvert next tries to match positions in the -c- -f+ -\item If this fails, AST\_CONVERT next tries to match positions in the -f- -PIXEL domain (\secref{ss:framedomains}). If it succeeds, the two -images will then be registered so that their corresponding pixel -positions correspond. If the PIXEL domain is offset from the data grid -(as typically happens in data reduction systems which implement a -``pixel origin''), then this will be correctly accounted for. - -\item If this also fails, the GRID domain is finally used. This will -result in image registration by matching corresponding points in the -data grids used by both images. This means they will be -aligned so that the first element their data arrays correspond. - -c+ -\item If all of the above fail, astConvert will return the value -c- -f+ -\item If all of the above fail, AST\_CONVERT will return the value -f- -AST\_\_NULL. Otherwise a pointer to a FrameSet will be returned. -\end{enumerate} - -c+ -The resulting ``cvt'' FrameSet may then be used directly -(\secref{ss:convertingskyframes}) to convert between positions in the -data grid of the first image and corresponding positions in the data -grid of the second image. -c- -f+ -The resulting CVT FrameSet may then be used directly -(\secref{ss:convertingskyframes}) to convert between positions in the -data grid of the first image and corresponding positions in the data -grid of the second image. -f- - -To determine which domain was used to achieve registration, -we can use the fact that the Base attribute of each FrameSet is set by -c+ -astConvert to indicate which intermediate Frames were used. We -c- -f+ -AST\_CONVERT to indicate which intermediate Frames were used. We -f- -can therefore simply invert either FrameSet (to make its base Frame -become the current one) and then enquire the Domain value: - -c+ -\small -\begin{terminalv} -const char *domain; - -... - -astInvert( frameseta ); -domain = astGetC( frameseta, "Domain" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 20 ) DOMAIN - - ... - - - CALL AST_INVERT( FRAMESETA, STATUS ) - DOMAIN = AST_GETC( FRAMESETA, 'Domain', STATUS ) -\end{terminalv} -\normalsize -f- - -If conversion was successful, the result will be one of the strings -``SKY'', ``PIXEL'' or ``GRID''. - -\subsection{\label{ss:remapframe}Re-Defining a FrameSet Coordinate System} - -As discussed earlier (\secref{ss:baseandcurrent}), an important -application of a FrameSet is to allow coordinate system information to -be attached to entities such as images in order to calibrate them. In -addition, one of the main objectives of AST is to simplify the -propagation of such information through successive stages of data -processing, so that it remains consistent with the associated image -data. - -In such a situation, the FrameSet's base Frame would correspond with -the image's data grid coordinates and its other Frames (if any) with -the various alternative world coordinate systems associated with the -image. If the data processing being performed does not change the -relationship between the image's data grid coordinates and any of the -associated world coordinate systems, then propagation of the WCS -information is straightforward and simply involves copying the -FrameSet associated with the image. - -If any of these relationships change, however, then corresponding -changes must be made to the way Frames within the FrameSet are -inter-related. By far the most common case occurs when the image -undergoes some geometrical transformation resulting in ``re-gridding'' -on to another data grid, but the same principles can be applied to any -re-definition of a coordinate system. - -To pursue the re-gridding example, we would need to modify our -FrameSet to account for the fact that the image's data grid coordinate -system (corresponding to the FrameSet's base Frame) has -changed. Looking at the steps needed in detail, we might proceed as -follows: - -\begin{enumerate} -\item Create a Mapping which represents the relationship between the -original data grid coordinate system and the new one. - -c+ -\item Obtain a Frame to represent the new data grid coordinate system -(we could re-use the original base Frame here, using astGetFrame to -obtain a pointer to it). -c- -f+ -\item Obtain a Frame to represent the new data grid coordinate system -(we could re-use the original base Frame here, using AST\_GETFRAME to -obtain a pointer to it). -f- - -\item Add the new Frame to the FrameSet, related to the original base -Frame by the new Mapping. This Frame now represents the new data grid -coordinate system and is correctly related to all the other Frames -present.\footnote{This is because any transformation to or from this -new Frame must go \emph{via} the base Frame representing the original -data grid coordinate system, which we assume was correctly related to -all the other Frames present.} - -\item Remove the original base Frame (representing the old data grid -coordinate system). - -\item Make the new Frame the base Frame and restore the original -current Frame. -\end{enumerate} - - The effect of these steps is to change the relationship between the - base Frame and all the other Frames present. It is as if a new Mapping - has been interposed between the Frame we want to alter and all the - other Frames within the FrameSet (Figure~\ref{fig:fsremap}). - \begin{figure}[hbtp] - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/fsremap} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/fsremap} -f- -\caption[Interposing a Mapping into a FrameSet]{The effect -c+ - of astRemapFrame is to interpose a Mapping between -c- -f+ - of AST\_REMAPFRAME is to interpose a Mapping between -f- - a nominated Frame within a FrameSet and the remaining contents of the - FrameSet. This effectively ``re-defines'' the coordinate system - represented by the affected Frame. It may be used to compensate (say) - for geometrical changes made to an associated image. The - inter-relationships between all the other Frames within the FrameSet - remain unchanged.} - \label{fig:fsremap} - \end{center} - \end{figure} - -c+ -Performing the steps above is rather lengthy, however, so the -astRemapFrame function is provided to perform all of these operations -in one go. A practical example of its use is given below -(\secref{ss:wcsprocessingexample}). -c- -f+ -Performing the steps above is rather lengthy, however, so the -AST\_REMAPFRAME function is provided to perform all of these -operations in one go. A practical example of its use is given below -(\secref{ss:wcsprocessingexample}). -f- - -\subsection{\label{ss:wcsprocessingexample}Example---Binning an Image} - -c+ -As an example of using astRemapFrame, consider a case where the pixels -of a 2-dimensional image have been binned 2$\times$2, so as to reduce -the image size by a factor of two in each dimension. We must now -modify the associated FrameSet to reflect this change to the -image. Much the same process would be needed for any other geometrical -change the image might undergo. -c- -f+ -As an example of using AST\_REMAPFRAME, consider a case where the -pixels of a 2-dimensional image have been binned 2$\times$2, so as to -reduce the image size by a factor of two in each dimension. We must -now modify the associated FrameSet to reflect this change to the -image. Much the same process would be needed for any other geometrical -change the image might undergo. -f- - -We first set up a Mapping (a WinMap in this case) which relates the -data grid coordinates in the original image to those in the new one: - -c+ -\small -\begin{terminalv} -AstWinMap *winmap; -double ina[ 2 ] = { 0.5, 0.5 }; -double inb[ 2 ] = { 2.5, 2.5 }; -double outa[ 2 ] = { 0.5, 0.5 }; -double outb[ 2 ] = { 1.5, 1.5 }; - -... - -winmap = astWinMap( 2, ina, inb, outa, outb, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER WINMAP - DOUBLE PRECISION INA( 2 ), INB( 2 ), OUTA( 2 ), OUTB( 2 ) - DATA INA / 0.5D0, 0.5D0 / - DATA INB / 2.5D0, 2.5D0 / - DATA OUTA / 0.5D0, 0.5D0 / - DATA OUTB / 1.5DO, 1.5DO / - - ... - - WINMAP = AST_WINMAP( 2, INA, INB, OUTA, OUTB, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, we have simply set up arrays containing the data grid -coordinates of the bottom left and top right corners of the first -element in the output image (``outa'' and ``outb'') and the -corresponding coordinates in the input image (``ina'' and -``inb''). astWinMap then creates a WinMap which performs the required -transformation. We do not need to know the size of the image. -c- -f+ -Here, we have simply set up arrays containing the data grid -coordinates of the bottom left and top right corners of the first -element in the output image (OUTA and OUTB) and the corresponding -coordinates in the input image (INA and INB). AST\_WINMAP then creates -a WinMap which performs the required transformation. We do not need to -know the size of the image. -f- - -c+ -We can then pass this WinMap to astRemapFrame. This modifies the -relationship between our FrameSet's base Frame and the other Frames in -the FrameSet, so that the base Frame represents the data grid -coordinate system of the new image rather than the old one: -c- -f+ -We can then pass this WinMap to AST\_REMAPFRAME. This modifies the -relationship between our FrameSet's base Frame and the other Frames in -the FrameSet, so that the base Frame represents the data grid -coordinate system of the new image rather than the old one: -f- - -c+ -\small -\begin{terminalv} -AstFrameSet *frameset; - -... - -astRemapFrame( frameset, AST__BASE, winmap ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER FRAMESET - - ... - - CALL AST_REMAPFRAME( FRAMESET, AST__BASE, WINMAP, STATUS ) -\end{terminalv} -\normalsize -f- - -Any other coordinate systems described by the FrameSet, no matter how -many of these there might be, are now correctly associated with the -new image. - -\subsection{\label{ss:framesetintegrity}Maintaining the Integrity of FrameSets} - -When constructing a FrameSet, you are provided with a framework into -which you can place any combination of Frames and Mappings that you -wish. There are relatively few constraints on this process and no -checks are performed to see whether the FrameSet you construct makes -physical sense. It is quite possible, for example, to construct a -FrameSet containing two identical SkyFrames which are inter-related by -a non-unit Mapping. AST will not object if you do this, but it makes -no sense, because applying a non-unit Mapping to any set of celestial -coordinates cannot yield positions that are still in the original -coordinate system. If you use such a FrameSet to perform coordinate -conversions, you are likely to get unpredictable results because the -information in the FrameSet is corrupt. - -It is, of course, your responsibility as a programmer to ensure the -validity of any information which you insert into a -FrameSet. Normally, this is straightforward and simply consists of -formulating your problem correctly (a diagram can often help to -clarify how coordinate systems are inter-related) and writing the -appropriate bug-free code to construct the FrameSet. However, once you -start to modify an existing FrameSet, there are new opportunities for -corrupting it! - -c+ -Consider, for example, a FrameSet whose current Frame is a -SkyFrame. We can set a new value for this SkyFrame's Equinox attribute -simply by using astSet on the FrameSet, as follows: -c- -f+ -Consider, for example, a FrameSet whose current Frame is a -SkyFrame. We can set a new value for this SkyFrame's Equinox attribute -simply by using AST\_SET on the FrameSet, as follows: -f- - -c+ -\small -\begin{terminalv} -astSet( frameset, "Equinox=J2010" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( FRAMESET, 'Equinox=J2010', STATUS ) -\end{terminalv} -\normalsize -f- - -The effect of this will be to change the celestial coordinate system -which the current Frame represents. You can see, however, that this -has the potential to make the FrameSet corrupt unless corresponding -changes are also made to the Mapping which relates this SkyFrame to -the other Frames within the FrameSet. In fact, it is a general rule -that any change to a FrameSet which affects its current Frame can -potentially require corresponding changes to the FrameSet's Mappings -in order to maintain its overall integrity. - -c+ -Fortunately, once you have stored valid information in a FrameSet, AST -will look after these details for you automatically, so that the -FrameSet's integrity is maintained. In the example above, it would do -this by appropriately re-mapping the current Frame (as if -astRemapFrame had been used---\secref{ss:remapframe}) in response to -the use of astSet. One way of illustrating this process is as follows: -c- -f+ -Fortunately, once you have stored valid information in a FrameSet, AST -will look after these details for you automatically, so that the -FrameSet's integrity is maintained. In the example above, it would do -this by appropriately re-mapping the current Frame (as if -AST\_REMAPFRAME had been used---\secref{ss:remapframe}) in response to -the use of AST\_SET. One way of illustrating this process is as -follows: -f- - -c+ -\small -\begin{terminalv} -AstSkyFrame *skyframe; - -... - -skyframe = astSkyFrame( "" ); -frameSet = astFrameSet( skyframe ); -astAddFrame( frameset, 1, astUnitMap( 2, "" ), skyframe ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER SKYFRAME - - ... - - SKYFRAME = AST_SKYFRAME( ' ', STATUS ) - FRAMESET = AST_FRAMESET( SKYFRAME, STATUS ) - CALL AST_ADDFRAME( FRAMESET, 1, AST_UNITMAP( 2, ' ', STATUS ) - : SKYFRAME, STATUS ) -\end{terminalv} -\normalsize -f- - -This constructs a trivial FrameSet whose base and current Frames are -both the same SkyFrame connected by a UnitMap. You can think of this -as a ``pipe'' connecting two coordinate systems. At present, these two -systems represent identical ICRS coordinates, so the FrameSet -implements a unit Mapping. We can change the coordinate system on the -current end of this pipe as follows: - -c+ -\small -\begin{terminalv} -astSet( frameset, "System=Ecliptic, Equinox=J2010" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( FRAMESET, 'System=Ecliptic, Equinox=J2010', STATUS ) -\end{terminalv} -\normalsize -f- - -and the Mapping which the FrameSet implements would change -accordingly. To change the coordinate system on the base end of the -pipe, we might use: - -c+ -\small -\begin{terminalv} -astInvert( frameset ); -astSet( frameset, "System=Galactic" ); -astInvert( frameset ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_INVERT( FRAMESET ) - CALL AST_SET( FRAMESET, 'System=Galactic', STATUS ) - CALL AST_INVERT( FRAMESET ) -\end{terminalv} -\normalsize -f- - -The FrameSet would then convert between galactic and ecliptic -coordinates. - -c+ -Note that astSet is not the only function which has this effect: -astClear behaves similarly, as also does astPermAxes -(\secref{ss:permutingaxes}). If you need to circumvent this mechanism -for any reason, this can be done by going behind the scenes and -obtaining a pointer directly to the Frame you wish to modify. Consider -the following, for example: -c- -f+ -Note that AST\_SET is not the only function which has this effect: -AST\_CLEAR behaves similarly, as also does AST\_PERMAXES -(\secref{ss:permutingaxes}). If you need to circumvent this mechanism -for any reason, this can be done by going behind the scenes and -obtaining a pointer directly to the Frame you wish to modify. Consider -the following, for example: -f- - -c+ -\small -\begin{terminalv} -skyframe = astGetFrame( frameset, AST__CURRENT ); -astSet( skyframe, "Equinox=J2010" ); -skyframe = astAnnul( skyframe ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SKYFRAME = AST_GETFRAME( FRAMESET, AST__CURRENT, STATUS ) - CALL AST_SET( SKYFRAME, 'Equinox=J2010', STATUS ) - CALL AST_ANNUL( SKYFRAME, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, astSet is applied to the SkyFrame pointer rather than the -FrameSet pointer, so the usual checks on FrameSet integrity do not -occur. The SkyFrame's Equinox attribute will therefore be modified -without any corresponding change to the FrameSet's Mappings. In this -case you must take responsibility yourself for maintaining the -FrameSet's integrity, perhaps through appropriate use of -astRemapFrame. -c- -f+ -Here, AST\_SET is applied to the SkyFrame pointer rather than the -FrameSet pointer, so the usual checks on FrameSet integrity do not -occur. The SkyFrame's Equinox attribute will therefore be modified -without any corresponding change to the FrameSet's Mappings. In this -case you must take responsibility yourself for maintaining the -FrameSet's integrity, perhaps through appropriate use of -AST\_REMAPFRAME. -f- - -\subsection{Merging FrameSets} - - As well as adding individual Frames to a FrameSet - (\secref{ss:addingframes}), it is also possible to add complete sets of - inter-related Frames which are contained within another - FrameSet. This, of course, corresponds to the process of merging two - FrameSets (Figure~\ref{fig:fsmerge}). - \begin{figure}[hbtp] - \begin{center} -c+ - \includegraphics[width=0.7\textwidth]{sun211_figures/fsmerge} -c- -f+ - \includegraphics[width=0.7\textwidth]{sun210_figures/fsmerge} -f- - \caption[Two FrameSets in the process of being merged.]{Two FrameSets in the process of being merged using -c+ - astAddFrame. FrameSet~B is being added to FrameSet~A by supplying a -c- -f+ - AST\_ADDFRAME. FrameSet~B is being added to FrameSet~A by supplying a -f- - new Mapping which inter-relates a nominated Frame in A (here number~1) - and the current Frame of B. In the merged FrameSet, the Frames - contributed by B will be re-numbered to become Frames~4, 5 and 6. The - base Frame will remain unchanged, but the current Frame of B becomes - the new current Frame. Note that FrameSet~B itself is not - altered by this process.} - \label{fig:fsmerge} - \end{center} - \end{figure} - - - -c+ -This process is performed by adding one FrameSet to another using -astAddFrame, in much the same manner as when adding a new Frame to an -existing FrameSet (\secref{ss:addingframes}). It is simply a matter of -providing a FrameSet pointer, instead of a Frame pointer, for the 4th -argument. In performing the merger you must, as usual, supply a -Mapping, but in this case the Mapping should relate the current Frame -of the FrameSet being added to one of the Frames already present. For -example, you might perform the merger shown in -Figure~\ref{fig:fsmerge} as follows: -c- -f+ -This process is performed by adding one FrameSet to another using -AST\_ADDFRAME, in much the same manner as when adding a new Frame to -an existing FrameSet (\secref{ss:addingframes}). It is simply a matter -of providing a FrameSet pointer, instead of a Frame pointer, for the -4th argument. In performing the merger you must, as usual, supply a -Mapping, but in this case the Mapping should relate the current Frame -of the FrameSet being added to one of the Frames already present. For -example, you might perform the merger shown in -Figure~\ref{fig:fsmerge} as follows: -f- - -c+ -\small -\begin{terminalv} -AstMapping *mapping; - -... - -astAddFrame( frameseta, 1, mapping, framesetb ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER MAPPING - - ... - - CALL AST_ADDFRAME( FRAMESETA, 1, MAPPING, FRAMESETB, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The Frames acquired by ``frameseta'' from the FrameSet being added -(``framesetb'') are re-numbered so that they retain their original -order and follow on consecutively after the Frames that were already -present, whose indices remain unchanged. The base Frame of -``frameseta'' remains unchanged, but the current Frame of -``framesetb'' becomes its new current Frame. All the -inter-relationships between Frames in both FrameSets remain in place -and are preserved in the merged FrameSet. -c- -f+ -The Frames acquired by FRAMESETA from the FrameSet being added -(FRAMESETB) are re-numbered so that they retain their original order -and follow on consecutively after the Frames that were already -present, whose indices remain unchanged. The base Frame of FRAMESETA -remains unchanged, but the current Frame of FRAMESETB becomes its new -current Frame. All the inter-relationships between Frames in both -FrameSets remain in place and are preserved in the merged FrameSet. -f- - -c+ -Note that while this process modifies the first FrameSet -(``frameseta''), it leaves the original contents of the one being -added (``framesetb'') unchanged. -c- -f+ -Note that while this process modifies the first FrameSet (FRAMESETA), -it leaves the original contents of the one being added (FRAMESETB) -unchanged. -f- - -%\cleardoublepage -%\section{\label{ss:searching}TBW - Searching for Coordinate Systems} - -\cleardoublepage -\section{\label{ss:channels}Saving and Restoring Objects (Channels)} - -Facilities are provided by the AST library for performing input and -output (I/O) with any kind of Object. This means it is possible -to write any Object into various external representations for -storage, and then to read these representations back in, so as to -restore the original Object. Typically, an Object would be written by -one program and read back in by another. - -We refer to ``external representations'' in the plural because AST is -designed to function independently of any particular data storage -system. This means that Objects may need converting into a number of -different external representations in order to be compatible with -(say) the astronomical data storage system in which they will reside. - -In this section, we discuss the basic I/O facilities which support -external representations based on a textual format referred to as the AST -``native format''. These are implemented using a new kind of Object---a -Channel. We will examine later how to use other representations, based on -an XML format or on the use of FITS headers, for storing Objects. These -are implemented using more specialised forms of Channel called XmlChan -(\secref{ss:xmlchan}) and FitsChan (\secref{ss:nativefits}). - -\subsection{The Channel Model} - -c+ -The best way to start thinking about a Channel is like a C file -stream, and to think of the process of creating a Channel as that -of opening a file and obtaining a FILE pointer. Subsequently, you can -read and write Objects \emph{via} the Channel. -c- -f+ -The best way to start thinking about a Channel is like a Fortran I/O -unit (also represented by an integer, as it happens) and to think of -the process of creating a Channel as the combined process of -allocating a unit number and attaching it to a file by opening the -file on that unit. Subsequently, you can read and write Objects -\emph{via} the Channel. -f- - -c+ -This analogy is not quite perfect, however, because a Channel has, in -principle, two ``files'' attached to it. One is used when reading, and -the other when writing. These are termed the Channel's \emph{source} -and \emph{sink} respectively. In practice, the source and sink may -both be the same, in which case the analogy with the C file stream is -correct, but this need not always be so. It is not necessarily so with -the basic Channel, as we will now see (\secref{ss:creatingachannel}). -c- -f+ -This analogy is not quite perfect, however, because a Channel has, in -principle, two ``files'' attached to it. One is used when reading, and -the other when writing. These are termed the Channel's \emph{source} -and \emph{sink} respectively. In practice, the source and sink may -both be the same, in which case the analogy with the Fortran I/O unit -is correct, but this need not always be so. It is not necessarily so -with the basic Channel, as we will now see -(\secref{ss:creatingachannel}). -f- - -\subsection{\label{ss:creatingachannel}Creating a Channel} - -c+ -The process of creating a Channel is straightforward. As you -might expect, it uses the constructor function astChannel: - -\small -\begin{terminalv} -#include "ast.h" -AstChannel *channel; - -... - -channel = astChannel( NULL, NULL, "" ); -\end{terminalv} -\normalsize - -The first two arguments to astChannel specify the external source and -sink that the Channel is to use. There arguments are pointers to C -functions and we will examine their use in more detail later -(\secref{ss:channelsource} and \secref{ss:channelsink}). -c- -f+ -The process of creating a Channel is straightforward. As you -might expect, it uses the constructor function AST\_CHANNEL: - -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER CHANNEL, STATUS - - STATUS = 0 - - ... - - CHANNEL = AST_CHANNEL( AST_NULL, AST_NULL, ' ', STATUS ) -\end{terminalv} -\normalsize - -The first two arguments to AST\_CHANNEL specify the external source -and sink that the Channel is to use. There arguments are the names of -Fortran subroutines and we will examine their use in more detail later -(\secref{ss:channelsource} and \secref{ss:channelsink}). -f- - -c+ -In this very simple example we have supplied NULL pointers for both -the source and sink functions. This requests the default behaviour, -which means that textual input will be read from the program's -standard input stream (typically, this means your keyboard) while -textual output will go to the standard output stream (typically -appearing on your screen). On UNIX systems, of course, either of these -streams can easily be redirected to files. This default behaviour can be -changed by assigning values to the Channel's SinkFile and/or SourceFile -attributes. These attributes specify the paths to text files that are to -be used in place of the standard input and output streams. -c- -f+ -In this very simple example we have supplied the name of the null -routine AST\_NULL\footnote{Note that AST\_NULL (one underscore) is a -routine name and is distinct from AST\_\_NULL (two underscores) which -is a null Object pointer. Since we are passing the name of one -routine to another routine, AST\_NULL would normally have to appear in -a Fortran EXTERNAL statement. In this example, however, a suitable -statement is already present in the AST\_PAR include file.} for both -the source and sink routines. This requests the default behaviour, -which means that textual input will be read from the program's -standard input stream (typically, this means your keyboard) while -textual output will go to the standard output stream (typically -appearing on your screen). On UNIX systems, of course, either of these -streams can easily be redirected to files. -f- - -\subsection{\label{ss:writingtoachannel}Writing Objects to a Channel} - -c+ -The process of saving Objects is very straightforward. You can -simply write any Object to a Channel using the astWrite -function, as follows: - -\small -\begin{terminalv} -int nobj; -AstObject *object; - -... - -nobj = astWrite( channel, object ); -\end{terminalv} -\normalsize -c- -f+ -The process of saving Objects is very straightforward. You can -simply write any Object to a Channel using the AST\_WRITE -function, as follows: - -\small -\begin{terminalv} - INTEGER NOBJ, OBJECT - - ... - - NOBJ = AST_WRITE( CHANNEL, OBJECT, STATUS ) -\end{terminalv} -\normalsize -f- - -The effect of this will be to produce a textual description of the -Object which will appear, by default, on your program's standard -output stream. Any class of Object may be converted into text in this -way. - -c+ -astWrite returns a count of the number of Objects written. Usually, -this will be one, unless the Object supplied cannot be -represented. With a basic Channel all Objects can be represented, so a -value of one will always be returned unless there has been an -error. We will see later, however, that more specialised forms of -Channel may impose restrictions on the kind of Object you can write -(\secref{ss:foreignfitslimitations}). In such cases, astWrite may -return zero to indicate that the Object was not acceptable. -c- -f+ -AST\_WRITE returns a count of the number of Objects written. Usually, -this will be one, unless the Object supplied cannot be -represented. With a basic Channel all Objects can be represented, so a -value of one will always be returned unless there has been an -error. We will see later, however, that more specialised forms of -Channel may impose restrictions on the kind of Object you can write -(\secref{ss:foreignfitslimitations}). In such cases, AST\_WRITE may -return zero to indicate that the Object was not acceptable. -f- - -\subsection{\label{ss:readingfromachannel}Reading Objects from a Channel} - -Before discussing the format of the output produced above -(\secref{ss:writingtoachannel}), let us consider how to read it back, -so as to reconstruct the original Object. Naturally, we would first -need to save the output in a file. We can do that either by using the -SinkFile attribute, or (on UNIX systems), by redirecting standard output -to a file using a shell command like: - -\small -\begin{terminalv} -program1 >file -\end{terminalv} -\normalsize - -c+ -Within a subsequent program, we can read this Object back in by -using the astRead function, having first created a suitable -Channel: - -\small -\begin{terminalv} -object = astRead( channel ); -\end{terminalv} -\normalsize -c- -f+ -Within a subsequent program, we can read this Object back in by -using the AST\_READ function, having first created a suitable -Channel: - -\small -\begin{terminalv} - OBJECT = AST_READ( CHANNEL, STATUS ) -\end{terminalv} -\normalsize -f- - -By default, this function will read from the standard input stream -(the default source for a basic Channel), so we would need to ensure -that our second program reads its input from the file in which the -Object description is stored. On UNIX systems, we could again use a -shell redirection command such as: - -\small -\begin{terminalv} -program2 <file -\end{terminalv} -\normalsize - -Alternatively, we could have assigned a value to the SinkFile attribute -before invoking -c+ -astRead. -c- -f+ -AST\_READ. -f- - -\subsection{Saving and Restoring Multiple Objects} - -I/O operations performed on a basic Channel are sequential. This -means that if you write more than one Object to a Channel, -each new Object's textual description is simply appended to the -previous one. You can store any number of Objects in this way, -subject only to the storage space you have available. - -c+ -After you read an Object back from a basic Channel, the -Channel is ``positioned'' at the end of that Object's -textual description. If you then perform another read, you will -read the next Object's textual description and therefore -retrieve the next Object. This process may be repeated to read -each Object in turn. When there are no more Objects to be -read, astRead will return the value AST\_\_NULL to indicate an -\emph{end-of-file}. -c- -f+ -After you read an Object back from a basic Channel, the -Channel is ``positioned'' at the end of that Object's -textual description. If you then perform another read, you will -read the next Object's textual description and therefore -retrieve the next Object. This process may be repeated to read -each Object in turn. When there are no more Objects to be -read, AST\_READ will return the value AST\_\_NULL to indicate an -\emph{end-of-file}. -f- - -\subsection{\label{ss:validatinginput}Validating Input} - -c+ -The pointer returned by astRead (\secref{ss:readingfromachannel}) could -identify any class of Object---this is determined entirely by the -external data being read. If it is necessary to test for a particular -class (say a Frame), this may be done as follows using the appropriate -member of the astIsA$<$Class$>$ family of functions: - -\small -\begin{terminalv} -int ok; - -... - -ok = astIsAFrame( object ); -\end{terminalv} -\normalsize -c- -f+ -The pointer returned by AST\_READ (\secref{ss:readingfromachannel}) -could identify any class of Object---this is determined entirely by -the external data being read. If it is necessary to test for a -particular class (say a Frame), this may be done as follows using the -appropriate member of the AST\_ISA$<$CLASS$>$ family of functions: - -\small -\begin{terminalv} - LOGICAL OK - - ... - - OK = AST_ISAFRAME( OBJECT, STATUS ) -\end{terminalv} -\normalsize -f- - -Note, however, that this will accept any Frame, so would be equally -happy with a basic Frame or a SkyFrame. An alternative validation -strategy would be to obtain the value of the Object's Class attribute -and then test this character string, as follows: - -c+ -\small -\begin{terminalv} -#include <string.h> - -... - -ok = !strcmp( astGetC( object, "Class" ), "Frame" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - OK = AST_GETC( OBJECT, 'Class', STATUS ) .EQ. 'Frame' -\end{terminalv} -\normalsize -f- - -This would only accept a basic Frame and would reject a SkyFrame. - -\subsection{Storing an ID String with an Object} - -Occasionally, you may want to store a number of Objects and later -retrieve them and use each for a different purpose. If the Objects are -of the same class, you cannot use the Class attribute to distinguish -them when you read them back -(\emph{c.f.}~\secref{ss:validatinginput}). Although relying on the -order in which they are stored is a possible solution, this becomes -complicated if some of the Objects are optional and may not always be -present. It also makes extending your data format in future more -difficult. - -To help with this, every AST Object has an ID attribute and an Ident -attribute, both of which allows you, in effect, to attach a textual -identification label to it. You simply set the ID or Ident attribute before -writing the Object: - -c+ -\small -\begin{terminalv} -astSet( object, "ID=Calibration" ); -nobj = astWrite( channel, object ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( OBJECT, 'ID=Calibration', STATUS ) - NOBJ = AST_WRITE( CHANNEL, OBJECT, STATUS ) -\end{terminalv} -\normalsize -f- - -You can then test its value after you read the Object back: - -c+ -\small -\begin{terminalv} -object = astRead( channel ); -if ( !strcmp( astGetC( object, "ID" ), "Calibration" ) ) { - <the Calibration Object has been read> -} else { - <some other Object has been read> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - OBJECT = AST_READ( CHANNEL, STATUS ) - IF ( AST_GETC( OBJECT, 'ID', STATUS ) .EQ. 'Calibration' ) THEN - <the Calibration Object has been read> - ELSE - <some other Object has been read> - END IF -\end{terminalv} -\normalsize -f- - -The only difference between the ID and Ident attributes is that the ID -attribute is unique to a particular Object and is lost if, for example, -you make a copy of the Object. The Ident attrubute, on the other hand, is -transferred to the new Object when a copy is made. Consequently, it is -safest to set the value of the ID attribute immediately before you -perform the write. - -\subsection{\label{ss:textualoutputformat}The Textual Output Format} - -Let us now examine the format of the textual output produced by -writing an Object to a basic Channel -(\secref{ss:writingtoachannel}). To give a concrete example, suppose -the Object in question is a SkyFrame, written out as follows: - -c+ -\small -\begin{terminalv} -AstSkyFrame *skyframe; - -... - -nobj = astWrite( channel, skyframe ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER SKYFRAME - - ... - - NOBJ = AST_WRITE( CHANNEL, SKYFRAME, STATUS ) -\end{terminalv} -\normalsize -f- - -The output should then look like the following: - -\small -\begin{terminalv} - Begin SkyFrame # Description of celestial coordinate system -# Title = "FK4 Equatorial Coordinates, no E-terms, Mean Equinox B1950.0, Epoch B1958.0" # Title of coordinate system - Naxes = 2 # Number of coordinate axes -# Domain = "SKY" # Coordinate system domain -# Lbl1 = "Right Ascension" # Label for axis 1 -# Lbl2 = "Declination" # Label for axis 2 -# Uni1 = "hh:mm:ss.s" # Units for axis 1 -# Uni2 = "ddd:mm:ss" # Units for axis 2 -# Dir1 = 0 # Plot axis 1 in reverse direction (hint) - Ax1 = # Axis number 1 - Begin SkyAxis # Celestial coordinate axis - End SkyAxis - Ax2 = # Axis number 2 - Begin SkyAxis # Celestial coordinate axis - End SkyAxis - IsA Frame # Coordinate system description - System = "FK4-NO-E" # Celestial coordinate system type - Epoch = 1958 # Besselian epoch of observation -# Eqnox = 1950 # Besselian epoch of mean equinox - End SkyFrame -\end{terminalv} -\normalsize - -c+ -You will notice that this output is designed both for a human reader, -in that it is formatted, and also to be read back by a computer in -order to reconstruct the SkyFrame. In fact, this is precisely the way -that astShow works (\secref{ss:displayingobjects}), this function being -roughly equivalent to the following use of a Channel: - -\small -\begin{terminalv} -channel = astChannel( NULL, NULL, "" ); -(void) astWrite( channel, object ); -channel = astAnnul( channel ); -\end{terminalv} -\normalsize -c- -f+ -You will notice that this output is designed both for a human reader, -in that it is formatted, and also to be read back by a computer in -order to reconstruct the SkyFrame. In fact, this is precisely the way -that AST\_SHOW works (\secref{ss:displayingobjects}), this routine -being roughly equivalent to the following use of a Channel: - -\small -\begin{terminalv} - CHANNEL = AST_CHANNEL( AST_NULL, AST_NULL, ' ', STATUS ) - NOBJ = AST_WRITE( CHANNEL, OBJECT, STATUS ) - CALL AST_ANNUL( CHANNEL, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Some lines of the output start with a ``\verb?#?'' comment character, -which turns the rest of the line into a comment. These lines will be -ignored when read back in by astRead. They typically contain default -values, or values that can be derived in some way from the other data -present, so that they do not actually need to be stored in order to -reconstruct the original Object. They are provided purely for human -information. The same comment character is also used to append -explanatory comments to most output lines. -c- -f+ -Some lines of the output start with a ``\verb?#?'' comment character, -which turns the rest of the line into a comment. These lines will be -ignored when read back in by AST\_READ. They typically contain -default values, or values that can be derived in some way from the -other data present, so that they do not actually need to be stored in -order to reconstruct the original Object. They are provided purely for -human information. The same comment character is also used to append -explanatory comments to most output lines. -f- - -It is not sensible to attempt a complete description of this output -format because every class of Object is potentially different and each -can define how its own data should be represented. However, there are -some basic rules, which mean that the following common features will -usually be present: - -\begin{enumerate} -\item Each Object is delimited by matching ``Begin'' and ``End'' -lines, which also identify the class of Object involved. - -\item Within each Object description, data values are represented -by a simple ``keyword~$=$~value'' syntax, with one value to a line. - -\item Lines beginning ``IsA'' are used to mark the divisions between -data belonging to different levels in the class hierarchy -(\appref{ss:classhierarchy}). Thus, ``IsA~Frame'' marks the end of data -associated with the Frame class and the start of data associated with -some derived class (a SkyFrame in the above example). ``IsA'' lines -may be omitted if associated data values are absent and no confusion -arises. - -\item Objects may contain other Objects as data. This is -indicated by an absent value, with the description of the data -Object following on subsequent lines. - -\item Indentation is used to clarify the overall structure. -\end{enumerate} - -Beyond these general principles, the best guide to what a particular -line of output represents will generally be the comment which -accompanies it together with a general knowledge of the class of -Object being described. - -\subsection{\label{ss:controllingchanneloutput}Controlling the Amount of Output} - -c+ -It is not always necessary for the output from astWrite -(\secref{ss:writingtoachannel}) to be human-readable, so a Channel has -attributes that allow the amount of detail in the output to be -controlled. -c- -f+ -It is not always necessary for the output from AST\_WRITE -(\secref{ss:writingtoachannel}) to be human-readable, so a Channel has -attributes that allow the amount of detail in the output to be -controlled. -f- - -The first of these is the integer attribute Full, which controls the -extent to which optional, commented out, output lines are produced. By -default, Full is zero, and this results in the standard style of -output (\secref{ss:textualoutputformat}) where default values that may -be helpful to humans are included. To suppress these optional lines, -Full should be set to $-$1. This is most conveniently done when the -Channel is created, so that: - -c+ -\small -\begin{terminalv} -channel = astChannel( NULL, NULL, "Full=-1" ); -(void) astWrite( channel, skyframe ); -channel = astAnnul( channel ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHANNEL = AST_CHANNEL( AST_NULL, AST_NULL, 'Full=-1', STATUS ) - NOBJ = AST_WRITE( CHANNEL, SKYFRAME, STATUS ) - CALL AST_ANNUL( CHANNEL, STATUS ) -\end{terminalv} -\normalsize -f- - -would result in output containing only the essential information, such -as: - -\small -\begin{terminalv} - Begin SkyFrame # Description of celestial coordinate system - Naxes = 2 # Number of coordinate axes - Ax1 = # Axis number 1 - Begin SkyAxis # Celestial coordinate axis - End SkyAxis - Ax2 = # Axis number 2 - Begin SkyAxis # Celestial coordinate axis - End SkyAxis - IsA Frame # Coordinate system description - System = "FK4-NO-E" # Celestial coordinate system type - Epoch = 1958 # Besselian epoch of observation - End SkyFrame -\end{terminalv} -\normalsize - -In contrast, setting Full to $+$1 will result in additional output -lines which will reveal every last detail of the Object's -construction. Often this will be rather more than you want, especially -for more complex Objects, but it can sometimes help when debugging -programs. This is how a SkyFrame appears at this level of detail: - -\small -\begin{terminalv} - Begin SkyFrame # Description of celestial coordinate system -# RefCnt = 1 # Count of active Object pointers -# Nobj = 1 # Count of active Objects in same class - IsA Object # Astrometry Object -# Nin = 2 # Number of input coordinates -# Nout = 2 # Number of output coordinates -# Invert = 0 # Mapping not inverted -# Fwd = 1 # Forward transformation defined -# Inv = 1 # Inverse transformation defined -# Report = 0 # Don't report coordinate transformations - IsA Mapping # Mapping between coordinate systems -# Title = "FK4 Equatorial Coordinates, no E-terms, Mean Equinox B1950.0, Epoch B1958.0" # Title of coordinate system - Naxes = 2 # Number of coordinate axes -# Domain = "SKY" # Coordinate system domain -# Lbl1 = "Right Ascension" # Label for axis 1 -# Lbl2 = "Declination" # Label for axis 2 -# Sym1 = "RA" # Symbol for axis 1 -# Sym2 = "Dec" # Symbol for axis 2 -# Uni1 = "hh:mm:ss.s" # Units for axis 1 -# Uni2 = "ddd:mm:ss" # Units for axis 2 -# Dig1 = 7 # Individual precision for axis 1 -# Dig2 = 7 # Individual precision for axis 2 -# Digits = 7 # Default formatting precision -# Fmt1 = "hms.1" # Format specifier for axis 1 -# Fmt2 = "dms" # Format specifier for axis 2 -# Dir1 = 0 # Plot axis 1 in reverse direction (hint) -# Dir2 = 1 # Plot axis 2 in conventional direction (hint) -# Presrv = 0 # Don't preserve target axes -# Permut = 1 # Axes may be permuted to match -# MinAx = 2 # Minimum number of axes to match -# MaxAx = 2 # Maximum number of axes to match -# MchEnd = 0 # Match initial target axes -# Prm1 = 1 # Axis 1 not permuted -# Prm2 = 2 # Axis 2 not permuted - Ax1 = # Axis number 1 - Begin SkyAxis # Celestial coordinate axis -# RefCnt = 1 # Count of active Object pointers -# Nobj = 2 # Count of active Objects in same class - IsA Object # Astrometry Object -# Label = "Angle on Sky" # Axis Label -# Symbol = "delta" # Axis symbol -# Unit = "ddd:mm:ss" # Axis units -# Digits = 7 # Default formatting precision -# Format = "dms" # Format specifier -# Dirn = 1 # Plot in conventional direction - IsA Axis # Coordinate axis -# Format = "dms" # Format specifier -# IsLat = 0 # Longitude axis (not latitude) -# AsTime = 0 # Display values as angles (not times) - End SkyAxis - Ax2 = # Axis number 2 - Begin SkyAxis # Celestial coordinate axis -# RefCnt = 1 # Count of active Object pointers -# Nobj = 2 # Count of active Objects in same class - IsA Object # Astrometry Object -# Label = "Angle on Sky" # Axis Label -# Symbol = "delta" # Axis symbol -# Unit = "ddd:mm:ss" # Axis units -# Digits = 7 # Default formatting precision -# Format = "dms" # Format specifier -# Dirn = 1 # Plot in conventional direction - IsA Axis # Coordinate axis -# Format = "dms" # Format specifier -# IsLat = 0 # Longitude axis (not latitude) -# AsTime = 0 # Display values as angles (not times) - End SkyAxis - IsA Frame # Coordinate system description - System = "FK4-NO-E" # Celestial coordinate system type - Epoch = 1958 # Besselian epoch of observation -# Eqnox = 1950 # Besselian epoch of mean equinox - End SkyFrame -\end{terminalv} -\normalsize - -\subsection{\label{ss:channelcommenting}Controlling Commenting} - -Another way of controlling output from a Channel is \emph{via} the -boolean (integer) Comment attribute, which controls whether comments -are appended to describe the purpose of each value. Comment has the -value 1 by default but, if set to zero, will suppress these -comments. This is normally appropriate only if you wish to minimise -the amount of output, for example: - -c+ -\small -\begin{terminalv} -astSet( channel, "Full=-1, Comment=0" ); -nobj = astWrite( channel, skyframe ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( CHANNEL, 'Full=-1, Comment=0', STATUS ) - NOBJ = AST_WRITE( CHANNEL, SKYFRAME, STATUS ) -\end{terminalv} -\normalsize -f- - -might result in the following more compact output: - -\small -\begin{terminalv} - Begin SkyFrame - Naxes = 2 - Ax1 = - Begin SkyAxis - End SkyAxis - Ax2 = - Begin SkyAxis - End SkyAxis - IsA Frame - System = "FK4-NO-E" - Epoch = 1958 - End SkyFrame -\end{terminalv} -\normalsize - -\subsection{Editing Textual Output} - -c+ -The safest advice about editing the textual output from astWrite (or -astShow) is ``don't!''---unless you know what you are doing. -c+ -f+ -The safest advice about editing the textual output from AST\_WRITE (or -AST\_SHOW) is ``don't!''---unless you know what you are doing. -f- - -Having given that warning, however, it is sometimes possible to make -changes to the text, or even to write entire Object descriptions from -scratch, and to read the results back in to construct new -Objects. Normally, simple changes to numerical values are safest, but -be aware that this is a back door method of creating Objects, so -you are on your own! There are a number of potential pitfalls. In -particular: - -\begin{itemize} -c+ -\item astRead is intended for retrieving data written by astWrite and -not for reading data input by humans. As such, the data validation -provided is very limited and is certainly not foolproof. This makes it -quite easy to construct Objects that are internally inconsistent by -this means. In contrast, the normal programming interface incorporates -numerous checks designed to make it impossible to construct invalid -Objects. You should not necessarily think you have found a bug if your -changes to an Object's textual description fail to produce the results -you expected! -c- -f+ -\item AST\_READ is intended for retrieving data written by AST\_WRITE -and not for reading data input by humans. As such, the data validation -provided is very limited and is certainly not foolproof. This makes it -quite easy to construct Objects that are internally inconsistent by -this means. In contrast, the normal programming interface incorporates -numerous checks designed to make it impossible to construct invalid -Objects. You should not necessarily think you have found a bug if your -changes to an Object's textual description fail to produce the results -you expected! -f- - -\item In many instances the names associated with values in textual -output will correspond with Object attributes. Sometimes, however, -these names may differ from the attribute name. This is mainly because -of length restrictions imposed by other common external formats, such -as FITS headers. Some of the names used do not correspond with -attributes at all. - -\item It is safest to change single numerical or string values. -Beware of changing the size or shape of Objects (\emph{e.g.}\ the -number of axes in a Frame). Often, these values must match others -stored elsewhere within the Object and changing them in a haphazard -fashion will not produce useful results. - -\item Be wary about un-commenting default values. Sometimes this will -work, but often these values are derived from other Objects stored -more deeply in the structure and the proper place to insert a new -value is not where the default itself appears. -\end{itemize} - -\subsection{\label{ss:mixingchanneltext}Mixing Objects with other Text} - -c+ -By default, when you use astRead to read from a basic Channel -(\secref{ss:readingfromachannel}), it is assumed that you are reading a -stream of text containing only AST Objects, which follow each other -end-to-end. If any extraneous input data are encountered which do not -appear to form part of the textual description of an Object, then an -error will result. In particular, the first input line must identify -the start of an Object description, so you cannot start reading half -way through an Object. -c- -f+ -By default, when you use AST\_READ to read from a basic Channel -(\secref{ss:readingfromachannel}), it is assumed that you are reading a -stream of text containing only AST Objects, which follow each other -end-to-end. If any extraneous input data are encountered which do not -appear to form part of the textual description of an Object, then an -error will result. In particular, the first input line must identify -the start of an Object description, so you cannot start reading half -way through an Object. -f- - -Sometimes, however, you may want to store AST Object descriptions -intermixed with other textual data. You can do this by setting the -Channel's boolean (integer) Skip attribute to 1. This will cause every -read to skip over extraneous data until the start of a new AST Object -description, if any, is found. So long as your other data do not mimic -the appearance of an AST Object description, the two sets of data can -co-exist. - -c+ -For example, by setting Skip to 1, the following complete C program -will read all the AST Objects whose descriptions appear in the source -of this document, ignoring the other text. astShow is used to display -those found: - -\small -\begin{terminalv} -#include "ast.h" -main() { - AstChannel *channel; - AstObject *object; - - channel = astChannel( NULL, NULL, "Skip=1" ); - while ( ( object = astRead( channel ) ) != AST__NULL ) { - astShow( object ); - object = astAnnul( object ); - } - channel = astAnnul( channel ); -} -\end{terminalv} -\normalsize -c- -f+ -For example, by setting Skip to 1, the following complete Fortran -program will read all the AST Objects whose descriptions appear in the -source of this document, ignoring the other text. AST\_SHOW is used to -display those found: - -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER CHANNEL, OBJECT, STATUS - - STATUS = 0 - CHANNEL = AST_CHANNEL( AST_NULL, AST_NULL, 'Skip=1', STATUS ) - 1 OBJECT = AST_READ( CHANNEL, STATUS ) - IF ( OBJECT .NE. AST__NULL ) THEN - CALL AST_SHOW( OBJECT, STATUS ) - CALL AST_ANNUL( OBJECT, STATUS ) - GO TO 1 - END IF - CALL AST_ANNUL( CHANNEL, STATUS ) - END -\end{terminalv} -\normalsize -f- - -\subsection{\label{ss:channelsource}Reading Objects from Files} - -Thus far, we have only considered the default behaviour of a Channel -in reading and writing Objects through a program's standard input and -output streams. We will now consider how to access Objects stored in -files more directly. - -The simple approach is to use the SinkFile and SourceFile attributes of -the Channel. For instance, the following will read a pair of Objects from -a text file called ``fred.txt'': - -c+ -\small -\begin{terminalv} -astSet( channel, "SourceFile=fred.txt" ); -obj1 = astRead( channel ); -obj2 = astRead( channel ); -astClear( channel, "SourceFile" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( CHANNEL, 'SourceFile=fred.txt', STATUS ) - OBJ1 = AST_READ( CHANNEL, STATUS ) - OBJ2 = AST_READ( CHANNEL, STATUS ) - CALL AST_CLEAR( CHANNEL, 'SourceFile', STATUS ) -\end{terminalv} -\normalsize -f- - -Note, the act of clearing the attribute tells AST that no more Objects -are to be read from the file and so the file is then closed. If the -attribute is not cleared, the file will remain open and further Objects -can be read from it. The file will always be closed when the Channel is -deleted. - -This simple approach will normally be sufficient. However, because the -AST library is designed to be used from more than one language, it has -to be a little careful about reading and writing to files. This is due -to incompatibilities that may exist between the file I/O facilities -provided by different languages. If such incompatibilities prevent the -above simple system being used, we need to adopt a system that off-loads -all file I/O to external code. - -c+ -What this means in practice is that if the above simple approach cannot -be used, you must instead provide some simple C -functions that perform the actual transfer of data to and from files -and similar external data stores. The functions you provide are -supplied as the source and/or sink function arguments to astChannel -when you create a Channel (\secref{ss:creatingachannel}). An example is -the best way to illustrate this. -c- -f+ -What this means in practice is that if the above simple approach cannot -be used, you must instead provide some simple -Fortran routines that perform the actual transfer of data to and from -files and similar external data stores. The routines you provide are -supplied as the source and/or sink routine arguments to AST\_CHANNEL -when you create a Channel (\secref{ss:creatingachannel}). An example is -the best way to illustrate this. -f- - -c+ -Consider the following simple function called Source. It reads a -single line of text from a C input stream and returns a pointer to it, -or NULL if there is no more input: - -\small -\begin{terminalv} -#include <stdio.h> -#define LEN 200 -static FILE *input_stream; - -const char *Source( void ) { - static char buffer[ LEN + 2 ]; - return fgets( buffer, LEN + 2, input_stream ); -} -\end{terminalv} -\normalsize -c- -f+ -Consider the following simple subroutine called SOURCE. It reads a -single line of text from a Fortran I/O unit and then calls -AST\_PUTLINE to pass it to the AST library, together with its -length. It sets this length to be negative if there is no more input: - -\small -\begin{terminalv} - SUBROUTINE SOURCE( STATUS ) - INTEGER STATUS - CHARACTER * ( 200 ) BUFFER - - READ( 1, '(A)', END = 99 ) BUFFER - CALL AST_PUTLINE( BUFFER, LEN( BUFFER ), STATUS ) - RETURN - - 99 CALL AST_PUTLINE( BUFFER, -1, STATUS ) - END -\end{terminalv} -\normalsize -f- - -c+ -Note that the input stream is a static variable which we will also -access from our main program. This might look something like this -(omitting error checking for brevity): - -\small -\begin{terminalv} -/* Open the input file. */ -input_stream = fopen( "infile.ast", "r" ); - -/* Create a Channel and read an Object from it. */ -channel = astChannel( Source, NULL, "" ); -object = astRead( channel ); - -... - -/* Annul the Channel and close the file when done. */ -channel = astAnnul( channel ); -(void) fclose( input_stream ); -\end{terminalv} -\normalsize -c- -f+ -Our main program might then look something like this (omitting error -checking for brevity): - -\small -\begin{terminalv} - EXTERNAL SOURCE - - ... - -* Open the input file. - OPEN( UNIT = 1, FILE = 'infile.ast', STATUS = 'OLD' ) - -* Create the Channel and read an Object from it. - CHANNEL = AST_CHANNEL( SOURCE, AST_NULL, ' ', STATUS ) - OBJECT = AST_READ( CHANNEL, STATUS ) - - ... - -* Annul the Channel and close the file when done. - CALL AST_ANNUL( CHANNEL, STATUS ) - CLOSE( 1 ) -\end{terminalv} -\normalsize -f- - -c+ -Here, we first open the required input file, saving the resulting FILE -pointer. We then pass a pointer to our Source function as the first -argument to astChannel when creating a new Channel. When we read -an Object from this Channel with astRead, the Source -function will be called to obtain the textual data from the file, the -end-of-file being detected when this function returns NULL. -c- -f+ -Here, we first open the required input file. We then pass the name of -our SOURCE routine as the first argument to AST\_CHANNEL when creating -a new Channel (ensuring that SOURCE also appears in an EXTERNAL -statement). When we read an Object from this Channel using -AST\_READ, the SOURCE routine will be called to obtain the textual -data from the file, the end-of-file being detected when it yields a -negative line length. -f- - -Note, if a value is set for the SourceFile attribute, -c+ -the astRead function will ignore any source function -c- -f+ -the AST\_READ function will ignore any source routine -f- -specified when the Channel was created. - -\subsection{\label{ss:channelsink}Writing Objects to Files} - -As for reading, writing Objects to files can be done in two different ways. -Again, the simple approach is to use the SinkFile attribute of the Channel. -For instance, the following will write a pair of Objects to a text file -called ``fred.txt'': - -c+ -\small -\begin{terminalv} -astSet( channel, "SinkFile=fred.txt" ); -nobj = astWrite( channel, object1 ); -nobj = astWrite( channel, object2 ); -astClear( channel, "SinkFile" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_SET( CHANNEL, 'SinkFile=fred.txt', STATUS ) - NOBJ = AST_WRITE( CHANNEL, OBJECT1, STATUS ) - NOBJ = AST_WRITE( CHANNEL, OBJECT2, STATUS ) - CALL AST_CLEAR( CHANNEL, 'SinkFile', STATUS ) -\end{terminalv} -\normalsize -f- - -Note, the act of clearing the attribute tells AST that no more output -will be written to the file and so the file is then closed. If the -attribute is not cleared, the file will remain open and further Objects -can be written to it. The file will always be closed when the Channel is -deleted. - -c+ -If the details of the language's I/O system on the computer you are using -means that the above approach cannot be used, then we can write a Sink function, -that writes a line of output text to a file, and use it in basically the same -way as the Source function in the previous section (\secref{ss:channelsource}): - -\small -\begin{terminalv} -static FILE *output_stream; - -void Sink( const char *line ) { - (void) fprintf( output_stream, "%s\n", line ); -} -\end{terminalv} -\normalsize - -Note that we must supply the final newline character ourselves. -c- -f+ -If the details of the language's I/O system on the computer you are using -means that the above approach cannot be used, then we can write a SINK routine, -that obtains a line of output text from the AST library by calling AST\_GETLINE -and then writes it to a file. We can use this in basically the same way as -the SOURCE routine in the previous section (\secref{ss:channelsource}): - -\small -\begin{terminalv} - SUBROUTINE SINK( STATUS ) - INTEGER L, STATUS - CHARACTER * ( 200 ) BUFFER - - CALL AST_GETLINE( BUFFER, L, STATUS ) - IF ( L .GT. 0 ) WRITE( 2, '(A)' ) BUFFER( : L ) - - END -\end{terminalv} -\normalsize -f- - -c+ -In this case, our main program would supply a pointer to this Sink -function as the second argument to astChannel, as follows: - -\small -\begin{terminalv} -/* Open the output file. */ -output_stream = fopen( "outfile.ast", "w" ); - -/* Create a Channel and write an Object to it. */ -channel = astChannel( Source, Sink, "" ); -nobj = astWrite( channel, object ); - - ... - -/* Annul the Channel and close the file when done. */ -channel = astAnnul( channel ); -(void) fclose( output_stream ); -\end{terminalv} -\normalsize -c- -f+ -In this case, our main program would supply the name of this SINK -routine as the second argument to AST\_CHANNEL (ensuring that it also -appears in an EXTERNAL statement), as follows: - -\small -\begin{terminalv} - EXTERNAL SINK - - ... - -* Open the output file. - OPEN( UNIT = 2, FILE = 'outfile.ast', STATUS = 'NEW' ) - -* Create a Channel and write an Object to it. - CHANNEL = AST_CHANNEL( SOURCE, SINK, ' ', STATUS ) - NOBJ = AST_WRITE( CHANNEL, OBJECT, STATUS ) - - ... - -* Annul the Channel and close the file when done. - CALL AST_ANNUL( CHANNEL, STATUS ) - CLOSE( 2 ) -\end{terminalv} -\normalsize -f- - -c+ -Note that we can specify a source and/or a sink function for the -Channel, and that these may use either the same file, or different -files according to whether we are reading or writing. AST has no -knowledge of the underlying file system, nor of file positioning. It -just reads and writes sequentially. If you wish, for example, to -reposition a file at the beginning in between reads and writes, then -this can be done directly (and completely independently of AST) using -standard C functions. -c- -f+ -Note that we can specify a source and/or a sink routine for the -Channel, and that these may use either the same file, or different -files according to whether we are reading or writing. AST has no -knowledge of the underlying file system, nor of file positioning. It -just reads and writes sequentially. If you wish, for example, to -reposition a file at the beginning in between reads and writes, then -this can be done directly (and completely independently of AST) using -standard Fortran statements. -f- - -c+ -If an error occurs in your source or sink function, you can -communicate this to the AST library by setting its error status to any -error value using astSetStatus (\secref{ss:errordetection}). This will -immediately terminate the read or write operation. -c- -f+ -If an error occurs in your source or sink routine, you can communicate -this to the AST library by setting the STATUS argument to any error -value. This will immediately terminate the read or write operation. -f- - -Note, if a value is set for the SinkFile attribute, -c+ -the astWrite function will ignore any sink function -c- -f+ -the AST\_WRITE function will ignore any sink routine -f- -specified when the Channel was created. - -\subsection{\label{ss:otherplaces}Reading and Writing Objects to other Places} - -c+ -It should be obvious from the above (\secref{ss:channelsource} and -\secref{ss:channelsink}) that a Channel's source and sink functions -provide a flexible means of intercepting textual data that describes -AST Objects as it flows in and out of your program. In fact, you might -like to regard a Channel simply as a filter for converting AST Objects -to and from a stream of text which is then handled by your source and -sink functions, where the real I/O occurs. -c- -f+ -It should be obvious from the above (\secref{ss:channelsource} and -\secref{ss:channelsink}) that a Channel's source and sink routines -provide a flexible means of intercepting textual data that describes -AST Objects as it flows in and out of your program. In fact, you might -like to regard a Channel simply as a filter for converting AST Objects -to and from a stream of text which is then handled by your source and -sink routines, where the real I/O occurs. -f- - -This gives you the ability to store AST Objects in virtually any data -system, so long as you can convert a stream of text into something -that can be stored (it need no longer be text) and retrieve it -again. There is generally no need to retain comments. Other -possibilities, such as inter-process and network communication, could -also be implemented \emph{via} source and sink functions in basically -the same way. - -\cleardoublepage -\section{\label{ss:nativefits}Storing AST Objects in FITS Headers (FitsChans)} - -A FITS header is a sequence of 80-character strings, formatted -according to particular rules defined by the Flexible Image Transport -System -(FITS). \htmladdnormallinkfoot{FITS}{http://fits.gsfc.nasa.gov/} -is a widely-used standard for data interchange in astronomy and has -also been adopted as a data processing format in some astronomical -data reduction systems. The individual 80-character strings in a FITS -header are usually called \emph{cards} or \emph{header cards} (for -entirely anachronistic reasons). - -A sequence of FITS cards appears as a header at the start of every -FITS data file, and sometimes also at other points within it, and is -used to provide ancillary information which qualifies or describes the -main array of data stored in the file. As such, FITS headers are prime -territory for storing information about the coordinate systems -associated with data held in FITS files. - -In this section, we will examine how to store information in FITS -headers directly in the form of AST Objects---a process which is -supported by a specialised class of Channel called a FitsChan. Our -discussion here will turn out to be a transitional step that -emphasises the similarities between a FitsChan and a Channel -(\secref{ss:channels}). At the same time, it will prepare us for the -next section (\secref{ss:foreignfits}), where we will examine how to -use a FitsChan to tackle some of the more difficult problems that FITS -headers can present. - -\subsection{\label{ss:nativeencoding}The Native FITS Encoding} - -As it turns out, we are not the first to have thought of storing WCS -information in FITS headers. In fact, the original FITS standard (1981 -vintage) defined a set of header keywords for this purpose which have -been widely used, although they have proved too limited for many -practical purposes. - -At the time of writing, a number of different ways of using FITS -headers for storing WCS information are in use, most (although not -all) based on the original standard. We will refer to these -alternative ways of storing the information as FITS \emph{encodings} -but will defer a discussion of their advantages and limitations until -the next section (\secref{ss:foreignfits}). - -Here, we will examine how to store AST Objects directly in FITS -headers. In effect, this defines a new encoding, which we will term -the \emph{native encoding}. This is a special kind of encoding, -because not only does it allow us to associate conventional -WCS calibration information with FITS data, but it also allows any other -information that can be expressed in terms of AST Objects to be stored -as well. In fact, the native encoding provides us with facilities -roughly analogous to those of the Channel -(\secref{ss:channels})---\emph{i.e.}\ a lossless way of -transferring AST Objects from program to program---but based on FITS -headers instead of free-format text. - -\subsection{The FitsChan Model} - -I/O between AST Objects and FITS headers is supported by a specialised -form of Channel called a FitsChan. A FitsChan contains a buffer which -may hold any number, including zero, of FITS header cards. This buffer -forms a workspace in which you can assemble FITS cards and manipulate -them before writing them out to a file. - -By default, when a FitsChan is first created, it contains no cards and -there are five ways of inserting cards into it: - -\begin{enumerate} -c+ -\item You may add cards yourself, one at a time, using astPutFits -(\secref{ss:addingfitscards}). -c- -f+ -\item You may add cards yourself, one at a time, using AST\_PUTFITS -(\secref{ss:addingfitscards}). -f- - -c+ -\item You may add cards yourself, supplying all cards concatenated into a -single string, using astPutCards -(\secref{ss:addingmulticards}). -c- -f+ -\item You may add cards yourself, supplying all cards concatenated into a -single string, using AST\_PUTCARDS. -(\secref{ss:addingmulticards}). -f- - -c+ -\item You may write an AST Object to the FitsChan (using astWrite), -which will have the effect of creating new cards within the FitsChan -which describe the Object (\secref{ss:writingnativefits}). -c- -f+ -\item You may write an AST Object to the FitsChan (using AST\_WRITE), -which will have the effect of creating new cards within the FitsChan -which describe the Object (\secref{ss:writingnativefits}). -f- - -\item You may assign a value to the SourceFile attribute of the FitsChan. -The value should be the path to a text file holding a set of FITS header -cards, one per line. When the SourceFile value is set (using -c+ -astSetC or astSet), -c- -f+ -AST\_SETC or AST\_SET). -f- -the file is opened and the headers copied from it into the FitsChan. -The file is then immediately closed. - -c+ -\item You may specify a source function which reads data from some -external store of FITS cards, just like the source associated with a -basic Channel (\secref{ss:channelsource}). If you supply a source -function, it will be called when the FitsChan is created in order to -fill it with an initial set of cards (\secref{ss:fitssourceandsink}). -c- -f+ -\item You may specify a source routine which reads data from some -external store of FITS cards, just like the source associated with a -basic Channel (\secref{ss:channelsource}). If you supply a source -routine, it will be called when the FitsChan is created in order to -fill it with an initial set of cards (\secref{ss:fitssourceandsink}). -f- -\end{enumerate} - -There are also four ways of removing cards from a FitsChan: - -\begin{enumerate} -c+ -\item You may delete cards yourself, one at a time, using astDelFits -(\secref{ss:findingandchangingfits}). -c- -f+ -\item You may delete cards yourself, one at a time, using AST\_DELFITS -(\secref{ss:findingandchangingfits}). -f- - -c+ -\item You may read an AST Object from the FitsChan (using astRead), -which will have the effect of removing those cards from the FitsChan -which describe the Object (\secref{ss:readingnativefits}). -c- -f+ -\item You may read an AST Object from the FitsChan (using AST\_READ), -which will have the effect of removing those cards from the FitsChan -which describe the Object (\secref{ss:readingnativefits}). -f- - -\item You may assign a value to the FitsChan's SinkFile attribute. When -the FitsChan is deleted, any remaining headers are written out to a text -file with path equal to the value of the SinkFile attribute. - -c+ -\item Alternatively, you may specify a sink function which writes data to some -external store of FITS cards, just like the sink associated with a -basic Channel (\secref{ss:channelsink}). If you supply a sink function, -it will be called when the FitsChan is deleted in order to write out -any FITS cards that remain in it (\secref{ss:fitssourceandsink}). Note, -the sink function is not called if the SinkFile attribute has been set. -c- -f+ -\item Alternatively, You may specify a sink routine which writes data to some -external store of FITS cards, just like the sink associated with a -basic Channel (\secref{ss:channelsink}). If you supply a sink routine, -it will be called when the FitsChan is deleted in order to write out -any FITS cards that remain in it (\secref{ss:fitssourceandsink}). Note, -the sink routine is not called if the SinkFile attribute has been set. -f- -\end{enumerate} - -Note, in particular, that reading an AST Object from a FitsChan is -\emph{destructive}. That is, it deletes the FITS cards that describe the -Object. The reason for this is explained in -\secref{ss:destructiveread}. - -c+ -In addition to the above, you may also read individual cards from a -FitsChan using the function astFindFits (which is not -destructive). This is the main means of writing out FITS cards if you -have not supplied a sink function. astFindFits also provides a means -of searching for particular FITS cards (by keyword, for example) and -there are other facilities for overwriting cards when required -(\secref{ss:findingandchangingfits}). -c- -f+ -In addition to the above, you may also read individual cards from a -FitsChan using the function AST\_FINDFITS (which is not -destructive). This is the main means of writing out FITS cards if you -have not supplied a sink routine. AST\_FINDFITS also provides a means -of searching for particular FITS cards (by keyword, for example) and -there are other facilities for overwriting cards when required -(\secref{ss:findingandchangingfits}). -f- - -\subsection{\label{ss:creatingafitschan}Creating a FitsChan} - -c+ -The FitsChan constructor function, astFitsChan, is straightforward to -use: -c- -f+ -The FitsChan constructor function, AST\_FITSCHAN, is straightforward -to use: -f- - -c+ -\small -\begin{terminalv} -#include "ast.h" -AstFitsChan *fitschan; - -... - -fitschan = astFitsChan( NULL, NULL, "Encoding=NATIVE" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER FITSCHAN, STATUS - - STATUS = 0 - - ... - - FITSCHAN = AST_FITSCHAN( AST_NULL, AST_NULL, 'Encoding=NATIVE', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, we have omitted any source or sink functions by supplying NULL -pointers for the first two arguments. -c- -f+ -Here, we have omitted any source or sink functions by supplying the -AST\_NULL routine for the first two arguments (remember to include the -AST\_PAR include file which contains the required EXTERNAL statement -for this routine). -f- -We have also initialised the FitsChan's Encoding attribute to -NATIVE. This indicates that we will be using the native encoding -(\secref{ss:nativeencoding}) to store and retrieve Objects. If this -was left unspecified, the default would depend on the FitsChan's -contents. An attempt is made to use whatever encoding appears to have -been used previously. For an empty FitsChan, the default is NATIVE, -but it does no harm to be sure. - -\subsection{\label{ss:addressingfitscards}Addressing Cards in a FitsChan} - -Because a FitsChan contains an ordered sequence of header cards, a -mechanism is needed for addressing them. This allows you to specify -where new cards are to be added, for example, or which card is to be -deleted. - -This role is filled by the FitsChan's integer Card attribute, which -gives the index of the \emph{current card} in the FitsChan. You can -nominate any card you like to be current, simply by setting a new -value for the Card attribute, for example: - -c+ -\small -\begin{terminalv} -int icard; - -... - -astSetI( fitschan, "Card", icard ) -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER ICARD - - ... - - CALL AST_SETI( FITSCHAN, 'Card', ICARD, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -where ``icard'' contains the index of the card on which you wish to -operate next. Some functions will update the Card attribute as a -means of advancing through the sequence of cards, when reading them -for example, or to indicate which card matches a search criterion. -c- -f+ -where ICARD contains the index of the card on which you wish to -operate next. Some functions will update the Card attribute as a -means of advancing through the sequence of cards, when reading them -for example, or to indicate which card matches a search criterion. -f- - -The default value for Card is one, which is the index of the first -card. This means that you can ``rewind'' a FitsChan to access its -first card by clearing the Card attribute: - -c+ -\small -\begin{terminalv} -astClear( fitschan, "Card" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_CLEAR( FITSCHAN, 'Card', STATUS ) -\end{terminalv} -\normalsize -f- - -The total number of cards in a FitsChan is given by the integer Ncard -attribute. This is a read-only attribute whose value is automatically -updated as you add or remove cards. It means you can address all the -cards in sequence using a loop such as the following: - -c+ -\small -\begin{terminalv} -int ncard; - -... - -ncard = astGetI( fitschan, "Ncard" ); -for ( icard = 1; icard <= ncard; icard++ ) { - astSetI( fitschan, "Card", icard ); - <access the current card> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DO 1 ICARD = 1, AST_GETI( FITSCHAN, 'Ncard', STATUS ) - CALL AST_SETI( FITSCHAN, 'Card', ICARD, STATUS ) - <access the current card> - 1 CONTINUE -\end{terminalv} -\normalsize -f- - -c+ -However, it is usually possible to write slightly tidier loops based -on the astFindFits function described later -(\secref{ss:extractingfitscards} and -\secref{ss:findingandchangingfits}). -c- -f+ -However, it is usually possible to write slightly tidier loops based -on the AST\_FINDFITS function described later -(\secref{ss:extractingfitscards} and -\secref{ss:findingandchangingfits}). -f- - -If you set the Card attribute to a value larger than Ncard, the -FitsChan is regarded as being positioned at its \emph{end-of-file}. In -this case there is no current card and an attempt to obtain a value -for the Card attribute will always return the value Ncard~$+$~1. When -a FitsChan is empty, it is always at the end-of-file. - -\subsection{\label{ss:writingnativefits}Writing Native Objects to a FitsChan} - -c+ -Having created an empty FitsChan (\secref{ss:creatingafitschan}), you -can write any AST Object to it in the native encoding using the -astWrite function. Let us assume we are writing a -SkyFrame,\footnote{More probably, you would want to write a FrameSet, -but for purposes of illustration a SkyFrame contains a more manageable -amount of data.} as follows: -c- -f+ -Having created an empty FitsChan (\secref{ss:creatingafitschan}), you -can write any AST Object to it in the native encoding using the -AST\_WRITE function. Let us assume we are writing a -SkyFrame,\footnote{More probably, you would want to write a FrameSet, -but for purposes of illustration a SkyFrame contains a more manageable -amount of data.} as follows: -f- - -c+ -\small -\begin{terminalv} -AstSkyFrame *skyframe; -int nobj; - -... - -nobj = astWrite( fitschan, skyframe ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER NOBJ, SKYFRAME - - ... - - NOBJ = AST_WRITE( FITSCHAN, SKYFRAME, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Since we have selected the native encoding -(\secref{ss:nativeencoding}), there are no restrictions on the class -of Object we may write, so astWrite should always return a value of -one, unless an error occurs. Unlike a basic Channel -(\secref{ss:writingtoachannel}), this write operation will not produce -any output from our program. The FITS headers produced are simply -stored inside the FitsChan. -c- -f+ -Since we have selected the native encoding -(\secref{ss:nativeencoding}), there are no restrictions on the class -of Object we may write, so AST\_WRITE should always return a value of -one, unless an error occurs. Unlike a basic Channel -(\secref{ss:writingtoachannel}), this write operation will not produce -any output from our program. The FITS headers produced are simply -stored inside the FitsChan. -f- - -After this write operation, the Ncard attribute will be updated to -reflect the number of new cards added to the FitsChan and the Card -attribute will point at the card immediately after the last one -written. Since our FitsChan was initially empty, the Card attribute -will, in this example, point at the end-of-file -(\secref{ss:addressingfitscards}). - -The FITS standard imposes a limit of 68 characters on the length of -strings which may be stored in a single header card. Sometimes, a -description of an AST Object involves the use of strings which exceed -this limit (\emph{e.g.}\ a Frame title can be of arbitrary length). If -this occurs, the long string will be split over two or more header cards. -Each ``continuation'' card will have the keyword \texttt{CONTINUE} in -columns 1 to 8, and will contain a space in column 9 (instead of the -usual equals sign). An ampersand (``\texttt{\&}'') is appended to the end of -each of the strings (except the last one) to indicate that the string is -continued on the next card. - -c+ -Note, this splitting of long strings over several cards only occurs when -writing AST Objects to a FitsChan using the astWrite function and the -\emph{native} encoding. If a long string is stored in a FitsChan using -(for instance) the astPutFits or astPutCards function, it will simply be truncated. -c- - -f+ -Note, this splitting of long strings over several cards only occurs when -writing AST Objects to a FitsChan using the AST\_WRITE routine and the -\emph{native} encoding. If a long string is stored in a FitsChan using -(for instance) the AST\_PUTFITS or AST\_PUTCARDS routine, it will simply be truncated. -f- - -\subsection{\label{ss:extractingfitscards}Extracting Individual Cards from a FitsChan} - -c+ -To examine the contents of the FitsChan after writing the SkyFrame -above (\secref{ss:writingnativefits}), we must write a simple loop to -extract each card in turn and print it out. We must also remember to -rewind the FitsChan first, \emph{e.g.}\ using astClear. The following -loop would do: -c- -f+ -To examine the contents of the FitsChan after writing the SkyFrame -above (\secref{ss:writingnativefits}), we must write a simple loop to -extract each card in turn and print it out. We must also remember to -rewind the FitsChan first, \emph{e.g.}\ using AST\_CLEAR. The -following loop would do: -f- - -c+ -\small -\begin{terminalv} -#include <stdio.h> -char card[ 81 ]; - -... - -astClear( fitschan, "Card" ); -while ( astFindFits( fitschan, "%f", card, 1 ) ) (void) printf( "%s\n", card ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 80 ) CARD - - ... - - CALL AST_CLEAR( FITSCHAN, 'Card', STATUS ) - - 2 CONTINUE - IF ( AST_FINDFITS( FITSCHAN, '%f', CARD, .TRUE., STATUS ) ) THEN - WRITE ( *, '(A)' ) CARD - GO TO 2 - END IF -\end{terminalv} -\normalsize -f- - -c+ -Here, we have used the astFindFits function to find a FITS card by -keyword. It is given a keyword template of ``\%f'', which matches any -FITS keyword, so it always finds the current card, which it -returns. Its fourth argument is set to 1, to indicate that the Card -attribute should be incremented afterwards so that the following card -will be found the next time around the loop. astFindFits returns zero -when it reaches the end-of-file and this terminates the loop. -c- -f+ -Here, we have used the AST\_FINDFITS function to find a FITS card by -keyword. It is given a keyword template of ``\%f'', which matches any -FITS keyword, so it always finds the current card, which it -returns. Its fourth argument is set to .TRUE., to indicate that the -Card attribute should be incremented afterwards so that the following -card will be found the next time around the loop. AST\_FINDFITS -returns .FALSE.\ when it reaches the end-of-file and this terminates -the loop. -f- - -c+ -If we were storing the FITS headers in an output FITS file instead of -printing them out, we might use a loop like this but replace -``printf'' with a suitable data storage operation. This would only be -necessary if we had not provided a sink function for the FitsChan -(\secref{ss:fitssourceandsink}). -c- -f+ -If we were storing the FITS headers in an output FITS file instead of -printing them out, we might use a loop like this but replace the WRITE -statement with a call to a suitable data access routine to store the -header card. This would only be necessary if we had not provided a -sink routine for the FitsChan (\secref{ss:fitssourceandsink}). -f- - -\subsection{The Native FitsChan Output Format} - -If we print out the FITS header cards describing the SkyFrame we wrote -earlier (\secref{ss:writingnativefits}), we should obtain something -like the following: - -\small -\begin{terminalv} -COMMENT AST ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AST -COMMENT AST Beginning of AST data for SkyFrame object AST -COMMENT AST ................................................................ AST -BEGAST_A= 'SkyFrame' / Description of celestial coordinate system -NAXES_A = 2 / Number of coordinate axes -AX1_A = ' ' / Axis number 1 -BEGAST_B= 'SkyAxis ' / Celestial coordinate axis -ENDAST_A= 'SkyAxis ' / End of object definition -AX2_A = ' ' / Axis number 2 -BEGAST_C= 'SkyAxis ' / Celestial coordinate axis -ENDAST_B= 'SkyAxis ' / End of object definition -ISA_A = 'Frame ' / Coordinate system description -SYSTEM_A= 'FK4-NO-E' / Celestial coordinate system type -EPOCH_A = 1958.0 / Besselian epoch of observation -ENDAST_C= 'SkyFrame' / End of object definition -COMMENT AST ................................................................ AST -COMMENT AST End of AST data for SkyFrame object AST -COMMENT AST ---------------------------------------------------------------- AST -\end{terminalv} -\normalsize - -As you can see, this resembles the information that would be written -to a basic Channel to describe the same SkyFrame -(\secref{ss:textualoutputformat}), except that it has been formatted -into 80-character header cards according to FITS conventions. - -There are also a number of other differences worth noting: - -\begin{enumerate} -\item There is no unnecessary information about default values -provided for the benefit of the human reader. This is because the Full -attribute for a FitsChan defaults to $-$1, thus suppressing this -information (\emph{c.f.}~\secref{ss:controllingchanneloutput}). You -can restore the information if you wish by setting Full to 0 or $+$1, -in which case additional COMMENT cards will be generated to hold it. - -\item The information is not indented, because FITS does not allow -this. However, if you change the Full attribute to 0 or $+$1, comments -will be included that are intended to help break up the sequence of -headers and highlight its structure. This will probably only be of use -if you are attempting to track down a problem by examining the FITS -cards produced in detail. - -\item The FITS keywords which appear to the left of the ``$=$'' signs -have additional characters (``\_A'', ``\_B'', \emph{etc.}) appended to -them. This is done in order to make each keyword unique. -\end{enumerate} - -c+ -This last point is worth further comment and is necessary because the -FITS standard only allows for certain keywords (such as COMMENT and -HISTORY) to appear more than once. astWrite therefore appends an -arbitrary sequence of two characters to each new keyword it generates -in order to ensure that it does not duplicate any already present in -the FitsChan. -c- -f+ -This last point is worth further comment and is necessary because the -FITS standard only allows for certain keywords (such as COMMENT and -HISTORY) to appear more than once. AST\_WRITE therefore appends an -arbitrary sequence of two characters to each new keyword it generates -in order to ensure that it does not duplicate any already present in -the FitsChan. -f- - -c+ -The main risk from not following this convention is that some software -might ignore (say) all but the last occurrence of a keyword before -passing the FITS headers on. Such an event is unlikely, but would -obviously destroy the information present, so astWrite enforces the -uniqueness of the keywords it uses. The extra characters added are -ignored when the information is read back. -c- -f+ -The main risk from not following this convention is that some software -might ignore (say) all but the last occurrence of a keyword before -passing the FITS headers on. Such an event is unlikely, but would -obviously destroy the information present, so AST\_WRITE enforces the -uniqueness of the keywords it uses. The extra characters added are -ignored when the information is read back. -f- - -As with a basic Channel, you can also suppress the comments produced -in a FitsChan by setting the boolean (integer) Comment attribute to -zero (\secref{ss:channelcommenting}). However, FITS headers are -traditionally generously commented, so this is not recommended. - -\subsection{\label{ss:addingfitscards}Adding Individual Cards to a FitsChan} - -c+ -To insert individual cards into a FitsChan, prior to reading them back -as Objects for example, you should use the astPutFits function. You -can insert a card in front of the current one as follows: -c- -f+ -To insert individual cards into a FitsChan, prior to reading them back -as Objects for example, you should use the AST\_PUTFITS routine. You -can insert a card in front of the current one as follows: -f- - -c+ -\small -\begin{terminalv} -astPutFits( fitschan, card, 0 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_PUTFITS( FITSCHAN, CARD, .FALSE., STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -where the third argument of zero indicates that the current card -should not be overwritten. Note that facilities are not provided by -AST for formatting the card contents. -c- -f+ -where the third argument of .FALSE.\ indicates that the current card -should not be overwritten. Note that facilities are not provided by -AST for formatting the card contents. -f- - -c+ -After inserting a card, the FitsChan's Card attribute points at the -original Card, or at the end-of-file if the FitsChan was originally -empty. Entering a sequence of cards is therefore straightforward. If -``cards'' is an array of pointers to strings containing FITS header -cards and ``ncards'' is the number of cards, then a loop such as the -following will insert the cards in sequence into a FitsChan: -c- -f+ -After inserting a card, the FitsChan's Card attribute points at the -original Card, or at the end-of-file if the FitsChan was originally -empty. Entering a sequence of cards is therefore straightforward. If -CARDS is an array of character strings containing FITS header cards -and NCARDS is the number of cards, then a loop such as the following -will insert the cards in sequence into a FitsChan: -f- - -c+ -\small -\begin{terminalv} -#define MAXCARD 100 -char *cards[ MAXCARD ]; -int ncard; - -... - -for ( icard = 0; icard < ncard; icard++ ) astPutFits( fitschan, cards[ icard ], 0 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER NCARD - CHARACTER * ( 80 ) CARDS( NCARD ) - - ... - - DO 3 ICARD = 1, NCARD - CALL AST_PUTFITS( FITSCHAN, CARDS( ICARD ), .FALSE., STATUS ) - 3 CONTINUE -\end{terminalv} -\normalsize -f- - -c+ -The string containing a card need not be null terminated if it is at -least 80 characters long (we have not allocated space for the strings -themselves in this brief example). -c- - -c+ -Note that astPutFits enforces the validity of a FitsChan by rejecting -any cards which do not adhere to the FITS standard. If any such cards -are detected, an error will result. -c- -f+ -Note that AST\_PUTFITS enforces the validity of a FitsChan by -rejecting any cards which do not adhere to the FITS standard. If any -such cards are detected, an error will result. -f- - -\subsection{\label{ss:addingmulticards}Adding Concatenated Cards to a FitsChan} - -If you have all your cards concatenated together into a single long string, -each occupying 80 characters (with no delimiters), you can insert them -into a FitsChan in a single call using -c+ -astPutCards. -c- -f+ -AST\_PUTCARDS. -f- -This call first empties the supplied FitsChan of any existing cards, then -inserts the new cards, and finally rewinds the FitsChan so that a -subsequent call to -c+ -astRead -c- -f+ -AST\_READ -f- -will start reading from the first supplied card. The -c+ -astPutCards function uses astPutFits -c- -f+ -AST\_PUTCARDS routine uses AST\_PUTFITS -f- -internally to interpret and store each individual card, and so the -caveats in \secref{ss:addingfitscards} should be read. - -c+ -For instance, if you are using the CFITSIO library for access to FITS -files, you can use the CFITSIO fits\_hdr2str function to obtain a string suitable -for passing to astPutCards: - -\small -\begin{terminalv} - - -if( !fits_hdr2str( fptr, 0, NULL, 0, &header, &nkeys, &status ) ) - fitschan = astFitsChan( NULL, NULL, "" ); - astPutCards( fitschan, header ); - header = free( header ); - wcsinfo = astRead( fitschan ); - - ... -} -\end{terminalv} -\normalsize - - -c- - -\subsection{\label{ss:readingnativefits}Reading Native Objects From a FitsChan} - -c+ -Once you have stored a FITS header description of an Object in a -FitsChan using the native encoding (\secref{ss:writingnativefits}), -you can read it back using astRead in much the same way as with a -basic Channel (\secref{ss:readingfromachannel}). Similar comments -about validating the Object you read also apply -(\secref{ss:validatinginput}). If you have just written to the -FitsChan, you must remember to rewind it first: -c- -f+ -Once you have stored a FITS header description of an Object in a -FitsChan using the native encoding (\secref{ss:writingnativefits}), -you can read it back using AST\_READ in much the same way as with a -basic Channel (\secref{ss:readingfromachannel}). Similar comments -about validating the Object you read also apply -(\secref{ss:validatinginput}). If you have just written to the -FitsChan, you must remember to rewind it first: -f- - -c+ -\small -\begin{terminalv} -AstObject *object; - -... - -astClear( fitschan, "Card" ); -object = astRead( fitschan ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER OBJECT - - ... - - CALL AST_CLEAR( FITSCHAN, 'Card', STATUS ) - OBJECT = AST_READ( FITSCHAN, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -An important feature of a FitsChan is that read operations are -destructive. This means that if an Object description is found, it -will be consumed by astRead which will remove all the cards involved, -including associated COMMENT cards, from the FitsChan. Thus, if you -write an Object to a FitsChan, rewind, and read the same Object back, -you should end up with the original FitsChan contents. If you need to -circumvent this behaviour for any reason, it is a simple matter to -make a copy of a FitsChan using astCopy -(\secref{ss:copyingobjects}). If you then read from the copy, the -original FitsChan will remain untouched. -c- -f+ -An important feature of a FitsChan is that read operations are -destructive. This means that if an Object description is found, it -will be consumed by AST\_READ which will remove all the cards -involved, including associated COMMENT cards, from the FitsChan. Thus, -if you write an Object to a FitsChan, rewind, and read the same Object -back, you should end up with the original FitsChan contents. If you -need to circumvent this behaviour for any reason, it is a simple -matter to make a copy of a FitsChan using AST\_COPY -(\secref{ss:copyingobjects}). If you then read from the copy, the -original FitsChan will remain untouched. -f- - -After a read completes, the FitsChan's Card attribute identifies the -card immediately following the last card read, or the end-of-file of -there are no more cards. - -c+ -Since the \emph{native} encoding is being used, any long strings involved -in the object description will have been split into two or more adjacent -contuation cards when the Object was stored in the header using function -astWrite. The astRead function reverses this process by concatenating any -such adjacent continuation cards to re-create the original long string. -c- - -f+ -Since the \emph{native} encoding is being used, any long strings involved -in the object description will have been split into two or more adjacent -contuation cards when the Object was stored in the header using routine -AST\_WRITE. The AST\_READ routine reverses this process by concatenating -any such adjacent continuation cards to re-create the original long -string. -f- - -\subsection{Saving and Restoring Multiple Objects in a FitsChan} - -When using the native FITS encoding, multiple Objects may be stored -and all I/O operations are sequential. This means that you can simply -write a sequence of Objects to a FitsChan. After each write operation, -the Card attribute will be updated so that the next write appends the -next Object description to the previous one. - -If you then rewind the FitsChan, you can read the Objects back in the -original order. Reading them back will, of course, remove their -descriptions from the FitsChan (\secref{ss:readingnativefits}) but the -behaviour of the Card attribute is such that successive reads will -simply return each Object in sequence. - -The only thing that may require care, given that a FitsChan can always -be addressed randomly by setting its Card attribute, is to avoid -writing one Object on top of another. For obvious reasons, the Object -descriptions in a FitsChan must remain separate if they are to make -sense when read back. - -\subsection{Mixing Native Objects with Other FITS Cards} - -Of course, any real FITS header will contain other information besides -AST Objects, if only the mandatory FITS cards that must accompany all -FITS data. When FITS headers are read in from a real dataset, -therefore, any native AST Object descriptions will be inter-mixed with -many other cards. - -Because this is the normal state of affairs, the boolean (integer) -Skip attribute for a FitsChan defaults to one. This means that when -you read an Object From a FitsChan, any irrelevant cards will simply -be skipped over until the start of the next Object description, if -any, is found. If you start reading part way through an Object -description, no error will result. The remainder of the description -will simply be skipped. - -Setting Skip to zero will change this behaviour to resemble that of a -basic Channel (\secref{ss:mixingchanneltext}), where extraneous data -are not permitted by default, but this will probably rarely be useful. - -\subsection{\label{ss:findingandchangingfits}Finding and Changing Cards in a FitsChan} - -c+ -You can search for, and retrieve, particular cards in a FitsChan by -keyword, using the function astFindFits. This performs a search, -starting at the current card, until it finds a card whose keyword -matches the template you supply, or the end-of-file is reached. -c- -f+ -You can search for, and retrieve, particular cards in a FitsChan by -keyword, using the function AST\_FINDFITS. This performs a search, -starting at the current card, until it finds a card whose keyword -matches the template you supply, or the end-of-file is reached. -f- - -c+ -If a suitable card is found, astFindFits optionally returns the card's -contents and then sets the FitsChan's Card attribute either to -identify the card found, or the one following it. The way you want the -Card attribute to be set is indicated by the final boolean (int) -argument to astFindFits. A value of one is returned to indicate -success. If a suitable card cannot be found, astFindFits returns a -value of zero to indicate failure and sets the FitsChan's Card -attribute to the end-of-file. -c- -f+ -If a suitable card is found, AST\_FINDFITS returns the card's contents -and then sets the FitsChan's Card attribute either to identify the -card found, or the one following it. The way you want the Card -attribute to be set is indicated by the fourth (logical) argument to -AST\_FINDFITS. A value of .TRUE.\ is returned to indicate success. If -a suitable card cannot be found, AST\_FINDFITS returns a value of -.FALSE.\ to indicate failure and sets the FitsChan's Card attribute to -the end-of-file. -f- - -c+ -Requesting that the Card attribute be set to indicate the card that -astFindFits finds is useful if you want to replace that card with a -new one, as in this example: -c- -f+ -Requesting that the Card attribute be set to indicate the card that -AST\_FINDFITS finds is useful if you want to replace that card with a -new one, as in this example: -f- - -c+ -\small -\begin{terminalv} -char newcard[ 81 ]; - -... - -(void) astFindFits( fitschan, "AIRMASS", NULL, 0 ); -astPutFits( fitschan, newcard, 1 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 80 ) NEWCARD - LOGICAL JUNK - - ... - - JUNK = AST_FINDFITS( FITSCHAN, 'AIRMASS', CARD, .FALSE., STATUS ) - CALL AST_PUTFITS( FITSCHAN, NEWCARD, .TRUE., STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, astFindFits is used to search for a card with the keyword -AIRMASS, with a NULL pointer being given to indicate that we do not -want the card's contents returned. If the card is found, astPutFits -then overwrites it with a new card. Otherwise, the Card attribute -ends up pointing at the end-of-file and the new card is simply -appended to the end of the FitsChan. -c- -f+ -Here, AST\_FINDFITS is used to search for a card with the keyword -AIRMASS. If the card is found, AST\_PUTFITS then overwrites it with a -new card. Otherwise, the Card attribute ends up pointing at the -end-of-file and the new card is simply appended to the end of the -FitsChan. -f- - -c+ -A similar approach can be used to delete selected cards from a -FitsChan using astDelFits, which deletes the current card: -c- -f+ -A similar approach can be used to delete selected cards from a -FitsChan using AST\_DELFITS, which deletes the current card: -f- - -c+ -\small -\begin{terminalv} -if ( astFindFits( fitschan, "BSCALE", NULL, 0 ) ) astDelFits( fitschan ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - IF ( AST_FINDFITS( FITSCHAN, 'BSCALE', CARD, .FALSE., STATUS ) ) THEN - CALL AST_DELFITS( FITSCHAN, STATUS ) - END IF -\end{terminalv} -\normalsize -f- - -This deletes the first card, if any, with the BSCALE keyword. - -c+ -Requesting that astFindFits increments the Card attribute to identify -the card following the one found is more useful when writing loops. -For example, the following loop extracts each card whose keyword -matches the template ``CD\%6d'' (that is, ``CD'' followed by six -decimal digits): -c- -f+ -Requesting that AST\_FINDFITS increments the Card attribute to -identify the card following the one found is more useful when writing -loops. For example, the following loop extracts each card whose -keyword matches the template ``CD\%6d'' (that is, ``CD'' followed by -six decimal digits): -f- - -c+ -\small -\begin{terminalv} -while ( astFindFits( fitschan, "CD%6d", card, 1 ) { - <process the card's contents> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - 4 CONTINUE - IF ( AST_FINDFITS( FITSCHAN, 'CD%6d', CARD, .TRUE., STATUS ) ) THEN - <process the card's contents> - GO TO 4 - END IF -\end{terminalv} -\normalsize -f- - -c+ -For further details of keyword templates, see the description of -astFindFits in \appref{ss:functiondescriptions}. -c- -f+ -For further details of keyword templates, see the description of -AST\_FINDFITS in \appref{ss:functiondescriptions}. -f- - -c+ -\subsection{\label{ss:fitssourceandsink}Source and Sink Functions for FitsChans} -c- -f+ -\subsection{\label{ss:fitssourceandsink}Source and Sink Routines for FitsChans} -f- - -c+ -The use of source and sink functions with a FitsChan is optional. This -is because you can always arrange to explicitly fill a FitsChan with -FITS cards (\secref{ss:addingfitscards} and \secref{ss:addingmulticards}) -and you can also extract any -cards that remain and write them out yourself -(\secref{ss:extractingfitscards}) before you delete the FitsChan. -c- -f+ -The use of source and sink routines with a FitsChan is optional. This -is because you can always arrange to explicitly fill a FitsChan with -FITS cards (\secref{ss:addingfitscards} and \secref{ss:addingmulticards}) -and you can also extract any -cards that remain and write them out yourself -(\secref{ss:extractingfitscards}) before you delete the FitsChan. -f- - -c+ -If you choose to use these functions, however, they behave in a very -similar manner to those used by a Channel (\secref{ss:channelsource} -and \secref{ss:channelsink}). You supply pointers to these functions, -as arguments to the constructor function astFitsChan when you create -the FitsChan (\secref{ss:creatingafitschan}). The source function is -invoked implicitly at this point to fill the FitsChan with FITS cards -and the FitsChan is then rewound, so that the first card becomes -current. The sink function is automatically invoked later, when the -FitsChan is deleted, in order to write out any cards that remain in -it. -c- -f+ -If you choose to use these routines, however, they behave in a very -similar manner to those used by a Channel (\secref{ss:channelsource} -and \secref{ss:channelsink}). You supply these routines, as arguments -to the constructor function AST\_FITSCHAN when you create the FitsChan -(\secref{ss:creatingafitschan}). The source routine is invoked -implicitly at this point to fill the FitsChan with FITS cards and the -FitsChan is then rewound, so that the first card becomes current. The -sink routine is automatically invoked later, when the FitsChan is -deleted, in order to write out any cards that remain in it. -f- - -c+ -The only real difference between the source and sink functions for a -FitsChan and a basic Channel is that FITS cards are limited in length -to 80~characters, so the choice of buffer size is simplified. The -``Source'' and ``Sink'' functions in \secref{ss:channelsource} and -\secref{ss:channelsink} could therefore be used to access FITS headers -stored in text files simply by changing LEN to be 80. If you were not -accessing a text file, however, appropriate changes to the I/O -statements would be needed since the separating newline characters -would be absent. The details obviously depend on the format of the -file you are handling, which need not necessarily be a true FITS file. -c- - -f+ -The only real difference between the source and sink routines for a -FitsChan and a basic Channel is that FITS cards are limited in length -to 80~characters, so the choice of buffer size is simplified. This -affects the way the card contents are passed, so the routines -themselves are slightly different. The following is therefore the -FitsChan equivalent of the Channel SOURCE routine given in -\secref{ss:channelsource}: - -\small -\begin{terminalv} - INTEGER FUNCTION FITSSOURCE( CARD, STATUS ) - CHARACTER * ( 80 ) CARD - INTEGER STATUS - - READ( 1, '(A)', END = 99 ) CARD - FITSSOURCE = 1 - RETURN - - 99 FITSSOURCE = 0 - END -\end{terminalv} -\normalsize - -Here, the FITS card contents are returned \emph{via} the CARD argument -(the AST\_PUTLINE routine should not be used) and the function returns -1 to indicate that a card has been read. A value of zero is returned -if there are no more cards to read. - -The sink routine for a FitsChan is also a little different -(\emph{c.f.}\ the SINK routine in~\secref{ss:channelsink}), as -follows: - -\small -\begin{terminalv} - SUBROUTINE FITSSINK( CARD, STATUS ) - CHARACTER * ( 80 ) CARD - INTEGER STATUS - - WRITE( 2, '(A)' ) CARD - - END -\end{terminalv} -\normalsize - -The contents of the FITS card being written are passed \emph{via}\ the -CARD argument (the AST\_GETLINE routine should not be used). - -Of course, both of these examples assume that you are accessing text -files. If this is not the case, then appropriate changes to the I/O -statements would be needed. The details obviously depend on the -format of the file you are handling, which need not necessarily be a -true FITS file. -f- - -\cleardoublepage -\section{\label{ss:foreignfits}Using Foreign FITS Encodings} - -We saw in the previous section (\secref{ss:nativefits}) 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. - -\subsection{\label{ss:foreignencodings}The Foreign FITS Encodings} - -As mentioned previously (\secref{ss:nativeencoding}), there are a -number of conventions currently in use for storing WCS information in -FITS headers, which we call \emph{encodings}. Here, we are concerned -with those encodings defined by software systems other than AST, which -we term \emph{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: - -\begin{quote} -\begin{description} -\item[DSS]\mbox{}\\ -This encoding stores WCS information using the convention developed at -the Space Telescope Science Institute for the Digitised Sky Survey -(DSS) astrometric plate calibrations. DSS images which use this -convention are widely available and it is understood by a number of -important and well-established astronomy applications. - -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. - -\item[FITS-WCS]\mbox{}\\ -This encoding is very important because it is based on a new FITS standard -which should, for the first time, address the problem of celestial coordinate -systems in a proper manner, by considerably extending the original FITS -standard. - -The conventions used are described in a series of papers by -E.W.\,Greisen, M.\,Calabretta, \emph{et. al.}, often referred to as the -``FITS-WCS papers''. They are described at -\url{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 \appref{ss:fitswcscoverage}. - -\item[FITS-IRAF]\mbox{}\\ -This encoding is based on the conventions described in the document -``World Coordinate Systems Representations Within the FITS Format'' by R.J. -Hanisch and D.G. Wells, 1988.\footnote{Available by ftp from -fits.cv.nrao.edu /fits/documents/wcs/wcs88.ps.Z} It is employed -by the IRAF data analysis facility, so its use will facilitate data -exchange with IRAF. This encoding is in effect a sub-set of the current -FITS-WCS encoding. - -\item[FITS-PC]\mbox{}\\ -This encoding is based on a previous version of the proposed new FITS WCS -standard which used \texttt{PCjjjjiii} and \texttt{CDELTj} keywords 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 \texttt{CDi\_j} -keywords instead.\footnote{There 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.} 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. - -\item[FITS-AIPS]\mbox{}\\ -This encoding is based on the conventions described in the document -``Non-linear Coordinate Systems in AIPS'' by Eric W. Greisen (revised 9th -September, 1994).\footnote{Available by ftp from fits.cv.nrao.edu -/fits/documents/wcs/aips27.ps.Z} It is currently employed by the AIPS -data analysis facility, so its use will facilitate data exchange with -AIPS. This encoding uses \texttt{CROTAi} and \texttt{CDELTi} keywords to -describe axis rotation and scaling. - -\item[FITS-AIPS++]\mbox{}\\ -Encodes coordinate system information in FITS -header cards using the conventions used by the AIPS++ project. -This is an extension of FITS-AIPS which includes some of the -features of FITS-PC and FITS-IRAF. -\end{description} -\end{quote} - -For more detail about the above encodings, see the description of the -Encoding attribute in \appref{ss:attributedescriptions}. - -\subsection{\label{ss:foreignfitslimitations}Limitations of Foreign Encodings} - -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 (\secref{ss:nativefits}). The main ones are: - -\begin{enumerate} -\item Only one class of AST Object, the FrameSet, may be represented -using a foreign FITS encoding. This should not come as a surprise, -because the purpose of storing WCS information in FITS headers is to -attach coordinate systems to an associated array of data. Since the -FrameSet is the AST Object designed for the same purpose -(\secref{ss:baseandcurrent}), there is a natural correspondence. - -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. - -\item You may store a representation of only a single FrameSet in any -individual set of FITS header cards (\emph{i.e.}\ in a single -FitsChan) at one time. If you attempt to store more than one, you may -over-write the previous one or generate an invalid representation of -your WCS information. - -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. - -\item In general, it will not be possible to store every possible -FrameSet that you might construct. Depending on the encoding, only -certain FrameSets that conform to particular restrictions can be -represented and, even then, some of their information may be lost. See -the description of the Encoding attribute in -\appref{ss:attributedescriptions} for more details of these -limitations. -\end{enumerate} - -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, \emph{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. - -\subsection{\label{ss:identifyingfitsencoding}Identifying Foreign Encodings on Input} - -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: - -\small -\begin{terminalv} -SIMPLE = T / Written by IDL: 30-Jul-1997 05:35:42.00 -BITPIX = -32 / Bits per pixel. -NAXIS = 2 / Number of dimensions -NAXIS1 = 300 / Length of x axis. -NAXIS2 = 300 / Length of y axis. -CTYPE1 = 'GLON-ZEA' / X-axis type -CTYPE2 = 'GLAT-ZEA' / Y-axis type -CRVAL1 = -149.56866 / Reference pixel value -CRVAL2 = -19.758201 / Reference pixel value -CRPIX1 = 150.500 / Reference pixel -CRPIX2 = 150.500 / Reference pixel -CDELT1 = -1.20000 / Degrees/pixel -CDELT2 = 1.20000 / Degrees/pixel -CROTA1 = 0.00000 / Rotation in degrees. -SURVEY = 'COBE DIRBE' -BUNITS = 'MJy/sr ' / -ORIGIN = 'CDAC ' / Cosmology Data Analysis Center -TELESCOP= 'COBE ' / COsmic Background Explorer satellite -INSTRUME= 'DIRBE ' / COBE instrument [DIRBE, DMR, FIRAS] -PIXRESOL= 9 / Quad tree pixel resolution [6, 9] -DATE = '27/09/94' / FITS file creation date (dd/mm/yy) -DATE-MAP= '16/09/94' / Date of original file creation (dd/mm/yy) -COMMENT COBE specific keywords -DATE-BEG= '08/12/89' / date of initial data represented (dd/mm/yy) -DATE-END= '25/09/90' / date of final data represented (dd/mm/yy) -\end{terminalv} -\normalsize - -c+ -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: -c- -f+ -The first step is to create a FitsChan and insert these cards into -it. If CARDS is an array of character strings holding the header cards -and NCARDS is the number of cards, this could be done as follows: -f- - -c+ -\small -\begin{terminalv} -#include "ast.h" -#define MAXCARD 100 -AstFitsChan *fitschan; -char *cards[ MAXCARD ]; -int icard, ncard; - -... - -fitschan = astFitsChan( NULL, NULL, "" ); -for ( icard = 0; icard < ncard; icard++ ) astPutFits( fitschan, cards[ icard ], 0 ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER FITSCHAN, ICARD, NCARD, STATUS - CHARACTER * ( 80 ) CARDS( NCARD ) - - STATUS = 0 - - ... - - FITSCHAN = AST_FITSCHAN( AST_NULL, AST_NULL, ' ', STATUS ) - DO 1 ICARD = 1, NCARD - CALL AST_PUTFITS( FITSCHAN, CARDS( ICARD ), .FALSE., STATUS ) - 1 CONTINUE -\end{terminalv} -\normalsize -f- - -Note that we have not initialised the Encoding attribute of the -FitsChan as we did in \secref{ss:creatingafitschan} 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 -\appref{ss:attributedescriptions}. - -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: - -c+ -\small -\begin{terminalv} -const char *encode; - -... - - -encode = astGetC( fitschan, "Encoding" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 20 ) ENCODE - - ... - - ENCODE = AST_GETC( FITSCHAN, 'Encoding', STATUS ) -\end{terminalv} -\normalsize -f- - -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: - -c+ -\small -\begin{terminalv} -fitschan = astFitsChan( NULL, NULL, "Encoding=FITS-AIPS" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - FITSCHAN = AST_FITSCHAN( AST_NULL, AST_NULL, 'Encoding=FITS-AIPS', STATUS ) -\end{terminalv} -\normalsize -f- - -If we tried to read information using this encoding -(\secref{ss:readingforeignfits}), 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. - -\subsection{\label{ss:readingforeignfits}Reading Foreign WCS Information from a FITS Header} - -c+ -Having stored a set of FITS header cards in a FitsChan and determined -how the WCS information is encoded -(\secref{ss:identifyingfitsencoding}), 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: -c- -f+ -Having stored a set of FITS header cards in a FitsChan and determined -how the WCS information is encoded -(\secref{ss:identifyingfitsencoding}), the next step is to read an AST -Object from the FitsChan using AST\_READ. We must also remember to -rewind the FitsChan first, if necessary, such as by clearing its Card -attribute, which defaults to 1: -f- - -c+ -\small -\begin{terminalv} -AstObject *wcsinfo; - -... - -astClear( fitschan, "Card" ); -wcsinfo = astRead( fitschan ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER WCSINFO - - ... - - CALL AST_CLEAR( FITSCHAN, 'Card', STATUS ) - WCSINFO = AST_READ( FITSCHAN, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -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 -(\secref{ss:identifyingfitsencoding}) was inappropriate. -c- -f+ -If the pointer returned by AST\_READ 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 -(\secref{ss:identifyingfitsencoding}) was inappropriate. -f- - -At this point you might like to indulge in a little data validation -along the lines described in \secref{ss:validatinginput}, for example: - -c+ -\small -\begin{terminalv} -if ( !strcmp( astGetC( wcsinfo, "Class" ), "FrameSet" ) ) { - <the Object is a FrameSet, so use it> -} else { - <something unexpected was read> -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - IF ( AST_GETC( WCSINFO, 'Class', STATUS ) .EQ. 'FrameSet' ) THEN - <the Object is a FrameSet, so use it> - ELSE - <something unexpected was read> - END IF -\end{terminalv} -\normalsize -f- - -If a foreign encoding has definitely been used, then the Object will -automatically be a FrameSet (\secref{ss:foreignfitslimitations}), so -this stage can be omitted. However, if the native encoding -(\secref{ss:nativeencoding}) 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. - -c+ -If you used astShow (\secref{ss:displayingobjects}) to examine the -FrameSet which results from reading our example FITS header -(\secref{ss:identifyingfitsencoding}), 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. -c- -f+ -If you used AST\_SHOW (\secref{ss:displayingobjects}) to examine the -FrameSet which results from reading our example FITS header -(\secref{ss:identifyingfitsencoding}), 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. -f- - -Because this FrameSet may be used both as a Mapping -(\secref{ss:framesetasmapping}) and as a Frame -(\secref{ss:framesetasframe}), it may be employed directly to perform -many useful operations without any need to decompose it into its -component parts. These include: - -\begin{itemize} -\item Transforming data grid (FITS pixel) coordinates into galactic -coordinates and \emph{vice versa} (\secref{ss:framesetasmapping}). - -\item Formatting coordinate values (either pixel or galactic -coordinates) ready for display to a user -(\secref{ss:formattingaxisvalues} and \secref{ss:normalising}). - -\item Enquiring about axis labels (or other axis -information---\secref{ss:frameattributes}) which might be used, for -example, to label columns of coordinates in a table -(\secref{ss:frameaxisattributes}). - -\item Aligning the image with another image from which a similar -FrameSet has been obtained (\secref{ss:registeringimages}). - -\item Creating a Plot (\secref{ss:plots}), which can be used to overlay -a variety of graphical information (including a coordinate -grid---Figure~\ref{fig:gridplot}) on the displayed image. - -\item Generating a new FrameSet which reflects any geometrical -processing you perform on the associated image data -(\secref{ss:wcsprocessingexample}). This new FrameSet could then be -written out as FITS headers to describe the modified image -(\secref{ss:writingforeignfits}). -\end{itemize} - -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. - -\subsection{\label{ss:destructiveread}Removing WCS Information from FITS Headers---the Destructive Read} - -It is instructive at this point to examine the contents of a FitsChan -after we have read a FrameSet from it -(\secref{ss:readingforeignfits}). The following would rewind our -FitsChan and display its contents: - -c+ -\small -\begin{terminalv} -#include <stdio.h> -char card[ 81 ]; - -... - -astClear( fitschan, "Card" ); -while ( astFindFits( fitschan, "%f", card, 1 ) ) (void) printf( "%s\n", card ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER CARD * ( 80 ) - - ... - - CALL AST_CLEAR( FITSCHAN, 'Card', STATUS ) - 2 CONTINUE - IF ( AST_FINDFITS( FITSCHAN, '%f', CARD, .TRUE., STATUS ) ) THEN - WRITE ( *, '(A)' ) CARD - GO TO 2 - END IF -\end{terminalv} -\normalsize -f- - -The output, if we started with the example FITS header in -\secref{ss:identifyingfitsencoding}, might look like this: - -\small -\begin{terminalv} -SIMPLE = T / Written by IDL: 30-Jul-1997 05:35:42.00 -BITPIX = -32 / Bits per pixel. -NAXIS = 2 / Number of dimensions -NAXIS1 = 300 / Length of x axis. -NAXIS2 = 300 / Length of y axis. -SURVEY = 'COBE DIRBE' -BUNITS = 'MJy/sr ' -ORIGIN = 'CDAC ' / Cosmology Data Analysis Center -TELESCOP= 'COBE ' / COsmic Background Explorer satellite -INSTRUME= 'DIRBE ' / COBE instrument [DIRBE, DMR, FIRAS] -PIXRESOL= 9 / Quad tree pixel resolution [6, 9] -DATE = '27/09/94' / FITS file creation date (dd/mm/yy) -DATE-MAP= '16/09/94' / Date of original file creation (dd/mm/yy) -COMMENT COBE specific keywords -DATE-BEG= '08/12/89' / date of initial data represented (dd/mm/yy) -DATE-END= '25/09/90' / date of final data represented (dd/mm/yy) -\end{terminalv} -\normalsize - -c+ -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 -(\secref{ss:writingforeignfits}) they will, as far as possible, go -back into their original locations. This helps to preserve the overall -layout of the FITS header. -c- -f+ -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 AST\_READ 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 -(\secref{ss:writingforeignfits}) they will, as far as possible, go -back into their original locations. This helps to preserve the -overall layout of the FITS header. -f- - -c+ -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. -c- -f+ -You can now see why AST\_READ 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. -f- - -Clearing this WCS information out of a FITS header is particularly -important when considering how to write new WCS information back after -processing (\secref{ss:writingforeignfits}). 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.\footnote{This 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.} The destructive read mechanism ensures that this doesn't -happen. - -\subsection{\label{ss:propagatingwcsinformation}Propagating WCS Information through Data Processing Steps} - -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: - -\begin{enumerate} -\item Read the image data and associated FITS header from the input -dataset, putting the header cards into a FitsChan -(\secref{ss:identifyingfitsencoding}). - -\item Read an AST Object, a FrameSet, from the FitsChan (typically -using a foreign FITS encoding---\secref{ss:readingforeignfits}). - -\item Process the image data and modify the FrameSet accordingly -(\emph{e.g.}~\secref{ss:wcsprocessingexample}). - -\item Write the FrameSet back into the FitsChan -(\secref{ss:writingforeignfits}). - -\item Perform any other modification of FITS header cards your program -may require. - -\item Write the FitsChan contents (\emph{i.e.}\ processed header -cards) and image data to the output dataset. -\end{enumerate} - -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 (\secref{ss:writingforeignfits}). - -\subsection{\label{ss:writingforeignfits}Writing Foreign WCS Information to a FITS Header} - -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 (\secref{ss:identifyingfitsencoding}), because the -destructive action of reading the WCS data -(\secref{ss:destructiveread}) 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. - -c+ -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 -(\secref{ss:identifyingfitsencoding}), 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: -c- -f+ -We will return to the question of the optimum choice of encoding -below. For now, let's assume 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 -(\secref{ss:identifyingfitsencoding}), 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). AST\_WRITE can then be used to write the output WCS -information into the FitsChan: -f- - -c+ -\small -\begin{terminalv} -int nobj; - -... - -astSet( fitschan, "Card=1, Encoding=%s", encode ); -nobj = astWrite( fitschan, wcsinfo ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER NOBJ - - ... - - - CALL AST_SET( FITSCHAN, 'Card=1, Encoding=' // ENCODE, STATUS ) - NOBJ = AST_WRITE( FITSCHAN, WCSINFO, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -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. -c- -f+ -The value returned by AST\_WRITE (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. -f- - -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.\footnote{Storing values in the FitsChan for -FITS headers NAXIS1, NAXIS2, \emph{etc.} (the grid dimensions in pixels), -before invoking -c+ -astWrite -c- -f+ -AST\_WRITE -f- -can sometimes help to produce a successful write.} 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: - -c+ -\small -\begin{terminalv} -/* 1. */ -astSet( fitschan, "Card=1, Encoding=FITS-IRAF" ); -if ( !astWrite( fitschan, wcsinfo ) ) { - -/* 2. */ - astSetC( fitschan, "Encoding", encode ); - if ( !astWrite( fitschan, wcsinfo ) ) { - -/* 3. */ - astSet( fitschan, "Encoding=NATIVE" ); - (void) astWrite( fitschan, wcsinfo ); - } -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} -* 1. - CALL AST_SET( FITSCHAN, 'Card=1, Encoding=FITS-WCS', STATUS ) - IF ( AST_WRITE( FITSCHAN, WCSINFO, STATUS ) .EQ. 0 ) THEN - -* 2. - CALL AST_SETC( FITSCHAN, 'Encoding', ENCODE, STATUS ) - IF ( AST_WRITE( FITSCHAN, WCSINFO, STATUS ) .EQ. 0 ) THEN - -* 3. - CALL AST_SET( FITSCHAN, 'Encoding=NATIVE', STATUS ) - NOBJ = AST_WRITE( FITSCHAN, WCSINFO, STATUS ) - END IF - END IF -\end{terminalv} -\normalsize -f- - -That is: - -\begin{enumerate} -\item Start by trying the FITS-WCS encoding, on the grounds that FITS -should provide a universal interchange standard in which all WCS -information should be expressed if possible. - -\item If that fails, then try the original encoding used for the input -WCS information, on the grounds that you are at least not making the -information any harder for others to read than it originally was. - -\item If that also fails, then you are probably trying to store fairly -complex information for which you need the native encoding. Only other -AST programs will then be able to read this information, but these are -probably the only programs that will be able to do anything sensible -with it anyway. -\end{enumerate} - -c+ -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 -encodings\footnote{In practice, this means you should avoid mixing -FITS-IRAF, FITS-WCS, FITS-AIPS, FITS-AIPS++ and FITS-PC encodings since they share -many keywords.}. Adopting this approach would simply require multiple -calls to astWrite, rewinding the FitsChan and changing its Encoding value -before each one. -c- -f+ -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 -encodings\footnote{In practice, this means you should avoid mixing -FITS-IRAF, FITS-WCS, FITS-AIPS, FITS-AIPS++ and FITS-PC encodings since they share -many keywords.}. Adopting this approach would simply require multiple -calls to AST\_WRITE, rewinding the FitsChan and changing its Encoding value -before each one. -f- - -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. - -\cleardoublepage -\section{\label{ss:xmlchan}Storing AST Objects as XML (XmlChan)} - -\htmladdnormallinkfoot{XML}{http://www.w3.org/XML/} -is fast becoming the standard format for passing structured data around -the internet, and much general purpose software has been written for -tasks such as the parsing, editing, display and transformation of XML -data. The XmlChan class (a specialised form of Channel) provides -facilities for storing AST objects externally in the form of XML documents, -thus allowing such software to be used. - -The primary XML format used by the XmlChan class is a fairly close -transliteration of the AST native format produced by the basic Channel -class. Currently, there is no DTD or schema defining the structure of data -produced in this format by an XmlChan. The following is a native AST -representation of a simple 1-D Frame (including comments and with the Full -attribute set to zero so that some default attribute values are included -as extra comments): - -\small -\begin{terminalv} - Begin Frame # Coordinate system description -# Title = "1-d coordinate system" # Title of coordinate system - Naxes = 1 # Number of coordinate axes - Domain = "SCREEN" # Coordinate system domain -# Lbl1 = "Axis 1" # Label for axis 1 -# Uni1 = "cm" # Units for axis 1 - Ax1 = # Axis number 1 - Begin Axis # Coordinate axis - Unit = "cm" # Axis units - End Axis - End Frame -\end{terminalv} -\normalsize - -The corresponding XmlChan output would look like: - -\small -\begin{terminalv} - <Frame xmlns="http://www.starlink.ac.uk/ast/xml/" - desc="Coordinate system description"> - <_attribute name="Title" quoted="true" value="1-d coordinate system" - desc="Title of coordinate system" default="true"/> - <_attribute name="Naxes" value="1" desc="Number of coordinate axes"/> - <_attribute name="Domain" quoted="true" value="SCREEN" - desc="Coordinate system domain"/> - <_attribute name="Lbl1" quoted="true" value="Axis 1" - desc="Label for axis 1" default="true"/> - <_attribute name="Uni1" quoted="true" value="cm" - desc="Units for axis 1" default="true"/> - <Axis label="Ax1" desc="Coordinate axis"> - <!--Axis number 1--> - <_attribute name="Unit" quoted="true" value="cm" desc="Axis units"/> - </Axis> - </Frame> -\end{terminalv} -\normalsize - - -Notes: - -\begin{enumerate} -\item The AST class name is used as the name for an XML element which contain -a description of an AST object. - -\item AST attributes are described by XML elements with the name -``\_attribute''. Unfortunately, the word ``attribute'' is also used by XML -to refer to a ``name=value'' pair within an element start tag. So for -instance, the ``Title'' attribute of the AST Frame object is described -within an XML element with name ``\_attribute'' in which the XML attribute -``name'' has the value ``Title'', and the XML attribute ``value'' has the -value ``1-d coordinate system''. The moral is always to be clear clear -about the context (AST or XML) in which the word \emph{attribute} is being -used! - -\item The XML includes comments both as XML attributes with the name ``desc'', -and as separate comment tags. - -\item Elements which describe default values are identified by the fact -that they have an XML attribute called ``default'' set to the value -``true''. These elements are ignored when being read back into an XmlChan. - -\item The outer-most XML element of an AST object will set the default -namespace to \verb+http://www.starlink.ac.uk/ast/xml/+ which will be -inherited by all nested elements. - -\end{enumerate} - - -The XmlChan class changes the default value for the Comment and Full -attributes (inherited from the base Channel class) to zero and -1, -resulting in terse output by default. With the default values for these -attributes, the above XML is reduced to the following: - -\small -\begin{terminalv} - <Frame xmlns="http://www.starlink.ac.uk/ast/xml/"> - <_attribute name="Naxes" value="1"/> - <_attribute name="Domain" quoted="true" value="SCREEN"/> - <Axis label="Ax1"> - <_attribute name="Unit" quoted="true" value="cm"/> - </Axis> - </Frame> -\end{terminalv} -\normalsize - - -The XmlChan class uses the Skip attributes very similarly to the Channel -class. If Skip is zero (the default) then an error will be reported if the text -supplied by the source function does not begin with an AST Object. If -Skip is non-zero, then initial text is skipped over without error until -the start of an AST object is found. this allows an AST object to be -located within a larger XML document. - -\subsection{Reading IVOA Space-Time-Coordinates XML (STC-X) Descriptions} -The XmlChan class also provides support for reading (but not writing) XML -documents which use a restricted subset of an early draft (V1.20) of the -IVOA Space-Time-Coordinates XML (STC-X) system. The version of STC-X -finally adopted by the IVOA differs in several significant respects from -V1.20, and so the STC-X support currently provided by AST is mainly of -historical interest. Note, AST also supports the alternative ``STC-S'' -linear string description of the STC model (see \secref{ss:stcschans}). - -STC-X V1.20 is documented at -\url{http://www.ivoa.net/Documents/WD/STC/STC-20050225.html}, and the current -version is documented at -\url{http://www.ivoa.net/Documents/latest/STC-X.html}. - -When an STC-X document is read using an XmlChan, the read operation -produces an AST Object of the Stc class, which is itself a subclass of -Region. Specifically, each such Object will be an instance of -StcSearchLocation, StcResourceProfile, StcCatalogEntryLocation or -StcObsDataLocation. See the description of the XmlChan class and the -XmlFormat attribute for further details. - -\cleardoublepage -\section{\label{ss:stcschans}Reading and writing STC-S descriptions (StcsChans)} - -The StcsChan class provides facilities for reading and writing -IVOA ``STC-S'' descriptions. STC-S (see -\url{http://www.ivoa.net/Documents/latest/STC-S.html}) is a linear string -syntax that allows simple specification of the STC metadata describing a -region in an astronomical coordinate system. AST supports a -subset of the STC-S specification, allowing an STC-S description of a -region within an AST-supported astronomical coordinate system to be converted -into an equivalent AST Region object, and vice-versa. For further -details, see the full description of the StcsChan class in -\appref{ss:classdescriptions}. - - -\cleardoublepage -\section{\label{ss:intramaps}Creating Your Own Private Mappings (IntraMaps)} - -\subsection{The Need for Extensibility} - -However many Mapping classes are provided by AST, sooner or later you -will want to transform coordinates in some way that has not been -foreseen. You might want to plot a graph in some novel curvilinear -coordinate system (perhaps you already have a WCS system in your -software and just want to use AST for its graphical capabilities). -Alternatively, you might need to calibrate a complex dataset (like an -objective prism plate) where each position must be converted to world -coordinates with reference to calibration data under the control of an -elaborate algorithm. - -In such cases, it is clear that the basic pre-formed components -provided by AST for building Mappings are just not enough. What you -need is access to a programming language. However, if you write your -own software to transform coordinate values, then it must be made -available in the form of an AST class (from which you can create -Objects) before it can be used in conjunction with other AST -facilities. - -At this point you might consider writing your own AST class, but this -is not recommended. Not only would the internal conventions used by -AST take some time to master, but you might also find yourself having -to change your software whenever a new version of AST was -released. Fortunately, there is a much easier route provided by the -IntraMap class. - -\subsection{The IntraMap Model} - -c+ -To allow you to write your own Mappings, AST provides a special kind -of Mapping called an IntraMap. An IntraMap is a sort of ``wrapper'' -for a coordinate transformation function written in C. You write this -function yourself and then register it with AST. This, in effect, -creates a new class from which you can create Mappings -(\emph{i.e.}\ IntraMaps) which will transform coordinates in whatever -way your transformation function specifies. -c- -f+ -To allow you to write your own Mappings, AST provides a special kind -of Mapping called an IntraMap. An IntraMap is a sort of ``wrapper'' -for a coordinate transformation routine written in Fortran. You write -this routine yourself and then register it with AST. This, in effect, -creates a new class from which you can create Mappings -(\emph{i.e.}\ IntraMaps) which will transform coordinates in whatever -way your transformation routine specifies. -f- - -Because IntraMaps are Mappings, they may be used in the same way as -any other Mapping. For instance, they may be combined in series or -parallel with other Mappings using a CmpMap (\secref{ss:cmpmaps}), -they may be inverted (\secref{ss:invertingmappings}), you may enquire -about their attributes (\secref{ss:gettingattributes}), they may be -inserted into FrameSets (\secref{ss:framesets}), \emph{etc.} They do, -however, have some important limitations of which you should be aware -before we go on to consider how to create them. - -\subsection{\label{ss:intramaplimitations}Limitations of IntraMaps} - -c+ -By now, you might be wondering why any other kind of Mapping is -required at all. After all, why not simply write your own coordinate -transformation functions in C, wrap them up in IntraMaps and do away -with all the other Mapping classes in AST? -c- -f+ -By now, you might be wondering why any other kind of Mapping is -required at all. After all, why not simply write your own coordinate -transformation routines in Fortran, wrap them up in IntraMaps and do -away with all the other Mapping classes in AST? -f- - -c+ -The reason is not too hard to find. Any transformation function you -write is created solely by you, so it is a private extension which -does not form a permanent part of AST. If you use it to calibrate some -data and then pass that data to someone else, who has only the -standard version of AST, then they will not be able to interpret it. -c- -f+ -The reason is not too hard to find. Any transformation routine you -write is created solely by you, so it is a private extension which -does not form a permanent part of AST. If you use it to calibrate some -data and then pass that data to someone else, who has only the -standard version of AST, then they will not be able to interpret it. -f- - -c+ -Thus, while an IntraMap is fine for use by you and your collaborators -(who we assume have access to the same transformation functions), it -does not address the need for universal data exchange like other AST -Mappings do. This is where the ``Intra'' in the class name -``IntraMap'' comes from, implying private or internal usage. -c- -f+ -Thus, while an IntraMap is fine for use by you and your collaborators -(who we assume have access to the same transformation routines), it -does not address the need for universal data exchange like other AST -Mappings do. This is where the ``Intra'' in the class name -``IntraMap'' comes from, implying private or internal usage. -f- - -For this reason, it is unwise to store IntraMaps in datasets, unless -they will be used solely for communication between collaborating items -of software which share conventions about their use. A private -database describing coordinate systems on a graphics device might be -an example where IntraMaps would be suitable, because the data would -probably never be accessed by anyone else's software. Restricting -IntraMap usage to within a single program (\emph{i.e.} never writing -it out) is, of course, completely safe. - -c+ -If, by accident, an IntraMap should happen to escape as part of a -dataset, then the unsuspecting recipient is likely to receive an error -message when they attempt to read the data. However, AST will -associate details of the IntraMap's transformation function and its -author (if provided) with the data, so that the recipient can make an -intelligent enquiry to obtain the necessary software if this proves -essential. -c- -f+ -If, by accident, an IntraMap should happen to escape as part of a -dataset, then the unsuspecting recipient is likely to receive an error -message when they attempt to read the data. However, AST will -associate details of the IntraMap's transformation routine and its -author (if provided) with the data, so that the recipient can make an -intelligent enquiry to obtain the necessary software if this proves -essential. -f- - -c+ -\subsection{\label{ss:transformationfunctions}Writing a Transformation Function} -c- -f+ -\subsection{\label{ss:transformationfunctions}Writing a Transformation Routine} -f- - -c+ -The first stage in creating an IntraMap is to write the coordinate -transformation function. This should have a calling interface like the -astTranP function provided by AST (\emph{q.v.}). Here is a simple -example of a suitable transformation function which transforms -coordinates by squaring them: -c- -f+ -The first stage in creating an IntraMap is to write the coordinate -transformation routine. This should have a calling interface like the -AST\_TRANN function provided by AST (\emph{q.v.}). Here is a simple -example of a suitable transformation routine which transforms -coordinates by squaring them: -f- -\xlabel{SqrTran} - -c+ -\small -\begin{terminalv} -#include "ast.h" -#include <math.h> - -void SqrTran( AstMapping *this, int npoint, int ncoord_in, - const double *ptr_in[], int forward, int ncoord_out, - double *ptr_out[] ) { - int point, coord; - double x; - -/* Forward transformation. */ - if ( forward ) { - for ( point = 0; point < npoint; point++ ) { - for ( coord = 0; coord < ncoord_in; coord++ ) { - x = ptr_in[ coord ][ point ]; - ptr_out[ coord ][ point ] = ( x == AST__BAD ) ? AST__BAD : x * x; - } - } - -/* Inverse transformation. */ - } else { - for ( point = 0; point < npoint; point++ ) { - for ( coord = 0; coord < ncoord_in; coord++ ) { - x = ptr_in[ coord ][ point ]; - ptr_out[ coord ][ point ] = - ( x < 0.0 || x == AST__BAD ) ? AST__BAD : sqrt( x ); - } - } - } -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SUBROUTINE SQRTRAN( THIS, NPOINT, NCOORD_IN, INDIM, IN, FORWARD, - : NCOORD_OUT, OUTDIM, OUT, STATUS ) - INTEGER THIS, NPOINT, NCOORD_IN, INDIM, NCOORD_OUT, OUTDIM, STATUS - DOUBLE PRECISION IN( INDIM, NCOORD_IN ), OUT( OUTDIM, NCOORD_OUT ) - LOGICAL FORWARD - - INCLUDE 'AST_PAR' - DOUBLE PRECISION X - INTEGER COORD, POINT - -* Forward transformation. - IF ( FORWARD ) THEN - DO 2 POINT = 1, NPOINT - DO 1 COORD = 1, NCOORD_IN - X = IN( POINT, COORD ) - IF ( X .EQ. AST__BAD ) THEN - OUT( POINT, COORD ) = AST__BAD - ELSE - OUT( POINT, COORD ) = X * X - ENDIF - 1 CONTINUE - 2 CONTINUE - -* Inverse transformation. - ELSE - DO 4 POINT = 1, NPOINT - DO 3 COORD = 1, NCOORD_IN - X = IN( POINT, COORD ) - IF ( X .LT. 0.0D0 .OR. X .EQ. AST__BAD ) THEN - OUT( POINT, COORD ) = AST__BAD - ELSE - OUT( POINT, COORD ) = SQRT( X ) - ENDIF - 3 CONTINUE - 4 CONTINUE - ENDIF - END -\end{terminalv} -\normalsize -f- - -c+ -As you can see, the function comes in two halves which implement the -forward and inverse coordinate transformations. The number of points -to be transformed (``npoint'') and the numbers of input and output -coordinates per point (``ncoord\_in'' and ``ncoord\_out''---in this -case both are assumed equal) are passed to the function. A pair of -loops then accesses all the coordinate values. Note that it is -legitimate to omit one or other of the forward/inverse transformations -and simply not to implement it, if it will not be required. It is also -permissible to require that the numbers of input and output -coordinates be fixed (\emph{e.g.}\ at 2), or to write the function so -that it can handle arbitrary dimensionality, as here. -c- -f+ -As you can see, the routine comes in two halves which implement the -forward and inverse coordinate transformations. The number of points -to be transformed (NPOINT) and the numbers of input and output -coordinates per point (NCOORD\_IN and NCOORD\_OUT---in this case both -are assumed equal) are passed to the routine. A pair of loops then -accesses all the coordinate values. Note that it is legitimate to -omit one or other of the forward/inverse transformations and simply -not to implement it, if it will not be required. It is also -permissible to require that the numbers of input and output -coordinates be fixed (\emph{e.g.}\ at 2), or to write the routine so -that it can handle arbitrary dimensionality, as here. -f- - -c+ -Before using an incoming coordinate, the function must first check -that it is not set to the value AST\_\_BAD, which indicates missing -data (\secref{ss:badcoordinates}). If it is, the same value is also -assigned to any affected output coordinates. The value AST\_\_BAD is -also generated if any coordinates cannot be transformed. In this -example, this can happen with the inverse transformation if negative -values are encountered, so that the square root cannot be taken. -c- -f+ -Before using an incoming coordinate, the routine must first check that -it is not set to the value AST\_\_BAD, which indicates missing data -(\secref{ss:badcoordinates}). If it is, the same value is also -assigned to any affected output coordinates. The value AST\_\_BAD is -also generated if any coordinates cannot be transformed. In this -example, this can happen with the inverse transformation if negative -values are encountered, so that the square root cannot be taken. -f- - -c+ -There are very few restrictions on what a coordinate transformation -function may do. For example, it may freely perform I/O to access any -external data needed, it may invoke other AST facilities (but beware -of unwanted recursion), \emph{etc.} Typically, you may also want to -pass information to it \emph{via}\ global variables. Remember, -however, that whatever facilities the transformation function requires -must be available in every program which uses it. -c- -f+ -There are very few restrictions on what a coordinate transformation -routine may do. For example, it may freely perform I/O to access any -external data needed, it may invoke other AST facilities (but beware -of unwanted recursion), \emph{etc.} Typically, you may also want to -pass information to it \emph{via}\ global variables held in common -blocks. Remember, however, that whatever facilities the -transformation routine requires must be available in every program -which uses it. -f- - -c+ -Generally, it is not a good idea to retain context information within -a transformation function. That is, it should transform each set of -coordinates as a single point and retain no memory of the points it -has transformed before. This is in order to conform with the AST model -of a Mapping. -c- -f+ -Generally, it is not a good idea to retain context information within -a transformation routine. That is, it should transform each set of -coordinates as a single point and retain no memory of the points it -has transformed before. This is in order to conform with the AST model -of a Mapping. -f- - -c+ -If an error occurs within a transformation function, it should use the -astSetStatus function (\secref{ss:errordetection}) to set the AST -status to an error value before returning. This will alert AST to the -error, causing it to abort the current operation. The error value -AST\_\_ITFER is available for this purpose, but other values may also -be used (\emph{e.g.}\ if you wish to distinguish different types of -error). -c- -f+ -If an error occurs within a transformation routine, it should set its -STATUS argument to an error value before returning. This will alert -AST to the error, causing it to abort the current operation. The error -value AST\_\_ITFER is available for this purpose, but other values may -also be used (\emph{e.g.}\ if you wish to distinguish different types -of error). The AST\_\_ITFER error value is defined in the AST\_ERR -include file. -f- - -c+ -\subsection{\label{ss:registeringintramaps}Registering a Transformation Function} -c- -f+ -\subsection{\label{ss:registeringintramaps}Registering a Transformation Routine} -f- - -c+ -Having written your coordinate transformation function, the next step -is to register it with AST. Registration is performed using -astIntraReg, as follows: -c- -f+ -Having written your coordinate transformation routine, the next step -is to register it with AST. Registration is performed using -AST\_INTRAREG, as follows: -f- - -c+ -\small -\begin{terminalv} -void SqrTran( AstMapping *, int, int, const double *[], int, int, double *[] ); - -const char *author, *contact, *purpose; - -... - -purpose = "Square each coordinate value"; -author = "R.F. Warren-Smith & D.S. Berry"; -contact = "http://www.starlink.ac.uk/cgi-bin/htxserver/sun211.htx/?xref_SqrTran"; - -astIntraReg( "SqrTran", 2, 2, SqrTran, 0, purpose, author, contact ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - EXTERNAL SQRTRAN - - CHARACTER * ( 80 ) AUTHOR, CONTACT, PURPOSE - - ... - - PURPOSE = 'Square each coordinate value' - AUTHOR = 'R.F. Warren-Smith & D.S. Berry' - CONTACT = 'http://www.starlink.ac.uk/cgi-bin/htxserver/' // - 'sun210.htx/?xref_SqrTran' - - CALL AST_INTRAREG( 'SqrTran', 2, 2, SQRTRAN, 0, - : PURPOSE, AUTHOR, CONTACT, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Note that you should also provide a function prototype to describe the -transformation function (the implementation of the function itself -would suffice, of course). -c- -f+ -Note that the transformation routine must also appear in a Fortran -EXTERNAL statement. -f- - -c+ -The first argument to astIntraReg is a name by which the -transformation function will be known. This will be used when we come -to create an IntraMap and is case sensitive. We recommend that you use -the actual function name here and make this sufficiently unusual that -it is unlikely to clash with any other functions in most people's -software. -c- -f+ -The first argument to AST\_INTRAREG is a name by which the -transformation routine will be known. This will be used when we come -to create an IntraMap and is case sensitive. We recommend that you -base this on the actual routine name and make this sufficiently -unusual that it is unlikely to clash with any other routines in most -people's software. -f- - -c+ -The next two arguments specify the number of input and output -coordinates which the transformation function will handle. These -correspond with the Nin and Nout attributes of the IntraMap we will -create. Here, we have set them both to 2, which means that we will -only be able to create IntraMaps with 2 input and 2 output coordinates -(despite the fact that the transformation function can actually handle -other dimensionalities). We will see later -(\secref{ss:variableintramapcoordinates}) how to remove this -restriction. -c- -f+ -The next two arguments specify the number of input and output -coordinates which the transformation routine will handle. These -correspond with the Nin and Nout attributes of the IntraMap we will -create. Here, we have set them both to 2, which means that we will -only be able to create IntraMaps with 2 input and 2 output coordinates -(despite the fact that the transformation routine can actually handle -other dimensionalities). We will see later -(\secref{ss:variableintramapcoordinates}) how to remove this -restriction. -f- - -c+ -The fourth argument should contain a set of flags which describe the -transformation function in a little more detail. We will return to -this shortly (\secref{ss:restrictedintramaps} \& -\secref{ss:simplifyingintramaps}). For now, we supply a value of zero. -c- -f+ -The fourth argument should contain a set of flags which describe the -transformation routine in a little more detail. We will return to this -shortly (\secref{ss:restrictedintramaps} \& -\secref{ss:simplifyingintramaps}). For now, we supply a value of zero. -f- - -c+ -The remaining arguments are character strings which document the -transformation function, mainly for the benefit of anyone who is -unfortunate enough to encounter a reference to it in their data which -they cannot interpret. As explained above -(\secref{ss:intramaplimitations}), you should try and avoid this, but -accidents will happen, so you should always provide strings containing -the following: -c- -f+ -The remaining arguments are character strings which document the -transformation routine, mainly for the benefit of anyone who is -unfortunate enough to encounter a reference to it in their data which -they cannot interpret. As explained above -(\secref{ss:intramaplimitations}), you should try and avoid this, but -accidents will happen, so you should always provide strings containing -the following: -f- - -\begin{enumerate} -c+ -\item A short description of what the transformation function is for. -c- -f+ -\item A short description of what the transformation routine is for. -f- -\item The name of the author. -\item Contact details, such as an e-mail or WWW address. -\end{enumerate} - -c+ -The idea is that anyone finding an IntraMap in their data, but lacking -the necessary transformation function, should be able to contact the -author and make a sensible enquiry in order to obtain it. If you -expect many enquiries, you may like to set up a World Wide Web page -and use that instead (in the example above, we use the WWW address of -the relevant part of this document). -c- -f+ -The idea is that anyone finding an IntraMap in their data, but lacking -the necessary transformation routine, should be able to contact the -author and make a sensible enquiry in order to obtain it. If you -expect many enquiries, you may like to set up a World Wide Web page -and use that instead (in the example above, we use the WWW address of -the relevant part of this document). -f- - -\subsection{Creating an IntraMap} - -c+ -Once a transformation function has been registered, creating an -IntraMap from it is simple: -c- -f+ -Once a transformation routine been registered, creating an IntraMap -from it is simple: -f- - -c+ -\small -\begin{terminalv} -AstIntraMap *intramap; - -... - -intramap = astIntraMap( "SqrTran", 2, 2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER INTRAMAP - - ... - - INTRAMAP = AST_INTRAMAP( 'SqrTran', 2, 2, ' ', STATUS ); -\end{terminalv} -\normalsize -f- - -c+ -We simply use the astIntraMap constructor function and pass it the -name of the transformation function to use. This name is the same -(case sensitive) one that we associated with the function when we -registered it using astIntraReg (\secref{ss:registeringintramaps}). -c- -f+ -We simply use the AST\_INTRAMAP constructor function and pass it the -name of the transformation routine to use. This name is the same (case -sensitive) one that we associated with the routine when we registered -it using AST\_INTRAREG (\secref{ss:registeringintramaps}). -f- - -c+ -You can, of course, register any number of transformation functions -and select which one to use whenever you create an IntraMap. You can -also create any number of independent IntraMaps using each -transformation function. In this sense, each transformation function -you register effectively creates a new ``sub-class'' of IntraMap, from -which you can create Objects just like any other class. However, an -error will occur if you attempt to use a transformation function that -has not yet been registered. -c- -f+ -You can, of course, register any number of transformation routines and -select which one to use whenever you create an IntraMap. You can also -create any number of independent IntraMaps using each transformation -routine. In this sense, each transformation routine you register -effectively creates a new ``sub-class'' of IntraMap, from which you -can create Objects just like any other class. However, an error will -occur if you attempt to use a transformation routine that has not yet -been registered. -f- - -c+ -The second and third arguments to astIntraMap are the numbers of input -and output coordinates. These define the Nin and Nout attributes for -the IntraMap that is created and they must match the corresponding -numbers given when the transformation function was registered. -c- -f+ -The second and third arguments to AST\_INTRAMAP are the numbers of -input and output coordinates. These define the Nin and Nout attributes -for the IntraMap that is created and they must match the corresponding -numbers given when the transformation routine was registered. -f- - -c+ -The final argument is the usual attribute initialisation string. You -may set attribute values for an IntraMap in exactly the same way as -for any other Mapping (\secref{ss:settingattributes}, and also see -\secref{ss:intraflag}). -c- -f+ -The penultimate argument is the usual attribute initialisation -string. You may set attribute values for an IntraMap in exactly the -same way as for any other Mapping (\secref{ss:settingattributes}, and -also see \secref{ss:intraflag}). -f- - -c+ -\subsection{\label{ss:restrictedintramaps}Restricted Implementations of Transformation Functions} -c- -f+ -\subsection{\label{ss:restrictedintramaps}Restricted Implementations of Transformation Routines} -f- - -c+ -You may not always want to use both the forward and inverse -transformations when you create an IntraMap, so it is possible to omit -either from the underlying coordinate transformation -function. Consider the following, for example: -c- -f+ -You may not always want to use both the forward and inverse -transformations when you create an IntraMap, so it is possible to omit -either from the underlying coordinate transformation routine. Consider -the following, for example: -f- - -c+ -\small -\begin{terminalv} -void Poly3Tran( AstMapping *this, int npoint, int ncoord_in, - const double *ptr_in[], int forward, int ncoord_out, - double *ptr_out[] ) { - double x; - int point; - -/* Forward transformation. */ - for ( point = 0; point < npoint; point++ ) { - x = ptr_in[ 0 ][ point ]; - ptr_out[ 0 ][ point ] = ( x == AST__BAD ) ? AST__BAD : - 6.18 + x * ( 0.12 + x * ( -0.003 + x * 0.0000101 ) ); - } -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SUBROUTINE POLY3TRAN( THIS, NPOINT, NCOORD_IN, INDIM, IN, FORWARD, - : NCOORD_OUT, OUTDIM, OUT, STATUS ) - INTEGER THIS, NPOINT, NCOORD_IN, INDIM, NCOORD_OUT, OUTDIM, STATUS - DOUBLE PRECISION IN( INDIM, NCOORD_IN ), OUT( OUTDIM, NCOORD_OUT ) - LOGICAL FORWARD - - INCLUDE 'AST_PAR' - DOUBLE PRECISION X - INTEGER POINT - -* Forward transformation. - DO 1 POINT = 1, NPOINT - X = IN( POINT, 1 ) - IF ( X .EQ. AST__BAD ) THEN - OUT( POINT, 1 ) = AST__BAD - ELSE - OUT( POINT, 1 ) = - : 6.18D0 + X * ( 0.12D0 + X * ( -0.003D0 + X * 0.0000101D0 ) ) - END IF - 1 CONTINUE - END -\end{terminalv} -\normalsize -f- - -c+ -This implements a 1-dimensional cubic polynomial transformation. Since -this is somewhat awkward to invert, however, we have only implemented -the forward transformation. When registering the function, this is -indicated via the ``flags'' argument to astIntraReg, as follows: -c- -f+ -This implements a 1-dimensional cubic polynomial transformation. Since -this is somewhat awkward to invert, however, we have only implemented -the forward transformation. When registering the routine, this is -indicated via the FLAGS argument to AST\_INTRAREG, as follows: -f- - -c+ -\small -\begin{terminalv} -void Poly3Tran( AstMapping *, int, int, const double *[], int, int, double *[] ); - -... - -astIntraReg( "Poly3Tran", 1, 1, Poly3Tran, AST__NOINV, - purpose, author, contact ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - EXTERNAL POLY3TRAN - - ... - - CALL AST_INTRAREG( 'Poly3Tran', 1, 1, POLY3TRAN, AST__NOINV, - : PURPOSE, AUTHOR, CONTACT, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, the fifth argument has been set to the flag value AST\_\_NOINV -to indicate the lack of an inverse. If the forward transformation were -absent, we would use AST\_\_NOFOR instead. Flag values for this -argument may be combined using a bitwise OR if necessary. -c- -f+ -Here, the fifth argument has been set to the flag value AST\_\_NOINV -to indicate the lack of an inverse. If the forward transformation were -absent, we would use AST\_\_NOFOR instead. Flag values for this -argument may be combined by summing them if necessary. -f- - -\subsection{\label{ss:variableintramapcoordinates}Variable Numbers of Coordinates} - -c+ -In our earlier examples, we have used a fixed number of input and -output coordinates when registering a coordinate transformation -function. It is not necessary to impose this restriction, however, if -the transformation function can cope with a variable number of -coordinates (as with the example in -\secref{ss:transformationfunctions}). We indicate the acceptability of -a variable number when registering the transformation function by -supplying the value AST\_\_ANY for the number of input and/or output -coordinates, as follows: -c- -f+ -In our earlier examples, we have used a fixed number of input and -output coordinates when registering a coordinate transformation -routine. It is not necessary to impose this restriction, however, if -the transformation routine can cope with a variable number of -coordinates (as with the example in -\secref{ss:transformationfunctions}). We indicate the acceptability of -a variable number when registering the transformation routine by -supplying the value AST\_\_ANY for the number of input and/or output -coordinates, as follows: -f- - -c+ -\small -\begin{terminalv} -astIntraReg( "SqrTran", AST__ANY, AST__ANY, SqrTran, 0, - purpose, author, contact ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_INTRAREG( 'SqrTran', AST__ANY, AST__ANY, SQRTRAN, 0, - : PURPOSE, AUTHOR, CONTACT, STATUS ) -\end{terminalv} -\normalsize -f- - -The result is that an IntraMap may now be created with any number of -input and output coordinates. For example: - -c+ -\small -\begin{terminalv} -AstIntraMap *intramap1, *intramap2; - -... - -intramap1 = astIntraMap( "SqrTran", 1, 1, "" ); -intramap2 = astIntraMap( "SqrTran", 3, 3, "Invert=1" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER INTRAMAP1, INTRAMAP2 - - ... - - INTRAMAP1 = AST_INTRAMAP( 'SqrTran', 1, 1, ' ', STATUS ) - INTRAMAP2 = AST_INTRAMAP( 'SqrTran', 3, 3, 'Invert=1', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -It is possible to fix either the number of input or output coordinates -(by supplying an explicit number to astIntraReg), but more subtle -restrictions on the number of coordinates, such as requiring that Nin -and Nout be equal, are not supported. This means that: -c- -f+ -It is possible to fix either the number of input or output coordinates -(by supplying an explicit number to AST\_INTRAREG), but more subtle -restrictions on the number of coordinates, such as requiring that Nin -and Nout be equal, are not supported. This means that: -f- - -c+ -\small -\begin{terminalv} -intramap = astIntraMap( "SqrTran", 1, 2, "" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTRAMAP = AST_INTRAMAP( 'SqrTran', 1, 2, ' ', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -will be accepted without error, although the transformation function -cannot actually handle such a combination sensibly. If this is -important, it would be worth adding a check within the transformation -function itself, so that the error would be detected when it came to -be used. -c- -f+ -will be accepted without error, although the transformation routine -cannot actually handle such a combination sensibly. If this is -important, it would be worth adding a check within the transformation -routine itself, so that the error would be detected when it came to be -used. -f- - -c+ -\subsection{\label{ss:intraflag}Adapting a Transformation Function to Individual IntraMaps} -c- -f+ -\subsection{\label{ss:intraflag}Adapting a Transformation Routine to Individual IntraMaps} -f- - -c+ -In the examples given so far, our coordinate transformation functions -have not made use of the ``this'' pointer passed to them (which -identifies the IntraMap whose transformation we are implementing). In -practice, this will often be the case. However, the presence of the -``this'' pointer allows the transformation function to invoke any -other AST function on the IntraMap, and this permits enquiries about -its attributes. The transformation function's behaviour can therefore -be modified according to any attribute values which are set. This -turns out to be a useful thing to do, so each IntraMap has a special -IntraFlag attribute reserved for exactly this purpose. -c- -f+ -In the examples given so far, our coordinate transformation routines -have not made use of the THIS pointer passed to them (which identifies -the IntraMap whose transformation we are implementing). In practice, -this will often be the case. However, the presence of the THIS pointer -allows the transformation routine to invoke any other AST routine on -the IntraMap, and this permits enquiries about its attributes. The -transformation routine's behaviour can therefore be modified according -to any attribute values which are set. This turns out to be a useful -thing to do, so each IntraMap has a special IntraFlag attribute reserved -for exactly this purpose. -f- - -c+ -Consider, for instance, the case where the transformation function has -access to several alternative sets of internally-stored data which it -may apply to perform its transformation. Rather than implement many -different versions of the transformation function, you may switch -between them by setting a value for the IntraFlag attribute when you -create an instance of an IntraMap, for example: -c- -f+ -Consider, for instance, the case where the transformation routine has -access to several alternative sets of internally-stored data which it -may apply to perform its transformation. Rather than implement many -different versions of the transformation routine, you may switch -between them by setting a value for the IntraFlag attribute when you -create an instance of an IntraMap, for example: -f- - -c+ -\small -\begin{terminalv} -intramap1 = astIntraMap( "MyTran", 2, 2, "IntraFlag=A" ); -intramap2 = astIntraMap( "MyTran", 2, 2, "IntraFlag=B" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTRAMAP1 = AST_INTRAMAP( 'MyTran', 2, 2, 'IntraFlag=A', STATUS ) - INTRAMAP2 = AST_INTRAMAP( 'MyTran', 2, 2, 'IntraFlag=B', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -The transformation function may then enquire the value of the IntraFlag -attribute (\emph{e.g.}\ using astGetC and passing it the ``this'' -pointer) and use whichever dataset is required for that particular -IntraMap. -c- -f+ -The transformation routine may then enquire the value of the IntraFlag -attribute (\emph{e.g.}\ using AST\_GETC and passing it the THIS -pointer) and use whichever dataset is required for that particular -IntraMap. -f- - -This approach is particularly useful when the number of possible -transformations is unbounded or not known in advance, in which case -the IntraFlag attribute may be used to hold numerical values encoded -as part of a character string (effectively using them as data for the -IntraMap). It is also superior to the use of a global switch for -communication (\emph{e.g.}\ setting an index to select the ``current'' -data before using the IntraMap), because it continues to work when -several IntraMaps are embedded within a more complex compound Mapping, -when you may have no control over the order in which they are used. - -\subsection{\xlabel{MaxTran}\label{ss:simplifyingintramaps}Simplifying IntraMaps} - -c+ -A notable disadvantage of IntraMaps is that they are ``black boxes'' -as far as AST is concerned. This means that they have limited ability -to participate in the simplification of compound Mappings performed, -\emph{e.g.}, by astSimplify (\secref{ss:simplifyingcmpmaps}), because -AST cannot know how they interact with other Mappings. In reality, of -course, they will often implement such specialised coordinate -transformations that the simplification possibilities will be rather -limited anyway. -c- -f+ -A notable disadvantage of IntraMaps is that they are ``black boxes'' -as far as AST is concerned. This means that they have limited ability -to participate in the simplification of compound Mappings performed, -\emph{e.g.}, by AST\_SIMPLIFY (\secref{ss:simplifyingcmpmaps}), -because AST cannot know how they interact with other Mappings. In -reality, of course, they will often implement such specialised -coordinate transformations that the simplification possibilities will -be rather limited anyway. -f- - -One important simplification, however, is the ability of a Mapping to -cancel with its own inverse to yield a unit Mapping (a UnitMap). This -is important because Mappings are frequently used to relate a dataset -to some external standard (a celestial coordinate system, for -example). When inter-relating two similar datasets calibrated using -the same standard, part of the Mapping often cancels, because it is -applied first in one direction and then the other, effectively -eliminating the reference to the standard. This is often a useful -simplification and can lead to greater efficiency. - -c+ -Many transformations have this property of cancelling with their own -inverse, but not necessarily all. Consider the following -transformation function, for example: -c- -f+ -Many transformations have this property of cancelling with their own -inverse, but not necessarily all. Consider the following -transformation routine, for example: -f- - -c+ -\small -\begin{terminalv} -void MaxTran( AstMapping *this, int npoint, int ncoord_in, - const double *ptr_in[], int forward, int ncoord_out, - double *ptr_out[] ) { - double hi, x; - int coord, point; - -/* Forward transformation. */ - if ( forward ) { - for ( point = 0; point < npoint; point++ ) { - hi = AST__BAD; - for ( coord = 0; coord < ncoord_in; coord++ ) { - x = ptr_in[ coord ][ point ]; - if ( x != AST__BAD ) { - if ( x > hi || hi == AST__BAD ) hi = x; - } - } - ptr_out[ 0 ][ point ] = hi; - } - -/* Inverse transformation. */ - } else { - for ( coord = 0; coord < ncoord_out; coord++ ) { - for ( point = 0; point < npoint; point++ ) { - ptr_out[ coord ][ point ] = ptr_in[ 0 ][ point ]; - } - } - } -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SUBROUTINE MAXTRAN( THIS, NPOINT, NCOORD_IN, INDIM, IN, FORWARD, - : NCOORD_OUT, OUTDIM, OUT, STATUS ) - INTEGER THIS, NPOINT, NCOORD_IN, INDIM, NCOORD_OUT, OUTDIM, STATUS - DOUBLE PRECISION IN( INDIM, NCOORD_IN ), OUT( OUTDIM, NCOORD_OUT ) - LOGICAL FORWARD - - INCLUDE 'AST_PAR' - DOUBLE PRECISION HI, X - INTEGER COORD, POINT - -* Forward transformation. - IF ( FORWARD ) THEN - DO 2 POINT = 1, NPOINT - HI = AST__BAD - DO 1 COORD = 1, NCOORD_IN - X = IN( POINT, COORD ) - IF ( X .NE. AST__BAD ) THEN - IF ( X .GT. HI .OR. HI .EQ. AST__BAD ) HI = X - END IF - 1 CONTINUE - 2 CONTINUE - -* Inverse transformation. - ELSE - DO 4 COORD = 1, NCOORD_OUT - DO 3 POINT = 1, NPOINT - OUT( POINT, COORD ) = IN( POINT, 1 ) - 3 CONTINUE - 4 CONTINUE - END IF - END -\end{terminalv} -\normalsize -f- - -c+ -This function takes any number of input coordinates and returns a -single output coordinate which is the maximum value of the input -coordinates. Its inverse (actually a ``pseudo-inverse'') sets all the -input coordinates to the value of the output -coordinate.\footnote{Remember that ``ptr\_in'' identifies the original -``output'' coordinates when applying the inverse transformation and -``ptr\_out'' identifies the original ``input'' coordinates.} -c- -f+ -This routine takes any number of input coordinates and returns a -single output coordinate which is the maximum value of the input -coordinates. Its inverse (actually a ``pseudo-inverse'') sets all the -input coordinates to the value of the output -coordinate.\footnote{Remember that IN holds the original ``output'' -coordinates when applying the inverse transformation and OUT holds the -original ``input'' coordinates.} -f- - -c+ -If this function is applied in the forward direction and then in the -inverse direction, it does \textbf{not} in general restore the original -coordinate values. However, if applied in the inverse direction and -then the forward direction, it does. Hence, replacing the sequence of -operations with an equivalent UnitMap is possible in the latter case, -but not in the former. -c- -f+ -If this routine is applied in the forward direction and then in the -inverse direction, it does \textbf{not} in general restore the original -coordinate values. However, if applied in the inverse direction and -then the forward direction, it does. Hence, replacing the sequence of -operations with an equivalent UnitMap is possible in the latter case, -but not in the former. -f- - -c+ -To distinguish these possibilities, two flag values are provided for -use with astIntraReg to indicate what simplification (if any) is -possible. For example, to register the above transformation function, -we might use: -c- -f+ -To distinguish these possibilities, two flag values are provided for -use with AST\_INTRAREG to indicate what simplification (if any) is -possible. For example, to register the above transformation routine, -we might use: -f- - -c+ -\small -\begin{terminalv} -void MaxTran( AstMapping *, int, int, const double *[], int, int, double *[] ); - -... - -astIntraReg( "MaxTran", AST__ANY, 1, MaxTran, AST__SIMPIF, - purpose, author, contact ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - EXTERNAL MAXTRAN - - ... - - CALL AST_INTRAREG( 'MaxTran', AST__ANY, 1, MAXTRAN, AST__SIMPIF, - : PURPOSE, AUTHOR, CONTACT, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, the flag value AST\_\_SIMPIF supplied for the fifth argument -indicates that simplification is possible if the transformation is -applied in the inverse direction followed by the forward direction. To -indicate the complementary case, the flag AST\_\_SIMPFI would be used -instead. If both simplifications are possible (as with the SqrTran -function in \secref{ss:transformationfunctions}), then we would use -the bitwise OR of both values. -c- -f+ -Here, the flag value AST\_\_SIMPIF supplied for the fifth argument -indicates that simplification is possible if the transformation is -applied in the inverse direction followed by the forward direction. To -indicate the complementary case, the flag AST\_\_SIMPFI would be used -instead. If both simplifications are possible (as with the SQRTRAN -function in \secref{ss:transformationfunctions}), then we would use -the sum of both values. -f- - -c+ -In practice, some judgement is usually necessary when deciding whether -to allow simplification. For example, seen in one light our SqrTran -function (\secref{ss:transformationfunctions}) does not cancel with -its own inverse, because squaring a coordinate value and then taking -its square root can change the original value, if this was -negative. Therefore, replacing this combination with a UnitMap will -change the behaviour of a compound Mapping and should not be -allowed. Seen in another light, however, where the coordinates being -processed are intrinsically all positive, it is a permissible and -probably useful simplification. -c- -f+ -In practice, some judgement is usually necessary when deciding whether -to allow simplification. For example, seen in one light our SQRTRAN -routine (\secref{ss:transformationfunctions}) does not cancel with its -own inverse, because squaring a coordinate value and then taking its -square root can change the original value, if this was -negative. Therefore, replacing this combination with a UnitMap will -change the behaviour of a compound Mapping and should not be -allowed. Seen in another light, however, where the coordinates being -processed are intrinsically all positive, it is a permissible and -probably useful simplification. -f- - -c+ -If such distinctions are ever important in practice, it is simple to -register the same transformation function twice with different flag -values (use a separate name for each) and then use whichever is -appropriate when creating an IntraMap. -c- -f+ -If such distinctions are ever important in practice, it is simple to -register the same transformation routine twice with different flag -values (use a separate name for each) and then use whichever is -appropriate when creating an IntraMap. -f- - -\subsection{\label{ss:readingandwritingintramaps}Writing and Reading IntraMaps} - -c+ -It is most important to realise that when you write an IntraMap to a -Channel (\secref{ss:writingtoachannel}), the transformation function -which it uses is not stored with it. To do so is impossible, because -the function has been compiled and loaded into memory ready for -execution before AST gets to see it. However, AST does store the name -associated with the transformation function and various details about -the IntraMap itself. - -c- -f+ -It is most important to realise that when you write an IntraMap to a -Channel (\secref{ss:writingtoachannel}), the transformation routine -which it uses is not stored with it. To do so is impossible, because -the routine has been compiled and loaded into memory ready for -execution before AST gets to see it. However, AST does store the name -associated with the transformation routine and various details about -the IntraMap itself. -f- - -c+ -This means that any program attempting to read the IntraMap -(\secref{ss:readingfromachannel}) cannot make use of it unless it also -has independent access to the original transformation function. If it -does not have access to this function, an error will occur at the -point where the IntraMap is read and the associated error message will -direct the user to the author of the transformation function for more -information. -c- -f+ -This means that any program attempting to read the IntraMap -(\secref{ss:readingfromachannel}) cannot make use of it unless it also -has independent access to the original transformation routine. If it -does not have access to this routine, an error will occur at the point -where the IntraMap is read and the associated error message will -direct the user to the author of the transformation routine for more -information. -f- - -c+ -However, if the necessary transformation function is available, and -has been registered before the read operation takes place, then AST is -able to re-create the original IntraMap and will do so. Registration -of the transformation function must, of course, use the same name -(and, in fact, be identical in most particulars) as was used in the -original program which wrote the data. -c- -f+ -However, if the necessary transformation routine is available, and -has been registered before the read operation takes place, then AST is -able to re-create the original IntraMap and will do so. Registration -of the transformation routine must, of course, use the same name -(and, in fact, be identical in most particulars) as was used in the -original program which wrote the data. -f- - -c+ -This means that a set of co-operating programs which all have access -to the same set of transformation functions and register them in -identical fashion (see \secref{ss:intramaplibrary} for how this can -best be achieved) can freely exchange data that contain IntraMaps. The -need to avoid exporting such data to unsuspecting third parties -(\secref{ss:intramaplimitations}) must, however, be re-iterated. -c- -f+ -This means that a set of co-operating programs which all have access -to the same set of transformation routines and register them in -identical fashion (see \secref{ss:intramaplibrary} for how this can -best be achieved) can freely exchange data that contain IntraMaps. The -need to avoid exporting such data to unsuspecting third parties -(\secref{ss:intramaplimitations}) must, however, be re-iterated. -f- - -c+ -\subsection{\label{ss:intramaplibrary}Managing Transformation Functions in Libraries} -c- -f+ -\subsection{\label{ss:intramaplibrary}Managing Transformation Routines in Libraries} -f- - -c+ -If you are developing a large suite of data reduction software, you -may have a need to use IntraMaps at various points within it. Very -probably this will occur in unrelated modules which are compiled -separately and then stored in a library. Since the transformation -functions required must be registered before they can be used, this -makes it difficult to decide where to perform this registration, -especially since any particular data reduction program may use an -arbitrary subset of the modules in your library. -c- -f+ -If you are developing a large suite of data reduction software, you -may have a need to use IntraMaps at various points within it. Very -probably this will occur in unrelated modules which are compiled -separately and then stored in a library. Since the transformation -routines required must be registered before they can be used, this -makes it difficult to decide where to perform this registration, -especially since any particular data reduction program may use an -arbitrary subset of the modules in your library. -f- - -c+ -To assist with this problem, AST allows you to perform the same -registration of a transformation function any number of times, so long -as it is performed using an identical invocation of astIntraReg on -each occasion (\emph{i.e.}\ all of its arguments must be -identical). This means you do not have to keep track of whether a -particular function has already been registered but could, in fact, -register it on each occasion immediately before it is required -(wherever that may be). In order that all registrations are identical, -however, it is recommended that you group them all together into a -single function, perhaps as follows: -c- -f+ -To assist with this problem, AST allows you to perform the same -registration of a transformation routine any number of times, so long -as it is performed using an identical invocation of AST\_INTRAREG on -each occasion (\emph{i.e.}\ all of its arguments must be -identical). This means you do not have to keep track of whether a -particular routine has already been registered but could, in fact, -register it on each occasion immediately before it is required -(wherever that may be). In order that all registrations are identical, -however, it is recommended that you group them all together into a -single routine, perhaps as follows: -f- - -c+ -\small -\begin{terminalv} -void MyTrans( void ) { - - ... - - astIntraReg( "MaxTran", AST__ANY, 1, MaxTran, AST__SIMPIF, - purpose, author, contact ); - - ... - - astIntraReg( "Poly3Tran", 1, 1, Poly3Tran, AST__NOINV, - purpose, author, contact ); - - ... - - astIntraReg( "SqrTran", 2, 2, SqrTran, 0, - purpose, author, contact ); -} -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - SUBROUTINE MYTRANS( STATUS ) - INTEGER STATUS - - INCLUDE 'AST_PAR' - EXTERNAL MAXTRAN, POLY3TRAN, SQRTRAN - - ... - - CALL AST_INTRAREG( 'MaxTran', AST__ANY, 1, MAXTRAN, AST__SIMPIF, - : PURPOSE, AUTHOR, CONTACT, STATUS ) - - ... - - CALL AST_INTRAREG( 'Poly3Tran', 1, 1, POLY3TRAN, AST__NOINV, - : PURPOSE, AUTHOR, CONTACT, STATUS ) - - ... - - CALL AST_INTRAREG( 'SqrTran, 2, 2, SQRTRAN, 0, - : PURPOSE, AUTHOR, CONTACT, STATUS ) - END -\end{terminalv} -\normalsize -f- - -c+ -You can then simply invoke this function wherever necessary. It is, in -fact, particularly important to register all relevant transformation -functions in this way before you attempt to read an Object that might -be (or contain) an IntraMap -(\secref{ss:readingandwritingintramaps}). This is because you may not -know in advance which of these transformation functions the IntraMap -will use, so they must all be available in order to avoid an error. -c- -f+ -You can then simply invoke this routine wherever necessary. It is, in -fact, particularly important to register all relevant transformation -routines in this way before you attempt to read an Object that might -be (or contain) an IntraMap -(\secref{ss:readingandwritingintramaps}). This is because you may not -know in advance which of these transformation routines the IntraMap -will use, so they must all be available in order to avoid an error. -f- - -\cleardoublepage -\section{\label{ss:plots}Producing Graphical Output (Plots)} - -Graphical output from AST is performed though an Object called a Plot, -which is a specialised form of FrameSet. A Plot does not represent the -graphical content itself, but is a route through which plotting -operations, such as drawing lines and curves, are conveyed on to a -plotting surface to appear as visible graphics. - -\subsection{The Plot Model} - -When a Plot is created, it is initialised by providing a FrameSet whose -base Frame (as specified by its Base attribute) is mapped linearly or -logarithmically (as specified by the LogPlot attribues) on to a -\emph{plotting area}. This is a rectangular region in the graphical -coordinate space of the underlying graphics system and becomes the new -base Frame of the Plot. In effect, the Plot becomes attached to the -plotting surface, in rather the same way that a basic FrameSet might be -attached to (say) an image. - -The current Frame of the Plot (derived from the current Frame of the -FrameSet supplied) is used to represent a \emph{physical coordinate -system}. This is the system in which plotting operations are -performed by your program. Every plotting operation is then -transformed through the Mapping which inter-relates the Plot's current -and base Frames in order to appear on the plotting surface. - -An example may help here. Suppose we start with a FrameSet whose base -Frame describes the pixel coordinates of an image and whose current -Frame describes a celestial (equatorial) coordinate system. Let us -assume that these two Frames are inter-related by a Mapping within the -FrameSet which represents a particular sky projection. - -When a Plot is created from this FrameSet, we specify how the pixel -coordinates (the base Frame) maps on to the plotting surface. This -simply corresponds to telling the Plot where we have previously -plotted the image data. If we now use the Plot to plot a line with -latitude zero in our physical coordinate system, as given by the -current Frame, this line would appear as a curve (the equator) on the -plotting surface, correctly registered with the image. - -There are a number of plotting functions provided, which all work in a -similar way. Plotting operations are transformed through the Mapping -which the Plot represents before they appear on the plotting -surface.\footnote{Like any FrameSet, a Plot can be used as a -Mapping. In this case it is the inverse transformation which is used -when plotting (\emph{i.e.}\ that which transforms between the current -and base Frames).} It is possible to draw symbols, lines, axes, -entire grids and more in this way. - -%\subsection{TBW---Creating a Plot} - -\subsection{Plotting Symbols} - -c+ -The simplest form of plotting is to draw symbols (termed -\emph{markers}) at a set of points. This is performed by astMark, -which is supplied with a set of physical coordinates at which to place -the markers: -c- -f+ -The simplest form of plotting is to draw symbols (termed -\emph{markers}) at a set of points. This is performed by AST\_MARK, -which is supplied with a set of physical coordinates at which to place -the markers: -f- - -c+ -\small -\begin{terminalv} -#include "ast.h" -#define NCOORD 2 -#define NMARK 10 -double in[ NCOORD ][ NMARK ]; -int type; - -... - -astMark( plot, NMARK, NCOORD, NMARK, in, type ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INCLUDE 'AST_PAR' - INTEGER NCOORD, NMARK, TYPE, STATUS - DOUBLE PRECISION IN( NMARK, NCOORD ) - - STATUS = 0 - - ... - - CALL AST_MARK( PLOT, NMARK, NCOORD, NMARK, IN, TYPE, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, NMARK specifies how many markers to plot and NCOORD specifies -how many coordinates are being supplied for each -point.\footnote{Remember, the physical coordinate space need not -necessarily be 2-dimensional, even if the plotting surface is.} The -array ``in'' supplies the coordinates and the integer ``type'' -specifies which type of marker to plot. -c- -f+ -Here, NMARK specifies how many markers to plot and NCOORD specifies -how many coordinates are being supplied for each -point.\footnote{Remember, the physical coordinate space need not -necessarily be 2-dimensional, even if the plotting surface is.} The -array IN supplies the coordinates and the integer TYPE specifies which -type of marker to plot. -f- - -\subsection{\label{ss:plottinggeodesics}Plotting Geodesic Curves} - -There is no Plot routine to draw a straight line, because any straight -line in physical coordinates can potentially turn into a curve in -graphical coordinates. We therefore start by considering how to draw -geodesic curves. These are curves which trace the path of shortest -distance between two points in physical coordinates - and are the basic drawing element in a Plot. - -c+ -In many instances, the geodesic will, in fact, be a straight line, but -this depends on the Plot's current Frame. If this represents a -celestial coordinate system, for instance, it will be a great circle -(corresponding with the behaviour of the astDistance function which -defines the metric of the physical coordinate space). The geodesic -will, of course, be transformed into graphics coordinates before being -plotted. A geodesic curve is plotted using astCurve as follows: -c- -f+ -In many instances, the geodesic will, in fact, be a straight line, but -this depends on the Plot's current Frame. If this represents a -celestial coordinate system, for instance, it will be a great circle -(corresponding with the behaviour of the AST\_DISTANCE function which -defines the metric of the physical coordinate space). The geodesic -will, of course, be transformed into graphics coordinates before being -plotted. A geodesic curve is plotted using AST\_CURVE as follows: -f- - -c+ -\small -\begin{terminalv} -double start[ NCOORD ], finish[ NCOORD ]; - -... - -astCurve( plot, start, finish ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - DOUBLE PRECISION START( NCOORD ), FINISH( NCOORD ) - - ... - - CALL AST_CURVE( PLOT, START, FINISH, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, ``start'' and ``finish'' are arrays containing the starting and -finishing coordinates of the curve. The astOffset and astDistance -functions can often be useful for computing these -(\secref{ss:distanceandoffset}). -c- -f+ -Here, START and FINISH are arrays containing the starting and -finishing coordinates of the curve. The AST\_OFFSET and AST\_DISTANCE -routines can often be useful for computing these -(\secref{ss:distanceandoffset}). -f- - -c+ -If you need to draw a series of curves end-to-end (when drawing a -contour line, for example), then a more efficient alternative is to -use astPolyCurve. This has the same effect as a sequence of -invocations of astCurve, but allows you to supply a whole set of -points at one time. astPolyCurve then joins them, in sequence, using -geodesic curves: -c- -f+ -If you need to draw a series of curves end-to-end (when drawing a -contour line, for example), then a more efficient alternative is to -use AST\_POLYCURVE. This has the same effect as a sequence of calls to -AST\_CURVE, but allows you to supply a whole set of points at the same -time. AST\_POLYLINE then joins them, in sequence, using geodesic -curves: -f- - -c+ -\small -\begin{terminalv} -#define NPOINT 100 -double coords[ NCOORD ][ NPOINT ]; - -... - -astPolyCurve( plot, NPOINT, NCOORD, NPOINT, coords ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER NPOINT - DOUBLE PRECISION COORDS( NPOINT, NCOORD ) - - ... - - CALL AST_POLYCURVE( PLOT, NPOINT, NCOORD, NPOINT, COORDS, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, NPOINT specifies how many points are to be joined and NCOORD -specifies how many coordinates are being supplied for each point. The -array ``coords'' supplies the coordinates of the points in the Plot's -physical coordinate system. -c- -f+ -Here, NPOINT specifies how many points are to be joined and NCOORD -specifies how many coordinates are being supplied for each point. The -array COORDS supplies the coordinates of the points in the Plot's -physical coordinate system. -f- - -\subsection{Plotting Curves Parallel to Axes} - -c+ -As there is no Plot function to draw a ``straight line'', drawing axes -and grid lines to represent coordinate systems requires a slightly -different approach. The problem is that for some coordinate systems, -these grid lines will not be geodesics, so astCurve and astPolyCurve -(\secref{ss:plottinggeodesics}) cannot easily be used (you would have -to resort to approximating grid lines by many small elements). Lines -of constant celestial latitude provide an example of this, with the -exception of the equator which is a geodesic. -c- -f+ -As there is no Plot routine to draw a ``straight line'', drawing axes -and grid lines to represent coordinate systems requires a slightly -different approach. The problem is that for some coordinate systems, -these grid lines will not be geodesics, so AST\_CURVE and -AST\_POLYCURVE (\secref{ss:plottinggeodesics}) cannot easily be used -(you would have to resort to approximating grid lines by many small -elements). Lines of constant celestial latitude provide an example of -this, with the exception of the equator which is a geodesic. -f- - -c+ -The astGridLine function allows these curves to be drawn, as follows: -c- -f+ -The AST\_GRIDLINE routine allows these curves to be drawn, as follows: -f- - -c+ -\small -\begin{terminalv} -int axis; -double length; - -... - -astGridLine( plot, axis, start, length ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER AXIS - DOUBLE PRECISION LENGTH - - ... - - CALL AST_GRIDLINE( PLOT, AXIS, START, LENGTH, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, ``axis'' specifies which physical coordinate axis we wish to -draw parallel to. The ``start'' array contains the coordinates of the -start of the curve and ``length'' specifies the distance to draw along -the axis in physical coordinate space. -c- -f+ -Here, AXIS specifies which physical coordinate axis we wish to draw -parallel to. The START array contains the coordinates of the start of -the curve and LENGTH specifies the distance to draw along the axis in -physical coordinate space. -f- - -\subsection{\label{ss:plottinggeneralizedcurves}Plotting Generalized Curves} -We have seen how geodesic curves and grid lines can be drawn. The Plot -class includes another method, -c+ -astGenCurve, -c- -f+ -AST\_GENCURVE, -f- -which allows curves of \emph{any} form to be drawn. The caller supplies a -Mapping which maps offset along the curve\footnote{normalized so that the -start of the curve is at offset 0.0 and the end of the curve is at offset -1.0 - offset need not be linearly related to distance.} into the -corresponding position in the current Frame of the Plot. -c+ -astGenCurve, -c- -f+ -AST\_GENCURVE, -f- -then takes care of Mapping these positions into graphics coordinates. The -choice of exactly which positions along the curve are to be used to -define the curve is also made by -c+ -astGenCurve, -c- -f+ -AST\_GENCURVE, -f- -using an adaptive algorithm which concentrates points around areas where -the curve is bending sharply or is discontinuous in graphics coordinates. - -The IntraMap class may be of particular use in this context since it allows -you to code your own Mappings to do any transformation you choose. - - -\subsection{\label{ss:clipping}Clipping} - -Like many graphics systems, a Plot allows you to \emph{clip} the graphics -you produce. This means that plotting is restricted to certain regions -of the plotting surface so that anything drawn outside these regions -will not appear. All Plots automatically clip at the edges of the -plotting area specified when the Plot is created. This means that -graphics are ultimately restricted to the rectangular region of -plotting space to which you have attached the Plot. - -In addition to this, you may also specify lower and upper limits on -each axis at which clipping should occur. This permits you to further -restrict the plotting region. Moreover, you may attach these clipping -limits to \emph{any} of the Frames in the Plot. This allows you to -place restrictions on where plotting will take place in either the -physical coordinate system, the graphical coordinate system, or in any -other coordinate system which is described by a Frame within the Plot. - -For example, you could plot using equatorial coordinates and set up -clipping limits in galactic coordinates. In general, you could set up -arbitrary clipping regions by adding a new Frame to a Plot (in which -clipping will be performed) and inter-relating this to the other -Frames in a suitable way. - -c+ -Clipping limits are defined using the astClip function, as follows: -c- -f+ -Clipping limits are defined using the AST\_CLIP routine, as follows: -f- - -c+ -\small -\begin{terminalv} -#define NAXES 2 -int iframe; -double lbnd[ NAXES ], ubnd[ NAXES ]; - -... -astClip( plot, iframe, lbnd, ubnd); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - INTEGER IFRAME, NAXES - DOUBLE PRECISION LBND( NAXES ), UBND( NAXES ) - - ... - - CALL AST_CLIP( PLOT, IFRAME, LBND, UBND, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, the ``iframe'' value gives the index of the Frame within the -Plot to which clipping is to be applied, while ``lbnd'' and ``ubnd'' -give the limits on each axis of the selected Frame (NAXES is the -number of axes in this Frame). -c- -f+ -Here, the IFRAME value gives the index of the Frame within the Plot to -which clipping is to be applied, while LBND and UBND give the limits -on each axis of the selected Frame (NAXES is the number of axes in -this Frame). -f- - -c+ -You can remove clipping by giving a value of AST\_\_NOFRAME for ``iframe''. -c- -f+ -You can remove clipping by giving a value of AST\_\_NOFRAME for IFRAME. -f- - -\subsection{Using a Plot as a Mapping} - -All Plots are also Mappings (just like the FrameSets from which they -are derived), so can be used to transform coordinates. - -Like FrameSets, the forward transformation of a Plot will convert -coordinates between the base and current Frames (\emph{i.e.}\ between -graphical and physical coordinates). This would be useful if you were -(say) reading a cursor position in graphical coordinates and needed to -convert this into physical coordinates for display. - -c+ -Conversely, a Plot's inverse transformation converts between its -current and base Frames (\emph{i.e.}\ from physical coordinates to -graphical coordinates). This transformation is applied automatically -whenever plotting operations are carried out by AST functions. It may -also be useful to apply it directly, however, if you wish to perform -additional plotting operations (\emph{e.g.}\ those provided by the -native graphics system) at positions specified in physical -coordinates. -c- -f+ -Conversely, a Plot's inverse transformation converts between its -current and base Frames (\emph{i.e.}\ from physical coordinates to -graphical coordinates). This transformation is applied automatically -whenever plotting operations are carried out by AST routines. It may -also be useful to apply it directly, however, if you wish to perform -additional plotting operations (\emph{e.g.}\ those provided by the -native graphics system) at positions specified in physical -coordinates. -f- - -c+ -There is, however, one important difference between using a FrameSet -and a Plot to transform coordinates, and this is that clipping may be -applied by a Plot (if it has been enabled using -astClip---\secref{ss:clipping}). Any point which lies within the -clipped region of a Plot will, when transformed, yield coordinates -with the value AST\_\_BAD. If you wish to avoid this clipping, you -should extract the relevant Mapping from the Plot (using -astGetMapping) and use this, instead of the Plot, to transform the -coordinates. -c- -f+ -There is, however. one important difference between using a FrameSet -and a Plot to transform coordinates, and this is that clipping may be -applied by a Plot (if it has been enabled using -AST\_CLIP---\secref{ss:clipping}). Any point which lies within the -clipped region of a Plot will, when transformed, yield coordinates -with the value AST\_\_BAD. If you wish to avoid this clipping, you -should extract the relevant Mapping from the Plot (using -AST\_GETMAPPING) and use this, instead of the Plot, to transform the -coordinates. -f- - -\subsection{Using a Plot as a Frame} - -Every Plot is also a Frame, so can be used to obtain the values of -Frame attributes such as a Title, axis Labels, axis Units, -\emph{etc.}, which are typically used when displaying data and/or -coordinates. These attributes are, as for any FrameSet, derived from -the current Frame of the Plot (\secref{ss:framesetasframe}). They are -also used automatically when using the Plot to plot coordinate axes -and coordinate grids (\emph{e.g.}\ for labelling -them---\secref{ss:plottingagrid}). - -c+ -Because the current Frame of a Plot represents physical coordinates, -any Frame operation applied to the Plot will effectively be working in -this coordinate system. For example, the astDistance and astOffset -functions will compute distances and offsets in physical coordinate -space, while astFormat and astNorm will format physical coordinates in -an appropriate way for display. -c- -f+ -Because the current Frame of a Plot represents physical coordinates, -any Frame operation applied to the Plot will effectively be working in -this coordinate system. For example, the AST\_DISTANCE and AST\_OFFSET -routines will compute distances and offsets in physical coordinate -space, and AST\_FORMAT will format physical coordinates in an -appropriate way for display. -f- - -\subsection{\label{ss:validphysicalcoordinates}Regions of Valid Physical Coordinates} - -When points in physical coordinate space are transformed by a Plot -into graphics coordinates for plotting, they may not always yield -valid coordinates, irrespective of any clipping being applied -(\secref{ss:clipping}). To indicate this, the resulting coordinate -values will be set to the value AST\_\_BAD -(\secref{ss:badcoordinates}). - -There are a number of reasons why this may occur, but typically it -will be because physical coordinates only map on to a subset of the -graphics coordinate space. This situation is commonly encountered with -all-sky projections where, typically, the celestial sphere appears, -when plotted, as a distorted shape (\emph{e.g.}\ an ellipse) which -does not entirely fill the graphics space. In some cases, there may -even be multiple regions of valid and invalid physical coordinates. - -When plotting is performed \emph{via} a Plot, graphical output will -only appear in the regions of valid physical coordinates. Nothing will -appear where invalid coordinates occur. Such output is effectively -clipped. If you wish to plot in these areas, you must change -coordinate system and use, say, graphical coordinates to address the -plotting surface directly. - -\subsection{Plotting Borders} - -c+ -The astBorder function is provided to draw a (line) border around your -graphical output. With most graphics systems, this would simply be a -rectangular box around the plotting area. With a Plot, however, this -boundary follows the edge of each region containing valid, unclipped -physical coordinates (\secref{ss:validphysicalcoordinates}). -c- -f+ -The AST\_BORDER routine is provided to draw a (line) border around -your graphical output. With most graphics systems, this would simply -be a rectangular box around the plotting area. With a Plot, however, -this boundary follows the edge of each region containing valid, -unclipped physical coordinates (\secref{ss:validphysicalcoordinates}). -f- - -c+ -This means, for example, that if you were plotting an all-sky -projection, this boundary would outline the perimeter of the celestial -sphere when projected on to your plotting surface. Of course, if there -is no clipping and all physical coordinates are valid, then you will -get the traditional rectangular box. astBorder requires only -a pointer to the Plot: -c- -f+ -This means, for example, that if you were plotting an all-sky -projection, this boundary would outline the perimeter of the celestial -sphere when projected on to your plotting surface. Of course, if there -is no clipping and all physical coordinates are valid, then you will -get the traditional rectangular box. AST\_BORDER requires only a -pointer to the Plot and the usual STATUS argument: -f- - -c+ -\small -\begin{terminalv} -int holes; - -... - -holes = astBorder( plot ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - LOGICAL HOLES - - ... - - HOLES = AST_BORDER( PLOT, STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -It returns a boolean (integer) value to indicate if any invalid or -clipped physical coordinates were found within the plotting area. If -they were, it will draw around the valid unclipped regions and return -a value of one. Otherwise, it will draw a simple rectangular border -and return zero. -c- -f+ -It returns a logical value to indicate if any invalid or clipped -physical coordinates were found within the plotting area. If they -were, it will draw around the valid unclipped regions and return -.TRUE.. Otherwise, it will draw a simple rectangular border and return -.FALSE.. -f- - -\subsection{Plotting Text} - -c+ -Using a Plot to draw text involves supplying a string of text to be -displayed and a position in physical coordinates where the text is to -appear. The position is transformed into graphical coordinates to -determine where the text should appear on the plotting surface. You -must also provide a 2-element ``up'' vector which gives the upward -direction of the text in graphical coordinates. This allows text to be -drawn at any angle. -c- -f+ -Using a Plot to draw text involves supplying a string of text to be -displayed and a position in physical coordinates where the text is to -appear. The position is transformed into graphical coordinates to -determine where the text should appear on the plotting surface. You -must also provide a 2-element UP vector which gives the upward -direction of the text in graphical coordinates. This allows text to be -drawn at any angle. -f- - -c+ -Plotting is performed by astText, for example: -c- -f+ -Plotting is performed by AST\_TEXT, for example: -f- - -c+ -\small -\begin{terminalv} -char text[ 21 ]; -double pos[ NCOORD ]; -float up[ 2 ] = { 0.0f, 1.0f }; - -... - -astText( plot, text, pos, up, "TL" ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CHARACTER * ( 20 ) TEXT - DOUBLE PRECISION POS( NCOORD ) - REAL UP( 2 ) - DATA UP / 0.0, 1.0 / - - ... - - CALL AST_TEXT( PLOT, TEXT, POS, UP, 'TL', STATUS ) -\end{terminalv} -\normalsize -f- - -c+ -Here, ``text'' contains the string to be drawn, ``pos'' is an array of -physical coordinates and ``up'' specifies the upward vector. In this -case, the text will be drawn horizontally. The final argument -specifies the text justification, here indicating that the top left -corner of the text should appear at the position given. -c- -f+ -Here, TEXT contains the string to be drawn, POS is an array of -physical coordinates and UP specifies the upward vector. In this case, -the text will be drawn horizontally. The penultimate argument -specifies the text justification, here indicating that the top left -corner of the text should appear at the position given. -f- - -Further control over the appearance of the text is possible by setting -values for various Plot attributes, for example Colour, Font and Size. -Sub-strings within the displayed text can be given different appearances, -or turned into super-scripts or sub-scripts, by the inclusion of escape -sequences (see section~\secref{ss:escapes}) within the supplied text string. - -\subsection{\label{ss:plottingagrid}Plotting a Grid} - -c+ -The most comprehensive plotting function available is astGrid, which -can be used to draw labelled coordinate axes and, optionally, to -overlay coordinate grids on the plotting area -(Figure~\ref{fig:gridplot}). The routine is straightforward to use, -simply requiring a pointer to the Plot: -c- -f+ -The most comprehensive plotting routine available is AST\_GRID, which -can be used to draw labelled coordinate axes and, optionally, to -overlay coordinate grids on the plotting area -(Figure~\ref{fig:gridplot}). The routine is straightforward to use, -simply requiring a pointer to the Plot and a STATUS argument: -f- - -c+ -\small -\begin{terminalv} -astGrid( plot ); -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} - CALL AST_GRID( PLOT, STATUS ) -\end{terminalv} -\normalsize -f- - -It will draw both linear and curvilinear axes and grids, as required -by the particular Plot. The appearance of the output can be modified -in a wide variety of ways by setting various Plot attributes. -The Label attributes of the current Frame are displayed as the axis -labels in the grid, and the Title attribute as the plot title. Sub-strings -within these strings can be given different appearances, or turned into -super-scripts or sub-scripts, by the inclusion of escape sequences (see -section~\secref{ss:escapes}) within the Label attributes. - -\subsection{\label{ss:escapes}Controlling the Appearance of Sub-strings} -Normally, each string of characters displayed using a Plot will be -plotted so that all characters in the string have the same font size, -colour, \emph{etc.}, specified by the appropriate attributes of the -Plot. However, it is possible to include \emph{escape sequences} within -the text to modify the appearance of sub-strings. Escape sequences can be -used to change, colour, font, size, width, to introduce extra horizontal -space between characters, and to change the base line of characters (thus -allowing super-scripts and sub-scripts to be created). See the entry for -the Escape attribute in \appref{ss:attributedescriptions} for details. - -As an example, if the character string ``\verb+10\%^50+\%s70+0.5+'' is -plotted, it will be displayed as ``$10^{0.5}$'' - that is, with a -super-scripted exponent. The exponent text will be 70\% of the size of -normal text (as determined by the Size attribute), and its baseline will -be raised by 50\% of the height of a normal character. - -Such escape sequences can be used in the strings assigned to textual -attributes of the Plot (such as the axis Labels), and may also be -included in strings plotted using -c+ -astText. -c- -f+ -AST\_TEXT. -f- - -The Format attribute for the SkyAxis class includes the ``g'' option -which will cause escape sequences to be included when formatting -celestial positions so that super-script characters are used as -delimiters for the various fields (a super-script ``h'' for hours, ``m'' -for minutes, \emph{etc}). - -Note, the facility for interpreting escape sequences is only available if -the graphics wrapper functions which provide the interface to the -underlying graphics system support all the functions included in the -\verb+grf.h+ file as of AST V3.2. Older grf interfaces may need to be -extended by the addition of new functions before escape sequences can be -interpretted. - -\subsection{\label{ss:logaxes}Producing Logarithmic Axes} -In certain situations you may wish for one or both of the plotted axes to -be displayed logarithmically rather than linearly. For instance, you may -wish to do this when using a Plot to represent a spectrum of, say, flux -against frequency. In this case, you can cause the frequency axis to be drawn -logarithmically simply by setting the boolean LogPlot attribute for the -frequency axis to a non-zero value. This causes several things to happen: - -\begin{enumerate} - -\item The Mapping between the base Frame of the Plot (which represents -the underlying graphics world coordinate system) and the base Frame of -the FrameSet supplied when the Plot was created, is modified. By -default, this mapping is linear on both axes, but setting LogPlot non-zero -for an axis causes the Mapping to be modified so that it is logarithmic -on the specified axis. This is only possible if the displayed section of -the axis does not include the value zero (otherwise the attempt to set -a new value for LogPlot is ignored,and it retains its default value of -zero). - -\item The major tick marks drawn as part of the annotated coordinate grid -are spaced logarithmically rather than linearly. That is, major axis -values are chosen so that there is a constant ratio between adjacent -tick mark values. This ratio is constrained to be a power of ten. The -minor tick marks are drawn at linearly distributed points between the -adjoining major tick values. Thus if a pair of adjacent major tick values -are drawn at axis values 10.0 and 100.0, minor ticks will be placed at -20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0 and 90.0 (note only 8 minor tick -marks are drawn). - -\item If possible, numerical axis labels are shown as powers of ten. -This depends on the facilities implemented by the graphics wrapper -functions (see the next section). Extra functions were introduced to this -set of wrapper functions at AST V3.2 which enable super-scripts and -sub-scripts to be produced. Some older wrappers may not yet have -implemented these functiosn and this will result in axis labels being -drawn in usual scientific or decimal notation. - -\end{enumerate} - -Whilst the LogPlot attribute can be used to control all three of the above -facilities, it is possible to control them individually as well. The -LogTicks and LogLabel attributes control the behaviour specified in items -2 and 3 above, but the default values for these attributes depend on the -setting of the LogPlot attribute. This means that setting LogPlot -non-zero will swicth all three facilites on, so long as zero values have -not been assigned explicitly to LogTicks or LogLabel. - - -\subsection{\label{ss:choosingagraphicspackage}Choosing a Graphics Package} -The Plot class itself does not include any code for actually drawing on a -graphics device. Instead, it requires a set of functions to be provided -which it uses to draw the required graphics. These include functions -to draw a straight line, draw a text string, \emph{etc}. You may choose -to provide functions from your favorite graphics package, or you can even -write your own! To accomodate variations in the calling interfaces of -different graphics packages, AST defines a standard interface for these -routines. If this interface differs from the interface provided by your -graphics package (which in general it will), then you must write a set of -\emph{wrapper functions}, which provide the interface expected by AST but -which then call functions from your graphics package to provide the -required functionality. AST comes with wrapper functions suitable for -the PGPLOT graphics package (see \xref{SUN/15}{sun15}{}). - -There are two ways of indicating which wrapper functions are to be used by -the Plot class: -\begin{enumerate} - -\item A file containing C functions with pre-defined names can be written -and linked with the application using options of the ast\_link command. -(see \secref{ss:howtobuild} and \appref{ss:commanddescriptions}). AST is -distributed with such a file (called \texttt{grf\_pgplot.c}) which calls PGPLOT -functions to implement the required functionality. This file can be used -as a template for writing your own. -f+ -Currently, it is not possible to write such ``grf modules'' in Fortran. -If you want to use wrapper functions written in Fortran, then you must -use the AST\_GRFSET method as described below. -f- - -\item The -c+ -astGrfSet -c- -f+ -AST\_GRFSET -f- -method of the Plot class can be used to ``register'' -wrapper functions at run-time. This allows an application to switch -between graphics systems if required. Graphics functions registered in -this way do not need to have the pre-defined names used in the link-time -method described above. - -\end{enumerate} - -For details of the interfaces of the wrapper routines, see -c+ -either the \texttt{grf\_pgplot.c} file included in the AST source -distribution, or the reference documentation for the astGrfSet method. -c- -f+ -the reference documentation for the AST\_GRFSET method. -f- - -\cleardoublepage -\section{Compiling and Linking Software that Uses AST} - -A small number of UNIX commands are provided by AST to assist with the -process of building software. A description of these can be found in -\appref{ss:commanddescriptions} and their use is discussed here. Note -that in order to access these commands, the appropriate directory -(normally ``/star/bin'') should be on your PATH.\footnote{If you have -not installed AST in the usual location, then substitute the -appropriate directory in place of ``/star'' wherever it occurs.} - -c+ -\subsection{\label{ss:accessingheaderfile}Accessing the ``ast.h'' Header File} -c- -f+ -\subsection{\label{ss:accessingheaderfile}Accessing AST Include Files} -f- - -c+ -The ``ast.h'' header file defines the external interface to the AST library, -including all constants, function prototypes, macros, \emph{etc.}. This file -should be located using the usual compiler options for finding C -include files, for instance: - -\small -\begin{terminalv} -cc prog.c -I/star/include -o prog -\end{terminalv} -\normalsize - -This is preferable to specifying the file's absolute name within your -software. -c- -f+ - -The include files provided for use with Fortran are: - -\begin{quote} -\begin{description} -\item[AST\_PAR]\mbox{}\\ -Declares the types of all AST functions and defines parameter -constants, except those that identify error values. - -\item[AST\_ERR]\mbox{}\\ -Defines parameter constants to represent the various error values to -which the AST error status may be set when an error occurs -(\secref{ss:errordetection}). -\end{description} -\end{quote} - -References to AST include files should be in upper case. Most modern -Fortran compilers allow the directory to be specified as a command line -option: - -\small -\begin{terminalv} -f77 prog.f -I/star/include -o prog -\end{terminalv} -\normalsize - -If you are using such a compiler then your Fortran source code should, -for instance, include: - -\small -\begin{terminalv} - INCLUDE 'AST_PAR' -\end{terminalv} -\normalsize - -(that is, there is no need to include the directory within the INCLUDE -statement). If your compiler does not provide such an option then your -source code must contain an absolute file name identifying the directory -where the include files reside, for instance: - -\small -\begin{terminalv} - INCLUDE '/star/include/AST_PAR' -\end{terminalv} -\normalsize - -f- - -\subsection{\label{ss:linking}Linking with AST Facilities} - -c+ -C programs which use AST facilities may be linked by including -execution of the command ``ast\_link'' on the compiler command -line. Thus, to compile and link a program called ``prog'', the -following might be used: -c- -f+ -Fortran programs may be linked with AST by including execution of the -command ``ast\_link'' on the compiler command line. Thus, to compile -and link a program called ``prog'', the following might be used: -f- - -c+ -\small -\begin{terminalv} -cc prog.c -L/star/lib `ast_link` -o prog -\end{terminalv} -\normalsize -c- -f+ -\small -\begin{terminalv} -f77 prog.f -L/star/lib `ast_link` -o prog -\end{terminalv} -\normalsize - -On Linux systems you should usually use \verb+g77 -fno-second-underscore+ in -place of \verb+f77+ - see \xref{``Software development on Linux''}{sun212} -{software_development_on_linux} in \xref{SUN/212}{sun212}{}. - -f- - -Note the use of backward quote characters, which cause the -``ast\_link'' command to be executed and its result substituted into -the compiler command. An alternative is to save the output from -``ast\_link'' in (say) a shell variable and use this instead. You may -find this a little faster if you are building software repeatedly -during development. - -Programs which use AST can also be linked in a number of other ways, -depending on the facilities they require. In the example above, we -have used the default method which assumes that the program will not -be generating graphical output, so that no graphics libraries need be -linked. If you need other facilities, then various switches can be -applied to the ``ast\_link'' command in order to control the linking -process. - -For example, if you were producing graphical output using the PGPLOT -graphics package, you could link with the AST/PGPLOT interface by -using the ``$-$pgplot'' switch with ``ast\_link'', as -follows:\footnote{Use the ``$-$pgp'' option instead if you wish to use -the Starlink version of PGPLOT which uses GKS to generate its output.} - -c+ -\small -\begin{terminalv} -cc prog.c -L/star/lib `ast_link -pgplot` -o prog -\end{terminalv} -\normalsize -c- -f+ -\begin{small} -\begin{terminalv} -f77 prog.f -L/star/lib `ast_link -pgplot` -o prog -\end{terminalv} -\end{small} - -again using \verb+g77 -fno-second-underscore+ in place of \verb+f77+ -on Linux systems. - -f- - -See the ``ast\_link'' command description in -\appref{ss:commanddescriptions} for details of the options available. - -\subsection{Building ADAM Applications that Use AST} - -Users of Starlink's \xref{ADAM}{sg4}{} programming environment -\latex{(SG/4)} on UNIX should use the -``\xref{alink}{sun144}{ADAM_link_scripts}'' command -(\xref{SUN/144}{sun144}{}) to compile and link applications and can -access the AST library by including execution of the command -``ast\_link\_adam'' on the command line, as follows: - -c+ -\begin{small} -\begin{terminalv} -alink adamprog.c `ast_link_adam` -\end{terminalv} -\end{small} -c- -f+ -\begin{small} -\begin{terminalv} -alink adamprog.f `ast_link_adam` -\end{terminalv} -\end{small} -f- - -Note the use of backward quote characters. - -By default, AST error messages produced by applications built in this -way will be delivered \emph{via} the Starlink EMS Error Message -Service (\xref{SSN/4}{ssn4}{}) so that error handling by AST is -consistent with the \xref{\emph{inherited -status}}{sun104}{inherited_status} error handling normally used in -Starlink software. - -Switches may be given to the ``ast\_link\_adam'' command (in a similar -way to ``ast\_link''---\secref{ss:linking}) in order to link with -additional AST-related facilities, such as a graphics interface. See -the ``ast\_link\_adam'' command description in -\appref{ss:commanddescriptions} for details of the options available. - -\appendix -\cleardoublepage -\section{\label{ss:classhierarchy}The AST Class Hierarchy} -The following table shows the hierarchy of classes in the AST library. -For a description of each class, you should consult -\appref{ss:classdescriptions}. - -\small -\begin{terminalv} -Object - Base class for all AST Objects - Axis - Store axis information - SkyAxis - Store celestial axis information - Channel - Basic (textual) I/O channel - FitsChan - I/O Channel using FITS header cards - XmlChan - I/O Channel using XML - StcsChan - I/O Channel using IVOA STC-S descriptions - KeyMap - Store a set of key/value pairs - Table - Store a 2-dimensional table of values - Mapping - Inter-relate two coordinate systems - CmpMap - Compound Mapping - DssMap - Map points using Digitised Sky Survey plate solution - Frame - Coordinate system description - CmpFrame - Compound Frame - SpecFluxFrame - Observed value versus spectral position - FluxFrame - Observed value at a given fixed spectral position - FrameSet - Set of inter-related coordinate systems - Plot - Provide facilities for 2D graphical output - Plot3D - Provide facilities for 3D graphical output - Region - Specify areas within a coordinate system - Box - A box region with sides parallel to the axes of a Frame - Circle - A circular or spherical region within a Frame - CmpRegion - A combination of two regions within a single Frame - Ellipse - An elliptical region within a 2-dimensional Frame - Interval - Intervals on one or more axes of a Frame. - NullRegion - A boundless region within a Frame - PointList - A collection of points in a Frame - Polygon - A polygonal region within a 2-dimensional Frame - Prism - An extrusion of a Region into orthogonal dimensions - Stc - Represents an generic instance of an IVOA STC-X description - StcResourceProfile - Represents an an IVOA STC-X ResourceProfile - StcSearchLocation - Represents an an IVOA STC-X SearchLocation - StcCatalogEntryLocation - Represents an an IVOA STC-X CatalogEntryLocation - StcObsDataLocation - Represents an an IVOA STC-X ObsDataLocation - SkyFrame - Celestial coordinate system description - SpecFrame - Spectral coordinate system description - DSBSpecFrame - Dual sideband spectral coordinate system description - TimeFrame - Time coordinate system description - GrismMap - Models the spectral dispersion produced by a grism - IntraMap - Map points using a private transformation function - LutMap - Transform 1-dimensional coordinates using a lookup table - MathMap - Transform coordinates using mathematical expressions - MatrixMap - Map positions by multiplying them by a matrix - NormMap - Normalise coordinates using a supplied Frame - PcdMap - Apply 2-dimensional pincushion/barrel distortion - PermMap - Coordinate permutation Mapping - PolyMap - General N-dimensional polynomial Mapping - RateMap - Calculates an element of a Mapping's Jacobian matrix - SelectorMap - Locates positions within a set of Regions - ShiftMap - Shifts each axis by a constant amount - SlaMap - Sequence of celestial coordinate conversions - SpecMap - Sequence of spectral coordinate conversions - SphMap - Map 3-d Cartesian to 2-d spherical coordinates - SwitchMap - Encapuslates a set of alternate Mappings - TimeMap - Sequence of time coordinate conversions - TranMap - Combine fwd. and inv. transformations from two Mappings - UnitMap - Unit (null) Mapping - WcsMap - Implement a FITS-WCS sky projection - WinMap - Match windows by scaling and shifting each axis - ZoomMap - Zoom coordinates about the origin -\end{terminalv} -\normalsize - -\cleardoublepage -c+ -\section{\label{ss:functiondescriptions}AST Function Descriptions} -\small -\include{c_routines} -\normalsize -c- -f+ -\section{\label{ss:functiondescriptions}AST Routine Descriptions} -\small -\include{f_routines} -\normalsize -f- - -\cleardoublepage -\section{\label{ss:attributedescriptions}AST Attribute Descriptions} -\small -c+ -\include{c_attribs} -c- -f+ -\include{f_attribs} -f- -\normalsize - -\cleardoublepage -\section{\label{ss:classdescriptions}AST Class Descriptions} -\small -c+ -\include{c_classes} -c- -f+ -\include{f_classes} -f- -\normalsize - -\cleardoublepage -\section{\label{ss:commanddescriptions}UNIX Command Descriptions} -The commands described here are provided for use from the UNIX shell -to assist with developing software which uses AST. To use these -commands, you should ensure that the directory -``/star/bin''\footnote{Or the equivalent directory if AST is installed -in a non-standard location.} is on your PATH. -\small -c+ -\include{c_commands} -c- -f+ -\include{f_commands} -f- -\normalsize - -c+ -\cleardoublepage -\section{\label{ss:memoryfunctions}AST Memory Management and Utility Functions} -AST provides a memory management layer that can be used in place of -system functions such as \texttt{malloc}, \texttt{free}, \texttt{realloc}, -\emph{etc.} The AST replacements for these functions ( \texttt{astMalloc}, -\texttt{astFree} and \texttt{astRealloc}) add extra information to each -allocated memory block that allows AST to check the validity of supplied -pointers. For example, this extra information allows \texttt{astFree} to -detect if the supplied pointer has already been freed, and if so to issue -an appropriate error message. The existence of this extra information is -invisible to outside callers, and stored in a header block located just -before the returned memory block. - -In addition to the standard functions, AST provides other memory management -functions, such as: - -\begin{description} -\item [\texttt{astStore}] - stores data in dynamically allocated memory, allocating -the memory (or adjusting the size of previously allocated memory) to match -the amount of data to be stored. -\item [\texttt{astGrow}] - allocates and expands memory to hold an adjustable-sized array. -\item [\texttt{astAppendString}] - allocates and expands memory to hold a -concatenated string. -\end{description} - -Theses are just a few of the available utilities functions in the AST -memory management layer. Prototypes for all AST memory management -functions are included in the header file ``\texttt{ast.h}''. - -An important restriction on these functions is that pointers created by -other memory management functions, such as the system version of \texttt{malloc} \emph{etc.}, should never supplied to an AST memory management -function. Only pointers created by AST should be used by these functions. - -In addition to memory management functions, AST provides various other -utility functions, such as a basic regular expression facility, and other -string manipulation functions. These are also documented in this appendix. - -The AST memory management layer is implemented on top of the usual \texttt{malloc}, {tt free} and \texttt{realloc} functions. By default these will be -the standard functions provided by <stdlib.h>. However, the facilities of -the STARMEM package (included in the Starlink Software Collection) can be -used to specify alternative functions to use. This requires that AST be -configured using the ``--with-starmem'' option when it is built. - -The STARMEM package provides a wrapper for the standard malloc -implementation that enables the user to switch malloc schemes at runtime -by setting the STARMEM\_MALLOC environment variable. Currently allowed -values for this variable are: - -\begin{description} -\item [SYSTEM] - standard system malloc/free - the default -\item [DL] - Doug Lea's malloc/free -\item [GC] - Hans-Boehm Garbage Collection -\end{description} - -\small -\include{memory_routines} -\normalsize -c- - -\newpage -\section{\xlabel{FitsWcsCoverage}\label{ss:fitswcscoverage}FITS-WCS Coverage} - -This appendix gives details of the FitsChan class -implementation of the conventions described in the FITS-WCS papers -available at -\url{http://fits.gsfc.nasa.gov/fits_wcs.html}. These conventions are -used only if the Encoding attribute of the FitsChan -has the value ``FITS-WCS'' (whether set explicitly or defaulted). It -should always be possible for a FrameSet to be read -(using the -c+ -astRead -c- -f+ -AST\_READ -f- -function) from a FitsChan containing a header which conforms to these -conventions. However, only those FrameSets which are compatible with the -FITS-WCS model can be \emph{written} to a FitsChan using the -c+ -astWrite -c- -f+ -AST\_WRITE -f- -function. For instance, if the current Frame of a -FrameSet is re-mapped using, say, an arbitrary MathMap -then the FrameSet will no longer be compatible with the FITS-WCS model, -and so will not be written out successfully to a FitsChan. - -The following sub-sections describe the details of the implementation of -each of the first four FITS-WCS papers. Here, the term ``pixel axes'' is -used to refer to the FITS pixel coordinates (i.e. the centre of the -first image pixel has a value 1.0 on each pixel axis); the term ``IWC -axes'' is used to refer to the axes of the Intermediate World Coordinate -system; and the term ``WCS axes'' is used to refer to the axes of the final -physical coordinate system described by the CTYPE\emph{i} keywords. - -\subsection{Paper I - General Linear Coordinates} -When reading a FrameSet from a FitsChan, these conventions are used if the CTYPE\emph{i} keyword -values within the FitsChan do not conform to the conventions described in -later papers, in which case the axes are assumed to be linear. When -writing a FrameSet to a FitsChan, these conventions are used for axes -which are described by a simple Frame (\emph{i.e.} not a -SkyFrame, SpecFrame, \emph{etc.}). - -Table \ref{tab:fitspaper1} describes the use made by AST of each keyword -defined by FITS-WCS paper I. - -\begin{table}[htbp] -\begin{tabular}{|l|p{2.5in}|p{2.5in}|} -\hline -\multicolumn{1}{|c|}{\textbf{Keyword}} & \multicolumn{1}{c|}{\textbf{Read}} -& \multicolumn{1}{c|}{\textbf{Write}} \\ \hline - -\fitskey{WCSAXES\emph{a}}{Ignored.}{Set to the number of axes in the WCS -Frame - only written if different to NAXIS.} - -\fitskey{CRVAL\emph{ia}}{Used to create the pixel to WCS -Mapping.}{Always written (see ``Choice of Reference -Point'' below).} - -\fitskey{CRPIX\emph{ja}}{Used to create the pixel to WCS Mapping.}{Always -written (see ``Choice of Reference Point'' below).} - -\fitskey{CDELT\emph{ia}}{Used to create the pixel to WCS Mapping.}{Only -written if the CDMatrix attribute of the FitsChan is -set to zero.} - -\fitskey{CROTA\emph{i}}{Used to create the pixel to WCS Mapping.}{Only -written in FITS-AIPS and FITS-AIPS++ encodings.} - -\fitskey{CTYPE\emph{ia}}{Used to choose the class and attributes of the -WCS Frame, and to create the pixel to WCS Mapping (note, ``STOKES'' and -``COMPLEX'' axes are treated as unknown linear axes).}{Always written -(see ``Use and Choice of CTYPE keywords'' below).} - -\fitskey{CUNIT\emph{ia}}{Used to set the Units attributes -of the WCS Frame.}{Only written if the Units attribute of the WCS Frame -has been set explicitly. If so, the Units value for each axis is used as -the CUNIT value.} - -\fitskey{PC\emph{i\_j}\emph{a}}{Used to create the pixel to WCS -Mapping.}{Only written if the CDMatrix attribute of the FitsChan is set to -zero.} - -\fitskey{CD\emph{i\_j}\emph{a}}{Used to create the pixel to WCS -Mapping.}{Only written if the CDMatrix attribute of the FitsChan is set to -a non-zero value.} - -\fitskey{PV\emph{i\_ma}}{Ignored for linear axes.}{Not written if the axes -are linear.} - -\fitskey{PS\emph{i\_ma}}{Ignored.}{Not used.} - -\fitskey{WCSNAME\emph{a}}{Used to set the Domain attribute -of the WCS Frame.}{Only written if the Domain attribute of the WCS Frame -has been set explicitly. If so, the Domain value is used as the WCSNAME -value.} - -\fitskey{CRDER\emph{ia}}{Ignored.}{Not used.} - -\fitskey{CSYER\emph{ia}}{Ignored.}{Not used.} - -\hline -\end{tabular} -\vspace{3.mm} -\caption{Use of FITS-WCS Paper I keywords} -\label{tab:fitspaper1} -\end{table} - -\subsubsection{Requirements for a Successful Write Operation} -When writing a FrameSet in which the WCS -Frame is a simple Frame to a FitsChan, -success depends on the Mapping from pixel coordinates -(the base Frame in the FrameSet) to the WCS Frame being linear. The write -operation will fail if this is not the case. - -\subsubsection{Use and Choice of CTYPE\emph{i} keywords} -When reading a FrameSet from a FitsChan the CTYPE\emph{i} values in the FitsChan are used to set the -Symbol attributes of the corresponding WCS Frame. The Label attributes of the WCS Frame are set from -the CNAME\emph{i} keywords, if present in the header. Otherwise they are set -from the CTYPE\emph{i} comments strings in the header, so long as each -axis has a unique non-blank comment. Otherwise, the Label attributes are -set to the CTYPE\emph{i} values. The above procedure is over-ridden if -the axis types conform to the conventions described in paper II or III, -as described below. - -When writing a FrameSet to a FitsChan, each CTYPE\emph{i} value is set to -the value of the Symbol attribute of the corresponding axis in the Frame -being written. If a value has been set explicitly for the axis Label -attribute, it is used as the axis comment (except that any existing -comments in the FitsChan take precedence if the keyword value has not -changed). The above procedure is over-ridden if the Frame is a -SkyFrame or a SpecFrame, in which -case the CTYPE\emph{i} value is derived from the System -attribute of the Frame and the nature of the pixel to WCS Mapping -according to the conventions of papers II and III, as described below. - -\subsubsection{Choice of Reference Point} -When writing a FrameSet to a -FitsChan, the pixel coordinates of the -reference point for linear axes (i.e. the CRPIX\emph{j} values) are -chosen as follows: - -\begin{itemize} -\item If the FrameSet is being written to a FitsChan which previously -contained a set of axis descriptions with the same identifying letter, -then the previous CRVAL\emph{j}values are converted into the coordinate system -of the Frame being written (if possible). These values are then -transformed into the pixel Frame, and the closest integer pixel values -are used as the CRPIX keywords. -\item If the above step could not be performed for any reason, the -central pixel is used as the reference point. This requires the image -dimensions to be present in the FitsChan in the form of a set of -NAXIS\emph{j} keyword values. -\item If both the above two steps failed for any axis, then the pixel -reference position is set to a value of 1.0 on the pixel axis. -\end{itemize} - -The pixel to WCS Mapping is then used to find the corresponding -CRVAL\emph{j}values. - -Again, the above procedure is over-ridden if the Frame is a -SkyFrame or a SpecFrame, in which -case the conventions of papers II and III are used as described below. - - -\subsubsection{Choice of Axis Ordering} -When reading a FrameSet from a -FitsChan, WCS axis $i$ in the current -Frame of the -resulting FrameSet corresponds to axis $i$ in the FITS header. - -When writing a FrameSet to a FitsChan, the axis ordering for the FITS -header is chosen to make the CD\emph{i\_j} or PC\emph{i\_j} matrix -predominately diagonal. This means that the axis numbering in the FITS -header will not necessarily be the same as that in the AST Frame. - -\subsubsection{Alternate Axis Descriptions} -When reading a FrameSet from a -FitsChan which contains alternate axis descriptions, -each complete set of axis descriptions results in a single Frame being added -to the final FrameSet, connected via an appropriate -Mapping to the base pixel Frame. The Ident attribute of the Frame is set to hold the single alphabetical -character which is used to identify the set of axis descriptions within -the FITS header (a single space is used for the primary axis descriptions). - -When writing a FrameSet to a FitsChan, it is assumed that the base Frame -represents pixel coordinates, and the current Frame represents the -primary axis descriptions. If there are any other Frames present in the -FrameSet, an attempt is made to create a complete set of ``alternate'' -set of keywords describing each additional Frame. The first character in -the Ident attribute of the Frame is used as the single character -descriptor to be appended to the keyword, with the proviso that a given -character can only be used once. If a second Frame is found with an Ident -attribute which has already been used, its Ident attribute is ignored and -the next free character is used instead. Note, failure to write a set of -alternate axis descriptions does not result in failure of the entire -write operation: the primary axis descriptions are still written, -together with any other alternate axis descriptions which can be produced -successfully. - -\subsection{Paper II - Celestial Coordinates} -These conventions are used when reading a FrameSet -from a FitsChan containing appropriate CTYPE\emph{i} -values, and when writing a FrameSet in which the WCS Frame -is a SkyFrame. - -Table \ref{tab:fitspaper2} describes the use made by AST of each keyword -whose meaning is defined or extended by FITS-WCS paper II. - -\begin{table}[htbp] -\begin{tabular}{|l|p{2.5in}|p{2.5in}|} -\hline -\multicolumn{1}{|c|}{\textbf{Keyword}} & \multicolumn{1}{c|}{\textbf{Read}} -& \multicolumn{1}{c|}{\textbf{Write}} \\ \hline - -\fitskey{CTYPE\emph{ia}}{All coordinate systems and projection types -listed in paper II are supported (note, ``CUBEFACE'' axes are treated as -unknown linear axes). In addition, "-HPX" (HEALPix) and "-XPH" (polar -HEALPix) are supported.}{Determined by the System attribute -of the SkyFrame and the WcsType attribute of the -WcsMap within the FrameSet.} - -\fitskey{CUNIT\emph{ia}}{Ignored (assumed to be 'degrees').}{Not written.} - -\fitskey{PV\emph{i\_ma}}{Used to create the pixel to WCS Mapping (values -are stored as attributes of a WcsMap within this Mapping).}{Values are -obtained from the WcsMap in the pixel to WCS Mapping.} - -\fitskey{LONPOLE\emph{a}}{Used to create the pixel to WCS Mapping. Also -stored as a PVi\_m attribute for the longitude axis of the WcsMap.}{Only -written if not equal to the default value defined in paper II (see -``Choice of LONPOLE/LATPOLE'' below).} - -\fitskey{LATPOLE\emph{a}}{Used to create the pixel to WCS Mapping. Also -stored as a PV attribute for the longitude axis of the WcsMap.}{Only -written if not equal to the default value defined in paper II (see -``Choice of LONPOLE/LATPOLE'' below).} - -\fitskey{RADESYS\emph{a}}{Used to set the attributes of the SkyFrame. All -values supported except that ecliptic coordinates are currently always -assumed to be FK5.}{Always written. Determined by the System attribute of -the SkyFrame.} - -\fitskey{EQUINOX\emph{a}}{Used to set the Equinox attribute -of the SkyFrame.}{Written if relevant. Determined by the Equinox attribute of -the SkyFrame.} - -\fitskey{EPOCH}{Used to set the Equinox attribute of the SkyFrame.}{Only -written if using FITS-AIPS and FITS-AIPS++ encodings. Determined by the Equinox attribute -of the SkyFrame.} - -\fitskey{MJD-OBS}{Used to set the Epoch attribute of the -SkyFrame. DATE-OBS is used if MJD-OBS is not present. A default value based on -RADESYS and EQUINOX is used if used if DATE-OBS is not present -either.}{Determined by the Epoch attribute of the SkyFrame. Only written -if this attribute has been set to an explicit value (in which case -DATE-OBS is also written).} - -\hline -\end{tabular} -\vspace{3.mm} -\caption{Use of FITS-WCS Paper II keywords} -\label{tab:fitspaper2} -\end{table} - -\subsubsection{Requirements for a Successful Write Operation} -When writing a FrameSet in which the WCS -Frame is a SkyFrame to a -FitsChan, success depends on the following conditions -being met: - -\begin{enumerate} -\item The Mapping from pixel coordinates (the base Frame -in the FrameSet) to the WCS SkyFrame includes a WcsMap. -\item The Mapping prior to the WcsMap (\emph{i.e.} from pixel to IWC) is linear. -\item The Mapping after the WcsMap (\emph{i.e.} from native spherical to -celestial coordinates) is a spherical rotation for the -celestial axes, and linear for any other axes. -\item The TabOK attribute is set to a non-zero positive value in the FitsChan, -and the longitude and latitude axes are separable. In this case the Mapping will -be described by a pair of 1-dimensional look-up tables, using the ``-TAB'' -algorithm described in FITS-WCS paper III. -\end{enumerate} - -If none of the above conditions hold, the write operation will be -unsuccessful. - -\subsubsection{Choice of LONPOLE/LATPOLE} -When writing a FrameSet to a FitsChan, -the choice of LONPOLE and LATPOLE values is determined as follows: - -\begin{enumerate} - -\item If the projection represented by the WcsMap is -azimuthal, then any values set for attributes ``PV\emph{i}\_3'' -and ``PV\emph{i}\_4'' (where ``\emph{i}'' is the index of the longitude axis) -within the WcsMap are used as the LONPOLE and LATPOLE values. Reading a -FrameSet from a FITS-WCS header -results in the original LONPOLE and LATPOLE values being stored within a -WcsMap within the FrameSet. Consequently, if a FrameSet is read from a -FITS-WCS header and it is subsequently written out to a new FITS-WCS -header, the original LONPOLE and LATPOLE values will usually be used in -the new header (the exception being if the WcsMap has been explicitly -modified before being written out again). Any extra rotation of the sky -is absorbed into the CD\emph{i\_j} or PC\emph{i\_j} matrix (this is -possible only if the projection is azimuthal). - -\item If the projection represented by the WcsMap is azimuthal but no -values have been set for the ``PV\emph{i}\_3'' and ``PV\emph{i}\_4'' -attributes within the WcsMap, then the default LONPOLE and LATPOLE values -are used. This results in no LONPOLE or LATPOLE keywords being stored in -the header since default values are never stored. Any extra rotation of -the sky is absorbed into the CD\emph{i\_j} or PC\emph{i\_j} matrix (this -is possible only if the projection is azimuthal). - -\item If the projection represented by the WcsMap is not azimuthal, -then the values of LONPOLE and LATPOLE are found by transforming the -coordinates of the celestial north pole (\emph{i.e} longitude zero, -latitude $+\pi/2$) into native spherical coordinates using the inverse of -the Mapping which follows the WcsMap. - -\end{enumerate} - -\subsubsection{User Defined Fiducial Points} -When reading a FrameSet from a FitsChan, projection parameters -PV\emph{i}\_0, PV\emph{i}\_1 and PV\emph{i}\_2 (for longitude axis -``\emph{i}'') are used to indicate a user-defined fiducial point as -described in section 2.5 of paper II. This results in a shift of IWC -origin being applied \emph{before} the WcsMap which converts -IWC into -native spherical coordinates. The values of these projection parameters, -if supplied, are stored as the corresponding PVi\_m attributes -of the WcsMap. - -When writing a FrameSet to a FitsChan, the PV attributes of the WcsMap -determine the native coordinates of the fiducial point (the fixed -defaults for each projection described in paper II are used if the PV -attributes of the WcsMap have not been assigned a value). The -corresponding celestial coordinates are used as the CRVAL\emph{i} -keywords and the corresponding pixel coordinates as the CRPIX\emph{j} -keywords. - -\subsubsection{Common Non-Standard Features} -A collection of common non-standard features are supported when reading a -FrameSet from a FitsChan, in addition -to those embodied within the -available encodings of the FitsChan class. These are translated into the -equivalent standard features before being used to create a FrameSet. -Note, the reverse operation is never performed: it is not possible to -produce non-standard features when writing a FrameSet to a FitsChan -(other than those embodied in the available encodings of the FitsChan -class). The supported non-standard features include: - -\begin{itemize} -\item EQUINOX keywords with string values equal to a date preceded -by the letter B or J (\emph{e.g.} ``B1995.0''). - -\item EQUINOX or EPOCH keywords with value zero (these are converted to -B1950). - -\item The IRAF ``ZPX'' projection is represented by a -WcsMap with type of -AST\_\_ZPN. Projection parameter values are read from any WAT\emph{i\_nnn} -keywords, and corresponding PVi\_m attributes are set in the -WcsMap. The WAT\emph{i\_nnn} keywords may specify corrections to the basic -ZPN projection by including ``lngcor'' or ``latcor'' terms. These are -supported if they use half cross-terms, in either simple or Chebyshev -representation. - -\item The IRAF ``TNX'' projection is represented by a WcsMap with type of -AST\_\_TPN (a distorted TAN projection retained within the WcsMap class -from an early draft of the FITS-WCS paper II). Projection parameter values -are read from any WAT\emph{i\_nnn} keywords, and corresponding PV -attributes are set in the WcsMap. If the TNX projection cannot be -converted exactly into an AST\_\_TPN projection, ASTWARN keywords are -added to the FitsChan containing a warning message (but only if the -Warnings attribute of the FitsChan is set appropriately). Currently, -TNX projections that use half cross-terms, in either simple or Chebyshev -representation, are supported. - -\item ``QV'' parameters for TAN projections (as produced by -\xref{AUTOASTROM}{sun242}{} -\footnote{\url{http://www.astro.gla.ac.uk/users/norman/star/autoastrom/}} -are renamed to the equivalent ``PV'' parameters. - -\item TAN projections that have associated ``PV'' parameters on the -latitude axis are converted to the corresponding TPN (distorted TAN) -projections. This conversion can be controlled using the PolyTan attribute -of the FitsChan class. - -\end{itemize} - -\subsection{Paper III - Spectral Coordinates} -These conventions are used when reading a FrameSet -from a FitsChan which includes appropriate -CTYPE\emph{i} values, and when writing a FrameSet in which -the WCS Frame is a SpecFrame. - -Table \ref{tab:fitspaper3} describes the use made by AST of each keyword -whose meaning is defined or extended by FITS-WCS paper III. - -\begin{table}[htbp] -\begin{footnotesize} -\begin{tabular}{|l|p{2.5in}|p{2.5in}|} -\hline -\multicolumn{1}{|c|}{\textbf{Keyword}} & \multicolumn{1}{c|}{\textbf{Read}} -& \multicolumn{1}{c|}{\textbf{Write}} \\ \hline - -\fitskey{CTYPE\emph{ia}}{All coordinate systems and projection types -listed in paper III are supported algorithm (the ``-LOG'' algorithm may -also be applied to non-spectral linear axes; the ``-TAB'' algorithm -requires the TabOK attribute to be set in the FitsChan).}{Determined by the System attribute of the -SpecFrame and the nature of the pixel to SpecFrame -Mapping.} - -\fitskey{CUNIT\emph{ia}}{Used to set the Units attribute of -the SpecFrame (note, SpecFrames always have an ``active'' Units attribute -(see astSetActiveUnit).}{Always written.} - -\fitskey{PV\emph{i\_ma}}{Used to create the pixel to WCS Mapping (values -are stored as attributes of a GrismMap).} -{Set from the attributes of the GrismMap, if present, and if set explicitly.} - -\fitskey{SPECSYS\emph{a}}{Used to set the StdOfRest -attribute of the SpecFrame (all systems are supported except CMBDIPOL).} -{Set from the StdOfRest attribute of the SpecFrame, but only if it has been -set explicitly.} - -\fitskey{SSYSOBS\emph{a}}{Ignored.}{Never written.} - -\fitskey{OBSGEO-X/Y/Z}{Used to set the ObsLon and -ObsLat attributes of the Frame (the observers -height above sea level is ignored).}{Set from the ObsLon and ObsLat -attributes of the Frame, if they have been set explicitly (it is -assumed that the observer is at sea level).} - -\fitskey{MJD-AVG}{Used to set the Epoch attributes of -the SpecFrame.}{Set from the Epoch attribute of the SpecFrame, if it has -been set explicitly.} - -\fitskey{SSYSSRC\emph{a}}{Used to set the SourceVRF attribute of the -SpecFrame -(all systems are supported except CMBDIPOL).} {Set from the SourceVRF -attribute of the SpecFrame.} - -\fitskey{ZSOURCE\emph{a}}{Used to set the SourceVel -attribute of the SpecFrame (the SourceVRF attribute -is first set to the system indicated by the SSYSSRC keyword, and the -ZSOURCE value is then converted to an apparent radial velocity and stored -as the SourceVel attribute).} -{Set from the SourceVel attribute of -the SpecFrame, if it has been set explicitly (the SourceVel value is -first converted from apparent radial velocity to redshift).} - -\fitskey{VELOSYS\emph{a}}{Ignored.}{Set from the attributes of the -SpecFrame that define the standard of rest and the observers position.} - -\fitskey{RESTFRQ\emph{a}}{Used to set the RestFreq -attribute of the SpecFrame.}{Set from the RestFreq attribute of the -SpecFrame, but only if the System attribute is not set to -``WAVE'', ``VOPT'', ``ZOPT'' or ``AWAV'', and only if RestFreq has been set -explicitly.} - -\fitskey{RESTWAV\emph{a}}{Used to set the RestFreq -attribute of the SpecFrame (after conversion from wavelength to frequency).} -{Set from the RestFreq attribute of the SpecFrame (after conversion), but only if the -System attribute is set to ``WAVE'', ``VOPT'', ``ZOPT'' or -``AWAV'', and only if RestFreq has been set explicitly.} - -\fitskey{CNAME\emph{ia}}{Used to set the Label attributes of -the WCS Frame keywords.}{Set from the Label attributes of the WCS Frame, -if they have been set explicitly.} -\hline -\end{tabular} -\end{footnotesize} -\vspace{3.mm} -\caption{Use of FITS-WCS Paper III keywords} -\label{tab:fitspaper3} -\end{table} - -\subsubsection{Requirements for a Successful Write Operation} -When writing a FrameSet in which the WCS Frame is a SpecFrame to a -FitsChan, the write operation is successful only if -the Mapping from pixel coordinates (the base Frame -in the FrameSet) to the SpecFrame satisfies one of the following conditions: - -\begin{enumerate} -\item It is linear. -\item It is logarithmic. -\item It is linear if the SpecFrame were to be re-mapped into one of the -other spectral systems supported by FITS-WCS paper III. -\item It contains a GrismMap, and the Mapping before the GrismMap (from -pixel coordinates to grism parameter) is linear, and the Mapping after the -GrismMap is either null or represents a change of spectral system from wavelength (air or -vacuum) to one of the supported spectral systems. -\item The TabOK attribute is set to a non-zero positive value in the FitsChan. -\end{enumerate} - -If none of the above conditions hold, the write operation will be -unsuccessful. Note, if the FitsChan's TabOK attribute is set to a positive -non-zero value then any Mapping that does not meet any of the earlier conditions -will be written out as a look-up table, using the ``-TAB'' algorithm described -in FITS-WCS paper III. If the TabOK attribute is to zero (the default) or -negative in the FitsChan, then the write operation will be unsuccessful unless -one of the eaerlier conditions is met.\footnote{If the -TAB algorithm is used, the -positive value of the TabOK attribute is used as the table version number -(the EXTVER header) in the associated FITS binary table.} - -\subsubsection{Common Non-Standard Features} -The following non-standard features are supported when reading spectral -axes from a FitsChan: - -\begin{itemize} -\item Conversion of ``-WAV'', ``-FRQ'' and ``-VEL'' algorithm codes -(specified in early drafts of paper III) to the corresponding -``-X2P'' form. -\item Conversion of ``RESTFREQ'' to ``RESTFRQ'' -\end{itemize} - -\subsection{Paper IV - Coordinate Distortions} - -This paper proposes that an additional 4 character code be appended to -the end of the CTYPE\emph{i} keyword to specify the nature of any -distortion away from the basic algorithm described by the first 8 -characters of the CTYPE\emph{i} value. Currently AST ignores all such -codes when reading a FrameSet from a FitsChan (except for the ``-SIP'' code -defined by the Spitzer Space Telescope project - see below). This means that -a FrameSet can still be read from such headers, but the Mapping which gives -the WCS position associated with a given pixel position will reflect only -the basic algorithm and will not include the effects of the distortion. - -If such a FrameSet is then written out to a FitsChan, the resulting -CTYPE\emph{i} keywords will include no distortion code. - -\subsubsection{The ``-SIP'' distortion code} - -The Spitzer Space Telescope project -(\url{http://www.spitzer.caltech.edu/}) -has developed its own system for encoding 2-dimensional image distortion -within a FITS header, based on the proposals of paper IV. A description -of this system is available in -\url{http://ssc.spitzer.caltech.edu/postbcd/doc/shupeADASS.pdf}. In this -system, the presence of distortion is indicated by appending the -distortion code ``-SIP'' to the CTYPE\emph{i} keyword values for the -celestial axes. The distortion takes the form of a polynomial function -which is applied to the pixel coordinates, after subtraction of the -CRPIX\emph{j} values. - -This system is a strictly 2 dimensional system. When reading a -FrameSet from a FitsChan which -includes the ``-SIP'' distortion code, AST assumes that it -is only applied to the first 2 WCS axes in a FITS header (i.e. -CTYPE1 and CTYPE2). If the ``-SIP'' distortion code is attached to other -axes, it will be ignored. The distortion itself is represented by a -PolyMap within the resulting FrameSet. - -If a FrameSet is read from a FitsChan which includes ``-SIP'' -distortion, and an attempt is then made to write this FrameSet out to a -FitsChan, the write operation will fail unless the distortion is -insignificant (\emph{i.e.} is so small that the tests for linearity built -into AST are passed). In this case, no distortion code will be appended to -the resulting CTYPE\emph{i} keyword values. - -\newpage -\section{\xlabel{changes_and_new_features}\label{ss:changes}Release Notes} - -\subsection{Changes Introduced in V1.1} - -The following describes the most significant changes which occurred in -the AST library between versions V1.0 and V1.1 (not the most recent -version): - -\begin{enumerate} - -\item A new ``How To\ldots'' section (\secref{ss:howto}) has been -added to this document. It contains simple recipies for performing -commonly-required operations using AST. - -c+ -\item A new astUnformat function has been provided to read formatted -coordinate values for the axes of a Frame -(\secref{ss:unformattingaxisvalues}). In essence, this function is the -inverse of astFormat. It may be used to decode user-supplied formatted -values representing coordinates, turning them into numerical values -for processing. Celestial coordinates may also be read using this -function (\secref{ss:unformattingskyaxisvalues}) and free-format input -is supported. -c- -f+ -\item A new AST\_UNFORMAT function has been provided to read formatted -coordinate values for the axes of a Frame -(\secref{ss:unformattingaxisvalues}). In essence, this function is the -inverse of AST\_FORMAT. It may be used to decode user-supplied -formatted values representing coordinates, turning them into numerical -values for processing. Celestial coordinates may also be read using -this function (\secref{ss:unformattingskyaxisvalues}) and free-format -input is supported. -f- - -\item The Format attribute string used by a SkyFrame when formatting -celestial coordinate values now allows the degrees/hours field to be -omitted, so that celestial coordinates may be given in (\emph{e.g.}) -arc-minutes and/or arc-seconds -(\secref{ss:formattingskyaxisvalues}). As a result, the degrees/hours -field is no longer included by default. A new ``t'' format specifier -has been introduced (see the Format attribute) to allow minutes and/or -seconds of time to be specified if required. - -c+ -\item A new function astMapBox has been introduced. This allows you to -find the extent of a ``bounding box'' which just encloses another box -after it has been transformed by a Mapping. A typical use might be to -calculate the size which an image would have if it were transformed by -the Mapping. -c- -f+ -\item A new routine AST\_MAPBOX has been introduced. This allows you -to find the extent of a ``bounding box'' which just encloses another -box after it has been transformed by a Mapping. A typical use might be -to calculate the size which an image would have if it were transformed -by the Mapping. -f- - -c+ -\item A new class of Object, the IntraMap, has been introduced -(\secref{ss:intramaps}). This is a specialised form of Mapping which -encapsulates a privately-defined coordinate transformation function -(\emph{e.g.}\ written in C) so that it may be used like any other AST -Mapping. This allows you to create Mappings that perform any -conceivable coordinate transformation. -c- -f+ -\item A new class of Object, the IntraMap, has been introduced -(\secref{ss:intramaps}). This is a specialised form of Mapping which -encapsulates a privately-defined coordinate transformation routine -(\emph{e.g.}\ written in Fortran) so that it may be used like any -other AST Mapping. This allows you to create Mappings that perform any -conceivable coordinate transformation. -f- - -\item The internal integrity of a FrameSet is now automatically -preserved whenever changes are made to any attributes which affect the -current Frame (either by setting or clearing their values). This is -accomplished by appropriately re-mapping the current Frame to account -for any change to the coordinate system which it represents -(\secref{ss:framesetintegrity}). - -\item The internal structure of a FrameSet is now automatically tidied -to eliminate redundant nodes whenever any of its Frames is removed or -re-mapped. Automatic simplification of any compound Mappings which -result may also occur. The effect of this change is to prevent the -accumulation of unnecessary structure in FrameSets which are -repeatedly modified. - -c+ -\item Some improvements have been made to the algorithms for -simplifying compound Mappings, as used by astSimplify. -c- -f+ -\item Some improvements have been made to the algorithms for -simplifying compound Mappings, as used by AST\_SIMPLIFY. -f- - -\item The textual representation used for some Objects -(\emph{i.e.}\ when they are written to a Channel) has changed -slightly, but remains compatible with earlier versions of AST. - -c+ -\item Interfaces to the internal functions and macros used by AST for -handling memory and error conditions are now provided \emph{via} the -``ast.h'' header file. This is for the benefit of those writing -(\emph{e.g.}) new graphics interfaces for AST. -c- - -c+ -\item A problem has been fixed which could result when using astRead -to read FITS headers in which the CDELT value is zero. Previously, -this could produce a Mapping whose inverse transformation was not -defined and this could unnecessarily restrict the use to which it -could be put. The problem has been overcome by supplying a suitable -small CDELT value for FITS axes which have only a single pixel. -c- -f+ -\item A problem has been fixed which could result when using AST\_READ -to read FITS headers in which the CDELT value is zero. Previously, -this could produce a Mapping whose inverse transformation was not -defined and this could unnecessarily restrict the use to which it -could be put. The problem has been overcome by supplying a suitable -small CDELT value for FITS axes which have only a single pixel. -f- - -\item A bug has been fixed which could occasionally cause a MatrixMap -to be used with the wrong Invert attribute value when it forms part of -c+ -a compound Mapping which is being simplified using astSimplify. -c- -f+ -a compound Mapping which is being simplified using AST\_SIMPLIFY. -f- - -f+ -\item A bug has been fixed which could cause the AST\_\_BAD parameter -to have an incorrect value on some platforms. -f- - -\item A problem has been fixed which could prevent tick marks being -drawn on a coordinate axis close to a singularity in the coordinate -system. -\end{enumerate} - -\subsection{Changes Introduced in V1.2} - -The following describes the most significant changes which occurred in -the AST library between versions V1.1 and V1.2 (not the most recent -version): - -\begin{enumerate} -c+ -\item A new function, astPolyCurve, has been introduced to allow more -efficient plotting of multiple geodesic curves -(\secref{ss:plottinggeodesics}). -c- -f+ -\item A new routine, AST\_POLYCURVE, has been introduced to allow more -efficient plotting of multiple geodesic curves -(\secref{ss:plottinggeodesics}). -f- - -c+ -\item A new set of functions, astResample$<$X$>$, has been introduced -to perform resampling of gridded data such as images -(\emph{i.e.}\ re-gridding) under the control of a geometrical -transformation specified by a Mapping. -c- -f+ -\item A new set of functions, AST\_RESAMPLE$<$X$>$, has been -introduced to perform resampling of gridded data such as images -(\emph{i.e.}\ re-gridding) under the control of a geometrical -transformation specified by a Mapping. -f- - -\item The command-line options ``$-$pgp'' and ``$-$pgplot'', which -were previously synonymous when used with the ``ast\_link'' and -``ast\_link\_adam'' commands, are no longer synonymous. The option -``$-$pgp'' now causes linking with the Starlink version of PGPLOT -(which uses GKS to generate its output), while ``$-$pgplot'' links -with the standard (or ``native'') version of PGPLOT. - -c+ -\item The function astMapBox has been changed to execute more quickly, -although this has been achieved at the cost of some loss of robustness -when used with difficult Mappings. -c- -f+ -\item The routine AST\_MAPBOX has been changed to execute more -quickly, although this has been achieved at the cost of some loss of -robustness when used with difficult Mappings. -f- - -\item A new value of ``FITS-IRAF'' has been introduced for the -Encoding attribute of a FitsChan. This new encoding provides an -interim solution to the problem of storing coordinate system -information in FITS headers, until the proposed new FITS-WCS standard -becomes stable. - -\item When a FrameSet is created from a set of FITS header cards (by -reading from a FitsChan using a ``foreign'' encoding), the base Frame -of the resulting FrameSet now has its Domain attribute set to -``GRID''. This reflects the fact that this Frame represents FITS data -grid coordinates (equivalent to FITS pixel coordinates---see -\secref{ss:domainconventions}). Previously, this Domain value was not -set. - -c+ -\item astFindFits now ignores trailing spaces in its keyword template. -c- -f+ -\item AST\_FINDFITS now ignores trailing spaces in its keyword template. -f- - -c+ -\item astPutFits now recognises ``D'' and ``d'' as valid exponent -characters in floating point numbers. -c- -f+ -\item AST\_PUTFITS now recognises ``D'' and ``d'' as valid exponent -characters in floating point numbers. -f- - -\item The FitsChan class is now more tolerant of common minor -violations of the FITS standard. - -\item The FitsChan class now incorporates an improved test for the -linearity of Mappings, allowing more reliable conversion of AST data -into FITS (using ``foreign'' FITS encodings). - -c+ -\item Some further improvements have been made to the algorithms for -simplifying compound Mappings, as used by astSimplify. -c- -f+ -\item Some further improvements have been made to the algorithms for -simplifying compound Mappings, as used by AST\_SIMPLIFY. -f- - -\item A new UnitRadius attribute has been added to the SphMap -class. This allows improved simplification of compound Mappings -(CmpMaps) involving SphMaps and typically improves performance when -handling FITS world coordinate information. - -\item A MatrixMap no longer propagates input coordinate values of -AST\_\_BAD automatically to all output coordinates. If certain output -coordinates do not depend on the affected input coordinate(s) because -the relevant matrix elements are zero, then they may now remain valid. - -\item A minor bug has been corrected which could cause certain -projections which involve half the celestial sphere to produce valid -coordinates for the other (unprojected) half of the sphere as well. - -c+ -\item A bug has been fixed which could occasionally cause astConvert -to think that conversion between a CmpFrame and another Frame was -possible when, in fact, it wasn't. -c- -f+ -\item A bug has been fixed which could occasionally cause AST\_CONVERT -to think that conversion between a CmpFrame and another Frame was -possible when, in fact, it wasn't. -f- -\end{enumerate} - -\subsection{Changes Introduced in V1.3} - -The following describes the most significant changes which occurred in -the AST library between versions V1.2 and V1.3 (not the most recent -version): - -\begin{enumerate} -c+ -\item A new set of functions, astResample$<$X$>$, has been introduced to -provide efficient resampling of gridded data, such as spectra and -images, under the control of a geometrical transformation specified by -a Mapping. A variety of sub-pixel interpolation schemes are supported. -c- -f+ -\item A new set of functions, AST\_RESAMPLE$<$X$>$, has been introduced to -provide efficient resampling of gridded data, such as spectra and -images, under the control of a geometrical transformation specified by -a Mapping. A variety of sub-pixel interpolation schemes are supported. -f- - -\item A new class, PcdMap, has been introduced. This is a specialised -form of Mapping which implements 2-dimensional pincushion or barrel -distortion. - -\item A bug has been fixed which could cause a FitsChan to produce too -many digits when formatting floating point values for inclusion in a -FITS header if the numerical value was in the range -0.00099999\ldots -to -0.0001. - -\item A bug has been fixed which could cause a FitsChan to lose the -comment associated with a string value in a FITS header. - -\item A FitsChan now reports an error if it reads a FITS header which -identifies a non-standard sky projection (previously, this was -accepted without error and a Cartesian projection used instead). - -\item A bug has been fixed which could prevent conversion between the -coordinate systems represented by two CmpFrames. This could only occur -if the CmpFrames contained a relatively large number of nested Frames. - -%\item A bug has been fixed which could cause a program to crash if -%FrameSets were nested inside each other (for example, if one FrameSet -%had another FrameSet added to it for use as a Frame or Mapping). The -%problem could only occur if the nested structure was loaded from a data -%c+ -%file (using astRead). -%c- -%f+ -%file (using AST\_READ). -%f- -% -\item Further improvements have been made to the simplification of -compound Mappings, including fixes for several bugs which could cause -indefinite looping or unwanted error messages. - -\item Some memory leaks have been fixed. - -\item A small number of documentation errors have been corrected. -\end{enumerate} - -\subsection{Changes Introduced in V1.4} - -The following describes the most significant changes which have occurred -in the AST library between versions V1.3 and V1.4 (not the most recent -version): - -\begin{enumerate} -c+ -\item A new MathMap class has been introduced. This is a form of -Mapping that allows you to define coordinate transformations in a -flexible and transportable way using arithmetic operations and -mathematical functions similar to those available in C. -c- -f+ -\item A new MathMap class has been introduced. This is a form of -Mapping that allows you to define coordinate transformations in a -flexible and transportable way using arithmetic operations and -mathematical functions similar to those available in Fortran. -f- - -c+ -\item {\bf{WARNING---INCOMPATIBLE CHANGE.}} Transformation functions -used with the IntraMap class (see, for example, astIntraReg) now -require a ``this'' pointer as their first parameter. \textbf{Existing -implementations will not continue to work correctly with this version -of AST unless this parameter is added.} There is no need for existing -software to make use of this pointer, but it must be present. -c- -f+ -\item {\bf{WARNING---INCOMPATIBLE CHANGE.}} Transformation routines -used with the IntraMap class (see, for example, AST\_INTRAREG) now -require a THIS pointer as their first argument. \textbf{Existing -implementations will not continue to work correctly with this version -of AST unless this argument is added.} There is no need for existing -software to make use of this pointer, but it must be present. -f- - -This change has been introduced so that transformation functions can gain -access to IntraMap attributes. - -c+ -\item A new IntraFlag attribute has been added to the IntraMap -class. This allows the transformation functions used by IntraMaps to -adapt to produce the required transformation on a per-IntraMap basis -(\secref{ss:intraflag}). -c- -f+ -\item A new IntraFlag attribute has been added to the IntraMap -class. This allows the transformation routines used by IntraMaps to -adapt to produce the required transformation on a per-IntraMap basis -(\secref{ss:intraflag}). -f- - -\item The Plot attributes MajTickLen and MinTickLen, which control the -length of major and minor tick marks on coordinate axes, may now be -subscripted using an axis number. This allows tick marks of different -lengths to be used on each axis. It also allows tick marks to be -suppressed on one axis only by setting the length to zero. - -\item The value of the Plot attribute NumLab, which controls the -plotting of numerical labels on coordinate axes, no longer has any -effect on whether labelling of a coordinate grid is interior or -exterior (as controlled by the Labelling attribute). - -\item The FitsChan class now provides some support for the -IRAF-specific ``ZPX'' sky projection, which is converted transparently -into the equivalent FITS ``ZPN'' projection (see the description of the -Encoding attribute for details). - -\item The FitsChan class now recognises the coordinate system ``ICRS'' -(International Celestial Reference System) as equivalent to -``FK5''. This is an interim measure and full support for the -(exceedingly small) difference between ICRS and FK5 will be added at a -future release. - -Note that ``ICRS'' is not yet recognised as a coordinate system by other -classes such as SkyFrame, so this change only facilitates the -importation of foreign data. - -\item A bug in the FitsChan class has been fixed which could result in -longitude values being incorrect by 180 degrees when using cylindrical -sky projections, such as the FITS ``CAR'' projection. - -\item A bug in the FitsChan class has been fixed which could result in -the FITS sky projection parameters ProjP(0) to ProjP(9) being -incorrectly named PROJP1 to PROJP10 when written out as FITS cards. - -\item A bug in the FitsChan class has been fixed which could cause -confusion between the FITS-IRAF and FITS-WCS encoding schemes if both -a CD matrix and a PC matrix are erroneously present in a FITS header. - -\item Some minor memory leaks have been fixed. - -\item A small number of documentation errors have been corrected. -\end{enumerate} - -\subsection{Changes Introduced in V1.5} - -The following describes the most significant changes which have -occurred in the AST library between versions V1.4 and V1.5 (not the most -recent version): - -\begin{enumerate} - -\item The FitsChan class has been modified to support the latest draft -FITS WCS standard, described in the two papers ``Representation of world -coordinates in FITS'' (E.W.\,Greisen and M.\,Calabretta, dated 30th -November, 1999), and ``Representation of celestial coordinates in FITS'' -(M.\,Calabretta and E.W.\,Greisen, dated 24th September, 1999). These are -available at -\url{http://www.cv.nrao.edu/fits/documents/wcs/wcs.html}. - -The FITS-WCS encoding now uses these updated conventions. The main -changes are: - -\begin{itemize} -\item Rotation and scaling of pixel axes is now represented by a matrix -of \texttt{CDj\_i} keywords instead of a combination of \texttt{PCjjjiii} and -\texttt{CDELTj} keywords. -\item Projection parameters are now associated with particular axes and -are represented by \texttt{PVi\_m} keywords instead of the \texttt{PROJPm} -keywords. -\item The tangent plane projection (``TAN'') can now include optional -polynomial correction terms. -\item An entire set of keywords must be supplied for each set of secondary -axis descriptions, and each such keyword must finish with a single -character indicating which set it belongs to. This means that keywords -which previously occupied eight characters have been shorten to seven to -leave room for this extra character. Thus \texttt{LONGPOLE} has become \texttt{LONPOLE} and \texttt{RADECSYS} has become \texttt{RADESYS}. -\end{itemize} - -\item Two new encodings have been added to the FitsChan class: -\begin{description} - -\item [FITS-PC] This encoding uses the conventions of the now superseded -FITS WCS paper by E.W.\,Greisen and M.\,Calabretta which used keywords -\texttt{CDELTj} and \texttt{PCjjjiii} to describe axis scaling and rotation. -These are the conventions which were used by the FITS-WCS encoding prior -to version 1.5 of AST. This encoding is provided to allow existing data -which use these conventions to be read. It should not in general be used -to create new data. - -\item [FITS-AIPS] This encoding is based on the conventions described in the -document ``Non-linear Coordinate Systems in AIPS'' by Eric W. Greisen -(revised 9th September, 1994 and available by ftp from fits.cv.nrao.edu -/fits/documents/wcs/aips27.ps.Z). This encoding uses \texttt{CROTAi} and -\texttt{CDELTi} keywords to describe axis rotation and scaling. - -\end{description} - -\item The FitsChan class now provides some support for the IRAF-specific -``TNX'' sky projection, which is converted transparently into the -equivalent FITS ``TAN'' projection (see the description of the Encoding -attribute for details). - -\item FrameSets originally read from a DSS encoded FITS header can now be -written out using the FITS-WCS encoding (a TAN projection with correction -terms will be used) in addition to the DSS encoding. The reverse is also -possible: FrameSets originally read from a FITS-WCS encoded FITS header -and which use a TAN projection can now be written out using the DSS -encoding. - -\item The algorithm used by the FitsChan class to verify that a FrameSet -conforms to the FITS-WCS model has been improved so that FrameSets -including more complex mixtures of parallel and serial Mappings -can be written out using the FITS-WCS encoding. - -\item The FitsChan class has been changed so that long strings included in -the description of an Object can be saved and restored without truncation -when using the NATIVE encoding. Previously, very long Frame titles, -mathematical expressions, \emph{etc.} were truncated if they exceeded the -capacity of a single FITS header card. They are now split over several -header cards so that they can be restored without truncation. Note, this -facility is only available when using NATIVE encoding. - -\item The FitsChan class has a new attribute called Warnings which -can be used to select potentially dangerous conditions under which -warnings should be issued. These conditions include (for instance) -unsupported features within non-standard projections, missing keywords -for which default values will be used, \emph{etc}. - -\item The WcsMap class has been changed to support the changes made to the -FITS-WCS encoding in the FitsChan class: -\begin{itemize} -\item Projection parameters are now associated with a particular axis and -are specified using a new set of attributes called PVj\_m. Here, ``j'' is -the index of an axis of WcsMap, and ``m'' is the index of the projection -parameter. -\item The old attributes ProjP(0) to ProjP(9) are still available but are -now deprecated in favour of the new PVj\_m attributes. They are interpreted -as aliases for PV(axlat)\_0 to PV(axlat)\_9, where ``axlat'' is the index of -the latitude axis. -\item The GLS projection projection has been renamed as SFL, but the -AST\_\_GLS type has been retained as an alias for AST\_\_SFL. -\end{itemize} - -\end{enumerate} - -\subsection{Changes Introduced in V1.6} - -The following describes the most significant changes which have -occurred in the AST library between versions V1.5 and V1.6: - -\begin{enumerate} - -c+ -\item The C interface to several methods (astTranN, astMark and -astPolyCurve) have been changed to make them easier to call from C++. -Parameters which previously had type ``double (*)[]'' have been changed -to the simpler ``double *''. Using the old types may result in non-fatal -compiler warnings, but should not change the behaviour of the methods. -c- - -\item A bug has been fixed in the Plot class which could cause groups -of tick marks to be skipped when using very small gaps. - -\item A bug has been fixed in the Plot class which could cause axes to be -labeled outside the visible window, resulting in no axes being visible. - -\item The FITS-WCS encoding used by the FitsChan class now includes the -WCSNAME keyword. When creating a FrameSet from FITS headers, the values of -the WCSNAME keywords are now used as the Domain names for the corresponding -Frames in the returned FrameSet. When writing a FrameSet to a FITS header -the Domain names of each Frame are stored in WCSNAME keywords in the -header. - -\item The FITS-WCS encoding used by the FitsChan class now attempts to -retain the identification letter associated with multiple axis -descriptions. When reading a FrameSet from a FITS header, the identification -letter is stored in the Ident attribute for each Frame. When writing a -FrameSet to a FITS header, the identification letter is read from the -Ident attribute of each Frame. The letter to associate with each Frame -can be changed by assigning a new value to the Frame's Ident attribute. - -\item The FITS-WCS, FITS-PC, FITS-IRAF and FITS-AIPS encodings used by the -FitsChan class now create a SkyFrame with the System attribute set to -``Unknown'' if the CTYPE keywords in the supplied header refers to an -unknown celestial coordinate system. Previously, a Frame was used instead -of a SkyFrame. - -\item The FITS-WCS, FITS-PC, FITS-IRAF and FITS-AIPS encodings used by the -FitsChan class no longer report an error if the FITS header contains no -CTYPE keywords. It is assumed that a missing CTYPE keyword implies that -the world coordinate system is linear and identically equal to -``intermediate world coordinates''. - -\item The new value ``noctype'' is now recognized by the Warnings attribute -of the FitsChan class. This value causes warnings to be issued if CTYPE -keywords are missing from foreign encodings. - -\item A new attribute called AllWarnings has been added to the FitsChan -class. This is a read-only, space separated list of all the known condition -names which can be specified in the Warnings attribute. - -\item The FitsChan class now attempts to assigns a Title to each Frame in -a FrameSet read using a foreign encoding. The Title is based on the Domain -name of the Frame. If the Frame has no Domain name, the default Title -supplied by the Frame class is retained. - -\item The FitsChan class uses the comments associated with CTYPE -keywords as axis labels when reading a foreign encoding. This behaviour -has been modified so that the default labels provided by the Frame class -are retained (instead of using the CTYPE comments) if any of the CTYPE -comments are identical. - -\item A new ``interpolation'' scheme identified by the symbolic constant -AST\_\_BLOCKAVE has been added to the AST\_RESAMPLE$<$X$>$ set of -functions. The new scheme calculates each output pixel value by finding -the mean of the input pixels in a box centred on the output pixel. - -\item The SkyFrame class can now be used to represent an arbitrary spherical -coordinate system by setting its System attribute to ``Unknown''. - -\item The indices of the latitude and longitude axes of a SkyFrame can -now be found using new read-only attributes LatAxis and LonAxis. The -effects of any axis permutation is taken into account. - -\item A new attribute called Ident has been added to the Object class. -This serves the same purpose as the existing ID attribute, but (unlike ID) -its value is transferred to the new Object when a copy is made. - -\item A bug has been fixed which could prevent complex CmpFrames -behaving correctly (for instance, resulting in the failure of attempts -to find a Mapping between a CmpFrame and itself). - -\end{enumerate} - -\subsection{Changes Introduced in V1.7} - -The following describes the most significant changes which have -occurred in the AST library between versions V1.6 and V1.7: - -\begin{enumerate} - -\item The Frame class has a new method called -f+ -AST\_ANGLE -f- -c+ -astAngle -c- -which returns the angle subtended by two points at a third point within a -2 or 3 dimensional Frame. - -\item The Frame class has a new method called -f+ -AST\_OFFSET2 -f- -c+ -astOffset2 -c- -which calculates a position which is offset away from a given starting -point by a specified distance along a geodesic curve which passes -through the starting point at a given position angle. It can only be used -with 2-dimensional Frames. - -\item The Frame class has a new method called -f+ -AST\_AXDISTANCE -f- -c+ -astAxDistance -c- -which returns the increment between two supplied axis values. For -axes belonging to SkyFrames, the returned value is normalized into -the range $\pm\pi$. - -\item The Frame class has a new method called -f+ -AST\_AXOFFSET -f- -c+ -astAxOffset -c- -which returns an axis value a given increment away from a specified axis -value. For axes belonging to SkyFrames, the returned value is normalized into -the range $\pm\pi$ (for latitude axes) or zero to $2\pi$ (for longitude -axes). - -\item The Plot class has a new method called -f+ -AST\_GENCURVE -f- -c+ -astGenCurve -c- -which allows generalised user-defined curves to be drawn. The curve is -defined by a user-supplied Mapping which maps distance along the curve -into the corresponding position in the current Frame of the Plot. The new -method then maps these current Frame position into graphics coordinates, -taking care of any non-linearities or discontinuities in the mapping. - -\item The Plot class has a new method called -f+ -AST\_GRFSET -f- -c+ -astGrfSet -c- -which allows the underlying primitive graphics functions to be selected -at run-time. Previously, the functions used by the Plot class to produce -graphics could only be selected at link-time, using the options of the -ast\_link command. The new Plot method allows an application to over-ride -the functions established at link-time, by specifying alternative -primitive graphics routines. In addition, the two new Plot methods -f+ -AST\_GRFPUSH and AST\_GRFPOP -f- -c+ -astGrfPush and astGrfPop -c- -allow the current graphics routines to be saved and restore on a -first-in-last-out stack, allowing temporary changes to be made to the set -of registered graphics routines. - -\item The DrawAxes attribute of the Plot class can now be specified -independantly for each axis, by appending the axis index to the -end of the attribute name. - -\item A bug has been fixed in the Plot class which could result in axis -labels being drawn on inappropriate edges of the plotting box when using -``interior'' labelling. - -\item A bug has been fixed in the IntraMap class which could cause IntraMaps -to be corrupted after transforming any points. - -\item Bugs have been fixed in the FitsChan class which could cause -inappropriate ordering of headers within a FitsChan when writing or -reading objects using NATIVE encodings. - -\item A bug has been fixed in the FitsChan class which could cause the -celestial longitude of a pixel to be estimated incorrectly by 180 degrees -if the reference point is at either the north or the south pole. - -\end{enumerate} - - -\subsection{Changes Introduced in V1.8-2} - -The following describes the most significant changes which have -occurred in the AST library between versions V1.7 and V1.8-2: - -\begin{enumerate} - -\item The SkyFrame class has a new attribute called NegLon which allows - longitude values to be displayed in the range $-\pi$ to $+\pi$, instead - of the usual range zero to $2.\pi$. - -\item Some new -c+ -functions (astAngle, astAxAngle, astResolve, astOffset2, astAxOffset, -astAxDistance) -c- -f+ -routines (AST\_ANGLE, AST\_AXANGLE, AST\_RESOLVE, AST\_OFFSET2, AST\_AXOFFSET, -AST\_AXDISTANCE) -f- -have been added to the Frame class to allow navigation of the coordinate space -to be performed without needing to know the underlying geometry -of the co-ordinate system (for instance, whether it is Cartesian or -spherical). - -Note, version 1.8-1 contained many of these facilities, but -some have been changed in version 1.8-2. Particularly, positions angles -are now referred to the second Frame axis for \emph{all} classes of Frames -(including SkyFrames), and the -c+ -astBear function has been replaced by astAxAngle. -c- -f+ -AST\_BEAR routine has been replaced by AST\_AXANGLE. -f- - -\end{enumerate} - -\subsection{Changes Introduced in V1.8-3} - -The following describes the most significant changes which -occurred in the AST library between versions V1.8-2 and V1.8-3: - -\begin{enumerate} - -\item A new method called astDecompose has been added to the Mapping class -which enables pointers to be obtained to the component parts of CmpMap and -CmpFrame objects. - -\item Functions within proj.c and wcstrig.c have been renamed to avoid name -clashes with functions in more recent versions of Mark Calabretta's wcslib -library. - -\end{enumerate} - -\subsection{Changes Introduced in V1.8-4} - -The following describes the most significant changes which -occurred in the AST library between versions V1.8-3 and V1.8-4: - -\begin{enumerate} - -\item The FitsChan class has a new attribute called DefB1950 which can be -used to select the default reference frame and equinox to be used if -a FitsChan with foreign encoding contains no indication of the -reference frame or equinox. - -\item A bug has been fixed in the FitsChan class which could prevent -astWrite from creating a set of FITS headers from an otherwise valid -FrameSet, when when using FITS-AIPS encoding. - -\item A bug has been fixed in the FitsChan class which could cause -astRead to mis-interpret the FITS CROTA keyword when using FITS-AIPS -encoding. - -\end{enumerate} - -\subsection{Changes Introduced in V1.8-5} - -The following describes the most significant changes which -occurred in the AST library between versions V1.8-4 and V1.8-5: - -\begin{enumerate} - -\item The Plot class defines new graphical elements Axis1, Axis2, -Grid1, Grid2, NumLabs1, NumLabs2, TextLab1, TextLab2, Ticks1 and Ticks2. -These allow graphical attributes (colour, width, etc) to be set for each -axis individually. Previously, graphical attributes could only be set for -both axes together, using graphical elements Axes, Grid, NumLabs, -TextLabs and Ticks. - -\end{enumerate} - - -\subsection{Changes Introduced in V1.8-7} - -The following describes the most significant changes which -occurred in the AST library between versions V1.8-5 and V1.8-7: - -\begin{enumerate} - -\item A new attribute called CarLin has been added to the FitsChan class -which controls the way CAR projections are handled when reading a -FrameSet from a non-native FITS header. Some FITS writers use a CAR -projection to represent a simple linear transformation between pixel -coordinates and celestial sky coordinates. This is not consistent with -the definition of the CAR projection in the draft FITS-WCS standard, which -requires the resultant Mapping to include a 3D rotation from native -spherical coordinates to celestial spherical coordinates, thus making the -Mapping non-linear. Setting CarLin to 1 forces -c+ -astRead -c- -f+ -AST\_READ -f- -to ignore the FITS-WCS standard and treat any CAR projections as simple -linear Mappings from pixel coordinates to celestial coordinates. - -\item A bug has been fixed which could result in axis Format attributes -set by the user being ignored under certain circumstances. - -\item A bug in the way tick marks positions are selected in the Plot class -has been fixed. This bug could result in extra ticks marks being displayed at -inappropriate positions. This bug manifested itself, for instance, if the -Mapping represented by the Plot was a simple Cartesian to Polar Mapping. -In this example, the bug caused tick marks to be drawn at negative radius -values. - -\item A bug has been fixed which could prevent attribute settings from -being read correctly by -c+ -astSet, -c- -f+ -AST\_SET, -f- -etc., on certain platforms (MacOS, for instance). - -\end{enumerate} - -\subsection{Changes Introduced in V1.8-8} - -The following describes the most significant changes which -occurred in the AST library between versions V1.8-7 and V1.8-8: - -\begin{enumerate} - -\item A bug has been fixed in the FitsChan class which could cause -problems when creating a FrameSet from a FITS header containing WCS -information stored in the form of Digitised Digitised Sky Survey (DSS) -keywords. These problems only occurred for DSS fields in the southern -hemisphere, and resulted in pixel positions being mapped to sky positions -close to the corresponding \emph{northern} hemispshere field. - -\item A new method called -c+ -astBoundingBox -c- -f+ -AST\_BOUNDINGBOX -f- -has been added to the Plot class. This method returns the bounding box of -the previous graphical output produced by a Plot method. - -\item A new attribute called Invisible has been added to the Plot class -which suppresses the graphical output normally produced by Plot methods. -All the calculations needed to produce the normal output are still -performed however, and so the bounding box returned by the new -c+ -astBoundingBox -c- -f+ -AST\_BOUNDINGBOX -f- -method is still usable. - -\item Bugs have been fixed related to the appearance of graphical output -produced by the Plot class. These bugs were to do with the way in which -graphical elements relating to a specific axis (e.g. \texttt{Colour(axis1)}, etc.) -interacted with the corresponding generic element (e.g. -\texttt{Colour(axes)}, etc.). - -\end{enumerate} - - -\subsection{Changes Introduced in V1.8-13} - -The following describes the most significant changes which occurred -in the AST library between versions V1.8-8 and V1.8-13: - -\begin{enumerate} - -\item The FitsChan class has been modified so that LONPOLE keywords -c+ -are only produced by astWrite when necessary. For zenithal projections such as -TAN, the LONPOLE keyword can always take its default value and so is -not included in the FITS header produced by astWrite. -c- -f+ -are only produced by AST\_WRITE when necessary. For zenithal projections such as -TAN, the LONPOLE keyword can always take its default value and so is -not included in the FITS header produced by AST\_WRITE -f- -Previously, the unnecessary production of a LONPOLE keyword could prevent -FrameSets being written out using encodings which do not support the -LONPOLE keyword (such as FITS-IRAF). - -\item The FitsChan class has been modified to retain leading and trailing -spaces within COMMENT cards. - -\item The FitsChan class has been modified to only use CTYPE comments as -axis labels if all non-celestial axes have unique non-blank comments -(otherwise the CTYPE keyword values are used as labels). - -\item The FitsChan class has been modified so that it does not append a -trailing ``Z'' character to the end of DATE-OBS keyword values. - -\item The FitsChan class has been modified to use latest list of FITS-WCS -projections, as described in the FITS-WCS paper II, ``Representations of -celestial coordinates in FITS'' (Calabretta \& Greisen, draft dated 23 -April 2002). Support has been retained for the polynomial correction -terms which previous drafts have allowed to be associated with TAN -projections. - -\item The WcsMap class has additional projection types of AST\_\_TPN -(which implements a distorted TAN projection) and AST\_\_SZP. The AST\_\_TAN -projection type now represents a simple TAN projection and has no -associated projection parameters. In addition, the usage of projection -parameters has been brought into line with the the FITS-WCS paper II. - -\item The WcsMap class has been modified so that a ``get'' operation on a -projection parameter attribute will return the default value defined in the -FITS-WCS paper II if no value has been set for the attribute. Previously, a -value of AST\_\_BAD was returned in such a situation. - -\item The Frame class has new attributes Top(axis) and Bottom(axis) which -allow a ``plottable range'' to be specified for each Frame axis. The grid -c+ -produced by the astGrid method will not extend beyond these limits. -c- -f+ -produced by the AST\_GRID routine will not extend beyond these limits. -f- - -\end{enumerate} - -\subsection{Changes Introduced in V2.0} - -Note, Frame descriptions created using AST V2.0 will not be readable by -applications linked with earlier versions of AST. This applies to Frame -descriptions created using: -\begin{itemize} -\item the Channel class -\item the FitsChan class if the NATIVE Encoding is used -c+ -\item the astShow function -c- -f+ -\item the AST\_SHOW routine. -f- -\end{itemize} - -Applications must be re-linked with AST V2.0 in order to be able to read -Frame descriptions created by AST v2.0. - -The following describes the most significant changes which have -occurred in the AST library between versions V1.8-13 and V2.0 (the -current version): - -\begin{enumerate} - -\item The default value for the Domain attribute provided by the CmpFrame -class has been changed from ``CMP'' to a string formed by concatenating -the Domain attributes of the two component Frames, separated by a minus -sign. If both component Domains are blank, then the old default of -``CMP'' is retained for the CmpFrame Domain. - -\item The implementation of the -c+ -astWrite function -c- -f+ -AST\_WRITE routine -f- -within the FitsChan class has been modified. It will now attempt to -produce a set of FITS header cards to describe a FrameSet even if the -number of axes in the Current Frames is greater than the number in the -Base Frame (that is, if there are more WCS axes than pixel axes). This -has always been possible with NATIVE encoding, but has not previously -been possible for foreign encodings. The WCSAXES keyword is used to store -the number of WCS axes in the FITS header. - -\item Another change to the -c+ -astWrite function -c- -f+ -AST\_WRITE routine -f- -within the FitsChan class is that the ordering of ``foreign'' axes -(\emph{i.e.} CTYPE keywords) is now chosen to make the CD (or PC) matrix -as diagonal as possible - any element of axis transposition is removed by -this re-ordering as recommended in FITS-WCS paper I. Previously the -ordering was determined by the order of the axes in the Current Frame of -the supplied FrameSet. This change does not affect NATIVE encoding. - -\item Support for spectral coordinate systems has been introduced -throught the addition of two new classes, SpecFrame and SpecMap. -The SpecFrame is a 1-dimensional Frame which can be used to describe -positions within an electromagnetic spectrum in various systems -(wavelength, frequency, various forms of velocity,~\emph{etc.}) and referred -to various standards of rest (topocentric, geocentric, heliocentric -LSRK,~\emph{etc.}). The SpecMap is a Mapping which can transform spectral -axis values between these various systems and standards of rest. Note, -FitsChans which have a foreign encoding (\emph{i.e.} any encoding other -than NATIVE) are not yet able to read or write these new classes. - -\item Facilities have been added to the Frame class which allow -differences in axis units to be taken into account when finding a Mapping -between two Frames. In previous versions of AST, the Unit attribute was a -purely descriptive item intended only for human readers - changing the -value of Unit made no difference to the behaviour of the Frame. As of -version 2.0, the Unit attribute can influence the nature of the Mappings -between Frames. For instance, if the -c+ -astFindrame or astConvert -c- -f+ -AST\_FINDRAME or AST\_CONVERT -f- -method is used to find the Mapping between an Axis with Unit set to ``m'' -and another Axis with Unit set to ``km'', then the method will return a -ZoomMap which introduces a scaling factor of 0.001 between the two axes. -These facilities assume that units are specified following the rules -included in FITS-WCS paper I (\emph{Representation of World -Coordinates in FITS}, Greisen \& Calabretta). - -In order to minimise the risk of breaking existing software, the default -behaviour for simple Frames is to ignore the Unit attribute (\emph{i.e.} -to retain the previous behaviour). However, the new Frame method -c+ -astSetActiveUnit -c- -f+ -AST\_SETACTIVEUNIT -f- -may be used to ``activate'' (or deactivate) the new facilities within a -specific Frame. Note, the new SpecFrame class is different to the simple -Frame class in that the new facilities for handling units are always active -within a SpecFrame. - -\item The System and Epoch attributes fo the SkyFrame class have been -moved to the parent Frame class. This enables all sub-classes of Frame -(such as the new SpecFrame class) to share these attributes, and to provide -suitable options for each class. - -\item The Frame class has a new attribute called AlignSystem, which allows -control over the alignment process performed by the methods -c+ -astFindFrame and astConvert. -c- -f+ -AST\_FINDFRAME and AST\_CONVERT. -f- - - -\item The CmpFrame class has been modified so that attributes of a -component Frame can be accessed without needing to extract the Frame first. -To do this, append an axis index to the end of the attribute name. For -instance, if a CmpFrame contains a SpecFrame and a SkyFrame (in that order), -then the StdOfRest attribute of the SpecFrame can be referred to as the -``StdOfRest(1)'' attribute of the CmpFrame. Likewise, the Equinox attribute -of the SkyFrame can be accessed as the ``Equinox(2)'' (or equivalently -``Equinox(3)'') attribute of the CmpFrame. The ``System(1)'' attribute of the -CmpFrame will refer to the System attribute of the SpecFrame, whereas the -``System(2)'' and ``System(3)'' attributes of the CmpFrame will refer to the -System attribute of the SkyFrame (the ``System'' attribute without an axis -specifier will refer to the System attribute of the CmpFrame as a whole, -since System is an attribute of all Frames, and a CmpFrame is a Frame and -so has its own System value which is independant of the System attributes -of its component Frames). - -\item The algorithms used by the Plot class for determining when to omit -overlapping axis labels, and the abbreviation of redundant leading fields -within sexagesimal axis labels, have been improved to avoid some anomolous -behaviour in previous versions. - -\item The curve drawing algorithm used by the Plot class has been -modified to reduce the chance of it ``missing'' small curve sections, -such as may be produced if a grid line cuts across the plot very close to -a corner. Previously, these missed sections could sometimes result in -axis labels being omitted. - -\item A new function -c+ -(astVersion) -c- -f+ -(AST\_VERSION) -f- -has been added to return the version of the AST library in use. - -\item Bugs have been fixed in the Plot class which caused serious problems -when plotting high precision data. These problems could range from the -omission of some tick marks to complete failure to produce a plot. - -\end{enumerate} - -Programs which are statically linked will need to be re-linked in -order to take advantage of these new facilities. - - -\subsection{Changes Introduced in V3.0} - -The following describes the most significant changes which -occurred in the AST library between versions V2.0 and V3.0: - -\begin{enumerate} - -\item Many changes have been made in the FitsChan class in order to bring -the FITS-WCS encoding into line with the current versions of the FITS-WCS -papers (see -\url{http://www.atnf.csiro.au/people/mcalabre/WCS/}): - -\begin{itemize} - -\item The rotation and scaling of the pixel axes may now be specified using -either CD\emph{i\_j} keywords, or PC\emph{i\_j} and CDELTj keywords. A new attribute -called CDMatrix has been added to the FitsChan class to indicate which -set of keywords should be used when writing a FrameSet to a FITS-WCS -header. - -\item The FITS-WCS encoding now supports most of the conventions -described in FITS-WCS paper III for the description of spectral -coordinates. The exceptions are that the SSYSOBS keyword is not -supported, and WCS stored in tabular form (as indicated by the ``-TAB'' -algorithm code) is not supported. - - -\item User-specified fiducial points for WCS projections are now -supported by FitsChans which use FITS-WCS encoding. This use keywords -PVi\_0, PVi\_1 and PVi\_2 for the longitude axis. - -\item When reading a FITS-WCS header, a FitsChan will now use keywords PVi\_3 -and PVi\_4 for the longitude axis (if present) in preference to any LONPOLE -and LATPOLE keywords which may be present. When writing a FITS-WCS header, -both forms are written out. - -\item The number of WCS axes is stored in the WCSAXES keyword if its value -would be different to that of the NAXIS keyword. - -\item Helio-ecliptic coordinates are now supported by FitsChans which use -FITS-WCS encoding. This uses CTYPE codes ``HLON'' and ``HLAT''. The -resulting SkyFrame will have a System value of ``HELIOECLIPTIC'', and all -the usual facilities, such as conversion to other celestial systems, are -available. - -\item The FITS-WCS encoding now supports most of the conventions -described in FITS-WCS paper III for the description of spectral -coordinates. The exceptions are that the SSYSOBS keyword is not -supported, and WCS stored in tabular form (as indicated by the ``-TAB'' -algorithm code) is not supported. - -\item When reading a FITS-WCS header, a FitsChan will now ignore any -distortion codes which are present in CTYPE keywords. Here, a ``distortion -code'' is the final group of four characters in a CTYPE value of the -form ``xxxx-yyy-zzz'', as described in FITS-WCS paper IV. The exception -to this is that the ``-SIP'' distortion code (as used by the Spitzer -Space Telescope project - see -\url{http://ssc.spitzer.caltech.edu/postbcd/doc/shupeADASS.pdf}) is -interpreted correctly and results in a PolyMap being used to represent -the distortion in the resulting FrameSet. Note, ``-SIP'' distortion codes -can only be read, not written. A FrameSet which uses a PolyMap will not -in general be able to be written out to a FitsChan using any foreign -encoding (although NATIVE encoding can of course be used). - -\item The Warnings attribute of the FitsChan class now accepts values -``BadVal'' (which gives warnings about conversion errors when reading -FITS keyword values), ``Distortion'' (which gives warnings about -unsupported distortion codes within CTYPE values), and ``BadMat'' (which -gives a warning if the rotation/scaling matrix cannot be inverted). - -\item When writing a FrameSet to a FitsChan which uses a non-Native -encoding, the comment associated with any card already in the FitsChan -will be retained if the keyword value being written is the same as the -keyword value already in the FitsChan. - -\item A FrameSet which uses the non-FITS projection type AST\_\_TPN (a TAN -projection with polynomial distortion terms) can now be written to a -FitsChan if the Encoding attribute is set to FITS-WCS. The standard -``-TAN'' code is used within the CTYPE values, and the distortion -coefficients are encoded in keywords of the form `` QVi\_ma'', which are -directly analogous to the standard ``PVi\_ma'' projection parameter keywords. -Thus a FITS reader which does not recognise the QV keywords will still -be able to read the header, but the distortion will be ignored. - -\item The default value for DefB1950 attribute now depends on the value -of the Encoding attribute. - -\item A new appendix has been added to SUN/210 and SUN/211 giving details -of the implementation provided by the FitsChan class of the -conventions contained in the first four FITS-WCS papers. -\end{itemize} - -\item The SkyFrame class now supports two new coordinate systems ``ICRS'' -and ``HELIOECLIPTIC''. The default for the System attribute for SkyFrames -has been changed from ``FK5'' to ``ICRS''. - -\item The -c+ -astRate -c- -f+ -AST\_RATE -f- -function has been added which allows an estimate to be made of the rate of -change of a Mapping output with respect to one of the Mapping inputs. - -\item All attribute names for Frames of any class may now include an optional -axis specifier. This includes those attributes which describe a property -of the whole Frame. For instance, the Domain attribute may now be -specified as ``Domain(1)'' in addition to the simpler ``Domain''. In cases -such as this, where the attribute describes a property of the whole -Frame, axis specifiers will usually be ignored. The exception is that a -CmpFrame will use the presence of an axis specifier to indicate that the -attribute name relates to the primary Frame containing the specified -axis, rather than to the CmpFrame as a whole. - -\item A new subclass of Mapping, the PolyMap, has been added which -performs a general N-dimensional polynomial mapping. - -\item A new subclass of Mapping, the GrismMap, has been added which -models the spectral dispersion produced by a grating, prism or grism. - -\item A new subclass of Mapping, the ShiftMap, has been added which adds -constant values onto all coordinates (this is equivalent to a WinMap -with unit scaling on all axes). - -\item Minor bugs have been fixed within the Plot class to do with the choice -and placement of numerical axis labels. - -\item The SphMap class has a new attribute called PolarLong which gives the -longitude value to be returned when a Cartesian position corresponding to -either the north or south pole is transformed into spherical coordinates. - -\item The WcsMap class now assigns a longitude of zero to output -celestial coordinates which have a latitude of plus or minus 90 degrees. - -\item The NatLat and NatLon attributes of the WcsMap class have been -changed so that they now return the fixed native coordinates of the -projection reference point, rather than the native coordinates of the -user-defined fiducial point. - -\item Notation has been changed in both the WcsMap and FitsChan classes to -reflect the convention used in the FITS-WCS papers that index ``i'' refers -to a world coordinate axis, and index ``j'' refers to a pixel axis. - -\item Changes have been made to several Mapping classes in order to allow -the -c+ -astSimplify -c- -f+ -AST\_SIMPLIFY -f- -function to make simplifications in a CmpMap which previously were not -possible. - -\item The SlaMap class has been extended by the addition of conversions -between FK5 and ICRS coordinates, and between FK5 and helio-ecliptic coordinates. - -\item The SpecMap class has been changed to use the equation for the -refractive index of air as given in the current version of FITS-WCS paper -III. Also, the forward and inverse transformations between frequency and -air-wavelength have been made more compatible by using an iterative -procedure to calculate the inverse. - -\end{enumerate} - -\subsection{Changes Introduced in V3.1} - -The following describes the most significant changes which have -occurred in the AST library between versions V3.0 and V3.1 (the -current version): - -\begin{enumerate} -\item Addition of a new class called XmlChan - a Channel which -reads and writes AST objects in the form of XML. -\item A bug has been fixed in the Plot class which could cause incorrect -graphical attributes to be used for various parts of the plot if either -axis has no tick marks (i.e. if both major and minor tick marks have zero -length). -\end{enumerate} - -Programs which are statically linked will need to be re-linked in -order to take advantage of these new facilities. - - -\subsection{Changes Introduced in V3.2} - -The following describes the most significant changes which have -occurred in the AST library between versions V3.1 and V3.2: - -\begin{enumerate} - -\item A new -c+ -function astPutCards -c- -f+ -routine AST\_PUTCARDS -f- -has been added to the FitsChan class. This allows multiple concatenated header -cards to be stored in a FitsChan in a single call, providing an alternative to -the existing -c+ -astPutCards function. -c- -f+ -AST\_PUTCARDS routine. -f- - -\item Some signficant changes have been made to the simplification of Mappings - which should resultin a greater degree of simplication taking place.Some - bugs have also been fixed which could result in an infinite loop being - entered when attempting to simplify certain Mappings. - -\item The FitsChan class now translates the spectral algorithm codes -``-WAV'', ``-FRQ'' and ``-VEL'' (specified in early drafts of paper III) to -the corresponding ``-X2P'' form when reading a spectral axis description -from a set of FITS header cards. - -\item A bug has been fixed in the FitsChan class which could cause -keywords associated with alternate axis descriptions to be mis-interpreted. - -\item The Plot class now provides facilities for modifying the appearance -of sub-strings within text strings such as axis labels, titles, \emph{etc}, -by producing super-scripts, sub-scripts, changing the font colour, size, -\emph{etc}. See attribute Escape. - -\item The default value of the Tol attribute of the Plot class has been -changed from 0.001 to 0.01. This should not usually cause any significant -visible change to the plot, but should make the plotting faster. You may -need to set a lower value for Tol if you are producing a particularly -large plot. - -\item The algorithm for finding the default value for the Gap attribute -has been changed. This attribute specifies the gap between major axis -values in an annotated grid drawn by the Plot class. The change in -algorithm may cause the default value to be different to previous versions -in cirtain circumstances. - -\item Some bugs have been fixed in the Plot class which could cause the -system to hang for a long time while drawing certain all-sky grids -(notable some of the FITS Quad-cube projections). - -\item The SkyAxis class has extended the Format attribute by the addition -of the ``g'' option. this option is similar to the older ``l'' option in that -it results in characters (``h'', ``m'', ``s'', \emph{etc}) being used as -delimiters between the sexagesimal fields of the celestial position. The -difference is that the ``g'' option includes graphics escape sequences -in the returned formatted string which result in the field delimiter -characters being drawn as super-scripts when plotted as numerical axis values -by a Plot. - -\item The Plot class has been extended to include facilities for producing -logarithmic axes. See attributes LogPlot, LogTicks, LogGap and LogLabel. - -\item New functions astGCap and astGScales have been added to the interface -defined by file \verb+grf.h+. The ast\_link command has been modified so -that the \verb+-mygrf+ switch loads dummy versions of the new grf -functions. This means that applications should continue to build without -any change. However, the facilities for interpreting escape sequences -within strings drawn by the Plot class will not be available unless the -new grf functions are implemented. If you choose to implement them, you -should modify your linking procedure to use the \verb+-grf+ switch in -place of the older \verb+-mygrf+ switch. See the description of the ast\_link -command for details of the new switches. Also note that the astGQch -function, whilst included in verb+grf.h+ in pervious versions of AST, was -not actually called. As of this version of AST, calls are made to the -astGQch function, and so any bugs in the implementation of astGQch may -cause spurious behaviour when plotting text strings. - -\item A new 'static' method called astEscapes has been added which is used -to control and enquire whether astGetC and astFormat will strip any graphical -escape sequences which may be present out of the returned value. - -\item New attribute XmlPrefix has been added to the XmlChan class. It -allows XML written by the XmlChan class to include an explicit namespace -prefix on each element. - -\item New attribute XmlFormat has been added to the XmlChan class. It -specifies the format in which AST objects should be written. - -\item A new class of Mapping, the TranMap, has been introduced. A TranMap -takes its forward transformation from an existing Mapping, and its inverse -transformation from another existing Mapping. - -\item A bug has been fixed in WcsMap which caused error reports to -include erroneous axis numbers when referring to missing parameter values. - -\end{enumerate} - -\subsection{Changes Introduced in V3.3} - -The following describes the most significant changes which have -occurred in the AST library between versions V3.2 and V3.3: - -\begin{enumerate} - -\item Options have been added to the SkyFrame class which allows the -origin -of celestial coordinates to be moved to any specified point. See the new -attributes SkyRef, SkyRefIs, SkyRefP and AlignOffset. - -\item An option has been added to the FitsChan class which allows extra -Frames representing cartesian projection plane coordinates (``intermediate -world coordinates'' in the parlance of FITS-WCS) to be created when -reading -WCS information from a foreign FITS header. This option is controlled by -a new attribute called Iwc. - -\item The FitsChan class which been modified to interpret FITS-WCS CAR -projection headers correctly if the longitude reference pixel (CRPIX) is -very large. - -\item The FITS-AIPS++ encoding in the FitsChan class now recognised -spectral axes if they conform to the AIPS convention in which the -spectral axis is descirbed by a CTYPE keyword od the form "AAAA-BBB" -where ``AAAA'' is one of FREQ, VELO or FELO, and ``BBB'' is one of LSR, LSD, -HEL or OBS. Such spectral axes can be both read and written. - -\item The FitsChan class now has a FITS-AIPS++ encoding which represents -WCS information using FITS header cards recognised by the AIPS++ project. -Support for spectral axes is identical to the FITS-AIPS encoding. - -\item The organisation of the AST distribution and the commands for -building it have been changed. Whereas AST used to be built and installed -with \verb+./mk build; ./mk install+, it now builds using the more standard -idiom \verb+./configure; make; make install+. The installation location is -controlled by the \verb+--prefix+ argument to ./configure (as is usual -for other packages which use this scheme). Note that the INSTALL environment -variable now has a \emph{different} meaning to that which it had -before, and it should generally be \emph{unset}. Also, there is no need to -set the SYSTEM variable. - -\item Shared libraries are now installed in the same directory as the -static libraries. In addition, links to sharable libraries are installed -with names which include version information, and ``libtool libraries'' -are also installed (see -\url{http://www.gnu.org/software/libtool/manual.html}). - -\item The \verb+ast_dev+ script has been removed. Instead, the location of -the AST include files should be specified using the -I option when -compiling. - -f+ -\item The names of the installed AST include files have been changed to -upper case. -f- - -\end{enumerate} - - -\subsection{Changes Introduced in V3.4} - -The following describes the most significant changes which have -occurred in the AST library between versions V3.3 and V3.4: - -\begin{enumerate} - -\item The Mapping class has a new method -c+ -(astLinearApprox) -c- -f+ -(AST\_LINEARAPPROX) -f- -which calculates the co-efficients of a linear approximation to a Mapping. - -\item The Format attribute for simple Frames and SkyFrames has been extended. -It has always been possible, in both classes, to specify a precision by -including a dot in the Format value followed by an integer (\emph{e.g.} -``\verb+dms.1+'' for a SkyFrame, or ``\verb+%.10g+'' for a simple Frame). -The precision can now also be specified using an asterisk in place of the -integer (\emph{e.g.} ``\verb+dms.*+'' or ``\verb+%.*g+''). This causes the -precision to be derived on the basis of the Digits attribute value. - -\item The Plot class has been changed so that the default value used for the -Digits attribute is chosen to be the smallest value which results in no -pair of adjacent labels being identical. For instance, if an annotated -grid is being drawn describing a SkyFrame, and the Format(1) value is set -to ``\verb+hms.*g+'' (the ``g'' causes field delimiters to be drawn as -superscripts), and the Digits(1) value is unset, then the seconds field -will have a number of decimal places which results in no pair of labels -being identical. - -\item Addition of a new class classed DSBSpecFrame. This is a -sub-class of SpecFrame which can be used to describe spectral axes -associated with dual sideband spectral data. - -\item The FitsChan class will now read headers which use the old ``-GLS'' -projection code, converting them to the corresponding modern ``-SFL'' code, -provided that the celestial axes are not rotated. - -\item The FitsChan class has a new Encoding, ``FITS-CLASS'', which allows -the reading and writing of FITS headers using the conventions of the CLASS -package - see -\url{http://www.iram.fr/IRAMFR/GILDAS/doc/html/class-html/class.html}). - -\end{enumerate} - - -\subsection{Changes Introduced in V3.5} - -The following describes the most significant changes which have -occurred in the AST library between versions V3.4 and V3.5: - -\begin{enumerate} - -\item AST now provides facilities for representing regions of various -shapes within a coordinate system. The Region class provides general -facilities which are independent of the specific shape of region being -used. Various sub-classes of Region are also now available which provide -means of creating Regions of specific shape. Facilities provided by the -Region class include testing points to see if they are inside the -Region, testing two Regions for overlap, transforming Regions from one -coordinate system to another \emph{etc}. - -\item A new class of 1-dimensional Frame called FluxFrame has been added which -can be used to describe various systems for describing ovserved value at a -single fixed spectral position. - -\item A new class of 2-dimensional Frame called SpecFluxFrame has been added which -can be used to describe a 2-d frame spanned by a spectral position axis -and and an observed value axis. - -\item A new class of Mapping called RateMap has been added. A RateMap encapsulates -a previously created Mapping. The inputs of the RateMap correspond to the -inputs of the encapsulated Mapping. All RateMaps have just a single -output which correspond to the rate of change of a specified output of -the encapsulated Mapping with respect to a specified input. - -\item The SkyFrame class now supports a value of ``J2000'' for System. -This system is an equatorial system based on the mean dynamical equator and -equinox at J2000, and differs slightly from an FK5(J2000) system. - -\item A new class called KeyMap has been added. A KeyMap can be used to -store a collection of vector or scalar values or Objects, indexed by a -character string rather than an integer. - -\item The parameter list for the -c+ -astRate -c- -f+ -AST\_RATE -f- -method of the Mapping class has been modified. It no longer returns a second -derivative estimate. Existing code which uses this method will need to be -changed. - -\item Methods -c+ -(astSetFits<X>) -c- -f+ -(AST\_SETFITS<X>) -f- -have been added to the FitsChan class to allow values for named -keywords to be changed or added. - -\end{enumerate} - - -\subsection{Changes Introduced in V3.6} - -The following describes the most significant changes which -occurred in the AST library between versions V3.5 and V3.6: - -\begin{enumerate} - -\item If the Format attribute associated with an axis of a SkyFrame -starts with a percent character (``\verb+%+''), then axis values are -now formatted and unformatted as a decimal radians value, using the -Format syntax of a simple Frame. - -\item The Plot class has a new attribute called Clip which controls the -clipping performed by AST at the plot boundary. - -\item The keys used to label components of the PolyMap structure when a -PolyMap is written out through a Channel have been changed. The new keys -are shorter than the old keys and so can written succesfully to a FitsChan. -The new PolyMap class always writes new styles keys but can read either -old or new style keys. Consequently, PolyMap dumps written by this -version of AST cannot be read by older versions of AST. - -\item A mimimal cut down subset of the C version of SLALIB is now -included with the AST distribution and built as part of building AST. -This means that it is no longer necessary to have SLALIB installed -separately at your site. The SLALIB code included with AST is distrubuted -under the GPL. The default behaviour of the ast\_link script is now to -link with this internal slalib subset. However, the ``-csla'' option can -still be used to force linking with an external full C SLALIB library. -A new option ``-fsla'' has been introduced which forces linking with the -external full Fortran SLALIB library. - -\end{enumerate} - -\subsection{Changes Introduced in V3.7} - -The following describes the most significant changes which -occurred in the AST library between versions V3.6 and V3.7: - -\begin{enumerate} - -\item Support for time coordinate systems has been introduced -throught the addition of two new classes, TimeFrame and TimeMap. -The TimeFrame is a 1-dimensional Frame which can be used to describe -moments in time (either absolute or relative) in various systems (MJD, -Julian Epoch, \emph{etc.}) and referred to various time scales (TAI, UTC, -UT1, GMST, \emph{etc}). The TimeMap is a Mapping which can transform time -values between these various systems and time scales. Note, -FitsChans which have a foreign encoding (\emph{i.e.} any encoding other -than NATIVE) are not able to read or write these new classes. - -\end{enumerate} - - -\subsection{Changes Introduced in V4.0} - -The following describes the most significant changes which -occurred in the AST library between versions V3.7 and V4.0: - -\begin{enumerate} - -\item Experimental support for reading IVOA Space-Time-Coordinates (STC-X) -descriptions using the XmlChan class has been added. Support is included -for a subset of V1.20 of the draft STC specification. - -\item A new set of methods (AST\_REBIN<X>/astRebin<X>) has been added to -the Mapping class. These are flux-conserving alternatives to the existing -AST\_RESAMPLE<X>/astResample<X> methods. - -\end{enumerate} - - -\subsection{Changes Introduced in V4.1} - -The following describes the most significant changes which -occurred in the AST library between versions V4.0 and V4.1: - -\begin{enumerate} - -\item A new control flag has been added to the AST\_RESAMPLE<X>/astResample<X> -functions which produces approximate flux conservation. - -\item New constants AST\_\_SOMB and AST\_\_SOMBCOS have been added to -c+ -ast.h. These specify kernels for astResample and astRebin -c- -f+ -AST\_PAR. These specify kernels for AST\_RESAMPLE and AST\_REBIN -f- -based on the ``Sombrero'' function ( $2*J1(x)/x$ where $J1(x)$ is the -first order Bessel function of the first kind). - -\item The SkyFrame class now supports a System value of AZEL corresponding -to horizon (azimuth/elevation) coordinates. - -\item The FitsChan class allows the non-standard strings ``AZ--'' and -``EL--'' to be used as axis types in FITS-WCS CTYPE keyword values. - -\item The Frame class now has attributes ObsLon and ObsLat to specify -the geodetic longitude and latitude of the observer. - -\item The ClockLon and ClockLat attributes have been removed from the -TimeFrame class. Likewise, the GeoLon and GeoLat attributes have been -removed from the SpecFrame class. Both classes now use the ObsLon and -ObsLat attributes of the parent Frame class instead. However, the old -attribute names can be used as synonyms for ObsLat and ObsLon. Also, -dumps created using the old scheme can be read succesfully by AST V4.1 -and converted to the new form. - -\item A new -c+ -function astMapSplit -c- -f+ -routine AST\_MAPSPLIT -f- -has been added to the Mapping class. This splits a Mapping into two component -Mappings which, when combined in parallel, are equivalent to the original -Mapping. - -\item The default value for the SkyRefIs attribute has been changed from -``Origin'' to ``Ignored''. This means that if you want to use a SkyFrame -to represent offsets from some origin position, you must now set the -SkyRefIs attribute explicitly to either ``Pole'' or ``Origin'', in -addition to assigning the required origin position to the SkyRef attribute. - -\end{enumerate} - -\subsection{Changes Introduced in V4.2} - -The following describes the most significant changes which -occurred in the AST library between versions V4.1 and V4.2: - -\begin{enumerate} - -\item The SideBand attribute of the DSBSpecFrame class can now take the -option ``LO'' in addition to ``USB'' and ``LSB''. The new option causes the -DSBSpecFrame to represent the offset from the local oscillator frequency, -rather than either of the two sidebands. - -\item The FitsChan class has been changed so that it writes out a VELOSYS -keyword when creating a FITS-WCS encoding (VELOSYS indicates the topocentric -apparent velocity of the standard of rest). FitsChan also strips out VELOSYS -keywords when reading a FrameSet from a FITS-WCS encoding. - -\item The FitsChan class has a new method called -c+ -astRetainFits -c- -f+ -AST\_RETAINFITS -f- -that indicates that the current card in the FitsChan should not be -stripped out of the FitsChan when an AST Object is read from the FitsChan. -Unless this method is used, all cards that were involved in the creation -of the AST Object will be stripped from the FitsChan afte a read operation. - -\item A problem with unaligned memory access that could cause bus errors on -Solaris has been fixed. - -\item A new read-only attribute called ObjSize has been added to the base -Object Class. This gives the number of bytes of memory occupied by the -Object. Note, this is the size of the internal in-memory representation of -the Object, not the size of the textual representation produced by -writing the Object out through a Channel. - -\item A new function -c+ -astTune -c- -f+ -AST\_TUNE -f- -has been added which can be used to get and set global AST tuning -parameters. At the moment there are only two such parameter, both of -which are concerned with memory management within AST. - -\item A new method called -c+ -astTranGrid -c- -f+ -AST\_TRANGRID -f- -has been added to the Mapping class. This method creates a regular -grid of points covering a rectangular region within the input space of a -Mapping, and then transforms this set of points into the output space of the -Mapping, using a piecewise-continuous linear approximation to the Mapping -if appropriate in order to achive higher speed. - -\item A new subclass of Mapping has been added called SwitchMap. A -SwitchMap represents several alternate Mappings, each of which is used to -transforms input positions within a different region of the input -coordinate space. - -\item A new subclass of Mapping has been added called SelectorMap. A -SelectorMap tests each input position to see if it falls within one of -several Regions. If it does, the index of the Region containing the -input position is returned as the Mapping output. - -\item The behaviour of the -c+ -astConvert -c- -f+ -AST\_CONVERT -f- -method when trying to align a CmpFrame with another Frame has been -modified. If no conversion between positions in the Frame and CmpFrame -can be found, an attempt is now made to find a conversion between the -Frame and one of two component Frames contained within the CmpFrame. Thus -is should now be possible to align a SkyFrame with a CmpFrame containing a -SkyFrame and a SpecFrame (for instance). The returned Mapping produces bad -values for the extra axes (i.e. for the SpecFrame axis in the above example). - -\item The ``ast\_link\_adam'' and ``ast\_link'' scripts now ignore the -\verb+-fsla+ and \verb+-csla+ options, and always link against the -minimal cut-down version of SLALIB distributed as part of AST. - -\end{enumerate} - -\subsection{Changes Introduced in V4.3} - -The following describes the most significant changes which occurred in the -AST library between versions V4.2 and V4.3: - -\begin{enumerate} - -\item The -c+ -astGetFitsS -c- -f+ -AST\_GETFITSS -f- -function now strips trailing white space from the returned string, if the -original string contains 8 or fewer characters - -\item The SpecFrame class has a new attribute called SourceSys that specified -whether the SourceVel attribute (which specifies the rest frame of the -source) should be accessed as an apparent radial velocity or a redshift. -Note, any existing software that assumes that SourceVel always represents -a velocity in km/s should be changed to allow for the possibility of -SourceVel representing a redshift value. - -\end{enumerate} - - -\subsection{Changes Introduced in V4.4} - -The following describes the most significant changes which occurred in -the AST library between versions V4.3 and V4.4: - -\begin{enumerate} - -\item The -c+ -astFindFrame -c- -f+ -AST\_FINDFRAME -f- -function can now be used to search a CmpFrame for an instance of a more -specialised class of Frame (SkyFrame, TimeFrame, SpecFrame, DSBSpecFrame -or FluxFrame). That is, if an instance of one of these classes is used as -the ``template'' when calling -c+ -astFindFrame, -c- -f+ -AST\_FINDFRAME, -f- -and the ``target'' being searched is a CmpFrame (or a FrameSet in which the -current Frame is a CmpFrame), then the component Frames within the CmpFrame -will be searched for an instance of the supplied template Frame, and, if -found, a suitable Mapping (which will include a PermMap to select the -required axes from the CmpFrame) will be returned by -c+ -astFindFrame. -c- -f+ -AST\_FINDFRAME. -f- -Note, for this to work, the MaxAxes and MinAxes attributes of the template -Frame must be set so that they cover a range that includes the number of axes -in the target CmpFrame. - -\item The SkyFrame, SpecFrame, DSBSpecFrame, TimeFrame and FluxFrame classes -now allow the MaxAxes and MinAxes attributes to be set freely to any value. -In previous versions of AST, any attempt to change the value of MinAxes -or MaxAxes was ignored, resulting in them always taking the default values. - -\item The DSBSpecFrame class has a new attribute called AlignSB that -specifies whether or not to take account of the SideBand attributes when -aligning two DSBSpecFrames using -c+ -astConvert. -c- -f+ -AST\_CONVERT. -f- - -\item The Frame class has a new attribute called Dut1 that can be used to -store a value for the difference between the UT1 and UTC timescales at -the epoch referred to by the Frame. - -\item The number of digits used to format the Frame attributes ObsLat and -ObsLon has been increased. - -\item The use of the SkyFrame attribute AlignOffset has been changed. This -attribute is used to control how two SkyFrames are aligned by -c+ -astConvert. -c- -f+ -AST\_CONVERT. -f- -If the template and target SkyFrames both have a non-zero value for -AlignOffset, then alignment occurs between the offset coordinate systems -(that is, a UnitMap will always be used to align the two SkyFrames). - -\item The Plot class has a new attribute called ForceExterior that can be -used to force exterior (rather than interior) tick marks to be produced. -By default, exterior ticks are only produced if this would result in -more than 3 tick marks being drawn. - -\item The TimeFrame class now supports conversion between angle based -timescales such as UT1 and atomic based timescales such as UTC. - -\end{enumerate} - -\subsection{Changes Introduced in V4.5} - -The following describes the most significant changes that -occurred in the AST library between versions V4.4 and V4.5: - -\begin{enumerate} - - - -\item All FITS-CLASS headers are now created with a frequency axis. If the -FrameSet supplied to -c+ -astWrite -c- -f+ -AST\_WRITE -f- -contains a velocity axis (or any other form -of spectral axis) it will be converted to an equivalent frequency axis -before being used to create the FITS-CLASS header. - -\item The value stored in the FITS-CLASS keyword ``VELO-LSR'' has been changed -from the velocity of the source to the velocity of the reference channel. - -\item Addition of a new method call -c+ -astPurgeWCS -c- -f+ -AST\_PURGEWCS -f- -to the FitsChan -class. This method removes all WCS-related header cards from a FitsChan. - -\item The Plot class has a new attribute called GrfContext that can be used -to comminicate context information between an application and any -graphics functions registered with the Plot class via the -c+ -astGrfSet function. -c- -f+ -AST\_GRFSET routine. -f- -\item Functions registered with the Plot class using -c+ -astGrfSet -c- -f+ -AST\_GRFSET -f- -now take a new additional integer parameter, ``grfcon''. The Plot class -sets this parameter to the value of the Plot's GrfContext attribute before -calling the graphics function. NOTE, THIS CHANGE WILL REQUIRE EXISTING -CODE THAT USES -c+ -astGrfSet -c- -f+ -AST\_GRFSET -f- -TO BE MODIFIED TO INCLUDE THE NEW PARAMETER. -\item The -c+ -astRebinSeq functions -c- -f+ -AST\_REBINSEQ routines -f- -now have an extra parameter that is used to record the total number of input -data values added into the output array. This is necessary to correct a -flaw in the calculation of output variances based on the spread of input -values. NOTE, THIS CHANGE WILL REQUIRE EXISTING CODE TO BE MODIFIED TO -INCLUDE THE NEW PARAMETER (CALLED "NUSED"). -\item Support has been added for the FITS-WCS ``HPX'' (HEALPix) projection. -\item A new flag ``AST\_\_VARWGT'' can be supplied to -c+ -astRebinSeq. -c- -f+ -AST\_REBINSEQ. -f- -This causes the input data values to be weighted using the reciprocals of -the input variances (if supplied). - -\item The Frame class has a new read-only attribute called NormUnit that -returns the normalised value of the Unit attribute for an axis. Here, -``normalisation'' means cancelling redundant units, etc. So for instance, a -Unit value of ``s*(m/s)'' would result in a NormUnit value of ``m''. - -\item A new -c+ -function astShowMesh -c- -f+ -routine AST\_SHOWMESH -f- -has been added to the Region class. It displays a mesh of points covering -the surface of a Region by writing out a table of axis values to standard -output. - -\item The Plot class now honours the value of the LabelUp attribute even if -numerical labels are placed around the edge of the Plot. Previously -LabelUp was only used if the labels were drawn within the interior of -the plot. The LabelUp attribute controls whether numerical labels are -drawn horizontally or parallel to the axis they describe. - -\item A bug has been fixed that could segmentation violations when setting -attribute values. - -\end{enumerate} - -\subsection{Changes Introduced in V4.6} - -The following describes the most significant changes which have -occurred in the AST library between versions V4.5 and V4.6: - -\begin{enumerate} - -\item The TimeFrame class now support Local Time as a time scale. The offset -from UTC to Local Time is specified by a new TimeFrame attribute called -LTOffset. - -\item A new class called Plot3D has been added. The Plot3D class allows -the creation of 3-dimensional annotated coordinate grids. - -\item A correction for diurnal aberration is now included when -converting between AZEL and other celestial coordinate systems. The -correction is based on the value of the ObsLat Frame attribute (the -geodetic latitude of the observer). - -\item A bug has been fixed which caused the DUT1 attribute to be ignored -by the SkyFrame class when finding conversions between AZEL and other -celestial coordinate systems. - -\end{enumerate} - -\subsection{Changes Introduced in V5.0} - -The following describes the most significant changes which -occurred in the AST library between versions V4.6 and V5.0: - -\begin{enumerate} - - -\item The AST library is now thread-safe (assuming that the POSIX pthreads -library is available when AST is built). Many of the macros defined in -the ast.h header file have changed. It is therefore necessary to -re-compile all source code that includes ast.h. - -\item New methods astLock and astUnlock allow an AST Object to be locked -for exclusive use by a thread. - -\item The TimeFrame class now support Local Time as a time scale. The offset -from UTC to Local Time is specified by a new TimeFrame attribute called -LTOffset. - -\item The Channel class has a new attribute called Strict which controls -whether or not to report an error if unexpected data items are found -within an AST Object description read from an external data source. Note, -the default behaviour is now not to report such errors. This differs from -previous versions of AST which always reported an error is unexpected -input items were encountered. - -\end{enumerate} - -\subsection{Changes Introduced in V5.1} - -The following describes the most significant changes which occurred in the -AST library between versions V5.0 and V5.1: - -\begin{enumerate} - -c+ -\item The astUnlock function now has an extra parameter that controls whether -or not an error is reported if the Object is currently locked by another -thread. -c- - -\item The Prism class has been modified so that any class of Region can -be used to define the extrusion axes. Previously, only a Box or Interval -could be used for this purpose. - -c+ -\item The values of the AST\_\_THREADSAFE macro (defined in ast.h) have -been changed from ``yes'' and ``no'' to ``1'' and ``0''. -c- - -\item Improvements have been made to the way that Prisms are simplified -when -c+ -astSimplify -c- -f+ -AST\_SIMPLIFY -f- -is called. The changes mean that more types of Prism will now simplify -into a simpler class of Region. - -\item The PointList class has a new method, -c+ -astPoints, -c- -f+ -AST\_POINTS, -f- -that copies the axis values from the PointList into a supplied array. - -\item The PointList class has a new (read-only) attribute, ListSize, that -gives the number of points stored in the PointList. - -\item The handling of warnings within different classes of Channel has -been rationalised. The XmlStrict attribute and -c+ -astXmlWarnings -c- -f+ -AST\_XMLWARNINGS -f- -function have been removed. The same functionality is now available via -the existing Strict attribute (which has had its remit widened), a new -attribute called ReportLevel, and the new -c+ -astWarnings -c- -f+ -AST\_WARNINGS -f- -function. This new function can be used on any class of Channel. Teh -FitsChan class retains its long standing ability to store warnings as -header cards within the FitsChan, but it also now stores warnings in the -parent Channel structure, from where they can be retrieved using the -c+ -astWarnings -c- -f+ -AST\_WARNINGS -f- -function. - -\item A new function called -c+ -astIntercept -c- -f+ -AST\_INTERCEPT -f- -has been added to the Frame class. This function finds the point of -intersection beteeen two geodesic curves. - -\item A bug in the type-checking of Objects passed as arguments to constructor -functions has been fixed. This bug could lead to applications crashing or -showing strange behaviour if an inappropriate class of Object was -supplied as an argument to a constructor. - -\item The -c+ -astPickAxes -c- -f+ -AST\_PICKAXES -f- -function will now return a Region, if possible, when applied to a Region. If -this is not possible, a Frame will be returned as before. - -\item The choice of default tick-mark for time axes has been improved, to avoid -previous issues which could result in no suitable gap being found, or -inappropriate tick marks when using formatted dates. - -\item A new function called -c+ -astTestFits -c- -f+ -AST\_TESTFITS -f- -has been added to the FitsChan class. This function tests a FitsChan to -see if it contains a defined value for specified FITS keyword. - -\item The AST\_\_UNDEF<X> parameters used to flag undefined FITS keyword values -have been removed. Use the new -c+ -astTestFits -c- -f+ -AST\_TESTFITS -f- -function instead. - -c+ -\item The astIsUndef<X> functions used to test FITS keyword values -have been removed. Use the new astTestFits function instead. -c- - -\end{enumerate} - -\subsection{Changes Introduced in V5.2} - -The following describes the most significant changes which -occurred in the AST library between versions V5.1 and V5.2: - -\begin{enumerate} - -\item A new method called -c+ -astSetFitsCM -c- -f+ -AST\_SETFITSCM -f- -has been added to the FitsChan class. It stores a pure comment card in a -FitsChan (that is, a card with no keyword name or equals sign). - -\item A new attribute called ObsAlt has been added to the Frame class. It -records the geodetic altitude of the observer, in metres. It defaults to -zero. It is used when converting times to or from the TDB timescale, or -converting spectral positions to or from the topocentric rest frame, or -converting sky positions to or from horizon coordinates. The FitsChan -class will include its effect when creating a set of values for the -OBSGEO-X/Y/Z keywords, and will also assign a value to it when reading a -set of OBSGEO-X/Y/Z keyword values from a FITS header. - -\item The TimeMap conversions ``TTTOTDB'' and ``TDBTOTT'', and the SpecMap -conversions ``TPF2HL'' and ``HLF2TP'', now have an additional argument - -the observer's geodetic altitude. - -\item The Polygon class has been modified to make it consistent with the -IVOA STC definition of a Polygon. Specifically, the inside of a polygon -is now the area to the left of each edge as the vertices are traversed in -an anti-clockwise manner, as seen from the inside of the celestial sphere. -Previously, AST used the anti-clockwise convention, but viewed from the -outside of the celestial sphere instead of the inside. Any Polygon saved -using previous versions of AST will be identified and negated automatically -when read by AST V5.2. - -\item A new class of Channel, called StcsChan, has been added that allows -conversion of suitable AST Objects to and from IVOA STC-S format. - -\item A new method called -c+ -astRemoveRegions -c- -f+ -AST\_REMOVEREGIONS -f- -has been added to the Mapping class. It searches a (possibly compound) -Mapping (or Frame) for any instances of the AST Region class, and either -removes them, or replaces them with UnitMaps (or equivalent Frames). It -can be used to remove the masking effects of Regions from a compound -Mapping or Frame. - -\item A new method called -c+ -astDownsize -c- -f+ -AST\_DOWNSIZE -f- -has been added to the Polygon class. It produces a new Polygon that -contains a subset of the vertices in the supplied Polygon. The subset is -chosen to retain the main features of the supplied Polygion, in so far -as that is possible, within specified constraints. - -\item A new constructor called -c+ -astOutline -c- -f+ -AST\_OUTLINE -f- -has been added to the Polygon class. Given a 2D data array, it identifies -the boundary of a region within the array that holds pixels with -specified values. It then creates a new Polygon to describe this boundary -to a specified accuracy. - -\item A new set of methods, called -c+ -astMapGetElem<X> -c- -f+ -AST\_MAPGETELEM<X> -f- -has been added to the KeyMap class. They allow a single element of a vector -valued entry to be returned. - -\item A new attribute called KeyError has been added to the KeyMap Class. It -controls whether the -c+ -astMapGet... -c- -f+ -AST\_MAPGET... -f- -family of functions report an error if an entry with the requested key does -not exist in the KeyMap. - -\end{enumerate} - -\subsection{Changes Introduced in V5.3} - -The following describes the most significant changes which -occurred in the AST library between versions V5.2 and V5.3: - -\begin{enumerate} - -\item The details of how a Frame is aligned with another Frame by the -c+ -astFindFrame and astConvert -c- -f+ -AST\_FINDFRAME and AST\_CONVERT -f- -functions have been changed. The changes mean that a Frame can now be -aligned with an instance of a sub-class of Frame, so long as the number -of axes and the Domain values are consistent. For instance, a basic -2-dimensional Frame with Domain ``SKY'' will now align succesfully with -a SkyFrame, conversion between the two Frames being achieved using a -UnitMap. - -c+ -\item The arrays that supply input values for astMapPut1<X> are now -declared ``const''. -c- - -\item Added method -c+ -astMatchAxes -c- -f+ -AST\_MATCHAXES -f- -to the Frame class. This method allows corresponding axes within two -Frames to be identified. - -\item The -c+ -astAddFrame -c- -f+ -AST\_ADDFRAME -f- -method can now be used to append one or more axes to all Frames in a FrameSet. -\end{enumerate} - -\subsection{Changes Introduced in V5.3-1} - -The following describes the most significant changes which have -occurred in the AST library between versions V5.3 and V5.3-1: - -\begin{enumerate} - -c+ -\item The utility functions provided by the AST memory management layer -are now documented in an appendix. -c- - -\item The KeyMap class now supports entries that have undefined values. A -new method called -c+ -astMapPutU -c- -f+ -AST\_MAPPUTU -f- -will store an entry with undefined value in a keymap. Methods that -retrieve values from a KeyMap -c+ -(astMapGet0<X>, etc.) -c- -f+ -(AST\_MAPGET0<X>, etc.) -f- -ignore entries with undefined values when searching for an entry with a given -key. - -\item The KeyMap class has a new method called -c+ -astMapCopy -c- -f+ -AST\_MAPCOPY -f- -that copies entries from one KeyMap to another KeyMap. - -\item The KeyMap class has a new boolean attribute called MapLocked. If -c+ -non-zero, -c- -f+ -.TRUE., -f- -an error is reported if an attempt is made to add any new entries -to a KeyMap (the value associated with any old entry may still be changed -without error). The default is -c+ -zero. -c- -f+ -.FALSE. -f- - -\item The Object class has a new method called astHasAttribute/AST\_HASATTRIBUTE -that returns a boolean value indicating if a specified Object has a named -attribute. - -\item The SkyFrame class has two new read-only boolean attributes called -IsLatAxis and IsLonAxis that can be used to determine the nature of a -specified SkyFrame axis. - -\item A bug has been fixed in the -c+ -astRebin(Seq) -c- -f+ -AST\_REBIN(SEQ) -f- -methods that could cause flux to be lost from the edges of the supplied array. - -\item A bug has been fixed in the -c+ -astRebin(Seq) -c- -f+ -AST\_REBIN(SEQ) -f- -methods that caused the first user supplied parameter to be interpreted as the -full width of the spreading kernel, rather than the half-width. - -\item The StcsChan class now ignores case when reading STC-S phrases (except -that units strings are still case sensitive). - -\item A new Mapping method, -c+ -astQuadApprox, -c- -f+ -AST\_QUADAPPROX, -f- -produces a quadratic least-squares fit to a 2D Mapping. - -\item A new Mapping method, -c+ -astSkyOffsetMap, -c- -f+ -AST\_SKYOFFSETMAP, -f- -produces a Mapping from absolute SkyFrame coordinates to offset SkyFrame -coordinates. - -\item The Channel class now has an Indent attribute that controls indentation -in the text created by -c+ -astWrite. -c- -f+ -AST\_WRITE. -f- -The StcsIndent and XmlIndent attributes have been removed. - -\item All classes of Channel now use the string ``<bad>'' to represent the -floating point value AST\_\_BAD, rather than the literal formatted value -(typically ``-1.79769313486232e+308'' ). - -\item The KeyMap class now uses the string ``<bad>'' to represent the -floating point value AST\_\_BAD, rather than the literal formatted value -(typically ``-1.79769313486232e+308'' ). - -\item The KeyMap class has a new method called -c+ -astMapPutElem<X> -c- -f+ -AST\_MAPPUTELEM<X> -f- -that allows a value to be put into a single element of a vector entry in -a KeyMap. The vector entry is extended automatically to hold the new -element if required. - -\item The DSBSpecFrame class now reports an error if the local oscillator -frequency is less than the absoliute value of the intermediate frequency. - -\end{enumerate} - - -\subsection{Changes Introduced in V5.3-2} - -The following describes the most significant changes which -occurred in the AST library between versions V5.3-1 and V5.3-2: - -\begin{enumerate} - -\item A bug has been fixed in the FitsChan class that could cause wavelength -axes to be assigned the units ``m/s'' when reading WCS information from a -FITS header. - -\item The -c+ -astSet function -c- -f+ -AST\_SET routine -f- -now allows literal commas to be included in string attribute values. String -attribute values that include a literal comma should be enclosed in quotation -marks. - -\item A bug in FitsChan has been fixed that caused ``-SIN'' projection -codes within FITS-WCS headers to be mis-interpreted, resulting in no -FrameSet being read by astRead. - -\item The KeyMap class has a new attribute called ``SortBy''. It controls -the order in which keys are returned by the -c+ -astMapKey -c- -f+ -AST\_MAPKEY -f- -function. Keys can be sorted alphabetically or by age, or left unsorted. - -\item Access to KeyMaps holding thousands of entries is now significantly -faster. - -\item KeyMaps can now hold word (i.e. -c+ -short integer) -c- -f+ -INTEGER*2) -f- -values. - -\end{enumerate} - - -\subsection{Changes Introduced in V5.4-0} - -The following describes the most significant changes which -occurred in the AST library between versions V5.3-2 and V5.4-0: - -\begin{enumerate} - -\item the FitsChan class now has an option to support reading and writing -of FITS-WCS headers that use the -TAB algorithm described in FITS-WCS paper -III. This option is controlled by a new FitsChan attribute called TabOK. -See the documentation for TabOK for more information. - -\item A new class called ``Table'' has been added. A Table is a KeyMap in -which each entry represents a cell in a two-dimensional table. - -\item A new class called ``FitsTable'' has been added. A FitsTable is a -Table that has an associated FitsChan holding headers appropriate to a -FITS binary table. - -\item KeyMaps can now hold byte values. These are held in variables -of type -c+ -"unsigned char". -c- -f+ -BYTE. -f- - -\item KeyMaps have a new attribute called KeyCase that can be set to zero to -make the handling of keys case insensitive. - -\item a memory leak associated with the use of the -c+ -astMapPutElem<X> -c- -f+ -AST\_MAPPUTELEM<X> -f- -functions has been fixed. - -\item A new method called -c+ -astMapRename -c- -f+ -AST\_MAPRENAME -f- -has been added to rename existing entry in a KeyMap. -\end{enumerate} - -\subsection{Changes Introduced in V5.5-0} - -The following describes the most significant changes which -occurred in the AST library between versions V5.4-0 and V5.5-0: - -\begin{enumerate} - -\item The FitsChan ``TabOK'' attribute is now an integer value rather -than a boolean value. If TabOK is set to a non-zero positive integer -before invoking the -c+ -astWrite -c- -f+ -AST\_WRITE -f- -method, its value is used as the version number for any table that is -created as a consequence of the write operation. This is the value stored -in the PVi\_1a keyword in the IMAGE header, and the EXTVER keyword in the -binary table header. In previous versions of AST, the value used for these -headers could not be controlled and was fixed at 1. If TabOK is set to a -negative or zero value, the -TAB algorithm will not be supported by -either the -c+ -astWrite or astRead -c- -f+ -AST\_WRITE or AST\_READ -f- -methods. - -\end{enumerate} - - - -\subsection{Changes Introduced in V5.6-0} - -The following describes the most significant changes which -occurred in the AST library between versions V5.5-0 and V5.6-0: - -\begin{enumerate} - -\item -c+ -New functions astBBuf and astEBuf -c- -f+ -New routines AST\_BBUF and AST\_EBUF -f- -have been added to the Plot class. These control the buffering of graphical -output produced by other Plot methods. - -\item New functions astGBBuf and astGEBuf have been added to the interface -defined by file \verb+grf.h+. The ast\_link command has been modified so -that the \verb+-grf_v3.2+ switch loads dummy versions of the new grf -functions. This means that applications that use the \verb+-grf_v3.2+ -switch should continue to build without any change. However, the new public -c+ -functions astBBuf and astEBuf -c- -f+ -routines AST\_BBUF and AST\_EBUF -f- -will report an error unless the new grf functions are implemented. If you -choose to implement them, you should modify your linking procedure to -use the \verb+-grf+ (or \verb+-grf_v5.6+ ) switch in place of the older -\verb+-grf_v3.2+ switch. See the description of the ast\_link command for -details of these switches. - -\item New method -c+ -astGetRegionMesh -c- -f+ -AST\_GETREGIONMESH -f- -returns a set of positions covering the boundary, or volume, of a supplied -Region. - -\end{enumerate} - - -\subsection{ChangesIntroduced in V5.6-1} - -The following describes the most significant changes which -occurred in the AST library between versions V5.6-0 and V5.6-1: - -\begin{enumerate} - -\item Tables can now have any number of parameters describing the global -properties of the Table. - -\item Frames now interpret the unit string ``A'' as meaning ``Ampere'' -rather than ``Angstrom'', as specified by FITS-WCS paper I. - -\item A bug has been fixed in the -c+ -astFindFrame -c- -f+ -AST\_FINDFRAME -f- -method that allowed a template Frame of a more specialised class to match -a target frame of a less specialised class. For example, this bug would -allow a template SkyFrame to match a target Frame. This no longer -happens. - -\end{enumerate} - -\subsection{Changes Introduced in V5.7-0} - -The following describes the most significant changes which -occurred in the AST library between versions V5.6-1 and V5.7-0: - -\begin{enumerate} - -\item The FitsChan class support for the IRAF-specific ``TNX'' projection has -been extended to include reading TNX headers that use a Chebyshev -representation for the distortion polynomial. - -\item The FitsChan class support for the IRAF-specific ``ZPX'' projection has -been extended to include reading ZPX headers that use simple or Chebyshev -representation for the distortion polynomial. - -\item A bug has been fixed in the FitsChan class that caused headers -including the Spitzer ``-SIP'' distortion code to be read incorrectly if no -inverse polynomial was specified in the header. - -\item A new attribute called PolyTan has been added to the FitsChan class. It -can be used to indicate that FITS headers that specify a TAN projection -should be interpreted according to the ``distorted TAN'' convention -included in an early draft of FITS-WCS paper II. Such headers are created -by (for instance) the SCAMP tool (\url{http://www.astromatic.net/software/scamp}). - -\item The PolyMap class now provides a method called -c+ -astPolyTran -c- -f+ -AST\_POLYTRAN -f- -that adds an inverse transformation to a PolyMap by sampling the forward -transformation on a regular grid, and then fitting a polynomial function -from the resulting output values to the grid of input values. - -\end{enumerate} - -\subsection{Changes Introduced in V5.7-1} - -The following describes the most significant changes which -occurred in the AST library between versions V5.7-0 and V5.7-1: - -\begin{enumerate} - -\item - All classes of Channel can now read to and write from specified -text files, without the need to provide source and sink functions when -the Channel is created. The files to use are specified by the new -attributes SourceFile and SinkFile. - -\item - The FitsChan class now ignores trailing spaces in character-valued WCS -keywords when reading a FrameSet from a FITS header. - -\item - If the FitsChan astRead method reads a FITS header that uses the --SIP (Spitzer) distortion code within the CTYPE values, but which does -not provide an inverse polynomial correction, the FitsChan class will now -use the PolyTran method of the PolyMap class to create an estimate of the -inverse polynomial correction. - -\end{enumerate} - - -\subsection{Changes Introduced in V5.7-2} - -The following describes the most significant changes which -occurred in the AST library between versions V5.7-1 and V5.7-2: - -\begin{enumerate} - -c+ -\item The Object class has a new function astToString (C only), which creates -an in-memory textual serialisation of a given AST Object. A corresponding -new function called astFromString re-creates the Object from its -serialisation. -c- - -\item The PolyMap class can now use an iterative Newton-Raphson method to -evaluate the inverse the inverse transformation if no inverse -transformation is defined when the PolyMap is created. - -\item The FitsChan class has a new method -c+ -astWriteFits -c- -f+ -AST\_WRITEFITS -f- -which writes out all cards currently in the FitsChan to the associated -external data sink (specified either by the SinkFile attribute or the -sink function supplied when the FitsChan was created), and then empties -the FitsChan. - -\item The FitsChan class has a new read-only attribute called ``Nkey'', which -holds the number of keywords for which values are held in a FitsChan. - -\item The FitsChan -c+ -astGetFits<X> -c- -f+ -AST\_GETFITS<X> -f- -methods can now be used to returned the value of the current card. - -\item The FitsChan class has a new read-only attribute called ``CardType'', which -holds the data type of the keyword value for the current card. - -\item The FitsChan class has a new method -c+ -astReadFits -c- -f+ -AST\_READFITS -f- -which forces the FitsChan to reads cards from the associated external -source and appends them to the end of the FitsChan. - -\item - If the FitsChan astRead method reads a FITS header that uses the --SIP (Spitzer) distortion code within the CTYPE values, but which does -not provide an inverse polynomial correction, and for which the PolyTran -method of the PolyMap class fails to create an accurate estimate of the -inverse polynomial correction, then an iterative method will be used to -evaluate the inverse correction for each point transformed. - -\end{enumerate} - -\subsection{Changes Introduced in V6.0} - -The following describes the most significant changes which -occurred in the AST library between versions V5.7-2 and V6.0: - -\begin{enumerate} - -\item This version of AST is the first that can be used with the Python -AST wrapper module, starlink.Ast, available at \url{http://github.com/timj/starlink-pyast}. - -\item When reading a FITS-WCS header, the FitsChan class now recognises the -non-standard ``TPV'' projection code within a CTYPE keyword value. This -code is used by SCAMP (see www.astromatic.net/software/scamp) to -represent a distorted TAN projection. - -\item The Plot class has been changed to remove visual anomalies (such as -incorrectly rotated numerical axis labels) if the graphics coordinates have -unequal scales on the X and Y axes. - -- The graphics escape sequences used to produce graphical sky axis labels -can now be changed using the new -c+ -function astTuneC. -c- -f+ -routine AST\_TUNEC. -f- - -\end{enumerate} - -\subsection{Changes Introduced in V6.0-1} - -The following describes the most significant changes which -occurred in the AST library between versions V6.0 and V6.0-1: - -\begin{enumerate} - -\item The FitsChan class now recognises the Spitzer ``-SIP'' distortion -code within FITS headers that describe non-celestial axes, as well as -celestial axes. - -\item A bug has been fixed that could cause inappropriate equinox values to -be used when aligning SkyFrames if the AlignSystem attribute is set. - -\item The versioning string for AST has changed from -``$<major>.<minor>-<release>$'' to ``$<major>.<minor>.<release>$''. - -\end{enumerate} - -\subsection{Changes Introduced in V7.0.0} - -The following describes the most significant changes which -occurred in the AST library between versions V6.0-1 and V7.0.0: - -\begin{enumerate} - -\item Fundamental positional astronomy calculations are now performed -using the IAU SOFA library where possible, and the Starlink PAL library \xref{SUN/268}{sun268}{} -otherwise (the PAL library contains a subset of the Fortran Starlink SLALIB -library re-written in C). Copies of these libraries are bundled with AST -and so do not need to be obtained or built separately, although external -copies of SOFA and PAL can be used if necessary by including the -``\texttt{--with-external\_pal}'' option when configuring AST. - -\end{enumerate} - -\subsection{Changes Introduced in V7.0.1} - -The following describes the most significant changes which -occurred in the AST library between versions V7.0.0 and V7.0.1: - -\begin{enumerate} - -\item The levmar and wcslib code distributed within AST is now stored in the -main AST library (libast.so) rather than in separate libraries. - -\end{enumerate} - -\subsection{Changes Introduced in V7.0.2} - -The following describes the most significant changes which -occurred in the AST library between versions V7.0.1 and V7.0.2: - -\begin{enumerate} - -\item The libast\_pal library is no longer built if the -``--with-external\_pal'' option is used when AST is configured. - -\end{enumerate} - -\subsection{Changes Introduced in V7.0.3} - -The following describes the most significant changes which -occurred in the AST library between versions V7.0.2 and V7.0.3: - -\begin{enumerate} - -\item A bug has been fixed which could cause an incorrect axis to be used when -accessing axis attributes within CmpFrames. This could happen if axes -within the CmpFrame have been permuted. - -\item A bug has been fixed in the SkyFrame class that could cause the two -values of the SkyRef and/or SkyRefP attributes to be reversed. - -\item Bugs have been fixed in the CmpRegion class that should allow the border -around a compound Region to be plotted more quickly, and more accurately. -Previously, component Regions nested deeply inside a CmpRegion may have -been completely or partially ignored. - -\item A bug has been fixed in the Plot3D class that caused a segmentation -violation if the MinTick attribute was set to zero. - -\item The astResampleX set of methods now includes astResampleK and -astResampleUK that handles 64 bit integer data. - -\end{enumerate} - - -\subsection{Changes Introduced in V7.0.4} - -The following describes the most significant changes which -occurred in the AST library between versions V7.0.3 and V7.0.4: - - -\begin{enumerate} - -\item The previously private grf3d.h header file is now installed into -prefix/include. - -\end{enumerate} - - -\subsection{Changes Introduced in V7.0.5} - -The following describes the most significant changes which -occurred in the AST library between versions V7.0.4 and V7.0.5: - -\begin{enumerate} - -\item The FitsChan class can now read FITS headers that use the SAO -convention for representing distorted TAN projections, based on the use -of ``COi\_m'' keywords to hold the coefficients of the distortion polynomial. - -\end{enumerate} - - -\subsection{Changes Introduced in V7.0.6} - -The following describes the most significant changes which -occurred in the AST library between versions V7.0.5 and V7.0.6: - -\begin{enumerate} - -\item A bug has been fixed in astRebinSeq<X> which could result in -incorrect normalisation of the final binned data and variance values. - -\item When reading a FrameSet from a FITS-DSS header, the keywords CNPIX1 -and CNPIX2 now default to zero if absent. Previously an error was reported. - -\end{enumerate} - - -\subsection{Changes Introduced in V7.1.0} - -The following describes the most significant changes which occurred in the -AST library between versions V7.0.6 and V7.1.0: - -\begin{enumerate} - -\item IMPORTANT! The default behaviour of astRebinSeq is now NOT to conserve -flux. To conserve flux, the AST\_\_CONSERVEFLUX flag should be supplied -when calling -c+ -astRebinSeq<X>. -c- -f+ -AST\_REBINSEQ<X>. -f- -Without this flag, each output value is a weighted mean of the neighbouring -input values. - -\item A new flag AST\_\_NONORM can be used with astRebinSeq<X> to indicate that -normalisation of the output arrays is not required. In this case no -weights array need be supplied. - -\item A bug has been fixed in -c+ -astAddFrame method -c- -f+ -AST\_ADDFRAME routine -f- -that could result in the incorrect inversion of Mappings within the FrameSet -when the AST\_\_ALLFRAMES flag is supplied for the -c+ -"iframe" parameter. -c- -f+ -IFRAME argument. -f- - -\item The -c+ -astRate method -c- -f+ -AST\_RATE function -f- -has been re-written to make it faster and more reliable. - -\end{enumerate} - -\subsection{Changes Introduced in V7.1.1} - -The following describes the most significant changes which -occurred in the AST library between versions V7.1.0 and V7.1.1: - -\begin{enumerate} - -\item When a FitsChan is used to write an ``offset'' SkyFrame (see attribute -SkyRefIs) to a FITS-WCS encoded header, two alternate axis descriptions -are now created - one for the offset coordinates and one for the absolute -coordinates. If such a header is subsequently read back into AST, the -original offset SkyFrame is recreated. - -\item A bug has been fixed in FitsChan that caused inappropriate CTYPE values -to be generated when writing a FrameSet to FITS-WCS headers if the -current Frame describes generalised spherical coordinates (i.e. a -SkyFrame with System=Unknown). - -\end{enumerate} - -\subsection{Changes Introduced in V7.2.0} - -The following describes the most significant changes which -occurred in the AST library between versions V7.1.1 and V7.2.0: - -\begin{enumerate} - -\item A new method call -c+ -astMapDefined -c- -f+ -AST\_MAPDEFINED -f- -has been added to the KeyMap class. It checks if a gtiven key name has -a defined value in a given KeyMap. - -\end{enumerate} - -\subsection{Changes Introduced in V7.3.0} - -The following describes the most significant changes which -occurred in the AST library between versions V7.2.0 and V7.3.0: - -\begin{enumerate} - -c+ -\item The interface for the astRebinSeq<X> family of functions has -been changed in order to allow a greater number of pixels to be pasted -into the output array. The "nused" parameter is now a pointer to a -"int64\_t" variable, instead of an "int". APPLICATION CODE SHOULD BE -CHANGED ACCORDINGLY TO AVOID SEGMENTATION FAULTS AND OTHER ERRATIC -BEHAVIOUR. -c- -f+ -\item The interface for the AST\_REBINSEQ<X> family of routines has -been changed in order to allow a greater number of pixels to be pasted -into the output array. The NUSED parameter is now an INTEGER*8 variable, -instead of an INTEGER. APPLICATION CODE SHOULD BE CHANGED ACCORDINGLY TO -AVOID SEGMENTATION FAULTS AND OTHER ERRATIC BEHAVIOUR. -f- - -\item Added a new facility to the FrameSet class to allow each Frame to be -associated with multiple Mappings, any one of which can be used to -connect the Frame to the other Frames in the FrameSet. The choice of -which Mapping to use is controlled by the new ``Variant'' attribute of the -FrameSet class. - -\item Mappings (but not Frames) that have a value set for their Ident -attribute are now left unchanged by the -c astSimplify function. -f AST\_SIMPLIFY routine. - -\end{enumerate} - -\subsection{Changes Introduced in V7.3.1} - -The following describes the most significant changes which -occurred in the AST library between versions V7.3.0 and V7.3.1: - -\begin{enumerate} - -\item Fix a bug that could cauise a segmentation violation when reading -certain FITS headers that use a TNX projection. - -\end{enumerate} - -\subsection{Changes Introduced in V7.3.2} - -The following describes the most significant changes which -occurred in the AST library between versions V7.3.1 and V7.3.2: - -\begin{enumerate} - -\item Fix support for reading FITS header that use a GLS projection. -Previously, an incorrect transformation was used for such projections if -any CRVAL or CROTA value was non-zero. - -\item The KeyMap class has new sorting options ``KeyAgeUp'' and -``KeyAgeDown'' that retain the position of an existing entry if its value -is changed. See the SortBy attribute. - -\item A bug has been fixed in the FitsChan class that caused CDELT keywords -for sky axes to be treated as radians rather than degrees when reading a -FITS header, if the corresponding CTYPE values included no projection code. - -\end{enumerate} - -\subsection{Changes Introduced in V7.3.3} - -The following describes the most significant changes which -occurred in the AST library between versions V7.3.2 and V7.3.3: - -\begin{enumerate} - -\item The FitsChan class has new attributes CardName and CardComm, which hold -the keyword name and comment of the current card. - -\item When using the FitsChan class to read FITS-WCS headers that include -polynomial distortion in the SIP format, any inverse transformation specified -in the header is now ignored and a new inverse is created to replace it based -on the supplied forward transformation. Previously, an inverse was created -only if the header did not include an inverse. The accuracy of the inverse -transformation has also been improved, although it may now be slower to -evaluate in some circumstances. - -\end{enumerate} - -\subsection{Changes Introduced in V7.3.4} - -The following describes the most significant changes which -occurred in the AST library between versions V7.3.3 and V7.3.4: - -\begin{enumerate} - -\item By default, the simplification of Polygons no longer checks that the -edges are not bent by the simplification. A new attribute, SimpVertices, -can be set to zero in order to re-instate this check. - -\item The Polygon class has a new mathod, -c+ -astConvex, -c- -f+ -AST\_CONVEX, -f- -that returns a Polygon representing the shortest polygon (i.e. convex -hull) enclosing a specified set of pixel values within a supplied array. - -\end{enumerate} - -\subsection{Changes Introduced in V8.0.0} - -The following describes the most significant changes which -occurred in the AST library between versions V7.3.4 and V8.0.0: - -\begin{enumerate} - -\item AST is now distributed under the Lesser GPL licence. - -\item The PolyMap class now uses files copied from the C/C++ Minpack -package (see \url{http://devernay.free.fr/hacks/cminpack/index.html}) to perform -least squares fitting of N-dimensional polynomials. - -\item Use of the IAU SOFA library has been replaced by ERFA library, which is -a re-badged copy of SOFA distributed under a less restrictive license. A -copy of ERFA is included within AST. - -\end{enumerate} - -\subsection{Changes Introduced in V8.0.1} - -The following describes the most significant changes which -occurred in the AST library between versions V8.0.0 and V8.0.1: - -\begin{enumerate} - -\item The Base and Current attributes of a FrameSet may now be set using the - Domain name or the index of the required Frame. -\item The order of WCS axes within new FITS-WCS headers created by astWrite - can now be controlled using a new attribute called FitsAxisOrder. -\item Supported added for FITS XPH (polar HEALPIX) projection. -c+ -\item The macro used to invoke the astAppendString utility function has - changed to allow printf-style converstions to be included in the - supplied text. Any code that uses this macro must be re-compiled. -\item The astRebin and astRebinSeq family of functions now include support - for arrays with char (byte) and unsigned char (unsigned byte) data types. -c- -f+ -\item The AST\_REBIN and AST\_REBINSEQ family of functions now include support - for arrays with \_BYTE (byte) and and \_UBYTE (unsigned byte) data types. -f- - -\end{enumerate} - -\subsection{Changes Introduced in V8.0.2} -c+ -The following describes the most significant changes which -occurred in the AST library between versions V8.0.1 and V8.0.2: - -\begin{enumerate} -\item For security reasons, the change introduced to astAppendString in - V8.0.1 has been moved to a new function called astAppendStringf, and - astAppendString itself has been reverted to its V8.0.0 version. - Any software that has been built against V8.0.1 will need to be - re-compiled and re-linked against V8.0.2. -\end{enumerate} - -c- -f+ -The changes that occurred in the AST library between versions V8.0.1 and -V8.0.2 only affect the C interface. The Fortran interface remains the -same as V8.0.1. -f- - -\subsection{Changes Introduced in V8.0.3} -The following describes the most significant changes which -occurred in the AST library between versions V8.0.2 and V8.0.3: - -\begin{enumerate} - -\item Methods -c+ -astRebin, astRebinSeq, astResample and astTranGrid -c- -f+ -AST\_REBIN, AST\_REBINSEQ, AST\_RESAMPLE and AST\_TRANGRID. -f- -now report an error if an array is specified that has more pixels than -can be counted by a 32 bit integer. -\item The hypertext documentation is now generated using Tex4HT rather -than latex2html. The format of the hypertext docs has changed significantly. -\item Another bug fix associated with reading CAR projections from -FITS-WCS headers. -f+ -\item Trailing spaces supplied within attribute setting strings are now ignored. -f- -c+ -\item Constructor options strings of the form ``\texttt{..., "\%s", text );}'' -can now be supplied. This avoids a security issue associated with the -alternative form ``\texttt{..., text );}''. -c- -\end{enumerate} - -\subsection{Changes Introduced in V8.0.4} -The following describes the most significant changes which -occurred in the AST library between versions V8.0.3 and V8.0.4: - -\begin{enumerate} - -\item The behaviour of the -c+ -astAddFrame method has been changed slightly. Previously, astAddFrame -c- -f+ -AST\_ADDFRAME method has been changed slightly. Previously, AST\_ADDFRAME -f- -modified the FrameSet by storing references to the supplied Mapping and -Frame objects within the FrameSet. This meant that any subsequent changes -to the current Frame of the modified FrameSet also affected the supplied -Frame object. Now, deep copies of the Mapping and Frame objects (rather -than references) are stored within the modified FrameSet. This means that -subsequent changes to the modified FrameSet will now have no effect on -the supplied Frame. - -\item The choice of default tick-mark gaps for time axes has been -improved, to avoid a previous issue which could result in no suitable gap -being found. - -- A new method called -c+ -astRegionOutline -c- -f+ -AST\_REGIONOUTLINE -f- -has been added to the Plot class. It draws the outline of a supplied AST -Region. - -\item A bug has been fixed that could cause astSimplfy to enter an infinite loop. - -\item Some improvements have been made to the Mapping simplification process -that allow more Mappings to be simplified. - -\item The Frame class has a new read-only attribute called InternalUnit, -which gives the units used for the unformatted (i.e. floating-point) axis -values used internally by application code. For most Frames, the -InternalUnit value is just the same as the Unit value (i.e. formatted and -unformatted axis values use the same units). However, the SkyFrame class -always returns ``\texttt{rad}'' for InternalUnit, regardless of the value of -Unit, indicating that floating-point SkyFrame axis values are always in units -of radians. - -\item The LutMap class has a new attribute called LutEpsilon, which specifies -the relative error of the values in the table. It is used to decide if -the LutMap can be simplified to a straight line. - -\end{enumerate} - - -\subsection{Changes Introduced in V8.0.5} -The following describes the most significant changes which -occurred in the AST library between versions V8.0.4 and V8.0.5: - -\begin{enumerate} - -\item The SkyFrame class has a new attribute called SkyTol, which specifies -the smallest significant distance within the SkyFrame. It is used to -decide if the Mapping between two SkyFrames can be considered a unit -transformation. The default value is 0.001 arc-seconds. - -\item A bug has been fixed in the FitsChan class that prevented illegal -characters within FITS keyword names (i.e. characters not allowed by the -FITS standard) being detected. This bug could under some circumstances -cause a subsequent segmentation violation to occur. - -- A ``BadKeyName'' warning is now issued by the FitsChan class if a FITS -keyword name is encountered that contains any illegal characters. See -attribute ``Warnings'' and -c+ -function ``astWarnings''. -c- -f+ -routine ``AST\_WARNINGS''. -f- - -\subsection{Changes Introduced in V8.1.0} -The following describes the most significant changes which -occurred in the AST library between versions V8.0.5 and V8.1.0: - -\begin{enumerate} - -\item The configure script has a new option ``--without-fortran'' that allows -AST to be built in situations where no Fortran compiler is available. The -resulting library has no Fortran interface and so cannot be used within -Fortran applications. Also, the link scripts do not attempt to include the -fortran runtime libraries. - -\end{enumerate} - -\subsection{\xlabel{changes}\xlabel{list_of_most_recent_changes}Changes -Introduced in V8.2} -The following describes the most significant changes which have -occurred in the AST library between versions V8.1.0 and V8.2.0 (the -current version): - -\begin{enumerate} - -\item The restriction that Mappings are immutable has been extended to all -Mapping classes. This means that attributes representing parameters of -a Mapping's forward or inverse transformation cannot be changed after -the Mapping has been created. In order to minimise the risk to existing -software, this rule does not apply to Mappings that have not yet been -included in other objects such as CmpMaps or FrameSets, or which have not -yet been cloned. In other words, an error is reported if an attempt is -made to change the nature of a Mapping's transformation, but only if the -reference count of the Mapping is greater than one. The Mapping classes -affected include: GrismMap, LutMap, PcdMap, SphMap, WcsMap and ZoomMap. - -\end{enumerate} - -% Programs which are statically linked will need to be re-linked in -% order to take advantage of these new facilities. - -\end{document} |