Changeset 10612
- Timestamp:
- Dec 10, 2006, 8:30:07 AM (19 years ago)
- Location:
- trunk/psModules
- Files:
-
- 3 edited
-
src/astrom/pmAstrometryWCS.c (modified) (17 diffs)
-
src/astrom/pmAstrometryWCS.h (modified) (3 diffs)
-
test/astrom/tap_pmAstrometryWCS.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/astrom/pmAstrometryWCS.c
r10606 r10612 7 7 * @author EAM, IfA 8 8 * 9 * @version $Revision: 1. 3$ $Name: not supported by cvs2svn $10 * @date $Date: 2006-12-10 04:14:45$9 * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2006-12-10 18:30:07 $ 11 11 * 12 12 * Copyright 2006 Institute for Astronomy, University of Hawaii … … 21 21 #include "pmAstrometryWCS.h" 22 22 23 // interpret header WCS (only handles traditional WCS for the moment) 24 // plateScale is nominal physical scale on tangent plane (radians / TPA physical units) 25 bool pmAstromReadWCS (pmFPA *fpa, pmChip *chip, psMetadata *header, double plateScale, bool isMosaic) 23 // the following functions support coordinate transformations direcly related to the FITS WCS 24 // keywords. The FITS WCS allows for only a single level of transformation, thus it is not 25 // appropriate for mosaic astrometry consisting of telescope distortion plus chip terms. 26 // Below, we support the Elixir convention of using two connected FITS headers to define two 27 // levels of coordinate transformation. In the pmFPA structure, the projection, distortion, 28 // and FPA-to-Chip transformations are carried independently. NOTE: The FITS WCS keywords do 29 // not represent a simply polynomial. Instead, they have no constant term, and the coordinates 30 // are corrected to a reference pixel before the polynomial transformation is applied. 31 32 static void pmAstromWCSFree (pmAstromWCS *wcs) 33 { 34 35 if (!wcs) 36 return; 37 psFree (wcs->trans); 38 } 39 40 pmAstromWCS *pmAstromWCSAlloc (int nXorder, int nYorder) 41 { 42 43 pmAstromWCS *wcs = (pmAstromWCS *) psAlloc(sizeof(pmAstromWCS)); 44 psMemSetDeallocator(wcs, (psFreeFunc) pmAstromWCSFree); 45 46 wcs->trans = psPlaneTransformAlloc (nXorder, nYorder); 47 48 memset (wcs->ctype1, 0, PM_ASTROM_WCS_TYPE_SIZE); 49 memset (wcs->ctype2, 0, PM_ASTROM_WCS_TYPE_SIZE); 50 return wcs; 51 } 52 53 bool pmAstromWCStoSky (psSphere *sky, pmAstromWCS *wcs, psPlane *chip) 54 { 55 56 if (chip == NULL) 57 return false; 58 if (sky == NULL) 59 return false; 60 if (wcs == NULL) 61 return false; 62 63 psPlane *Chip = psPlaneAlloc(); 64 psPlane *FP = psPlaneAlloc(); 65 66 Chip->x = chip->x - wcs->crpix1; 67 Chip->y = chip->y - wcs->crpix2; 68 69 psPlaneTransformApply (FP, wcs->trans, Chip); 70 psDeproject (sky, FP, wcs->toSky); // find the RA,DEC coord of the focal-plane coordinate 71 72 psFree (Chip); 73 psFree (FP); 74 return true; 75 } 76 77 bool pmAstromWCStoChip (psPlane *chip, pmAstromWCS *wcs, psSphere *sky) 78 { 79 80 if (chip == NULL) 81 return false; 82 if (sky == NULL) 83 return false; 84 if (wcs == NULL) 85 return false; 86 87 psError(PS_ERR_UNKNOWN, true, "not yet implemented: needs to invert the transformation"); 88 return false; 89 90 psPlane *Chip = psPlaneAlloc(); 91 psPlane *FP = psPlaneAlloc(); 92 93 psProject (FP, sky, wcs->toSky); // find the RA,DEC coord of the focal-plane coordinate 94 95 // I need the inverse of wcs->transform at this point 96 psPlaneTransformApply (Chip, wcs->trans, FP); 97 98 chip->x = Chip->x + wcs->crpix1; 99 chip->y = Chip->y + wcs->crpix2; 100 101 psFree (Chip); 102 psFree (FP); 103 return true; 104 } 105 106 // interpret header WCS keywords (only handles traditional WCS for the moment) 107 pmAstromWCS *pmAstromWCSfromHeader (psMetadata *header) 26 108 { 27 109 psProjectionType type; 28 psPlaneTransform *toFPA;29 110 bool status, pcKeys, cdKeys, isPoly; 30 float crval1, crval2, crpix1, crpix2, cdelt1, cdelt2;31 111 char name[16]; // used to store FITS keyword below (always < 8, so 16 should be safe!) 32 112 … … 35 115 if (!status) { 36 116 psLogMsg ("psastro", 2, "warning: no WCS metadata in header\n"); 37 return false;117 return NULL; 38 118 } 39 119 … … 51 131 if (type == PS_PROJ_NTYPE) { 52 132 psLogMsg ("psastro", 2, "warning: unknown projection type %s\n", ctype); 53 return false;133 return NULL; 54 134 } 55 135 … … 67 147 psError(PS_ERR_UNKNOWN, true, "missing both CDi_j and PC00i00j WCS terms"); 68 148 // XXX we could default here to RA, DEC, ROTANGLE 69 return false;149 return NULL; 70 150 } 71 151 if (isPoly && !pcKeys) { 72 152 psError(PS_ERR_UNKNOWN, true, "polynomial terms defined, but missing PC00i00j WCS terms"); 73 return false;153 return NULL; 74 154 if (fitOrder == 0) 75 155 fitOrder = 1; 76 156 if ((fitOrder > 3) || (fitOrder < 1)) { 77 157 psError(PS_ERR_UNKNOWN, true, "NPLYTERM value undefined: %d", fitOrder); 78 return false;158 return NULL; 79 159 } 80 160 } else { 81 161 fitOrder = 1; 82 162 } 163 164 pmAstromWCS *wcs = pmAstromWCSAlloc (fitOrder, fitOrder); 83 165 84 166 // construct a transformation from X,Y in pixels to L,M in pixels 85 167 // NOTE that the WCS keywords convert X,Y to degrees first (using cdelt1,2) 86 168 // and then define a transformation from degrees to degrees 87 psPlaneTransform *wcsTrans = psPlaneTransformAlloc (fitOrder, fitOrder); 88 89 crval1 = psMetadataLookupF32 (&status, header, "CRVAL1");90 crval2 = psMetadataLookupF32 (&status, header, "CRVAL2");91 crpix1 = psMetadataLookupF32 (&status, header, "CRPIX1");92 crpix2 = psMetadataLookupF32 (&status, header, "CRPIX2");169 170 wcs->crval1 = psMetadataLookupF32 (&status, header, "CRVAL1"); 171 wcs->crval2 = psMetadataLookupF32 (&status, header, "CRVAL2"); 172 wcs->crpix1 = psMetadataLookupF32 (&status, header, "CRPIX1"); 173 wcs->crpix2 = psMetadataLookupF32 (&status, header, "CRPIX2"); 174 wcs->toSky = psProjectionAlloc (wcs->crval1*PM_RAD_DEG, wcs->crval2*PM_RAD_DEG, PM_RAD_DEG, PM_RAD_DEG, type); 93 175 94 176 // test the CDELTi varient 95 177 if (pcKeys) { 96 cdelt1 = psMetadataLookupF32 (&status, header, "CDELT1");97 cdelt2 = psMetadataLookupF32 (&status, header, "CDELT2");178 wcs->cdelt1 = psMetadataLookupF32 (&status, header, "CDELT1"); 179 wcs->cdelt2 = psMetadataLookupF32 (&status, header, "CDELT2"); 98 180 99 181 // test the CROTAi varient: … … 101 183 double rotate = psMetadataLookupF32 (&status, header, "CROTA2"); 102 184 if (status) { 103 wcs Trans->x->coeff[1][0] = +cdelt1 * cos(rotate*PS_RAD_DEG); // == PC1_1104 wcs Trans->x->coeff[0][1] = -cdelt2 * sin(rotate*PS_RAD_DEG); // == PC1_2105 wcs Trans->y->coeff[1][0] = +cdelt1 * sin(rotate*PS_RAD_DEG); // == PC2_1106 wcs Trans->y->coeff[1][0] = +cdelt2 * cos(rotate*PS_RAD_DEG); // == PC2_2107 goto got_matrix;185 wcs->trans->x->coeff[1][0] = +wcs->cdelt1 * cos(rotate*PM_RAD_DEG); // == PC1_1 186 wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2 187 wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1 188 wcs->trans->y->coeff[1][0] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2 189 return wcs; 108 190 } 109 191 110 192 // test the PC00i00j varient: 111 wcs Trans->x->coeff[1][0] =cdelt1 * psMetadataLookupF32 (&status, header, "PC001001"); // == PC1_1112 wcs Trans->x->coeff[0][1] =cdelt2 * psMetadataLookupF32 (&status, header, "PC001002"); // == PC1_2113 wcs Trans->y->coeff[1][0] =cdelt1 * psMetadataLookupF32 (&status, header, "PC002001"); // == PC2_1114 wcs Trans->y->coeff[0][1] =cdelt2 * psMetadataLookupF32 (&status, header, "PC002002"); // == PC2_2193 wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF32 (&status, header, "PC001001"); // == PC1_1 194 wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF32 (&status, header, "PC001002"); // == PC1_2 195 wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF32 (&status, header, "PC002001"); // == PC2_1 196 wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF32 (&status, header, "PC002002"); // == PC2_2 115 197 116 198 if (isPoly) { 117 199 // Elixir-style polynomial terms 118 for (int i = 0; i < wcsTrans->x->nX; i++) { 119 for (int j = 0; j < wcsTrans->x->nX; j++) { 200 // XXX currently, Elixir/DVO cannot accept mixed orders 201 for (int i = 0; i < fitOrder; i++) { 202 for (int j = 0; j < fitOrder; j++) { 120 203 if (i + j < 2) 121 204 continue; … … 123 206 continue; 124 207 sprintf (name, "PCA1dX%1dY%1d", i, j); 125 wcsTrans->x->coeff[i][j] = pow(cdelt1, i) * pow(cdelt2, j) * psMetadataLookupF32 (&status, header, name); 208 wcs->trans->x->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF32 (&status, header, name); 209 sprintf (name, "PCA2dX%1dY%1d", i, j); 210 wcs->trans->y->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF32 (&status, header, name); 126 211 } 127 212 } 128 // XXX currently, Elixir/DVO cannot accept mixed orders 129 for (int i = 0; i < wcsTrans->y->nX; i++) { 130 for (int j = 0; j < wcsTrans->y->nX; j++) { 131 if (i + j < 2) 132 continue; 133 if (i + j > fitOrder) 134 continue; 135 sprintf (name, "PCA2dX%1dY%1d", i, j); 136 wcsTrans->y->coeff[i][j] = pow(cdelt1, i) * pow(cdelt2, j) * psMetadataLookupF32 (&status, header, name); 137 } 138 } 139 } 140 goto got_matrix; 213 } 214 return wcs; 141 215 } 142 216 143 217 // test the CDi_j varient 144 218 if (cdKeys) { 145 wcsTrans->x->coeff[1][0] = psMetadataLookupF32 (&status, header, "CD1_1"); // == PC1_1 146 wcsTrans->x->coeff[0][1] = psMetadataLookupF32 (&status, header, "CD1_2"); // == PC1_2 147 wcsTrans->y->coeff[1][0] = psMetadataLookupF32 (&status, header, "CD2_1"); // == PC2_1 148 wcsTrans->y->coeff[0][1] = psMetadataLookupF32 (&status, header, "CD2_2"); // == PC2_2 149 goto got_matrix; 219 wcs->cdelt1 = 1.0; 220 wcs->cdelt2 = 1.0; 221 wcs->trans->x->coeff[1][0] = psMetadataLookupF32 (&status, header, "CD1_1"); // == PC1_1 222 wcs->trans->x->coeff[0][1] = psMetadataLookupF32 (&status, header, "CD1_2"); // == PC1_2 223 wcs->trans->y->coeff[1][0] = psMetadataLookupF32 (&status, header, "CD2_1"); // == PC2_1 224 wcs->trans->y->coeff[0][1] = psMetadataLookupF32 (&status, header, "CD2_2"); // == PC2_2 225 return wcs; 150 226 } 151 227 psLogMsg ("psastro", 2, "warning: missing rotation matrix?\n"); 152 return false; 153 154 got_matrix: 228 return NULL; 229 } 230 231 // interpret header WCS (only handles traditional WCS for the moment) 232 // plateScale is nominal physical scale on tangent plane (radians / TPA physical units) 233 bool pmAstromReadWCS (pmFPA *fpa, pmChip *chip, psMetadata *header, double plateScale, bool isMosaic) 234 { 235 psPlaneTransform *toFPA; 236 237 pmAstromWCS *wcs = pmAstromWCSfromHeader (header); 238 if (!wcs) { 239 return false; 240 } 155 241 156 242 /* at this point, we have extracted from the header the WCS terms in the form of a polynomial, 157 * wcs Trans, which will convert X,Y in pixels to L,M in degrees. we also have the following243 * wcs->trans, which will convert X,Y in pixels to L,M in degrees. we also have the following 158 244 * elements defined: 159 245 * type (CTYPE) … … 163 249 * plateScale (radians / physical TPA units) 164 250 * 165 * now we convert wcs Trans to toFPA, which is different from wcsTrans in 3 important ways:251 * now we convert wcs->trans to toFPA, which is different from wcs->trans in 3 important ways: 166 252 * 1) the output is in pixel (not degrees): divide by cdelt1,2 raised to an appropriate power 167 253 * 2) X,Y are applied directly, without an applied Xo,Yo offset … … 169 255 */ 170 256 171 /*** XXXX need to extend these formulae to higher-order terms ***/ 172 173 // XXX free an existing toFPA? 257 // convert wcs->trans to a matrix which yields L,M in pixels 258 double cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]); 259 double cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]); 260 for (int i = 0; i <= wcs->trans->x->nX; i++) { 261 for (int j = 0; j <= wcs->trans->x->nX; j++) { 262 wcs->trans->x->coeff[i][j] /= cdelt1; 263 wcs->trans->y->coeff[i][j] /= cdelt2; 264 } 265 } 266 267 // validate fit order 268 int fitOrder = wcs->trans->x->nX; 174 269 toFPA = psPlaneTransformAlloc(fitOrder, fitOrder); 175 270 176 271 /* given two equivalent polynomial representations L(x,y) = \sum_i \sum_j A_{i,j} x^i y^j 177 * we can transform L(x,y) into L'(x +xo,y+yo) by taking the derivatives of both sides and272 * we can transform L(x,y) into L'(x-xo,y-yo) by taking the derivatives of both sides and 178 273 * noting that the constant term in each is the coefficient in the case of L(x,y) and is the 179 * value of L'( xo,yo) in the second case. in this case, xo,yo = crpix1,2274 * value of L'(-xo,-yo) in the second case. in this case, xo,yo = crpix1,2 180 275 */ 181 276 182 psPolynomial2D *xPx = psPolynomial2DCopy (NULL, wcsTrans->x); 183 psPolynomial2D *yPx = psPolynomial2DCopy (NULL, wcsTrans->y); 277 psPolynomial2D *tmp; 278 279 psPolynomial2D *xPx = psPolynomial2DCopy (NULL, wcs->trans->x); 280 psPolynomial2D *yPx = psPolynomial2DCopy (NULL, wcs->trans->y); 184 281 185 282 for (int i = 0; i <= fitOrder; i++) { … … 187 284 psPolynomial2D *yPy = psPolynomial2DCopy (NULL, yPx); 188 285 for (int j = 0; j <= fitOrder; j++) { 189 toFPA->x->mask[i][j] = wcsTrans->x->mask[i][j]; 190 toFPA->y->mask[i][j] = wcsTrans->y->mask[i][j]; 191 toFPA->x->coeff[i][j] = (toFPA->x->mask[i][j]) ? 0 : psPolynomial2DEval (xPy, crpix1, crpix2) / tgamma(i+1) / tgamma(j+1) / cdelt1; 192 toFPA->y->coeff[i][j] = (toFPA->y->mask[i][j]) ? 0 : psPolynomial2DEval (yPy, crpix1, crpix2) / tgamma(i+1) / tgamma(j+1) / cdelt2; 193 194 // take the next derivative wrt y 195 psPolynomial2D_dY(xPy, xPy); 196 psPolynomial2D_dY(yPy, yPy); 197 } 198 psFree (xPy); 199 psFree (yPy); 200 // take the next derivative wrt x 201 psPolynomial2D_dX(xPx, xPx); 202 psPolynomial2D_dX(yPx, yPx); 203 } 204 psFree (xPx); 205 psFree (yPx); 206 207 // save until we verify the transformation 208 # if (0) 209 // basic transformation from chip to FPA (FPA in pixels) 210 toFPA->x->coeff[0][0] = -(pc1_1*crpix1 + pc1_2*crpix2); 211 toFPA->x->coeff[1][0] = pc1_1; 212 toFPA->x->coeff[0][1] = pc1_2; 213 toFPA->x->mask[1][1] = 1; 214 215 toFPA->y->coeff[0][0] = -(pc2_1*crpix1 + pc2_2*crpix2); 216 toFPA->y->coeff[1][0] = pc2_1; 217 toFPA->y->coeff[0][1] = pc2_2; 218 toFPA->y->mask[1][1] = 1; 219 # endif 286 toFPA->x->mask[i][j] = wcs->trans->x->mask[i][j]; 287 toFPA->y->mask[i][j] = wcs->trans->y->mask[i][j]; 288 toFPA->x->coeff[i][j] = (toFPA->x->mask[i][j]) ? 0 : psPolynomial2DEval (xPy, -wcs->crpix1, -wcs->crpix2) / tgamma(i+1) / tgamma(j+1); 289 toFPA->y->coeff[i][j] = (toFPA->y->mask[i][j]) ? 0 : psPolynomial2DEval (yPy, -wcs->crpix1, -wcs->crpix2) / tgamma(i+1) / tgamma(j+1); 290 291 // take the next derivative wrt y, catch output (is NULL on last pass) 292 tmp = psPolynomial2D_dY(NULL, xPy); 293 psFree (xPy); 294 xPy = tmp; 295 tmp = psPolynomial2D_dY(NULL, yPy); 296 psFree (yPy); 297 yPy = tmp; 298 } 299 // take the next derivative wrt x, catch output (is NULL on last pass) 300 tmp = psPolynomial2D_dX(NULL, xPx); 301 psFree (xPx); 302 xPx = tmp; 303 tmp = psPolynomial2D_dX(NULL, yPx); 304 psFree (yPx); 305 yPx = tmp; 306 } 220 307 221 308 // scale from FPA to TPA (microns / pixel) 222 double pdelt1 = cdelt1*P S_RAD_DEG / plateScale;223 double pdelt2 = cdelt2*P S_RAD_DEG / plateScale;309 double pdelt1 = cdelt1*PM_RAD_DEG / plateScale; 310 double pdelt2 = cdelt2*PM_RAD_DEG / plateScale; 224 311 float rX = 1.0; 225 312 float rY = 1.0; 226 313 227 314 // projection from TPA to SKY 228 psProjection *toSky = psProjectionAlloc ( crval1*PS_RAD_DEG, crval2*PS_RAD_DEG, plateScale, plateScale,type);315 psProjection *toSky = psProjectionAlloc (wcs->toSky->R, wcs->toSky->D, plateScale, plateScale, wcs->toSky->type); 229 316 230 317 if (fpa->toSky == NULL) { … … 263 350 psPlaneTransformApply (fp, toFPA, chip); // find the focal-plane coordinate of this chip's 0,0 coordinate 264 351 psPlaneDistortApply (tp, fpa->toTPA, fp, 0.0, 0.0); 265 p _psDeproject (sky, tp, toSky); // find the RA,DEC coord of the focal-plane coordinate266 p _psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection352 psDeproject (sky, tp, toSky); // find the RA,DEC coord of the focal-plane coordinate 353 psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection 267 354 psPlaneDistortApply (fp, fpa->fromTPA, tp, 0.0, 0.0); 268 355 … … 309 396 chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]); 310 397 311 psLogMsg ("psastro", 3, "field center: %f,%f, plate scale: %f,%f (arcsec/pixel)\n", 312 PS_DEG_RAD*fpa->toSky->R, PS_DEG_RAD*fpa->toSky->D, 313 3600*PS_DEG_RAD*fpa->toSky->Xs, 3600*PS_DEG_RAD*fpa->toSky->Ys); 314 315 psFree (wcsTrans); 398 psFree (wcs->trans); 316 399 317 400 return true; … … 373 456 374 457 // solve for CDELT1,2 (degrees / pixel) 375 cdelt1 = P S_DEG_RAD*toSky->Xs*toTPA->x->coeff[1][0][0][0];376 cdelt2 = P S_DEG_RAD*toSky->Ys*toTPA->y->coeff[0][1][0][0];458 cdelt1 = PM_DEG_RAD*toSky->Xs*toTPA->x->coeff[1][0][0][0]; 459 cdelt2 = PM_DEG_RAD*toSky->Ys*toTPA->y->coeff[0][1][0][0]; 377 460 378 461 // L,M = toFPA(X,Y) … … 445 528 coords[0].crval1 -= 360.0; 446 529 447 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*P S_DEG_RAD);448 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*P S_DEG_RAD);530 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*PM_DEG_RAD); 531 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*PM_DEG_RAD); 449 532 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", Xo); 450 533 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", Yo); … … 477 560 # else 478 561 479 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*P S_DEG_RAD);480 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*P S_DEG_RAD);562 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*PM_DEG_RAD); 563 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*PM_DEG_RAD); 481 564 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", toFPA->x->coeff[0][0]); 482 565 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", toFPA->y->coeff[0][0]); 483 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*P S_DEG_RAD*plateScale);484 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*P S_DEG_RAD*plateScale);566 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*PM_DEG_RAD*plateScale); 567 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*PM_DEG_RAD*plateScale); 485 568 486 569 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", toFPA->x->coeff[1][0]/plateScale); … … 566 649 567 650 // XXX need to handle the plateScale?? 568 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*P S_DEG_RAD);569 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*P S_DEG_RAD);651 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*PM_DEG_RAD); 652 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*PM_DEG_RAD); 570 653 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", 0.0); 571 654 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", 0.0); 572 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*P S_DEG_RAD*plateScale);573 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*P S_DEG_RAD*plateScale);655 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*PM_DEG_RAD*plateScale); 656 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*PM_DEG_RAD*plateScale); 574 657 575 658 if (toTP->x->nX != toTP->x->nY) … … 738 821 *****/ 739 822 823 824 // save until we verify the transformation 825 # if (0) 826 // basic transformation from chip to FPA (FPA in pixels) 827 toFPA->x->coeff[0][0] = -(pc1_1*crpix1 + pc1_2*crpix2); 828 toFPA->x->coeff[1][0] = pc1_1; 829 toFPA->x->coeff[0][1] = pc1_2; 830 toFPA->x->mask[1][1] = 1; 831 832 toFPA->y->coeff[0][0] = -(pc2_1*crpix1 + pc2_2*crpix2); 833 toFPA->y->coeff[1][0] = pc2_1; 834 toFPA->y->coeff[0][1] = pc2_2; 835 toFPA->y->mask[1][1] = 1; 836 # endif 837 -
trunk/psModules/src/astrom/pmAstrometryWCS.h
r10603 r10612 7 7 * @author EAM, IfA 8 8 * 9 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $10 * @date $Date: 2006-12-10 02:06:47 $9 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2006-12-10 18:30:07 $ 11 11 * 12 12 * Copyright 2006 Institute for Astronomy, University of Hawaii … … 15 15 #ifndef PM_ASTROMETRY_WCS_H 16 16 #define PM_ASTROMETRY_WCS_H 17 18 #define PM_ASTROM_WCS_TYPE_SIZE 80 19 typedef struct 20 { 21 char ctype1[PM_ASTROM_WCS_TYPE_SIZE]; 22 char ctype2[PM_ASTROM_WCS_TYPE_SIZE]; 23 double crval1, crval2; 24 double crpix1, crpix2; 25 double cdelt1, cdelt2; 26 psProjection *toSky; 27 psPlaneTransform *trans; 28 } 29 pmAstromWCS; 30 31 pmAstromWCS *pmAstromWCSAlloc (int nXorder, int nYorder); 32 bool pmAstromWCStoSky (psSphere *sky, pmAstromWCS *wcs, psPlane *chip); 33 bool pmAstromWCStoChip (psPlane *chip, pmAstromWCS *wcs, psSphere *sky); 34 pmAstromWCS *pmAstromWCSfromHeader (psMetadata *header); 17 35 18 36 bool pmAstromReadWCS (pmFPA *fpa, pmChip *chip, psMetadata *header, double plateScale, bool isMosaic); … … 25 43 bool psPlaneDistortIsIdentity (psPlaneDistort *distort); 26 44 27 # define P S_DEG_RAD 57.29577951308232228 # define P S_RAD_DEG 0.01745329251994345 # define PM_DEG_RAD 57.295779513082322 46 # define PM_RAD_DEG 0.017453292519943 29 47 30 48 #endif // PM_ASTROMETRY_WCS_H 49 50 /* 51 * the wcs->trans component defines a polynomial which converts (x-crpix1),(y-crpix2) to 52 * L,M in degrees 53 */ -
trunk/psModules/test/astrom/tap_pmAstrometryWCS.c
r10606 r10612 83 83 } 84 84 85 { 86 diag("test pmAstromReadWCS"); 87 psMemId id = psMemGetId(); 88 89 psPlaneTransform *wcsTrans = psPlaneTransformAlloc (1, 1); 90 wcsTrans->x->coeff[0][0] = 0.0; 91 wcsTrans->y->coeff[0][0] = 0.0; 92 wcsTrans->x->coeff[1][0] = 1.0; 93 wcsTrans->x->coeff[0][1] = 0.0; 94 wcsTrans->y->coeff[1][0] = 0.0; 95 wcsTrans->y->coeff[0][1] = 1.0; 96 97 98 99 // construct a header with a simple set of WCS values 100 // convert to pmFPA components and check 101 102 psMetadata *header = psMetadataAlloc(); 103 104 psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", "RA---TAN"); 105 psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", "DEC--TAN"); 106 107 // center coords (R,D) 108 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", 0.0); 109 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", 0.0); 110 111 // center coords (X,Y) 112 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", 10.0); 113 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", 10.0); 114 115 // degrees per pixel 116 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", 1.0/3600.0); 117 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", 1.0/3600.0); 118 119 // rotation matrix 120 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", 1.0); 121 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", 0.0); 122 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", 0.0); 123 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", 1.0); 124 125 pmFPA *fpa = pmFPAAlloc (NULL); 126 pmChip *chip = pmChipAlloc (NULL, "test"); 127 128 // toFPA carries pixel scale (pixels per micron) 129 // toTPA carries plate scale (microns per arcsecond) 130 bool status = pmAstromReadWCS (fpa, chip, header, 25.0*PS_RAD_DEG/3600.0, false); 131 ok (status, "converted WCS keywords to FPA astrometry"); 132 skip_start (!status, 1, "*** WCS Conversion FAILS *** : skipping related tests"); 133 134 ok(fpa->toSky->type == PS_PROJ_TAN, "correct projection (TAN)"); 135 136 // make these tests double 137 ok_float(fpa->toSky->R*PS_DEG_RAD, 0.0, "projection center RA %f", fpa->toSky->R*PS_DEG_RAD); 138 ok_float(fpa->toSky->R*PS_DEG_RAD, 0.0, "projection center DEC %f", fpa->toSky->R*PS_DEG_RAD); 139 140 ok_float(fpa->toSky->Xs, 25.0*PS_RAD_DEG/3600.0, "projection X scale %f", fpa->toSky->Xs); 141 ok_float(fpa->toSky->Ys, 25.0*PS_RAD_DEG/3600.0, "projection X scale %f", fpa->toSky->Ys); 142 143 ok_float(fpa->toTPA->x->coeff[1][0][0][0], 0.04, "TP scale (mm per pixel): %f", fpa->toTPA->x->coeff[1][0][0][0]); 144 ok_float(fpa->toTPA->y->coeff[0][1][0][0], 0.04, "TP scale (mm per pixel): %f", fpa->toTPA->x->coeff[1][0][0][0]); 145 146 ok_float(chip->toFPA->x->coeff[0][0], -10.0, "ref pixel X: %f", chip->toFPA->x->coeff[0][0]); 147 ok_float(chip->toFPA->y->coeff[0][0], -10.0, "ref pixel Y: %f", chip->toFPA->y->coeff[0][0]); 148 149 ok_float(chip->toFPA->x->coeff[1][0], 1.0, "CD1_1: %f", chip->toFPA->x->coeff[1][0]); 150 ok_float(chip->toFPA->x->coeff[0][1], 0.0, "CD1_2: %f", chip->toFPA->x->coeff[0][1]); 151 ok_float(chip->toFPA->y->coeff[1][0], 0.0, "CD2_1: %f", chip->toFPA->y->coeff[1][0]); 152 ok_float(chip->toFPA->y->coeff[0][1], 1.0, "CD2_2: %f", chip->toFPA->y->coeff[0][1]); 153 154 // apply both systems to real data: 155 156 157 psFree (fpa); 158 psFree (chip); 159 psFree (header); 160 161 skip_end(); 162 ok(!psMemCheckLeaks (id, NULL, stderr, false), "no memory leaks"); 163 } 164 85 165 return exit_status(); 86 166 }
Note:
See TracChangeset
for help on using the changeset viewer.
