IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 19515


Ignore:
Timestamp:
Sep 11, 2008, 3:09:39 PM (18 years ago)
Author:
eugene
Message:

various fixes to make the model and guess consistent wrt boresite coords

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psastro/src/psastroModelAdjust.c

    r15891 r19515  
    11# include "psastroStandAlone.h"
    22# define NONLIN_TOL 0.001 /* tolerance in pixels */
     3# define DEBUG 0
     4
     5bool psastroModelAdjustBoresite (pmFPAfile *output, pmChip *refChip);
    36
    47bool psastroModelAdjust (pmConfig *config) {
     
    1316    }
    1417
     18    // if we have not measured the boresite position, no adjustment is needed
     19    bool fitBoresite = psMetadataLookupBool (&status, recipe, "PSASTRO.MODEL.FIT.BORESITE");
     20    if (!status) psAbort ("Can't find recipe option PSASTRO.MODEL.FIT.BORESITE");
     21
     22    // as an alternative to fit the boresite from a rotation sequence, we can set the boresite
     23    // relative to the reference chip coordinates
     24    bool setBoresite = psMetadataLookupBool (&status, recipe, "PSASTRO.MODEL.SET.BORESITE");
     25    if (!status) psAbort ("Can't find recipe option PSASTRO.MODEL.SET.BORESITE");
     26
     27    if (fitBoresite && setBoresite) {
     28        psError(PS_ERR_IO, true, "invalid to choose both FIT.BORESITE and SET.BORESITE");
     29        return false;
     30    }
     31       
    1532    pmFPAfile *output = psMetadataLookupPtr (&status, config->files, "PSASTRO.OUT.MODEL");
    1633    if (!status) psAbort ("Can't find output pmFPAfile PSASTRO.OUT.MODEL");
     
    2946    if (!refChip->toFPA) psAbort ("invalid astrometry for reference chip");
    3047
    31     psPlane *boreCH = psPlaneAlloc();
    32     psPlane *boreFP = psPlaneAlloc();   
    33     psPlane *boreTP = psPlaneAlloc();   
     48    // save the TPA region for tranformation inversions below
     49    // psRegion *tpaRegion = pmAstromFPInTP (output->fpa);
     50    psRegion *fpaRegion = pmAstromFPAExtent (output->fpa);
     51
     52    if (DEBUG) psastroDumpCorners ("corners.up.raw.dat", "corners.dn.raw.dat", output->fpa);
     53
     54    if (setBoresite) {
     55        float boreXchip = psMetadataLookupF32 (&status, recipe, "PSASTRO.MODEL.BORESITE.X");
     56        float boreYchip = psMetadataLookupF32 (&status, recipe, "PSASTRO.MODEL.BORESITE.Y");
     57        psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.X0", PS_META_REPLACE, "boresite parameter", boreXchip);
     58        psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.Y0", PS_META_REPLACE, "boresite parameter", boreYchip);
     59    }
     60
     61    if (fitBoresite || setBoresite) {
     62        psastroModelAdjustBoresite (output, refChip);
     63    } else {
     64        // FPA.BORE.X0,Y0 should be 0,0 in the focal plane, not the chip.  Ask for the
     65        // coordinates which make refChip->toFPA(x,y) = (0,0)
     66        psPlane *PT = psPlaneTransformGetCenter (refChip->toFPA, NONLIN_TOL);
     67        psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.X0", PS_META_REPLACE, "boresite parameter", PT->x);
     68        psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.Y0", PS_META_REPLACE, "boresite parameter", PT->y);
     69        psFree (PT);
     70    }
     71
     72    // rotate the chip-to-FPA transforms to have 0.0 posangle for refChip;
     73    // compensate by rotating fpa to TPA transform
     74
     75    // get the current posangle of the ref chip
     76    float chipAngle = atan2 (refChip->toFPA->y->coeff[1][0], refChip->toFPA->x->coeff[1][0]);
     77    fprintf (stderr, "chipAngle: %f\n", chipAngle*PS_DEG_RAD);
     78    // psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "boresite parameter", posangle);
     79
     80    // rotate the chip transforms
     81    for (int i = 0; i < output->fpa->chips->n; i++) {
     82        pmChip *chip = output->fpa->chips->data[i];
     83        if (!chip->toFPA) continue;
     84        // skip chips without astrometry
     85
     86        // save the region of this chip for the inversion below
     87        psRegion *region = pmChipPixels (chip);
     88
     89        psPlaneTransform *toFPA = psPlaneTransformRotate (NULL, chip->toFPA, chipAngle);
     90        psFree (chip->toFPA);
     91        chip->toFPA = toFPA;
     92
     93        // invert the new fromFPA transform to get the new toFPA transform
     94        psPlaneTransform *fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
     95        psFree (chip->fromFPA);
     96        chip->fromFPA = fromFPA;
     97
     98        psFree (region);
     99
     100        // save the transformation in the header
     101        pmAstromWriteBilevelChip (chip->hdu->header, chip, NONLIN_TOL);
     102    }
     103
     104    // get the current posangle of the fpa
     105    float fpaAngle = atan2 (output->fpa->toTPA->y->coeff[1][0], output->fpa->toTPA->x->coeff[1][0]);
     106    fprintf (stderr, "fpaAngle: %f\n", fpaAngle*PS_DEG_RAD);
     107    // psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "boresite parameter", posangle);
     108
     109    // remove the fpa rotation to generate a rotation-free model
     110    psPlaneTransform *toTPA = psPlaneTransformRotate (NULL, output->fpa->toTPA, fpaAngle);
     111    psFree (output->fpa->toTPA);
     112    output->fpa->toTPA = toTPA;
     113
     114    psFree (output->fpa->fromTPA);
     115    output->fpa->fromTPA = psPlaneTransformInvert(NULL, output->fpa->toTPA, *fpaRegion, 50);
     116
     117    // the model now describes the unrotated focal-plane
     118    if (DEBUG) psastroDumpCorners ("corners.up.rot.dat", "corners.dn.rot.dat", output->fpa);
     119
     120    psMetadata *header = output->fpa->hdu->header;
     121    pmAstromWriteBilevelMosaic (header, output->fpa, NONLIN_TOL);
     122
     123    psFree (fpaRegion);
     124
     125    return true;
     126}
     127
     128bool psastroModelAdjustBoresite (pmFPAfile *output, pmChip *refChip) {
     129
     130    bool status;
     131
     132    psPlane  *boreCH  = psPlaneAlloc();
     133    psPlane  *boreFP  = psPlaneAlloc();   
     134    psPlane  *boreTP  = psPlaneAlloc();   
    34135    psSphere *boreSky = psSphereAlloc();   
    35136
     
    46147        // skip the chips without astrometry
    47148
    48         psPlaneTransform *fromFPA = psPlaneTransformSetCenter (NULL, chip->fromFPA, boreFP->x, boreFP->y);
     149        // save the FPA region of this chip for the inversion below
     150        psRegion *region = pmChipPixels (chip);
     151
     152        // the current toFPA returns boreFP->x,y for the boresite; subtract this from the transformations
     153        chip->toFPA->x->coeff[0][0] -= boreFP->x;
     154        chip->toFPA->y->coeff[0][0] -= boreFP->y;
     155
     156        // psPlaneTransform *toFPA = psPlaneTransformSetCenter (NULL, chip->toFPA, -boreFP->x, -boreFP->y);
     157        // psFree (chip->toFPA);
     158        // chip->toFPA = toFPA;
     159
     160        // invert the new fromFPA transform to get the new toFPA transform
     161        // the region used here is the region covered by the chip in the FPA
     162        psPlaneTransform *fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
    49163        psFree (chip->fromFPA);
    50164        chip->fromFPA = fromFPA;
    51165
    52         // invert the new fromFPA transform to get the new toFPA transform
    53         psRegion *region = pmChipPixels (chip);
    54         psFree (chip->toFPA);
    55         chip->toFPA = psPlaneTransformInvert(NULL, chip->fromFPA, *region, 50);
    56166        psFree (region);
    57167    }
    58168
    59     // XXX we have now shifted the (0,0) pixel of the focal plane to the true boresite from the
    60     // reported boresite.  At this point, we need to shift the tangent plane to use the new
    61     // center as well.  if the toTPA transform were not linear, we would need to modify fromFPA
    62     // to yield 0,0 at the new boresite location (ie, find Po,Qo = toTPA(Lo,Mo), probably could modify the
    63     // toTPA/fromTPA transforms to use the new ref pixel, but this would only give us a tranf
    64 
    65     // save the old (L,M) = (0,0) TP coordinate
    66     float Po = output->fpa->toTPA->x->coeff[0][0];
    67     float Qo = output->fpa->toTPA->y->coeff[0][0];
    68 
    69     // the new toTPA yields the same TP coordinates for FP coordinates offset by Lo,Mo
    70     psPlaneTransform *toTPA = psPlaneTransformSetCenter (NULL, output->fpa->toTPA, boreFP->x, boreFP->y);
    71     psFree (output->fpa->toTPA);
    72     output->fpa->toTPA = toTPA;
    73    
    74     // we are going to shift P,Q to have toTPA(0,0) = Po, Qo. 
    75     // find the sky coordinates of the 0,0 pixel for the new frame
    76     boreTP->x = output->fpa->toTPA->x->coeff[0][0] - Po;
    77     boreTP->y = output->fpa->toTPA->y->coeff[0][0] - Qo;
     169    if (DEBUG) psastroDumpCorners ("corners.up.shf.dat", "corners.dn.shf.dat", output->fpa);
     170
     171    // we have now adjusted the chips to use the correct boresite position as the center of the focal-plane system.
     172    // we now need to reconstruct the TP to FP transformation, starting from stars projected about this new boresite position.
     173
     174    // find the R,D of the new boresite (boreFP -> 0,0; 0,0 -> -boreFP)
     175    boreFP->x = -boreFP->x;
     176    boreFP->y = -boreFP->y;
     177    psPlaneTransformApply (boreTP, output->fpa->toTPA, boreFP);
    78178    psDeproject (boreSky, boreTP, output->fpa->toSky); // find the RA,DEC coord of the focal-plane coordinate
    79179
    80     // adjust the new TP frame to yield the same old (L,M) = 0,0 TP coordinate:
    81     output->fpa->toTPA->x->coeff[0][0] = Po;
    82     output->fpa->toTPA->y->coeff[0][0] = Qo;
    83 
    84     // set the projection to use the new (P,Q) = (0,0) position
    85     output->fpa->toSky->R = boreSky->r;
    86     output->fpa->toSky->D = boreSky->d;
    87 
     180    psProjection *newSky = psProjectionAlloc (boreSky->r, boreSky->d, output->fpa->toSky->Xs, output->fpa->toSky->Ys, output->fpa->toSky->type);
     181
     182    // generate a collection of points on the sky using the old toTPA transformation and toSky projection, projected with the newSky projection
     183    // this is the FPA coordinate range covered by the FP:
    88184    psRegion *fpaRegion = pmAstromFPAExtent (output->fpa);
    89 
    90     psFree (output->fpa->fromTPA);
    91     output->fpa->fromTPA = psPlaneTransformInvert(NULL, output->fpa->toTPA, *fpaRegion, 50);
    92 
    93     // rotate the chip to FPA transforms to have 0.0 posangle;
    94     // compensate by rotating fpa to TPA transforms
    95 
    96     // get the current posangle of the ref chip
    97     float posangle = atan2 (refChip->toFPA->y->coeff[1][0], refChip->toFPA->x->coeff[1][0]);
    98     psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "boresite parameter", posangle);
    99 
    100     // rotate the chip transforms
    101     for (int i = 0; i < output->fpa->chips->n; i++) {
    102         pmChip *chip = output->fpa->chips->data[i];
    103         if (!chip->toFPA) continue;
    104         // skip chips without astrometry
    105 
    106         psPlaneTransform *toFPA = psPlaneTransformRotate (NULL, chip->toFPA, posangle);
    107         psFree (chip->toFPA);
    108         chip->toFPA = toFPA;
    109 
    110         // invert the new fromFPA transform to get the new toFPA transform
    111         psRegion *region = pmChipPixels (chip);
    112         psFree (chip->fromFPA);
    113         chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50);
    114         psFree (region);
    115 
    116         // XXX temporary output dump
    117         psMetadata *header = chip->hdu->header;
    118         // XXX to make the output single-level, this needs to be in a loop *after* the fromTPA rotation below
    119         // pmAstromWriteWCS (header, output->fpa, chip, NONLIN_TOL);
    120         pmAstromWriteBilevelChip (header, chip, NONLIN_TOL);
    121     }
    122 
    123     psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, output->fpa->fromTPA, posangle);
    124     psFree (output->fpa->fromTPA);
    125     output->fpa->fromTPA = fromTPA;
    126 
    127     psFree (output->fpa->toTPA);
    128     output->fpa->toTPA = psPlaneTransformInvert(NULL, output->fpa->fromTPA, *fpaRegion, 50);
    129 
    130     psMetadata *header = output->fpa->hdu->header;
    131     pmAstromWriteBilevelMosaic (header, output->fpa, NONLIN_TOL);
    132 
     185    float dx = (fpaRegion->x1 - fpaRegion->x0) / 50.0;
     186    float dy = (fpaRegion->y1 - fpaRegion->y0) / 50.0;
     187
     188    psPlane fp, tp;
     189    psSphere sky;
     190
     191    psVector *FPx = psVectorAllocEmpty (100, PS_TYPE_F32);
     192    psVector *FPy = psVectorAllocEmpty (100, PS_TYPE_F32);
     193    psVector *TPx = psVectorAllocEmpty (100, PS_TYPE_F32);
     194    psVector *TPy = psVectorAllocEmpty (100, PS_TYPE_F32);
     195
     196    // XXX a test: boreFP->x,y, should transform to tp.x,y = 0,0
     197    fp.x = boreFP->x;
     198    fp.y = boreFP->y;
     199    psPlaneTransformApply (&tp, output->fpa->toTPA, &fp);
     200    psDeproject (&sky, &tp, output->fpa->toSky); // find the RA,DEC coord of the focal-plane coordinate
     201    psProject (&tp, &sky, newSky); // find the RA,DEC coord of the focal-plane coordinate
     202
     203    int Npts = 0;
     204    for (fp.x = fpaRegion->x0; fp.x <= fpaRegion->x1; fp.x += dx) {
     205        for (fp.y = fpaRegion->y0; fp.y <= fpaRegion->y1; fp.y += dy) {
     206            psPlaneTransformApply (&tp, output->fpa->toTPA, &fp);
     207            psDeproject (&sky, &tp, output->fpa->toSky); // find the RA,DEC coord of the focal-plane coordinate
     208            psProject (&tp, &sky, newSky); // find the RA,DEC coord of the focal-plane coordinate
     209
     210            // we are fitting points in the NEW FP system to points in the NEW TP system
     211            FPx->data.F32[Npts] = fp.x - boreFP->x;
     212            FPy->data.F32[Npts] = fp.y - boreFP->y;
     213            TPx->data.F32[Npts] = tp.x;
     214            TPy->data.F32[Npts] = tp.y;
     215            psVectorExtend (FPx, 100, 1);
     216            psVectorExtend (FPy, 100, 1);
     217            psVectorExtend (TPx, 100, 1);
     218            psVectorExtend (TPy, 100, 1);
     219            Npts ++;
     220        }
     221    }
    133222    psFree (fpaRegion);
    134223
     224    // fit both up and down transformations to the same points
     225    psVectorFitPolynomial2D (output->fpa->toTPA->x, NULL, 0, TPx, NULL, FPx, FPy);
     226    psVectorFitPolynomial2D (output->fpa->toTPA->y, NULL, 0, TPy, NULL, FPx, FPy);
     227    psVectorFitPolynomial2D (output->fpa->fromTPA->x, NULL, 0, FPx, NULL, TPx, TPy);
     228    psVectorFitPolynomial2D (output->fpa->fromTPA->y, NULL, 0, FPy, NULL, TPx, TPy);
     229
     230    psFree (output->fpa->toSky);
     231    output->fpa->toSky = newSky;
     232
     233    if (DEBUG) psastroDumpCorners ("corners.up.bore.dat", "corners.dn.bore.dat", output->fpa);
     234
     235    psFree (FPx);
     236    psFree (FPy);
     237    psFree (TPx);
     238    psFree (TPy);
     239
     240    psFree (boreCH);
     241    psFree (boreFP);
     242    psFree (boreTP);
     243    psFree (boreSky);
    135244    return true;
    136245}
Note: See TracChangeset for help on using the changeset viewer.