wcslib (8.2.2)

(root)/
include/
wcslib-8.2.2/
spc.h
       1  /*============================================================================
       2    WCSLIB 8.2 - an implementation of the FITS WCS standard.
       3    Copyright (C) 1995-2023, Mark Calabretta
       4  
       5    This file is part of WCSLIB.
       6  
       7    WCSLIB is free software: you can redistribute it and/or modify it under the
       8    terms of the GNU Lesser General Public License as published by the Free
       9    Software Foundation, either version 3 of the License, or (at your option)
      10    any later version.
      11  
      12    WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
      13    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      14    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
      15    more details.
      16  
      17    You should have received a copy of the GNU Lesser General Public License
      18    along with WCSLIB.  If not, see http://www.gnu.org/licenses.
      19  
      20    Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
      21    http://www.atnf.csiro.au/people/Mark.Calabretta
      22    $Id: spc.h,v 8.2.1.1 2023/11/16 10:05:57 mcalabre Exp mcalabre $
      23  *=============================================================================
      24  *
      25  * WCSLIB 8.2 - C routines that implement the FITS World Coordinate System
      26  * (WCS) standard.  Refer to the README file provided with WCSLIB for an
      27  * overview of the library.
      28  *
      29  *
      30  * Summary of the spc routines
      31  * ---------------------------
      32  * Routines in this suite implement the part of the FITS World Coordinate
      33  * System (WCS) standard that deals with spectral coordinates, as described in
      34  *
      35  =   "Representations of world coordinates in FITS",
      36  =   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (WCS Paper I)
      37  =
      38  =   "Representations of spectral coordinates in FITS",
      39  =   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
      40  =   2006, A&A, 446, 747 (WCS Paper III)
      41  *
      42  * These routines define methods to be used for computing spectral world
      43  * coordinates from intermediate world coordinates (a linear transformation
      44  * of image pixel coordinates), and vice versa.  They are based on the spcprm
      45  * struct which contains all information needed for the computations.  The
      46  * struct contains some members that must be set by the user, and others that
      47  * are maintained by these routines, somewhat like a C++ class but with no
      48  * encapsulation.
      49  *
      50  * Routine spcini() is provided to initialize the spcprm struct with default
      51  * values, spcfree() reclaims any memory that may have been allocated to store
      52  * an error message, spcsize() computes its total size including allocated
      53  * memory, and spcprt() prints its contents.
      54  *
      55  * spcperr() prints the error message(s) (if any) stored in a spcprm struct.
      56  *
      57  * A setup routine, spcset(), computes intermediate values in the spcprm struct
      58  * from parameters in it that were supplied by the user.  The struct always
      59  * needs to be set up by spcset() but it need not be called explicitly - refer
      60  * to the explanation of spcprm::flag.
      61  *
      62  * spcx2s() and spcs2x() implement the WCS spectral coordinate transformations.
      63  * In fact, they are high level driver routines for the lower level spectral
      64  * coordinate transformation routines described in spx.h.
      65  *
      66  * A number of routines are provided to aid in analysing or synthesising sets
      67  * of FITS spectral axis keywords:
      68  *
      69  *   - spctype() checks a spectral CTYPEia keyword for validity and returns
      70  *     information derived from it.
      71  *
      72  *   - Spectral keyword analysis routine spcspxe() computes the values of the
      73  *     X-type spectral variables for the S-type variables supplied.
      74  *
      75  *   - Spectral keyword synthesis routine, spcxpse(), computes the S-type
      76  *     variables for the X-types supplied.
      77  *
      78  *   - Given a set of spectral keywords, a translation routine, spctrne(),
      79  *     produces the corresponding set for the specified spectral CTYPEia.
      80  *
      81  *   - spcaips() translates AIPS-convention spectral CTYPEia and VELREF
      82  *     keyvalues.
      83  *
      84  * Spectral variable types - S, P, and X:
      85  * --------------------------------------
      86  * A few words of explanation are necessary regarding spectral variable types
      87  * in FITS.
      88  *
      89  * Every FITS spectral axis has three associated spectral variables:
      90  *
      91  *   S-type: the spectral variable in which coordinates are to be
      92  *     expressed.  Each S-type is encoded as four characters and is
      93  *     linearly related to one of four basic types as follows:
      94  *
      95  *     F (Frequency):
      96  *       - 'FREQ':  frequency
      97  *       - 'AFRQ':  angular frequency
      98  *       - 'ENER':  photon energy
      99  *       - 'WAVN':  wave number
     100  *       - 'VRAD':  radio velocity
     101  *
     102  *     W (Wavelength in vacuo):
     103  *       - 'WAVE':  wavelength
     104  *       - 'VOPT':  optical velocity
     105  *       - 'ZOPT':  redshift
     106  *
     107  *     A (wavelength in Air):
     108  *       - 'AWAV':  wavelength in air
     109  *
     110  *     V (Velocity):
     111  *       - 'VELO':  relativistic velocity
     112  *       - 'BETA':  relativistic beta factor
     113  *
     114  *     The S-type forms the first four characters of the CTYPEia keyvalue,
     115  *     and CRVALia and CDELTia are expressed as S-type quantities so that
     116  *     they provide a first-order approximation to the S-type variable at
     117  *     the reference point.
     118  *
     119  *     Note that 'AFRQ', angular frequency, is additional to the variables
     120  *     defined in WCS Paper III.
     121  *
     122  *   P-type: the basic spectral variable (F, W, A, or V) with which the
     123  *     S-type variable is associated (see list above).
     124  *
     125  *     For non-grism axes, the P-type is encoded as the eighth character of
     126  *     CTYPEia.
     127  *
     128  *   X-type: the basic spectral variable (F, W, A, or V) for which the
     129  *     spectral axis is linear, grisms excluded (see below).
     130  *
     131  *     For non-grism axes, the X-type is encoded as the sixth character of
     132  *     CTYPEia.
     133  *
     134  *   Grisms: Grism axes have normal S-, and P-types but the axis is linear,
     135  *     not in any spectral variable, but in a special "grism parameter".
     136  *     The X-type spectral variable is either W or A for grisms in vacuo or
     137  *     air respectively, but is encoded as 'w' or 'a' to indicate that an
     138  *     additional transformation is required to convert to or from the
     139  *     grism parameter.  The spectral algorithm code for grisms also has a
     140  *     special encoding in CTYPEia, either 'GRI' (in vacuo) or 'GRA' (in air).
     141  *
     142  * In the algorithm chain, the non-linear transformation occurs between the
     143  * X-type and the P-type variables; the transformation between P-type and
     144  * S-type variables is always linear.
     145  *
     146  * When the P-type and X-type variables are the same, the spectral axis is
     147  * linear in the S-type variable and the second four characters of CTYPEia
     148  * are blank.  This can never happen for grism axes.
     149  *
     150  * As an example, correlating radio spectrometers always produce spectra that
     151  * are regularly gridded in frequency; a redshift scale on such a spectrum is
     152  * non-linear.  The required value of CTYPEia would be 'ZOPT-F2W', where the
     153  * desired S-type is 'ZOPT' (redshift), the P-type is necessarily 'W'
     154  * (wavelength), and the X-type is 'F' (frequency) by the nature of the
     155  * instrument.
     156  *
     157  * Air-to-vacuum wavelength conversion:
     158  * ------------------------------------
     159  * Please refer to the prologue of spx.h for important comments relating to the
     160  * air-to-vacuum wavelength conversion.
     161  *
     162  * Argument checking:
     163  * ------------------
     164  * The input spectral values are only checked for values that would result in
     165  * floating point exceptions.  In particular, negative frequencies and
     166  * wavelengths are allowed, as are velocities greater than the speed of
     167  * light.  The same is true for the spectral parameters - rest frequency and
     168  * wavelength.
     169  *
     170  * Accuracy:
     171  * ---------
     172  * No warranty is given for the accuracy of these routines (refer to the
     173  * copyright notice); intending users must satisfy for themselves their
     174  * adequacy for the intended purpose.  However, closure effectively to within
     175  * double precision rounding error was demonstrated by test routine tspc.c
     176  * which accompanies this software.
     177  *
     178  *
     179  * spcini() - Default constructor for the spcprm struct
     180  * ----------------------------------------------------
     181  * spcini() sets all members of a spcprm struct to default values.  It should
     182  * be used to initialize every spcprm struct.
     183  *
     184  * PLEASE NOTE: If the spcprm struct has already been initialized, then before
     185  * reinitializing, it spcfree() should be used to free any memory that may have
     186  * been allocated to store an error message.  A memory leak may otherwise
     187  * result.
     188  *
     189  * Given and returned:
     190  *   spc       struct spcprm*
     191  *                       Spectral transformation parameters.
     192  *
     193  * Function return value:
     194  *             int       Status return value:
     195  *                         0: Success.
     196  *                         1: Null spcprm pointer passed.
     197  *
     198  *
     199  * spcfree() - Destructor for the spcprm struct
     200  * --------------------------------------------
     201  * spcfree() frees any memory that may have been allocated to store an error
     202  * message in the spcprm struct.
     203  *
     204  * Given:
     205  *   spc       struct spcprm*
     206  *                       Spectral transformation parameters.
     207  *
     208  * Function return value:
     209  *             int       Status return value:
     210  *                         0: Success.
     211  *                         1: Null spcprm pointer passed.
     212  *
     213  *
     214  * spcsize() - Compute the size of a spcprm struct
     215  * -----------------------------------------------
     216  * spcsize() computes the full size of a spcprm struct, including allocated
     217  * memory.
     218  *
     219  * Given:
     220  *   spc       const struct spcprm*
     221  *                       Spectral transformation parameters.
     222  *
     223  *                       If NULL, the base size of the struct and the allocated
     224  *                       size are both set to zero.
     225  *
     226  * Returned:
     227  *   sizes     int[2]    The first element is the base size of the struct as
     228  *                       returned by sizeof(struct spcprm).  The second element
     229  *                       is the total allocated size, in bytes.  This figure
     230  *                       includes memory allocated for the constituent struct,
     231  *                       spcprm::err.
     232  *
     233  *                       It is not an error for the struct not to have been set
     234  *                       up via spcset().
     235  *
     236  * Function return value:
     237  *             int       Status return value:
     238  *                         0: Success.
     239  *
     240  *
     241  * spcprt() - Print routine for the spcprm struct
     242  * ----------------------------------------------
     243  * spcprt() prints the contents of a spcprm struct using wcsprintf().  Mainly
     244  * intended for diagnostic purposes.
     245  *
     246  * Given:
     247  *   spc       const struct spcprm*
     248  *                       Spectral transformation parameters.
     249  *
     250  * Function return value:
     251  *             int       Status return value:
     252  *                         0: Success.
     253  *                         1: Null spcprm pointer passed.
     254  *
     255  *
     256  * spcperr() - Print error messages from a spcprm struct
     257  * -----------------------------------------------------
     258  * spcperr() prints the error message(s) (if any) stored in a spcprm struct.
     259  * If there are no errors then nothing is printed.  It uses wcserr_prt(), q.v.
     260  *
     261  * Given:
     262  *   spc       const struct spcprm*
     263  *                       Spectral transformation parameters.
     264  *
     265  *   prefix    const char *
     266  *                       If non-NULL, each output line will be prefixed with
     267  *                       this string.
     268  *
     269  * Function return value:
     270  *             int       Status return value:
     271  *                         0: Success.
     272  *                         1: Null spcprm pointer passed.
     273  *
     274  *
     275  * spcset() - Setup routine for the spcprm struct
     276  * ----------------------------------------------
     277  * spcset() sets up a spcprm struct according to information supplied within
     278  * it.
     279  *
     280  * Note that this routine need not be called directly; it will be invoked by
     281  * spcx2s() and spcs2x() if spcprm::flag is anything other than a predefined
     282  * magic value.
     283  *
     284  * Given and returned:
     285  *   spc       struct spcprm*
     286  *                       Spectral transformation parameters.
     287  *
     288  * Function return value:
     289  *             int       Status return value:
     290  *                         0: Success.
     291  *                         1: Null spcprm pointer passed.
     292  *                         2: Invalid spectral parameters.
     293  *
     294  *                       For returns > 1, a detailed error message is set in
     295  *                       spcprm::err if enabled, see wcserr_enable().
     296  *
     297  *
     298  * spcx2s() - Transform to spectral coordinates
     299  * --------------------------------------------
     300  * spcx2s() transforms intermediate world coordinates to spectral coordinates.
     301  *
     302  * Given and returned:
     303  *   spc       struct spcprm*
     304  *                       Spectral transformation parameters.
     305  *
     306  * Given:
     307  *   nx        int       Vector length.
     308  *
     309  *   sx        int       Vector stride.
     310  *
     311  *   sspec     int       Vector stride.
     312  *
     313  *   x         const double[]
     314  *                       Intermediate world coordinates, in SI units.
     315  *
     316  * Returned:
     317  *   spec      double[]  Spectral coordinates, in SI units.
     318  *
     319  *   stat      int[]     Status return value status for each vector element:
     320  *                         0: Success.
     321  *                         1: Invalid value of x.
     322  *
     323  * Function return value:
     324  *             int       Status return value:
     325  *                         0: Success.
     326  *                         1: Null spcprm pointer passed.
     327  *                         2: Invalid spectral parameters.
     328  *                         3: One or more of the x coordinates were invalid,
     329  *                            as indicated by the stat vector.
     330  *
     331  *                       For returns > 1, a detailed error message is set in
     332  *                       spcprm::err if enabled, see wcserr_enable().
     333  *
     334  *
     335  * spcs2x() - Transform spectral coordinates
     336  * -----------------------------------------
     337  * spcs2x() transforms spectral world coordinates to intermediate world
     338  * coordinates.
     339  *
     340  * Given and returned:
     341  *   spc       struct spcprm*
     342  *                       Spectral transformation parameters.
     343  *
     344  * Given:
     345  *   nspec     int       Vector length.
     346  *
     347  *   sspec     int       Vector stride.
     348  *
     349  *   sx        int       Vector stride.
     350  *
     351  *   spec      const double[]
     352  *                       Spectral coordinates, in SI units.
     353  *
     354  * Returned:
     355  *   x         double[]  Intermediate world coordinates, in SI units.
     356  *
     357  *   stat      int[]     Status return value status for each vector element:
     358  *                         0: Success.
     359  *                         1: Invalid value of spec.
     360  *
     361  * Function return value:
     362  *             int       Status return value:
     363  *                         0: Success.
     364  *                         1: Null spcprm pointer passed.
     365  *                         2: Invalid spectral parameters.
     366  *                         4: One or more of the spec coordinates were
     367  *                            invalid, as indicated by the stat vector.
     368  *
     369  *                       For returns > 1, a detailed error message is set in
     370  *                       spcprm::err if enabled, see wcserr_enable().
     371  *
     372  *
     373  * spctype() - Spectral CTYPEia keyword analysis
     374  * ---------------------------------------------
     375  * spctype() checks whether a CTYPEia keyvalue is a valid spectral axis type
     376  * and if so returns information derived from it relating to the associated S-,
     377  * P-, and X-type spectral variables (see explanation above).
     378  *
     379  * The return arguments are guaranteed not be modified if CTYPEia is not a
     380  * valid spectral type; zero-pointers may be specified for any that are not of
     381  * interest.
     382  *
     383  * A deprecated form of this function, spctyp(), lacks the wcserr** parameter.
     384  *
     385  * Given:
     386  *   ctype     const char[9]
     387  *                       The CTYPEia keyvalue, (eight characters with null
     388  *                       termination).
     389  *
     390  * Returned:
     391  *   stype     char[]    The four-letter name of the S-type spectral variable
     392  *                       copied or translated from ctype.  If a non-zero
     393  *                       pointer is given, the array must accomodate a null-
     394  *                       terminated string of length 5.
     395  *
     396  *   scode     char[]    The three-letter spectral algorithm code copied or
     397  *                       translated from ctype.  Logarithmic ('LOG') and
     398  *                       tabular ('TAB') codes are also recognized.  If a
     399  *                       non-zero pointer is given, the array must accomodate a
     400  *                       null-terminated string of length 4.
     401  *
     402  *   sname     char[]    Descriptive name of the S-type spectral variable.
     403  *                       If a non-zero pointer is given, the array must
     404  *                       accomodate a null-terminated string of length 22.
     405  *
     406  *   units     char[]    SI units of the S-type spectral variable.  If a
     407  *                       non-zero pointer is given, the array must accomodate a
     408  *                       null-terminated string of length 8.
     409  *
     410  *   ptype     char*     Character code for the P-type spectral variable
     411  *                       derived from ctype, one of 'F', 'W', 'A', or 'V'.
     412  *
     413  *   xtype     char*     Character code for the X-type spectral variable
     414  *                       derived from ctype, one of 'F', 'W', 'A', or 'V'.
     415  *                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
     416  *                       grisms in vacuo and air respectively.  Set to 'L' or
     417  *                       'T' for logarithmic ('LOG') and tabular ('TAB') axes.
     418  *
     419  *   restreq   int*      Multivalued flag that indicates whether rest
     420  *                       frequency or wavelength is required to compute
     421  *                       spectral variables for this CTYPEia:
     422  *                         0: Not required.
     423  *                         1: Required for the conversion between S- and
     424  *                            P-types (e.g. 'ZOPT-F2W').
     425  *                         2: Required for the conversion between P- and
     426  *                            X-types (e.g. 'BETA-W2V').
     427  *                         3: Required for the conversion between S- and
     428  *                            P-types, and between P- and X-types, but not
     429  *                            between S- and X-types (this applies only for
     430  *                            'VRAD-V2F', 'VOPT-V2W', and 'ZOPT-V2W').
     431  *                        Thus the rest frequency or wavelength is required for
     432  *                        spectral coordinate computations (i.e. between S- and
     433  *                        X-types) only if restreq%3 != 0.
     434  *
     435  *   err       struct wcserr **
     436  *                       If enabled, for function return values > 1, this
     437  *                       struct will contain a detailed error message, see
     438  *                       wcserr_enable().  May be NULL if an error message is
     439  *                       not desired.  Otherwise, the user is responsible for
     440  *                       deleting the memory allocated for the wcserr struct.
     441  *
     442  * Function return value:
     443  *             int       Status return value:
     444  *                         0: Success.
     445  *                         2: Invalid spectral parameters (not a spectral
     446  *                            CTYPEia).
     447  *
     448  *
     449  * spcspxe() - Spectral keyword analysis
     450  * ------------------------------------
     451  * spcspxe() analyses the CTYPEia and CRVALia FITS spectral axis keyword values
     452  * and returns information about the associated X-type spectral variable.
     453  *
     454  * A deprecated form of this function, spcspx(), lacks the wcserr** parameter.
     455  *
     456  * Given:
     457  *   ctypeS    const char[9]
     458  *                       Spectral axis type, i.e. the CTYPEia keyvalue, (eight
     459  *                       characters with null termination).  For non-grism
     460  *                       axes, the character code for the P-type spectral
     461  *                       variable in the algorithm code (i.e. the eighth
     462  *                       character of CTYPEia) may be set to '?' (it will not
     463  *                       be reset).
     464  *
     465  *   crvalS    double    Value of the S-type spectral variable at the reference
     466  *                       point, i.e. the CRVALia keyvalue, SI units.
     467  *
     468  *   restfrq,
     469  *   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
     470  *                       only one of which need be given, the other should be
     471  *                       set to zero.
     472  *
     473  * Returned:
     474  *   ptype     char*     Character code for the P-type spectral variable
     475  *                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
     476  *
     477  *   xtype     char*     Character code for the X-type spectral variable
     478  *                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
     479  *                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
     480  *                       grisms in vacuo and air respectively; crvalX and dXdS
     481  *                       (see below) will conform to these.
     482  *
     483  *   restreq   int*      Multivalued flag that indicates whether rest frequency
     484  *                       or wavelength is required to compute spectral
     485  *                       variables for this CTYPEia, as for spctype().
     486  *
     487  *   crvalX    double*   Value of the X-type spectral variable at the reference
     488  *                       point, SI units.
     489  *
     490  *   dXdS      double*   The derivative, dX/dS, evaluated at the reference
     491  *                       point, SI units.  Multiply the CDELTia keyvalue by
     492  *                       this to get the pixel spacing in the X-type spectral
     493  *                       coordinate.
     494  *
     495  *   err       struct wcserr **
     496  *                       If enabled, for function return values > 1, this
     497  *                       struct will contain a detailed error message, see
     498  *                       wcserr_enable().  May be NULL if an error message is
     499  *                       not desired.  Otherwise, the user is responsible for
     500  *                       deleting the memory allocated for the wcserr struct.
     501  *
     502  * Function return value:
     503  *             int       Status return value:
     504  *                         0: Success.
     505  *                         2: Invalid spectral parameters.
     506  *
     507  *
     508  * spcxpse() - Spectral keyword synthesis
     509  * -------------------------------------
     510  * spcxpse(), for the spectral axis type specified and the value provided for
     511  * the X-type spectral variable at the reference point, deduces the value of
     512  * the FITS spectral axis keyword CRVALia and also the derivative dS/dX which
     513  * may be used to compute CDELTia.  See above for an explanation of the S-,
     514  * P-, and X-type spectral variables.
     515  *
     516  * A deprecated form of this function, spcxps(), lacks the wcserr** parameter.
     517  *
     518  * Given:
     519  *   ctypeS    const char[9]
     520  *                       The required spectral axis type, i.e. the CTYPEia
     521  *                       keyvalue, (eight characters with null termination).
     522  *                       For non-grism axes, the character code for the P-type
     523  *                       spectral variable in the algorithm code (i.e. the
     524  *                       eighth character of CTYPEia) may be set to '?' (it
     525  *                       will not be reset).
     526  *
     527  *   crvalX    double    Value of the X-type spectral variable at the reference
     528  *                       point (N.B. NOT the CRVALia keyvalue), SI units.
     529  *
     530  *   restfrq,
     531  *   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
     532  *                       only one of which need be given, the other should be
     533  *                       set to zero.
     534  *
     535  * Returned:
     536  *   ptype     char*     Character code for the P-type spectral variable
     537  *                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
     538  *
     539  *   xtype     char*     Character code for the X-type spectral variable
     540  *                       derived from ctypeS, one of 'F', 'W', 'A', or 'V'.
     541  *                       Also, 'w' and 'a' are synonymous to 'W' and 'A' for
     542  *                       grisms; crvalX and cdeltX must conform to these.
     543  *
     544  *   restreq   int*      Multivalued flag that indicates whether rest frequency
     545  *                       or wavelength is required to compute spectral
     546  *                       variables for this CTYPEia, as for spctype().
     547  *
     548  *   crvalS    double*   Value of the S-type spectral variable at the reference
     549  *                       point (i.e. the appropriate CRVALia keyvalue), SI
     550  *                       units.
     551  *
     552  *   dSdX      double*   The derivative, dS/dX, evaluated at the reference
     553  *                       point, SI units.  Multiply this by the pixel spacing
     554  *                       in the X-type spectral coordinate to get the CDELTia
     555  *                       keyvalue.
     556  *
     557  *   err       struct wcserr **
     558  *                       If enabled, for function return values > 1, this
     559  *                       struct will contain a detailed error message, see
     560  *                       wcserr_enable().  May be NULL if an error message is
     561  *                       not desired.  Otherwise, the user is responsible for
     562  *                       deleting the memory allocated for the wcserr struct.
     563  *
     564  * Function return value:
     565  *             int       Status return value:
     566  *                         0: Success.
     567  *                         2: Invalid spectral parameters.
     568  *
     569  *
     570  * spctrne() - Spectral keyword translation
     571  * ---------------------------------------
     572  * spctrne() translates a set of FITS spectral axis keywords into the
     573  * corresponding set for the specified spectral axis type.  For example, a
     574  * 'FREQ' axis may be translated into 'ZOPT-F2W' and vice versa.
     575  *
     576  * A deprecated form of this function, spctrn(), lacks the wcserr** parameter.
     577  *
     578  * Given:
     579  *   ctypeS1   const char[9]
     580  *                       Spectral axis type, i.e. the CTYPEia keyvalue, (eight
     581  *                       characters with null termination).  For non-grism
     582  *                       axes, the character code for the P-type spectral
     583  *                       variable in the algorithm code (i.e. the eighth
     584  *                       character of CTYPEia) may be set to '?' (it will not
     585  *                       be reset).
     586  *
     587  *   crvalS1   double    Value of the S-type spectral variable at the reference
     588  *                       point, i.e. the CRVALia keyvalue, SI units.
     589  *
     590  *   cdeltS1   double    Increment of the S-type spectral variable at the
     591  *                       reference point, SI units.
     592  *
     593  *   restfrq,
     594  *   restwav   double    Rest frequency [Hz] and rest wavelength in vacuo [m],
     595  *                       only one of which need be given, the other should be
     596  *                       set to zero.  Neither are required if the translation
     597  *                       is between wave-characteristic types, or between
     598  *                       velocity-characteristic types.  E.g., required for
     599  *                       'FREQ'     -> 'ZOPT-F2W', but not required for
     600  *                       'VELO-F2V' -> 'ZOPT-F2W'.
     601  *
     602  * Given and returned:
     603  *   ctypeS2   char[9]   Required spectral axis type (eight characters with
     604  *                       null termination).  The first four characters are
     605  *                       required to be given and are never modified.  The
     606  *                       remaining four, the algorithm code, are completely
     607  *                       determined by, and must be consistent with, ctypeS1
     608  *                       and the first four characters of ctypeS2.  A non-zero
     609  *                       status value will be returned if they are inconsistent
     610  *                       (see below).  However, if the final three characters
     611  *                       are specified as "???", or if just the eighth
     612  *                       character is specified as '?', the correct algorithm
     613  *                       code will be substituted (applies for grism axes as
     614  *                       well as non-grism).
     615  *
     616  * Returned:
     617  *   crvalS2   double*   Value of the new S-type spectral variable at the
     618  *                       reference point, i.e. the new CRVALia keyvalue, SI
     619  *                       units.
     620  *
     621  *   cdeltS2   double*   Increment of the new S-type spectral variable at the
     622  *                       reference point, i.e. the new CDELTia keyvalue, SI
     623  *                       units.
     624  *
     625  *   err       struct wcserr **
     626  *                       If enabled, for function return values > 1, this
     627  *                       struct will contain a detailed error message, see
     628  *                       wcserr_enable().  May be NULL if an error message is
     629  *                       not desired.  Otherwise, the user is responsible for
     630  *                       deleting the memory allocated for the wcserr struct.
     631  *
     632  * Function return value:
     633  *             int       Status return value:
     634  *                         0: Success.
     635  *                         2: Invalid spectral parameters.
     636  *
     637  *                       A status value of 2 will be returned if restfrq or
     638  *                       restwav are not specified when required, or if ctypeS1
     639  *                       or ctypeS2 are self-inconsistent, or have different
     640  *                       spectral X-type variables.
     641  *
     642  *
     643  * spcaips() - Translate AIPS-convention spectral keywords
     644  * -------------------------------------------------------
     645  * spcaips() translates AIPS-convention spectral CTYPEia and VELREF keyvalues.
     646  *
     647  * Given:
     648  *   ctypeA    const char[9]
     649  *                       CTYPEia keyvalue possibly containing an
     650  *                       AIPS-convention spectral code (eight characters, need
     651  *                       not be null-terminated).
     652  *
     653  *   velref    int       AIPS-convention VELREF code.  It has the following
     654  *                       integer values:
     655  *                         1: LSR kinematic, originally described simply as
     656  *                            "LSR" without distinction between the kinematic
     657  *                            and dynamic definitions.
     658  *                         2: Barycentric, originally described as "HEL"
     659  *                            meaning heliocentric.
     660  *                         3: Topocentric, originally described as "OBS"
     661  *                            meaning geocentric but widely interpreted as
     662  *                            topocentric.
     663  *                       AIPS++ extensions to VELREF are also recognized:
     664  *                         4: LSR dynamic.
     665  *                         5: Geocentric.
     666  *                         6: Source rest frame.
     667  *                         7: Galactocentric.
     668  *
     669  *                       For an AIPS 'VELO' axis, a radio convention velocity
     670  *                       (VRAD) is denoted by adding 256 to VELREF, otherwise
     671  *                       an optical velocity (VOPT) is indicated (this is not
     672  *                       applicable to 'FREQ' or 'FELO' axes).  Setting velref
     673  *                       to 0 or 256 chooses between optical and radio velocity
     674  *                       without specifying a Doppler frame, provided that a
     675  *                       frame is encoded in ctypeA.  If not, i.e. for
     676  *                       ctypeA = 'VELO', ctype will be returned as 'VELO'.
     677  *
     678  *                       VELREF takes precedence over CTYPEia in defining the
     679  *                       Doppler frame, e.g.
     680  *
     681  =                         ctypeA = 'VELO-HEL'
     682  =                         velref = 1
     683  *
     684  *                       returns ctype = 'VOPT' with specsys set to 'LSRK'.
     685  *
     686  *                       If omitted from the header, the default value of
     687  *                       VELREF is 0.
     688  *
     689  * Returned:
     690  *   ctype     char[9]   Translated CTYPEia keyvalue, or a copy of ctypeA if no
     691  *                       translation was performed (in which case any trailing
     692  *                       blanks in ctypeA will be replaced with nulls).
     693  *
     694  *   specsys   char[9]   Doppler reference frame indicated by VELREF or else
     695  *                       by CTYPEia with value corresponding to the SPECSYS
     696  *                       keyvalue in the FITS WCS standard.  May be returned
     697  *                       blank if neither specifies a Doppler frame, e.g.
     698  *                       ctypeA = 'FELO' and velref%256 == 0.
     699  *
     700  * Function return value:
     701  *             int       Status return value:
     702  *                        -1: No translation required (not an error).
     703  *                         0: Success.
     704  *                         2: Invalid value of VELREF.
     705  *
     706  *
     707  * spcprm struct - Spectral transformation parameters
     708  * --------------------------------------------------
     709  * The spcprm struct contains information required to transform spectral
     710  * coordinates.  It consists of certain members that must be set by the user
     711  * ("given") and others that are set by the WCSLIB routines ("returned").  Some
     712  * of the latter are supplied for informational purposes while others are for
     713  * internal use only.
     714  *
     715  *   int flag
     716  *     (Given and returned) This flag must be set to zero whenever any of the
     717  *     following spcprm structure members are set or changed:
     718  *
     719  *       - spcprm::type,
     720  *       - spcprm::code,
     721  *       - spcprm::crval,
     722  *       - spcprm::restfrq,
     723  *       - spcprm::restwav,
     724  *       - spcprm::pv[].
     725  *
     726  *     This signals the initialization routine, spcset(), to recompute the
     727  *     returned members of the spcprm struct.  spcset() will reset flag to
     728  *     indicate that this has been done.
     729  *
     730  *   char type[8]
     731  *     (Given) Four-letter spectral variable type, e.g "ZOPT" for
     732  *     CTYPEia = 'ZOPT-F2W'.  (Declared as char[8] for alignment reasons.)
     733  *
     734  *   char code[4]
     735  *     (Given) Three-letter spectral algorithm code, e.g "F2W" for
     736  *     CTYPEia = 'ZOPT-F2W'.
     737  *
     738  *   double crval
     739  *     (Given) Reference value (CRVALia), SI units.
     740  *
     741  *   double restfrq
     742  *     (Given) The rest frequency [Hz], and ...
     743  *
     744  *   double restwav
     745  *     (Given) ... the rest wavelength in vacuo [m], only one of which need be
     746  *     given, the other should be set to zero.  Neither are required if the
     747  *     X and S spectral variables are both wave-characteristic, or both
     748  *     velocity-characteristic, types.
     749  *
     750  *   double pv[7]
     751  *     (Given) Grism parameters for 'GRI' and 'GRA' algorithm codes:
     752  *       - 0: G, grating ruling density.
     753  *       - 1: m, interference order.
     754  *       - 2: alpha, angle of incidence [deg].
     755  *       - 3: n_r, refractive index at the reference wavelength, lambda_r.
     756  *       - 4: n'_r, dn/dlambda at the reference wavelength, lambda_r (/m).
     757  *       - 5: epsilon, grating tilt angle [deg].
     758  *       - 6: theta, detector tilt angle [deg].
     759  *
     760  * The remaining members of the spcprm struct are maintained by spcset() and
     761  * must not be modified elsewhere:
     762  *
     763  *   double w[6]
     764  *     (Returned) Intermediate values:
     765  *       - 0: Rest frequency or wavelength (SI).
     766  *       - 1: The value of the X-type spectral variable at the reference point
     767  *           (SI units).
     768  *       - 2: dX/dS at the reference point (SI units).
     769  *      The remainder are grism intermediates.
     770  *
     771  *   int isGrism
     772  *     (Returned) Grism coordinates?
     773  *       - 0: no,
     774  *       - 1: in vacuum,
     775  *       - 2: in air.
     776  *
     777  *   int padding1
     778  *     (An unused variable inserted for alignment purposes only.)
     779  *
     780  *   struct wcserr *err
     781  *     (Returned) If enabled, when an error status is returned, this struct
     782  *     contains detailed information about the error, see wcserr_enable().
     783  *
     784  *   void *padding2
     785  *     (An unused variable inserted for alignment purposes only.)
     786  *   int (*spxX2P)(SPX_ARGS)
     787  *     (Returned) The first and ...
     788  *   int (*spxP2S)(SPX_ARGS)
     789  *     (Returned) ... the second of the pointers to the transformation
     790  *     functions in the two-step algorithm chain X -> P -> S in the
     791  *     pixel-to-spectral direction where the non-linear transformation is from
     792  *     X to P.  The argument list, SPX_ARGS, is defined in spx.h.
     793  *
     794  *   int (*spxS2P)(SPX_ARGS)
     795  *     (Returned) The first and ...
     796  *   int (*spxP2X)(SPX_ARGS)
     797  *     (Returned) ... the second of the pointers to the transformation
     798  *     functions in the two-step algorithm chain S -> P -> X in the
     799  *     spectral-to-pixel direction where the non-linear transformation is from
     800  *     P to X.  The argument list, SPX_ARGS, is defined in spx.h.
     801  *
     802  *
     803  * Global variable: const char *spc_errmsg[] - Status return messages
     804  * ------------------------------------------------------------------
     805  * Error messages to match the status value returned from each function.
     806  *
     807  *===========================================================================*/
     808  
     809  #ifndef WCSLIB_SPC
     810  #define WCSLIB_SPC
     811  
     812  #include "spx.h"
     813  
     814  #ifdef __cplusplus
     815  extern "C" {
     816  #endif
     817  
     818  
     819  extern const char *spc_errmsg[];
     820  
     821  enum spc_errmsg_enum {
     822    SPCERR_NO_CHANGE       = -1,	// No change.
     823    SPCERR_SUCCESS         =  0,	// Success.
     824    SPCERR_NULL_POINTER    =  1,	// Null spcprm pointer passed.
     825    SPCERR_BAD_SPEC_PARAMS =  2,	// Invalid spectral parameters.
     826    SPCERR_BAD_X           =  3,	// One or more of x coordinates were
     827  				// invalid.
     828    SPCERR_BAD_SPEC        =  4 	// One or more of the spec coordinates were
     829  				// invalid.
     830  };
     831  
     832  struct spcprm {
     833    // Initialization flag (see the prologue above).
     834    //--------------------------------------------------------------------------
     835    int    flag;			// Set to zero to force initialization.
     836  
     837    // Parameters to be provided (see the prologue above).
     838    //--------------------------------------------------------------------------
     839    char   type[8];		// Four-letter spectral variable type.
     840    char   code[4];		// Three-letter spectral algorithm code.
     841  
     842    double crval;			// Reference value (CRVALia), SI units.
     843    double restfrq;		// Rest frequency, Hz.
     844    double restwav;		// Rest wavelength, m.
     845  
     846    double pv[7];			// Grism parameters:
     847  				//   0: G, grating ruling density.
     848  				//   1: m, interference order.
     849  				//   2: alpha, angle of incidence.
     850  				//   3: n_r, refractive index at lambda_r.
     851  				//   4: n'_r, dn/dlambda at lambda_r.
     852  				//   5: epsilon, grating tilt angle.
     853  				//   6: theta, detector tilt angle.
     854  
     855    // Information derived from the parameters supplied.
     856    //--------------------------------------------------------------------------
     857    double w[6];			// Intermediate values.
     858  				//   0: Rest frequency or wavelength (SI).
     859  				//   1: CRVALX (SI units).
     860  				//   2: CDELTX/CDELTia = dX/dS (SI units).
     861  				// The remainder are grism intermediates.
     862  
     863    int    isGrism;		// Grism coordinates?  1: vacuum, 2: air.
     864    int    padding1;		// (Dummy inserted for alignment purposes.)
     865  
     866    // Error handling
     867    //--------------------------------------------------------------------------
     868    struct wcserr *err;
     869  
     870    // Private
     871    //--------------------------------------------------------------------------
     872    void   *padding2;		// (Dummy inserted for alignment purposes.)
     873    int (*spxX2P)(SPX_ARGS);	// Pointers to the transformation functions
     874    int (*spxP2S)(SPX_ARGS);	// in the two-step algorithm chain in the
     875  				// pixel-to-spectral direction.
     876  
     877    int (*spxS2P)(SPX_ARGS);	// Pointers to the transformation functions
     878    int (*spxP2X)(SPX_ARGS);	// in the two-step algorithm chain in the
     879  				// spectral-to-pixel direction.
     880  };
     881  
     882  // Size of the spcprm struct in int units, used by the Fortran wrappers.
     883  #define SPCLEN (sizeof(struct spcprm)/sizeof(int))
     884  
     885  
     886  int spcini(struct spcprm *spc);
     887  
     888  int spcfree(struct spcprm *spc);
     889  
     890  int spcsize(const struct spcprm *spc, int sizes[2]);
     891  
     892  int spcprt(const struct spcprm *spc);
     893  
     894  int spcperr(const struct spcprm *spc, const char *prefix);
     895  
     896  int spcset(struct spcprm *spc);
     897  
     898  int spcx2s(struct spcprm *spc, int nx, int sx, int sspec,
     899             const double x[], double spec[], int stat[]);
     900  
     901  int spcs2x(struct spcprm *spc, int nspec, int sspec, int sx,
     902             const double spec[], double x[], int stat[]);
     903  
     904  int spctype(const char ctype[9], char stype[], char scode[], char sname[],
     905              char units[], char *ptype, char *xtype, int *restreq,
     906              struct wcserr **err);
     907  
     908  int spcspxe(const char ctypeS[9], double crvalS, double restfrq,
     909              double restwav, char *ptype, char *xtype, int *restreq,
     910              double *crvalX, double *dXdS, struct wcserr **err);
     911  
     912  int spcxpse(const char ctypeS[9], double crvalX, double restfrq,
     913              double restwav, char *ptype, char *xtype, int *restreq,
     914              double *crvalS, double *dSdX, struct wcserr **err);
     915  
     916  int spctrne(const char ctypeS1[9], double crvalS1, double cdeltS1,
     917              double restfrq, double restwav, char ctypeS2[9], double *crvalS2,
     918              double *cdeltS2, struct wcserr **err);
     919  
     920  int spcaips(const char ctypeA[9], int velref, char ctype[9], char specsys[9]);
     921  
     922  
     923  // Deprecated.
     924  #define spcini_errmsg spc_errmsg
     925  #define spcprt_errmsg spc_errmsg
     926  #define spcset_errmsg spc_errmsg
     927  #define spcx2s_errmsg spc_errmsg
     928  #define spcs2x_errmsg spc_errmsg
     929  
     930  int spctyp(const char ctype[9], char stype[], char scode[], char sname[],
     931             char units[], char *ptype, char *xtype, int *restreq);
     932  int spcspx(const char ctypeS[9], double crvalS, double restfrq,
     933             double restwav, char *ptype, char *xtype, int *restreq,
     934             double *crvalX, double *dXdS);
     935  int spcxps(const char ctypeS[9], double crvalX, double restfrq,
     936             double restwav, char *ptype, char *xtype, int *restreq,
     937             double *crvalS, double *dSdX);
     938  int spctrn(const char ctypeS1[9], double crvalS1, double cdeltS1,
     939             double restfrq, double restwav, char ctypeS2[9], double *crvalS2,
     940             double *cdeltS2);
     941  
     942  #ifdef __cplusplus
     943  }
     944  #endif
     945  
     946  #endif // WCSLIB_SPC