summaryrefslogtreecommitdiffstats
path: root/ast/specmap.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2018-09-21 17:02:41 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2018-09-21 17:02:41 (GMT)
commitbd7d67f66c53df36bb50e3423bfc91eae8618201 (patch)
tree343b06f7a9f2decdfa8d3e4aae885be3e909aa14 /ast/specmap.c
parentf2f490ba0f98917b590fd7e538b9514e4119e640 (diff)
downloadblt-bd7d67f66c53df36bb50e3423bfc91eae8618201.zip
blt-bd7d67f66c53df36bb50e3423bfc91eae8618201.tar.gz
blt-bd7d67f66c53df36bb50e3423bfc91eae8618201.tar.bz2
update ast
Diffstat (limited to 'ast/specmap.c')
-rw-r--r--ast/specmap.c4696
1 files changed, 0 insertions, 4696 deletions
diff --git a/ast/specmap.c b/ast/specmap.c
deleted file mode 100644
index 48ada4e..0000000
--- a/ast/specmap.c
+++ /dev/null
@@ -1,4696 +0,0 @@
-/*
-*class++
-* Name:
-* SpecMap
-
-* Purpose:
-* Sequence of spectral coordinate conversions.
-
-* Constructor Function:
-c astSpecMap (also see astSpecAdd)
-f AST_SPECMAP (also see AST_SPECADD)
-
-* Description:
-* A SpecMap is a specialised form of Mapping which can be used to
-* represent a sequence of conversions between standard spectral
-* coordinate systems.
-*
-* When an SpecMap is first created, it simply performs a unit
-c (null) Mapping. Using the astSpecAdd
-f (null) Mapping. Using the AST_SPECADD
-c function, a series of coordinate conversion steps may then be
-f routine, a series of coordinate conversion steps may then be
-* added. This allows multi-step conversions between a variety of
-* spectral coordinate systems to be assembled out of a set of building
-* blocks.
-*
-* Conversions are available to transform between standards of rest.
-* Such conversions need to know the source position as an RA and DEC.
-* This information can be supplied in the form of parameters for
-* the relevant conversions, in which case the SpecMap is 1-dimensional,
-* simply transforming the spectral axis values. This means that the
-* same source position will always be used by the SpecMap. However, this
-* may not be appropriate for an accurate description of a 3-D spectral
-* cube, where changes of spatial position can produce significant
-* changes in the Doppler shift introduced when transforming between
-* standards of rest. For this situation, a 3-dimensional SpecMap can
-* be created in which axes 2 and 3 correspond to the source RA and DEC
-* The SpecMap simply copies values for axes 2 and 3 from input to
-* output), but modifies axis 1 values (the spectral axis) appropriately.
-*
-* For details of the individual coordinate conversions available,
-c see the description of the astSpecAdd function.
-f see the description of the AST_SPECADD routine.
-
-* Inheritance:
-* The SpecMap class inherits from the Mapping class.
-
-* Attributes:
-* The SpecMap class does not define any new attributes beyond those
-* which are applicable to all Mappings.
-
-* Functions:
-c In addition to those functions applicable to all Mappings, the
-c following function may also be applied to all SpecMaps:
-f In addition to those routines applicable to all Mappings, the
-f following routine may also be applied to all SpecMaps:
-*
-c - astSpecAdd: Add a spectral coordinate conversion to an SpecMap
-f - AST_SPECADD: Add a spectral coordinate conversion to an SpecMap
-
-* Copyright:
-* Copyright (C) 1997-2006 Council for the Central Laboratory of the
-* Research Councils
-* Copyright (C) 2009 Science & Technology Facilities Council.
-* All Rights Reserved.
-
-* Licence:
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation, either
-* version 3 of the License, or (at your option) any later
-* version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General
-* License along with this program. If not, see
-* <http://www.gnu.org/licenses/>.
-
-* Authors:
-* DSB: David S. Berry (Starlink)
-
-* History:
-* 6-NOV-2002 (DSB):
-* Original version.
-* 14-JUL-2003 (DSB):
-* Added checks for NAN values produced by transformation functions.
-* 17-SEP-2003 (DSB):
-* - Improve FRTOAW accuracy by iterating.
-* - Changed Refrac to use algorithm given in FITS-WCS paper 3
-* version dated 21/9/03.
-* 14-FEB-2006 (DSB):
-* Override astGetObjSize.
-* 10-MAY-2006 (DSB):
-* Override astEqual.
-* 15-NOV-2006 (DSB):
-* Guard against division by zero when converting freq to wave in
-* SystemChange.
-* 18-JUN-2009 (DSB):
-* Add OBSALT argument to TPF2HL and HLF2TP conversions.
-* Change GEOLON/LAT to OBSLON/LAT for consistency with other
-* classes.
-* 2-OCT-2012 (DSB):
-* Check for Infs as well as NaNs.
-* 1-DEC-2016 (DSB):
-* Added a "narg" argumeent to astSpecAdd.
-
-*class--
-*/
-
-/* Module Macros. */
-/* ============== */
-/* Set the name of the class we are implementing. This indicates to
- the header files that define class interfaces that they should make
- "protected" symbols available. */
-#define astCLASS SpecMap
-
-/* Codes to identify spectral coordinate conversions. */
-#define AST__SPEC_NULL 0 /* Null value */
-#define AST__FRTOVL 1 /* Frequency to relativistic velocity */
-#define AST__VLTOFR 2 /* Relativistic velocity to Frequency */
-#define AST__ENTOFR 3 /* Energy to frequency */
-#define AST__FRTOEN 4 /* Frequency to energy */
-#define AST__WNTOFR 5 /* Wave number to frequency */
-#define AST__FRTOWN 6 /* Frequency to wave number */
-#define AST__WVTOFR 7 /* Wavelength (vacuum) to frequency */
-#define AST__FRTOWV 8 /* Frequency to wavelength (vacuum) */
-#define AST__AWTOFR 9 /* Wavelength (air) to frequency */
-#define AST__FRTOAW 10 /* Frequency to wavelength (air) */
-#define AST__VRTOVL 11 /* Radio to relativistic velocity */
-#define AST__VLTOVR 12 /* Relativistic to radio velocity */
-#define AST__VOTOVL 13 /* Optical to relativistic velocity */
-#define AST__VLTOVO 14 /* Relativistic to optical velocity */
-#define AST__ZOTOVL 15 /* Redshift to relativistic velocity */
-#define AST__VLTOZO 16 /* Relativistic velocity to redshift */
-#define AST__BTTOVL 17 /* Beta factor to relativistic velocity */
-#define AST__VLTOBT 18 /* Relativistic velocity to beta factor */
-#define AST__USF2HL 19 /* User-defined to heliocentric frequency */
-#define AST__HLF2US 20 /* Heliocentric to user-defined frequency */
-#define AST__TPF2HL 21 /* Topocentric to heliocentric frequency */
-#define AST__HLF2TP 22 /* Heliocentric to topocentric frequency */
-#define AST__GEF2HL 23 /* Geocentric to heliocentric frequency */
-#define AST__HLF2GE 24 /* Heliocentric to geocentric frequency */
-#define AST__BYF2HL 25 /* Barycentric to heliocentric frequency */
-#define AST__HLF2BY 26 /* Heliocentric to barycentric frequency */
-#define AST__LKF2HL 27 /* LSRK to heliocentric frequency */
-#define AST__HLF2LK 28 /* Heliocentric to LSRK frequency */
-#define AST__LDF2HL 29 /* LSRD to heliocentric frequency */
-#define AST__HLF2LD 30 /* Heliocentric to LSRD frequency */
-#define AST__LGF2HL 31 /* Local group to heliocentric frequency */
-#define AST__HLF2LG 32 /* Heliocentric to local group frequency */
-#define AST__GLF2HL 33 /* Galactic to heliocentric frequency */
-#define AST__HLF2GL 34 /* Heliocentric to galactic frequency */
-
-/* Maximum number of arguments required by a conversion. */
-#define MAX_ARGS 7
-
-/* The alphabet (used for generating keywords for arguments). */
-#define ALPHABET "abcdefghijklmnopqrstuvwxyz"
-
-/* Angle conversion */
-#define PI 3.141592653589793238462643
-#define PIBY2 (PI/2.0)
-#define D2R (PI/180.0)
-#define R2D (180.0/PI)
-
-/* Include files. */
-/* ============== */
-/* Interface definitions. */
-/* ---------------------- */
-#include "pal.h" /* SLALIB interface */
-
-#include "globals.h" /* Thread-safe global data access */
-#include "error.h" /* Error reporting facilities */
-#include "memory.h" /* Memory allocation facilities */
-#include "object.h" /* Base Object class */
-#include "pointset.h" /* Sets of points/coordinates */
-#include "mapping.h" /* Coordinate Mappings (parent class) */
-#include "unitmap.h" /* Unit (null) Mappings */
-#include "specmap.h" /* Interface definition for this class */
-
-/* Error code definitions. */
-/* ----------------------- */
-#include "ast_err.h" /* AST error codes */
-
-/* C header files. */
-/* --------------- */
-#include <ctype.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-/* Module Variables. */
-/* ================= */
-
-/* Address of this static variable is used as a unique identifier for
- member of this class. */
-static int class_check;
-
-/* Pointers to parent class methods which are extended by this class. */
-static int (* parent_getobjsize)( AstObject *, int * );
-static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
-static double (* parent_rate)( AstMapping *, double *, int, int, int * );
-
-
-#ifdef THREAD_SAFE
-/* Define how to initialise thread-specific globals. */
-#define GLOBAL_inits \
- globals->Class_Init = 0;
-
-/* Create the function that initialises global data for this module. */
-astMAKE_INITGLOBALS(SpecMap)
-
-/* Define macros for accessing each item of thread specific global data. */
-#define class_init astGLOBAL(SpecMap,Class_Init)
-#define class_vtab astGLOBAL(SpecMap,Class_Vtab)
-
-
-#include <pthread.h>
-
-
-#else
-
-
-/* Define the class virtual function table and its initialisation flag
- as static variables. */
-static AstSpecMapVtab class_vtab; /* Virtual function table */
-static int class_init = 0; /* Virtual function table initialised? */
-
-#endif
-
-/* Structure to hold parameters and intermediate values describing a
- reference frame */
-typedef struct FrameDef {
- double obsalt; /* Observers geodetic altitude (m) */
- double obslat; /* Observers geodetic latitude (rads) */
- double obslon; /* Observers geodetic longitude (rads, +ve east) */
- double epoch; /* Julian epoch of observation */
- double refdec; /* RA of reference point (FK5 J2000) */
- double refra; /* DEC of reference point (FK5 J2000) */
- double veluser; /* Heliocentric velocity of user-defined system (m/s) */
- double last; /* Local apparent sideral time */
- double amprms[21]; /* Mean to apparent parameters */
- double vuser[3]; /* Used-defined velocity as a FK5 J2000 vector */
- double dvh[3]; /* Earth-sun velocity */
- double dvb[3]; /* Barycentre-sun velocity */
-} FrameDef;
-
-/* External Interface Function Prototypes. */
-/* ======================================= */
-/* The following functions have public prototypes only (i.e. no
- protected prototypes), so we must provide local prototypes for use
- within this module. */
-AstSpecMap *astSpecMapId_( int, int, const char *, ... );
-
-/* Prototypes for Private Member Functions. */
-/* ======================================== */
-static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
-static const char *CvtString( int, const char **, int *, int *, int *, int *, const char *[ MAX_ARGS ], int * );
-static double BaryVel( double, double, FrameDef *, int * );
-static double GalVel( double, double, FrameDef *, int * );
-static double GeoVel( double, double, FrameDef *, int * );
-static double LgVel( double, double, FrameDef *, int * );
-static double LsrdVel( double, double, FrameDef *, int * );
-static double LsrkVel( double, double, FrameDef *, int * );
-static double Rate( AstMapping *, double *, int, int, int * );
-static double Refrac( double, int * );
-static double Rverot( double, double, double, double, double, int * );
-static double TopoVel( double, double, FrameDef *, int * );
-static double UserVel( double, double, FrameDef *, int * );
-static int CvtCode( const char *, int * );
-static int Equal( AstObject *, AstObject *, int * );
-static int FrameChange( int, int, double *, double *, double *, double *, int, int * );
-static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
-static int SystemChange( int, int, double *, double *, int, int * );
-static void AddSpecCvt( AstSpecMap *, int, int, const double *, int * );
-static void Copy( const AstObject *, AstObject *, int * );
-static void Delete( AstObject *, int * );
-static void Dump( AstObject *, AstChannel *, int * );
-static void SpecAdd( AstSpecMap *, const char *, int, const double[], int * );
-
-static int GetObjSize( AstObject *, int * );
-/* Member functions. */
-/* ================= */
-static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
-/*
-* Name:
-* Equal
-
-* Purpose:
-* Test if two SpecMaps are equivalent.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* int Equal( AstObject *this, AstObject *that, int *status )
-
-* Class Membership:
-* SpecMap member function (over-rides the astEqual protected
-* method inherited from the astMapping class).
-
-* Description:
-* This function returns a boolean result (0 or 1) to indicate whether
-* two SpecMaps are equivalent.
-
-* Parameters:
-* this
-* Pointer to the first Object (a SpecMap).
-* that
-* Pointer to the second Object.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* One if the SpecMaps are equivalent, zero otherwise.
-
-* Notes:
-* - A value of zero will be returned if this function is invoked
-* with the global status set, or if it should fail for any reason.
-*/
-
-/* Local Variables: */
- AstSpecMap *that;
- AstSpecMap *this;
- const char *argdesc[ MAX_ARGS ];
- const char *comment;
- int argdec;
- int argra;
- int i, j;
- int nargs;
- int nin;
- int nout;
- int result;
- int szargs;
-
-/* Initialise. */
- result = 0;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Obtain pointers to the two SpecMap structures. */
- this = (AstSpecMap *) this_object;
- that = (AstSpecMap *) that_object;
-
-/* Check the second object is a SpecMap. We know the first is a
- SpecMap since we have arrived at this implementation of the virtual
- function. */
- if( astIsASpecMap( that ) ) {
-
-/* Get the number of inputs and outputs and check they are the same for both. */
- nin = astGetNin( this );
- nout = astGetNout( this );
- if( astGetNin( that ) == nin && astGetNout( that ) == nout ) {
-
-/* If the Invert flags for the two SpecMaps differ, it may still be possible
- for them to be equivalent. First compare the SpecMaps if their Invert
- flags are the same. In this case all the attributes of the two SpecMaps
- must be identical. */
- if( astGetInvert( this ) == astGetInvert( that ) ) {
- if( this->ncvt == that->ncvt ) {
- result = 1;
- for( i = 0; i < this->ncvt && result; i++ ) {
- if( this->cvttype[ i ] != that->cvttype[ i ] ) {
- result = 0;
- } else {
- CvtString( this->cvttype[ i ], &comment, &argra,
- &argdec, &nargs, &szargs, argdesc, status );
- for( j = 0; j < nargs; j++ ) {
- if( !astEQUAL( this->cvtargs[ i ][ j ],
- that->cvtargs[ i ][ j ] ) ){
- result = 0;
- break;
- }
- }
- }
- }
- }
-
-/* If the Invert flags for the two SpecMaps differ, the attributes of the two
- SpecMaps must be inversely related to each other. */
- } else {
-
-/* In the specific case of a SpecMap, Invert flags must be equal. */
- result = 0;
-
- }
- }
- }
-
-/* If an error occurred, clear the result value. */
- if ( !astOK ) result = 0;
-
-/* Return the result, */
- return result;
-}
-
-static int GetObjSize( AstObject *this_object, int *status ) {
-/*
-* Name:
-* GetObjSize
-
-* Purpose:
-* Return the in-memory size of an Object.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* int GetObjSize( AstObject *this, int *status )
-
-* Class Membership:
-* SpecMap member function (over-rides the astGetObjSize protected
-* method inherited from the parent class).
-
-* Description:
-* This function returns the in-memory size of the supplied SpecMap,
-* in bytes.
-
-* Parameters:
-* this
-* Pointer to the SpecMap.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The Object size, in bytes.
-
-* Notes:
-* - A value of zero will be returned if this function is invoked
-* with the global status set, or if it should fail for any reason.
-*/
-
-/* Local Variables: */
- AstSpecMap *this; /* Pointer to SpecMap structure */
- int result; /* Result value to return */
- int cvt; /* Loop counter for coordinate conversions */
-
-/* Initialise. */
- result = 0;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Obtain a pointers to the SpecMap structure. */
- this = (AstSpecMap *) this_object;
-
-/* Invoke the GetObjSize method inherited from the parent class, and then
- add on any components of the class structure defined by thsi class
- which are stored in dynamically allocated memory. */
- result = (*parent_getobjsize)( this_object, status );
-
- for ( cvt = 0; cvt < this->ncvt; cvt++ ) {
- result += astTSizeOf( this->cvtargs[ cvt ] );
- }
-
- result += astTSizeOf( this->cvtargs );
- result += astTSizeOf( this->cvttype );
-
-/* If an error occurred, clear the result value. */
- if ( !astOK ) result = 0;
-
-/* Return the result, */
- return result;
-}
-
-static void AddSpecCvt( AstSpecMap *this, int cvttype, int narg,
- const double *args, int *status ) {
-/*
-* Name:
-* AddSpecCvt
-
-* Purpose:
-* Add a coordinate conversion step to an SpecMap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* void AddSpecCvt( AstSpecMap *this, int cvttype, int narg,
-* const double *args )
-
-* Class Membership:
-* SpecMap member function.
-
-* Description:
-* This function allows one of the supported spectral coordinate
-* conversions to be appended to a SpecMap. When a SpecMap is first
-* created (using astSpecMap), it simply performs a unit mapping. By
-* using AddSpecCvt repeatedly, a series of coordinate conversions may
-* then be specified which the SpecMap will subsequently perform in
-* sequence. This allows a complex coordinate conversion to be
-* assembled out of the basic building blocks. The SpecMap will also
-* perform the inverse coordinate conversion (applying the individual
-* conversion steps in reverse) if required.
-
-* Parameters:
-* this
-* Pointer to the SpecMap.
-* cvttype
-* A code to identify which spectral coordinate conversion is to be
-* appended. See the "Coordinate Conversions" section for details
-* of those available.
-* narg
-* The number of argument values supplied in "args".
-* args
-* Pointer to an array of double containing the argument values
-* required to fully specify the required coordinate
-* conversion. The number of arguments depends on the conversion
-* (see the "Coordinate Conversions" section for details). This
-* value is ignored and may be NULL if no arguments are required.
-
-* Returned Value:
-* void.
-
-* Coordinate Conversions:
-* The following values may be supplied for the "cvttype" parameter
-* in order to specify the coordinate conversion to be performed.
-* The argument(s) required to fully specify each conversion are
-* indicated in parentheses after each value, and described at the end
-* of the list. Values for these should be given in the array pointed
-* at by "args".
-*
-* AST__FRTOVL( RF )
-* Convert frequency to relativistic velocity.
-* AST__VLTOFR( RF )
-* Convert relativistic velocity to Frequency.
-* AST__ENTOFR
-* Convert energy to frequency.
-* AST__FRTOEN
-* Convert frequency to energy.
-* AST__WNTOFR
-* Convert wave number to frequency.
-* AST__FRTOWN
-* Convert frequency to wave number.
-* AST__WVTOFR
-* Convert wavelength (vacuum) to frequency.
-* AST__FRTOWV
-* Convert frequency to wavelength (vacuum).
-* AST__AWTOFR
-* Convert wavelength (air) to frequency.
-* AST__FRTOAW
-* Convert frequency to wavelength (air).
-* AST__VRTOVL
-* Convert radio to relativistic velocity.
-* AST__VLTOVR
-* Convert relativistic to radio velocity.
-* AST__VOTOVL
-* Convert optical to relativistic velocity.
-* AST__VLTOVO
-* Convert relativistic to optical velocity.
-* AST__ZOTOVL
-* Convert redshift to relativistic velocity.
-* AST__VLTOZO
-* Convert relativistic velocity to redshift.
-* AST__BTTOVL
-* Convert beta factor to relativistic velocity.
-* AST__VLTOBT
-* Convert relativistic velocity to beta factor.
-* AST_USF2HL( VOFF, RA, DEC )
-* Convert frequency from a user-defined reference frame to
-* heliocentric.
-* AST__HLF2US( VOFF, RA, DEC )
-* Convert frequency from heliocentric reference frame to
-* user-defined.
-* AST__TPF2HL( OBSLON, OBSLAT, OBSALT, EPOCH, RA, DEC )
-* Convert from Topocentric to heliocentric frequency
-* AST__HLF2TP( OBSLON, OBSLAT, OBSALT, EPOCH, RA, DEC )
-* Convert from Heliocentric to topocentric frequency.
-* AST__GEF2HL( EPOCH, RA, DEC )
-* Convert from Geocentric to heliocentric frequency.
-* AST__HLF2GE( EPOCH, RA, DEC )
-* Convert from Heliocentric to geocentric frequency.
-* AST__BYF2HL( EPOCH, RA, DEC )
-* Convert from Barycentric to heliocentric frequency.
-* AST__HLF2BY( EPOCH, RA, DEC )
-* Convert from Heliocentric to barycentric frequency.
-* AST__LKF2HL( RA, DEC )
-* Convert from LSRK to heliocentric frequency.
-* AST__HLF2LK( RA, DEC )
-* Convert from Heliocentric to LSRK frequency.
-* AST__LDF2HL( RA, DEC )
-* Convert from LSRD to heliocentric frequency.
-* AST__HLF2LD( RA, DEC )
-* Convert from Heliocentric to LSRD frequency.
-* AST__LGF2HL( RA, DEC )
-* Convert from Local group to heliocentric frequency.
-* AST__HLF2LG( RA, DEC )
-* Convert from Heliocentric to local group frequency.
-* AST__GLF2HL( RA, DEC )
-* Convert from Galactic to heliocentric frequency.
-* AST__HLF2GL( RA, DEC )
-* Convert from Heliocentric to galactic frequency.
-*
-* The units for the values processed by the above conversions are as
-* follows:
-*
-* - all velocities: metres per second.
-* - frequency: Hertz.
-* - all wavelengths: metres.
-* - energy: Joules.
-* - wave number: cycles per metre.
-*
-* The arguments used in the above conversions are as follows:
-*
-* - RF: Rest frequency (Hz).
-* - OBSALT: Geodetic altitude of observer (IAU 1975, metres).
-* - OBSLAT: Geodetic latitude of observer (IAU 1975, radians).
-* - OBSLON: Longitude of observer (radians, positive eastwards).
-* - EPOCH: Epoch of observation (UT1 expressed as a Modified Julian Date).
-* - RA: Right Ascension of source (radians, FK5 J2000).
-* - DEC: Declination of source (radians, FK5 J2000).
-* - VOFF: Velocity of the user-defined reference frame, towards the
-* position given by RA and DEC, measured in the heliocentric
-* reference frame.
-*
-* If the SpecMap is 3-dimensional, source positions are provided by the
-* values supplied to inputs 2 and 3 of the SpecMap (which are simply
-* copied to outputs 2 and 3). Note, usable values are still required
-* for the RA and DEC arguments in order to define the "user-defined"
-* reference frame used by USF2HL and HLF2US. However, AST__BAD can be
-* supplied for RA and DEC if the user-defined reference frame is not
-* required.
-
-* Notes:
-* - The specified conversion is appended only if the SpecMap's
-* Invert attribute is zero. If it is non-zero, this function
-* effectively prefixes the inverse of the conversion specified
-* instead.
-*/
-
-/* Local Variables: */
- const char *argdesc[ MAX_ARGS ]; /* Pointers to argument descriptions */
- const char *comment; /* Pointer to comment string */
- const char *cvt_string; /* Pointer to conversion type string */
- int argdec; /* Index of DEC argument */
- int argra; /* Index of RA argument */
- int i; /* Argument index */
- int nargs; /* Number of user-supplied arguments */
- int ncvt; /* Number of coordinate conversions */
- int szargs; /* Size of arguments array */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Validate the coordinate conversion type and obtain the number of
- required user-supplied arguments, and the size of the array in which
- to put the user-supplied arguments (the array meay leave room after
- the user-supplied arguments for various useful pre-calculated values). */
- cvt_string = CvtString( cvttype, &comment, &argra, &argdec, &nargs,
- &szargs, argdesc, status );
-
-/* If the coordinate conversion type was not valid, then report an
- error. */
- if ( astOK && !cvt_string ) {
- astError( AST__SPCIN, "AddSpecCvt(%s): Invalid spectral coordinate "
- "conversion type (%d).", status, astGetClass( this ),
- (int) cvttype );
- }
-
-/* If the number of supplied arguments is incorrect, then report an error. */
- if ( astOK && nargs != narg ) {
- astError( AST__TIMIN, "AddSpecCvt(%s): Invalid no. of arguments for spectral "
- "coordinate conversion type %d - %d supplied, %d required.",
- status, astGetClass( this ), (int) cvttype, narg, nargs );
- }
-
-/* Note the number of coordinate conversions already stored in the SpecMap. */
- if ( astOK ) {
- ncvt = this->ncvt;
-
-/* Extend the array of conversion types and the array of pointers to
- their argument lists to accommodate the new one. */
- this->cvttype = (int *) astGrow( this->cvttype, ncvt + 1,
- sizeof( int ) );
- this->cvtargs = (double **) astGrow( this->cvtargs, ncvt + 1,
- sizeof( double * ) );
-
-/* If OK, allocate memory and store a copy of the argument list,
- putting a pointer to the copy into the SpecMap. */
- if ( astOK ) {
- this->cvtargs[ ncvt ] = astStore( NULL, args,
- sizeof( double ) * (size_t) szargs );
- }
-
-/* Store the conversion type and increment the conversion count. Also put
- AST__BAD in any elements of the argument array which are beyond the
- end of the user-supplied arguments. These will be used to hold
- intermediate values calculated on the basis of the user-supplied
- arguments. */
- if ( astOK ) {
- this->cvttype[ ncvt ] = cvttype;
- this->ncvt++;
- for( i = nargs; i < szargs; i++ ) this->cvtargs[ ncvt ][ i ] = AST__BAD;
- }
- }
-}
-
-static double BaryVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* BaryVel
-
-* Purpose:
-* Find the velocity of the earth-sun barycentre away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double BaryVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the earth-sun
-* barycentre away from a specified source position, at a given epoch, in
-* the frame of rest of the centre of the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-
-/* Local Variables: */
- double dpb[ 3 ]; /* Barycentric earth position vector */
- double dph[ 3 ]; /* Heliocentric earth position vector */
- double dvh[ 3 ]; /* Heliocentric earth velocity vector */
- double v[ 3 ]; /* Source direction vector */
-
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* Get the Cartesian vector towards the source, in the Cartesian FK5
- J2000 system. */
- palDcs2c( ra, dec, v );
-
-/* If not already done so, get the Earth/Sun velocity and position vectors in
- the same system. Speed is returned in units of AU/s. Store in the supplied
- frame definition structure. */
- if( def->dvb[ 0 ] == AST__BAD ) {
- palEvp( def->epoch, 2000.0, def->dvb, dpb, dvh, dph );
-
-/* Change the barycentric velocity of the earth into the heliocentric
- velocity of the barycentre. */
- def->dvb[ 0 ] = dvh[ 0 ] - def->dvb[ 0 ];
- def->dvb[ 1 ] = dvh[ 1 ] - def->dvb[ 1 ];
- def->dvb[ 2 ] = dvh[ 2 ] - def->dvb[ 2 ];
- }
-
-/* Return the component away from the source, of the velocity of the
- barycentre relative to the sun (in m/s). */
- return -palDvdv( v, def->dvb )*149.597870E9;
-
-}
-
-static int CvtCode( const char *cvt_string, int *status ) {
-/*
-* Name:
-* CvtCode
-
-* Purpose:
-* Convert a conversion type from a string representation to a code value.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* int CvtCode( const char *cvt_string, int *status )
-
-* Class Membership:
-* SpecMap member function.
-
-* Description:
-* This function accepts a string used to repersent one of the
-* SpecMap coordinate conversions and converts it into a code
-* value for internal use.
-
-* Parameters:
-* cvt_string
-* Pointer to a constant null-terminated string representing a
-* spectral coordinate conversion. This is case sensitive and should
-* contain no unnecessary white space.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The equivalent conversion code. If the string was not
-* recognised, the code AST__SPEC_NULL is returned, without error.
-
-* Notes:
-* - A value of AST__SPEC_NULL will be returned if this function is
-* invoked with the global error status set, or if it should fail
-* for any reason.
-*/
-
-/* Local Variables: */
- int result; /* Result value to return */
-
-/* Initialise. */
- result = AST__SPEC_NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Test the string against each recognised value in turn and assign
- the result. */
- if ( astChrMatch( cvt_string, "FRTOVL" ) ) {
- result = AST__FRTOVL;
-
- } else if ( astChrMatch( cvt_string, "VLTOFR" ) ) {
- result = AST__VLTOFR;
-
- } else if ( astChrMatch( cvt_string, "VLTOFR" ) ) {
- result = AST__VLTOFR;
-
- } else if ( astChrMatch( cvt_string, "ENTOFR" ) ) {
- result = AST__ENTOFR;
-
- } else if ( astChrMatch( cvt_string, "FRTOEN" ) ) {
- result = AST__FRTOEN;
-
- } else if ( astChrMatch( cvt_string, "WNTOFR" ) ) {
- result = AST__WNTOFR;
-
- } else if ( astChrMatch( cvt_string, "FRTOWN" ) ) {
- result = AST__FRTOWN;
-
- } else if ( astChrMatch( cvt_string, "WVTOFR" ) ) {
- result = AST__WVTOFR;
-
- } else if ( astChrMatch( cvt_string, "FRTOWV" ) ) {
- result = AST__FRTOWV;
-
- } else if ( astChrMatch( cvt_string, "AWTOFR" ) ) {
- result = AST__AWTOFR;
-
- } else if ( astChrMatch( cvt_string, "FRTOAW" ) ) {
- result = AST__FRTOAW;
-
- } else if ( astChrMatch( cvt_string, "VRTOVL" ) ) {
- result = AST__VRTOVL;
-
- } else if ( astChrMatch( cvt_string, "VLTOVR" ) ) {
- result = AST__VLTOVR;
-
- } else if ( astChrMatch( cvt_string, "VOTOVL" ) ) {
- result = AST__VOTOVL;
-
- } else if ( astChrMatch( cvt_string, "VLTOVO" ) ) {
- result = AST__VLTOVO;
-
- } else if ( astChrMatch( cvt_string, "ZOTOVL" ) ) {
- result = AST__ZOTOVL;
-
- } else if ( astChrMatch( cvt_string, "VLTOZO" ) ) {
- result = AST__VLTOZO;
-
- } else if ( astChrMatch( cvt_string, "BTTOVL" ) ) {
- result = AST__BTTOVL;
-
- } else if ( astChrMatch( cvt_string, "VLTOBT" ) ) {
- result = AST__VLTOBT;
-
- } else if ( astChrMatch( cvt_string, "USF2HL" ) ) {
- result = AST__USF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2US" ) ) {
- result = AST__HLF2US;
-
- } else if ( astChrMatch( cvt_string, "TPF2HL" ) ) {
- result = AST__TPF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2TP" ) ) {
- result = AST__HLF2TP;
-
- } else if ( astChrMatch( cvt_string, "GEF2HL" ) ) {
- result = AST__GEF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2GE" ) ) {
- result = AST__HLF2GE;
-
- } else if ( astChrMatch( cvt_string, "BYF2HL" ) ) {
- result = AST__BYF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2BY" ) ) {
- result = AST__HLF2BY;
-
- } else if ( astChrMatch( cvt_string, "LKF2HL" ) ) {
- result = AST__LKF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2LK" ) ) {
- result = AST__HLF2LK;
-
- } else if ( astChrMatch( cvt_string, "LDF2HL" ) ) {
- result = AST__LDF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2LD" ) ) {
- result = AST__HLF2LD;
-
- } else if ( astChrMatch( cvt_string, "LGF2HL" ) ) {
- result = AST__LGF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2LG" ) ) {
- result = AST__HLF2LG;
-
- } else if ( astChrMatch( cvt_string, "GLF2HL" ) ) {
- result = AST__GLF2HL;
-
- } else if ( astChrMatch( cvt_string, "HLF2GL" ) ) {
- result = AST__HLF2GL;
-
- }
-
-/* Return the result. */
- return result;
-}
-
-static const char *CvtString( int cvt_code, const char **comment,
- int *argra, int *argdec, int *nargs, int *szargs,
- const char *arg[ MAX_ARGS ], int *status ) {
-/*
-* Name:
-* CvtString
-
-* Purpose:
-* Convert a conversion type from a code value to a string representation.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* const char *CvtString( int cvt_code, const char **comment,
-* int *argra, int *argdec, int *nargs,
-* int *szargs, const char *arg[ MAX_ARGS ], int *status )
-
-* Class Membership:
-* SpecMap member function.
-
-* Description:
-* This function accepts a code value used to represent one of the
-* SpecMap coordinate conversions and converts it into an
-* equivalent string representation. It also returns a descriptive
-* comment and information about the arguments required in order to
-* perform the conversion.
-
-* Parameters:
-* cvt_code
-* The conversion code.
-* comment
-* Address of a location to return a pointer to a constant
-* null-terminated string containing a description of the
-* conversion.
-* argra
-* Address of an int in which to return the index of the argument
-* corresponding to the source RA. Returned equal to -1 if the
-* conversion does not have a source RA argument.
-* argdec
-* Address of an int in which to return the index of the argument
-* corresponding to the source DEC. Returned equal to -1 if the
-* conversion does not have a source DEC argument.
-* nargs
-* Address of an int in which to return the number of arguments
-* required from the user in order to perform the conversion (may
-* be zero).
-* szargs
-* Address of an int in which to return the number of arguments
-* associated with the conversion. This may be bigger than "nargs"
-* if the conversion can pre-calculate useful values on the basis
-* of the user-supplied values. Such precalculated values are
-* stored after the last user-supplied argument.
-* arg
-* An array in which to return a pointer to a constant
-* null-terminated string for each argument (above) containing a
-* description of what each argument represents. This includes both
-* user-supplied arguments and pre-calculated values.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* Pointer to a constant null-terminated string representation of
-* the conversion code value supplied. If the code supplied is not
-* valid, a NULL pointer will be returned, without error.
-
-* Notes:
-* - A NULL pointer value will be returned if this function is
-* invoked with the global error status set, or if it should fail
-* for any reason.
-*/
-
-/* Local Variables: */
- const char *result; /* Result pointer to return */
-
-/* Initialise the returned values. */
- *comment = NULL;
- *nargs = 0;
- *argra = -1;
- *argdec = -1;
- result = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Test for each valid code value in turn and assign the appropriate
- return values. */
- switch ( cvt_code ) {
-
- case AST__FRTOVL:
- *comment = "Convert frequency to rel. velocity";
- result = "FRTOVL";
- *nargs = 1;
- *szargs = 1;
- arg[ 0 ] = "Rest frequency (Hz)";
- break;
-
- case AST__VLTOFR:
- *comment = "Convert rel. velocity to frequency";
- result = "VLTOFR";
- *nargs = 1;
- *szargs = 1;
- arg[ 0 ] = "Rest frequency (Hz)";
- break;
-
- case AST__ENTOFR:
- *comment = "Convert energy to frequency";
- result = "ENTOFR";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__FRTOEN:
- *comment = "Convert frequency to energy";
- result = "FRTOEN";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__WNTOFR:
- *comment = "Convert wave number to frequency";
- result = "WNTOFR";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__FRTOWN:
- *comment = "Convert frequency to wave number";
- result = "FRTOWN";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__WVTOFR:
- *comment = "Convert wavelength (vacuum) to frequency";
- result = "WVTOFR";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__FRTOWV:
- *comment = "Convert frequency to wavelength (vacuum)";
- result = "FRTOWV";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__AWTOFR:
- *comment = "Convert wavelength (air) to frequency";
- result = "AWTOFR";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__FRTOAW:
- *comment = "Convert frequency to wavelength (air)";
- result = "FRTOAW";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__VRTOVL:
- *comment = "Convert radio to rel. velocity";
- result = "VRTOVL";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__VLTOVR:
- *comment = "Convert relativistic to radio velocity";
- result = "VLTOVR";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__VOTOVL:
- *comment = "Convert optical to rel. velocity";
- result = "VOTOVL";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__VLTOVO:
- *comment = "Convert relativistic to optical velocity";
- result = "VLTOVO";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__ZOTOVL:
- *comment = "Convert redshift to rel. velocity";
- result = "ZOTOVL";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__VLTOZO:
- *comment = "Convert rel. velocity to redshift";
- result = "VLTOZO";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__BTTOVL:
- *comment = "Convert beta factor to rel. velocity";
- result = "BTTOVL";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__VLTOBT:
- *comment = "Convert rel. velocity to beta factor";
- result = "VLTOBT";
- *nargs = 0;
- *szargs = 0;
- break;
-
- case AST__USF2HL:
- *comment = "Convert from user-defined to heliocentric frequency";
- result = "USF2HL";
- *argra = 1;
- *argdec = 2;
- *nargs = 3;
- *szargs = 4;
- arg[ 0 ] = "Velocity offset (m/s)";
- arg[ 1 ] = "RA of source (FK5 J2000, radians)";
- arg[ 2 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 3 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2US:
- *comment = "Convert from heliocentric to user-defined frequency";
- result = "HLF2US";
- *argra = 1;
- *argdec = 2;
- *nargs = 3;
- *szargs = 4;
- arg[ 0 ] = "Velocity offset (m/s)";
- arg[ 1 ] = "RA of source (FK5 J2000, radians)";
- arg[ 2 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 3 ] = "Frequency correction factor";
- break;
-
- case AST__TPF2HL:
- *comment = "Convert from Topocentric to heliocentric frequency";
- result = "TPF2HL";
- *argra = 4;
- *argdec = 5;
- *nargs = 6;
- *szargs = 7;
- arg[ 0 ] = "Longitude (positive eastwards, radians)";
- arg[ 1 ] = "Latitude (geodetic, radians)";
- arg[ 2 ] = "Altitude (geodetic, metres)";
- arg[ 3 ] = "UT1 epoch of observaton (Modified Julian Date)";
- arg[ 4 ] = "RA of source (FK5 J2000, radians)";
- arg[ 5 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 6 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2TP:
- *comment = "Convert from Heliocentric to topocentric frequency";
- result = "HLF2TP";
- *argra = 4;
- *argdec = 5;
- *nargs = 6;
- *szargs = 7;
- arg[ 0 ] = "Longitude (positive eastwards, radians)";
- arg[ 1 ] = "Latitude (geodetic, radians)";
- arg[ 2 ] = "Altitude (geodetic, metres)";
- arg[ 3 ] = "UT1 epoch of observaton (Modified Julian Date)";
- arg[ 4 ] = "RA of source (FK5 J2000, radians)";
- arg[ 5 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 6 ] = "Frequency correction factor";
- break;
-
- case AST__GEF2HL:
- *comment = "Convert from Geocentric to heliocentric frequency";
- result = "GEF2HL";
- *argra = 1;
- *argdec = 2;
- *nargs = 3;
- *szargs = 4;
- arg[ 0 ] = "UT1 epoch of observaton (Modified Julian Date)";
- arg[ 1 ] = "RA of source (FK5 J2000, radians)";
- arg[ 2 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 3 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2GE:
- *comment = "Convert from Heliocentric to geocentric frequency";
- result = "HLF2GE";
- *argra = 1;
- *argdec = 2;
- *nargs = 3;
- *szargs = 4;
- arg[ 0 ] = "UT1 epoch of observaton (Modified Julian Date)";
- arg[ 1 ] = "RA of source (FK5 J2000, radians)";
- arg[ 2 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 3 ] = "Frequency correction factor";
- break;
-
- case AST__BYF2HL:
- *comment = "Convert from Barycentric to heliocentric frequency";
- result = "BYF2HL";
- *argra = 1;
- *argdec = 2;
- *nargs = 3;
- *szargs = 4;
- arg[ 0 ] = "UT1 epoch of observaton (Modified Julian Date)";
- arg[ 1 ] = "RA of source (FK5 J2000, radians)";
- arg[ 2 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 3 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2BY:
- *comment = "Convert from Heliocentric to barycentric frequency";
- result = "HLF2BY";
- *argra = 1;
- *argdec = 2;
- *nargs = 3;
- *szargs = 4;
- arg[ 0 ] = "UT1 epoch of observaton (Modified Julian Date)";
- arg[ 1 ] = "RA of source (FK5 J2000, radians)";
- arg[ 2 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 3 ] = "Frequency correction factor";
- break;
-
- case AST__LKF2HL:
- *comment = "Convert from LSRK to heliocentric frequency";
- result = "LKF2HL";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2LK:
- *comment = "Convert from Heliocentric to LSRK frequency";
- result = "HLF2LK";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__LDF2HL:
- *comment = "Convert from LSRD to heliocentric frequency";
- result = "LDF2HL";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2LD:
- *comment = "Convert from Heliocentric to LSRD frequency";
- result = "HLF2LD";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__LGF2HL:
- *comment = "Convert from Local group to heliocentric frequency";
- result = "LGF2HL";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2LG:
- *comment = "Convert from Heliocentric to local group frequency";
- result = "HLF2LG";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__GLF2HL:
- *comment = "Convert from Galactic to heliocentric frequency";
- result = "GLF2HL";
- *argra = 0;
- *argdec = 1;
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- case AST__HLF2GL:
- *comment = "Convert from Heliocentric to galactic frequency";
- *argra = 0;
- *argdec = 1;
- result = "HLF2GL";
- *nargs = 2;
- *szargs = 3;
- arg[ 0 ] = "RA of source (FK5 J2000, radians)";
- arg[ 1 ] = "DEC of source (FK5 J2000, radians)";
- arg[ 2 ] = "Frequency correction factor";
- break;
-
- }
-
-/* Return the result. */
- return result;
-}
-
-static int FrameChange( int cvt_code, int np, double *ra, double *dec, double *freq,
- double *args, int forward, int *status ){
-/*
-* Name:
-* FrameChange
-
-* Purpose:
-* Apply a doppler shift caused by a change of reference frame.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* int FrameChange( int cvt_code, int np, double *ra, double *dec,
-* double *freq, double *args, int forward, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function modifies the supplied frequency values in order to
-* apply a doppler shift caused by a change of the observers rest-frame.
-
-* Parameters:
-* cvt_code
-* A code indicating the conversion to be applied. If the code does
-* not correspond to a change of rest-frame, then the supplied
-* frequencies are left unchanged and zero is returned as the
-* function value.
-* np
-* The number of frequency values to transform.
-* ra
-* Pointer to an array of "np" RA (J2000 FK5) values at which the
-* "np" frequencies are observed. These are unchanged on exit. If a
-* NULL pointer is supplied, then all frequencies are assumed to be
-* observed at the single RA value given by "refra"
-* dec
-* Pointer to an array of "np" Dec (J2000 FK5) values at which the
-* "np" frequencies are observed. These are unchanged on exit. If a
-* NULL pointer is supplied, then all frequencies are assumed to be
-* observed at the single Dec value given by "refdec"
-* freq
-* Pointer to an array of "np" frequency values, measured in the
-* input rest-frame. These are modified on return to hold the
-* corresponding values measured in the output rest-frame.
-* args
-* Pointer to an array holding the conversion arguments. The number
-* of arguments expected depends on the particular conversion being
-* used.
-* forward
-* Should the conversion be applied in the forward or inverse
-* direction? Non-zero for forward, zero for inverse.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* Non-zero if the supplied conversion code corresponds to a change of
-* reference frame. Zoer otherwise (in which case the upplied values
-* will not have been changed).
-
-* Notes:
-* - The "args" array contains RA and DEC values which give the "source"
-* position (FK5 J2000). If a NULL value is supplied for the "ra"
-* parameter, then these args define the position of all the frequency
-* values. In addition they also define the direction of motion of
-* the "user-defined" rest-frame (see "veluser"). Thus they should still
-* be supplied even if "ra" is NULL.
-
-*/
-
-/* Local Variables: */
- FrameDef def; /* Structure holding frame parameters */
- double (* cvtFunc)( double, double, FrameDef *, int * ); /* Pointer to conversion function */
- double *fcorr; /* Pointer to frequency correction factor */
- double *pdec; /* Pointer to next Dec value */
- double *pf; /* Pointer to next frequency value */
- double *pra; /* Pointer to next RA value */
- double factor; /* Frequency correction factor */
- double s; /* Velocity correction (m/s) */
- int i; /* Loop index */
- int result; /* Returned value */
- int sign; /* Sign for velocity correction */
-
-/* Check inherited status. */
- if( !astOK ) return 0;
-
-/* Initialise */
- cvtFunc = NULL;
- fcorr = NULL;
- sign = 0;
-
-/* Set the return value to indicate that the supplied conversion code
- represents a change of rest-frame. */
- result = 1;
-
-/* Initialise a structure which stores parameters which define the
- transformation. */
- def.obsalt = AST__BAD;
- def.obslat = AST__BAD;
- def.obslon = AST__BAD;
- def.epoch = AST__BAD;
- def.refdec = AST__BAD;
- def.refra = AST__BAD;
- def.veluser = AST__BAD;
- def.last = AST__BAD;
- def.amprms[ 0 ] = AST__BAD;
- def.vuser[ 0 ] = AST__BAD;
- def.dvh[ 0 ] = AST__BAD;
- def.dvb[ 0 ] = AST__BAD;
-
-/* Test for each rest-frame code value in turn and assign the appropriate
- values. */
- switch ( cvt_code ) {
-
- case AST__USF2HL:
- cvtFunc = UserVel;
- def.veluser = args[ 0 ];
- def.refra = args[ 1 ];
- def.refdec = args[ 2 ];
- fcorr = args + 3;
- sign = -1;
- break;
-
- case AST__HLF2US:
- cvtFunc = UserVel;
- def.veluser = args[ 0 ];
- def.refra = args[ 1 ];
- def.refdec = args[ 2 ];
- fcorr = args + 3;
- sign = +1;
- break;
-
- case AST__TPF2HL:
- cvtFunc = TopoVel;
- def.obslon = args[ 0 ];
- def.obslat = args[ 1 ];
- def.obsalt = args[ 2 ];
- def.epoch = args[ 3 ];
- def.refra = args[ 4 ];
- def.refdec = args[ 5 ];
- fcorr = args + 6;
- sign = -1;
- break;
-
- case AST__HLF2TP:
- cvtFunc = TopoVel;
- def.obslon = args[ 0 ];
- def.obslat = args[ 1 ];
- def.obsalt = args[ 2 ];
- def.epoch = args[ 3 ];
- def.refra = args[ 4 ];
- def.refdec = args[ 5 ];
- fcorr = args + 6;
- sign = +1;
- break;
-
- case AST__GEF2HL:
- cvtFunc = GeoVel;
- def.epoch = args[ 0 ];
- def.refra = args[ 1 ];
- def.refdec = args[ 2 ];
- fcorr = args + 3;
- sign = -1;
- break;
-
- case AST__HLF2GE:
- cvtFunc = GeoVel;
- def.epoch = args[ 0 ];
- def.refra = args[ 1 ];
- def.refdec = args[ 2 ];
- fcorr = args + 3;
- sign = +1;
- break;
-
- case AST__BYF2HL:
- cvtFunc = BaryVel;
- def.epoch = args[ 0 ];
- def.refra = args[ 1 ];
- def.refdec = args[ 2 ];
- fcorr = args + 3;
- sign = -1;
- break;
-
- case AST__HLF2BY:
- cvtFunc = BaryVel;
- def.epoch = args[ 0 ];
- def.refra = args[ 1 ];
- def.refdec = args[ 2 ];
- fcorr = args + 3;
- sign = +1;
- break;
-
- case AST__LKF2HL:
- cvtFunc = LsrkVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = -1;
- break;
-
- case AST__HLF2LK:
- cvtFunc = LsrkVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = +1;
- break;
-
- case AST__LDF2HL:
- cvtFunc = LsrdVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = -1;
- break;
-
- case AST__HLF2LD:
- cvtFunc = LsrdVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = +1;
- break;
-
- case AST__LGF2HL:
- cvtFunc = LgVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = -1;
- break;
-
- case AST__HLF2LG:
- cvtFunc = LgVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = +1;
- break;
-
- case AST__GLF2HL:
- cvtFunc = GalVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = -1;
- break;
-
- case AST__HLF2GL:
- cvtFunc = GalVel;
- def.refra = args[ 0 ];
- def.refdec = args[ 1 ];
- fcorr = args + 2;
- sign = +1;
- break;
-
-/* If the supplied code does not represent a change of rest-frame, clear
- the returned flag. */
- default:
- result = 0;
- }
-
-/* Check we have a rest-frame code. */
- if( result ) {
-
-/* First deal with cases where we have a single source position (given by
- refra and refdec). */
- if( !ra ) {
-
-/* If the frequency correction factor has not been found, find it now. */
- if( *fcorr == AST__BAD ) {
-
-/* Get the velocity correction. This is the component of the velocity of the
- output system, away from the source, as measured in the input system. */
- s = sign*cvtFunc( def.refra, def.refdec, &def, status );
-
-/* Find the factor by which to correct supplied frequencies. If the
- velocity correction is positive, the output frequency wil be lower than
- the input frequency. */
- if( s < AST__C && s > -AST__C ) {
- *fcorr = sqrt( ( AST__C - s )/( AST__C + s ) );
- }
- }
-
-/* Correct each supplied frequency. */
- if( *fcorr != AST__BAD && *fcorr != 0.0 ) {
- factor = forward ? *fcorr : 1.0 / ( *fcorr );
- pf = freq;
- for( i = 0; i < np; i++, pf++ ) {
- if( *pf != AST__BAD ) *pf *= factor;
- }
-
-/* Set returned values bad if the velocity correction is un-physical. */
- } else {
- pf = freq;
- for( i = 0; i < np; i++ ) *(pf++) = AST__BAD;
- }
-
-/* Now deal with cases where each frequency value has its own source
- position. */
- } else {
-
-/* Invert the sign if we are doing a inverse transformation. */
- if( !forward ) sign = -sign;
-
-/* Loop round each value. */
- pf = freq;
- pra = ra;
- pdec = dec;
- for( i = 0; i < np; i++ ) {
-
-/* If the ra or dec is bad, store a bad frequency. */
- if( *pra == AST__BAD || *pdec == AST__BAD || *pf == AST__BAD ) {
- *pf = AST__BAD;
-
-/* Otherwise, produce a corrected frequency. */
- } else {
-
-/* Get the velocity correction. */
- s = sign*cvtFunc( *pra, *pdec, &def, status );
-
-/* Correct this frequency, if possible. Otherwise set bad. */
- if( s < AST__C && s > -AST__C ) {
- *pf *= sqrt( ( AST__C - s )/( AST__C + s ) );
- } else {
- *pf = AST__BAD;
- }
- }
-
-/* Move on to the next position. */
- pf++;
- pra++;
- pdec++;
- }
- }
- }
-
-/* Return the result. */
- return result;
-}
-
-static double GalVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* GalVel
-
-* Purpose:
-* Find the velocity of the galactic centre away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double GalVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the galactic
-* centre away from a specified source position, in the frame of rest
-* of the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-
-/* Local Variables: */
- double s1, s2;
-
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* Get the component away from the source, of the velocity of the sun
- relative to the dynamic LSR (in km/s). */
- s1 = (double) palRvlsrd( (float) ra, (float) dec );
-
-/* Get the component away from the source, of the velocity of the
- dynamic LSR relative to the galactic centre (in km/s). */
- s2 = (double) palRvgalc( (float) ra, (float) dec );
-
-/* Return the total velocity of the galactic centre away from the source,
- relative to the sun, in m/s. */
- return -1000.0*( s1 + s2 );
-}
-
-static double GeoVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* GeoVel
-
-* Purpose:
-* Find the velocity of the earth away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double GeoVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the earth away
-* from a specified source position, at a given epoch, in the frame of
-* rest of the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-
-/* Local Variables: */
- double dpb[ 3 ]; /* Barycentric earth position vector */
- double dph[ 3 ]; /* Heliocentric earth position vector */
- double dvb[ 3 ]; /* Barycentric earth velocity vector */
- double v[ 3 ]; /* Source direction vector */
-
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* Get the Cartesian vector towards the source, in the Cartesian FK5
- J2000 system. */
- palDcs2c( ra, dec, v );
-
-/* If not already done so, get the Earth/Sun velocity and position vectors in
- the same system. Speed is returned in units of AU/s. Store in the supplied
- frame definition structure. */
- if( def->dvh[ 0 ] == AST__BAD ) palEvp( def->epoch, 2000.0, dvb, dpb,
- def->dvh, dph );
-
-/* Return the component away from the source, of the velocity of the earths
- centre relative to the sun (in m/s). */
- return -palDvdv( v, def->dvh )*149.597870E9;
-}
-
-void astInitSpecMapVtab_( AstSpecMapVtab *vtab, const char *name, int *status ) {
-/*
-*+
-* Name:
-* astInitSpecMapVtab
-
-* Purpose:
-* Initialise a virtual function table for a SpecMap.
-
-* Type:
-* Protected function.
-
-* Synopsis:
-* #include "specmap.h"
-* void astInitSpecMapVtab( AstSpecMapVtab *vtab, const char *name )
-
-* Class Membership:
-* SpecMap vtab initialiser.
-
-* Description:
-* This function initialises the component of a virtual function
-* table which is used by the SpecMap class.
-
-* Parameters:
-* vtab
-* Pointer to the virtual function table. The components used by
-* all ancestral classes will be initialised if they have not already
-* been initialised.
-* name
-* Pointer to a constant null-terminated character string which contains
-* the name of the class to which the virtual function table belongs (it
-* is this pointer value that will subsequently be returned by the Object
-* astClass function).
-*-
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstObjectVtab *object; /* Pointer to Object component of Vtab */
- AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
-
-/* Check the local error status. */
- if ( !astOK ) return;
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Initialize the component of the virtual function table used by the
- parent class. */
- astInitMappingVtab( (AstMappingVtab *) vtab, name );
-
-/* Store a unique "magic" value in the virtual function table. This
- will be used (by astIsASpecMap) to determine if an object belongs to
- this class. We can conveniently use the address of the (static)
- class_check variable to generate this unique value. */
- vtab->id.check = &class_check;
- vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
-
-/* Initialise member function pointers. */
-/* ------------------------------------ */
-/* Store pointers to the member functions (implemented here) that
- provide virtual methods for this class. */
- vtab->SpecAdd = SpecAdd;
-
-/* Save the inherited pointers to methods that will be extended, and
- replace them with pointers to the new member functions. */
- object = (AstObjectVtab *) vtab;
- mapping = (AstMappingVtab *) vtab;
- parent_getobjsize = object->GetObjSize;
- object->GetObjSize = GetObjSize;
-
- parent_transform = mapping->Transform;
- mapping->Transform = Transform;
-
- parent_rate = mapping->Rate;
- mapping->Rate = Rate;
-
-/* Store replacement pointers for methods which will be over-ridden by
- new member functions implemented here. */
- object->Equal = Equal;
- mapping->MapMerge = MapMerge;
-
-/* Declare the copy constructor, destructor and class dump
- function. */
- astSetCopy( vtab, Copy );
- astSetDelete( vtab, Delete );
- astSetDump( vtab, Dump, "SpecMap",
- "Conversion between spectral coordinate systems" );
-
-/* If we have just initialised the vtab for the current class, indicate
- that the vtab is now initialised, and store a pointer to the class
- identifier in the base "object" level of the vtab. */
- if( vtab == &class_vtab ) {
- class_init = 1;
- astSetVtabClassIdentifier( vtab, &(vtab->id) );
- }
-}
-
-static double LgVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* LgVel
-
-* Purpose:
-* Find the velocity of the Local Group away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double LgVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the Local Group velocity away
-* from a specified source position, in the frame of rest of the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-
-/* Return the component away from the source, of the velocity of the
- local group relative to the sun (in m/s). */
- return -1000.0*palRvlg( (float) ra, (float) dec );
-}
-
-static double LsrdVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* LsrdVel
-
-* Purpose:
-* Find the velocity of the Dynamical LSR away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double LsrdVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the Dynamical
-* LSR away from a specified source position, in the frame of rest of
-* the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* Get the component away from the source, of the velocity of the sun
- relative to the dynamical LSR (in m/s). This can also be thought of as the
- velocity of the LSR towards the source relative to the sun. Return the
- negated value (i.e. velocity of lsrd *away from* the source. */
- return -1000.0*palRvlsrd( (float) ra, (float) dec );
-}
-
-static double LsrkVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* LsrkVel
-
-* Purpose:
-* Find the velocity of the Kinematic LSR away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double LsrkVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the Kinematic
-* LSR away from a specified source position, in the frame of rest of
-* the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* Get the component away from the source, of the velocity of the sun
- relative to the kinematic LSR (in m/s). This can also be thought of as the
- velocity of the LSR towards the source relative to the sun. Return the
- negated value (i.e. velocity of lsrk *away from* the source. */
- return -1000.0*palRvlsrk( (float) ra, (float) dec );
-}
-
-static int MapMerge( AstMapping *this, int where, int series, int *nmap,
- AstMapping ***map_list, int **invert_list, int *status ) {
-/*
-* Name:
-* MapMerge
-
-* Purpose:
-* Simplify a sequence of Mappings containing a SpecMap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "mapping.h
-* int MapMerge( AstMapping *this, int where, int series, int *nmap,
-* AstMapping ***map_list, int **invert_list, int *status )
-
-* Class Membership:
-* SpecMap method (over-rides the protected astMapMerge method
-* inherited from the Mapping class).
-
-* Description:
-* This function attempts to simplify a sequence of Mappings by
-* merging a nominated SpecMap in the sequence with its neighbours,
-* so as to shorten the sequence if possible.
-*
-* In many cases, simplification will not be possible and the
-* function will return -1 to indicate this, without further
-* action.
-*
-* In most cases of interest, however, this function will either
-* attempt to replace the nominated SpecMap with one which it
-* considers simpler, or to merge it with the Mappings which
-* immediately precede it or follow it in the sequence (both will
-* normally be considered). This is sufficient to ensure the
-* eventual simplification of most Mapping sequences by repeated
-* application of this function.
-*
-* In some cases, the function may attempt more elaborate
-* simplification, involving any number of other Mappings in the
-* sequence. It is not restricted in the type or scope of
-* simplification it may perform, but will normally only attempt
-* elaborate simplification in cases where a more straightforward
-* approach is not adequate.
-
-* Parameters:
-* this
-* Pointer to the nominated SpecMap which is to be merged with
-* its neighbours. This should be a cloned copy of the SpecMap
-* pointer contained in the array element "(*map_list)[where]"
-* (see below). This pointer will not be annulled, and the
-* SpecMap it identifies will not be modified by this function.
-* where
-* Index in the "*map_list" array (below) at which the pointer
-* to the nominated SpecMap resides.
-* series
-* A non-zero value indicates that the sequence of Mappings to
-* be simplified will be applied in series (i.e. one after the
-* other), whereas a zero value indicates that they will be
-* applied in parallel (i.e. on successive sub-sets of the
-* input/output coordinates).
-* nmap
-* Address of an int which counts the number of Mappings in the
-* sequence. On entry this should be set to the initial number
-* of Mappings. On exit it will be updated to record the number
-* of Mappings remaining after simplification.
-* map_list
-* Address of a pointer to a dynamically allocated array of
-* Mapping pointers (produced, for example, by the astMapList
-* method) which identifies the sequence of Mappings. On entry,
-* the initial sequence of Mappings to be simplified should be
-* supplied.
-*
-* On exit, the contents of this array will be modified to
-* reflect any simplification carried out. Any form of
-* simplification may be performed. This may involve any of: (a)
-* removing Mappings by annulling any of the pointers supplied,
-* (b) replacing them with pointers to new Mappings, (c)
-* inserting additional Mappings and (d) changing their order.
-*
-* The intention is to reduce the number of Mappings in the
-* sequence, if possible, and any reduction will be reflected in
-* the value of "*nmap" returned. However, simplifications which
-* do not reduce the length of the sequence (but improve its
-* execution time, for example) may also be performed, and the
-* sequence might conceivably increase in length (but normally
-* only in order to split up a Mapping into pieces that can be
-* more easily merged with their neighbours on subsequent
-* invocations of this function).
-*
-* If Mappings are removed from the sequence, any gaps that
-* remain will be closed up, by moving subsequent Mapping
-* pointers along in the array, so that vacated elements occur
-* at the end. If the sequence increases in length, the array
-* will be extended (and its pointer updated) if necessary to
-* accommodate any new elements.
-*
-* Note that any (or all) of the Mapping pointers supplied in
-* this array may be annulled by this function, but the Mappings
-* to which they refer are not modified in any way (although
-* they may, of course, be deleted if the annulled pointer is
-* the final one).
-* invert_list
-* Address of a pointer to a dynamically allocated array which,
-* on entry, should contain values to be assigned to the Invert
-* attributes of the Mappings identified in the "*map_list"
-* array before they are applied (this array might have been
-* produced, for example, by the astMapList method). These
-* values will be used by this function instead of the actual
-* Invert attributes of the Mappings supplied, which are
-* ignored.
-*
-* On exit, the contents of this array will be updated to
-* correspond with the possibly modified contents of the
-* "*map_list" array. If the Mapping sequence increases in
-* length, the "*invert_list" array will be extended (and its
-* pointer updated) if necessary to accommodate any new
-* elements.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* If simplification was possible, the function returns the index
-* in the "map_list" array of the first element which was
-* modified. Otherwise, it returns -1 (and makes no changes to the
-* arrays supplied).
-
-* Notes:
-* - A value of -1 will be returned if this function is invoked
-* with the global error status set, or if it should fail for any
-* reason.
-*/
-
-/* Local Variables: */
- AstMapping *new; /* Pointer to replacement Mapping */
- AstSpecMap *specmap; /* Pointer to SpecMap */
- const char *argdesc[ MAX_ARGS ]; /* Argument descriptions (junk) */
- const char *class; /* Pointer to Mapping class string */
- const char *comment; /* Pointer to comment string (junk) */
- double (*cvtargs)[ MAX_ARGS ]; /* Pointer to argument arrays */
- double tmp; /* Temporary storage */
- int *cvttype; /* Pointer to transformation type codes */
- int *narg; /* Pointer to argument count */
- int *szarg; /* Pointer to argument array size */
- int argdec; /* Index of DEC argument */
- int argra; /* Index of RA argument */
- int done; /* Finished (no further simplification)? */
- int iarg; /* Loop counter for arguments */
- int icvt1; /* Loop initial value */
- int icvt2; /* Loop final value */
- int icvt; /* Loop counter for transformation steps */
- int ikeep; /* Index to store step being kept */
- int imap1; /* Index of first SpecMap to merge */
- int imap2; /* Index of last SpecMap to merge */
- int imap; /* Loop counter for Mappings */
- int inc; /* Increment for transformation step loop */
- int invert; /* SpecMap applied in inverse direction? */
- int istep; /* Loop counter for transformation steps */
- int keep; /* Keep transformation step? */
- int ngone; /* Number of Mappings eliminated */
- int nin; /* Numbr of axes for SpecMaps being merged */
- int nstep0; /* Original number of transformation steps */
- int nstep; /* Total number of transformation steps */
- int result; /* Result value to return */
- int simpler; /* Simplification possible? */
- int unit; /* Replacement Mapping is a UnitMap? */
-
-/* Initialise. */
- result = -1;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* SpecMaps can only be merged if they are in series (or if there is
- only one Mapping present, in which case it makes no difference), so
- do nothing if they are not. */
- if ( series || ( *nmap == 1 ) ) {
-
-/* Save the number of inputs for the SpecMap. */
- nin = astGetNin( this );
-
-/* Initialise the number of transformation steps to be merged to equal
- the number in the nominated SpecMap. */
- nstep = ( (AstSpecMap *) ( *map_list )[ where ] )->ncvt;
-
-/* Search adjacent lower-numbered Mappings until one is found which is
- not a SpecMap, or is a SpecMap with a different number of axes. Accumulate
- the number of transformation steps involved in any SpecMaps found. */
- imap1 = where;
- while ( ( imap1 - 1 >= 0 ) && astOK ) {
- class = astGetClass( ( *map_list )[ imap1 - 1 ] );
- if ( !astOK || strcmp( class, "SpecMap" ) ||
- astGetNin( ( *map_list )[ imap1 - 1 ] ) != nin ) break;
- nstep += ( (AstSpecMap *) ( *map_list )[ imap1 - 1 ] )->ncvt;
- imap1--;
- }
-
-/* Similarly search adjacent higher-numbered Mappings. */
- imap2 = where;
- while ( ( imap2 + 1 < *nmap ) && astOK ) {
- class = astGetClass( ( *map_list )[ imap2 + 1 ] );
- if ( !astOK || strcmp( class, "SpecMap" ) ||
- astGetNin( ( *map_list )[ imap2 + 1 ] ) != nin ) break;
- nstep += ( (AstSpecMap *) ( *map_list )[ imap2 + 1 ] )->ncvt;
- imap2++;
- }
-
-/* Remember the initial number of transformation steps. */
- nstep0 = nstep;
-
-/* Allocate memory for accumulating a list of all the transformation
- steps involved in all the SpecMaps found. */
- cvttype = astMalloc( sizeof( int ) * (size_t) nstep );
- cvtargs = astMalloc( sizeof( double[ MAX_ARGS ] ) * (size_t) nstep );
- szarg = astMalloc( sizeof( int ) * (size_t) nstep );
- narg = astMalloc( sizeof( int ) * (size_t) nstep );
-
-/* Loop to obtain the transformation data for each SpecMap being merged. */
- nstep = 0;
- for ( imap = imap1; astOK && ( imap <= imap2 ); imap++ ) {
-
-/* Obtain a pointer to the SpecMap and note if it is being applied in
- its inverse direction. */
- specmap = (AstSpecMap *) ( *map_list )[ imap ];
- invert = ( *invert_list )[ imap ];
-
-/* Set up loop limits and an increment to scan the transformation
- steps in each SpecMap in either the forward or reverse direction, as
- dictated by the associated "invert" value. */
- icvt1 = invert ? specmap->ncvt - 1 : 0;
- icvt2 = invert ? -1 : specmap->ncvt;
- inc = invert ? -1 : 1;
-
-/* Loop through each transformation step in the SpecMap. */
- for ( icvt = icvt1; icvt != icvt2; icvt += inc ) {
-
-/* Store the transformation type code and use "CvtString" to determine
- the associated number of arguments. Then store these arguments. */
- cvttype[ nstep ] = specmap->cvttype[ icvt ];
- (void) CvtString( cvttype[ nstep ], &comment, &argra, &argdec,
- narg + nstep, szarg + nstep, argdesc, status );
- if ( !astOK ) break;
- for ( iarg = 0; iarg < szarg[ nstep ]; iarg++ ) {
- cvtargs[ nstep ][ iarg ] = specmap->cvtargs[ icvt ][ iarg ];
- }
-
-/* If the SpecMap is inverted, we must not only accumulate its
- transformation steps in reverse, but also apply them in
- reverse. For some steps this means changing arguments, for some it
- means changing the transformation type code to a complementary
- value, and for others it means both. Define macros to perform each
- of the required changes. */
-
-/* Macro to exchange a transformation type code for its inverse (and
- vice versa). */
-#define SWAP_CODES( code1, code2 ) \
- if ( cvttype[ nstep ] == code1 ) { \
- cvttype[ nstep ] = code2; \
- } else if ( cvttype[ nstep ] == code2 ) { \
- cvttype[ nstep ] = code1; \
- }
-
-/* Macro to exchange a transformation type code for its inverse (and
- vice versa), and reciprocate a specified argument. */
-#define SWAP_CODES2( code1, code2, jarg ) \
- if ( cvttype[ nstep ] == code1 ) { \
- cvttype[ nstep ] = code2; \
- tmp = cvtargs[ nstep ][ jarg ]; \
- if( tmp != AST__BAD && tmp != 0.0 ) { \
- cvtargs[ nstep ][ jarg ] = 1.0/tmp; \
- } else { \
- cvtargs[ nstep ][ jarg ] = AST__BAD; \
- } \
- } else if ( cvttype[ nstep ] == code2 ) { \
- cvttype[ nstep ] = code1; \
- tmp = cvtargs[ nstep ][ jarg ]; \
- if( tmp != AST__BAD && tmp != 0.0 ) { \
- cvtargs[ nstep ][ jarg ] = 1.0/tmp; \
- } else { \
- cvtargs[ nstep ][ jarg ] = AST__BAD; \
- } \
- }
-
-/* Macro to exchange a transformation type code for its inverse (and
- vice versa), and negate a specified argument. */
-#define SWAP_CODES3( code1, code2, jarg ) \
- if ( cvttype[ nstep ] == code1 ) { \
- cvttype[ nstep ] = code2; \
- tmp = cvtargs[ nstep ][ jarg ]; \
- if( tmp != AST__BAD ) { \
- cvtargs[ nstep ][ jarg ] = -tmp; \
- } \
- } else if ( cvttype[ nstep ] == code2 ) { \
- cvttype[ nstep ] = code1; \
- tmp = cvtargs[ nstep ][ jarg ]; \
- if( tmp != AST__BAD ) { \
- cvtargs[ nstep ][ jarg ] = -tmp; \
- } \
- }
-
-/* Use these macros to apply the changes where needed. */
- if ( invert ) {
-
-/* Exchange transformation codes for their inverses. */
- SWAP_CODES( AST__FRTOVL, AST__VLTOFR )
- SWAP_CODES( AST__ENTOFR, AST__FRTOEN )
- SWAP_CODES( AST__WNTOFR, AST__FRTOWN )
- SWAP_CODES( AST__WVTOFR, AST__FRTOWV )
- SWAP_CODES( AST__AWTOFR, AST__FRTOAW )
- SWAP_CODES( AST__VRTOVL, AST__VLTOVR )
- SWAP_CODES( AST__VOTOVL, AST__VLTOVO )
- SWAP_CODES( AST__ZOTOVL, AST__VLTOZO )
- SWAP_CODES( AST__BTTOVL, AST__VLTOBT )
-
-/* Exchange transformation codes for their inverses, and reciprocate the
- frequency correction factor. */
- SWAP_CODES2( AST__TPF2HL, AST__HLF2TP, 6 )
- SWAP_CODES2( AST__USF2HL, AST__HLF2US, 3 )
- SWAP_CODES2( AST__GEF2HL, AST__HLF2GE, 3 )
- SWAP_CODES2( AST__BYF2HL, AST__HLF2BY, 3 )
- SWAP_CODES2( AST__LKF2HL, AST__HLF2LK, 2 )
- SWAP_CODES2( AST__LDF2HL, AST__HLF2LD, 2 )
- SWAP_CODES2( AST__LGF2HL, AST__HLF2LG, 2 )
- SWAP_CODES2( AST__GLF2HL, AST__HLF2GL, 2 )
-
- }
-
-/* Undefine the local macros. */
-#undef SWAP_CODES
-#undef SWAP_CODES2
-#undef SWAP_CODES3
-
-/* Count the transformation steps. */
- nstep++;
- }
- }
-
-/* Loop to simplify the sequence of transformation steps until no
- further improvement is possible. */
- done = 0;
- while ( astOK && !done ) {
-
-/* Examine each remaining transformation step in turn. */
- ikeep = -1;
- for ( istep = 0; istep < nstep; istep++ ) {
-
-/* Initially assume we will retain the current step. */
- keep = 1;
-
-/* The only simplifications for the conversions currently in this class act
- to combine adjacent transformation steps, so only apply them while there
- are at least 2 steps left. */
- if ( istep < ( nstep - 1 ) ) {
-
-/* Define a macro to test if two adjacent transformation type codes
- have specified values. */
-#define PAIR_CVT( code1, code2 ) \
- ( ( cvttype[ istep ] == code1 ) && \
- ( cvttype[ istep + 1 ] == code2 ) )
-
-/* Define a macro to test if two adjacent transformation type codes
- have specified values, either way round. */
-#define PAIR_CVT2( code1, code2 ) \
- ( ( PAIR_CVT( code1, code2 ) ) || \
- ( PAIR_CVT( code2, code1 ) ) )
-
-/* If a correction is followed by its inverse, and the user-supplied argument
- values are unchanged (we do not need to test values stored in the
- argument array which were not supplied by the user), we can eliminate them.
- First check for conversions which have no user-supplied arguments. */
- if ( PAIR_CVT2( AST__ENTOFR, AST__FRTOEN ) ||
- PAIR_CVT2( AST__WNTOFR, AST__FRTOWN ) ||
- PAIR_CVT2( AST__WVTOFR, AST__FRTOWV ) ||
- PAIR_CVT2( AST__AWTOFR, AST__FRTOAW ) ||
- PAIR_CVT2( AST__VRTOVL, AST__VLTOVR ) ||
- PAIR_CVT2( AST__VOTOVL, AST__VLTOVO ) ||
- PAIR_CVT2( AST__ZOTOVL, AST__VLTOZO ) ||
- PAIR_CVT2( AST__BTTOVL, AST__VLTOBT ) ) {
- istep++;
- keep = 0;
-
-/* Now check for conversions which have a single user-supplied argument. */
- } else if( PAIR_CVT2( AST__FRTOVL, AST__VLTOFR ) &&
- astEQUAL( cvtargs[ istep ][ 0 ],
- cvtargs[ istep + 1 ][ 0 ] ) ) {
- istep++;
- keep = 0;
-
-/* Now check for conversions which have two user-supplied arguments. */
- } else if( ( PAIR_CVT2( AST__LKF2HL, AST__HLF2LK ) ||
- PAIR_CVT2( AST__LDF2HL, AST__HLF2LD ) ||
- PAIR_CVT2( AST__LGF2HL, AST__HLF2LG ) ||
- PAIR_CVT2( AST__GLF2HL, AST__HLF2GL ) ) &&
- astEQUAL( cvtargs[ istep ][ 0 ],
- cvtargs[ istep + 1 ][ 0 ] ) &&
- astEQUAL( cvtargs[ istep ][ 1 ],
- cvtargs[ istep + 1 ][ 1 ] ) ) {
- istep++;
- keep = 0;
-
-/* Now check for conversions which have three user-supplied arguments. */
- } else if( ( PAIR_CVT2( AST__GEF2HL, AST__HLF2GE ) ||
- PAIR_CVT2( AST__BYF2HL, AST__HLF2BY ) ||
- PAIR_CVT2( AST__USF2HL, AST__HLF2US ) ) &&
- astEQUAL( cvtargs[ istep ][ 0 ],
- cvtargs[ istep + 1 ][ 0 ] ) &&
- astEQUAL( cvtargs[ istep ][ 1 ],
- cvtargs[ istep + 1 ][ 1 ] ) &&
- astEQUAL( cvtargs[ istep ][ 2 ],
- cvtargs[ istep + 1 ][ 2 ] ) ) {
- istep++;
- keep = 0;
-
-/* Now check for conversions which have six user-supplied arguments (currently
- no conversions have four or five user-supplied arguments). */
- } else if( ( PAIR_CVT2( AST__TPF2HL, AST__HLF2TP ) ) &&
- astEQUAL( cvtargs[ istep ][ 0 ],
- cvtargs[ istep + 1 ][ 0 ] ) &&
- astEQUAL( cvtargs[ istep ][ 1 ],
- cvtargs[ istep + 1 ][ 1 ] ) &&
- astEQUAL( cvtargs[ istep ][ 2 ],
- cvtargs[ istep + 1 ][ 2 ] ) &&
- astEQUAL( cvtargs[ istep ][ 3 ],
- cvtargs[ istep + 1 ][ 3 ] ) &&
- astEQUAL( cvtargs[ istep ][ 4 ],
- cvtargs[ istep + 1 ][ 4 ] ) &&
- astEQUAL( cvtargs[ istep ][ 5 ],
- cvtargs[ istep + 1 ][ 5 ] ) ) {
- istep++;
- keep = 0;
-
- }
-
-/* Undefine the local macros. */
-#undef PAIR_CVT
-#undef PAIR_CVT2
- }
-
-/* If the current transformation (possibly modified above) is being
- kept, then increment the index that identifies its new location in
- the list of transformation steps. */
- if ( keep ) {
- ikeep++;
-
-/* If the new location is different to its current location, copy the
- transformation data into the new location. */
- if ( ikeep != istep ) {
- cvttype[ ikeep ] = cvttype[ istep ];
- for ( iarg = 0; iarg < szarg[ istep ]; iarg++ ) {
- cvtargs[ ikeep ][ iarg ] = cvtargs[ istep ][ iarg ];
- }
- szarg[ ikeep ] = szarg[ istep ];
- narg[ ikeep ] = narg[ istep ];
- }
- }
- }
-
-/* Note if no simplification was achieved on this iteration (i.e. the
- number of transformation steps was not reduced). This is the signal
- to quit. */
- done = ( ( ikeep + 1 ) >= nstep );
-
-/* Note how many transformation steps now remain. */
- nstep = ikeep + 1;
- }
-
-/* Determine how many Mappings can be eliminated by condensing all
- those considered above into a single Mapping. */
- if ( astOK ) {
- ngone = imap2 - imap1;
-
-/* Determine if the replacement Mapping can be a UnitMap (a null
- Mapping). This will only be the case if all the transformation
- steps were eliminated above. */
- unit = ( nstep == 0 );
-
-/* Determine if simplification is possible. This will be the case if
- (a) Mappings were eliminated ("ngone" is non-zero), or (b) the
- number of transformation steps was reduced, or (c) the SpecMap(s)
- can be replaced by a UnitMap, or (d) if there was initially only
- one SpecMap present, its invert flag was set (this flag will always
- be cleared in the replacement Mapping). */
- simpler = ngone || ( nstep < nstep0 ) || unit ||
- ( *invert_list )[ where ];
-
-/* Do nothing more unless simplification is possible. */
- if ( simpler ) {
-
-/* If the replacement Mapping is a UnitMap, then create it. */
- if ( unit ) {
- new = (AstMapping *)
- astUnitMap( astGetNin( ( *map_list )[ where ] ), "", status );
-
-/* Otherwise, create a replacement SpecMap and add each of the
- remaining transformation steps to it. */
- } else {
- new = (AstMapping *) astSpecMap( nin, 0, "", status );
- for ( istep = 0; istep < nstep; istep++ ) {
- AddSpecCvt( (AstSpecMap *) new, cvttype[ istep ],
- narg[ istep ], cvtargs[ istep ], status );
- }
- }
-
-/* Annul the pointers to the Mappings being eliminated. */
- if ( astOK ) {
- for ( imap = imap1; imap <= imap2; imap++ ) {
- ( *map_list )[ imap ] = astAnnul( ( *map_list )[ imap ] );
- }
-
-/* Insert the pointer and invert value for the new Mapping. */
- ( *map_list )[ imap1 ] = new;
- ( *invert_list )[ imap1 ] = 0;
-
-/* Move any subsequent Mapping information down to close the gap. */
- for ( imap = imap2 + 1; imap < *nmap; imap++ ) {
- ( *map_list )[ imap - ngone ] = ( *map_list )[ imap ];
- ( *invert_list )[ imap - ngone ] = ( *invert_list )[ imap ];
- }
-
-/* Blank out any information remaining at the end of the arrays. */
- for ( imap = ( *nmap - ngone ); imap < *nmap; imap++ ) {
- ( *map_list )[ imap ] = NULL;
- ( *invert_list )[ imap ] = 0;
- }
-
-/* Decrement the Mapping count and return the index of the first
- Mapping which was eliminated. */
- ( *nmap ) -= ngone;
- result = imap1;
-
-/* If an error occurred, annul the new Mapping pointer. */
- } else {
- new = astAnnul( new );
- }
- }
- }
-
-/* Free the memory used for the transformation steps. */
- cvttype = astFree( cvttype );
- cvtargs = astFree( cvtargs );
- szarg = astFree( szarg );
- narg = astFree( narg );
- }
-
-/* If an error occurred, clear the returned value. */
- if ( !astOK ) result = -1;
-
-/* Return the result. */
- return result;
-}
-
-static double Rate( AstMapping *this, double *at, int ax1, int ax2, int *status ){
-/*
-* Name:
-* Rate
-
-* Purpose:
-* Calculate the rate of change of a Mapping output.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* result = Rate( AstMapping *this, double *at, int ax1, int ax2, int *status )
-
-* Class Membership:
-* SpecMap member function (overrides the astRate method inherited
-* from the Mapping class ).
-
-* Description:
-* This function returns the rate of change of a specified output of
-* the supplied Mapping with respect to a specified input, at a
-* specified input position.
-
-* Parameters:
-* this
-* Pointer to the Mapping to be applied.
-* at
-* The address of an array holding the axis values at the position
-* at which the rate of change is to be evaluated. The number of
-* elements in this array should equal the number of inputs to the
-* Mapping.
-* ax1
-* The index of the Mapping output for which the rate of change is to
-* be found (output numbering starts at 0 for the first output).
-* ax2
-* The index of the Mapping input which is to be varied in order to
-* find the rate of change (input numbering starts at 0 for the first
-* input).
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The rate of change of Mapping output "ax1" with respect to input
-* "ax2", evaluated at "at", or AST__BAD if the value cannot be
-* calculated.
-
-* Implementation Deficiencies:
-* The initial version of this implementation only deals with
-* frequency->wavelength conversions. This is because the slowness of
-* the numerical differentiation implemented by the astRate method in
-* the parent Mapping class is cripples conversion between SpecFluxFrames.
-* Such conversions only rely on rate of change of wavelength with
-* respect to frequency. This implementation should be extended when
-* needed.
-
-*/
-
-/* Local Variables: */
- AstSpecMap *map;
- double result;
- int cvt;
-
-/* Check inherited status */
- if( !astOK ) return AST__BAD;
-
-/* Get a pointer to the SpecMap structure. */
- map = (AstSpecMap *) this;
-
-/* Return 1.0 if the SpecMap has no conversions. */
- if( map->ncvt == 0 ) return 1.0;
-
-/* Store the type of the first conversion.*/
- cvt = map->cvttype[ 0 ];
-
-/* If this is a 3D SpecMap or if it has more than one component, or if
- that conversion is not between frequency and wavelength, use the
- astRate method inherited form the parent Mapping class. */
- if( astGetNin( map ) != 1 || map->ncvt != 1 ||
- ( cvt != AST__WVTOFR && cvt != AST__FRTOWV ) ) {
- result = (*parent_rate)( this, at, ax1, ax2, status );
-
-/* Otherwise, evaluate the known analytical expressions for the rate of
- change of frequency with respect to wavelength or wavelength with
- respect to frequency. */
- } else {
- result = ( *at != AST__BAD ) ? -AST__C/((*at)*(*at)) : AST__BAD;
- }
-
-/* Return the result. */
- return result;
-}
-
-static double Refrac( double wavelen, int *status ){
-/*
-* Name:
-* Refrac
-
-* Purpose:
-* Returns the refractive index of dry air at a given wavelength.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double Refrac( double wavelen, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function returns the refractive index of dry air at standard
-* temperature and pressure, at a given wavelength. The formula is
-* taken from the paper "Representation of Spectral Coordinates in FITS"
-* (Greisen et al).
-
-* Parameters:
-* wavelen
-* The wavelength, in metres. This should be the air wavelength,
-* but supplying the vacuum wavelength will make no significant
-* difference.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The refractive index. A value of 1.0 is returned if an error
-* occurs, or has already occurred.
-
-*/
-
-/* Local Variables: */
- double w2; /* Wavenumber squared */
-
-/* Check the global error status. */
- if ( !astOK || wavelen == 0.0 ) return 1.0;
-
-/* Find the squared wave number in units of "(per um)**2". */
- w2 = 1.0E-12/( wavelen * wavelen );
-
-/* Apply the rest of the algorithm as described in the FITS WCS
- paper III. */
- return 1.0 + 1.0E-6*( 287.6155 + 1.62887*w2 + 0.01360*w2*w2 );
-}
-
-static double Rverot( double phi, double h, double ra, double da,
- double st, int *status ) {
-/*
-* Name:
-* Rverot
-
-* Purpose:
-* Find the velocity component in a given direction due to Earth rotation.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double Rverot( double phi, double h, double ra, double da,
-* double st, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function is like slaRverot, except that it takes account of the
-* observers height (h), and does all calculations in double precision.
-
-* Parameters:
-* phi
-* The geodetic latitude of the observer (radians, IAU 1976).
-* h
-* The geodetic height above the reference spheroid of the observer
-* (metres, IAU 1976).
-* ra
-* The geocentric apparent RA (rads) of the source.
-* da
-* The geocentric apparent Dec (rads) of the source.
-* st
-* The local apparent sidereal time (radians).
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the Earth rotation in direction [RA,DA] (km/s).
-* The result is positive when the observer is receding from the
-* given point on the sky. Zero is returned if an error has already
-* occurred.
-
-*/
-
-/* Local Variables: */
- double pv[ 6 ]; /* Observer position and velocity */
- double v[ 3 ]; /* Source direction vector */
-
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* Get the Cartesian coordinates of the unit vector pointing towards the
- given sky position. */
- palDcs2c( ra, da, v );
-
-/* Get velocity and position of the observer. */
- palPvobs( phi, h, st, pv );
-
-/* Return the component of the observer's velocity away from the sky
- position, and convert from AU/s to km/s. */
- return -palDvdv( v, pv + 3 )*149.597870E6;
-}
-
-static void SpecAdd( AstSpecMap *this, const char *cvt, int narg,
- const double args[], int *status ) {
-/*
-*++
-* Name:
-c astSpecAdd
-f AST_SPECADD
-
-* Purpose:
-* Add a spectral coordinate conversion to a SpecMap.
-
-* Type:
-* Public virtual function.
-
-* Synopsis:
-c #include "specmap.h"
-c void astSpecAdd( AstSpecMap *this, const char *cvt, int narg,
-c const double args[] )
-f CALL AST_SPECADD( THIS, CVT, NARG, ARGS, STATUS )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-c This function adds one of the standard spectral coordinate
-f This routine adds one of the standard spectral coordinate
-* system conversions listed below to an existing SpecMap.
-*
-c When a SpecMap is first created (using astSpecMap), it simply
-f When a SpecMap is first created (using AST_SPECMAP), it simply
-c performs a unit (null) Mapping. By using astSpecAdd (repeatedly
-f performs a unit (null) Mapping. By using AST_SPECADD (repeatedly
-* if necessary), one or more coordinate conversion steps may then
-* be added, which the SpecMap will perform in sequence. This allows
-* multi-step conversions between a variety of spectral coordinate
-* systems to be assembled out of the building blocks provided by
-* this class.
-*
-* Normally, if a SpecMap's Invert attribute is zero (the default),
-* then its forward transformation is performed by carrying out
-* each of the individual coordinate conversions specified by
-c astSpecAdd in the order given (i.e. with the most recently added
-f AST_SPECADD in the order given (i.e. with the most recently added
-* conversion applied last).
-*
-* This order is reversed if the SpecMap's Invert attribute is
-* non-zero (or if the inverse transformation is requested by any
-* other means) and each individual coordinate conversion is also
-* replaced by its own inverse. This process inverts the overall
-* effect of the SpecMap. In this case, the first conversion to be
-* applied would be the inverse of the one most recently added.
-
-* Parameters:
-c this
-f THIS = INTEGER (Given)
-* Pointer to the SpecMap.
-c cvt
-f CVT = CHARACTER * ( * ) (Given)
-c Pointer to a null-terminated string which identifies the
-f A character string which identifies the
-* spectral coordinate conversion to be added to the
-* SpecMap. See the "Available Conversions" section for details of
-* those available.
-c narg
-f NARG = INTEGER (Given)
-* The number of argument values supplied in the
-c "args" array.
-f ARGS array.
-c args
-f ARGS( * ) = DOUBLE PRECISION (Given)
-* An array containing argument values for the spectral
-* coordinate conversion. The number of arguments required, and
-* hence the number of array elements used, depends on the
-* conversion specified (see the "Available Conversions"
-* section). This array is ignored
-c and a NULL pointer may be supplied
-* if no arguments are needed.
-f STATUS = INTEGER (Given and Returned)
-f The global status.
-
-* Notes:
-* - When assembling a multi-stage conversion, it can sometimes be
-* difficult to determine the most economical conversion path. For
-* example, when converting between reference frames, converting first
-* to the heliographic reference frame as an intermediate stage is often
-* sensible in formulating the problem, but may introduce unnecessary
-* extra conversion steps. A solution to this is to include all the steps
-* which are (logically) necessary, but then to use
-c astSimplify to simplify the resulting
-f AST_SIMPLIFY to simplify the resulting
-* SpecMap. The simplification process will eliminate any steps
-* which turn out not to be needed.
-c - This function does not check to ensure that the sequence of
-f - This routine does not check to ensure that the sequence of
-* coordinate conversions added to a SpecMap is physically
-* meaningful.
-
-* Available Conversions:
-* The following strings (which are case-insensitive) may be supplied
-c via the "cvt" parameter to indicate which spectral coordinate
-f via the CVT argument to indicate which spectral coordinate
-* conversion is to be added to the SpecMap. Where arguments are needed by
-* the conversion, they are listed in parentheses. Values for
-c these arguments should be given, via the "args" array, in the
-f these arguments should be given, via the ARGS array, in the
-* order indicated. Units and argument names are described at the end of
-* the list of conversions.
-
-* - "FRTOVL" (RF): Convert frequency to relativistic velocity.
-* - "VLTOFR" (RF): Convert relativistic velocity to Frequency.
-* - "ENTOFR": Convert energy to frequency.
-* - "FRTOEN": Convert frequency to energy.
-* - "WNTOFR": Convert wave number to frequency.
-* - "FRTOWN": Convert frequency to wave number.
-* - "WVTOFR": Convert wavelength (vacuum) to frequency.
-* - "FRTOWV": Convert frequency to wavelength (vacuum).
-* - "AWTOFR": Convert wavelength (air) to frequency.
-* - "FRTOAW": Convert frequency to wavelength (air).
-* - "VRTOVL": Convert radio to relativistic velocity.
-* - "VLTOVR": Convert relativistic to radio velocity.
-* - "VOTOVL": Convert optical to relativistic velocity.
-* - "VLTOVO": Convert relativistic to optical velocity.
-* - "ZOTOVL": Convert redshift to relativistic velocity.
-* - "VLTOZO": Convert relativistic velocity to redshift.
-* - "BTTOVL": Convert beta factor to relativistic velocity.
-* - "VLTOBT": Convert relativistic velocity to beta factor.
-* - "USF2HL" (VOFF,RA,DEC): Convert frequency from a user-defined
-* reference frame to heliocentric.
-* - "HLF2US" (VOFF,RA,DEC): Convert frequency from heliocentric
-* reference frame to user-defined.
-* - "TPF2HL" (OBSLON,OBSLAT,OBSALT,EPOCH,RA,DEC): Convert frequency from
-* topocentric reference frame to heliocentric.
-* - "HLF2TP" (OBSLON,OBSLAT,OBSALT,EPOCH,RA,DEC): Convert frequency from
-* heliocentric reference frame to topocentric.
-* - "GEF2HL" (EPOCH,RA,DEC): Convert frequency from geocentric
-* reference frame to heliocentric.
-* - "HLF2GE" (EPOCH,RA,DEC): Convert frequency from
-* heliocentric reference frame to geocentric.
-* - "BYF2HL" (EPOCH,RA,DEC): Convert frequency from
-* barycentric reference frame to heliocentric.
-* - "HLF2BY" (EPOCH,RA,DEC): Convert frequency from
-* heliocentric reference frame to barycentric.
-* - "LKF2HL" (RA,DEC): Convert frequency from kinematic LSR
-* reference frame to heliocentric.
-* - "HLF2LK" (RA,DEC): Convert frequency from heliocentric
-* reference frame to kinematic LSR.
-* - "LDF2HL" (RA,DEC): Convert frequency from dynamical LSR
-* reference frame to heliocentric.
-* - "HLF2LD" (RA,DEC): Convert frequency from heliocentric
-* reference frame to dynamical LSR.
-* - "LGF2HL" (RA,DEC): Convert frequency from local group
-* reference frame to heliocentric.
-* - "HLF2LG" (RA,DEC): Convert frequency from heliocentric
-* reference frame to local group.
-* - "GLF2HL" (RA,DEC): Convert frequency from galactic
-* reference frame to heliocentric.
-* - "HLF2GL" (RA,DEC): Convert frequency from heliocentric
-* reference frame to galactic.
-
-* The units for the values processed by the above conversions are as
-* follows:
-*
-* - all velocities: metres per second (positive if the source receeds from
-* the observer).
-* - frequency: Hertz.
-* - all wavelengths: metres.
-* - energy: Joules.
-* - wave number: cycles per metre.
-*
-* The arguments used in the above conversions are as follows:
-*
-* - RF: Rest frequency (Hz).
-* - OBSALT: Geodetic altitude of observer (IAU 1975, metres).
-* - OBSLAT: Geodetic latitude of observer (IAU 1975, radians).
-* - OBSLON: Longitude of observer (radians - positive eastwards).
-* - EPOCH: Epoch of observation (UT1 expressed as a Modified Julian Date).
-* - RA: Right Ascension of source (radians, FK5 J2000).
-* - DEC: Declination of source (radians, FK5 J2000).
-* - VOFF: Velocity of the user-defined reference frame, towards the
-* position given by RA and DEC, measured in the heliocentric
-* reference frame.
-*
-* If the SpecMap is 3-dimensional, source positions are provided by the
-* values supplied to inputs 2 and 3 of the SpecMap (which are simply
-* copied to outputs 2 and 3). Note, usable values are still required
-* for the RA and DEC arguments in order to define the "user-defined"
-* reference frame used by USF2HL and HLF2US. However, AST__BAD can be
-* supplied for RA and DEC if the user-defined reference frame is not
-* required.
-*
-*--
-*/
-
-/* Local Variables: */
- int cvttype; /* Conversion type code */
-
-/* Check the inherited status. */
- if ( !astOK ) return;
-
-/* Validate the type string supplied and obtain the equivalent
- conversion type code. */
- cvttype = CvtCode( cvt, status );
-
-/* If the string was not recognised, then report an error. */
- if ( astOK && ( cvttype == AST__SPEC_NULL ) ) {
- astError( AST__SPCIN,
- "%s(%s): Invalid SpecMap spectral coordinate "
- "conversion type \"%s\".", status, "astAddSpec", astGetClass( this ), cvt );
- }
-
-/* Add the new conversion to the SpecMap. */
- AddSpecCvt( this, cvttype, narg, args, status );
-}
-
-static int SystemChange( int cvt_code, int np, double *values, double *args,
- int forward, int *status ){
-/*
-* Name:
-* SystemChange
-
-* Purpose:
-* Change values between two spectral systems.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* int SystemChange( int cvt_code, int np, double *values, double *args,
-* int forward, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function modifies the supplied values in order to change the
-* spectral co-ordinate system (frequency, wavelength, etc) to which
-* they refer.
-
-* Parameters:
-* cvt_code
-* A code indicating the conversion to be applied. If the code does
-* not correspond to a change of system, then the supplied values
-* are left unchanged and zero is returned as the function value.
-* np
-* The number of frequency values to transform.
-* values
-* Pointer to an array of "np" spectral values. These are modified on
-* return to hold the corresponding values measured in the output
-* system.
-* args
-* Pointer to an array holding the conversion arguments. The number
-* of arguments expected depends on the particular conversion being
-* used.
-* forward
-* Should the conversion be applied in the forward or inverse
-* direction? Non-zero for forward, zero for inverse.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* Non-zero if the supplied conversion code corresponds to a change of
-* system. Zero otherwise (in which case the upplied values will not
-* have been changed).
-
-*/
-
-/* Local Variables: */
- double *pv; /* Pointer to next value */
- double d; /* Intermediate value */
- double f2; /* Squared frequency */
- double temp; /* Intermediate value */
- int i; /* Loop index */
- int iter; /* Iteration count */
- int result; /* Returned value */
-
-/* Check inherited status. */
- if( !astOK ) return 0;
-
-/* Set the return value to indicate that the supplied conversion code
- represents a change of system. */
- result = 1;
-
-/* Test for each code value in turn and assign the appropriate values. */
- switch ( cvt_code ) {
-
-/* Frequency to relativistic velocity. */
- case AST__FRTOVL:
- if( forward ) {
- if( args[ 0 ] != AST__BAD ) {
- temp = args[ 0 ] * args[ 0 ];
- pv = values - 1;
- for( i = 0; i < np; i++ ){
- pv++;
- if( *pv != AST__BAD ) {
- f2 = ( *pv ) * ( *pv );
- d = temp + f2;
- if( d > 0.0 ) {
- *pv = AST__C*( ( temp - f2 )/d );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- }
- }
- } else {
- pv = values;
- for( i = 0; i < np; i++ ) *( pv++ ) = AST__BAD;
- }
- } else {
- SystemChange( AST__VLTOFR, np, values, args, 1, status );
- }
- break;
-
-/* Relativistic velocity to frequency. */
- case AST__VLTOFR:
- if( forward ) {
- if( args[ 0 ] != AST__BAD ) {
- temp = args[ 0 ];
- pv = values - 1;
- for( i = 0; i < np; i++ ){
- pv++;
- if( *pv != AST__BAD ) {
- d = AST__C + ( *pv );
- if( d != 0.0 ) {
- d = ( AST__C - ( *pv ) )/d;
- if( d >= 0.0 ) {
- *pv = temp*sqrt( d );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- } else {
- *pv = AST__BAD;
- }
- }
- }
- } else {
- pv = values;
- for( i = 0; i < np; i++ ) *( pv++ ) = AST__BAD;
- }
- } else {
- SystemChange( AST__FRTOVL, np, values, args, 1, status );
- }
- break;
-
-/* Energy to frequency */
- case AST__ENTOFR:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- *pv /= AST__H;
- }
- }
- } else {
- SystemChange( AST__FRTOEN, np, values, args, 1, status );
- }
- break;
-
-/* Frequency to energy */
- case AST__FRTOEN:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- *pv *= AST__H;
- }
- }
- } else {
- SystemChange( AST__ENTOFR, np, values, args, 1, status );
- }
- break;
-
-/* Wave number to frequency */
- case AST__WNTOFR:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- *pv *= AST__C;
- }
- }
- } else {
- SystemChange( AST__FRTOWN, np, values, args, 1, status );
- }
- break;
-
-/* Wave number to frequency */
- case AST__FRTOWN:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- *pv /= AST__C;
- }
- }
- } else {
- SystemChange( AST__WNTOFR, np, values, args, 1, status );
- }
- break;
-
-/* Wavelength to frequency */
- case AST__WVTOFR:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD && *pv != 0.0 ) {
- *pv = AST__C/( *pv );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__FRTOWV, np, values, args, 1, status );
- }
- break;
-
-/* Frequency to wavelength. */
- case AST__FRTOWV:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD && *pv != 0.0 ) {
- *pv = AST__C/( *pv );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__WVTOFR, np, values, args, 1, status );
- }
- break;
-
-/* Wavelength in air to frequency. */
- case AST__AWTOFR:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD && *pv != 0.0 ) {
- *pv = AST__C/( ( *pv )*Refrac( *pv, status ) );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__FRTOAW, np, values, args, 1, status );
- }
- break;
-
-/* Frequency to wavelength in air. */
- case AST__FRTOAW:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD && *pv != 0.0 ) {
-
-/* Form the vacuum wavelength. */
- temp = AST__C/( *pv );
-
-/* The refractive index function "Refrac" requires the wavelength in air
- as its parameter. Initially assume that the wavelength in air is equal
- to the vacuum wavelength to get he first estimate of the wavelength in
- air. Then use this estimate to get a better refractive index in order to
- form a better estimate of the air wavelength, etc. Iterate in this way a
- few times. */
- *pv = temp;
- for( iter = 0; iter < 3; iter++ ) {
- *pv = temp/Refrac( *pv, status );
- if( !astISFINITE( *pv ) ) {
- *pv = AST__BAD;
- break;
- }
- }
-
- } else {
- *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__AWTOFR, np, values, args, 1, status );
- }
- break;
-
-/* Radio velocity to relativistic velocity */
- case AST__VRTOVL:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- temp = 1.0 - ( *pv )/AST__C;
- temp *= temp;
- *pv = AST__C*( 1.0 - temp )/( 1.0 + temp );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__VLTOVR, np, values, args, 1, status );
- }
- break;
-
-/* Relativistic velocity to radio velocity. */
- case AST__VLTOVR:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- temp = AST__C + ( *pv );
- if( temp != 0.0 ) {
- temp = (AST__C - *pv )/temp;
- if( temp >= 0.0 ) {
- *pv = AST__C*( 1.0 - sqrt( temp ) );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- } else {
- *pv = AST__BAD;
- }
- }
- }
- } else {
- SystemChange( AST__VRTOVL, np, values, args, 1, status );
- }
- break;
-
-/* Optical velocity to relativistic velocity */
- case AST__VOTOVL:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- temp = 1.0 + ( *pv )/AST__C;
- temp *= temp;
- *pv = AST__C*( temp - 1.0 )/( temp + 1.0 );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__VLTOVO, np, values, args, 1, status );
- }
- break;
-
-/* Relativistic velocity to optical velocity. */
- case AST__VLTOVO:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- temp = AST__C - *pv;
- if( temp != 0.0 ) {
- temp = (AST__C + *pv )/temp;
- if( temp >= 0.0 ) {
- *pv = AST__C*( sqrt( temp ) - 1.0 );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- } else {
- *pv = AST__BAD;
- }
- }
- }
- } else {
- SystemChange( AST__VOTOVL, np, values, args, 1, status );
- }
- break;
-
-/* Redshift to relativistic velocity */
- case AST__ZOTOVL:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- temp = 1.0 + ( *pv );
- temp *= temp;
- *pv = AST__C*( temp - 1.0 )/( temp + 1.0 );
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- }
- }
- } else {
- SystemChange( AST__VLTOZO, np, values, args, 1, status );
- }
- break;
-
-/* Relativistic velocity to redshift. */
- case AST__VLTOZO:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- temp = AST__C - *pv;
- if( temp != 0.0 ) {
- temp = (AST__C + *pv )/temp;
- if( temp >= 0.0 ) {
- *pv = sqrt( temp ) - 1.0;
- if( !astISFINITE( *pv ) ) *pv = AST__BAD;
- } else {
- *pv = AST__BAD;
- }
- } else {
- *pv = AST__BAD;
- }
- }
- }
- } else {
- SystemChange( AST__ZOTOVL, np, values, args, 1, status );
- }
- break;
-
-/* Beta factor to relativistic velocity */
- case AST__BTTOVL:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- *pv *= AST__C;
- }
- }
- } else {
- SystemChange( AST__VLTOBT, np, values, args, 1, status );
- }
- break;
-
-/* Relativistic velocity to beta factor. */
- case AST__VLTOBT:
- if( forward ) {
- pv = values - 1;
- for( i = 0; i < np; i++ ) {
- pv++;
- if( *pv != AST__BAD ) {
- *pv /= AST__C;
- }
- }
- } else {
- SystemChange( AST__BTTOVL, np, values, args, 1, status );
- }
- break;
-
-/* If the supplied code does not represent a change of system, clear
- the returned flag. */
- default:
- result = 0;
- }
-
-/* Return the result. */
- return result;
-}
-
-static double TopoVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* TopoVel
-
-* Purpose:
-* Find the velocity of the observer away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double TopoVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the observer away
-* from a specified source position, at a given epoch, in the frame of
-* rest of the Sun.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-*/
-
-/* Local Variables: */
- double deca; /* Apparent DEC */
- double raa; /* Apparent RA */
- double vobs; /* Velocity of observer relative to earth */
- double vearth; /* Velocity of earth realtive to sun */
-
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* If not already done so, get the parameters defining the transformation
- of mean ra and dec to apparent ra and dec, and store in the supplied frame
- definition structure. */
- if( def->amprms[ 0 ] == AST__BAD ) palMappa( 2000.0, def->epoch,
- def->amprms );
-
-/* Convert the source position from mean ra and dec to apparent ra and dec. */
- palMapqkz( ra, dec, def->amprms, &raa, &deca );
-
-/* If not already done so, get the local apparent siderial time (in radians)
- and store in the supplied frame definition structure. */
- if( def->last == AST__BAD ) def->last = palGmst( def->epoch ) +
- palEqeqx( def->epoch ) +
- def->obslon;
-
-/* Get the component away from the source, of the velocity of the observer
- relative to the centre of the earth (in m/s). */
- vobs = 1000.0*Rverot( def->obslat, def->obsalt, raa, deca, def->last,
- status );
-
-/* Get the component away from the source, of the velocity of the earth's
- centre relative to the Sun, in m/s. */
- vearth = GeoVel( ra, dec, def, status );
-
-/* Return the total velocity of the observer away from the source in the
- frame of the sun. */
- return vobs + vearth;
-}
-
-static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
- int forward, AstPointSet *out, int *status ) {
-/*
-* Name:
-* Transform
-
-* Purpose:
-* Apply a SpecMap to transform a set of points.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* AstPointSet *Transform( AstMapping *this, AstPointSet *in,
-* int forward, AstPointSet *out, int *status )
-
-* Class Membership:
-* SpecMap member function (over-rides the astTransform method inherited
-* from the Mapping class).
-
-* Description:
-* This function takes a SpecMap and a set of points encapsulated
-* in a PointSet and transforms the points so as to perform the
-* sequence of spectral coordinate conversions specified by
-* previous invocations of astSpecAdd.
-
-* Parameters:
-* this
-* Pointer to the SpecMap.
-* in
-* Pointer to the PointSet holding the input coordinate data.
-* forward
-* A non-zero value indicates that the forward coordinate transformation
-* should be applied, while a zero value requests the inverse
-* transformation.
-* out
-* Pointer to a PointSet which will hold the transformed (output)
-* coordinate values. A NULL value may also be given, in which case a
-* new PointSet will be created by this function.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* Pointer to the output (possibly new) PointSet.
-
-* Notes:
-* - A null pointer will be returned if this function is invoked with the
-* global error status set, or if it should fail for any reason.
-* - The number of coordinate values per point in the input PointSet must
-* match the number of coordinates for the SpecMap being applied.
-* - If an output PointSet is supplied, it must have space for sufficient
-* number of points and coordinate values per point to accommodate the
-* result. Any excess space will be ignored.
-*/
-
-/* Local Variables: */
- AstPointSet *result; /* Pointer to output PointSet */
- AstSpecMap *map; /* Pointer to SpecMap to be applied */
- double **ptr_in; /* Pointer to input coordinate data */
- double **ptr_out; /* Pointer to output coordinate data */
- double *spec; /* Pointer to output spectral axis value array */
- double *alpha; /* Pointer to output RA axis value array */
- double *beta; /* Pointer to output DEC axis value array */
- int cvt; /* Loop counter for conversions */
- int end; /* Termination index for conversion loop */
- int inc; /* Increment for conversion loop */
- int map3d; /* Is the SpecMap 3-dimensional? */
- int ncoord_in; /* Number of coordinates per input point */
- int npoint; /* Number of points */
- int start; /* Starting index for conversion loop */
-
-/* Check the global error status. */
- if ( !astOK ) return NULL;
-
-/* Obtain a pointer to the SpecMap. */
- map = (AstSpecMap *) this;
-
-/* Apply the parent mapping using the stored pointer to the Transform member
- function inherited from the parent Mapping class. This function validates
- all arguments and generates an output PointSet if necessary, but does not
- actually transform any coordinate values. */
- result = (*parent_transform)( this, in, forward, out, status );
-
-/* We will now extend the parent astTransform method by performing the
- coordinate conversions needed to generate the output coordinate values. */
-
-/* Determine the numbers of points and coordinates per point from the input
- PointSet and obtain pointers for accessing the input and output coordinate
- values. */
- ncoord_in = astGetNcoord( in );
- npoint = astGetNpoint( in );
- ptr_in = astGetPoints( in );
- ptr_out = astGetPoints( result );
-
-/* Determine whether to apply the forward or inverse transformation, according
- to the direction specified and whether the mapping has been inverted. */
- if ( astGetInvert( this ) ) forward = !forward;
-
-/* Transform the coordinate values. */
-/* -------------------------------- */
-/* Use "spec" as a synonym for the array of spectral axis values stored in
- the output PointSet. */
- if ( astOK ) {
- spec = ptr_out[ 0 ];
-
-/* If this is a 3D SpecMap use "alpha" as a synonym for the array of RA axis
- values and "beta" as a synonym for the array of DEC axis values stored
- in the output PointSet. */
- map3d = ( ncoord_in == 3 );
- if( map3d ) {
- alpha = ptr_out[ 1 ];
- beta = ptr_out[ 2 ];
- } else {
- alpha = NULL;
- beta = NULL;
- }
-
-/* Initialise the output coordinate values by copying the input ones. */
- (void) memcpy( spec, ptr_in[ 0 ], sizeof( double ) * (size_t) npoint );
- if( map3d ) {
- (void) memcpy( alpha, ptr_in[ 1 ], sizeof( double ) * (size_t) npoint );
- (void) memcpy( beta, ptr_in[ 2 ], sizeof( double ) * (size_t) npoint );
- }
-
-/* We will loop to apply each spectral coordinate conversion in turn to the
- (spec) array. However, if the inverse transformation was requested,
- we must loop through these transformations in reverse order, so set up
- appropriate limits and an increment to control this loop. */
- start = forward ? 0 : map->ncvt - 1;
- end = forward ? map->ncvt : -1;
- inc = forward ? 1 : -1;
-
-/* Loop through the coordinate conversions in the required order. */
- for ( cvt = start; cvt != end; cvt += inc ) {
-
-/* Process conversions which correspond to changes of reference frames. */
- if( !FrameChange( map->cvttype[ cvt ], npoint, alpha, beta, spec,
- map->cvtargs[ cvt ], forward, status ) ) {
-
-/* If this conversion was not a change of reference frame, it must be a
- change of system. */
- SystemChange( map->cvttype[ cvt ], npoint, spec,
- map->cvtargs[ cvt ], forward, status );
- }
- }
- }
-
-/* If an error has occurred and a new PointSet may have been created, then
- clean up by annulling it. In any case, ensure that a NULL result is
- returned.*/
- if ( !astOK ) {
- if ( !out ) result = astAnnul( result );
- result = NULL;
- }
-
-/* Return a pointer to the output PointSet. */
- return result;
-
-}
-
-static double UserVel( double ra, double dec, FrameDef *def, int *status ) {
-/*
-* Name:
-* UserVel
-
-* Purpose:
-* Find the component of the velocity of the user-defined rest-frame
-* away from the source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* double UserVel( double ra, double dec, FrameDef *def, int *status )
-
-* Class Membership:
-* SpecMap method.
-
-* Description:
-* This function finds the component of the velocity of the user-defined
-* rest-frame away from a specified position. The magnitude and direction
-* of the rest-frames velocity are defined within the supplied "def"
-* structure. The user-defined rest-frame is typically used to represent
-* the velocity of the source within the heliocentric rest-frame.
-
-* Parameters:
-* ra
-* The RA (rads, FK5 J2000) of the source.
-* dec
-* The Dec (rads, FK5 J2000) of the source.
-* def
-* Pointer to a FrameDef structure which holds the parameters which
-* define the frame, together with cached intermediate results.
-* status
-* Pointer to the inherited status variable.
-
-* Returns:
-* The component of the frame's velocity away from the position given by
-* "ra" and "dec", in m/s, measured within the Heliographic frame of
-* rest. Zero is returned if an error has already occurred.
-
-* Notes:
-* - The direction of the user velocity is given by def->refra and
-* def->refdec (an FK5 J2000 position). The maginitude of the velocity
-* is given by def->veluser, in m/s, positive when the source is moving
-* away from the observer towards def->refra, def->refdec, and given
-* with respect to the heliocentric rest-frame.
-
-*/
-
-/* Local Variables: */
- double vb[ 3 ]; /* Source position vector */
-
-/* Check the global error status. */
- if ( !astOK ) return 0.0;
-
-/* If not already done so, express the user velocity in the form of a
- J2000.0 x,y,z vector. */
- if( def->vuser[ 0 ] == AST__BAD ) {
- def->vuser[ 0 ] = def->veluser*cos( def->refra )*cos( def->refdec );
- def->vuser[ 1 ] = def->veluser*sin( def->refra )*cos( def->refdec );
- def->vuser[ 2 ] = def->veluser*sin( def->refdec );
- }
-
-/* Convert given J2000 RA,Dec to x,y,z. */
- palDcs2c( ra, dec, vb );
-
-/* Return the dot product with the user velocity. Invert it to get the
- velocity towards the observer (the def->veluser value is supposed to be
- positive if the source is moving away from the observer). */
- return -palDvdv( def->vuser, vb );
-}
-
-/* Copy constructor. */
-/* ----------------- */
-static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
-/*
-* Name:
-* Copy
-
-* Purpose:
-* Copy constructor for SpecMap objects.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* void Copy( const AstObject *objin, AstObject *objout, int *status )
-
-* Description:
-* This function implements the copy constructor for SpecMap objects.
-
-* Parameters:
-* objin
-* Pointer to the object to be copied.
-* objout
-* Pointer to the object being constructed.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* void
-
-* Notes:
-* - This constructor makes a deep copy.
-*/
-
-/* Local Variables: */
- AstSpecMap *in; /* Pointer to input SpecMap */
- AstSpecMap *out; /* Pointer to output SpecMap */
- int cvt; /* Loop counter for coordinate conversions */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Obtain pointers to the input and output SpecMap structures. */
- in = (AstSpecMap *) objin;
- out = (AstSpecMap *) objout;
-
-/* For safety, first clear any references to the input memory from the output
- SpecMap. */
- out->cvtargs = NULL;
- out->cvttype = NULL;
-
-/* Allocate memory for the output array of argument list pointers. */
- out->cvtargs = astMalloc( sizeof( double * ) * (size_t) in->ncvt );
-
-/* If necessary, allocate memory and make a copy of the input array of
- coordinate conversion codes. */
- if ( in->cvttype ) out->cvttype = astStore( NULL, in->cvttype,
- sizeof( int )
- * (size_t) in->ncvt );
-
-/* If OK, loop through each conversion in the input SpecMap and make a copy of
- its argument list, storing the new pointer in the output argument list
- array. */
- if ( astOK ) {
- for ( cvt = 0; cvt < in->ncvt; cvt++ ) {
- out->cvtargs[ cvt ] = astStore( NULL, in->cvtargs[ cvt ],
- astSizeOf( in->cvtargs[ cvt ] ) );
- }
-
-/* If an error occurred while copying the argument lists, loop through the
- conversions again and clean up by ensuring that the new memory allocated for
- each argument list is freed. */
- if ( !astOK ) {
- for ( cvt = 0; cvt < in->ncvt; cvt++ ) {
- out->cvtargs[ cvt ] = astFree( out->cvtargs[ cvt ] );
- }
- }
- }
-
-/* If an error occurred, free all other memory allocated above. */
- if ( !astOK ) {
- out->cvtargs = astFree( out->cvtargs );
- out->cvttype = astFree( out->cvttype );
- }
-}
-
-/* Destructor. */
-/* ----------- */
-static void Delete( AstObject *obj, int *status ) {
-/*
-* Name:
-* Delete
-
-* Purpose:
-* Destructor for SpecMap objects.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* void Delete( AstObject *obj, int *status )
-
-* Description:
-* This function implements the destructor for SpecMap objects.
-
-* Parameters:
-* obj
-* Pointer to the object to be deleted.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* void
-
-* Notes:
-* This function attempts to execute even if the global error status is
-* set.
-*/
-
-/* Local Variables: */
- AstSpecMap *this; /* Pointer to SpecMap */
- int cvt; /* Loop counter for coordinate conversions */
-
-/* Obtain a pointer to the SpecMap structure. */
- this = (AstSpecMap *) obj;
-
-/* Loop to free the memory containing the argument list for each coordinate
- conversion. */
- for ( cvt = 0; cvt < this->ncvt; cvt++ ) {
- this->cvtargs[ cvt ] = astFree( this->cvtargs[ cvt ] );
- }
-
-/* Free the memory holding the array of conversion types and the array of
- argument list pointers. */
- this->cvtargs = astFree( this->cvtargs );
- this->cvttype = astFree( this->cvttype );
-}
-
-/* Dump function. */
-/* -------------- */
-static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
-/*
-* Name:
-* Dump
-
-* Purpose:
-* Dump function for SpecMap objects.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* void Dump( AstObject *this, AstChannel *channel, int *status )
-
-* Description:
-* This function implements the Dump function which writes out data
-* for the SpecMap class to an output Channel.
-
-* Parameters:
-* this
-* Pointer to the SpecMap whose data are being written.
-* channel
-* Pointer to the Channel to which the data are being written.
-* status
-* Pointer to the inherited status variable.
-*/
-
-/* Local Constants: */
-#define KEY_LEN 50 /* Maximum length of a keyword */
-
-/* Local Variables: */
- AstSpecMap *this; /* Pointer to the SpecMap structure */
- char key[ KEY_LEN + 1 ]; /* Buffer for keyword string */
- const char *argdesc[ MAX_ARGS ]; /* Pointers to argument descriptions */
- const char *comment; /* Pointer to comment string */
- const char *sval; /* Pointer to string value */
- int argdec; /* Index of DEC argument */
- int argra; /* Index of RA argument */
- int iarg; /* Loop counter for arguments */
- int icvt; /* Loop counter for conversion steps */
- int ival; /* Integer value */
- int nargs; /* Number of user-supplied arguments */
- int szargs; /* Number of stored arguments */
- int set; /* Attribute value set? */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Obtain a pointer to the SpecMap structure. */
- this = (AstSpecMap *) this_object;
-
-/* Write out values representing the instance variables for the SpecMap
- class. Accompany these with appropriate comment strings, possibly
- depending on the values being written.*/
-
-/* In the case of attributes, we first use the appropriate (private)
- Test... member function to see if they are set. If so, we then use
- the (private) Get... function to obtain the value to be written
- out.
-
- For attributes which are not set, we use the astGet... method to
- obtain the value instead. This will supply a default value
- (possibly provided by a derived class which over-rides this method)
- which is more useful to a human reader as it corresponds to the
- actual default attribute value. Since "set" will be zero, these
- values are for information only and will not be read back. */
-
-/* Number of conversion steps. */
-/* --------------------------- */
-/* Regard this as "set" if it is non-zero. */
- ival = this->ncvt;
- set = ( ival != 0 );
- astWriteInt( channel, "Nspec", set, 0, ival, "Number of conversion steps" );
-
-/* Write out data for each conversion step... */
- for ( icvt = 0; icvt < this->ncvt; icvt++ ) {
-
-/* Conversion type. */
-/* ---------------- */
-/* Change each conversion type code into an equivalent string and
- obtain associated descriptive information. If the conversion code
- was not recognised, report an error and give up. */
- if ( astOK ) {
- sval = CvtString( this->cvttype[ icvt ], &comment, &argra, &argdec,
- &nargs, &szargs, argdesc, status );
- if ( astOK && !sval ) {
- astError( AST__SPCIN,
- "astWrite(%s): Corrupt %s contains invalid SpecMap "
- "spectral coordinate conversion code (%d).", status,
- astGetClass( channel ), astGetClass( this ),
- (int) this->cvttype[ icvt ] );
- break;
- }
-
-/* Create an appropriate keyword and write out the conversion code
- information. */
- (void) sprintf( key, "Spec%d", icvt + 1 );
- astWriteString( channel, key, 1, 1, sval, comment );
-
-/* Write out data for each conversion argument... */
- for ( iarg = 0; iarg < szargs; iarg++ ) {
-
-/* Arguments. */
-/* ---------- */
-/* Create an appropriate keyword and write out the argument value,
- accompanied by the descriptive comment obtained above. */
- if( this->cvtargs[ icvt ][ iarg ] != AST__BAD ) {
- (void) sprintf( key, "Spec%d%c", icvt + 1, ALPHABET[ iarg ] );
- astWriteDouble( channel, key, 1, 1, this->cvtargs[ icvt ][ iarg ],
- argdesc[ iarg ] );
- }
- }
-
-/* Quit looping if an error occurs. */
- if ( !astOK ) break;
- }
- }
-
-/* Undefine macros local to this function. */
-#undef KEY_LEN
-}
-
-/* Standard class functions. */
-/* ========================= */
-/* Implement the astIsASpecMap and astCheckSpecMap functions using the macros
- defined for this purpose in the "object.h" header file. */
-astMAKE_ISA(SpecMap,Mapping)
-astMAKE_CHECK(SpecMap)
-
-AstSpecMap *astSpecMap_( int nin, int flags, const char *options, int *status, ...) {
-/*
-*++
-* Name:
-c astSpecMap
-f AST_SPECMAP
-
-* Purpose:
-* Create a SpecMap.
-
-* Type:
-* Public function.
-
-* Synopsis:
-c #include "specmap.h"
-c AstSpecMap *astSpecMap( int nin, int flags, const char *options, ... )
-f RESULT = AST_SPECMAP( NIN, FLAGS, OPTIONS, STATUS )
-
-* Class Membership:
-* SpecMap constructor.
-
-* Description:
-* This function creates a new SpecMap and optionally initialises
-* its attributes.
-*
-* An SpecMap is a specialised form of Mapping which can be used to
-* represent a sequence of conversions between standard spectral
-* coordinate systems. This includes conversions between frequency,
-* wavelength, and various forms of velocity, as well as conversions
-* between different standards of rest.
-*
-* When a SpecMap is first created, it simply performs a unit
-c (null) Mapping. Using the astSpecAdd function,
-f (null) Mapping. Using the AST_SPECADD routine,
-* a series of coordinate conversion steps may then be added, selected
-* from the list of supported conversions. This allows multi-step
-* conversions between a variety of spectral coordinate systems to
-* be assembled out of the building blocks provided by this class.
-*
-* For details of the individual coordinate conversions available,
-c see the description of the astSpecAdd function.
-f see the description of the AST_SPECADD routine.
-*
-* Conversions are available to transform between standards of rest.
-* Such conversions need to know the source position as an RA and DEC.
-* This information can be supplied in the form of parameters for
-* the relevant conversions, in which case the SpecMap is 1-dimensional,
-* simply transforming the spectral axis values. This means that the
-* same source position will always be used by the SpecMap. However, this
-* may not be appropriate for an accurate description of a 3-D spectral
-* cube, where changes of spatial position can produce significant
-* changes in the Doppler shift introduced when transforming between
-* standards of rest. For this situation, a 3-dimensional SpecMap can
-* be created in which axes 2 and 3 correspond to the source RA and DEC
-* The SpecMap simply copies values for axes 2 and 3 from input to
-* output).
-
-* Parameters:
-c nin
-f NIN = INTEGER (Given)
-* The number of inputs to the Mapping (this will also equal the
-* number of outputs). This value must be either 1 or 3. In either
-* case, the first input and output correspoindis the spectral axis.
-* For a 3-axis SpecMap, the second and third axes give the RA and
-* DEC (J2000 FK5) of the source. This positional information is
-* used by conversions which transform between standards of rest,
-* and replaces the "RA" and "DEC" arguments for the individual
-* conversions listed in description of the "SpecAdd"
-c function.
-f routine.
-c flags
-f FLAGS = INTEGER (Given)
-c This parameter is reserved for future use and should currently
-f This argument is reserved for future use and should currently
-* always be set to zero.
-c options
-f OPTIONS = CHARACTER * ( * ) (Given)
-c Pointer to a null-terminated string containing an optional
-c comma-separated list of attribute assignments to be used for
-c initialising the new SpecMap. The syntax used is identical to
-c that for the astSet function and may include "printf" format
-c specifiers identified by "%" symbols in the normal way.
-c If no initialisation is required, a zero-length string may be
-c supplied.
-f A character string containing an optional comma-separated
-f list of attribute assignments to be used for initialising the
-f new SpecMap. The syntax used is identical to that for the
-f AST_SET routine. If no initialisation is required, a blank
-f value may be supplied.
-c ...
-c If the "options" string contains "%" format specifiers, then
-c an optional list of additional arguments may follow it in
-c order to supply values to be substituted for these
-c specifiers. The rules for supplying these are identical to
-c those for the astSet function (and for the C "printf"
-c function).
-f STATUS = INTEGER (Given and Returned)
-f The global status.
-
-* Returned Value:
-c astSpecMap()
-f AST_SPECMAP = INTEGER
-* A pointer to the new SpecMap.
-
-* Notes:
-* - The nature and units of the coordinate values supplied for the
-* first input (i.e. the spectral input) of a SpecMap must be appropriate
-* to the first conversion step applied by the SpecMap. For instance, if
-* the first conversion step is "FRTOVL" (frequency to relativistic
-* velocity), then the coordinate values for the first input should
-* be frequency in units of Hz. Similarly, the nature and units of the
-* coordinate values returned by a SpecMap will be determined by the
-* last conversion step applied by the SpecMap. For instance, if the
-* last conversion step is "VLTOVO" (relativistic velocity to optical
-* velocity), then the coordinate values for the first output will be optical
-* velocity in units of metres per second. See the description of the
-c astSpecAdd function for the units expected and returned by each
-f AST_SPECADD routine for the units expected and returned by each
-* conversion.
-* - A null Object pointer (AST__NULL) will be returned if this
-c function is invoked with the AST error status set, or if it
-f function is invoked with STATUS set to an error value, or if it
-* should fail for any reason.
-*--
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstSpecMap *new; /* Pointer to the new SpecMap */
- va_list args; /* Variable argument list */
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* Initialise the SpecMap, allocating memory and initialising the virtual
- function table as well if necessary. */
- new = astInitSpecMap( NULL, sizeof( AstSpecMap ), !class_init, &class_vtab,
- "SpecMap", nin, flags );
-
-/* If successful, note that the virtual function table has been initialised. */
- if ( astOK ) {
- class_init = 1;
-
-/* Obtain the variable argument list and pass it along with the options string
- to the astVSet method to initialise the new SpecMap's attributes. */
- va_start( args, status );
- astVSet( new, options, NULL, args );
- va_end( args );
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return a pointer to the new SpecMap. */
- return new;
-}
-
-AstSpecMap *astSpecMapId_( int nin, int flags, const char *options, ... ) {
-/*
-* Name:
-* astSpecMapId_
-
-* Purpose:
-* Create a SpecMap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "specmap.h"
-* AstSpecMap *astSpecMapId_( int nin, int flags, const char *options, ... )
-
-* Class Membership:
-* SpecMap constructor.
-
-* Description:
-* This function implements the external (public) interface to the
-* astSpecMap constructor function. It returns an ID value (instead
-* of a true C pointer) to external users, and must be provided
-* because astSpecMap_ has a variable argument list which cannot be
-* encapsulated in a macro (where this conversion would otherwise
-* occur).
-*
-* The variable argument list also prevents this function from
-* invoking astSpecMap_ directly, so it must be a re-implementation
-* of it in all respects, except for the final conversion of the
-* result to an ID value.
-
-* Parameters:
-* As for astSpecMap_.
-
-* Returned Value:
-* The ID value associated with the new SpecMap.
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstSpecMap *new; /* Pointer to the new SpecMap */
- va_list args; /* Variable argument list */
-
- int *status; /* Pointer to inherited status value */
-
-/* Get a pointer to the inherited status value. */
- status = astGetStatusPtr;
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* Initialise the SpecMap, allocating memory and initialising the virtual
- function table as well if necessary. */
- new = astInitSpecMap( NULL, sizeof( AstSpecMap ), !class_init, &class_vtab,
- "SpecMap", nin, flags );
-
-/* If successful, note that the virtual function table has been initialised. */
- if ( astOK ) {
- class_init = 1;
-
-/* Obtain the variable argument list and pass it along with the options string
- to the astVSet method to initialise the new SpecMap's attributes. */
- va_start( args, options );
- astVSet( new, options, NULL, args );
- va_end( args );
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return an ID value for the new SpecMap. */
- return astMakeId( new );
-}
-
-AstSpecMap *astInitSpecMap_( void *mem, size_t size, int init,
- AstSpecMapVtab *vtab, const char *name,
- int nin, int flags, int *status ) {
-/*
-*+
-* Name:
-* astInitSpecMap
-
-* Purpose:
-* Initialise a SpecMap.
-
-* Type:
-* Protected function.
-
-* Synopsis:
-* #include "specmap.h"
-* AstSpecMap *astInitSpecMap( void *mem, size_t size, int init,
-* AstSpecMapVtab *vtab, const char *name,
-* int nin, int flags )
-
-* Class Membership:
-* SpecMap initialiser.
-
-* Description:
-* This function is provided for use by class implementations to initialise
-* a new SpecMap object. It allocates memory (if necessary) to accommodate
-* the SpecMap plus any additional data associated with the derived class.
-* It then initialises a SpecMap structure at the start of this memory. If
-* the "init" flag is set, it also initialises the contents of a virtual
-* function table for a SpecMap at the start of the memory passed via the
-* "vtab" parameter.
-
-* Parameters:
-* mem
-* A pointer to the memory in which the SpecMap is to be initialised.
-* This must be of sufficient size to accommodate the SpecMap data
-* (sizeof(SpecMap)) plus any data used by the derived class. If a value
-* of NULL is given, this function will allocate the memory itself using
-* the "size" parameter to determine its size.
-* size
-* The amount of memory used by the SpecMap (plus derived class data).
-* This will be used to allocate memory if a value of NULL is given for
-* the "mem" parameter. This value is also stored in the SpecMap
-* structure, so a valid value must be supplied even if not required for
-* allocating memory.
-* init
-* A logical flag indicating if the SpecMap's virtual function table is
-* to be initialised. If this value is non-zero, the virtual function
-* table will be initialised by this function.
-* vtab
-* Pointer to the start of the virtual function table to be associated
-* with the new SpecMap.
-* name
-* Pointer to a constant null-terminated character string which contains
-* the name of the class to which the new object belongs (it is this
-* pointer value that will subsequently be returned by the astClass
-* method).
-* nin
-* The number of inputs and outputs for the SpecMap (either 1 or 3).
-* flags
-* This parameter is reserved for future use. It is currently ignored.
-
-* Returned Value:
-* A pointer to the new SpecMap.
-
-* Notes:
-* - A null pointer will be returned if this function is invoked with the
-* global error status set, or if it should fail for any reason.
-*-
-*/
-
-/* Local Variables: */
- AstSpecMap *new; /* Pointer to the new SpecMap */
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* Check nin is OK (1 or 3). */
- if( nin != 1 && nin != 3 ) {
- astError( AST__BADNI, "astInitSpecMap(SpecMap): Supplied number of "
- "SpecMap axes (%d) is illegal; it should be 1 or 2. ", status,
- nin );
- }
-
-/* If necessary, initialise the virtual function table. */
- if ( init ) astInitSpecMapVtab( vtab, name );
-
-/* Initialise a 1D Mapping structure (the parent class) as the first component
- within the SpecMap structure, allocating memory if necessary. Specify that
- the Mapping should be defined in both the forward and inverse directions. */
- new = (AstSpecMap *) astInitMapping( mem, size, 0,
- (AstMappingVtab *) vtab, name,
- nin, nin, 1, 1 );
-
- if ( astOK ) {
-
-/* Initialise the SpecMap data. */
-/* --------------------------- */
-/* The initial state is with no conversions set, in which condition the
- SpecMap simply implements a unit mapping. */
- new->ncvt = 0;
- new->cvtargs = NULL;
- new->cvttype = NULL;
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return a pointer to the new object. */
- return new;
-}
-
-AstSpecMap *astLoadSpecMap_( void *mem, size_t size,
- AstSpecMapVtab *vtab, const char *name,
- AstChannel *channel, int *status ) {
-/*
-*+
-* Name:
-* astLoadSpecMap
-
-* Purpose:
-* Load a SpecMap.
-
-* Type:
-* Protected function.
-
-* Synopsis:
-* #include "specmap.h"
-* AstSpecMap *astLoadSpecMap( void *mem, size_t size,
-* AstSpecMapVtab *vtab, const char *name,
-* AstChannel *channel )
-
-* Class Membership:
-* SpecMap loader.
-
-* Description:
-* This function is provided to load a new SpecMap using data read
-* from a Channel. It first loads the data used by the parent class
-* (which allocates memory if necessary) and then initialises a
-* SpecMap structure in this memory, using data read from the input
-* Channel.
-*
-* If the "init" flag is set, it also initialises the contents of a
-* virtual function table for a SpecMap at the start of the memory
-* passed via the "vtab" parameter.
-
-
-* Parameters:
-* mem
-* A pointer to the memory into which the SpecMap is to be
-* loaded. This must be of sufficient size to accommodate the
-* SpecMap data (sizeof(SpecMap)) plus any data used by derived
-* classes. If a value of NULL is given, this function will
-* allocate the memory itself using the "size" parameter to
-* determine its size.
-* size
-* The amount of memory used by the SpecMap (plus derived class
-* data). This will be used to allocate memory if a value of
-* NULL is given for the "mem" parameter. This value is also
-* stored in the SpecMap structure, so a valid value must be
-* supplied even if not required for allocating memory.
-*
-* If the "vtab" parameter is NULL, the "size" value is ignored
-* and sizeof(AstSpecMap) is used instead.
-* vtab
-* Pointer to the start of the virtual function table to be
-* associated with the new SpecMap. If this is NULL, a pointer to
-* the (static) virtual function table for the SpecMap class is
-* used instead.
-* name
-* Pointer to a constant null-terminated character string which
-* contains the name of the class to which the new object
-* belongs (it is this pointer value that will subsequently be
-* returned by the astGetClass method).
-*
-* If the "vtab" parameter is NULL, the "name" value is ignored
-* and a pointer to the string "SpecMap" is used instead.
-
-* Returned Value:
-* A pointer to the new SpecMap.
-
-* Notes:
-* - A null pointer will be returned if this function is invoked
-* with the global error status set, or if it should fail for any
-* reason.
-*-
-*/
-
-/* Local Constants: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
-#define KEY_LEN 50 /* Maximum length of a keyword */
-
-/* Local Variables: */
- AstSpecMap *new; /* Pointer to the new SpecMap */
- char *sval; /* Pointer to string value */
- char key[ KEY_LEN + 1 ]; /* Buffer for keyword string */
- const char *argdesc[ MAX_ARGS ]; /* Pointers to argument descriptions */
- const char *comment; /* Pointer to comment string */
- int argdec; /* Index of DEC argument */
- int argra; /* Index of RA argument */
- int iarg; /* Loop counter for arguments */
- int icvt; /* Loop counter for conversion steps */
- int nargs; /* Number of user-supplied arguments */
- int szargs; /* Number of stored arguments */
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(channel);
-
-/* Initialise. */
- new = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return new;
-
-/* If a NULL virtual function table has been supplied, then this is
- the first loader to be invoked for this SpecMap. In this case the
- SpecMap belongs to this class, so supply appropriate values to be
- passed to the parent class loader (and its parent, etc.). */
- if ( !vtab ) {
- size = sizeof( AstSpecMap );
- vtab = &class_vtab;
- name = "SpecMap";
-
-/* If required, initialise the virtual function table for this class. */
- if ( !class_init ) {
- astInitSpecMapVtab( vtab, name );
- class_init = 1;
- }
- }
-
-/* Invoke the parent class loader to load data for all the ancestral
- classes of the current one, returning a pointer to the resulting
- partly-built SpecMap. */
- new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
- channel );
-
- if ( astOK ) {
-
-/* Read input data. */
-/* ================ */
-/* Request the input Channel to read all the input data appropriate to
- this class into the internal "values list". */
- astReadClassData( channel, "SpecMap" );
-
-/* Now read each individual data item from this list and use it to
- initialise the appropriate instance variable(s) for this class. */
-
-/* In the case of attributes, we first read the "raw" input value,
- supplying the "unset" value as the default. If a "set" value is
- obtained, we then use the appropriate (private) Set... member
- function to validate and set the value properly. */
-
-/* Number of conversion steps. */
-/* --------------------------- */
-/* Read the number of conversion steps and allocate memory to hold
- data for each step. */
- new->ncvt = astReadInt( channel, "nspec", 0 );
- if ( new->ncvt < 0 ) new->ncvt = 0;
- new->cvttype = astMalloc( sizeof( int ) * (size_t) new->ncvt );
- new->cvtargs = astMalloc( sizeof( double * ) * (size_t) new->ncvt );
-
-/* If an error occurred, ensure that all allocated memory is freed. */
- if ( !astOK ) {
- new->cvttype = astFree( new->cvttype );
- new->cvtargs = astFree( new->cvtargs );
-
-/* Otherwise, initialise the argument pointer array. */
- } else {
- for ( icvt = 0; icvt < new->ncvt; icvt++ ) {
- new->cvtargs[ icvt ] = NULL;
- }
-
-/* Read in data for each conversion step... */
- for ( icvt = 0; icvt < new->ncvt; icvt++ ) {
-
-/* Conversion type. */
-/* ---------------- */
-/* Create an appropriate keyword and read the string representation of
- the conversion type. */
- (void) sprintf( key, "spec%d", icvt + 1 );
- sval = astReadString( channel, key, NULL );
-
-/* If no value was read, report an error. */
- if ( astOK ) {
- if ( !sval ) {
- astError( AST__BADIN,
- "astRead(%s): A spectral coordinate conversion "
- "type is missing from the input SpecMap data.", status,
- astGetClass( channel ) );
-
-/* Otherwise, convert the string representation into the required
- conversion type code. */
- } else {
- new->cvttype[ icvt ] = CvtCode( sval, status );
-
-/* If the string was not recognised, report an error. */
- if ( new->cvttype[ icvt ] == AST__SPEC_NULL ) {
- astError( AST__BADIN,
- "astRead(%s): Invalid spectral conversion "
- "type \"%s\" in SpecMap data.", status,
- astGetClass( channel ), sval );
- }
- }
-
-/* Free the memory holding the string value. */
- sval = astFree( sval );
- }
-
-/* Obtain the number of arguments associated with the conversion and
- allocate memory to hold them. */
- (void) CvtString( new->cvttype[ icvt ], &comment, &argra,
- &argdec, &nargs, &szargs, argdesc, status );
- new->cvtargs[ icvt ] = astMalloc( sizeof( double ) *
- (size_t) szargs );
-
-/* Read in data for each argument... */
- if ( astOK ) {
- for ( iarg = 0; iarg < szargs; iarg++ ) {
-
-/* Arguments. */
-/* ---------- */
-/* Create an appropriate keyword and read each argument value. */
- (void) sprintf( key, "spec%d%c", icvt + 1, ALPHABET[ iarg ] );
- new->cvtargs[ icvt ][ iarg ] = astReadDouble( channel, key,
- AST__BAD );
- }
- }
-
-/* Quit looping if an error occurs. */
- if ( !astOK ) break;
- }
- }
-
-/* If an error occurred, clean up by deleting the new SpecMap. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return the new SpecMap pointer. */
- return new;
-
-/* Undefine macros local to this function. */
-#undef KEY_LEN
-}
-
-/* Virtual function interfaces. */
-/* ============================ */
-/* These provide the external interface to the virtual functions defined by
- this class. Each simply checks the global error status and then locates and
- executes the appropriate member function, using the function pointer stored
- in the object's virtual function table (this pointer is located using the
- astMEMBER macro defined in "object.h").
-
- Note that the member function may not be the one defined here, as it may
- have been over-ridden by a derived class. However, it should still have the
- same interface. */
-void astSpecAdd_( AstSpecMap *this, const char *cvt, int narg,
- const double args[], int *status ) {
- if ( !astOK ) return;
- (**astMEMBER(this,SpecMap,SpecAdd))( this, cvt, narg, args, status );
-}
-
-
-
-