diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/utilities/nttools/stxtools/xtwcs.x | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/utilities/nttools/stxtools/xtwcs.x')
-rw-r--r-- | pkg/utilities/nttools/stxtools/xtwcs.x | 1286 |
1 files changed, 1286 insertions, 0 deletions
diff --git a/pkg/utilities/nttools/stxtools/xtwcs.x b/pkg/utilities/nttools/stxtools/xtwcs.x new file mode 100644 index 00000000..aa8b2798 --- /dev/null +++ b/pkg/utilities/nttools/stxtools/xtwcs.x @@ -0,0 +1,1286 @@ +include <imhdr.h> +include <math.h> + +# This file contains the following high-level routines for converting +# between world coordinates and pixel coordinates: +# +# xt_wcs_init initialize struct for world coordinate system +# xt_wcs_init_c initialize from input cdelt, crota, etc +# xt_wcs_init_cd initialize from input CD matrix, etc +# xt_wcs_free deallocate wcs struct +# xt_wc_pix convert from world coordinates to pixel coordinates +# xt_pix_wc convert from pixel coordinates to world coordinates +# +# Phil Hodge, 27-Sept-1988 Created, based on code by Nelson & Zolt. +# Phil Hodge, 6-April-1990 CD matrix mult. was transposed in xt_pix_wc. +# Phil Hodge, 26-July-1991 In xt_e_ctype, change GBS to GLS (global sine). + +define LEN_WCS 136 # size of wcs struct for naxis <= 7 + +define W_VALID Memi[$1] # coordinates valid, YES or NO? +define W_NAXIS Memi[$1+1] # number of axes +define W_RA_AX Memi[$1+2] # which axis is RA? zero if none +define W_DEC_AX Memi[$1+3] # which axis is Dec? zero if none +define W_PROJECTION Memi[$1+4] # projection type + +# 6 is currently not used + +# 7 - 55: full CD matrix (7x7); units = e.g. degrees +# 56 - 104: LU decomposition of CD matrix +# 105 - 111: index returned by ludcmp for use by lubksb +# 112 - 118: reference pixel location +# 119 - 122: cosine & sine of declination at the reference pixel +# 123 - 136: coordinates at crpix; units = e.g. degrees + +define W_CD Memr[P2R($1+6 +($2-1)+($3-1)*7)] +define W_CDLU Memr[P2R($1+55 +($2-1)+($3-1)*7)] +define W_CDINDX Memr[P2R($1+104)] # this is an array of 7 +define W_CRPIX Memr[P2R($1+110+$2)] +define W_COSDEC Memd[P2D($1+118)] +define W_SINDEC Memd[P2D($1+120)] +define W_CRVAL Memd[P2D($1+120)+$2] + +# Projection types. + +define W_LINEAR 0 +define W_GNOMONIC 1 # TAN +define W_SINE 2 # SIN +define W_ARC 3 # ARC +define W_NORTH_POLAR 4 # NCP, north celestial pole (Westerbork) +define W_STEREOGRAPHIC 5 # STG (conformal) +define W_AITOFF 6 # AIT (equal-area) +define W_GLOBAL_SINE 7 # GLS (equal-area) +define W_MERCATOR 8 # MER (conformal) + + +# xt_wcs_init -- initialize wcs struct +# This routine allocates space for a structure describing the world +# coordinate system for an image, fills in the values or defaults, and +# returns a pointer to that structure. + +procedure xt_wcs_init (im, wcs) + +pointer im # i: pointer to image descriptor +pointer wcs # o: pointer to world coord system struct +#-- +real dummy # returned by ludcmp and ignored +int ira, idec # index of RA, Dec axes +int j, k # loop indexes +errchk xt_load_ctstruct + +begin + call calloc (wcs, LEN_WCS, TY_STRUCT) + + W_VALID(wcs) = YES # initial value + W_NAXIS(wcs) = IM_NDIM(im) + + call xt_load_wcsstruct (im, wcs) # get CRVAL, etc from image + + if (W_NAXIS(wcs) >= 2) { + + ira = W_RA_AX(wcs) + idec = W_DEC_AX(wcs) + + if (idec > 0) { + W_COSDEC(wcs) = cos (DEGTORAD(W_CRVAL(wcs,idec))) + W_SINDEC(wcs) = sin (DEGTORAD(W_CRVAL(wcs,idec))) + } else { + W_COSDEC(wcs) = 1.d0 + W_SINDEC(wcs) = 0.d0 + } + + # Copy the CD matrix to W_CDLU, and do the LU decomposition + # on W_CDLU in-place. + do k = 1, IM_MAXDIM + do j = 1, IM_MAXDIM + W_CDLU(wcs,j,k) = W_CD(wcs,j,k) + + iferr { + call ludcmp (W_CDLU(wcs,1,1), W_NAXIS(wcs), IM_MAXDIM, + W_CDINDX(wcs), dummy) + } then { + call mfree (wcs, TY_STRUCT) + call error (0, "xt_wcs_init: cd matrix is singular") + } + } +end + + +# xt_wcs_free -- deallocate wcs struct +# This routine deallocates space for a wcs structure. + +procedure xt_wcs_free (wcs) + +pointer wcs # io: pointer to world coord system struct +#-- + +begin + if (wcs != NULL) + call mfree (wcs, TY_STRUCT) +end + + +# xt_wcs_init_c -- initialize wcs struct +# xt_wcs_init_c and xt_wcs_init_cd allocate space for a structure +# describing the world coordinate system for an image, fill in the values +# or defaults, and return a pointer to that structure. They differ from +# xt_wcs_init in that these take the coordinate parameters as arguments +# rather than getting them from the image. +# xt_wcs_init_c takes cdelt & crota, and xt_wcs_init_cd takes the CD matrix. + +procedure xt_wcs_init_c (crval, crpix, cdelt, crota, ctype, naxis, wcs) + +double crval[naxis] # i: coordinate values at reference pixel +real crpix[naxis] # i: reference pixel +real cdelt[naxis] # i: pixel spacing +real crota # i: rotation angle (if 2-D) +char ctype[SZ_CTYPE,naxis] # i: e.g. "RA---TAN" +int naxis # i: size of arrays +pointer wcs # o: pointer to world coord system struct +#-- +real dummy # returned by ludcmp and ignored +int ira, idec # index of RA, Dec axes +int j, k # loop indexes +errchk ludcmp + +begin + do k = 1, naxis + if (cdelt[k] == 0.) + call error (0, "xt_wcs_init_c: zero value of CDELT") + + call calloc (wcs, LEN_WCS, TY_STRUCT) + + W_NAXIS(wcs) = naxis + W_VALID(wcs) = YES # initial value + + # Examine ctype to get ira, idec, proj_type. + call xt_e_ctype (ctype, naxis, ira, idec, W_PROJECTION(wcs)) + W_RA_AX(wcs) = ira + W_DEC_AX(wcs) = idec + + do k = 1, naxis { + W_CRVAL(wcs,k) = crval[k] + W_CRPIX(wcs,k) = crpix[k] + } + do k = naxis+1, IM_MAXDIM { + W_CRVAL(wcs,k) = 0.d0 + W_CRPIX(wcs,k) = 1. + } + + if (naxis == 1) { + + W_CD(wcs,1,1) = cdelt[1] + + } else if (naxis >= 2) { + + if (idec > 0) { + W_COSDEC(wcs) = cos (DEGTORAD(W_CRVAL(wcs,idec))) + W_SINDEC(wcs) = sin (DEGTORAD(W_CRVAL(wcs,idec))) + } else { + W_COSDEC(wcs) = 1.d0 + W_SINDEC(wcs) = 0.d0 + } + + # Convert cdelt & crota to the CD matrix. + call xt_to_cd (wcs, cdelt, crota, naxis) + + # Copy the CD matrix, and do the LU decomposition on W_CDLU. + do k = 1, IM_MAXDIM + do j = 1, IM_MAXDIM + W_CDLU(wcs,j,k) = W_CD(wcs,j,k) + + call ludcmp (W_CDLU(wcs,1,1), naxis, IM_MAXDIM, + W_CDINDX(wcs), dummy) + } +end + + +# xt_wcs_init_cd -- initialize wcs struct (CD) + +procedure xt_wcs_init_cd (crval, crpix, cd, ctype, naxis, wcs) + +double crval[naxis] # i: coordinate values at reference pixel +real crpix[naxis] # i: reference pixel +real cd[naxis,naxis] # i: CD matrix +char ctype[SZ_CTYPE,naxis] # i: e.g. "RA---TAN" +int naxis # i: size of arrays +pointer wcs # o: pointer to world coord system struct +#-- +real dummy # returned by ludcmp and ignored +int ira, idec # index of RA, Dec axes +int j, k # loop indexes + +begin + call calloc (wcs, LEN_WCS, TY_STRUCT) + + W_NAXIS(wcs) = naxis + W_VALID(wcs) = YES # initial value + + # Examine ctype to get ira, idec, proj_type. + call xt_e_ctype (ctype, naxis, ira, idec, W_PROJECTION(wcs)) + W_RA_AX(wcs) = ira + W_DEC_AX(wcs) = idec + + do k = 1, naxis { + W_CRVAL(wcs,k) = crval[k] + W_CRPIX(wcs,k) = crpix[k] + } + do k = naxis+1, IM_MAXDIM { + W_CRVAL(wcs,k) = 0.d0 + W_CRPIX(wcs,k) = 1. + } + + if (naxis == 1) { + + W_CD(wcs,1,1) = cd[1,1] + + } else if (naxis >= 2) { + + if (idec > 0) { + W_COSDEC(wcs) = cos (DEGTORAD(W_CRVAL(wcs,idec))) + W_SINDEC(wcs) = sin (DEGTORAD(W_CRVAL(wcs,idec))) + } else { + W_COSDEC(wcs) = 1.d0 + W_SINDEC(wcs) = 0.d0 + } + + # Assign initial values to the CD matrix. + do k = 1, IM_MAXDIM { + do j = 1, IM_MAXDIM { + if (j == k) { + W_CD(wcs,k,k) = 1. + W_CDLU(wcs,k,k) = 1. + } else { + W_CD(wcs,j,k) = 0. + W_CDLU(wcs,j,k) = 0. + } + } + } + + # Copy the CD matrix, and do the LU decomposition on W_CDLU. + do k = 1, naxis { + do j = 1, naxis { + W_CD(wcs,j,k) = cd[j,k] + W_CDLU(wcs,j,k) = cd[j,k] + } + } + + iferr { + call ludcmp (W_CDLU(wcs,1,1), naxis, IM_MAXDIM, + W_CDINDX(wcs), dummy) + } then { + call mfree (wcs, TY_STRUCT) + call error (0, "xt_wcs_init_cd: cd matrix is singular") + } + } +end + +# xt_to_cd -- from cdelt & crota to cd matrix +# This routine computes the CD matrix from CDELT and CROTA. + +procedure xt_to_cd (wcs, cdelt, crota, naxis) + +pointer wcs # i: pointer to world coord system struct +real cdelt[naxis] # i: pixel spacing +real crota # i: rotation angle (if 2-D) +int naxis # i: size of arrays +#-- +real cosrota, sinrota # cosine & sine of crota +real sign_cdelt[2] # one, with sign of cdelt1 or cdelt2 +int ira, idec # index of RA, Dec axes +int j, k # loop indexes + +begin + ira = W_RA_AX(wcs) + idec = W_DEC_AX(wcs) + + if ( ! IS_INDEFD(crota) ) { + cosrota = cos (DEGTORAD(crota)) + sinrota = sin (DEGTORAD(crota)) + } else { + cosrota = 1.d0 + sinrota = 0.d0 + } + + # Initial values for CD matrix. + do k = 1, IM_MAXDIM { + do j = 1, IM_MAXDIM { + if (j == k) + W_CD(wcs,k,k) = 1. + else + W_CD(wcs,j,k) = 0. + } + } + do k = 1, naxis + W_CD(wcs,k,k) = cdelt[k] + + if (ira > 0 && idec > 0) { + + if (cdelt[ira] >= 0.) + sign_cdelt[1] = 1. + else + sign_cdelt[1] = -1. + + if (cdelt[idec] >= 0.) + sign_cdelt[2] = 1. + else + sign_cdelt[2] = -1. + + W_CD(wcs,ira,ira) = cdelt[ira] * cosrota + W_CD(wcs,ira,idec) = abs (cdelt[idec]) * sign_cdelt[1] * sinrota + W_CD(wcs,idec,ira) = -abs (cdelt[ira]) * sign_cdelt[2] * sinrota + W_CD(wcs,idec,idec) = cdelt[idec] * cosrota + } +end + +# xt_e_ctype -- examine ctype +# Examine each element of the ctype array to find which axes (if any) +# are RA & Dec (or glon & glat, etc). Also get the projection type, +# such as gnomonic, if this was specified in ctype. + +procedure xt_e_ctype (ctype, naxis, ra_axis, dec_axis, proj_type) + +char ctype[SZ_CTYPE,naxis] # i: coordinate type, e.g. "RA---TAN" +int naxis # i: dimension +int ra_axis # o: which axis is RA (or glon, etc)? +int dec_axis # o: which axis is Dec (or glat, etc)? +int proj_type # o: type of projection +#-- +char lctype[SZ_CTYPE] # local copy of an element of ctype +char dash # '-' +int k +int index # index of '-' in ctype +int strncmp(), strldx() + +begin + # Assign defaults. + ra_axis = 0 + dec_axis = 0 + if (naxis == 1) + proj_type = W_LINEAR + else + proj_type = W_GNOMONIC + + # Search for "RA", "DEC", etc. + do k = 1, naxis { + # Make a local copy of ctype & make sure it's upper case. + call strcpy (ctype[1,k], lctype, SZ_CTYPE) + call strupr (lctype) + + if (strncmp (lctype, "RA", 2) == 0) + ra_axis = k + else if (strncmp (lctype, "DEC", 3) == 0) + dec_axis = k + + else if (strncmp (lctype, "GLON", 4) == 0) + ra_axis = k + else if (strncmp (lctype, "LL", 2) == 0) + ra_axis = k + else if (strncmp (lctype, "UU", 2) == 0) + ra_axis = k + else if (strncmp (lctype, "ELON", 4) == 0) + ra_axis = k + + else if (strncmp (lctype, "GLAT", 4) == 0) + dec_axis = k + else if (strncmp (lctype, "MM", 2) == 0) + dec_axis = k + else if (strncmp (lctype, "VV", 2) == 0) + dec_axis = k + else if (strncmp (lctype, "ELAT", 4) == 0) + dec_axis = k + } + + if (ra_axis > 0) + k = ra_axis + else if (dec_axis > 0) + k = dec_axis + else + k = 0 + + # If at least one of the axes is like RA or Dec, check to see + # whether a projection type was specified. + if (k > 0) { + dash = '-' + index = strldx (dash, lctype) + if (index > 0) { + index = index + 1 + if (strncmp (lctype[index], "TAN", 3) == 0) + proj_type = W_GNOMONIC + else if (strncmp (lctype[index], "SIN", 3) == 0) + proj_type = W_SINE + else if (strncmp (lctype[index], "ARC", 3) == 0) + proj_type = W_ARC + else if (strncmp (lctype[index], "NCP", 3) == 0) + proj_type = W_NORTH_POLAR + else if (strncmp (lctype[index], "STG", 3) == 0) + proj_type = W_STEREOGRAPHIC + else if (strncmp (lctype[index], "AIT", 3) == 0) + proj_type = W_AITOFF + else if (strncmp (lctype[index], "GLS", 3) == 0) + proj_type = W_GLOBAL_SINE + else if (strncmp (lctype[index], "MER", 3) == 0) + proj_type = W_MERCATOR + } + } +end + + +define SZ_PNAME 8 + +# xt_load_wcsstruct -- load coordinate information +# Get the coordinate information from the image, and load +# that info into the wcs structure. + +procedure xt_load_wcsstruct (im, wcs) + +pointer im # i: pointer to image header struct +pointer wcs # i: pointer to world coord system struct +#-- +char pname[SZ_PNAME] +char ctype[SZ_CTYPE,IM_MAXDIM] +int naxis, iax # dimension of image; loop index for axis +bool cdm_found # true if CD matrix present in image +int imaccf() +double imgetd() +real imgetr() +errchk imgstr, imgetd, imgetr, xt_g_cd_matrix, xt_c_cd_matrix + +begin + naxis = IM_NDIM(im) + + # Get the coordinate info. If anything is missing set W_VALID to NO. + do iax = 1, naxis { + + # CTYPE for each axis. + call sprintf (pname, SZ_PNAME, "ctype%d") + call pargi (iax) + if (imaccf (im, pname) == YES) { + call imgstr (im, pname, ctype[1,iax], SZ_CTYPE) + } else { + call strcpy ("PIXEL", ctype[1,iax], SZ_CTYPE) + W_VALID(wcs) = NO + } + + # CRVAL for each axis + call sprintf (pname, SZ_PNAME, "crval%d") + call pargi (iax) + if (imaccf (im, pname) == YES) { + W_CRVAL(wcs,iax) = imgetd (im, pname) + } else { + W_CRVAL(wcs,iax) = 0.d0 + W_VALID(wcs) = NO + } + + # CRPIX for each axis + call sprintf (pname, SZ_PNAME, "crpix%d") + call pargi (iax) + if (imaccf (im, pname) == YES) { + W_CRPIX(wcs,iax) = imgetr (im, pname) + } else { + W_CRPIX(wcs,iax) = 1. + W_VALID(wcs) = NO + } + } + # Assign reasonable values to the unused elements. + do iax = naxis+1, IM_MAXDIM { + W_CRVAL(wcs,iax) = 0.d0 + W_CRPIX(wcs,iax) = 1. + } + + # Examine ctype array. + call xt_e_ctype (ctype, naxis, + W_RA_AX(wcs), W_DEC_AX(wcs), W_PROJECTION(wcs)) + + # First try to get the CD matrix, and if it isn't there + # get CDELT and CROTA and convert to CD. + + call xt_g_cd_matrix (im, wcs, naxis, cdm_found) + + if ( ! cdm_found ) + call xt_c_cd_matrix (im, wcs, naxis) +end + + +# xt_g_cd_matrix -- get CD matrix +# If the CD matrix is present, get the values and place them into the +# wcs structure. Note that we assume that if *any* of the CD matrix +# parameters are there, they are *all* there. + +define TOLER 1.e-5 + +procedure xt_g_cd_matrix (im, wcs, naxis, cdm_found) + +pointer im # i: image pointer +pointer wcs # i: pointer to wcs structure +int naxis # i: number of axes in image +bool cdm_found # o: true if CD matrix found +#-- +real cd_matrix[IM_MAXDIM,IM_MAXDIM] # the CD matrix +char pname[SZ_PNAME] +int i, j +int imaccf() +real imgetr() +errchk imgetr + +begin + # This is reset below if any element of the CD matrix is found. + cdm_found = false + + # Assign default values. + do j = 1, IM_MAXDIM + do i= 1, IM_MAXDIM + if (i == j) + cd_matrix[i,j] = 1. + else + cd_matrix[i,j] = 0. + + # Get each element of the CD matrix. + do j = 1, naxis { + do i = 1, naxis { + call sprintf (pname, SZ_PNAME, "cd%d_%d") + call pargi (i) + call pargi (j) + if (imaccf (im, pname) == YES) { + cd_matrix[i,j] = imgetr (im, pname) + cdm_found = true + } + } + } + + # Copy to the wcs structure. + do j = 1, IM_MAXDIM + do i = 1, IM_MAXDIM + W_CD(wcs,i,j) = cd_matrix[i,j] +end + + +# xt_c_cd_matrix -- create CD matrix +# If the CD matrix is not present, get the values of CDELT & CROTA, +# convert to the CD matrix, and store the values in the wcs structure. +# Since this is called after trying unsuccessfully to get the CD matrix, +# if cdelt or crota is not present W_VALID will be reset to NO. + +procedure xt_c_cd_matrix (im, wcs, naxis) + +pointer im # i: image pointer +pointer wcs # i: pointer to wcs structure +int naxis # i: number of axes in image +#-- +char pname[SZ_PNAME] # parameter name (e.g. "cdelt1") +real cdelt[IM_MAXDIM] # pixel spacing +real crota # rotation angle in degrees +int k # loop index for axis +int imaccf() +real imgetr() +errchk imgetr + +begin + do k = 1, naxis { + + # CDELT for each axis. + call sprintf (pname, SZ_PNAME, "cdelt%d") + call pargi (k) + if (imaccf (im, pname) == YES) { + cdelt[k] = imgetr (im, pname) + if (cdelt[k] == 0.) + call error (0, "xt_c_cd_matrix: cdelt is zero") + } else { + cdelt[k] = 1. + W_VALID(wcs) = NO + } + } + + # For a 1-D image, assign CD1_1 and return. + if (naxis == 1) { + W_CD(wcs,1,1) = cdelt[1] + return + } + + # CROTA (only one). + call strcpy ("crota1", pname, SZ_PNAME) + if (imaccf (im, pname) == YES) { + crota = imgetr (im, pname) + } else { + crota = 0. + W_VALID(wcs) = NO + } + + # Compute CD matrix from CDELT & CROTA. + call xt_to_cd (wcs, cdelt, crota, naxis) +end + + +# xt_wc_pix -- wcs to pixels +# This routine converts world coordinates to pixel coordinates. +# +# In the 1-D case, CRVAL is subtracted from the coordinate, the +# result is divided by CDELT (same as CD1_1), and CRPIX is added. +# +# For 2-D or higher dimension, if two of the axes are like RA and Dec, +# the input coordinates are converted to standard coordinates Xi +# and Eta. The (Xi, Eta) vector is then multiplied on the left by +# the inverse of the CD matrix, and CRPIX is added. +# The units for axes like Ra & Dec are degrees, not hours or radians. +# For linear axes the conversion is the same as for 1-D. + +procedure xt_wc_pix (wcs, phys, pix, naxis) + +pointer wcs # i: pointer to world coord system struct +double phys[naxis] # i: physical (world) coordinates (e.g. degrees) +real pix[naxis] # o: pixel coordinates +int naxis # i: size of arrays +#-- +double delta_ra # RA of object - RA at reference pixel +double dra_r, dec_r # delta_ra & declination in radians +double xi_r, eta_r # xi & eta in radians +real dphys[IM_MAXDIM] # phys coord - reference coord +int ira, idec # index of RA, Dec axes +int k # loop index +errchk xt_wp_ncp, xt_wp_mer + +begin + do k = 1, naxis + dphys[k] = phys[k] - W_CRVAL(wcs,k) + + if (naxis == 1) { + + pix[1] = dphys[1] / W_CD(wcs,1,1) + W_CRPIX(wcs,1) + + } else { + + ira = W_RA_AX(wcs) + idec = W_DEC_AX(wcs) + + # Convert RA & Dec to Xi & Eta (standard coordinates). + if (ira > 0 && idec > 0) { + + delta_ra = phys[ira] - W_CRVAL(wcs,ira) # double prec + dra_r = DEGTORAD (delta_ra) + dec_r = DEGTORAD (phys[idec]) + + switch (W_PROJECTION(wcs)) { + case W_GNOMONIC: + call xt_wp_tan (wcs, dra_r, dec_r, xi_r, eta_r) + case W_SINE: + call xt_wp_sin (wcs, dra_r, dec_r, xi_r, eta_r) + case W_ARC: + call xt_wp_arc (wcs, dra_r, dec_r, xi_r, eta_r) + case W_NORTH_POLAR: + call xt_wp_ncp (wcs, dra_r, dec_r, xi_r, eta_r) + case W_STEREOGRAPHIC: + call xt_wp_stg (wcs, dra_r, dec_r, xi_r, eta_r) + case W_AITOFF: + call xt_wp_ait (wcs, dra_r, dec_r, xi_r, eta_r) + case W_GLOBAL_SINE: + call xt_wp_gls (wcs, dra_r, dec_r, xi_r, eta_r) + case W_MERCATOR: + call xt_wp_mer (wcs, dra_r, dec_r, xi_r, eta_r) + } + + dphys[ira] = RADTODEG (xi_r) # xi, eta in degrees + dphys[idec] = RADTODEG (eta_r) + } + + # Use LU backsubstitution to get pixel coords from physical coords. + call lubksb (W_CDLU(wcs,1,1), naxis, IM_MAXDIM, + W_CDINDX(wcs), dphys) # dphys is modified in-place + do k = 1, naxis + pix[k] = dphys[k] + W_CRPIX(wcs,k) # copy to output + } +end + + +# xt_pix_wc -- pixels to wcs +# This routine converts pixel coordinates to world coordinates. +# +# In the 1-D case, CRPIX is subtracted from the pixel coordinate, +# the result is multiplied by CDELT (same as CD1_1), and CRVAL is added. +# +# For 2-D or higher dimension, CRPIX is subtracted, and the result is +# multiplied on the left by the CD matrix. If two of the axes are like +# RA and Dec, the pixel coordinates are converted to standard coordinates +# Xi and Eta. The (xi, eta) vector is then converted to differences +# between RA and Dec and CRVAL, and then CRVAL is added to each coordinate. + +procedure xt_pix_wc (wcs, pix, phys, naxis) + +pointer wcs # i: pointer to world coord system struct +real pix[naxis] # i: pixel coordinates +double phys[naxis] # o: physical (world) coordinates +int naxis # i: size of arrays +#-- +double dpix[IM_MAXDIM] # pix coord - crpix +double sum # for matrix multiplication +double dra_r, dec_r # delta_ra & declination in radians +double xi_r, eta_r # xi & eta in radians +int ira, idec # index of RA, Dec axes +int j, k # loop indexes + +begin + do k = 1, naxis + dpix[k] = pix[k] - W_CRPIX(wcs,k) + + if (naxis == 1) { + + phys[1] = dpix[1] * W_CD(wcs,1,1) + W_CRVAL(wcs,1) + + } else { + + do j = 1, naxis { + sum = 0.d0 + do k = 1, naxis + sum = sum + W_CD(wcs,j,k) * dpix[k] + phys[j] = sum + } + + ira = W_RA_AX(wcs) + idec = W_DEC_AX(wcs) + + # Convert Xi & Eta (standard coordinates) to RA & Dec. + if (ira > 0 && idec > 0) { + xi_r = DEGTORAD (phys[ira]) + eta_r = DEGTORAD (phys[idec]) + + switch (W_PROJECTION(wcs)) { + case W_GNOMONIC: + call xt_pw_tan (wcs, xi_r, eta_r, dra_r, dec_r) + case W_SINE: + call xt_pw_sin (wcs, xi_r, eta_r, dra_r, dec_r) + case W_ARC: + call xt_pw_arc (wcs, xi_r, eta_r, dra_r, dec_r) + case W_NORTH_POLAR: + call xt_pw_ncp (wcs, xi_r, eta_r, dra_r, dec_r) + case W_STEREOGRAPHIC: + call xt_pw_stg (wcs, xi_r, eta_r, dra_r, dec_r) + case W_AITOFF: + call xt_pw_ait (wcs, xi_r, eta_r, dra_r, dec_r) + case W_GLOBAL_SINE: + call xt_pw_gls (wcs, xi_r, eta_r, dra_r, dec_r) + case W_MERCATOR: + call xt_pw_mer (wcs, xi_r, eta_r, dra_r, dec_r) + } + + phys[idec] = RADTODEG (dec_r) + phys[ira] = RADTODEG (dra_r) + W_CRVAL(wcs,ira) + if (phys[ira] < 0.d0) + phys[ira] = phys[ira] + 360.d0 + } + do k = 1, naxis + if (k != ira && k != idec) + phys[k] = phys[k] + W_CRVAL(wcs,k) + } +end + + +# xt_wp_tan -- convert from ra & dec using gnomonic projection + +procedure xt_wp_tan (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double cosdra, sindra # cos & sin of dra_r +double cosdec, sindec # cos & sin of object declination +double cosdist # cos of dist from ref pixel to object + +begin + cosdra = cos (dra_r) + sindra = sin (dra_r) + + cosdec = cos (dec_r) + sindec = sin (dec_r) + + cosdist = sindec * W_SINDEC(wcs) + cosdec * W_COSDEC(wcs) * cosdra + + xi_r = cosdec * sindra / cosdist + eta_r = (sindec * W_COSDEC(wcs) - + cosdec * W_SINDEC(wcs) * cosdra) / cosdist +end + + +# xt_pw_tan -- convert to ra & dec using gnomonic projection +# In rectangular coordinates the vector (1, xi, eta) points toward +# the object; the origin is the observer's location, the x-axis points +# toward the reference pixel, the y-axis is in the direction of increasing +# right ascension, and the z-axis is in the direction of increasing +# declination. The coordinate system is then rotated by the declination so +# the x-axis passes through the equator at the RA of the reference pixel; +# the components of the vector in this coordinate system are used to +# compute (RA - reference_RA) and declination. + +procedure xt_pw_tan (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double x, y, z # vector (not unit length) pointing toward object + +begin + # Rotate the rectangular coordinate system of the vector (1, xi, eta) + # by the declination so the x-axis will pass through the equator. + x = W_COSDEC(wcs) - eta_r * W_SINDEC(wcs) + y = xi_r + z = W_SINDEC(wcs) + eta_r * W_COSDEC(wcs) + + if (x == 0.d0 && y == 0.d0) + dra_r = 0.d0 + else + dra_r = atan2 (y, x) + dec_r = atan2 (z, sqrt (x*x + y*y)) +end + + +# xt_wp_sin -- convert from ra & dec using sine projection +# +# Reference: AIPS Memo No. 27 by Eric W. Greisen + +procedure xt_wp_sin (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double cosdra, sindra # cos & sin of delta_ra +double cosdec, sindec # cos & sin of object declination + +begin + cosdra = cos (dra_r) + sindra = sin (dra_r) + + cosdec = cos (dec_r) + sindec = sin (dec_r) + + xi_r = cosdec * sindra + eta_r = sindec * W_COSDEC(wcs) - cosdec * W_SINDEC(wcs) * cosdra +end + + +# xt_pw_sin -- convert to ra & dec using sine projection +# In rectangular coordinates the vector (v1, xi, eta), where +# v1 = sqrt (1 - xi**2 - eta**2), is the location of the object on the +# unit celestial sphere. The x-axis points toward the reference pixel, +# the y-axis is in the direction of increasing right ascension, and the +# z-axis is in the direction of increasing declination. The coordinate +# system is then rotated (around the y-axis) by the declination so the +# x-axis passes through the equator at the RA of the reference pixel; +# the components of the vector in this coordinate system are used to +# compute (RA - reference_RA) and declination. + +procedure xt_pw_sin (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double v1 # x component of unit vector +double x, y, z # unit vector with x[1] pointing toward equator + +begin + v1 = sqrt (1.d0 - xi_r*xi_r - eta_r*eta_r) + + # Rotate the rectangular coordinate system of the vector (v1, xi, eta) + # by the declination so the x-axis will pass through the equator. + x = v1 * W_COSDEC(wcs) - eta_r * W_SINDEC(wcs) + y = xi_r + z = v1 * W_SINDEC(wcs) + eta_r * W_COSDEC(wcs) + + if (x == 0.d0 && y == 0.d0) + dra_r = 0.d0 + else + dra_r = atan2 (y, x) + dec_r = atan2 (z, sqrt (x*x + y*y)) +end + + +# xt_wp_arc -- convert from ra & dec using arc projection +# +# Reference: AIPS Memo No. 27 by Eric W. Greisen + +procedure xt_wp_arc (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double cosdra, sindra # cos & sin of delta_ra +double cosdec, sindec # cos & sin of object declination +double theta # distance (radians) from ref pixel to object +double r # theta / sin (theta) + +begin + cosdra = cos (dra_r) + sindra = sin (dra_r) + + cosdec = cos (dec_r) + sindec = sin (dec_r) + + theta = acos (sindec * W_SINDEC(wcs) + cosdec * W_COSDEC(wcs) * cosdra) + if (theta == 0.d0) + r = 1.d0 + else + r = theta / sin (theta) + + xi_r = r * cosdec * sindra + eta_r = r * (sindec * W_COSDEC(wcs) - cosdec * W_SINDEC(wcs) * cosdra) +end + + +# xt_pw_arc -- convert to ra & dec using arc projection +# The rectangular coordinates of the pixel on a unit celestial sphere +# are computed in a coordinate system such that the x-axis points toward +# the reference pixel, the y-axis is in the direction of increasing right +# ascension, and the z-axis is in the direction of increasing declination. +# The coordinate system is then rotated (around the y-axis) by the +# declination so the x-axis passes through the equator at the RA of the +# reference pixel; the components of the vector in this coordinate system +# are used to compute (RA - reference_RA) and declination. + +procedure xt_pw_arc (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double theta # arc length, i.e. sqrt (xi**2 + eta**2) +double v[3] # unit vector with v[1] pointing toward ref pixel +double x, y, z # vector with x[1] pointing toward equator + +begin + theta = sqrt (xi_r*xi_r + eta_r*eta_r) + if (theta == 0.d0) { + v[1] = 1.d0 + v[2] = 0.d0 + v[3] = 0.d0 + } else { + v[1] = cos (theta) + v[2] = sin (theta) / theta * xi_r + v[3] = sin (theta) / theta * eta_r + } + + # Rotate the rectangular coordinate system of the vector v by the + # declination so the x-axis will pass through the equator. + x = v[1] * W_COSDEC(wcs) - v[3] * W_SINDEC(wcs) + y = v[2] + z = v[1] * W_SINDEC(wcs) + v[3] * W_COSDEC(wcs) + + if (x == 0.d0 && y == 0.d0) + dra_r = 0.d0 + else + dra_r = atan2 (y, x) + dec_r = atan2 (z, sqrt (x*x + y*y)) +end + + +# xt_wp_ncp -- convert from ra & dec using ncp projection +# +# References: +# AIPS Memo No. 27 by Eric W. Greisen +# Data Processing for the Westerbork Synthesis Radio Telescope +# by W. N. Brouw + +procedure xt_wp_ncp (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double cosdra, sindra # cos & sin of delta_ra +double cosdec # cos of object declination + +begin + if (W_SINDEC(wcs) == 0.) + call error (1, "NCP projection: dec is zero") + + cosdra = cos (dra_r) + sindra = sin (dra_r) + + cosdec = cos (dec_r) + + xi_r = - cosdec * sindra + eta_r = (W_COSDEC(wcs) - cosdec * cosdra) / W_SINDEC(wcs) +end + + +# xt_pw_ncp -- convert to ra & dec using ncp projection +# +# References: +# AIPS Memo No. 27 by Eric W. Greisen +# Data Processing for the Westerbork Synthesis Radio Telescope +# by W. N. Brouw + +procedure xt_pw_ncp (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double temp + +begin + temp = W_COSDEC(wcs) - eta_r * W_SINDEC(wcs) + + dra_r = atan2 (-xi_r, temp) + dec_r = acos (temp / cos (dra_r)) + if (W_SINDEC(wcs) < 0) + dec_r = -dec_r +end + + +# xt_wp_gls -- convert from ra & dec using global-sine projection +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_wp_gls (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double cosdec # cos of object declination +double temp # delta RA +int idec # which axis is declination axis + +begin + cosdec = cos (dec_r) + idec = W_DEC_AX(wcs) + + temp = dra_r + + # Put dra_r on the interval (-180,+180] degrees. + if (temp <= -PI) + temp = temp + TWOPI + if (temp > PI) + temp = temp - TWOPI + + xi_r = temp * cosdec + + if (idec > 0) + eta_r = dec_r - DEGTORAD (W_CRVAL(wcs,idec)) + else + eta_r = dec_r +end + + +# xt_pw_gls -- convert to ra & dec using global-sine projection +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_pw_gls (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double cosdec # cosine of object declination +int idec # which axis is declination axis + +begin + idec = W_DEC_AX(wcs) + if (idec > 0) + dec_r = eta_r + DEGTORAD (W_CRVAL(wcs,idec)) + else + dec_r = eta_r + + cosdec = cos (dec_r) + if (cosdec > 0.d0) + dra_r = xi_r / cosdec + else + dra_r = 0.d0 +end + +# xt_wp_stg -- convert from ra & dec using stereographic projection +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_wp_stg (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double cosdra, sindra # cos & sin of dra_r +double cosdec, sindec # cos & sin of object declination +double cosdist # cos of dist from ref pixel to object +double sincos # sin (theta) * cos (phi) + +begin + cosdra = cos (dra_r) + sindra = sin (dra_r) + + cosdec = cos (dec_r) + sindec = sin (dec_r) + + cosdist = sindec * W_SINDEC(wcs) + cosdec * W_COSDEC(wcs) * cosdra + sincos = sindec * W_COSDEC(wcs) - cosdec * W_SINDEC(wcs) * cosdra + + xi_r = 2.d0 * cosdec * sindra / (1.d0 + cosdist) + eta_r = 2.d0 * sincos / (1.d0 + cosdist) +end + + +# xt_pw_stg -- convert to ra & dec using stereographic projection + +procedure xt_pw_stg (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double rho2 # square of distance from reference pixel +double scale # factor to reduce xi, eta to y, z +double x, y, z # unit vector toward object +double temp + +begin + rho2 = xi_r * xi_r + eta_r * eta_r + + x = (4.d0 - rho2) / (4.d0 + rho2) + scale = (x + 1.d0) / 2.d0 + + y = xi_r * scale + z = eta_r * scale + + temp = x * W_COSDEC(wcs) - z * W_SINDEC(wcs) + z = x * W_SINDEC(wcs) + z * W_COSDEC(wcs) + x = temp + + if (x == 0.d0 && y == 0.d0) + dra_r = 0.d0 + else + dra_r = atan2 (y, x) + dec_r = atan2 (z, sqrt (x*x + y*y)) +end + + +# xt_wp_ait -- convert from ra & dec using Aitoff projection +# +# Note that the declination at the reference pixel is ignored and is +# assumed to be zero. The algorithms given in the AIPS reference do +# allow for a non-zero declination at the reference pixel. +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_wp_ait (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double z # temp variable +double cosdec # cosine of declination + +begin + cosdec = cos (dec_r) + z = sqrt ((1.d0 + cosdec * cos (dra_r/2.d0)) / 2.d0) + + xi_r = 2.d0 * cosdec * sin (dra_r/2.d0) / z + eta_r = sin (dec_r) / z +end + + +# xt_pw_ait -- convert to ra & dec using Aitoff projection +# +# Note that the declination at the reference pixel is ignored and is +# assumed to be zero. The algorithms given in the AIPS reference do +# allow for a non-zero declination at the reference pixel. +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_pw_ait (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- +double z # temp variable +double cosdec # cosine of declination + +begin + z = sqrt (1.d0 - xi_r*xi_r/16.d0 - eta_r*eta_r/4.d0) + + dec_r = asin (eta_r * z) + cosdec = cos (dec_r) + + if (cosdec > 0.d0) { + dra_r = 2.d0 * asin (xi_r * z / (2.d0 * cosdec)) + } else { + dra_r = 0.d0 + } +end + + +# xt_wp_mer -- convert from ra & dec using Mercator projection +# +# Note that the declination at the reference pixel is ignored and is +# assumed to be zero. The algorithms given in the AIPS reference do +# allow for a non-zero declination at the reference pixel. +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_wp_mer (wcs, dra_r, dec_r, xi_r, eta_r) + +pointer wcs # i: pointer to world coord system struct +double dra_r # i: RA of object - RA at reference pixel (radians) +double dec_r # i: declination of object (radians) +double xi_r # o: standard coordinate (radians) +double eta_r # o: standard coordinate (radians) +#-- +double temp + +begin + xi_r = dra_r + temp = (dec_r + HALFPI) / 2.d0 + if (temp >= HALFPI || temp <= 0.d0) + call error (1, "invalid declination for Mercator projection") + eta_r = log (tan (temp)) +end + + +# xt_pw_mer -- convert to ra & dec using Mercator projection +# +# Reference: AIPS Memo No. 46 by Eric W. Greisen + +procedure xt_pw_mer (wcs, xi_r, eta_r, dra_r, dec_r) + +pointer wcs # i: pointer to world coord system struct +double xi_r # i: standard coordinate (radians) +double eta_r # i: standard coordinate (radians) +double dra_r # o: RA of object - RA at reference pixel (radians) +double dec_r # o: declination of object (radians) +#-- + +begin + dra_r = xi_r + dec_r = 2.d0 * atan (exp (eta_r)) - HALFPI +end |