Changeset 15884 for trunk/psModules/src/astrom/pmAstrometryTable.c
- Timestamp:
- Dec 19, 2007, 8:57:05 AM (18 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/astrom/pmAstrometryTable.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/astrom/pmAstrometryTable.c
r15676 r15884 1 /** @file pmAstrometry Objects.c1 /** @file pmAstrometryTable.c 2 2 * 3 * @brief This file defines the basic types for matching objects 4 * based on their astrometry. 3 * @brief Functions to read and write astrometric information using the generic astrometry 4 * model. 5 * 6 * The generic model does not specify the location of the boresite on the sky, and it includes 7 * a model for the rotator and motion of the boresite. 5 8 * 6 9 * @ingroup AstroImage 7 10 * 8 11 * @author EAM, IfA 12 * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2007-12-19 18:57:05 $ 9 14 * 10 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2007-11-21 12:01:10 $ 12 * 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 15 * Copyright 2007 Institute for Astronomy, University of Hawaii 14 16 */ 15 17 … … 38 40 #include "pmFPAExtent.h" 39 41 #include "pmAstrometryWCS.h" 42 #include "pmAstrometryUtils.h" 40 43 #include "pmAstrometryRegions.h" 41 44 #include "pmAstrometryTable.h" 45 46 # define REQUIRE(TEST,MESSAGE){ if (!(TEST)) { psAbort (MESSAGE); }} 42 47 43 48 /********************* CheckDataStatus functions *****************************/ … … 96 101 // write the full table in one pass: require the level to be FPA 97 102 if (view->chip != -1) { 98 psError(PS_ERR_IO, false, "Astrometry must be written at the chiplevel");103 psError(PS_ERR_IO, false, "Astrometry must be written at the FPA level"); 99 104 return false; 100 105 } … … 222 227 psMetadataAddF32(row, PS_LIST_TAIL, "XSCALE", PS_META_REPLACE, "", file->fpa->toSky->Xs * PM_DEG_RAD); 223 228 psMetadataAddF32(row, PS_LIST_TAIL, "YSCALE", PS_META_REPLACE, "", file->fpa->toSky->Ys * PM_DEG_RAD); 224 psMetadataAddF32(row, PS_LIST_TAIL, "XREF", PS_META_REPLACE, "", file->fpa->toSky->R * PM_DEG_RAD);225 psMetadataAddF32(row, PS_LIST_TAIL, "YREF", PS_META_REPLACE, "", file->fpa->toSky->D * PM_DEG_RAD);229 psMetadataAddF32(row, PS_LIST_TAIL, "XREF", PS_META_REPLACE, "", file->fpa->toSky->R * PM_DEG_RAD); 230 psMetadataAddF32(row, PS_LIST_TAIL, "YREF", PS_META_REPLACE, "", file->fpa->toSky->D * PM_DEG_RAD); 226 231 227 232 psArrayAdd (table, 100, row); … … 313 318 314 319 // set the chip name 315 char *chiprule = psStringCopy (" CHIP.{CHIP.NAME}");320 char *chiprule = psStringCopy ("{CHIP.NAME}"); 316 321 char *chipname = pmFPAfileNameFromRule (chiprule, file, view); 317 322 … … 327 332 psMetadataAddF32(row, PS_LIST_TAIL, "MAXY", PS_META_REPLACE, "range", region->y1); 328 333 329 psMetadataAddS32(row, PS_LIST_TAIL, "NX", PS_META_REPLACE, "", chip->toFPA->x->nX);330 psMetadataAddS32(row, PS_LIST_TAIL, "NY", PS_META_REPLACE, "", chip->toFPA->x->nY);334 psMetadataAddS32(row, PS_LIST_TAIL, "NX", PS_META_REPLACE, "", i); 335 psMetadataAddS32(row, PS_LIST_TAIL, "NY", PS_META_REPLACE, "", j); 331 336 psMetadataAddF32(row, PS_LIST_TAIL, "POLY_X", PS_META_REPLACE, "", chip->toFPA->x->coeff[i][j]); 332 337 psMetadataAddF32(row, PS_LIST_TAIL, "POLY_Y", PS_META_REPLACE, "", chip->toFPA->y->coeff[i][j]); … … 357 362 358 363 bool pmAstromReadForView (const pmFPAview *view, pmFPAfile *file, const pmConfig *config) 359 { 360 361 pmFPA *fpa = file->fpa; 362 363 if (view->chip == -1) { 364 return pmAstromReadFPA(fpa, view, file, config); 365 } 366 367 if (view->chip >= fpa->chips->n) { 368 psAbort("Programming error: view does not apply to FPA."); 369 } 370 pmChip *chip = fpa->chips->data[view->chip]; 371 372 if (view->cell == -1) { 373 return pmAstromReadChip(chip, view, file, config); 374 } 375 376 psError(PS_ERR_IO, false, "Astrometry must be read at the chip level"); 377 return false; 378 } 379 380 // read in fpa-level Astrometry files for this FPA, and all chips 381 bool pmAstromReadFPA (pmFPA *fpa, const pmFPAview *view, pmFPAfile *file, const pmConfig *config) 382 { 383 bool success = true; // Was everything successful? 364 { 365 366 // write the full table in one pass: require the level to be FPA 367 if (view->chip != -1) { 368 psError(PS_ERR_IO, false, "Astrometry must be read at the FPA level"); 369 return false; 370 } 371 372 if (!pmAstromReadFPA (file)) { 373 psError(PS_ERR_IO, false, "Failed to read Astrometry for fpa"); 374 return false; 375 } 376 return true; 377 } 378 379 // read out all chip-level Astrometry data for this FPA 380 bool pmAstromReadFPA (pmFPAfile *file) { 381 382 if (!pmAstromReadPHU (file)) { 383 psError(PS_ERR_IO, false, "Failed to read PHU for Astrometry table"); 384 return false; 385 } 386 387 if (!pmAstromReadChips (file)) { 388 psError(PS_ERR_IO, false, "Failed to read Astrometry for chips"); 389 return false; 390 } 391 392 if (!pmAstromReadFP (file)) { 393 psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry table"); 394 return false; 395 } 396 397 // NOTE : TP must come after FP as it applies the POS, ROT boresite corrections to the 398 // transformation determined in FP 399 if (!pmAstromReadTP (file)) { 400 psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry table"); 401 return false; 402 } 403 404 if (!pmAstromReadSky (file)) { 405 psError(PS_ERR_IO, false, "Failed to read Sky for Astrometry table"); 406 return false; 407 } 408 409 return true; 410 } 411 412 bool pmAstromReadPHU (pmFPAfile *file) { 413 414 fprintf (stderr, "not sure we need to read PHU\n"); 415 return true; 416 } 417 418 int pmConceptsChipNumberFromName (pmFPA *fpa, char *name) { 419 384 420 for (int i = 0; i < fpa->chips->n; i++) { 385 pmChip *chip = fpa->chips->data[i]; 386 success &= pmAstromReadChip(chip, view, file, config); 387 } 388 return success; 389 } 390 391 // read in chip-level Astrometry data for this chip 392 bool pmAstromReadChip (pmChip *chip, const pmFPAview *view, pmFPAfile *file, const pmConfig *config) 393 { 421 pmChip *chip = fpa->chips->data[i]; 422 if (!chip) continue; 423 char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME"); 424 if (!thisone) continue; 425 if (!strcmp (name, thisone)) return (i); 426 } 427 return -1; 428 } 429 430 pmChip *pmConceptsChipFromName (pmFPA *fpa, char *name) { 431 432 for (int i = 0; i < fpa->chips->n; i++) { 433 pmChip *chip = fpa->chips->data[i]; 434 if (!chip) continue; 435 char *thisone = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME"); 436 if (!thisone) continue; 437 if (!strcmp (name, thisone)) return (chip); 438 } 439 return NULL; 440 } 441 442 // first layer converts Chip to Focal Plane 443 bool pmAstromReadChips (pmFPAfile *file) { 444 394 445 bool status; 395 446 396 // lookup the EXTNAME values used for table data and image header segments 397 char *rule = NULL; 398 399 // Menu of EXTNAME rules 400 psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES"); 401 if (!menu) { 402 psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config"); 403 return false; 404 } 405 406 // EXTNAME for image header 407 rule = psMetadataLookupStr(&status, menu, "REF.ASTROM"); 408 if (!rule) { 409 psError(PS_ERR_UNKNOWN, false, "missing entry for REF.ASTROM in EXTNAME.RULES in camera.config"); 410 return false; 411 } 412 413 // XXX finish this: uncomment when used 414 # if (0) 415 char *extname = pmFPAfileNameFromRule (rule, file, view); 416 # endif 417 418 // read the chip elements in the following form: 419 // chipID, ...? I forget the form: look at ICD 420 421 return true; 422 } 423 447 // set FITS cursor 448 if (!psFitsMoveExtName (file->fits, "CHIPS")) { 449 psError(PS_ERR_IO, false, "missing CHIPS extension in astrometry table\n"); 450 return false; 451 } 452 453 // free exising tranformations in prep for new alloc below 454 for (int i = 0; i < file->fpa->chips->n; i++) { 455 pmChip *chip = file->fpa->chips->data[i]; 456 psFree (chip->toFPA); 457 chip->toFPA = NULL; 458 } 459 460 // XXX do I need anything from the header? 461 psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header 462 if (!header) psAbort("cannot read table header"); 463 464 // load the full table in one shot 465 psArray *table = psFitsReadTable (file->fits); 466 if (!table) psAbort("cannot read table"); 467 fprintf (stderr, "read %ld rows from FP\n", table->n); 468 469 // parse the table entries 470 for (int i = 0; i < table->n; i++) { 471 psMetadata *row = table->data[i]; 472 473 // name of the chip for this row. 474 char *chipname = psMetadataLookupStr (&status, row, "SEGMENT"); 475 476 // get chip from name 477 pmChip *chip = pmConceptsChipFromName (file->fpa, chipname); 478 REQUIRE (chip, "invalid chip name"); 479 480 // define the toFPA transform if not already defined 481 int nX = psMetadataLookupS32(&status, row, "NXORDER"); REQUIRE (status, "missing NXORDER"); 482 int nY = psMetadataLookupS32(&status, row, "NYORDER"); REQUIRE (status, "missing NYORDER"); 483 if (chip->toFPA == NULL) { 484 chip->toFPA = psPlaneTransformAlloc(nX, nY); 485 } else { 486 REQUIRE (chip->toFPA->x->nX == nX, "mismatch in chip order"); 487 REQUIRE (chip->toFPA->x->nY == nY, "mismatch in chip order"); 488 REQUIRE (chip->toFPA->y->nX == nX, "mismatch in chip order"); 489 REQUIRE (chip->toFPA->y->nY == nY, "mismatch in chip order"); 490 } 491 492 int ix = psMetadataLookupS32(&status, row, "XORDER"); REQUIRE (status, "missing XORDER"); 493 int iy = psMetadataLookupS32(&status, row, "YORDER"); REQUIRE (status, "missing YORDER"); 494 495 // XXX do I need to use this or can i rely on the camera concepts? 496 // minX = psMetadataLookupF32(&status, row, "MINX"); 497 // maxX = psMetadataLookupF32(&status, row, "MAXX"); 498 // minY = psMetadataLookupF32(&status, row, "MINY"); 499 // maxY = psMetadataLookupF32(&status, row, "MAXY"); 500 501 // XXX need to include mask values 502 chip->toFPA->x->coeff[ix][iy] = psMetadataLookupF32(&status, row, "POLY_X"); 503 chip->toFPA->y->coeff[ix][iy] = psMetadataLookupF32(&status, row, "POLY_Y"); 504 chip->toFPA->x->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_X"); 505 chip->toFPA->y->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_Y"); 506 } 507 508 // convert the toFPA transfomations to fromFPA transformations 509 for (int i = 0; i < file->fpa->chips->n; i++) { 510 pmChip *chip = file->fpa->chips->data[i]; 511 psRegion *region = pmChipPixels (chip); 512 psFree (chip->fromFPA); 513 chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50); 514 psFree (region); 515 } 516 517 psFree (table); 518 psFree (header); 519 return true; 520 } 521 522 // second layer converts Focal Plane to Tangent Plane (unrotated) 523 bool pmAstromReadFP (pmFPAfile *file) { 524 525 bool status; 526 527 if (!psFitsMoveExtName (file->fits, "FP")) { 528 psError(PS_ERR_IO, false, "missing FP extension in astrometry table\n"); 529 return false; 530 } 531 532 psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header 533 if (!header) psAbort("cannot read table header"); 534 535 // there is only one transformation in this table; the order is defined in the header 536 int nX = psMetadataLookupS32(&status, header, "NXORDER"); REQUIRE (status, "missing NXORDER"); 537 int nY = psMetadataLookupS32(&status, header, "NYORDER"); REQUIRE (status, "missing NYORDER"); 538 539 // allocate the new transformation 540 psFree (file->fpa->toTPA); 541 file->fpa->toTPA = psPlaneTransformAlloc(nX, nY); 542 543 // free & DON'T allocate the new transformation fromTPA; this is created after the boresite 544 // is applied in pmAstromReadTP 545 psFree (file->fpa->fromTPA); 546 file->fpa->fromTPA = NULL; 547 548 // read the complete table data at one shot 549 psArray *table = psFitsReadTable (file->fits); 550 fprintf (stderr, "read %ld rows from FP\n", table->n); 551 552 // parse the table 553 for (int i = 0; i < table->n; i++) { 554 psMetadata *row = table->data[i]; 555 int ix = psMetadataLookupS32(&status, row, "XORDER"); REQUIRE (status, "missing XORDER"); 556 int iy = psMetadataLookupS32(&status, row, "YORDER"); REQUIRE (status, "missing YORDER"); 557 file->fpa->toTPA->x->coeff[ix][iy] = psMetadataLookupF32(&status, row, "POLY_X"); REQUIRE (status, "missing POLY_X"); 558 file->fpa->toTPA->y->coeff[ix][iy] = psMetadataLookupF32(&status, row, "POLY_Y"); REQUIRE (status, "missing POLY_Y"); 559 file->fpa->toTPA->x->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_X"); REQUIRE (status, "missing ERROR_X"); 560 file->fpa->toTPA->y->coeffErr[ix][iy] = psMetadataLookupF32(&status, row, "ERROR_Y"); REQUIRE (status, "missing ERROR_Y"); 561 } 562 563 psFree (table); 564 psFree (header); 565 return true; 566 } 567 568 // third layer applies boresite corrections and converts tangent plane to sky 569 bool pmAstromReadTP (pmFPAfile *file) { 570 571 bool status; 572 573 // these externally supplied values are used to set the final transformation terms 574 double RA = psMetadataLookupF64 (&status, file->fpa->concepts, "FPA.RA"); REQUIRE (status, "missing FPA.RA"); 575 double DEC = psMetadataLookupF64 (&status, file->fpa->concepts, "FPA.DEC"); REQUIRE (status, "missing FPA.DEC"); 576 double POS = psMetadataLookupF64 (&status, file->fpa->concepts, "FPA.POSANGLE"); REQUIRE (status, "missing FPA.POSANGLE"); 577 double ROT = psMetadataLookupF64 (&status, file->fpa->concepts, "FPA.ROTANGLE"); REQUIRE (status, "missing FPA.ROTANGLE"); 578 579 if (!psFitsMoveExtName (file->fits, "TP")) { 580 psError(PS_ERR_IO, false, "missing TP extension in astrometry table\n"); 581 return false; 582 } 583 584 psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header 585 if (!header) psAbort("cannot read table header"); 586 587 psArray *table = psFitsReadTable (file->fits); 588 fprintf (stderr, "read %ld rows from TP\n", table->n); 589 if (table->n != 1) psAbort("invalid number of rows in TP table (%ld)", table->n); 590 591 psMetadata *row = table->data[0]; 592 593 // get projection scale; center is supplied 594 float Xs = psMetadataLookupF32(&status, row, "XSCALE") * PM_RAD_DEG; REQUIRE (status, "missing XSCALE"); 595 float Ys = psMetadataLookupF32(&status, row, "YSCALE") * PM_RAD_DEG; REQUIRE (status, "missing YSCALE"); 596 597 // allocate a new toSky projection 598 psFree (file->fpa->toSky); 599 file->fpa->toSky = psProjectionAlloc (RA, DEC, Xs, Ys, PS_PROJ_WRP); 600 601 // get boresite correction terms. L,M,T define an ellipse along which the boresite travels 602 double R_L = psMetadataLookupF32(&status, row, "ROTATOR_L"); REQUIRE (status, "missing ROTATOR_L"); 603 double R_M = psMetadataLookupF32(&status, row, "ROTATOR_M"); REQUIRE (status, "missing ROTATOR_M"); 604 double R_T = psMetadataLookupF32(&status, row, "ROTATOR_T"); REQUIRE (status, "missing ROTATOR_T"); 605 606 // the position of the boresite on the ellipse is the ROTANGLE - ROT_ZERO 607 double R_0 = psMetadataLookupF32(&status, row, "ROT_ZERO"); REQUIRE (status, "missing ROT_ZERO"); 608 609 // find the current position of the boresite for this image 610 double Lo = R_L*cos(ROT - R_0)*cos(R_T) + R_M*sin(ROT - R_0)*sin(R_T); 611 double Mo = R_M*sin(ROT - R_0)*cos(R_T) - R_L*cos(ROT - R_0)*sin(R_T); 612 613 // apply new reference pixel to transformation 614 psPlaneTransform *tmpToTPA = psPlaneTransformSetCenter (NULL, file->fpa->toTPA, Lo, Mo); 615 psFree (file->fpa->toTPA); 616 617 // apply POSANGLE 618 double Po = psMetadataLookupF32(&status, row, "POS_ZERO"); REQUIRE (status, "missing POS_ZERO"); 619 file->fpa->toTPA = psPlaneTransformRotate (NULL, tmpToTPA, POS - Po); 620 psFree (tmpToTPA); 621 622 psRegion *region = pmAstromFPAExtent (file->fpa); 623 psFree (file->fpa->fromTPA); 624 file->fpa->fromTPA = psPlaneTransformInvert(NULL, file->fpa->toTPA, *region, 50); 625 626 psFree (region); 627 psFree (table); 628 psFree (header); 629 return (true); 630 } 631 632 // first layer is the sky 633 bool pmAstromReadSky (pmFPAfile *file) { 634 635 if (!psFitsMoveExtName (file->fits, "SKY")) { 636 psError(PS_ERR_IO, false, "missing SKY extension in astrometry table\n"); 637 return false; 638 } 639 640 psMetadata *header = psFitsReadHeader(NULL, file->fits); // The FITS header 641 if (!header) psAbort("cannot read table header"); 642 643 psArray *table = psFitsReadTable (file->fits); 644 fprintf (stderr, "read %ld rows from SKY\n", table->n); 645 if (table->n != 1) psAbort("invalid number of rows in SKY table (%ld)", table->n); 646 647 // XXX not much information of interest in this table... 648 649 psFree (table); 650 psFree (header); 651 return (true); 652 } 653
Note:
See TracChangeset
for help on using the changeset viewer.
