- Timestamp:
- Sep 15, 2016, 3:10:46 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/czw_branch/20160809/psModules/src/astrom/pmAstrometryWCS.c
r39685 r39697 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 … … 280 280 // XXX if type == ZPN, look for PV2_%d elements: 281 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 present296 if ((i == 1) && !status) {297 maxRadial->data.F64[i] = 1.0;298 continue;299 }300 }301 maxRadial->n ++;302 wcs->toSky->radial = maxRadial;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 303 } 304 304 … … 314 314 // test the CDELTi varient 315 315 if (pcKeys) { 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_1325 wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2326 wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1327 wcs->trans->y->coeff[0][1] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2328 return wcs;329 }330 331 // FITS WCS PCi,j has units of unity332 // wcs->trans has units of degrees/pixel333 wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC001001"); // == PC1_1334 wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC001002"); // == PC1_2335 wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC002001"); // == PC2_1336 wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC002002"); // == PC2_2337 338 if (isPoly) {339 // Elixir-style polynomial terms340 // XXX currently, Elixir/DVO cannot accept mixed orders341 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;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; 358 358 } 359 359 360 360 // test the CDi_j varient 361 361 if (cdKeys) { 362 wcs->wcsCDkeys = 1;363 364 wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1365 wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2366 wcs->trans->y->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD2_1"); // == PC2_1367 wcs->trans->y->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD2_2"); // == PC2_2368 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;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; 371 371 } 372 372 psLogMsg ("psastro", 2, "warning: missing rotation matrix?\n"); … … 402 402 403 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 }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 410 } 411 411 … … 414 414 if (!wcs->wcsCDkeys) { 415 415 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_1423 psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2424 psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1425 psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2426 427 // Elixir-style polynomial terms428 // XXX currently, Elixir/DVO cannot accept mixed orders429 // XXX need to respect the masks430 // 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 keywords449 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 keywords457 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);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); 477 477 478 478 479 479 } else { 480 480 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 }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 } 492 492 } 493 493 … … 507 507 // cdelt1,2 has units of degree/pixel 508 508 for (int i = 0; i <= toFPA->x->nX; i++) { 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 }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 } 513 513 } 514 514 … … 524 524 psFree(fpa->toTPA); 525 525 psFree(fpa->fromTPA); 526 fpa->toTPA = psPlaneTransformIdentity (1);527 fpa->fromTPA = psPlaneTransformIdentity (1);528 fpa->toSky = toSky;526 fpa->toTPA = psPlaneTransformIdentity (1); 527 fpa->fromTPA = psPlaneTransformIdentity (1); 528 fpa->toSky = toSky; 529 529 } else { 530 530 531 // this section allows the loaded chip to be included in an fpa structure in which532 // other chips have already been loaded (ie, the fpa->toTPA, fpa->toSky components have533 // 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 chip541 // rX has units of refpixels / pixel542 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 layter553 // XXX this only works if toTPA is at most a linear transformation554 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 coordinate573 // 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 projection582 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 projection587 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);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); 598 598 } 599 599 … … 613 613 // XXX if the inversion fails, we probably do not have a valid transform anyway 614 614 if (!chip->fromFPA) { 615 psWarning ("failed to find a valid transformation");616 psFree (chip->toFPA);617 return false;615 psWarning ("failed to find a valid transformation"); 616 psFree (chip->toFPA); 617 return false; 618 618 } 619 619 620 620 // this can take a very long time... 621 621 while (fpa->toSky->R < 0) 622 fpa->toSky->R += 2.0*M_PI;622 fpa->toSky->R += 2.0*M_PI; 623 623 while (fpa->toSky->R > 2.0*M_PI) 624 fpa->toSky->R -= 2.0*M_PI;624 fpa->toSky->R -= 2.0*M_PI; 625 625 626 626 fpa->wcsCDkeys = wcs->wcsCDkeys; 627 627 628 628 psTrace ("psastro", 5, "toFPA: %f %f (%f,%f),(%f,%f)\n", 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]);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]); 632 632 633 633 psTrace ("psastro", 5, "frFPA: %f %f (%f,%f),(%f,%f)\n", 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]);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]); 637 637 638 638 return true; … … 648 648 */ 649 649 650 // create transformation with 0,0 reference pixel and units of microns/pixel651 650 psFree (chip->toFPA); 652 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; 653 660 654 661 // determine the inverse transformation: we need the chip pixels covered by this transform … … 675 682 // convert fpa->toTPA to units of unity (microns/micron) 676 683 for (int i = 0; i <= fpa->toTPA->x->nX; i++) { 677 for (int j = 0; j <= fpa->toTPA->x->nY; j++) {678 fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1;679 fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2;680 }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 } 681 688 } 682 689 … … 720 727 721 728 for (int i = 0; i <= toTPA->x->nX; i++) { 722 for (int j = 0; j <= toTPA->x->nY; j++) {723 double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];724 double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];725 toTPA->x->coeff[i][j] = f1 + f2;726 727 double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];728 double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];729 toTPA->y->coeff[i][j] = g1 + g2;730 }729 for (int j = 0; j <= toTPA->x->nY; j++) { 730 double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j]; 731 double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j]; 732 toTPA->x->coeff[i][j] = f1 + f2; 733 734 double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j]; 735 double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j]; 736 toTPA->y->coeff[i][j] = g1 + g2; 737 } 731 738 } 732 739 toTPA->x->coeff[0][0] += fpa->toTPA->x->coeff[0][0]; … … 752 759 psPlane *center = psPlaneTransformGetCenter (tpa1, tol); 753 760 if (!center) { 754 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");755 psFree (toTPA);756 psFree (tpa1);757 psFree (wcs);758 return NULL;761 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center."); 762 psFree (toTPA); 763 psFree (tpa1); 764 psFree (wcs); 765 return NULL; 759 766 } 760 767 … … 789 796 // convert wcs->trans to a matrix with units of degrees/pixel 790 797 for (int i = 0; i <= wcs->trans->x->nX; i++) { 791 for (int j = 0; j <= wcs->trans->x->nY; j++) {792 wcs->trans->x->coeff[i][j] *= pdelt1;793 wcs->trans->y->coeff[i][j] *= pdelt2;794 }798 for (int j = 0; j <= wcs->trans->x->nY; j++) { 799 wcs->trans->x->coeff[i][j] *= pdelt1; 800 wcs->trans->y->coeff[i][j] *= pdelt2; 801 } 795 802 } 796 803 … … 811 818 */ 812 819 813 // convert the chip-level toFPA to a wcs polynomial transformation 820 // convert the chip-level toFPA to a wcs polynomial transformation. the pmAstromWCS 821 // structure represents a single layer transformation (e.g., RA-TAN, RA-WRP). Here we are 822 // converting the chip-level to a WRP projection in the structure. Later, this will be 823 // converted to the WCS keywords 824 814 825 pmAstromWCS *pmAstromWCSBilevelChipFromFPA (const pmChip *chip, double tol) 815 826 { … … 822 833 pmAstromWCS *wcs = pmAstromWCSAlloc(chip->toFPA->x->nX, chip->toFPA->x->nY); 823 834 835 // copy the toFPA x,y, transformations to the wcs version 836 wcs->trans->x = psPolynomial2DCopy (wcs->trans->x, chip->toFPA->x); 837 wcs->trans->y = psPolynomial2DCopy (wcs->trans->y, chip->toFPA->y); 838 824 839 // Chip to FPA transformation is a Cartesian 'projection' 825 840 // reference pixel for FPA is 0.0, 0.0 826 841 wcs->toSky = psProjectionAlloc (0.0, 0.0, 1.0, 1.0, PS_PROJ_WRP); 827 wcs->crval1 = 0.0; 828 wcs->crval2 = 0.0; 829 830 // given transformation, solve for coordinates which yields output coordinates of 0,0 831 psPlane *center = psPlaneTransformGetCenter (chip->toFPA, tol); 832 if (!center) { 833 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center."); 834 psFree (wcs); 835 return NULL; 836 } 837 838 // adjust wcs transform to use center as reference coordinate 839 // resulting transformation has units of microns/pixel 840 psPlaneTransformSetCenter (wcs->trans, chip->toFPA, center->x, center->y); 841 842 // calculated center is crpix1,2 843 wcs->crpix1 = center->x; 844 wcs->crpix2 = center->y; 845 psFree (center); 846 842 843 // reference pixel (CRPIX1,2) is (0.0, 0.0): 844 wcs->crpix1 = 0.0; 845 wcs->crpix2 = 0.0; 846 847 // we need to set CRVAL1,2 for the 0,0 pixel: 848 wcs->crval1 = psPolynomial2DEval (chip->toFPA->x, 0.0, 0.0); 849 wcs->crval2 = psPolynomial2DEval (chip->toFPA->y, 0.0, 0.0); 850 851 wcs->toSky->R = wcs->crval1*PM_RAD_DEG; 852 wcs->toSky->D = wcs->crval2*PM_RAD_DEG; 853 854 // these need to be set to 0.0 since they have been moved to crpix1,crpix2 855 wcs->trans->x->coeff[0][0] = 0.0; 856 wcs->trans->y->coeff[0][0] = 0.0; 857 847 858 // output coordinates are in microns : CDELT1,2 has units of microns/pixel 848 859 wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]); … … 872 883 psPlane *center = psPlaneTransformGetCenter (fpa->toTPA, tol); 873 884 if (!center) { 874 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");875 psFree (wcs);876 return NULL;885 psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center."); 886 psFree (wcs); 887 return NULL; 877 888 } 878 889 … … 892 903 // convert wcs->trans to units of degree/micron 893 904 for (int i = 0; i <= wcs->trans->x->nX; i++) { 894 for (int j = 0; j <= wcs->trans->x->nY; j++) {895 wcs->trans->x->coeff[i][j] *= pdelt1;896 wcs->trans->y->coeff[i][j] *= pdelt2;897 }905 for (int j = 0; j <= wcs->trans->x->nY; j++) { 906 wcs->trans->x->coeff[i][j] *= pdelt1; 907 wcs->trans->y->coeff[i][j] *= pdelt2; 908 } 898 909 } 899 910 … … 918 929 int k=0; 919 930 for (int j=0; j<nSamples; j++) { 920 double y = bounds->y0 + (j * deltaY / nSamples);921 for (int i=0; i<nSamples; i++) {922 psPlane *s = psPlaneAlloc();923 s->x = bounds->x0 + (i * deltaX / nSamples);924 s->y = y;925 psArraySet(src, k, s);926 psPlane *d = psPlaneTransformApply(NULL, trans, s);927 psArraySet(dst, k, d);928 psFree(s); // drop our refs to s and d929 psFree(d);930 ++k;931 }931 double y = bounds->y0 + (j * deltaY / nSamples); 932 for (int i=0; i<nSamples; i++) { 933 psPlane *s = psPlaneAlloc(); 934 s->x = bounds->x0 + (i * deltaX / nSamples); 935 s->y = y; 936 psArraySet(src, k, s); 937 psPlane *d = psPlaneTransformApply(NULL, trans, s); 938 psArraySet(dst, k, d); 939 psFree(s); // drop our refs to s and d 940 psFree(d); 941 ++k; 942 } 932 943 } 933 944 … … 935 946 936 947 if (!psPlaneTransformFit(newTrans, src, dst, 0, 0)) { 937 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");938 return NULL;948 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed"); 949 return NULL; 939 950 } 940 951 … … 945 956 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"); 946 957 for (int i=0; i<psArrayLength(dst); i++) { 947 psPlane *d = (psPlane *) psArrayGet(dst, i);948 psPlane *s = (psPlane *) psArrayGet(src, i);949 950 new = psPlaneTransformApply(new, newTrans, s);951 952 double xerr = new->x - d->x;953 double yerr = new->y - d->y;954 bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5);955 printf("%4d %9.2f %9.2f %9.2f %9.4f %9.2f %9.2f %9.2f %9.4f %s\n"956 , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : "");958 psPlane *d = (psPlane *) psArrayGet(dst, i); 959 psPlane *s = (psPlane *) psArrayGet(src, i); 960 961 new = psPlaneTransformApply(new, newTrans, s); 962 963 double xerr = new->x - d->x; 964 double yerr = new->y - d->y; 965 bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5); 966 printf("%4d %9.2f %9.2f %9.2f %9.4f %9.2f %9.2f %9.2f %9.4f %s\n" 967 , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : ""); 957 968 } 958 969 psFree(new); … … 972 983 973 984 if (outFPA == NULL) { 974 outFPA = inFPA;985 outFPA = inFPA; 975 986 } 976 987 if (outChip == NULL) { 977 outChip = inChip;988 outChip = inChip; 978 989 } 979 990 if (outputBounds == NULL) { 980 outputBounds = pmChipPixels(outChip);991 outputBounds = pmChipPixels(outChip); 981 992 } 982 993 … … 984 995 psPlaneTransform *chipToTPA = psPlaneTransformCombine(NULL, inChip->toFPA, inFPA->toTPA, *outputBounds, 50); 985 996 if (!chipToTPA) { 986 psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA");987 return false;997 psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA"); 998 return false; 988 999 } 989 1000 … … 992 1003 psFree(chipToTPA); 993 1004 if (!chipToFPA) { 994 psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed");995 return false;1005 psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed"); 1006 return false; 996 1007 } 997 1008 … … 999 1010 psPlaneTransform *outToFPA; 1000 1011 if (offset_x != 0. && offset_y != 0.) { 1001 outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y);1002 psFree(chipToFPA);1012 outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y); 1013 psFree(chipToFPA); 1003 1014 } else { 1004 outToFPA = chipToFPA;1015 outToFPA = chipToFPA; 1005 1016 } 1006 1017 1007 1018 psPlaneTransform *outFromFPA = psPlaneTransformInvert(NULL, outToFPA, *outputBounds, 50); 1008 1019 if (!outFromFPA) { 1009 psFree(outToFPA);1010 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");1011 return false;1020 psFree(outToFPA); 1021 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed"); 1022 return false; 1012 1023 } 1013 1024 … … 1061 1072 1062 1073 for (int j = 0; j < nSamples; j++) { 1063 double y = bounds->y0 + (j * deltaY / nSamples);1064 for (int i = 0; i < nSamples; i++) {1065 1066 psSphere srcSky;1067 psPlane *srcChip = psPlaneAlloc();1068 psPlane *dstTP = psPlaneAlloc();1069 1070 srcChip->x = bounds->x0 + (i * deltaX / nSamples);1071 srcChip->y = y;1072 1073 psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip);1074 psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP);1075 psDeproject (&srcSky, &srcTP, inFPA->toSky);1076 1077 // 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);1078 1079 psProject (dstTP, &srcSky, outFPA->toSky);1080 1081 srcChip->x -= bounds->x0;1082 srcChip->y -= bounds->y0;1083 psArrayAdd (src, 100, srcChip);1084 psArrayAdd (dst, 100, dstTP);1085 1086 psFree(srcChip); // drop our refs to s and d1087 psFree(dstTP);1088 }1074 double y = bounds->y0 + (j * deltaY / nSamples); 1075 for (int i = 0; i < nSamples; i++) { 1076 1077 psSphere srcSky; 1078 psPlane *srcChip = psPlaneAlloc(); 1079 psPlane *dstTP = psPlaneAlloc(); 1080 1081 srcChip->x = bounds->x0 + (i * deltaX / nSamples); 1082 srcChip->y = y; 1083 1084 psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip); 1085 psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP); 1086 psDeproject (&srcSky, &srcTP, inFPA->toSky); 1087 1088 // 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); 1089 1090 psProject (dstTP, &srcSky, outFPA->toSky); 1091 1092 srcChip->x -= bounds->x0; 1093 srcChip->y -= bounds->y0; 1094 psArrayAdd (src, 100, srcChip); 1095 psArrayAdd (dst, 100, dstTP); 1096 1097 psFree(srcChip); // drop our refs to s and d 1098 psFree(dstTP); 1099 } 1089 1100 } 1090 1101 … … 1094 1105 1095 1106 if (!psPlaneTransformFit(newToFPA, src, dst, 0, 0)) { 1096 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");1097 psFree(src);1098 psFree(dst);1099 return NULL;1107 psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed"); 1108 psFree(src); 1109 psFree(dst); 1110 return NULL; 1100 1111 } 1101 1112 … … 1103 1114 for (int i = 0; i < src->n; i++) { 1104 1115 1105 psSphere srcSky, dstSky;1106 psPlane *srcChip = src->data[i];1107 psPlane *dstTP = dst->data[i];1108 1109 psPlaneTransformApply (&srcFP, newToFPA, srcChip);1110 psDeproject (&srcSky, &srcFP, outFPA->toSky);1111 psDeproject (&dstSky, dstTP, outFPA->toSky);1112 1113 double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0;1114 double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0;1115 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);1116 psSphere srcSky, dstSky; 1117 psPlane *srcChip = src->data[i]; 1118 psPlane *dstTP = dst->data[i]; 1119 1120 psPlaneTransformApply (&srcFP, newToFPA, srcChip); 1121 psDeproject (&srcSky, &srcFP, outFPA->toSky); 1122 psDeproject (&dstSky, dstTP, outFPA->toSky); 1123 1124 double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0; 1125 double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0; 1126 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); 1116 1127 1117 1128 } … … 1124 1135 psPlaneTransform *newFromFPA = psPlaneTransformInvert(NULL, newToFPA, *bounds, 1); 1125 1136 if (!newFromFPA) { 1126 psFree(newToFPA);1127 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");1128 return false;1137 psFree(newToFPA); 1138 psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed"); 1139 return false; 1129 1140 } 1130 1141 … … 1149 1160 1150 1161 if (!wcs) 1151 return;1162 return; 1152 1163 psFree (wcs->trans); 1153 1164 psFree (wcs->toSky); … … 1171 1182 /***** 1172 1183 1173 For mosaic astrometry, we need to have a starting set of projection terms in which the1174 chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or1175 microns). This set of projections, coupled with an identity toTPA (ie, no distortion) will1176 result in substantial errors between the observed and predicted star positions on the focal1177 plane: this is the measurement of the optical distortion in the camera. At the same time,1178 we need to carry around the transformations which allow us to make an accurate calculation1179 of the position of the stars based on the input (per-chip) astrometry. These1180 transformations will allow us to match the raw and ref stars robustly. To convert the1181 per-chip astrometry (which may have been calculated with a different plate scale for each1182 chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust1183 the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for1184 each chip (eg, cdelt1). Thus, we need to carry around both the1184 For mosaic astrometry, we need to have a starting set of projection terms in which the 1185 chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or 1186 microns). This set of projections, coupled with an identity toTPA (ie, no distortion) will 1187 result in substantial errors between the observed and predicted star positions on the focal 1188 plane: this is the measurement of the optical distortion in the camera. At the same time, 1189 we need to carry around the transformations which allow us to make an accurate calculation 1190 of the position of the stars based on the input (per-chip) astrometry. These 1191 transformations will allow us to match the raw and ref stars robustly. To convert the 1192 per-chip astrometry (which may have been calculated with a different plate scale for each 1193 chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust 1194 the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for 1195 each chip (eg, cdelt1). Thus, we need to carry around both the 1185 1196 1186 1197 *****/
Note:
See TracChangeset
for help on using the changeset viewer.
