/*============================================================================
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: tspx.c,v 4.3 2007/12/27 05:35:51 cal103 Exp $
*=============================================================================
*
* tspx tests the spectral transformation routines for closure.
*
*---------------------------------------------------------------------------*/
#include
#include
#include
#define NSPEC 9991
const double tol = 1.0e-9;
void closure (const char *, const char *, double, int (*)(), int (*)(),
const double [], double []);
const double C = 2.99792458e8;
int main()
{
int stat[NSPEC], status;
double restfrq, restwav, step;
double awav[NSPEC], freq[NSPEC], spc1[NSPEC], spc2[NSPEC], velo[NSPEC],
wave[NSPEC];
struct spxprm spx;
register int j, k;
printf(
"Testing closure of WCSLIB spectral transformation routines (tspx.c)\n"
"-------------------------------------------------------------------\n");
/* List status return messages. */
printf("\nList of spx status return values:\n");
for (status = 1; status <= 4; status++) {
printf("%4d: %s.\n", status, spx_errmsg[status]);
}
restfrq = 1420.40595e6;
restwav = C/restfrq;
/* Exercise specx(). */
printf("\nTesting spectral cross-conversions (specx).\n\n");
if ((status = specx("VELO", 4.3e5, restfrq, restwav, &spx))) {
printf("specx ERROR %d: %s.\n", status, spx_errmsg[status]);
return 1;
}
printf(" restfrq:%20.12E\n", spx.restfrq);
printf(" restwav:%20.12E\n", spx.restwav);
printf(" wavetype:%3d\n", spx.wavetype);
printf(" velotype:%3d\n", spx.velotype);
printf("\n");
printf(" freq:%20.12E\n", spx.freq);
printf(" afrq:%20.12E\n", spx.afrq);
printf(" ener:%20.12E\n", spx.ener);
printf(" wavn:%20.12E\n", spx.wavn);
printf(" vrad:%20.12E\n", spx.vrad);
printf(" wave:%20.12E\n", spx.wave);
printf(" vopt:%20.12E\n", spx.vopt);
printf(" zopt:%20.12E\n", spx.zopt);
printf(" awav:%20.12E\n", spx.awav);
printf(" velo:%20.12E\n", spx.velo);
printf(" beta:%20.12E\n", spx.beta);
printf("\n");
printf("dfreq/dafrq:%20.12E\n", spx.dfreqafrq);
printf("dafrq/dfreq:%20.12E\n", spx.dafrqfreq);
printf("dfreq/dener:%20.12E\n", spx.dfreqener);
printf("dener/dfreq:%20.12E\n", spx.denerfreq);
printf("dfreq/dwavn:%20.12E\n", spx.dfreqwavn);
printf("dwavn/dfreq:%20.12E\n", spx.dwavnfreq);
printf("dfreq/dvrad:%20.12E\n", spx.dfreqvrad);
printf("dvrad/dfreq:%20.12E\n", spx.dvradfreq);
printf("dfreq/dwave:%20.12E\n", spx.dfreqwave);
printf("dwave/dfreq:%20.12E\n", spx.dwavefreq);
printf("dfreq/dawav:%20.12E\n", spx.dfreqawav);
printf("dawav/dfreq:%20.12E\n", spx.dawavfreq);
printf("dfreq/dvelo:%20.12E\n", spx.dfreqvelo);
printf("dvelo/dfreq:%20.12E\n", spx.dvelofreq);
printf("dwave/dvopt:%20.12E\n", spx.dwavevopt);
printf("dvopt/dwave:%20.12E\n", spx.dvoptwave);
printf("dwave/dzopt:%20.12E\n", spx.dwavezopt);
printf("dzopt/dwave:%20.12E\n", spx.dzoptwave);
printf("dwave/dawav:%20.12E\n", spx.dwaveawav);
printf("dawav/dwave:%20.12E\n", spx.dawavwave);
printf("dwave/dvelo:%20.12E\n", spx.dwavevelo);
printf("dvelo/dwave:%20.12E\n", spx.dvelowave);
printf("dawav/dvelo:%20.12E\n", spx.dawavvelo);
printf("dvelo/dawav:%20.12E\n", spx.dveloawav);
printf("dvelo/dbeta:%20.12E\n", spx.dvelobeta);
printf("dbeta/dvelo:%20.12E\n", spx.dbetavelo);
printf("\n");
/* Construct a linear velocity spectrum. */
step = (2.0*C/NSPEC) / 2.0;
for (j = 0, k = -NSPEC; j < NSPEC; j++, k += 2) {
velo[j] = (k+1)*step;
}
printf("\nVelocity range: %.3f to %.3f km/s, step: %.3f km/s\n",
velo[0]*1e-3, velo[NSPEC-1]*1e-3, (velo[1] - velo[0])*1e-3);
/* Convert it to frequency. */
velofreq(restfrq, NSPEC, 1, 1, velo, freq, stat);
/* Test closure of all two-way combinations. */
closure("freq", "afrq", 0.0, freqafrq, afrqfreq, freq, spc1);
closure("afrq", "freq", 0.0, afrqfreq, freqafrq, spc1, spc2);
closure("freq", "ener", 0.0, freqener, enerfreq, freq, spc1);
closure("ener", "freq", 0.0, enerfreq, freqener, spc1, spc2);
closure("freq", "wavn", 0.0, freqwavn, wavnfreq, freq, spc1);
closure("wavn", "freq", 0.0, wavnfreq, freqwavn, spc1, spc2);
closure("freq", "vrad", restfrq, freqvrad, vradfreq, freq, spc1);
closure("vrad", "freq", restfrq, vradfreq, freqvrad, spc1, spc2);
closure("freq", "wave", 0.0, freqwave, wavefreq, freq, wave);
closure("wave", "freq", 0.0, wavefreq, freqwave, wave, spc2);
closure("freq", "awav", 0.0, freqawav, awavfreq, freq, awav);
closure("awav", "freq", 0.0, awavfreq, freqawav, awav, spc2);
closure("freq", "velo", restfrq, freqvelo, velofreq, freq, velo);
closure("velo", "freq", restfrq, velofreq, freqvelo, velo, spc2);
closure("wave", "vopt", restwav, wavevopt, voptwave, wave, spc1);
closure("vopt", "wave", restwav, voptwave, wavevopt, spc1, spc2);
closure("wave", "zopt", restwav, wavezopt, zoptwave, wave, spc1);
closure("zopt", "wave", restwav, zoptwave, wavezopt, spc1, spc2);
closure("wave", "awav", 0.0, waveawav, awavwave, wave, spc1);
closure("awav", "wave", 0.0, awavwave, waveawav, spc1, spc2);
closure("wave", "velo", restwav, wavevelo, velowave, wave, spc1);
closure("velo", "wave", restwav, velowave, wavevelo, spc1, spc2);
closure("awav", "velo", restwav, awavvelo, veloawav, awav, spc1);
closure("velo", "awav", restwav, veloawav, awavvelo, spc1, spc2);
closure("velo", "beta", 0.0, velobeta, betavelo, velo, spc1);
closure("beta", "velo", 0.0, betavelo, velobeta, spc1, spc2);
return 0;
}
/*--------------------------------------------------------------------------*/
void closure (from, to, parm, fwd, rev, spec1, spec2)
const char *from, *to;
double parm;
SPX_PROTO((*fwd))
SPX_PROTO((*rev))
const double spec1[];
double spec2[];
{
static char skip = '\0';
int stat1[NSPEC], stat2[NSPEC], status;
register int j;
double clos[NSPEC], resid, residmax;
/* Convert the first to the second. */
if ((status = fwd(parm, NSPEC, 1, 1, spec1, spec2, stat1))) {
printf("%s%s ERROR %d: %s.\n", from, to, status, spx_errmsg[status]);
}
/* Convert the second back to the first. */
if ((status = rev(parm, NSPEC, 1, 1, spec2, clos, stat2))) {
printf("%s%s ERROR %d: %s.\n", to, from, status, spx_errmsg[status]);
}
residmax = 0.0;
/* Test closure. */
for (j = 0; j < NSPEC; j++) {
if (stat1[j]) {
printf("%c%s%s: %s = %.12E -> %s = ???, stat = %d\n", skip, from, to,
from, spec1[j], to, stat1[j]);
skip = '\0';
continue;
}
if (stat2[j]) {
printf("%c%s%s: %s = %.12E -> %s = %.12E -> %s = ???, stat = %d\n",
skip, to, from, from, spec1[j], to, spec2[j], from, stat2[j]);
skip = '\0';
continue;
}
if (spec1[j] == 0.0) {
resid = fabs(clos[j] - spec1[j]);
} else {
resid = fabs((clos[j] - spec1[j])/spec1[j]);
if (resid > residmax) residmax = resid;
}
if (resid > tol) {
printf("%c%s%s: %s = %.12E -> %s = %.12E ->\n %s = %.12E, "
"resid = %.12E\n", skip, from, to, from, spec1[j], to,
spec2[j], from, clos[j], resid);
skip = '\0';
}
}
printf("%s%s: Maximum closure residual = %.12E\n", from, to, residmax);
if (residmax > tol) {
printf("\n");
skip = '\0';
} else {
skip = '\n';
}
return;
}