/*============================================================================ 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: twcs.c,v 4.3 2007/12/27 05:35:51 cal103 Exp $ *============================================================================= * * twcs tests wcss2p() and wcsp2s() for closure on an oblique 2-D slice * through a 4-D image with celestial, spectral and logarithmic coordinate * axes. * *---------------------------------------------------------------------------*/ #include #include #include #include #include void parser(struct wcsprm *); /* Reporting tolerance. */ const double tol = 1.0e-10; /* In real life these would be encoded as FITS header keyrecords. */ const int NAXIS = 4; const double CRPIX[4] = { 513.0, 0.0, 0.0, 0.0}; const double PC[4][4] = {{ 1.1, 0.0, 0.0, 0.0}, { 0.0, 1.0, 0.0, 0.1}, { 0.0, 0.0, 1.0, 0.0}, { 0.0, 0.2, 0.0, 1.0}}; const double CDELT[4] = {-9.635265432e-6, 1.0, 0.1, -1.0}; char CTYPE[4][9] = {"WAVE-F2W", "XLAT-BON", "TIME-LOG", "XLON-BON"}; const double CRVAL[4] = {0.214982042, -30.0, 1.0, 150.0}; const double LONPOLE = 150.0; const double LATPOLE = 999.0; const double RESTFRQ = 1.42040575e9; const double RESTWAV = 0.0; int NPV = 3; struct pvcard PV[3]; /* Projection parameters are set in main(). */ int main() { #define NELEM 9 char ok[] = "", mismatch[] = " (WARNING, mismatch)", *s; int i, k, lat, lng, stat[361], status; double freq, img[361][NELEM], lat1, lng1, phi[361], pixel1[361][NELEM], pixel2[361][NELEM], r, resid, residmax, theta[361], time, world1[361][NELEM], world2[361][NELEM]; struct wcsprm *wcs; printf("Testing closure of WCSLIB world coordinate transformation " "routines (twcs.c)\n" "----------------------------------------------------------" "-----------------\n"); /* List status return messages. */ printf("\nList of wcs status return values:\n"); for (status = 1; status <= 13; status++) { printf("%4d: %s.\n", status, wcs_errmsg[status]); } printf("\nSize of data types (bytes):\n"); printf(" char:%5zd\n", sizeof(char)); printf(" short int:%5zd\n", sizeof(short int)); printf(" int:%5zd\n", sizeof(int)); printf(" long int:%5zd\n", sizeof(long int)); printf(" float:%5zd\n", sizeof(float)); printf(" double:%5zd\n", sizeof(double)); printf(" char *:%5zd\n", sizeof(char *)); printf(" char (*)[72]:%5zd\n", sizeof(char (*)[72])); printf(" int *:%5zd\n", sizeof(int *)); printf(" float *:%5zd\n", sizeof(float *)); printf(" double *:%5zd\n", sizeof(double *)); printf("struct pvcard *:%5zd\n", sizeof(struct pvcard *)); printf("struct pscard *:%5zd\n", sizeof(struct pscard *)); printf("\nSize of structs (bytes/ints):\n"); s = (sizeof(struct linprm) == sizeof(int)*LINLEN) ? ok : mismatch; printf(" linprm:%5zd /%4zd%s\n", sizeof(struct linprm), LINLEN, s); s = (sizeof(struct celprm) == sizeof(int)*CELLEN) ? ok : mismatch; printf(" celprm:%5zd /%4zd%s\n", sizeof(struct celprm), CELLEN, s); s = (sizeof(struct prjprm) == sizeof(int)*PRJLEN) ? ok : mismatch; printf(" prjprm:%5zd /%4zd%s\n", sizeof(struct prjprm), PRJLEN, s); s = (sizeof(struct spcprm) == sizeof(int)*SPCLEN) ? ok : mismatch; printf(" spcprm:%5zd /%4zd%s\n", sizeof(struct spcprm), SPCLEN, s); s = (sizeof(struct tabprm) == sizeof(int)*TABLEN) ? ok : mismatch; printf(" tabprm:%5zd /%4zd%s\n", sizeof(struct tabprm), TABLEN, s); s = (sizeof(struct wcsprm) == sizeof(int)*WCSLEN) ? ok : mismatch; printf(" wcsprm:%5zd /%4zd%s\n", sizeof(struct wcsprm), WCSLEN, s); /* Set the PVi_ma keyvalues for the longitude axis. */ /*----------------------------------------------------------*/ /* For test purposes, these are set so that the fiducial */ /* native coordinates are at the native pole, i.e. so that */ /* (phi0,theta0) = (0,90), but without any fiducial offset, */ /* i.e. iwith PVi_0a == 0 (by default). */ /*----------------------------------------------------------*/ PV[0].i = 4; /* Longitude is on axis 4. */ PV[0].m = 1; /* Parameter number 1. */ PV[0].value = 0.0; /* Fiducial native longitude. */ PV[1].i = 4; /* Longitude is on axis 4. */ PV[1].m = 2; /* Parameter number 2. */ PV[1].value = 90.0; /* Fiducial native latitude. */ /* Set the PVi_m keyvaluess for the latitude axis. */ PV[2].i = 2; /* Latitude is on axis 2. */ PV[2].m = 1; /* Parameter number 1. */ PV[2].value = -30.0; /* PVi_1. */ /* The following routine simulates the actions of a FITS header parser. */ wcs = malloc(sizeof(struct wcsprm)); wcs->flag = -1; parser(wcs); printf("\nReporting tolerance %5.1g pixel.\n", tol); /* Initialize non-celestial world coordinates. */ time = 1.0; freq = 1.42040595e9 - 180.0 * 62500.0; for (k = 0; k < 361; k++) { world1[k][0] = 0.0; world1[k][1] = 0.0; world1[k][2] = 0.0; world1[k][3] = 0.0; world1[k][2] = time; time *= 1.01; world1[k][wcs->spec] = 2.99792458e8 / freq; freq += 62500.0; } residmax = 0.0; for (lat = 90; lat >= -90; lat--) { lat1 = (double)lat; for (lng = -180, k = 0; lng <= 180; lng++, k++) { lng1 = (double)lng; world1[k][wcs->lng] = lng1; world1[k][wcs->lat] = lat1; } if ((status = wcss2p(wcs, 361, NELEM, world1[0], phi, theta, img[0], pixel1[0], stat))) { printf(" wcss2p(1) ERROR %2d (lat1 = %f)\n", status, lat1); continue; } if ((status = wcsp2s(wcs, 361, NELEM, pixel1[0], img[0], phi, theta, world2[0], stat))) { printf(" wcsp2s ERROR %2d (lat1 = %f)\n", status, lat1); continue; } if ((status = wcss2p(wcs, 361, NELEM, world2[0], phi, theta, img[0], pixel2[0], stat))) { printf(" wcss2p(2) ERROR %2d (lat1 = %f)\n", status, lat1); continue; } for (k = 0; k < 361; k++) { resid = 0.0; for (i = 0; i < NAXIS; i++) { r = pixel2[k][i] - pixel1[k][i]; resid += r*r; } resid = sqrt(resid); if (resid > residmax) residmax = resid; if (resid > tol) { printf("\nClosure error:\n" "world1:%18.12f%18.12f%18.12f%18.12f\n" "pixel1:%18.12f%18.12f%18.12f%18.12f\n" "world2:%18.12f%18.12f%18.12f%18.12f\n" "pixel2:%18.12f%18.12f%18.12f%18.12f\n", world1[k][0], world1[k][1], world1[k][2], world1[k][3], pixel1[k][0], pixel1[k][1], pixel1[k][2], pixel1[k][3], world2[k][0], world2[k][1], world2[k][2], world2[k][3], pixel2[k][0], pixel2[k][1], pixel2[k][2], pixel2[k][3]); } } } printf("Maximum closure residual: %10.3e pixel.\n", residmax); wcsfree(wcs); free(wcs); return 0; } /*--------------------------------------------------------------------------*/ void parser(wcs) struct wcsprm *wcs; { int i, j, status; double *pcij; /* In practice a parser would read the FITS header until it encountered */ /* the NAXIS keyword which must occur near the start, before any of the */ /* WCS keywords. It would then use wcsini() to allocate memory for */ /* arrays in the wcsprm struct and set default values. In this */ /* simulation the header keyvalues are set as global variables. */ wcsini(1, NAXIS, wcs); /* Now the parser scans the FITS header, identifying WCS keywords and */ /* loading their values into the appropriate elements of the wcsprm */ /* struct. */ for (j = 0; j < NAXIS; j++) { wcs->crpix[j] = CRPIX[j]; } pcij = wcs->pc; for (i = 0; i < NAXIS; i++) { for (j = 0; j < NAXIS; j++) { *(pcij++) = PC[i][j]; } } for (i = 0; i < NAXIS; i++) { wcs->cdelt[i] = CDELT[i]; } for (i = 0; i < NAXIS; i++) { strcpy(wcs->ctype[i], &CTYPE[i][0]); } for (i = 0; i < NAXIS; i++) { wcs->crval[i] = CRVAL[i]; } wcs->lonpole = LONPOLE; wcs->latpole = LATPOLE; wcs->restfrq = RESTFRQ; wcs->restwav = RESTWAV; wcs->npv = NPV; for (i = 0; i < NPV; i++) { wcs->pv[i] = PV[i]; } /* Extract information from the FITS header. */ if ((status = wcsset(wcs))) { printf("wcsset ERROR%3d\n", status); } return; }