wcslib (8.2.2)

(root)/
include/
wcslib-8.2.2/
wcsfix.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: wcsfix.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 wcsfix routines
      31  * ------------------------------
      32  * Routines in this suite identify and translate various forms of construct
      33  * known to occur in FITS headers that violate the FITS World Coordinate System
      34  * (WCS) standard described in
      35  *
      36  =   "Representations of world coordinates in FITS",
      37  =   Greisen, E.W., & Calabretta, M.R. 2002, A&A, 395, 1061 (WCS Paper I)
      38  =
      39  =   "Representations of celestial coordinates in FITS",
      40  =   Calabretta, M.R., & Greisen, E.W. 2002, A&A, 395, 1077 (WCS Paper II)
      41  =
      42  =   "Representations of spectral coordinates in FITS",
      43  =   Greisen, E.W., Calabretta, M.R., Valdes, F.G., & Allen, S.L.
      44  =   2006, A&A, 446, 747 (WCS Paper III)
      45  =
      46  =   "Representations of time coordinates in FITS -
      47  =    Time and relative dimension in space",
      48  =   Rots, A.H., Bunclark, P.S., Calabretta, M.R., Allen, S.L.,
      49  =   Manchester, R.N., & Thompson, W.T. 2015, A&A, 574, A36 (WCS Paper VII)
      50  *
      51  * Repairs effected by these routines range from the translation of
      52  * non-standard values for standard WCS keywords, to the repair of malformed
      53  * coordinate representations.  Some routines are also provided to check the
      54  * consistency of pairs of keyvalues that define the same measure in two
      55  * different ways, for example, as a date and an MJD.
      56  *
      57  * A separate routine, wcspcx(), "regularizes" the linear transformation matrix
      58  * component (PCi_j) of the coordinate transformation to make it more human-
      59  * readable.  Where a coordinate description was constructed from CDi_j, it
      60  * decomposes it into PCi_j + CDELTi in a meaningful way.  Optionally, it can
      61  * also diagonalize the PCi_j matrix (as far as possible), i.e. undo a
      62  * transposition of axes in the intermediate pixel coordinate system.
      63  *
      64  * Non-standard keyvalues:
      65  * -----------------------
      66  *   AIPS-convention celestial projection types, NCP and GLS, and spectral
      67  *   types, 'FREQ-LSR', 'FELO-HEL', etc., set in CTYPEia are translated
      68  *   on-the-fly by wcsset() but without modifying the relevant ctype[], pv[] or
      69  *   specsys members of the wcsprm struct.  That is, only the information
      70  *   extracted from ctype[] is translated when wcsset() fills in wcsprm::cel
      71  *   (celprm struct) or wcsprm::spc (spcprm struct).
      72  *
      73  *   On the other hand, these routines do change the values of wcsprm::ctype[],
      74  *   wcsprm::pv[], wcsprm::specsys and other wcsprm struct members as
      75  *   appropriate to produce the same result as if the FITS header itself had
      76  *   been translated.
      77  *
      78  *   Auxiliary WCS header information not used directly by WCSLIB may also be
      79  *   translated.  For example, the older DATE-OBS date format (wcsprm::dateobs)
      80  *   is recast to year-2000 standard form, and MJD-OBS (wcsprm::mjdobs) will be
      81  *   deduced from it if not already set.
      82  *
      83  *   Certain combinations of keyvalues that result in malformed coordinate
      84  *   systems, as described in Sect. 7.3.4 of Paper I, may also be repaired.
      85  *   These are handled by cylfix().
      86  *
      87  * Non-standard keywords:
      88  * ----------------------
      89  *   The AIPS-convention CROTAn keywords are recognized as quasi-standard
      90  *   and as such are accomodated by wcsprm::crota[] and translated to
      91  *   wcsprm::pc[][] by wcsset().  These are not dealt with here, nor are any
      92  *   other non-standard keywords since these routines work only on the contents
      93  *   of a wcsprm struct and do not deal with FITS headers per se.  In
      94  *   particular, they do not identify or translate CD00i00j, PC00i00j, PROJPn,
      95  *   EPOCH, VELREF or VSOURCEa keywords; this may be done by the FITS WCS
      96  *   header parser supplied with WCSLIB, refer to wcshdr.h.
      97  *
      98  * wcsfix() and wcsfixi() apply all of the corrections handled by the following
      99  * specific functions, which may also be invoked separately:
     100  *
     101  *   - cdfix(): Sets the diagonal element of the CDi_ja matrix to 1.0 if all
     102  *     CDi_ja keywords associated with a particular axis are omitted.
     103  *
     104  *   - datfix(): recast an older DATE-OBS date format in dateobs to year-2000
     105  *     standard form.  Derive dateref from mjdref if not already set.
     106  *     Alternatively, if dateref is set and mjdref isn't, then derive mjdref
     107  *     from it.  If both are set, then check consistency.  Likewise for dateobs
     108  *     and mjdobs; datebeg and mjdbeg; dateavg and mjdavg; and dateend and
     109  *     mjdend.
     110  *
     111  *   - obsfix(): if only one half of obsgeo[] is set, then derive the other
     112  *     half from it.  If both halves are set, then check consistency.
     113  *
     114  *   - unitfix(): translate some commonly used but non-standard unit strings in
     115  *     the CUNITia keyvalues, e.g. 'DEG' -> 'deg'.
     116  *
     117  *   - spcfix(): translate AIPS-convention spectral types, 'FREQ-LSR',
     118  *     'FELO-HEL', etc., in ctype[] as set from CTYPEia.
     119  *
     120  *   - celfix(): translate AIPS-convention celestial projection types, NCP and
     121  *     GLS, in ctype[] as set from CTYPEia.
     122  *
     123  *   - cylfix(): fixes WCS keyvalues for malformed cylindrical projections that
     124  *     suffer from the problem described in Sect. 7.3.4 of Paper I.
     125  *
     126  *
     127  * wcsfix() - Translate a non-standard WCS struct
     128  * ----------------------------------------------
     129  * wcsfix() is identical to wcsfixi(), but lacks the info argument.
     130  *
     131  *
     132  * wcsfixi() - Translate a non-standard WCS struct
     133  * -----------------------------------------------
     134  * wcsfixi() applies all of the corrections handled separately by cdfix(),
     135  * datfix(), obsfix(), unitfix(), spcfix(), celfix(), and cylfix().
     136  *
     137  * Given:
     138  *   ctrl      int       Do potentially unsafe translations of non-standard
     139  *                       unit strings as described in the usage notes to
     140  *                       wcsutrn().
     141  *
     142  *   naxis     const int []
     143  *                       Image axis lengths.  If this array pointer is set to
     144  *                       zero then cylfix() will not be invoked.
     145  *
     146  * Given and returned:
     147  *   wcs       struct wcsprm*
     148  *                       Coordinate transformation parameters.
     149  *
     150  * Returned:
     151  *   stat      int [NWCSFIX]
     152  *                       Status returns from each of the functions.  Use the
     153  *                       preprocessor macros NWCSFIX to dimension this vector
     154  *                       and CDFIX, DATFIX, OBSFIX, UNITFIX, SPCFIX, CELFIX,
     155  *                       and CYLFIX to access its elements.  A status value
     156  *                       of -2 is set for functions that were not invoked.
     157  *
     158  *   info      struct wcserr [NWCSFIX]
     159  *                       Status messages from each of the functions.  Use the
     160  *                       preprocessor macros NWCSFIX to dimension this vector
     161  *                       and CDFIX, DATFIX, OBSFIX, UNITFIX, SPCFIX, CELFIX,
     162  *                       and CYLFIX to access its elements.
     163  *
     164  *                       Note that the memory allocated by wcsfixi() for the
     165  *                       message in each wcserr struct (wcserr::msg, if
     166  *                       non-zero) must be freed by the user.  See
     167  *                       wcsdealloc().
     168  *
     169  * Function return value:
     170  *             int       Status return value:
     171  *                         0: Success.
     172  *                         1: One or more of the translation functions
     173  *                            returned an error.
     174  *
     175  *
     176  * cdfix() - Fix erroneously omitted CDi_ja keywords
     177  * -------------------------------------------------
     178  * cdfix() sets the diagonal element of the CDi_ja matrix to unity if all
     179  * CDi_ja keywords associated with a given axis were omitted.  According to WCS
     180  * Paper I, if any CDi_ja keywords at all are given in a FITS header then those
     181  * not given default to zero.  This results in a singular matrix with an
     182  * intersecting row and column of zeros.
     183  *
     184  * cdfix() is expected to be invoked before wcsset(), which will fail if these
     185  * errors have not been corrected.
     186  *
     187  * Given and returned:
     188  *   wcs       struct wcsprm*
     189  *                       Coordinate transformation parameters.
     190  *
     191  * Function return value:
     192  *             int       Status return value:
     193  *                        -1: No change required (not an error).
     194  *                         0: Success.
     195  *                         1: Null wcsprm pointer passed.
     196  *
     197  *
     198  * datfix() - Translate DATE-OBS and derive MJD-OBS or vice versa
     199  * --------------------------------------------------------------
     200  * datfix() translates the old DATE-OBS date format set in wcsprm::dateobs to
     201  * year-2000 standard form (yyyy-mm-ddThh:mm:ss).  It derives wcsprm::dateref
     202  * from wcsprm::mjdref if not already set.  Alternatively, if dateref is set
     203  * and mjdref isn't, then it derives mjdref from it.  If both are set but
     204  * disagree by more than 0.001 day (86.4 seconds) then an error status is
     205  * returned.  Likewise for wcsprm::dateobs and wcsprm::mjdobs; wcsprm::datebeg
     206  * and wcsprm::mjdbeg; wcsprm::dateavg and wcsprm::mjdavg; and wcsprm::dateend
     207  * and wcsprm::mjdend.
     208  *
     209  * If neither dateobs nor mjdobs are set, but wcsprm::jepoch (primarily) or
     210  * wcsprm::bepoch is, then both are derived from it.  If jepoch and/or bepoch
     211  * are set but disagree with dateobs or mjdobs by more than 0.000002 year
     212  * (63.2 seconds), an informative message is produced.
     213  *
     214  * The translations done by datfix() do not affect and are not affected by
     215  * wcsset().
     216  *
     217  * Given and returned:
     218  *   wcs       struct wcsprm*
     219  *                       Coordinate transformation parameters.
     220  *                       wcsprm::dateref and/or wcsprm::mjdref may be changed.
     221  *                       wcsprm::dateobs and/or wcsprm::mjdobs may be changed.
     222  *                       wcsprm::datebeg and/or wcsprm::mjdbeg may be changed.
     223  *                       wcsprm::dateavg and/or wcsprm::mjdavg may be changed.
     224  *                       wcsprm::dateend and/or wcsprm::mjdend may be changed.
     225  *
     226  * Function return value:
     227  *             int       Status return value:
     228  *                        -1: No change required (not an error).
     229  *                         0: Success.
     230  *                         1: Null wcsprm pointer passed.
     231  *                         5: Invalid parameter value.
     232  *
     233  *                       For returns >= 0, a detailed message, whether
     234  *                       informative or an error message, may be set in
     235  *                       wcsprm::err if enabled, see wcserr_enable(), with
     236  *                       wcsprm::err.status set to FIXERR_DATE_FIX.
     237  *
     238  * Notes:
     239  *   1: The MJD algorithms used by datfix() are from D.A. Hatcher, 1984, QJRAS,
     240  *      25, 53-55, as modified by P.T. Wallace for use in SLALIB subroutines
     241  *      CLDJ and DJCL.
     242  *
     243  *
     244  * obsfix() - complete the OBSGEO-[XYZLBH] vector of observatory coordinates
     245  * -------------------------------------------------------------------------
     246  * obsfix() completes the wcsprm::obsgeo vector of observatory coordinates.
     247  * That is, if only the (x,y,z) Cartesian coordinate triplet or the (l,b,h)
     248  * geodetic coordinate triplet are set, then it derives the other triplet from
     249  * it.  If both triplets are set, then it checks for consistency at the level
     250  * of 1 metre.
     251  *
     252  * The operations done by obsfix() do not affect and are not affected by
     253  * wcsset().
     254  *
     255  * Given:
     256  *   ctrl      int       Flag that controls behaviour if one triplet is
     257  *                       defined and the other is only partially defined:
     258  *                         0: Reset only the undefined elements of an
     259  *                            incomplete coordinate triplet.
     260  *                         1: Reset all elements of an incomplete triplet.
     261  *                         2: Don't make any changes, check for consistency
     262  *                            only.  Returns an error if either of the two
     263  *                            triplets is incomplete.
     264  *
     265  * Given and returned:
     266  *   wcs       struct wcsprm*
     267  *                       Coordinate transformation parameters.
     268  *                       wcsprm::obsgeo may be changed.
     269  *
     270  * Function return value:
     271  *             int       Status return value:
     272  *                        -1: No change required (not an error).
     273  *                         0: Success.
     274  *                         1: Null wcsprm pointer passed.
     275  *                         5: Invalid parameter value.
     276  *
     277  *                       For returns >= 0, a detailed message, whether
     278  *                       informative or an error message, may be set in
     279  *                       wcsprm::err if enabled, see wcserr_enable(), with
     280  *                       wcsprm::err.status set to FIXERR_OBS_FIX.
     281  *
     282  * Notes:
     283  *   1: While the International Terrestrial Reference System (ITRS) is based
     284  *      solely on Cartesian coordinates, it recommends the use of the GRS80
     285  *      ellipsoid in converting to geodetic coordinates.  However, while WCS
     286  *      Paper III recommends ITRS Cartesian coordinates, Paper VII prescribes
     287  *      the use of the IAU(1976) ellipsoid for geodetic coordinates, and
     288  *      consequently that is what is used here.
     289  *
     290  *   2: For reference, parameters of commonly used global reference ellipsoids:
     291  *
     292  =          a (m)          1/f                    Standard
     293  =        ---------  -------------  --------------------------------
     294  =        6378140    298.2577        IAU(1976)
     295  =        6378137    298.257222101   GRS80
     296  =        6378137    298.257223563   WGS84
     297  =        6378136    298.257         IERS(1989)
     298  =        6378136.6  298.25642       IERS(2003,2010), IAU(2009/2012)
     299  *
     300  *      where f = (a - b) / a is the flattening, and a and b are the semi-major
     301  *      and semi-minor radii in metres.
     302  *
     303  *   3: The transformation from geodetic (lng,lat,hgt) to Cartesian (x,y,z) is
     304  *
     305  =        x = (n + hgt)*coslng*coslat,
     306  =        y = (n + hgt)*sinlng*coslat,
     307  =        z = (n*(1.0 - e^2) + hgt)*sinlat,
     308  *
     309  *      where the "prime vertical radius", n, is a function of latitude
     310  *
     311  =        n = a / sqrt(1 - (e*sinlat)^2),
     312  *
     313  *      and a, the equatorial radius, and e^2 = (2 - f)*f, the (first)
     314  *      eccentricity of the ellipsoid, are constants.  obsfix() inverts these
     315  *      iteratively by writing
     316  *
     317  =           x = rho*coslng*coslat,
     318  =           y = rho*sinlng*coslat,
     319  =        zeta = rho*sinlat,
     320  *
     321  *      where
     322  *
     323  =         rho = n + hgt,
     324  =             = sqrt(x^2 + y^2 + zeta^2),
     325  =        zeta = z / (1 - n*e^2/rho),
     326  *
     327  *      and iterating over the value of zeta.  Since e is small, a good first
     328  *      approximation is given by zeta = z.
     329  *
     330  *
     331  * unitfix() - Correct aberrant CUNITia keyvalues
     332  * ----------------------------------------------
     333  * unitfix() applies wcsutrn() to translate non-standard CUNITia keyvalues,
     334  * e.g. 'DEG' -> 'deg', also stripping off unnecessary whitespace.
     335  *
     336  * unitfix() is expected to be invoked before wcsset(), which will fail if
     337  * non-standard CUNITia keyvalues have not been translated.
     338  *
     339  * Given:
     340  *   ctrl      int       Do potentially unsafe translations described in the
     341  *                       usage notes to wcsutrn().
     342  *
     343  * Given and returned:
     344  *   wcs       struct wcsprm*
     345  *                       Coordinate transformation parameters.
     346  *
     347  * Function return value:
     348  *             int       Status return value:
     349  *                        -1: No change required (not an error).
     350  *                         0: Success (an alias was applied).
     351  *                         1: Null wcsprm pointer passed.
     352  *
     353  *                       When units are translated (i.e. 0 is returned), an
     354  *                       informative message is set in wcsprm::err if enabled,
     355  *                       see wcserr_enable(), with wcsprm::err.status set to
     356  *                       FIXERR_UNITS_ALIAS.
     357  *
     358  *
     359  * spcfix() - Translate AIPS-convention spectral types
     360  * ---------------------------------------------------
     361  * spcfix() translates AIPS-convention spectral coordinate types,
     362  * '{FREQ,FELO,VELO}-{LSR,HEL,OBS}' (e.g. 'FREQ-OBS', 'FELO-HEL', 'VELO-LSR')
     363  * set in wcsprm::ctype[], subject to VELREF set in wcsprm::velref.
     364  *
     365  * Note that if wcs::specsys is already set then it will not be overridden.
     366  *
     367  * AIPS-convention spectral types set in CTYPEia are translated on-the-fly by
     368  * wcsset() but without modifying wcsprm::ctype[] or wcsprm::specsys.  That is,
     369  * only the information extracted from wcsprm::ctype[] is translated when
     370  * wcsset() fills in wcsprm::spc (spcprm struct).  spcfix() modifies
     371  * wcsprm::ctype[] so that if the header is subsequently written out, e.g. by
     372  * wcshdo(), then it will contain translated CTYPEia keyvalues.
     373  *
     374  * The operations done by spcfix() do not affect and are not affected by
     375  * wcsset().
     376  *
     377  * Given and returned:
     378  *   wcs       struct wcsprm*
     379  *                       Coordinate transformation parameters.  wcsprm::ctype[]
     380  *                       and/or wcsprm::specsys may be changed.
     381  *
     382  * Function return value:
     383  *             int       Status return value:
     384  *                        -1: No change required (not an error).
     385  *                         0: Success.
     386  *                         1: Null wcsprm pointer passed.
     387  *                         2: Memory allocation failed.
     388  *                         3: Linear transformation matrix is singular.
     389  *                         4: Inconsistent or unrecognized coordinate axis
     390  *                            types.
     391  *                         5: Invalid parameter value.
     392  *                         6: Invalid coordinate transformation parameters.
     393  *                         7: Ill-conditioned coordinate transformation
     394  *                            parameters.
     395  *
     396  *                       For returns >= 0, a detailed message, whether
     397  *                       informative or an error message, may be set in
     398  *                       wcsprm::err if enabled, see wcserr_enable(), with
     399  *                       wcsprm::err.status set to FIXERR_SPC_UPDTE.
     400  *
     401  *
     402  * celfix() - Translate AIPS-convention celestial projection types
     403  * ---------------------------------------------------------------
     404  * celfix() translates AIPS-convention celestial projection types, NCP and
     405  * GLS, set in the ctype[] member of the wcsprm struct.
     406  *
     407  * Two additional pv[] keyvalues are created when translating NCP, and three
     408  * are created when translating GLS with non-zero reference point.  If the pv[]
     409  * array was initially allocated by wcsini() then the array will be expanded if
     410  * necessary.  Otherwise, error 2 will be returned if sufficient empty slots
     411  * are not already available for use.
     412  *
     413  * AIPS-convention celestial projection types set in CTYPEia are translated
     414  * on-the-fly by wcsset() but without modifying wcsprm::ctype[], wcsprm::pv[],
     415  * or wcsprm::npv.  That is, only the information extracted from
     416  * wcsprm::ctype[] is translated when wcsset() fills in wcsprm::cel (celprm
     417  * struct).  celfix() modifies wcsprm::ctype[], wcsprm::pv[], and wcsprm::npv
     418  * so that if the header is subsequently written out, e.g. by wcshdo(), then it
     419  * will contain translated CTYPEia keyvalues and the relevant PVi_ma.
     420  *
     421  * The operations done by celfix() do not affect and are not affected by
     422  * wcsset().  However, it uses information in the wcsprm struct provided by
     423  * wcsset(), and will invoke it if necessary.
     424  *
     425  * Given and returned:
     426  *   wcs       struct wcsprm*
     427  *                       Coordinate transformation parameters.  wcsprm::ctype[]
     428  *                       and/or wcsprm::pv[] may be changed.
     429  *
     430  * Function return value:
     431  *             int       Status return value:
     432  *                        -1: No change required (not an error).
     433  *                         0: Success.
     434  *                         1: Null wcsprm pointer passed.
     435  *                         2: Memory allocation failed.
     436  *                         3: Linear transformation matrix is singular.
     437  *                         4: Inconsistent or unrecognized coordinate axis
     438  *                            types.
     439  *                         5: Invalid parameter value.
     440  *                         6: Invalid coordinate transformation parameters.
     441  *                         7: Ill-conditioned coordinate transformation
     442  *                            parameters.
     443  *
     444  *                       For returns > 1, a detailed error message is set in
     445  *                       wcsprm::err if enabled, see wcserr_enable().
     446  *
     447  *
     448  * cylfix() - Fix malformed cylindrical projections
     449  * ------------------------------------------------
     450  * cylfix() fixes WCS keyvalues for malformed cylindrical projections that
     451  * suffer from the problem described in Sect. 7.3.4 of Paper I.
     452  *
     453  * cylfix() requires the wcsprm struct to have been set up by wcsset(), and
     454  * will invoke it if necessary.  After modification, the struct is reset on
     455  * return with an explicit call to wcsset().
     456  *
     457  * Given:
     458  *   naxis     const int []
     459  *                       Image axis lengths.
     460  *
     461  * Given and returned:
     462  *   wcs       struct wcsprm*
     463  *                       Coordinate transformation parameters.
     464  *
     465  * Function return value:
     466  *             int       Status return value:
     467  *                        -1: No change required (not an error).
     468  *                         0: Success.
     469  *                         1: Null wcsprm pointer passed.
     470  *                         2: Memory allocation failed.
     471  *                         3: Linear transformation matrix is singular.
     472  *                         4: Inconsistent or unrecognized coordinate axis
     473  *                            types.
     474  *                         5: Invalid parameter value.
     475  *                         6: Invalid coordinate transformation parameters.
     476  *                         7: Ill-conditioned coordinate transformation
     477  *                            parameters.
     478  *                         8: All of the corner pixel coordinates are invalid.
     479  *                         9: Could not determine reference pixel coordinate.
     480  *                        10: Could not determine reference pixel value.
     481  *
     482  *                       For returns > 1, a detailed error message is set in
     483  *                       wcsprm::err if enabled, see wcserr_enable().
     484  *
     485  *
     486  * wcspcx() - regularize PCi_j
     487  * ---------------------------
     488  * wcspcx() "regularizes" the linear transformation matrix component of the
     489  * coordinate transformation (PCi_ja) to make it more human-readable.
     490  *
     491  * Normally, upon encountering a FITS header containing a CDi_ja matrix,
     492  * wcsset() simply treats it as PCi_ja and sets CDELTia to unity.  However,
     493  * wcspcx() decomposes CDi_ja into PCi_ja and CDELTia in such a way that
     494  * CDELTia form meaningful scaling parameters.  In practice, the residual
     495  * PCi_ja matrix will often then be orthogonal, i.e. unity, or describing a
     496  * pure rotation, axis permutation, or reflection, or a combination thereof.
     497  *
     498  * The decomposition is based on normalizing the length in the transformed
     499  * system (i.e. intermediate pixel coordinates) of the orthonormal basis
     500  * vectors of the pixel coordinate system.  This deviates slightly from the
     501  * prescription given by Eq. (4) of WCS Paper I, namely Sum(j=1,N)(PCi_ja)² = 1,
     502  * in replacing the sum over j with the sum over i.  Consequently, the columns
     503  * of PCi_ja will consist of unit vectors.  In practice, especially in cubes
     504  * and higher dimensional images, at least some pairs of these unit vectors, if
     505  * not all, will often be orthogonal or close to orthogonal.
     506  *
     507  * The sign of CDELTia is chosen to make the PCi_ja matrix as close to the,
     508  * possibly permuted, unit matrix as possible, except that where the coordinate
     509  * description contains a pair of celestial axes, the sign of CDELTia is set
     510  * negative for the longitude axis and positive for the latitude axis.
     511  *
     512  * Optionally, rows of the PCi_ja matrix may also be permuted to diagonalize
     513  * it as far as possible, thus undoing any transposition of axes in the
     514  * intermediate pixel coordinate system.
     515  *
     516  * If the coordinate description contains a celestial plane, then the angle of
     517  * rotation of each of the basis vectors associated with the celestial axes is
     518  * returned.  For a pure rotation the two angles should be identical.  Any
     519  * difference between them is a measure of axis skewness.
     520  *
     521  * The decomposition is not performed for axes involving a sequent distortion
     522  * function that is defined in terms of CDi_ja, such as TPV, TNX, or ZPX, which
     523  * always are.  The independent variables of the polynomial are therefore
     524  * intermediate world coordinates rather than intermediate pixel coordinates.
     525  * Because sequent distortions are always applied before CDELTia, if CDi_ja was
     526  * translated to PCi_ja plus CDELTia, then the distortion would be altered
     527  * unless the polynomial coefficients were also adjusted to account for the
     528  * change of scale.
     529  *
     530  * wcspcx() requires the wcsprm struct to have been set up by wcsset(), and
     531  * will invoke it if necessary.  The wcsprm struct is reset on return with an
     532  * explicit call to wcsset().
     533  *
     534  * Given and returned:
     535  *   wcs       struct wcsprm*
     536  *                       Coordinate transformation parameters.
     537  *
     538  * Given:
     539  *   dopc      int       If 1, then PCi_ja and CDELTia, as given, will be
     540  *                       recomposed according to the above prescription.  If 0,
     541  *                       the operation is restricted to decomposing CDi_ja.
     542  *
     543  *   permute   int       If 1, then after decomposition (or recomposition),
     544  *                       permute rows of PCi_ja to make the axes of the
     545  *                       intermediate pixel coordinate system match as closely
     546  *                       as possible those of the pixel coordinates.  That is,
     547  *                       make it as close to a diagonal matrix as possible.
     548  *                       However, celestial axes are special in always being
     549  *                       paired, with the longitude axis preceding the latitude
     550  *                       axis.
     551  *
     552  *                       All WCS entities indexed by i, such as CTYPEia,
     553  *                       CRVALia, CDELTia, etc., including coordinate lookup
     554  *                       tables, will also be permuted as necessary to account
     555  *                       for the change to PCi_ja.  This does not apply to
     556  *                       CRPIXja, nor prior distortion functions.  These
     557  *                       operate on pixel coordinates, which are not affected
     558  *                       by the permutation.
     559  *
     560  * Returned:
     561  *   rotn      double[2] Rotation angle [deg] of each basis vector associated
     562  *                       with the celestial axes.  For a pure rotation the two
     563  *                       angles should be identical.  Any difference between
     564  *                       them is a measure of axis skewness.
     565  *
     566  *                       May be set to the NULL pointer if this information is
     567  *                       not required.
     568  *
     569  * Function return value:
     570  *             int       Status return value:
     571  *                         0: Success.
     572  *                         1: Null wcsprm pointer passed.
     573  *                         2: Memory allocation failed.
     574  *                         5: CDi_j matrix not used.
     575  *                         6: Sequent distortion function present.
     576  *
     577  *
     578  * Global variable: const char *wcsfix_errmsg[] - Status return messages
     579  * ---------------------------------------------------------------------
     580  * Error messages to match the status value returned from each function.
     581  *
     582  *===========================================================================*/
     583  
     584  #ifndef WCSLIB_WCSFIX
     585  #define WCSLIB_WCSFIX
     586  
     587  #include "wcs.h"
     588  #include "wcserr.h"
     589  
     590  #ifdef __cplusplus
     591  extern "C" {
     592  #endif
     593  
     594  #define CDFIX    0
     595  #define DATFIX   1
     596  #define OBSFIX   2
     597  #define UNITFIX  3
     598  #define SPCFIX   4
     599  #define CELFIX   5
     600  #define CYLFIX   6
     601  #define NWCSFIX  7
     602  
     603  extern const char *wcsfix_errmsg[];
     604  #define cylfix_errmsg wcsfix_errmsg
     605  
     606  enum wcsfix_errmsg_enum {
     607    FIXERR_OBSGEO_FIX       = -5, // Observatory coordinates amended.
     608    FIXERR_DATE_FIX         = -4, // Date string reformatted.
     609    FIXERR_SPC_UPDATE       = -3, // Spectral axis type modified.
     610    FIXERR_UNITS_ALIAS      = -2,	// Units alias translation.
     611    FIXERR_NO_CHANGE        = -1,	// No change.
     612    FIXERR_SUCCESS          =  0,	// Success.
     613    FIXERR_NULL_POINTER     =  1,	// Null wcsprm pointer passed.
     614    FIXERR_MEMORY           =  2,	// Memory allocation failed.
     615    FIXERR_SINGULAR_MTX     =  3,	// Linear transformation matrix is singular.
     616    FIXERR_BAD_CTYPE        =  4,	// Inconsistent or unrecognized coordinate
     617  				// axis types.
     618    FIXERR_BAD_PARAM        =  5,	// Invalid parameter value.
     619    FIXERR_BAD_COORD_TRANS  =  6,	// Invalid coordinate transformation
     620  				// parameters.
     621    FIXERR_ILL_COORD_TRANS  =  7,	// Ill-conditioned coordinate transformation
     622  				// parameters.
     623    FIXERR_BAD_CORNER_PIX   =  8,	// All of the corner pixel coordinates are
     624  				// invalid.
     625    FIXERR_NO_REF_PIX_COORD =  9,	// Could not determine reference pixel
     626  				// coordinate.
     627    FIXERR_NO_REF_PIX_VAL   = 10	// Could not determine reference pixel value.
     628  };
     629  
     630  int wcsfix(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[]);
     631  
     632  int wcsfixi(int ctrl, const int naxis[], struct wcsprm *wcs, int stat[],
     633              struct wcserr info[]);
     634  
     635  int cdfix(struct wcsprm *wcs);
     636  
     637  int datfix(struct wcsprm *wcs);
     638  
     639  int obsfix(int ctrl, struct wcsprm *wcs);
     640  
     641  int unitfix(int ctrl, struct wcsprm *wcs);
     642  
     643  int spcfix(struct wcsprm *wcs);
     644  
     645  int celfix(struct wcsprm *wcs);
     646  
     647  int cylfix(const int naxis[], struct wcsprm *wcs);
     648  
     649  int wcspcx(struct wcsprm *wcs, int dopc, int permute, double rotn[2]);
     650  
     651  
     652  #ifdef __cplusplus
     653  }
     654  #endif
     655  
     656  #endif // WCSLIB_WCSFIX