Changeset 7332 for trunk/psastro/src/psastroWCS.c
- Timestamp:
- Jun 4, 2006, 7:02:16 AM (20 years ago)
- File:
-
- 1 edited
-
trunk/psastro/src/psastroWCS.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psastro/src/psastroWCS.c
r7014 r7332 3 3 // interpret header WCS (only handles traditional WCS for the moment) 4 4 // plateScale is nominal physical scale on tangent plane (microns / arcsecond) 5 bool pmAstromReadWCS (psProjection **toSkyOut, psPlaneDistort **toTPAout, psPlaneTransform **toFPAout, psMetadata *header, double plateScale) { 6 7 psPlaneTransform *toFPA; 8 psPlaneDistort *toTPA; 9 psProjection *toSky; 5 bool pmAstromReadWCS (pmFPA *fpa, pmChip *chip, psMetadata *header, double plateScale, bool isMosaic) { 6 10 7 psProjectionType type; 11 8 bool status; … … 13 10 float pc1_1, pc1_2, pc2_1, pc2_2; 14 11 15 // ***interpret header data, convert to crval(i), etc12 // interpret header data, convert to crval(i), etc 16 13 char *ctype = psMetadataLookupPtr (&status, header, "CTYPE2"); 17 14 if (!status) { … … 88 85 got_matrix: 89 86 90 // XXX EAM : if fpa->toSky and fpa->toTPA are already defined, then the 91 // toFPA must be modified to match the crval(i), scale(i) and crpix(i) 92 // scale = scale(i)/scale(0) (i == chip #) 93 // project crval1(0),crval2(0 using projection 94 toFPA = psPlaneTransformAlloc (1, 1); 87 /***** 88 89 For mosaic astrometry, we need to have a starting set of projection terms in which the 90 chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or 91 microns). This set of projections, coupled with an identity toTPA (ie, no distortion) will 92 result in substantial errors between the observed and predicted star positions on the focal 93 plane: this is the measurement of the optical distortion in the camera. At the same time, 94 we need to carry around the transformations which allow us to make an accurate calculation 95 of the position of the stars based on the input (per-chip) astrometry. These 96 transformations will allow us to match the raw and ref stars robustly. To convert the 97 per-chip astrometry (which may have been calculated with a different plate scale for each 98 chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust 99 the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for 100 each chip (eg, cdelt1). Thus, we need to carry around both the 101 102 *****/ 103 104 { 105 double rX = 1.0; 106 double rY = 1.0; 107 108 // XXX free an existing toFPA? 109 psPlaneTransform *toFPA = psPlaneTransformAlloc (1, 1); 95 110 96 double cdelt = hypot (cdelt1, cdelt2) / plateScale; // degrees / micron (eg, in fact, whatever unit user chooses for focal plane) 97 cdelt1 /= cdelt; 98 cdelt2 /= cdelt; 99 100 toFPA->x->coeff[0][0] = -(pc1_1*cdelt1*crpix1 + pc1_2*cdelt2*crpix2); 101 toFPA->x->coeff[1][0] = +(pc1_1*cdelt1); 102 toFPA->x->coeff[0][1] = +(pc1_2*cdelt2); 103 toFPA->x->mask[1][1] = 1; 104 105 toFPA->y->coeff[0][0] = -(pc2_1*cdelt1*crpix1 + pc2_2*cdelt2*crpix2); 106 toFPA->y->coeff[1][0] = +(pc2_1*cdelt1); 107 toFPA->y->coeff[0][1] = +(pc2_2*cdelt2); 108 toFPA->y->mask[1][1] = 1; 109 *toFPAout = toFPA; 110 111 if (*toSkyOut != NULL) { 112 if (*toTPAout == NULL) psAbort ("wcs", "projection defined, tangent-plane not defined"); 113 114 psSphere sky; 115 psPlane tpa; 116 117 sky.r = crval1*RAD_DEG; 118 sky.d = crval2*RAD_DEG; 119 p_psProject (&tpa, &sky, *toSkyOut); 111 // basic transformation from chip to FPA 112 toFPA->x->coeff[0][0] = -(pc1_1*crpix1 + pc1_2*crpix2); 113 toFPA->x->coeff[1][0] = pc1_1; 114 toFPA->x->coeff[0][1] = pc1_2; 115 toFPA->x->mask[1][1] = 1; 116 117 toFPA->y->coeff[0][0] = -(pc2_1*crpix1 + pc2_2*crpix2); 118 toFPA->y->coeff[1][0] = pc2_1; 119 toFPA->y->coeff[0][1] = pc2_2; 120 toFPA->y->mask[1][1] = 1; 121 122 // projection from TPA to SKY 123 psProjection *toSky = psProjectionAlloc (crval1*RAD_DEG, crval2*RAD_DEG, cdelt1*RAD_DEG, cdelt2*RAD_DEG, type); 124 125 if (fpa->toSky == NULL) { 126 // XXX for now, use the identity for TPA <--> FPA 127 fpa->toTangentPlane = psPlaneDistortIdentity (1); 128 fpa->fromTangentPlane = psPlaneDistortIdentity (1); 129 fpa->toSky = toSky; 130 } else { 131 if (fpa->toTangentPlane == NULL) psAbort ("wcs", "projection defined, tangent-plane not defined"); 132 if (fpa->fromTangentPlane == NULL) psAbort ("wcs", "projection defined, tangent-plane not defined"); 133 134 // adjust for common toSky for mosaic: 135 // ignore the TPA since toTPA is identity 136 // find the FPA coordinate of 0,0 for this chip. 137 psPlane *fp = psPlaneAlloc(); 138 psPlane *chip = psPlaneAlloc(); 139 psSphere *sky = psSphereAlloc(); 140 chip->x = chip->y = 0; 120 141 121 // XXX for the moment, assume toTPA is the identity transformation 122 toFPA->x->coeff[0][0] = tpa.x; 123 toFPA->y->coeff[0][0] = tpa.y; 124 } else { 125 // XXX for now, use the identity for TPA <--> FPA 126 toTPA = psPlaneDistortIdentity (); 127 128 // center of projection is (0,0) coordinate of TPA 129 toSky = psProjectionAlloc (crval1*RAD_DEG, crval2*RAD_DEG, RAD_DEG*cdelt, RAD_DEG*cdelt, type); 130 131 *toTPAout = toTPA; 132 *toSkyOut = toSky; 142 psPlaneTransformApply (fp, toFPA, chip); // find the focal-plane coordinate of this chip's 0,0 coordinate 143 p_psDeproject (sky, fp, toSky); // find the RA,DEC coord of the focal-plane coordinate 144 p_psProject (fp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection 145 146 toFPA->x->coeff[0][0] = fp->x; 147 toFPA->y->coeff[0][0] = fp->y; 148 149 rX = toSky->Xs/fpa->toSky->Xs; 150 rY = toSky->Ys/fpa->toSky->Ys; 151 152 // correct to common plate scale 153 toFPA->x->coeff[1][0] *= rX; 154 toFPA->x->coeff[0][1] *= rX; 155 toFPA->y->coeff[1][0] *= rY; 156 toFPA->y->coeff[0][1] *= rY; 157 158 psFree (fp); 159 psFree (sky); 160 psFree (chip); 161 psFree (toSky); 162 } 163 164 chip->toFPA = toFPA; 165 chip->fromFPA = p_psPlaneTransformLinearInvert(toFPA); 166 167 // remove the correction to the common plate scale 168 if (isMosaic) { 169 chip->toFPA->x->coeff[1][0] /= rX; 170 chip->toFPA->x->coeff[0][1] /= rX; 171 chip->toFPA->y->coeff[1][0] /= rY; 172 chip->toFPA->y->coeff[0][1] /= rY; 173 } 174 175 fprintf (stderr, "toFPA: %f %f (%f,%f),(%f,%f)\n", 176 chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0], 177 chip->toFPA->x->coeff[1][0], chip->toFPA->x->coeff[0][1], 178 chip->toFPA->y->coeff[1][0], chip->toFPA->y->coeff[0][1]); 179 180 fprintf (stderr, "frFPA: %f %f (%f,%f),(%f,%f)\n", 181 chip->fromFPA->x->coeff[0][0], chip->fromFPA->y->coeff[0][0], 182 chip->fromFPA->x->coeff[1][0], chip->fromFPA->x->coeff[0][1], 183 chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]); 184 185 fprintf (stderr, "field: %f,%f %f,%f\n", 186 DEG_RAD*fpa->toSky->R, DEG_RAD*fpa->toSky->D, 187 3600*DEG_RAD*fpa->toSky->Xs, 3600*DEG_RAD*fpa->toSky->Ys); 188 133 189 } 134 190 return true; 135 191 } 136 137 192 138 193 // convert toFPA / toSky components to traditional WCS … … 169 224 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", toFPA->x->coeff[0][0]); 170 225 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", toFPA->y->coeff[0][0]); 171 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*DEG_RAD );172 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*DEG_RAD );173 174 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", toFPA->x->coeff[1][0] );175 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", toFPA->x->coeff[0][1] );176 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", toFPA->y->coeff[1][0] );177 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", toFPA->y->coeff[0][1] );226 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*DEG_RAD*plateScale); 227 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*DEG_RAD*plateScale); 228 229 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", toFPA->x->coeff[1][0]/plateScale); 230 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", toFPA->x->coeff[0][1]/plateScale); 231 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", toFPA->y->coeff[1][0]/plateScale); 232 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", toFPA->y->coeff[0][1]/plateScale); 178 233 179 234 // alternative representations use … … 184 239 } 185 240 186 psPlaneDistort *psPlaneDistortIdentity () { 241 // convert toFPA / toSky components to traditional WCS 242 // plateScale is nominal physical scale on tangent plane (microns / arcsecond) 243 bool pmAstromWriteBilevelChip (psPlaneTransform *toFPA, psMetadata *header, double plateScale) { 244 245 psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", "RA---WRP"); 246 psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", "DEC--WRP"); 247 248 // XXX not really right: needs to deal with non-identity toTP coeffs & plateScale 249 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toFPA->x->coeff[0][0]); 250 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toFPA->y->coeff[0][0]); 251 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", 0.0); 252 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", 0.0); 253 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", 1.0); 254 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", 1.0); 255 256 if (toFPA->x->nX != toFPA->x->nY) psAbort ("psastro", "mis-matched tangent plane orders (1)"); 257 if (toFPA->x->nX != toFPA->y->nX) psAbort ("psastro", "mis-matched tangent plane orders (2)"); 258 if (toFPA->x->nX != toFPA->y->nY) psAbort ("psastro", "mis-matched tangent plane orders (3)"); 259 260 switch (toFPA->x->nX) { 261 case 3: 262 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X3Y0", PS_META_REPLACE, "", toFPA->x->coeff[3][0]); 263 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y1", PS_META_REPLACE, "", toFPA->x->coeff[2][1]); 264 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y2", PS_META_REPLACE, "", toFPA->x->coeff[1][2]); 265 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y3", PS_META_REPLACE, "", toFPA->x->coeff[0][3]); 266 267 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X3Y0", PS_META_REPLACE, "", toFPA->y->coeff[3][0]); 268 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y1", PS_META_REPLACE, "", toFPA->y->coeff[2][1]); 269 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y2", PS_META_REPLACE, "", toFPA->y->coeff[1][2]); 270 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y3", PS_META_REPLACE, "", toFPA->y->coeff[0][3]); 271 272 case 2: 273 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y0", PS_META_REPLACE, "", toFPA->x->coeff[2][0]); 274 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y1", PS_META_REPLACE, "", toFPA->x->coeff[1][1]); 275 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y2", PS_META_REPLACE, "", toFPA->x->coeff[0][2]); 276 277 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y0", PS_META_REPLACE, "", toFPA->y->coeff[2][0]); 278 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y1", PS_META_REPLACE, "", toFPA->y->coeff[1][1]); 279 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y2", PS_META_REPLACE, "", toFPA->y->coeff[0][2]); 280 281 case 1: 282 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", toFPA->x->coeff[1][0]/plateScale); 283 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", toFPA->x->coeff[0][1]/plateScale); 284 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", toFPA->y->coeff[1][0]/plateScale); 285 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", toFPA->y->coeff[0][1]/plateScale); 286 break; 287 288 case 0: 289 psAbort ("psastro", "invalid tangent plane order"); 290 } 291 return true; 292 } 293 294 // convert toFPA / toSky components to traditional WCS 295 // plateScale is nominal physical scale on tangent plane (microns / arcsecond) 296 psMetadata *pmAstromWriteBilevelMosaic (psProjection *toSky, psPlaneDistort *toTP, double plateScale) { 297 298 psMetadata *header = psMetadataAlloc (); 299 300 psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE1", PS_META_REPLACE, "", "RA---DIS"); 301 psMetadataAddStr (header, PS_LIST_TAIL, "CTYPE2", PS_META_REPLACE, "", "DEC--DIS"); 302 303 // XXX need to handle the plateScale?? 304 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL1", PS_META_REPLACE, "", toSky->R*DEG_RAD); 305 psMetadataAddF32 (header, PS_LIST_TAIL, "CRVAL2", PS_META_REPLACE, "", toSky->D*DEG_RAD); 306 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", 0.0); 307 psMetadataAddF32 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", 0.0); 308 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", toSky->Xs*DEG_RAD*plateScale); 309 psMetadataAddF32 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", toSky->Ys*DEG_RAD*plateScale); 310 311 if (toTP->x->nX != toTP->x->nY) psAbort ("psastro", "mis-matched tangent plane orders (1)"); 312 if (toTP->x->nX != toTP->y->nX) psAbort ("psastro", "mis-matched tangent plane orders (2)"); 313 if (toTP->x->nX != toTP->y->nY) psAbort ("psastro", "mis-matched tangent plane orders (3)"); 314 315 switch (toTP->x->nX) { 316 case 3: 317 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X3Y0", PS_META_REPLACE, "", toTP->x->coeff[3][0][0][0]); 318 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y1", PS_META_REPLACE, "", toTP->x->coeff[2][1][0][0]); 319 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y2", PS_META_REPLACE, "", toTP->x->coeff[1][2][0][0]); 320 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y3", PS_META_REPLACE, "", toTP->x->coeff[0][3][0][0]); 321 322 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X3Y0", PS_META_REPLACE, "", toTP->y->coeff[3][0][0][0]); 323 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y1", PS_META_REPLACE, "", toTP->y->coeff[2][1][0][0]); 324 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y2", PS_META_REPLACE, "", toTP->y->coeff[1][2][0][0]); 325 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y3", PS_META_REPLACE, "", toTP->y->coeff[0][3][0][0]); 326 327 case 2: 328 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X2Y0", PS_META_REPLACE, "", toTP->x->coeff[2][0][0][0]); 329 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X1Y1", PS_META_REPLACE, "", toTP->x->coeff[1][1][0][0]); 330 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA1X0Y2", PS_META_REPLACE, "", toTP->x->coeff[0][2][0][0]); 331 332 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X2Y0", PS_META_REPLACE, "", toTP->y->coeff[2][0][0][0]); 333 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X1Y1", PS_META_REPLACE, "", toTP->y->coeff[1][1][0][0]); 334 psMetadataAddF32 (header, PS_LIST_TAIL, "PCA2X0Y2", PS_META_REPLACE, "", toTP->y->coeff[0][2][0][0]); 335 336 case 1: 337 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", toTP->x->coeff[1][0][0][0]); 338 psMetadataAddF32 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", toTP->x->coeff[0][1][0][0]); 339 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", toTP->y->coeff[1][0][0][0]); 340 psMetadataAddF32 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", toTP->y->coeff[0][1][0][0]); 341 break; 342 343 case 0: 344 psAbort ("psastro", "invalid tangent plane order"); 345 } 346 return header; 347 } 348 349 // XXX for the moment, we mimic the limited Elixir mosastro orders 350 psPlaneDistort *psPlaneDistortIdentity (int order) { 187 351 188 352 psPlaneDistort *distort; 189 353 190 distort = psPlaneDistortAlloc (1, 1, 0, 0); 191 distort->x->coeff[0][0][0][0] = 0; 354 if (order < 1) psAbort ("psastro", "invalid order"); 355 if (order > 3) psAbort ("psastro", "invalid order"); 356 357 // all coeffs and masks initially set to 0 358 distort = psPlaneDistortAlloc (order, order, 0, 0); 359 360 for (int i = 0; i <= order; i++) { 361 for (int j = 0; j <= order; j++) { 362 if (i + j > order) { 363 distort->x->mask [1][1][0][0] = 1; 364 distort->y->mask [1][1][0][0] = 1; 365 } 366 } 367 } 192 368 distort->x->coeff[1][0][0][0] = 1; 193 distort->x->coeff[0][1][0][0] = 0;194 distort->x->mask [1][1][0][0] = 1;195 196 distort->y->coeff[0][0][0][0] = 0;197 distort->y->coeff[1][0][0][0] = 0;198 369 distort->y->coeff[0][1][0][0] = 1; 199 distort->y->mask [1][1][0][0] = 1;200 370 201 371 return distort;
Note:
See TracChangeset
for help on using the changeset viewer.
