/*============================================================================
WCSLIB 4.3 - an implementation of the FITS WCS standard.
Copyright (C) 1995-2007, Mark Calabretta
This file is part of WCSLIB.
WCSLIB is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
WCSLIB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
You should have received a copy of the GNU Lesser General Public License
along with WCSLIB. If not, see .
Correspondence concerning WCSLIB may be directed to:
Internet email: mcalabre@atnf.csiro.au
Postal address: Dr. Mark Calabretta
Australia Telescope National Facility, CSIRO
PO Box 76
Epping NSW 1710
AUSTRALIA
Author: Mark Calabretta, Australia Telescope National Facility
http://www.atnf.csiro.au/~mcalabre/index.html
$Id: spx.c,v 4.3 2007/12/27 05:41:36 cal103 Exp $
*===========================================================================*/
#include
#include
#include
#include "spx.h"
/* Map status return value to message. */
const char *spx_errmsg[] = {
"Success",
"Null spxprm pointer passed",
"Invalid spectral parameters",
"Invalid spectral variable",
"One or more of the inspec coordinates were invalid"};
#define C 2.99792458e8
#define h 6.6260755e-34
/*============================================================================
* Spectral cross conversions; given one spectral coordinate it computes all
* the others, plus the required derivatives of each with respect to the
* others.
*===========================================================================*/
int specx(type, spec, restfrq, restwav, spx)
const char *type;
double spec, restfrq, restwav;
struct spxprm *spx;
{
register int k;
int haverest;
double beta, dwaveawav, gamma, n, s, t, u;
if (spx == 0x0) return 1;
haverest = 1;
if (restfrq == 0.0) {
if (restwav == 0.0) {
/* No line rest frequency supplied. */
haverest = 0;
/* Temporarily set a dummy value for conversions. */
spx->restwav = 1.0;
} else {
spx->restwav = restwav;
}
spx->restfrq = C/spx->restwav;
} else {
spx->restfrq = restfrq;
spx->restwav = C/restfrq;
}
/* Convert to frequency. */
spx->wavetype = 0;
spx->velotype = 0;
if (strcmp(type, "FREQ") == 0) {
if (spec == 0.0) return 3;
spx->freq = spec;
spx->wavetype = 1;
} else if (strcmp(type, "AFRQ") == 0) {
if (spec == 0.0) return 3;
spx->freq = spec/360.0;
spx->wavetype = 1;
} else if (strcmp(type, "ENER") == 0) {
if (spec == 0.0) return 3;
spx->freq = spec/h;
spx->wavetype = 1;
} else if (strcmp(type, "WAVN") == 0) {
if (spec == 0.0) return 3;
spx->freq = spec*C;
spx->wavetype = 1;
} else if (strcmp(type, "VRAD") == 0) {
spx->freq = spx->restfrq*(1.0 - spec/C);
spx->velotype = 1;
} else if (strcmp(type, "WAVE") == 0) {
if (spec == 0.0) return 3;
spx->freq = C/spec;
spx->wavetype = 1;
} else if (strcmp(type, "VOPT") == 0) {
s = 1.0 + spec/C;
if (s == 0.0) return 3;
spx->freq = spx->restfrq/s;
spx->velotype = 1;
} else if (strcmp(type, "ZOPT") == 0) {
s = 1.0 + spec;
if (s == 0.0) return 3;
spx->freq = spx->restfrq/s;
spx->velotype = 1;
} else if (strcmp(type, "AWAV") == 0) {
if (spec == 0.0) return 3;
s = 1.0/spec;
s *= s;
n = 2.554e8 / (0.41e14 - s);
n += 294.981e8 / (1.46e14 - s);
n += 1.000064328;
spx->freq = C/(spec*n);
spx->wavetype = 1;
} else if (strcmp(type, "VELO") == 0) {
beta = spec/C;
if (fabs(beta) == 1.0) return 3;
spx->freq = spx->restfrq*(1.0 - beta)/sqrt(1.0 - beta*beta);
spx->velotype = 1;
} else if (strcmp(type, "BETA") == 0) {
if (fabs(spec) == 1.0) return 3;
spx->freq = spx->restfrq*(1.0 - spec)/sqrt(1.0 - spec*spec);
spx->velotype = 1;
} else {
/* Unrecognized type. */
return 2;
}
/* Convert frequency to the other spectral types. */
n = 1.0;
for (k = 0; k < 4; k++) {
s = n*spx->freq/C;
s *= s;
t = 0.41e14 - s;
u = 1.46e14 - s;
n = 1.000064328 + (2.554e8/t + 294.981e8/u);
}
dwaveawav = n - 2.0*s*(2.554e8/(t*t) + 294.981e8/(u*u));
s = spx->freq/spx->restfrq;
spx->ener = spx->freq*h;
spx->afrq = spx->freq*360.0;
spx->wavn = spx->freq/C;
spx->vrad = C*(1.0 - s);
spx->wave = C/spx->freq;
spx->awav = spx->wave/n;
spx->vopt = C*(1.0/s - 1.0);
spx->zopt = spx->vopt/C;
spx->velo = C*(1.0 - s*s)/(1.0 + s*s);
spx->beta = spx->velo/C;
/* Compute the required derivatives. */
gamma = 1.0/sqrt(1.0 - spx->beta*spx->beta);
spx->dfreqafrq = 1.0/360.0;
spx->dafrqfreq = 1.0/spx->dfreqafrq;
spx->dfreqener = 1.0/h;
spx->denerfreq = 1.0/spx->dfreqener;
spx->dfreqwavn = C;
spx->dwavnfreq = 1.0/spx->dfreqwavn;
spx->dfreqvrad = -spx->restfrq/C;
spx->dvradfreq = 1.0/spx->dfreqvrad;
spx->dfreqwave = -spx->freq/spx->wave;
spx->dwavefreq = 1.0/spx->dfreqwave;
spx->dfreqawav = spx->dfreqwave * dwaveawav;
spx->dawavfreq = 1.0/spx->dfreqawav;
spx->dfreqvelo = -gamma*spx->restfrq/(C + spx->velo);
spx->dvelofreq = 1.0/spx->dfreqvelo;
spx->dwavevopt = spx->restwav/C;
spx->dvoptwave = 1.0/spx->dwavevopt;
spx->dwavezopt = spx->restwav;
spx->dzoptwave = 1.0/spx->dwavezopt;
spx->dwaveawav = dwaveawav;
spx->dawavwave = 1.0/spx->dwaveawav;
spx->dwavevelo = gamma*spx->restwav/(C - spx->velo);
spx->dvelowave = 1.0/spx->dwavevelo;
spx->dawavvelo = spx->dwavevelo/dwaveawav;
spx->dveloawav = 1.0/spx->dawavvelo;
spx->dvelobeta = C;
spx->dbetavelo = 1.0/spx->dvelobeta;
/* Reset values if no line rest frequency was supplied. */
if (haverest) {
spx->wavetype = 1;
spx->velotype = 1;
} else {
spx->restfrq = 0.0;
spx->restwav = 0.0;
if (!spx->wavetype) {
/* Don't have wave characteristic types. */
spx->freq = 0.0;
spx->afrq = 0.0;
spx->ener = 0.0;
spx->wavn = 0.0;
spx->wave = 0.0;
spx->awav = 0.0;
spx->dfreqwave = 0.0;
spx->dwavefreq = 0.0;
spx->dfreqawav = 0.0;
spx->dawavfreq = 0.0;
spx->dwaveawav = 0.0;
spx->dawavwave = 0.0;
} else {
/* Don't have velocity types. */
spx->vrad = 0.0;
spx->vopt = 0.0;
spx->zopt = 0.0;
spx->velo = 0.0;
spx->beta = 0.0;
}
spx->dfreqvrad = 0.0;
spx->dvradfreq = 0.0;
spx->dfreqvelo = 0.0;
spx->dvelofreq = 0.0;
spx->dwavevopt = 0.0;
spx->dvoptwave = 0.0;
spx->dwavezopt = 0.0;
spx->dzoptwave = 0.0;
spx->dwavevelo = 0.0;
spx->dvelowave = 0.0;
spx->dawavvelo = 0.0;
spx->dveloawav = 0.0;
}
return 0;
}
/*============================================================================
* Conversions between frequency and vacuum wavelength.
*===========================================================================*/
int freqwave(dummy, nfreq, sfreq, swave, freq, wave, stat)
double dummy;
int nfreq, sfreq, swave;
const double freq[];
double wave[];
int stat[];
{
int status = 0;
register int ifreq, *statp;
register const double *freqp;
register double *wavep;
freqp = freq;
wavep = wave;
statp = stat;
for (ifreq = 0; ifreq < nfreq; ifreq++) {
if (*freqp != 0.0) {
*wavep = C/(*freqp);
*(statp++) = 0;
} else {
*(statp++) = 1;
status = 4;
}
freqp += sfreq;
wavep += swave;
}
return status;
}
/*--------------------------------------------------------------------------*/
int wavefreq(dummy, nwave, swave, sfreq, wave, freq, stat)
double dummy;
int nwave, swave, sfreq;
const double wave[];
double freq[];
int stat[];
{
int status = 0;
register int iwave, *statp;
register const double *wavep;
register double *freqp;
wavep = wave;
freqp = freq;
statp = stat;
for (iwave = 0; iwave < nwave; iwave++) {
if (*wavep != 0.0) {
*freqp = C/(*wavep);
*(statp++) = 0;
} else {
*(statp++) = 1;
status = 4;
}
wavep += swave;
freqp += sfreq;
}
return status;
}
/*============================================================================
* Conversions between frequency and air wavelength.
*===========================================================================*/
int freqawav(dummy, nfreq, sfreq, sawav, freq, awav, stat)
double dummy;
int nfreq, sfreq, sawav;
const double freq[];
double awav[];
int stat[];
{
int status;
if ((status = freqwave(dummy, nfreq, sfreq, sawav, freq, awav, stat))) {
return status;
}
return waveawav(dummy, nfreq, sawav, sawav, awav, awav, stat);
}
/*--------------------------------------------------------------------------*/
int awavfreq(dummy, nawav, sawav, sfreq, awav, freq, stat)
double dummy;
int nawav, sawav, sfreq;
const double awav[];
double freq[];
int stat[];
{
int status;
if ((status = awavwave(dummy, nawav, sawav, sfreq, awav, freq, stat))) {
return status;
}
return wavefreq(dummy, nawav, sfreq, sfreq, freq, freq, stat);
}
/*============================================================================
* Conversions between frequency and relativistic velocity.
*===========================================================================*/
int freqvelo(restfrq, nfreq, sfreq, svelo, freq, velo, stat)
double restfrq;
int nfreq, sfreq, svelo;
const double freq[];
double velo[];
int stat[];
{
double r, s;
register int ifreq, *statp;
register const double *freqp;
register double *velop;
r = restfrq*restfrq;
freqp = freq;
velop = velo;
statp = stat;
for (ifreq = 0; ifreq < nfreq; ifreq++) {
s = *freqp * *freqp;
*velop = C*(r - s)/(r + s);
*(statp++) = 0;
freqp += sfreq;
velop += svelo;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int velofreq(restfrq, nvelo, svelo, sfreq, velo, freq, stat)
double restfrq;
int nvelo, svelo, sfreq;
const double velo[];
double freq[];
int stat[];
{
int status = 0;
double s;
register int ivelo, *statp;
register const double *velop;
register double *freqp;
velop = velo;
freqp = freq;
statp = stat;
for (ivelo = 0; ivelo < nvelo; ivelo++) {
s = C + *velop;
if (s != 0.0) {
*freqp = restfrq*sqrt((C - *velop)/s);
*(statp++) = 0;
} else {
*(statp++) = 1;
status = 4;
}
velop += svelo;
freqp += sfreq;
}
return status;
}
/*============================================================================
* Conversions between vacuum wavelength and air wavelength.
*===========================================================================*/
int waveawav(dummy, nwave, swave, sawav, wave, awav, stat)
double dummy;
int nwave, swave, sawav;
const double wave[];
double awav[];
int stat[];
{
int status = 0;
double n, s;
register int iwave, k, *statp;
register const double *wavep;
register double *awavp;
wavep = wave;
awavp = awav;
statp = stat;
for (iwave = 0; iwave < nwave; iwave++) {
if (*wavep != 0.0) {
n = 1.0;
for (k = 0; k < 4; k++) {
s = n/(*wavep);
s *= s;
n = 2.554e8 / (0.41e14 - s);
n += 294.981e8 / (1.46e14 - s);
n += 1.000064328;
}
*awavp = (*wavep)/n;
*(statp++) = 0;
} else {
*(statp++) = 1;
status = 4;
}
wavep += swave;
awavp += sawav;
}
return status;
}
/*--------------------------------------------------------------------------*/
int awavwave(dummy, nawav, sawav, swave, awav, wave, stat)
double dummy;
int nawav, sawav, swave;
const double awav[];
double wave[];
int stat[];
{
int status = 0;
double n, s;
register int iawav, *statp;
register const double *awavp;
register double *wavep;
awavp = awav;
wavep = wave;
statp = stat;
for (iawav = 0; iawav < nawav; iawav++) {
if (*awavp != 0.0) {
s = 1.0/(*awavp);
s *= s;
n = 2.554e8 / (0.41e14 - s);
n += 294.981e8 / (1.46e14 - s);
n += 1.000064328;
*wavep = (*awavp)*n;
*(statp++) = 0;
} else {
*(statp++) = 1;
status = 4;
}
awavp += sawav;
wavep += swave;
}
return status;
}
/*============================================================================
* Conversions between vacuum wavelength and relativistic velocity.
*===========================================================================*/
int wavevelo(restwav, nwave, swave, svelo, wave, velo, stat)
double restwav;
int nwave, swave, svelo;
const double wave[];
double velo[];
int stat[];
{
double r, s;
register int iwave, *statp;
register const double *wavep;
register double *velop;
r = restwav*restwav;
wavep = wave;
velop = velo;
statp = stat;
for (iwave = 0; iwave < nwave; iwave++) {
s = *wavep * *wavep;
*velop = C*(s - r)/(s + r);
*(statp++) = 0;
wavep += swave;
velop += svelo;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int velowave(restwav, nvelo, svelo, swave, velo, wave, stat)
double restwav;
int nvelo, svelo, swave;
const double velo[];
double wave[];
int stat[];
{
int status = 0;
double s;
register int ivelo, *statp;
register const double *velop;
register double *wavep;
velop = velo;
wavep = wave;
statp = stat;
for (ivelo = 0; ivelo < nvelo; ivelo++) {
s = C - *velop;
if (s != 0.0) {
*wavep = restwav*sqrt((C + *velop)/s);
*(statp++) = 0;
} else {
*(statp++) = 1;
status = 4;
}
velop += svelo;
wavep += swave;
}
return status;
}
/*============================================================================
* Conversions between air wavelength and relativistic velocity.
*===========================================================================*/
int awavvelo(dummy, nawav, sawav, svelo, awav, velo, stat)
double dummy;
int nawav, sawav, svelo;
const double awav[];
double velo[];
int stat[];
{
int status;
if ((status = awavwave(dummy, nawav, sawav, svelo, awav, velo, stat))) {
return status;
}
return wavevelo(dummy, nawav, svelo, svelo, velo, velo, stat);
}
/*--------------------------------------------------------------------------*/
int veloawav(dummy, nvelo, svelo, sawav, velo, awav, stat)
double dummy;
int nvelo, svelo, sawav;
const double velo[];
double awav[];
int stat[];
{
int status;
if ((status = velowave(dummy, nvelo, svelo, sawav, velo, awav, stat))) {
return status;
}
return waveawav(dummy, nvelo, sawav, sawav, awav, awav, stat);
}
/*============================================================================
* Conversions between frequency and angular frequency.
*===========================================================================*/
int freqafrq(dummy, nfreq, sfreq, safrq, freq, afrq, stat)
double dummy;
int nfreq, sfreq, safrq;
const double freq[];
double afrq[];
int stat[];
{
register int ifreq, *statp;
register const double *freqp;
register double *afrqp;
freqp = freq;
afrqp = afrq;
statp = stat;
for (ifreq = 0; ifreq < nfreq; ifreq++) {
*afrqp = (*freqp)*360.0;
*(statp++) = 0;
freqp += sfreq;
afrqp += safrq;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int afrqfreq(dummy, nafrq, safrq, sfreq, afrq, freq, stat)
double dummy;
int nafrq, safrq, sfreq;
const double afrq[];
double freq[];
int stat[];
{
register int iafrq, *statp;
register const double *afrqp;
register double *freqp;
afrqp = afrq;
freqp = freq;
statp = stat;
for (iafrq = 0; iafrq < nafrq; iafrq++) {
*freqp = (*afrqp)/360.0;
*(statp++) = 0;
afrqp += safrq;
freqp += sfreq;
}
return 0;
}
/*============================================================================
* Conversions between frequency and energy.
*===========================================================================*/
int freqener(dummy, nfreq, sfreq, sener, freq, ener, stat)
double dummy;
int nfreq, sfreq, sener;
const double freq[];
double ener[];
int stat[];
{
register int ifreq, *statp;
register const double *freqp;
register double *enerp;
freqp = freq;
enerp = ener;
statp = stat;
for (ifreq = 0; ifreq < nfreq; ifreq++) {
*enerp = (*freqp)*h;
*(statp++) = 0;
freqp += sfreq;
enerp += sener;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int enerfreq(dummy, nener, sener, sfreq, ener, freq, stat)
double dummy;
int nener, sener, sfreq;
const double ener[];
double freq[];
int stat[];
{
register int iener, *statp;
register const double *enerp;
register double *freqp;
enerp = ener;
freqp = freq;
statp = stat;
for (iener = 0; iener < nener; iener++) {
*freqp = (*enerp)/h;
*(statp++) = 0;
enerp += sener;
freqp += sfreq;
}
return 0;
}
/*============================================================================
* Conversions between frequency and wave number.
*===========================================================================*/
int freqwavn(dummy, nfreq, sfreq, swavn, freq, wavn, stat)
double dummy;
int nfreq, sfreq, swavn;
const double freq[];
double wavn[];
int stat[];
{
register int ifreq, *statp;
register const double *freqp;
register double *wavnp;
freqp = freq;
wavnp = wavn;
statp = stat;
for (ifreq = 0; ifreq < nfreq; ifreq++) {
*wavnp = (*freqp)/C;
*(statp++) = 0;
freqp += sfreq;
wavnp += swavn;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int wavnfreq(dummy, nwavn, swavn, sfreq, wavn, freq, stat)
double dummy;
int nwavn, swavn, sfreq;
const double wavn[];
double freq[];
int stat[];
{
register int iwavn, *statp;
register const double *wavnp;
register double *freqp;
wavnp = wavn;
freqp = freq;
statp = stat;
for (iwavn = 0; iwavn < nwavn; iwavn++) {
*freqp = (*wavnp)*C;
*(statp++) = 0;
wavnp += swavn;
freqp += sfreq;
}
return 0;
}
/*============================================================================
* Conversions between frequency and radio velocity.
*===========================================================================*/
int freqvrad(restfrq, nfreq, sfreq, svrad, freq, vrad, stat)
double restfrq;
int nfreq, sfreq, svrad;
const double freq[];
double vrad[];
int stat[];
{
double r;
register int ifreq, *statp;
register const double *freqp;
register double *vradp;
if (restfrq == 0.0) {
return 2;
}
r = C/restfrq;
freqp = freq;
vradp = vrad;
statp = stat;
for (ifreq = 0; ifreq < nfreq; ifreq++) {
*vradp = r*(restfrq - *freqp);
*(statp++) = 0;
freqp += sfreq;
vradp += svrad;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int vradfreq(restfrq, nvrad, svrad, sfreq, vrad, freq, stat)
double restfrq;
int nvrad, svrad, sfreq;
const double vrad[];
double freq[];
int stat[];
{
double r;
register int ivrad, *statp;
register const double *vradp;
register double *freqp;
r = restfrq/C;
vradp = vrad;
freqp = freq;
statp = stat;
for (ivrad = 0; ivrad < nvrad; ivrad++) {
*freqp = r*(C - *vradp);
*(statp++) = 0;
vradp += svrad;
freqp += sfreq;
}
return 0;
}
/*============================================================================
* Conversions between vacuum wavelength and optical velocity.
*===========================================================================*/
int wavevopt(restwav, nwave, swave, svopt, wave, vopt, stat)
double restwav;
int nwave, swave, svopt;
const double wave[];
double vopt[];
int stat[];
{
double r;
register int iwave, *statp;
register const double *wavep;
register double *voptp;
if (restwav == 0.0) {
return 2;
}
r = C/restwav;
wavep = wave;
voptp = vopt;
statp = stat;
for (iwave = 0; iwave < nwave; iwave++) {
*voptp = r*(*wavep) - C;
*(statp++) = 0;
wavep += swave;
voptp += svopt;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int voptwave(restwav, nvopt, svopt, swave, vopt, wave, stat)
double restwav;
int nvopt, svopt, swave;
const double vopt[];
double wave[];
int stat[];
{
double r;
register int ivopt, *statp;
register const double *voptp;
register double *wavep;
r = restwav/C;
voptp = vopt;
wavep = wave;
statp = stat;
for (ivopt = 0; ivopt < nvopt; ivopt++) {
*wavep = r*(C + *voptp);
*(statp++) = 0;
voptp += svopt;
wavep += swave;
}
return 0;
}
/*============================================================================
* Conversions between vacuum wavelength and redshift.
*===========================================================================*/
int wavezopt(restwav, nwave, swave, szopt, wave, zopt, stat)
double restwav;
int nwave, swave, szopt;
const double wave[];
double zopt[];
int stat[];
{
double r;
register int iwave, *statp;
register const double *wavep;
register double *zoptp;
if (restwav == 0.0) {
return 2;
}
r = 1.0/restwav;
wavep = wave;
zoptp = zopt;
statp = stat;
for (iwave = 0; iwave < nwave; iwave++) {
*zoptp = r*(*wavep) - 1.0;
*(statp++) = 0;
wavep += swave;
zoptp += szopt;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int zoptwave(restwav, nzopt, szopt, swave, zopt, wave, stat)
double restwav;
int nzopt, szopt, swave;
const double zopt[];
double wave[];
int stat[];
{
register int izopt, *statp;
register const double *zoptp;
register double *wavep;
zoptp = zopt;
wavep = wave;
statp = stat;
for (izopt = 0; izopt < nzopt; izopt++) {
*wavep = restwav*(1.0 + *zoptp);
*(statp++) = 0;
zoptp += szopt;
wavep += swave;
}
return 0;
}
/*============================================================================
* Conversions between relativistic velocity and beta (= v/c).
*===========================================================================*/
int velobeta(dummy, nvelo, svelo, sbeta, velo, beta, stat)
double dummy;
int nvelo, svelo, sbeta;
const double velo[];
double beta[];
int stat[];
{
register int ivelo, *statp;
register const double *velop;
register double *betap;
velop = velo;
betap = beta;
statp = stat;
for (ivelo = 0; ivelo < nvelo; ivelo++) {
*betap = (*velop)/C;
*(statp++) = 0;
velop += svelo;
betap += sbeta;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int betavelo(dummy, nbeta, sbeta, svelo, beta, velo, stat)
double dummy;
int nbeta, sbeta, svelo;
const double beta[];
double velo[];
int stat[];
{
register int ibeta, *statp;
register const double *betap;
register double *velop;
betap = beta;
velop = velo;
statp = stat;
for (ibeta = 0; ibeta < nbeta; ibeta++) {
*velop = (*betap)*C;
*(statp++) = 0;
betap += sbeta;
velop += svelo;
}
return 0;
}