1 /*============================================================================ 2 WCSLIB 7.7 - an implementation of the FITS WCS standard. 3 Copyright (C) 1995-2021, 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 7.7 2021/07/12 06:36:49 mcalabre Exp $ 23 *============================================================================= 24 * 25 * WCSLIB 7.7 - 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 947