Changeset 39926 for trunk/psModules
- Timestamp:
- Jan 6, 2017, 11:30:10 AM (10 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
-
. (modified) (1 prop)
-
psModules/src/astrom/pmAstrometryDistortion.c (modified) (1 diff)
-
psModules/src/astrom/pmAstrometryModel.c (modified) (4 diffs)
-
psModules/src/astrom/pmAstrometryObjects.c (modified) (9 diffs)
-
psModules/src/astrom/pmAstrometryObjects.h (modified) (2 diffs)
-
psModules/src/astrom/pmAstrometryWCS.c (modified) (42 diffs)
-
psModules/src/detrend/pmFringeStats.c (modified) (1 diff)
-
psModules/src/objects/pmPCM_MinimizeChisq.c (modified) (5 diffs)
-
psModules/src/objects/pmSourceIO_MatchedRefs.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to
/branches/czw_branch/20160809 merged eligible
-
Property svn:mergeinfo
set to
-
trunk/psModules/src/astrom/pmAstrometryDistortion.c
r23989 r39926 335 335 336 336 psFree (fpa->fromTPA); 337 fpa->fromTPA = psPlaneTransformInvert(NULL, fpa->toTPA, *region, 50); 337 psPlaneTransform *myPT = psPlaneTransformAlloc(fpa->toTPA->x->nX+4, fpa->toTPA->x->nY+4); 338 fpa->fromTPA = psPlaneTransformInvert(myPT, fpa->toTPA, *region, 50); 339 psFree (myPT); 338 340 psFree (region); 339 341 -
trunk/psModules/src/astrom/pmAstrometryModel.c
r36834 r39926 320 320 // the PosZero is the offset between the reported and actual POSANGLE values 321 321 float PosZero = psMetadataLookupF32 (&status, file->fpa->concepts, "FPA.POS_ZERO"); /// XXX be consistent with degrees v radians 322 // Indicate which direction the position angle goes 323 int rotParity = psMetadataLookupS32 (&status, file->fpa->concepts, "FPA.ROT_PARITY"); 322 324 char *refChip = psMetadataLookupStr (&status, file->fpa->concepts, "FPA.REF.CHIP"); 323 325 … … 349 351 350 352 psMetadataAddF32(row, PS_LIST_TAIL, "POS_ZERO", PS_META_REPLACE, "POSANGLE offset (degrees)", PosZero); 353 psMetadataAddS32(row, PS_LIST_TAIL, "ROT_PARITY", PS_META_REPLACE, "rotator parity", rotParity); 351 354 psMetadataAddStr(row, PS_LIST_TAIL, "REF_CHIP", PS_META_REPLACE, "reference chip for model", refChip); 352 355 … … 624 627 TRANSFER (file->fpa->concepts, row, "BORE_P0"); 625 628 TRANSFER (file->fpa->concepts, row, "POS_ZERO"); 629 TRANSFER (file->fpa->concepts, row, "ROT_PARITY"); 626 630 TRANSFER (file->fpa->concepts, row, "REF_CHIP"); 627 631 … … 687 691 char *refChip = psMetadataLookupStr(&status, file->fpa->concepts, "REF_CHIP"); REQUIRE (status, "missing REF_CHIP"); 688 692 693 int rotatorParity = psMetadataLookupS32(&status, file->fpa->concepts, "ROT_PARITY"); REQUIRE (status, "missing ROT_PARITY"); 694 689 695 // XXX we've swapped the sign and parity of POS (add to model) 690 696 // apply true posangle = -(POS - POS_ZERO) 691 697 psLogMsg ("psModules.astrom", 4, "Position Angle: %f, Model Position Angle Zero Point: %f\n", POS, PosZero); 692 psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, file->fpa->fromTPA, (PosZero - POS));698 psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, file->fpa->fromTPA, rotatorParity * (PosZero - POS)); 693 699 psFree (file->fpa->fromTPA); 694 700 file->fpa->fromTPA = fromTPA; -
trunk/psModules/src/astrom/pmAstrometryObjects.c
r36834 r39926 225 225 psArray *ref, 226 226 psArray *match, 227 psStats *stats) 227 psStats *stats, 228 const psMetadata *config) 228 229 { 229 230 PS_ASSERT_PTR_NON_NULL(map, NULL); … … 232 233 PS_ASSERT_PTR_NON_NULL(match, NULL); 233 234 PS_ASSERT_PTR_NON_NULL(stats, NULL); 235 PS_ASSERT_PTR_NON_NULL(config, NULL); 236 237 // sigma of gaussian window to down-weight photometric outliers (ignored if NAN or 0.0) 238 bool status; 239 double photomWindowSigma = psMetadataLookupF32 (&status, config, "PSASTRO.PHOTOM.WINDOW.SIGMA"); 240 bool photomWindowApply = !(isnan(photomWindowSigma) || (fabs(photomWindowSigma) < 0.01)); 241 double photomWindowFactor = photomWindowApply ? -0.5/PS_SQR(photomWindowSigma) : 0.0; 234 242 235 243 // reassign values for clip fit … … 252 260 y->data.F32[i] = refStar->FP->y; 253 261 254 wt->data.F32[i] = 1.0; 262 // wt is used as an error (sqrt(variance)) in the fit. the 1.01 prevents the weight from going to 0.0 for perfect matches 263 wt->data.F32[i] = 1.01 - exp(photomWindowFactor*PS_SQR(refStar->magCal - rawStar->magCal)); 255 264 } 256 265 … … 657 666 obj->Color= 0; 658 667 obj->dMag = 0; 668 obj->magCal = 0; 659 669 660 670 return (obj); … … 685 695 obj->Color = old->Color; 686 696 obj->dMag = old->dMag; 697 obj->magCal = old->magCal; 687 698 688 699 return(obj); … … 774 785 double gridOffset = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.OFFSET"); 775 786 776 // sampling scale of the grid 777 double gridScale = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.SCALE"); 787 // sampling scale of the grid 788 double gridScale = psMetadataLookupF32 (&status, config, "PSASTRO.GRID.SCALE"); 789 790 // sigma of gaussian window to down-weight photometric outliers (ignored if NAN or 0.0) 791 double photomWindowSigma = psMetadataLookupF32 (&status, config, "PSASTRO.PHOTOM.WINDOW.SIGMA"); 792 bool photomWindowApply = !(isnan(photomWindowSigma) || (fabs(photomWindowSigma) < 0.01)); 793 double photomWindowFactor = photomWindowApply ? -0.5/PS_SQR(photomWindowSigma) : 0.0; 778 794 779 795 // set the static scaling factors … … 816 832 } 817 833 834 // XXX should I make the scale factor in front a recipe value? 835 int Npts = 10 * exp(photomWindowFactor*PS_SQR(ob1->magCal - ob2->magCal)); 836 818 837 // accumulate bin stats 819 NP[iY][iX] + +;820 DX[iY][iX] += dX ;821 DY[iY][iX] += dY ;822 D2[iY][iX] += PS_SQR(dX ) + PS_SQR(dY);838 NP[iY][iX] += Npts; 839 DX[iY][iX] += dX*Npts; 840 DY[iY][iX] += dY*Npts; 841 D2[iY][iX] += PS_SQR(dX*Npts) + PS_SQR(dY*Npts); 823 842 } 824 843 } … … 1053 1072 double tweakNsigma = psMetadataLookupF32 (&status, recipe, "PSASTRO.TWEAK.NSIGMA"); 1054 1073 1074 // sigma of gaussian window to down-weight photometric outliers (ignored if NAN or 0.0) 1075 double photomWindowSigma = psMetadataLookupF32 (&status, recipe, "PSASTRO.PHOTOM.WINDOW.SIGMA"); 1076 bool photomWindowApply = !(isnan(photomWindowSigma) || (fabs(photomWindowSigma) < 0.01)); 1077 double photomWindowFactor = photomWindowApply ? -0.5/PS_SQR(photomWindowSigma) : 0.0; 1078 1055 1079 nBin = 2*tweakRange / tweakScale; 1056 1080 psVector *xHist = psVectorAlloc (nBin, PS_TYPE_F32); … … 1079 1103 continue; 1080 1104 1081 xHist->data.F32[xBin] += 1.0; 1082 yHist->data.F32[yBin] += 1.0; 1105 // XXX should I make the scale factor in front a recipe value? 1106 int Npts = 10 * exp(photomWindowFactor*PS_SQR(ob1->magCal - ob2->magCal)); // sigma = 0.22 mag 1107 1108 xHist->data.F32[xBin] += Npts; 1109 yHist->data.F32[yBin] += Npts; 1083 1110 } 1084 1111 } -
trunk/psModules/src/astrom/pmAstrometryObjects.h
r36834 r39926 43 43 float dMag; ///< error on object magnitude 44 44 float SBinst; ///< surface brightness, used for Koppenhoefer correction 45 float magCal; ///< object calibrated magnitude in extracted filter 45 46 } 46 47 pmAstromObj; … … 347 348 psArray *ref, 348 349 psArray *match, 349 psStats *stats 350 psStats *stats, 351 const psMetadata *config 350 352 ); 351 353 -
trunk/psModules/src/astrom/pmAstrometryWCS.c
r36492 r39926 43 43 pmAstromWCS *wcs = pmAstromWCSfromHeader (header); 44 44 if (!wcs) { 45 return false;45 return false; 46 46 } 47 47 … … 70 70 pmAstromWCS *wcs = pmAstromWCSfromHeader (header); 71 71 if (!wcs) { 72 return false;72 return false; 73 73 } 74 74 … … 86 86 pmAstromWCS *wcs = pmAstromWCSfromHeader (header); 87 87 if (!wcs) { 88 psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from header");89 return false;88 psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from header"); 89 return false; 90 90 } 91 91 … … 96 96 97 97 if (!status1 || !status2) { 98 Nx = psMetadataLookupS32 (&status1, header, "IMNAXIS1");99 Ny = psMetadataLookupS32 (&status2, header, "IMNAXIS2");98 Nx = psMetadataLookupS32 (&status1, header, "IMNAXIS1"); 99 Ny = psMetadataLookupS32 (&status2, header, "IMNAXIS2"); 100 100 } 101 101 102 102 if (!status1 || !status2) { 103 Nx = psMetadataLookupS32 (&status1, header, "ZNAXIS1");104 Ny = psMetadataLookupS32 (&status2, header, "ZNAXIS2");103 Nx = psMetadataLookupS32 (&status1, header, "ZNAXIS1"); 104 Ny = psMetadataLookupS32 (&status2, header, "ZNAXIS2"); 105 105 } 106 106 107 107 if (!status1 || !status2) { 108 psFree (wcs);109 psError(PS_ERR_UNKNOWN, false, "missing required FPA size in header");110 return false;108 psFree (wcs); 109 psError(PS_ERR_UNKNOWN, false, "missing required FPA size in header"); 110 return false; 111 111 } 112 112 … … 123 123 pmAstromWCS *wcs = pmAstromWCSBilevelChipFromFPA (chip, tol); 124 124 if (!wcs) { 125 psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa");126 return false;125 psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa"); 126 return false; 127 127 } 128 128 … … 139 139 pmAstromWCS *wcs = pmAstromWCSBilevelMosaicFromFPA (fpa, tol); 140 140 if (!wcs) { 141 psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa");142 return false;141 psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa"); 142 return false; 143 143 } 144 144 … … 163 163 164 164 if (chip == NULL) 165 return false;165 return false; 166 166 if (sky == NULL) 167 return false;167 return false; 168 168 if (wcs == NULL) 169 return false;169 return false; 170 170 171 171 psPlane *Chip = psPlaneAlloc(); … … 188 188 189 189 if (chip == NULL) 190 return false;190 return false; 191 191 if (sky == NULL) 192 return false;192 return false; 193 193 if (wcs == NULL) 194 return false;194 return false; 195 195 196 196 psError(PS_ERR_UNKNOWN, true, "not yet implemented: needs to invert the transformation"); … … 223 223 char *ctype = psMetadataLookupPtr (&status, header, "CTYPE2"); 224 224 if (!status) { 225 psLogMsg ("psastro", 5, "warning: no WCS metadata in header\n");226 return NULL;225 psLogMsg ("psastro", 5, "warning: no WCS metadata in header\n"); 226 return NULL; 227 227 } 228 228 … … 232 232 type = psProjectTypeFromString (ctype); 233 233 if (type == PS_PROJ_NTYPE) { 234 psLogMsg ("psastro", 2, "warning: unknown projection type %s\n", ctype);235 return NULL;234 psLogMsg ("psastro", 2, "warning: unknown projection type %s\n", ctype); 235 return NULL; 236 236 } 237 237 … … 243 243 244 244 if (cdKeys && pcKeys) { 245 // XXX make this an option246 psLogMsg ("psastro", 5, "warning: both CDi_j and PC00i00j defined in headers, using PC00i00j terms\n");245 // XXX make this an option 246 psLogMsg ("psastro", 5, "warning: both CDi_j and PC00i00j defined in headers, using PC00i00j terms\n"); 247 247 } 248 248 if (!cdKeys && !pcKeys) { 249 psError(PS_ERR_UNKNOWN, true, "missing both CDi_j and PC00i00j WCS terms");250 // XXX we could default here to RA, DEC, ROTANGLE251 return NULL;249 psError(PS_ERR_UNKNOWN, true, "missing both CDi_j and PC00i00j WCS terms"); 250 // XXX we could default here to RA, DEC, ROTANGLE 251 return NULL; 252 252 } 253 253 if (isPoly) { 254 if (!pcKeys) {255 psError(PS_ERR_UNKNOWN, true, "polynomial terms defined, but missing PC00i00j WCS terms");256 return NULL;257 }258 if (fitOrder == 0)259 fitOrder = 1;260 if ((fitOrder > 3) || (fitOrder < 1)) {261 psError(PS_ERR_UNKNOWN, true, "NPLYTERM value undefined: %d", fitOrder);262 return NULL;263 }254 if (!pcKeys) { 255 psError(PS_ERR_UNKNOWN, true, "polynomial terms defined, but missing PC00i00j WCS terms"); 256 return NULL; 257 } 258 if (fitOrder == 0) 259 fitOrder = 1; 260 if ((fitOrder > 3) || (fitOrder < 1)) { 261 psError(PS_ERR_UNKNOWN, true, "NPLYTERM value undefined: %d", fitOrder); 262 return NULL; 263 } 264 264 } else { 265 fitOrder = 1;265 fitOrder = 1; 266 266 } 267 267 … … 277 277 wcs->crpix2 = psMetadataLookupF64 (&status, header, "CRPIX2"); 278 278 wcs->toSky = psProjectionAlloc (wcs->crval1*PM_RAD_DEG, wcs->crval2*PM_RAD_DEG, PM_RAD_DEG, PM_RAD_DEG, type); 279 280 // XXX if type == ZPN, look for PV2_%d elements: 281 if (type == PS_PROJ_ZPN) { 282 psVector *maxRadial = psVectorAlloc (21, PS_TYPE_F64); 283 for (int i = 0; i <= 20; i++) { 284 char name[64]; 285 snprintf (name, 64, "PV2_%d", i); 286 287 maxRadial->data.F64[i] = 0.0; 288 double value = psMetadataLookupF64 (&status, header, name); 289 290 if (status) { 291 maxRadial->data.F64[i] = value; 292 maxRadial->n = i; 293 } 294 295 // PV2_1 is implicit if not present 296 if ((i == 1) && !status) { 297 maxRadial->data.F64[i] = 1.0; 298 continue; 299 } 300 } 301 maxRadial->n ++; 302 wcs->toSky->radial = maxRadial; 303 } 279 304 280 305 // These aren't needed but having them empty is disconcerting … … 289 314 // test the CDELTi varient 290 315 if (pcKeys) { 291 wcs->wcsCDkeys = 0;292 wcs->cdelt1 = psMetadataLookupF64 (&status, header, "CDELT1");293 wcs->cdelt2 = psMetadataLookupF64 (&status, header, "CDELT2");294 295 // test the CROTAi varient:296 // XXX double check lambda..297 double rotate = psMetadataLookupF64 (&status, header, "CROTA2");298 if (status) {299 wcs->trans->x->coeff[1][0] = +wcs->cdelt1 * cos(rotate*PM_RAD_DEG); // == PC1_1300 wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2301 wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1302 wcs->trans->y->coeff[0][1] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2303 return wcs;304 }305 306 // FITS WCS PCi,j has units of unity307 // wcs->trans has units of degrees/pixel308 wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC001001"); // == PC1_1309 wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC001002"); // == PC1_2310 wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC002001"); // == PC2_1311 wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC002002"); // == PC2_2312 313 if (isPoly) {314 // Elixir-style polynomial terms315 // XXX currently, Elixir/DVO cannot accept mixed orders316 for (int i = 0; i <= fitOrder; i++) {317 for (int j = 0; j <= fitOrder; j++) {318 if (i + j < 2)319 continue;320 if (i + j > fitOrder) {321 wcs->trans->x->coeffMask[i][j] = PS_POLY_MASK_SET;322 wcs->trans->y->coeffMask[i][j] = PS_POLY_MASK_SET;323 continue;324 }325 sprintf (name, "PCA1X%1dY%1d", i, j);326 wcs->trans->x->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);327 sprintf (name, "PCA2X%1dY%1d", i, j);328 wcs->trans->y->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);329 }330 }331 }332 return wcs;316 wcs->wcsCDkeys = 0; 317 wcs->cdelt1 = psMetadataLookupF64 (&status, header, "CDELT1"); 318 wcs->cdelt2 = psMetadataLookupF64 (&status, header, "CDELT2"); 319 320 // test the CROTAi varient: 321 // XXX double check lambda.. 322 double rotate = psMetadataLookupF64 (&status, header, "CROTA2"); 323 if (status) { 324 wcs->trans->x->coeff[1][0] = +wcs->cdelt1 * cos(rotate*PM_RAD_DEG); // == PC1_1 325 wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2 326 wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1 327 wcs->trans->y->coeff[0][1] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2 328 return wcs; 329 } 330 331 // FITS WCS PCi,j has units of unity 332 // wcs->trans has units of degrees/pixel 333 wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC001001"); // == PC1_1 334 wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC001002"); // == PC1_2 335 wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC002001"); // == PC2_1 336 wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC002002"); // == PC2_2 337 338 if (isPoly) { 339 // Elixir-style polynomial terms 340 // XXX currently, Elixir/DVO cannot accept mixed orders 341 for (int i = 0; i <= fitOrder; i++) { 342 for (int j = 0; j <= fitOrder; j++) { 343 if (i + j < 2) 344 continue; 345 if (i + j > fitOrder) { 346 wcs->trans->x->coeffMask[i][j] = PS_POLY_MASK_SET; 347 wcs->trans->y->coeffMask[i][j] = PS_POLY_MASK_SET; 348 continue; 349 } 350 sprintf (name, "PCA1X%1dY%1d", i, j); 351 wcs->trans->x->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name); 352 sprintf (name, "PCA2X%1dY%1d", i, j); 353 wcs->trans->y->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name); 354 } 355 } 356 } 357 return wcs; 333 358 } 334 359 335 360 // test the CDi_j varient 336 361 if (cdKeys) { 337 wcs->wcsCDkeys = 1;338 339 wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1340 wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2341 wcs->trans->y->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD2_1"); // == PC2_1342 wcs->trans->y->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD2_2"); // == PC2_2343 wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);344 wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);345 return wcs;362 wcs->wcsCDkeys = 1; 363 364 wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1 365 wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2 366 wcs->trans->y->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD2_1"); // == PC2_1 367 wcs->trans->y->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD2_2"); // == PC2_2 368 wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]); 369 wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]); 370 return wcs; 346 371 } 347 372 psLogMsg ("psastro", 2, "warning: missing rotation matrix?\n"); … … 376 401 psMetadataAddF64 (header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", wcs->crpix2); 377 402 403 if (wcs->toSky->type == PS_PROJ_ZPN) { 404 psAssert (wcs->toSky->radial, "missing radial vector"); 405 for (int i = 0; i < wcs->toSky->radial->n; i++) { 406 if (wcs->toSky->radial->data.F64[i] == 0.0) continue; 407 snprintf (name, 16, "PV2_%d", i); 408 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->toSky->radial->data.F64[i]); 409 } 410 } 411 378 412 // XXX make it optional to write out CDi_j terms, or other versions 379 413 // apply CDELT1,2 (degrees / pixel) to yield PCi,j terms of order unity 380 414 if (!wcs->wcsCDkeys) { 381 415 382 double cdelt1 = wcs->cdelt1;383 double cdelt2 = wcs->cdelt2;384 psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1);385 psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2);386 387 // test the PC00i00j varient:388 psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1389 psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2390 psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1391 psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2392 393 // Elixir-style polynomial terms394 // XXX currently, Elixir/DVO cannot accept mixed orders395 // XXX need to respect the masks396 // XXX is wcs->cdelt1,2 always consistent?397 int fitOrder = wcs->trans->x->nX;398 if (fitOrder > 1) {399 for (int i = 0; i <= fitOrder; i++) {400 for (int j = 0; j <= fitOrder; j++) {401 if (i + j < 2)402 continue;403 if (i + j > fitOrder)404 continue;405 sprintf (name, "PCA1X%1dY%1d", i, j);406 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));407 sprintf (name, "PCA2X%1dY%1d", i, j);408 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));409 }410 }411 psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", fitOrder);412 }413 414 // remove any existing 'CDi_j style' wcs keywords415 if (psMetadataLookup(header, "CD1_1")) {416 psMetadataRemoveKey(header, "CD1_1");417 psMetadataRemoveKey(header, "CD1_2");418 psMetadataRemoveKey(header, "CD2_1");419 psMetadataRemoveKey(header, "CD2_2");420 }421 422 // Remove 'CDi_jX' WCS keywords423 psString cd11 = psStringCopy("CD1_1 ");424 psString cd12 = psStringCopy("CD1_2 ");425 psString cd21 = psStringCopy("CD2_1 ");426 psString cd22 = psStringCopy("CD2_2 ");427 for (char extra = 'A'; extra <= 'Z'; extra++) {428 cd11[strlen(cd11)-1] = extra;429 if (psMetadataLookup(header, cd11)) {430 cd12[strlen(cd12)-1] = extra;431 cd21[strlen(cd21)-1] = extra;432 cd22[strlen(cd22)-1] = extra;433 psMetadataRemoveKey(header, cd11);434 psMetadataRemoveKey(header, cd12);435 psMetadataRemoveKey(header, cd21);436 psMetadataRemoveKey(header, cd22);437 }438 }439 psFree(cd11);440 psFree(cd12);441 psFree(cd21);442 psFree(cd22);416 double cdelt1 = wcs->cdelt1; 417 double cdelt2 = wcs->cdelt2; 418 psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1); 419 psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2); 420 421 // test the PC00i00j varient: 422 psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1 423 psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2 424 psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1 425 psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2 426 427 // Elixir-style polynomial terms 428 // XXX currently, Elixir/DVO cannot accept mixed orders 429 // XXX need to respect the masks 430 // XXX is wcs->cdelt1,2 always consistent? 431 int fitOrder = wcs->trans->x->nX; 432 if (fitOrder > 1) { 433 for (int i = 0; i <= fitOrder; i++) { 434 for (int j = 0; j <= fitOrder; j++) { 435 if (i + j < 2) 436 continue; 437 if (i + j > fitOrder) 438 continue; 439 sprintf (name, "PCA1X%1dY%1d", i, j); 440 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j)); 441 sprintf (name, "PCA2X%1dY%1d", i, j); 442 psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j)); 443 } 444 } 445 psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", fitOrder); 446 } 447 448 // remove any existing 'CDi_j style' wcs keywords 449 if (psMetadataLookup(header, "CD1_1")) { 450 psMetadataRemoveKey(header, "CD1_1"); 451 psMetadataRemoveKey(header, "CD1_2"); 452 psMetadataRemoveKey(header, "CD2_1"); 453 psMetadataRemoveKey(header, "CD2_2"); 454 } 455 456 // Remove 'CDi_jX' WCS keywords 457 psString cd11 = psStringCopy("CD1_1 "); 458 psString cd12 = psStringCopy("CD1_2 "); 459 psString cd21 = psStringCopy("CD2_1 "); 460 psString cd22 = psStringCopy("CD2_2 "); 461 for (char extra = 'A'; extra <= 'Z'; extra++) { 462 cd11[strlen(cd11)-1] = extra; 463 if (psMetadataLookup(header, cd11)) { 464 cd12[strlen(cd12)-1] = extra; 465 cd21[strlen(cd21)-1] = extra; 466 cd22[strlen(cd22)-1] = extra; 467 psMetadataRemoveKey(header, cd11); 468 psMetadataRemoveKey(header, cd12); 469 psMetadataRemoveKey(header, cd21); 470 psMetadataRemoveKey(header, cd22); 471 } 472 } 473 psFree(cd11); 474 psFree(cd12); 475 psFree(cd21); 476 psFree(cd22); 443 477 444 478 445 479 } else { 446 480 447 psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_1", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0]);448 psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_2", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1]);449 psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_1", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0]);450 psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_2", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1]);451 452 if (psMetadataLookup(header, "PC001001")) {453 psMetadataRemoveKey(header, "PC001001");454 psMetadataRemoveKey(header, "PC001002");455 psMetadataRemoveKey(header, "PC002001");456 psMetadataRemoveKey(header, "PC002002");457 }481 psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_1", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0]); 482 psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_2", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1]); 483 psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_1", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0]); 484 psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_2", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1]); 485 486 if (psMetadataLookup(header, "PC001001")) { 487 psMetadataRemoveKey(header, "PC001001"); 488 psMetadataRemoveKey(header, "PC001002"); 489 psMetadataRemoveKey(header, "PC002001"); 490 psMetadataRemoveKey(header, "PC002002"); 491 } 458 492 } 459 493 … … 473 507 // cdelt1,2 has units of degree/pixel 474 508 for (int i = 0; i <= toFPA->x->nX; i++) { 475 for (int j = 0; j <= toFPA->x->nX; j++) {476 toFPA->x->coeff[i][j] *= pixelScale/wcs->cdelt1;477 toFPA->y->coeff[i][j] *= pixelScale/wcs->cdelt2;478 }509 for (int j = 0; j <= toFPA->x->nX; j++) { 510 toFPA->x->coeff[i][j] *= pixelScale/wcs->cdelt1; 511 toFPA->y->coeff[i][j] *= pixelScale/wcs->cdelt2; 512 } 479 513 } 480 514 … … 485 519 // projection from TPA (linear microns) to SKY (radians) 486 520 psProjection *toSky = psProjectionAlloc (wcs->toSky->R, wcs->toSky->D, PM_RAD_DEG*pdelt1, PM_RAD_DEG*pdelt2, wcs->toSky->type); 521 toSky->radial = psMemIncrRefCounter (wcs->toSky->radial); 487 522 488 523 if (fpa->toSky == NULL) { 489 524 psFree(fpa->toTPA); 490 525 psFree(fpa->fromTPA); 491 fpa->toTPA = psPlaneTransformIdentity (1);492 fpa->fromTPA = psPlaneTransformIdentity (1);493 fpa->toSky = toSky;526 fpa->toTPA = psPlaneTransformIdentity (1); 527 fpa->fromTPA = psPlaneTransformIdentity (1); 528 fpa->toSky = toSky; 494 529 } else { 495 530 496 // this section allows the loaded chip to be included in an fpa structure in which497 // other chips have already been loaded (ie, the fpa->toTPA, fpa->toSky components have498 // already been defined). we have to adjust to match the existing transformation.499 500 if (fpa->toTPA == NULL)501 psAbort("projection defined, tangent-plane not defined");502 if (fpa->fromTPA == NULL)503 psAbort("projection defined, tangent-plane not defined");504 505 // convert from pixels on this chip to pixels on reference chip506 // rX has units of refpixels / pixel507 double rX = toSky->Xs / fpa->toSky->Xs;508 double rY = toSky->Ys / fpa->toSky->Ys;509 510 for (int i = 0; i <= toFPA->x->nX; i++) {511 for (int j = 0; j <= toFPA->x->nY; j++) {512 toFPA->x->coeff[i][j] *= rX;513 toFPA->y->coeff[i][j] *= rY;514 }515 }516 517 // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter518 // XXX this only works if toTPA is at most a linear transformation519 psPlaneTransform *toFPAnew = psPlaneTransformAlloc(toFPA->x->nX, toFPA->x->nY);520 for (int i = 0; i <= toFPA->x->nX; i++) {521 for (int j = 0; j <= toFPA->x->nY; j++) {522 double f1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[1][0]*toFPA->x->coeff[i][j];523 double f2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[0][1]*toFPA->y->coeff[i][j];524 toFPAnew->x->coeff[i][j] = f1 + f2;525 526 double g1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[1][0]*toFPA->x->coeff[i][j];527 double g2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[0][1]*toFPA->y->coeff[i][j];528 toFPAnew->y->coeff[i][j] = g1 + g2;529 }530 }531 toFPAnew->x->coeff[0][0] += fpa->fromTPA->x->coeff[0][0];532 toFPAnew->y->coeff[0][0] += fpa->fromTPA->y->coeff[0][0];533 534 psFree (toFPA);535 toFPA = toFPAnew;536 537 // adjust reference pixel for new toSky reference coordinate538 // find the FPA coordinate of 0,0 for this chip.539 psPlane *fpOld = psPlaneAlloc();540 psPlane *fpNew = psPlaneAlloc();541 psPlane *tp = psPlaneAlloc();542 psSphere *sky = psSphereAlloc();543 544 sky->r = toSky->R;545 sky->d = toSky->D;546 psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection547 psPlaneTransformApply (fpOld, fpa->fromTPA, tp);548 549 sky->r = fpa->toSky->R;550 sky->d = fpa->toSky->D;551 psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection552 psPlaneTransformApply (fpNew, fpa->fromTPA, tp);553 554 toFPA->x->coeff[0][0] -= fpNew->x - fpOld->x;555 toFPA->y->coeff[0][0] -= fpNew->y - fpOld->y;556 557 psFree (sky);558 psFree (tp);559 psFree (fpOld);560 psFree (fpNew);561 562 psFree (toSky);531 // this section allows the loaded chip to be included in an fpa structure in which 532 // other chips have already been loaded (ie, the fpa->toTPA, fpa->toSky components have 533 // already been defined). we have to adjust to match the existing transformation. 534 535 if (fpa->toTPA == NULL) 536 psAbort("projection defined, tangent-plane not defined"); 537 if (fpa->fromTPA == NULL) 538 psAbort("projection defined, tangent-plane not defined"); 539 540 // convert from pixels on this chip to pixels on reference chip 541 // rX has units of refpixels / pixel 542 double rX = toSky->Xs / fpa->toSky->Xs; 543 double rY = toSky->Ys / fpa->toSky->Ys; 544 545 for (int i = 0; i <= toFPA->x->nX; i++) { 546 for (int j = 0; j <= toFPA->x->nY; j++) { 547 toFPA->x->coeff[i][j] *= rX; 548 toFPA->y->coeff[i][j] *= rY; 549 } 550 } 551 552 // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter 553 // XXX this only works if toTPA is at most a linear transformation 554 psPlaneTransform *toFPAnew = psPlaneTransformAlloc(toFPA->x->nX, toFPA->x->nY); 555 for (int i = 0; i <= toFPA->x->nX; i++) { 556 for (int j = 0; j <= toFPA->x->nY; j++) { 557 double f1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[1][0]*toFPA->x->coeff[i][j]; 558 double f2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[0][1]*toFPA->y->coeff[i][j]; 559 toFPAnew->x->coeff[i][j] = f1 + f2; 560 561 double g1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[1][0]*toFPA->x->coeff[i][j]; 562 double g2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[0][1]*toFPA->y->coeff[i][j]; 563 toFPAnew->y->coeff[i][j] = g1 + g2; 564 } 565 } 566 toFPAnew->x->coeff[0][0] += fpa->fromTPA->x->coeff[0][0]; 567 toFPAnew->y->coeff[0][0] += fpa->fromTPA->y->coeff[0][0]; 568 569 psFree (toFPA); 570 toFPA = toFPAnew; 571 572 // adjust reference pixel for new toSky reference coordinate 573 // find the FPA coordinate of 0,0 for this chip. 574 psPlane *fpOld = psPlaneAlloc(); 575 psPlane *fpNew = psPlaneAlloc(); 576 psPlane *tp = psPlaneAlloc(); 577 psSphere *sky = psSphereAlloc(); 578 579 sky->r = toSky->R; 580 sky->d = toSky->D; 581 psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection 582 psPlaneTransformApply (fpOld, fpa->fromTPA, tp); 583 584 sky->r = fpa->toSky->R; 585 sky->d = fpa->toSky->D; 586 psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection 587 psPlaneTransformApply (fpNew, fpa->fromTPA, tp); 588 589 toFPA->x->coeff[0][0] -= fpNew->x - fpOld->x; 590 toFPA->y->coeff[0][0] -= fpNew->y - fpOld->y; 591 592 psFree (sky); 593 psFree (tp); 594 psFree (fpOld); 595 psFree (fpNew); 596 597 psFree (toSky); 563 598 } 564 599 … … 578 613 // XXX if the inversion fails, we probably do not have a valid transform anyway 579 614 if (!chip->fromFPA) { 580 psWarning ("failed to find a valid transformation");581 psFree (chip->toFPA);582 return false;615 psWarning ("failed to find a valid transformation"); 616 psFree (chip->toFPA); 617 return false; 583 618 } 584 619 585 620 // this can take a very long time... 586 621 while (fpa->toSky->R < 0) 587 fpa->toSky->R += 2.0*M_PI;622 fpa->toSky->R += 2.0*M_PI; 588 623 while (fpa->toSky->R > 2.0*M_PI) 589 fpa->toSky->R -= 2.0*M_PI;624 fpa->toSky->R -= 2.0*M_PI; 590 625 591 626 fpa->wcsCDkeys = wcs->wcsCDkeys; 592 627 593 628 psTrace ("psastro", 5, "toFPA: %f %f (%f,%f),(%f,%f)\n", 594 chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0],595 chip->toFPA->x->coeff[1][0], chip->toFPA->x->coeff[0][1],596 chip->toFPA->y->coeff[1][0], chip->toFPA->y->coeff[0][1]);629 chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0], 630 chip->toFPA->x->coeff[1][0], chip->toFPA->x->coeff[0][1], 631 chip->toFPA->y->coeff[1][0], chip->toFPA->y->coeff[0][1]); 597 632 598 633 psTrace ("psastro", 5, "frFPA: %f %f (%f,%f),(%f,%f)\n", 599 chip->fromFPA->x->coeff[0][0], chip->fromFPA->y->coeff[0][0],600 chip->fromFPA->x->coeff[1][0], chip->fromFPA->x->coeff[0][1],601 chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]);634 chip->fromFPA->x->coeff[0][0], chip->fromFPA->y->coeff[0][0], 635 chip->fromFPA->x->coeff[1][0], chip->fromFPA->x->coeff[0][1], 636 chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]); 602 637 603 638 return true; … … 613 648 */ 614 649 615 // create transformation with 0,0 reference pixel and units of microns/pixel616 650 psFree (chip->toFPA); 617 chip->toFPA = psPlaneTransformSetCenter (NULL, wcs->trans, -wcs->crpix1, -wcs->crpix2); 651 chip->toFPA = psPlaneTransformAlloc(wcs->trans->x->nX, wcs->trans->x->nY); 652 653 // copy the toFPA x,y, transformations to the wcs version 654 chip->toFPA->x = psPolynomial2DCopy (chip->toFPA->x, wcs->trans->x); 655 chip->toFPA->y = psPolynomial2DCopy (chip->toFPA->y, wcs->trans->y); 656 657 // these need to be set based on crval1,2 658 chip->toFPA->x->coeff[0][0] = wcs->crval1; 659 chip->toFPA->y->coeff[0][0] = wcs->crval2; 618 660 619 661 // determine the inverse transformation: we need the chip pixels covered by this transform … … 633 675 // cdelt1,2 has units of degrees/micron 634 676 fpa->toSky = psProjectionAlloc (wcs->toSky->R, wcs->toSky->D, wcs->cdelt1*PM_RAD_DEG, wcs->cdelt2*PM_RAD_DEG, wcs->toSky->type); 677 fpa->toSky->radial = psMemIncrRefCounter (wcs->toSky->radial); 635 678 636 679 // create transformation with 0,0 reference pixel … … 639 682 // convert fpa->toTPA to units of unity (microns/micron) 640 683 for (int i = 0; i <= fpa->toTPA->x->nX; i++) { 641 for (int j = 0; j <= fpa->toTPA->x->nY; j++) {642 fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1;643 fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2;644 }684 for (int j = 0; j <= fpa->toTPA->x->nY; j++) { 685 fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1; 686 fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2; 687 } 645 688 } 646 689 … … 648 691 // the region defines the FPA pixels covered by the tranformation 649 692 psFree (fpa->fromTPA); 650 fpa->fromTPA = psPlaneTransformInvert(NULL, fpa->toTPA, region, 50); 693 psPlaneTransform *myPT = psPlaneTransformAlloc(fpa->toTPA->x->nX+4, fpa->toTPA->x->nY+4); 694 fpa->fromTPA = psPlaneTransformInvert(myPT, fpa->toTPA, region, 50); 695 psFree (myPT); 651 696 return true; 652 697 } … … 684 729 685 730 for (int i = 0; i <= toTPA->x->nX; i++) { 686 for (int j = 0; j <= toTPA->x->nY; j++) {687 double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];688 double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];689 toTPA->x->coeff[i][j] = f1 + f2;690 691 double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];692 double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];693 toTPA->y->coeff[i][j] = g1 + g2;694 }731 for (int j = 0; j <= toTPA->x->nY; j++) { 732 double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j]; 733 double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j]; 734 toTPA->x->coeff[i][j] = f1 + f2; 735 736 double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j]; 737 double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j]; 738 toTPA->y->coeff[i][j] = g1 + g2; 739 } 695 740 } 696 741 toTPA->x->coeff[0][0] += fpa->toTPA->x->coeff[0][0]; … … 701 746 // convert projection from FPA to SKY into wcs projection (degrees to radians) 702 747 wcs->toSky = psProjectionAlloc (fpa->toSky->R, fpa->toSky->D, PM_RAD_DEG, PM_RAD_DEG, fpa->toSky->type); 748 wcs->toSky->radial = psMemIncrRefCounter (fpa->toSky->radial); 749 703 750 wcs->crval1 = fpa->toSky->R*PS_DEG_RAD; 704 751 wcs->crval2 = fpa->toSky->D*PS_DEG_RAD; … … 714 761 psPlane *center = psPlaneTransformGetCenter (tpa1, tol); 715 762 if (!center) { 716 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");717 psFree (toTPA);718 psFree (tpa1);719 psFree (wcs);720 return NULL;763 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center."); 764 psFree (toTPA); 765 psFree (tpa1); 766 psFree (wcs); 767 return NULL; 721 768 } 722 769 … … 751 798 // convert wcs->trans to a matrix with units of degrees/pixel 752 799 for (int i = 0; i <= wcs->trans->x->nX; i++) { 753 for (int j = 0; j <= wcs->trans->x->nY; j++) {754 wcs->trans->x->coeff[i][j] *= pdelt1;755 wcs->trans->y->coeff[i][j] *= pdelt2;756 }800 for (int j = 0; j <= wcs->trans->x->nY; j++) { 801 wcs->trans->x->coeff[i][j] *= pdelt1; 802 wcs->trans->y->coeff[i][j] *= pdelt2; 803 } 757 804 } 758 805 … … 773 820 */ 774 821 775 // convert the chip-level toFPA to a wcs polynomial transformation 822 // convert the chip-level toFPA to a wcs polynomial transformation. the pmAstromWCS 823 // structure represents a single layer transformation (e.g., RA-TAN, RA-WRP). Here we are 824 // converting the chip-level to a WRP projection in the structure. Later, this will be 825 // converted to the WCS keywords 826 776 827 pmAstromWCS *pmAstromWCSBilevelChipFromFPA (const pmChip *chip, double tol) 777 828 { … … 784 835 pmAstromWCS *wcs = pmAstromWCSAlloc(chip->toFPA->x->nX, chip->toFPA->x->nY); 785 836 837 // copy the toFPA x,y, transformations to the wcs version 838 wcs->trans->x = psPolynomial2DCopy (wcs->trans->x, chip->toFPA->x); 839 wcs->trans->y = psPolynomial2DCopy (wcs->trans->y, chip->toFPA->y); 840 786 841 // Chip to FPA transformation is a Cartesian 'projection' 787 842 // reference pixel for FPA is 0.0, 0.0 788 843 wcs->toSky = psProjectionAlloc (0.0, 0.0, 1.0, 1.0, PS_PROJ_WRP); 789 wcs->crval1 = 0.0; 790 wcs->crval2 = 0.0; 791 792 // given transformation, solve for coordinates which yields output coordinates of 0,0 793 psPlane *center = psPlaneTransformGetCenter (chip->toFPA, tol); 794 if (!center) { 795 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center."); 796 psFree (wcs); 797 return NULL; 798 } 799 800 // adjust wcs transform to use center as reference coordinate 801 // resulting transformation has units of microns/pixel 802 psPlaneTransformSetCenter (wcs->trans, chip->toFPA, center->x, center->y); 803 804 // calculated center is crpix1,2 805 wcs->crpix1 = center->x; 806 wcs->crpix2 = center->y; 807 psFree (center); 808 844 845 // reference pixel (CRPIX1,2) is (0.0, 0.0): 846 wcs->crpix1 = 0.0; 847 wcs->crpix2 = 0.0; 848 849 // we need to set CRVAL1,2 for the 0,0 pixel: 850 wcs->crval1 = psPolynomial2DEval (chip->toFPA->x, 0.0, 0.0); 851 wcs->crval2 = psPolynomial2DEval (chip->toFPA->y, 0.0, 0.0); 852 853 wcs->toSky->R = wcs->crval1*PM_RAD_DEG; 854 wcs->toSky->D = wcs->crval2*PM_RAD_DEG; 855 856 // these need to be set to 0.0 since they have been moved to crpix1,crpix2 857 wcs->trans->x->coeff[0][0] = 0.0; 858 wcs->trans->y->coeff[0][0] = 0.0; 859 809 860 // output coordinates are in microns : CDELT1,2 has units of microns/pixel 810 861 wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]); … … 834 885 psPlane *center = psPlaneTransformGetCenter (fpa->toTPA, tol); 835 886 if (!center) { 836 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");837 psFree (wcs);838 return NULL;887 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center."); 888 psFree (wcs); 889 return NULL; 839 890 } 840 891 … … 854 905 // convert wcs->trans to units of degree/micron 855 906 for (int i = 0; i <= wcs->trans->x->nX; i++) { 856 for (int j = 0; j <= wcs->trans->x->nY; j++) {857 wcs->trans->x->coeff[i][j] *= pdelt1;858 wcs->trans->y->coeff[i][j] *= pdelt2;859 }907 for (int j = 0; j <= wcs->trans->x->nY; j++) { 908 wcs->trans->x->coeff[i][j] *= pdelt1; 909 wcs->trans->y->coeff[i][j] *= pdelt2; 910 } 860 911 } 861 912 … … 880 931 int k=0; 881 932 for (int j=0; j<nSamples; j++) { 882 double y = bounds->y0 + (j * deltaY / nSamples);883 for (int i=0; i<nSamples; i++) {884 psPlane *s = psPlaneAlloc();885 s->x = bounds->x0 + (i * deltaX / nSamples);886 s->y = y;887 psArraySet(src, k, s);888 psPlane *d = psPlaneTransformApply(NULL, trans, s);889 psArraySet(dst, k, d);890 psFree(s); // drop our refs to s and d891 psFree(d);892 ++k;893 }933 double y = bounds->y0 + (j * deltaY / nSamples); 934 for (int i=0; i<nSamples; i++) { 935 psPlane *s = psPlaneAlloc(); 936 s->x = bounds->x0 + (i * deltaX / nSamples); 937 s->y = y; 938 psArraySet(src, k, s); 939 psPlane *d = psPlaneTransformApply(NULL, trans, s); 940 psArraySet(dst, k, d); 941 psFree(s); // drop our refs to s and d 942 psFree(d); 943 ++k; 944 } 894 945 } 895 946 … … 897 948 898 949 if (!psPlaneTransformFit(newTrans, src, dst, 0, 0)) { 899 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");900 return NULL;950 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed"); 951 return NULL; 901 952 } 902 953 … … 907 958 printf(" i chip_x tpa_x tpa_x_fit dx chip_y tpa_y tpa_y_fit dy dx > 0.5 || dy > 0.5\n"); 908 959 for (int i=0; i<psArrayLength(dst); i++) { 909 psPlane *d = (psPlane *) psArrayGet(dst, i);910 psPlane *s = (psPlane *) psArrayGet(src, i);911 912 new = psPlaneTransformApply(new, newTrans, s);913 914 double xerr = new->x - d->x;915 double yerr = new->y - d->y;916 bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5);917 printf("%4d %9.2f %9.2f %9.2f %9.4f %9.2f %9.2f %9.2f %9.4f %s\n"918 , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : "");960 psPlane *d = (psPlane *) psArrayGet(dst, i); 961 psPlane *s = (psPlane *) psArrayGet(src, i); 962 963 new = psPlaneTransformApply(new, newTrans, s); 964 965 double xerr = new->x - d->x; 966 double yerr = new->y - d->y; 967 bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5); 968 printf("%4d %9.2f %9.2f %9.2f %9.4f %9.2f %9.2f %9.2f %9.4f %s\n" 969 , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : ""); 919 970 } 920 971 psFree(new); … … 934 985 935 986 if (outFPA == NULL) { 936 outFPA = inFPA;987 outFPA = inFPA; 937 988 } 938 989 if (outChip == NULL) { 939 outChip = inChip;990 outChip = inChip; 940 991 } 941 992 if (outputBounds == NULL) { 942 outputBounds = pmChipPixels(outChip);993 outputBounds = pmChipPixels(outChip); 943 994 } 944 995 … … 946 997 psPlaneTransform *chipToTPA = psPlaneTransformCombine(NULL, inChip->toFPA, inFPA->toTPA, *outputBounds, 50); 947 998 if (!chipToTPA) { 948 psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA");949 return false;999 psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA"); 1000 return false; 950 1001 } 951 1002 … … 954 1005 psFree(chipToTPA); 955 1006 if (!chipToFPA) { 956 psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed");957 return false;1007 psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed"); 1008 return false; 958 1009 } 959 1010 … … 961 1012 psPlaneTransform *outToFPA; 962 1013 if (offset_x != 0. && offset_y != 0.) { 963 outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y);964 psFree(chipToFPA);1014 outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y); 1015 psFree(chipToFPA); 965 1016 } else { 966 outToFPA = chipToFPA;1017 outToFPA = chipToFPA; 967 1018 } 968 1019 969 1020 psPlaneTransform *outFromFPA = psPlaneTransformInvert(NULL, outToFPA, *outputBounds, 50); 970 1021 if (!outFromFPA) { 971 psFree(outToFPA);972 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");973 return false;1022 psFree(outToFPA); 1023 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed"); 1024 return false; 974 1025 } 975 1026 … … 1023 1074 1024 1075 for (int j = 0; j < nSamples; j++) { 1025 double y = bounds->y0 + (j * deltaY / nSamples);1026 for (int i = 0; i < nSamples; i++) {1027 1028 psSphere srcSky;1029 psPlane *srcChip = psPlaneAlloc();1030 psPlane *dstTP = psPlaneAlloc();1031 1032 srcChip->x = bounds->x0 + (i * deltaX / nSamples);1033 srcChip->y = y;1034 1035 psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip);1036 psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP);1037 psDeproject (&srcSky, &srcTP, inFPA->toSky);1038 1039 // fprintf (stderr, "%f %f | %f %f | %f %f | %f %f\n", srcChip->x, srcChip->y, srcFP.x, srcFP.y, srcTP.x, srcTP.y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD);1040 1041 psProject (dstTP, &srcSky, outFPA->toSky);1042 1043 srcChip->x -= bounds->x0;1044 srcChip->y -= bounds->y0;1045 psArrayAdd (src, 100, srcChip);1046 psArrayAdd (dst, 100, dstTP);1047 1048 psFree(srcChip); // drop our refs to s and d1049 psFree(dstTP);1050 }1076 double y = bounds->y0 + (j * deltaY / nSamples); 1077 for (int i = 0; i < nSamples; i++) { 1078 1079 psSphere srcSky; 1080 psPlane *srcChip = psPlaneAlloc(); 1081 psPlane *dstTP = psPlaneAlloc(); 1082 1083 srcChip->x = bounds->x0 + (i * deltaX / nSamples); 1084 srcChip->y = y; 1085 1086 psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip); 1087 psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP); 1088 psDeproject (&srcSky, &srcTP, inFPA->toSky); 1089 1090 // fprintf (stderr, "%f %f | %f %f | %f %f | %f %f\n", srcChip->x, srcChip->y, srcFP.x, srcFP.y, srcTP.x, srcTP.y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD); 1091 1092 psProject (dstTP, &srcSky, outFPA->toSky); 1093 1094 srcChip->x -= bounds->x0; 1095 srcChip->y -= bounds->y0; 1096 psArrayAdd (src, 100, srcChip); 1097 psArrayAdd (dst, 100, dstTP); 1098 1099 psFree(srcChip); // drop our refs to s and d 1100 psFree(dstTP); 1101 } 1051 1102 } 1052 1103 … … 1056 1107 1057 1108 if (!psPlaneTransformFit(newToFPA, src, dst, 0, 0)) { 1058 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");1059 psFree(src);1060 psFree(dst);1061 return NULL;1109 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed"); 1110 psFree(src); 1111 psFree(dst); 1112 return NULL; 1062 1113 } 1063 1114 … … 1065 1116 for (int i = 0; i < src->n; i++) { 1066 1117 1067 psSphere srcSky, dstSky;1068 psPlane *srcChip = src->data[i];1069 psPlane *dstTP = dst->data[i];1070 1071 psPlaneTransformApply (&srcFP, newToFPA, srcChip);1072 psDeproject (&srcSky, &srcFP, outFPA->toSky);1073 psDeproject (&dstSky, dstTP, outFPA->toSky);1074 1075 double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0;1076 double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0;1077 fprintf (stderr, "%f %f | %f %f | %f %f | %f %f | %f %f | %f %f\n", dX, dY, srcChip->x, srcChip->y, srcFP.x, srcFP.y, dstTP->x, dstTP->y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD, dstSky.r*PS_DEG_RAD, dstSky.d*PS_DEG_RAD);1118 psSphere srcSky, dstSky; 1119 psPlane *srcChip = src->data[i]; 1120 psPlane *dstTP = dst->data[i]; 1121 1122 psPlaneTransformApply (&srcFP, newToFPA, srcChip); 1123 psDeproject (&srcSky, &srcFP, outFPA->toSky); 1124 psDeproject (&dstSky, dstTP, outFPA->toSky); 1125 1126 double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0; 1127 double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0; 1128 fprintf (stderr, "%f %f | %f %f | %f %f | %f %f | %f %f | %f %f\n", dX, dY, srcChip->x, srcChip->y, srcFP.x, srcFP.y, dstTP->x, dstTP->y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD, dstSky.r*PS_DEG_RAD, dstSky.d*PS_DEG_RAD); 1078 1129 1079 1130 } … … 1086 1137 psPlaneTransform *newFromFPA = psPlaneTransformInvert(NULL, newToFPA, *bounds, 1); 1087 1138 if (!newFromFPA) { 1088 psFree(newToFPA);1089 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");1090 return false;1139 psFree(newToFPA); 1140 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed"); 1141 return false; 1091 1142 } 1092 1143 … … 1111 1162 1112 1163 if (!wcs) 1113 return;1164 return; 1114 1165 psFree (wcs->trans); 1115 1166 psFree (wcs->toSky); … … 1133 1184 /***** 1134 1185 1135 For mosaic astrometry, we need to have a starting set of projection terms in which the1136 chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or1137 microns). This set of projections, coupled with an identity toTPA (ie, no distortion) will1138 result in substantial errors between the observed and predicted star positions on the focal1139 plane: this is the measurement of the optical distortion in the camera. At the same time,1140 we need to carry around the transformations which allow us to make an accurate calculation1141 of the position of the stars based on the input (per-chip) astrometry. These1142 transformations will allow us to match the raw and ref stars robustly. To convert the1143 per-chip astrometry (which may have been calculated with a different plate scale for each1144 chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust1145 the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for1146 each chip (eg, cdelt1). Thus, we need to carry around both the1186 For mosaic astrometry, we need to have a starting set of projection terms in which the 1187 chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or 1188 microns). This set of projections, coupled with an identity toTPA (ie, no distortion) will 1189 result in substantial errors between the observed and predicted star positions on the focal 1190 plane: this is the measurement of the optical distortion in the camera. At the same time, 1191 we need to carry around the transformations which allow us to make an accurate calculation 1192 of the position of the stars based on the input (per-chip) astrometry. These 1193 transformations will allow us to match the raw and ref stars robustly. To convert the 1194 per-chip astrometry (which may have been calculated with a different plate scale for each 1195 chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust 1196 the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for 1197 each chip (eg, cdelt1). Thus, we need to carry around both the 1147 1198 1148 1199 *****/ -
trunk/psModules/src/detrend/pmFringeStats.c
r34085 r39926 336 336 dfPt[i] = 1.0 / medianSd->sampleStdev; 337 337 338 psTrace("psModules.detrend", 7, "[%d:%d,%d:%d]: %f %f : %s\n", (int)region.x0, (int)region.x1, 339 (int)region.y0, (int)region.y1, fPt[i], dfPt[i], readout->parent->hdu->extname); 338 if (readout->parent->hdu) { 339 psTrace("psModules.detrend", 7, "[%d:%d,%d:%d]: %f %f : %s\n", (int)region.x0, (int)region.x1, 340 (int)region.y0, (int)region.y1, fPt[i], dfPt[i], readout->parent->hdu->extname); 341 } 342 else { 343 psTrace("psModules.detrend", 7, "[%d:%d,%d:%d]: %f %f : THIS_IS_A_SPOOKY_GHOST_CELL\n", (int)region.x0, (int)region.x1, 344 (int)region.y0, (int)region.y1, fPt[i], dfPt[i]); 345 } 340 346 } 341 347 psFree(sky); -
trunk/psModules/src/objects/pmPCM_MinimizeChisq.c
r36859 r39926 480 480 # if (TESTCOPY) 481 481 psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type); 482 # else 482 # else // TESTCOPY 483 483 if (pcm->use1Dgauss) { 484 484 … … 496 496 psImageConvolveKernel (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psfFFT); 497 497 } 498 # endif 498 # endif // TESTCOPY 499 499 500 500 for (int n = 0; n < pcm->dmodelsFlux->n; n++) { … … 505 505 # if (TESTCOPY) 506 506 psImageCopy (dmodelConv, dmodel, dmodel->type.type); 507 # else 507 # else // TESTCOPY 508 508 if (pcm->use1Dgauss) { 509 509 if (USE_1D_CACHE) { … … 520 520 psImageConvolveKernel (dmodelConv, dmodel, NULL, 0, pcm->psfFFT); 521 521 } 522 # endif 523 } 524 # else 522 # endif // TESTCOPY 523 } 524 # else // PRE_CONVOLVE 525 525 // convolve model image and derivative images with psf via FFT 526 526 psImageConvolveFFT (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psf); … … 547 547 } 548 548 # endif // PRE-CONVOLVE 549 # else 549 # else // USE_FFT 550 550 // convolve model image and derivative images with psf direct 551 551 psImageConvolveDirect (pcm->modelConvFlux, pcm->modelFlux, pcm->psf); -
trunk/psModules/src/objects/pmSourceIO_MatchedRefs.c
r36856 r39926 119 119 psMetadataAdd (row, PS_LIST_TAIL, "RA_REF", PS_DATA_F64, "right ascension (deg, J2000)", PM_DEG_RAD*ref->sky->r); 120 120 psMetadataAdd (row, PS_LIST_TAIL, "DEC_REF", PS_DATA_F64, "declination (deg, J2000)", PM_DEG_RAD*ref->sky->d); 121 psMetadataAdd (row, PS_LIST_TAIL, "RA_RAW", PS_DATA_F64, "right ascension (deg, J2000)", PM_DEG_RAD*raw->sky->r); 122 psMetadataAdd (row, PS_LIST_TAIL, "DEC_RAW", PS_DATA_F64, "declination (deg, J2000)", PM_DEG_RAD*raw->sky->d); 121 123 psMetadataAdd (row, PS_LIST_TAIL, "X_CHIP_REF", PS_DATA_F32, "x fitted coord on chip", ref->chip->x); 122 124 psMetadataAdd (row, PS_LIST_TAIL, "Y_CHIP_REF", PS_DATA_F32, "y fitted coord on chip", ref->chip->y);
Note:
See TracChangeset
for help on using the changeset viewer.
