IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Feb 9, 2009, 11:25:34 AM (17 years ago)
Author:
Paul Price
Message:

Merging cnb_branch_20090113. No major conflicts. Compiles, but not tested.

File:
1 edited

Legend:

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

    r21409 r21422  
    11/** @file psastroFixChips.c
    22 *
    3  *  @brief 
     3 *  @brief
    44 *
    55 *  @ingroup libpsastro
    66 *
    77 *  @author IfA
    8  *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2009-02-07 02:03:34 $
     8 *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2009-02-09 21:25:34 $
    1010 *  Copyright 2009 Institute for Astronomy, University of Hawaii
    1111 */
     
    2525    bool fixChips = psMetadataLookupBool (&status, config->arguments, "PSASTRO.FIX.CHIPS");
    2626    if (!status) {
    27         fixChips = psMetadataLookupBool (&status, recipe, "PSASTRO.FIX.CHIPS");
     27        fixChips = psMetadataLookupBool (&status, recipe, "PSASTRO.FIX.CHIPS");
    2828    }
    2929    if (!fixChips) return true;
     
    3737    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
    3838    if (!input) {
    39         psError(PSASTRO_ERR_CONFIG, true, "Can't find input data");
    40         return false;
     39        psError(PSASTRO_ERR_CONFIG, true, "Can't find input data");
     40        return false;
    4141    }
    4242
     
    6060    // files associated with the science image
    6161    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
    62         psError (PS_ERR_IO, false, "Can't load the astrometry model file");
    63         return false;
     62        psError (PS_ERR_IO, false, "Can't load the astrometry model file");
     63        return false;
    6464    }
    6565
     
    7676
    7777    if (DEBUG) {
    78         f = fopen ("corners.raw.dat", "w");
    79         chipName = NULL;
     78        f = fopen ("corners.raw.dat", "w");
     79        chipName = NULL;
    8080    }
    8181
    8282    pmChip *obsChip = NULL;
    8383    while ((obsChip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
    84         if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }
    85 
    86         // XXX we are currently inconsistent with marking the good vs the bad data
    87         // psastroChipAstrom sets data_exists to false if the fit is bad.  this is
    88         // probably wrong since it implies there is no data!
    89 
    90         // skip chips for which the astrometry failed (NASTRO == 0)
    91         if (!obsChip->cells->n) continue;
    92         pmCell *cell = obsChip->cells->data[0];
    93         if (!cell) continue;
    94 
    95         if (!cell->readouts->n) continue;
    96         pmReadout *readout = cell->readouts->data[0];
    97         if (!readout) continue;
    98 
    99         psMetadata *updates = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
    100         if (!updates) continue;
    101        
    102         int nAstro = psMetadataLookupS32 (&status, updates, "NASTRO");
    103         if (!nAstro) continue;
    104 
    105         // set the chip astrometry using the astrom file
    106         pmChip *refChip = pmFPAviewThisChip (view, astrom->fpa);
    107 
    108         psRegion *region = pmChipPixels (obsChip);
    109         psPlane ptCP, ptFP;
    110 
    111         ptCP.x = region->x0; ptCP.y = region->y0;
    112         psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
    113         xObs->data.F32[nPts] = ptFP.x;
    114         yObs->data.F32[nPts] = ptFP.y;
    115         psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
    116         xRef->data.F32[nPts] = ptFP.x;
    117         yRef->data.F32[nPts] = ptFP.y;
    118 
    119         if (DEBUG) {
    120             chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
    121             fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
    122         }
    123         nPts ++;
    124 
    125         ptCP.x = region->x0; ptCP.y = region->y1;
    126         psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
    127         xObs->data.F32[nPts] = ptFP.x;
    128         yObs->data.F32[nPts] = ptFP.y;
    129         psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
    130         xRef->data.F32[nPts] = ptFP.x;
    131         yRef->data.F32[nPts] = ptFP.y;
    132 
    133         if (DEBUG) {
    134             chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
    135             fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
    136         }
    137         nPts ++;
    138 
    139         ptCP.x = region->x1; ptCP.y = region->y1;
    140         psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
    141         xObs->data.F32[nPts] = ptFP.x;
    142         yObs->data.F32[nPts] = ptFP.y;
    143         psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
    144         xRef->data.F32[nPts] = ptFP.x;
    145         yRef->data.F32[nPts] = ptFP.y;
    146 
    147         if (DEBUG) {
    148             chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
    149             fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
    150         }
    151         nPts ++;
    152 
    153         ptCP.x = region->x1; ptCP.y = region->y0;
    154         psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
    155         xObs->data.F32[nPts] = ptFP.x;
    156         yObs->data.F32[nPts] = ptFP.y;
    157         psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
    158         xRef->data.F32[nPts] = ptFP.x;
    159         yRef->data.F32[nPts] = ptFP.y;
    160 
    161         if (DEBUG) {
    162             chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
    163             fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
    164         }
    165         nPts ++;
    166 
    167         psFree (region);
     84        if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }
     85
     86        // XXX we are currently inconsistent with marking the good vs the bad data
     87        // psastroChipAstrom sets data_exists to false if the fit is bad.  this is
     88        // probably wrong since it implies there is no data!
     89
     90        // skip chips for which the astrometry failed (NASTRO == 0)
     91        if (!obsChip->cells->n) continue;
     92        pmCell *cell = obsChip->cells->data[0];
     93        if (!cell) continue;
     94
     95        if (!cell->readouts->n) continue;
     96        pmReadout *readout = cell->readouts->data[0];
     97        if (!readout) continue;
     98
     99        psMetadata *updates = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
     100        if (!updates) continue;
     101
     102        int nAstro = psMetadataLookupS32 (&status, updates, "NASTRO");
     103        if (!nAstro) continue;
     104
     105        // set the chip astrometry using the astrom file
     106        pmChip *refChip = pmFPAviewThisChip (view, astrom->fpa);
     107
     108        psRegion *region = pmChipPixels (obsChip);
     109        psPlane ptCP, ptFP;
     110
     111        ptCP.x = region->x0; ptCP.y = region->y0;
     112        psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
     113        xObs->data.F32[nPts] = ptFP.x;
     114        yObs->data.F32[nPts] = ptFP.y;
     115        psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
     116        xRef->data.F32[nPts] = ptFP.x;
     117        yRef->data.F32[nPts] = ptFP.y;
     118
     119        if (DEBUG) {
     120            chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
     121            fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
     122        }
     123        nPts ++;
     124
     125        ptCP.x = region->x0; ptCP.y = region->y1;
     126        psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
     127        xObs->data.F32[nPts] = ptFP.x;
     128        yObs->data.F32[nPts] = ptFP.y;
     129        psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
     130        xRef->data.F32[nPts] = ptFP.x;
     131        yRef->data.F32[nPts] = ptFP.y;
     132
     133        if (DEBUG) {
     134            chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
     135            fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
     136        }
     137        nPts ++;
     138
     139        ptCP.x = region->x1; ptCP.y = region->y1;
     140        psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
     141        xObs->data.F32[nPts] = ptFP.x;
     142        yObs->data.F32[nPts] = ptFP.y;
     143        psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
     144        xRef->data.F32[nPts] = ptFP.x;
     145        yRef->data.F32[nPts] = ptFP.y;
     146
     147        if (DEBUG) {
     148            chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
     149            fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
     150        }
     151        nPts ++;
     152
     153        ptCP.x = region->x1; ptCP.y = region->y0;
     154        psPlaneTransformApply (&ptFP, obsChip->toFPA, &ptCP);
     155        xObs->data.F32[nPts] = ptFP.x;
     156        yObs->data.F32[nPts] = ptFP.y;
     157        psPlaneTransformApply (&ptFP, refChip->toFPA, &ptCP);
     158        xRef->data.F32[nPts] = ptFP.x;
     159        yRef->data.F32[nPts] = ptFP.y;
     160
     161        if (DEBUG) {
     162            chipName = psMetadataLookupStr(NULL, obsChip->concepts, "CHIP.NAME");
     163            fprintf (f, "%s  %f %f  %f %f\n", chipName, xObs->data.F32[nPts], yObs->data.F32[nPts], xRef->data.F32[nPts], yRef->data.F32[nPts]);
     164        }
     165        nPts ++;
     166
     167        psFree (region);
    168168    }
    169169    xObs->n = yObs->n = xRef->n = yRef->n = nPts;
    170170    if (DEBUG) fclose (f);
    171        
     171
    172172    psPlaneTransform *map = psPlaneTransformAlloc (1, 1);
    173  
     173
    174174    psVector *mask = psVectorAlloc (nPts, PS_TYPE_VECTOR_MASK);
    175175    psVectorInit (mask, 0);
     
    179179
    180180    for (int i = 0; i < 3; i++) {
    181         psVectorClipFitPolynomial2D (map->x, stats, mask, 0xff, xObs, NULL, xRef, yRef);
    182         psTrace ("psModules.astrom", 3, "x resid: %f +/- %f (%ld of %ld)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues, xObs->n);
    183 
    184         psVectorClipFitPolynomial2D (map->y, stats, mask, 0xff, yObs, NULL, xRef, yRef);
    185         psTrace ("psModules.astrom", 3, "y resid: %f +/- %f (%ld of %ld)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues, yObs->n);
     181        psVectorClipFitPolynomial2D (map->x, stats, mask, 0xff, xObs, NULL, xRef, yRef);
     182        psTrace ("psModules.astrom", 3, "x resid: %f +/- %f (%ld of %ld)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues, xObs->n);
     183
     184        psVectorClipFitPolynomial2D (map->y, stats, mask, 0xff, yObs, NULL, xRef, yRef);
     185        psTrace ("psModules.astrom", 3, "y resid: %f +/- %f (%ld of %ld)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues, yObs->n);
    186186    }
    187187
    188188    // loop over all chips, select the outliers, and replace the measured astrometry with the model
    189     // the measured transformation above must be applied to make the comparison, and also then applied to the 
     189    // the measured transformation above must be applied to make the comparison, and also then applied to the
    190190    // model transformation
    191191
    192192    if (DEBUG) {
    193         f = fopen ("corners.fit.dat", "w");
    194         for (int i = 0; i < xObs->n; i++) {
    195             psPlane obsCoord, refCoord;
    196             refCoord.x = xRef->data.F32[i];
    197             refCoord.y = yRef->data.F32[i];
    198             psPlaneTransformApply (&obsCoord, map, &refCoord);
    199             fprintf (f, "%f %f  %f %f  %f %f\n", xObs->data.F32[i], yObs->data.F32[i], xRef->data.F32[i], yRef->data.F32[i], obsCoord.x, obsCoord.y);
    200         }
    201         fclose (f);
     193        f = fopen ("corners.fit.dat", "w");
     194        for (int i = 0; i < xObs->n; i++) {
     195            psPlane obsCoord, refCoord;
     196            refCoord.x = xRef->data.F32[i];
     197            refCoord.y = yRef->data.F32[i];
     198            psPlaneTransformApply (&obsCoord, map, &refCoord);
     199            fprintf (f, "%f %f  %f %f  %f %f\n", xObs->data.F32[i], yObs->data.F32[i], xRef->data.F32[i], yRef->data.F32[i], obsCoord.x, obsCoord.y);
     200        }
     201        fclose (f);
    202202    }
    203203
     
    211211
    212212    while ((obsChip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
    213         psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, obsChip->file_exists, obsChip->process);
    214         if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }
    215 
    216         // set the chip astrometry using the astrom file
    217         pmChip *refChip = pmFPAviewThisChip (view, astrom->fpa);
    218 
    219         // bad Astrometry test:  ref pixel or angle outside nominal
    220 
    221         psPlane refPixel = {0.0, 0.0, 0.0, 0.0};
    222         psPlane obsCoord, refCoord, tmpCoord;
    223 
    224         // find location of 0,0 pixel in focal plane coords for this chip
    225         psPlaneTransformApply (&obsCoord, obsChip->toFPA, &refPixel);
    226 
    227         // find location of 0,0 pixel in focal plane coords for ref chip
    228         // apply the global field rotation and offset before comparing
    229         psPlaneTransformApply (&tmpCoord, refChip->toFPA, &refPixel);
    230         psPlaneTransformApply (&refCoord, map, &tmpCoord);
    231    
    232         psPlane offPixel = {100.0, 0.0, 100.0, 0.0};
    233         psPlane obsOffPt, refOffPt;
    234 
    235         // find location of 0,0 pixel in focal plane coords for this chip
    236         psPlaneTransformApply (&obsOffPt, obsChip->toFPA, &offPixel);
    237 
    238         // find location of 0,0 pixel in focal plane coords for ref chip
    239         psPlaneTransformApply (&tmpCoord, refChip->toFPA, &offPixel);
    240         psPlaneTransformApply (&refOffPt, map, &tmpCoord);
    241    
    242         double obsAngle = PM_DEG_RAD*atan2 (obsOffPt.y - obsCoord.y, obsOffPt.x - obsCoord.x);
    243         double refAngle = PM_DEG_RAD*atan2 (refOffPt.y - refCoord.y, refOffPt.x - refCoord.x);
    244 
    245         bool badAstrom = false;
    246         badAstrom |= fabs(obsCoord.x - refCoord.x) > pixelTol;
    247         badAstrom |= fabs(obsCoord.y - refCoord.y) > pixelTol;
    248         badAstrom |= fabs(obsAngle   - refAngle)   > angleTol;
    249 
    250         fprintf (stderr, "chip %d, angle: %f, pixel: %f,%f\n", view->chip, obsAngle - refAngle, obsCoord.x - refCoord.x, obsCoord.y - refCoord.y);
    251 
    252         // XXX for now, just use first readout
    253         pmCell *cell = obsChip->cells->data[0];
    254         pmReadout *readout = cell->readouts->data[0];
    255 
    256         // update the header (pull or create local view to entry on readout->analysis)
    257         psMetadata *updates = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
    258         if (!updates) {
    259             updates = psMetadataAlloc ();
    260             psMetadataAddMetadata (readout->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", updates);
    261             psFree (updates);
    262         }
    263 
    264         psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_DX", PS_META_REPLACE, "chip x offset wrt model", obsCoord.x - refCoord.x);
    265         psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_DY", PS_META_REPLACE, "chip y offset wrt model", obsCoord.y - refCoord.y);
    266         psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_DT", PS_META_REPLACE, "chip rot offset wrt model", obsAngle - refAngle);
    267 
    268         // for successful chips, save the measured offsets in the header
    269         if (!badAstrom) continue;
    270 
    271         // XXX for now, let's just fail on the bad chips.  In the future, let's try to recover, but we still need to
    272         // catch the failures relative to the model
    273         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO", PS_META_REPLACE, "number of astrometry stars", 0);
    274         continue;
    275 
    276         psLogMsg ("psastro", PS_LOG_INFO, "fixing chip %d, angle: %f, pixel: %f,%f\n",
    277                   view->chip, obsAngle - refAngle, obsCoord.x - refCoord.x, obsCoord.y - refCoord.y);
    278 
    279         psFree (obsChip->toFPA);
    280         psFree (obsChip->fromFPA);
    281 
    282         // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter
    283         // XXX this only works if toTPA is at most a linear transformation
    284         psPlaneTransform *toFPA = psPlaneTransformAlloc(refChip->toFPA->x->nX, refChip->toFPA->x->nY);
    285         for (int i = 0; i <= refChip->toFPA->x->nX; i++) {
    286             for (int j = 0; j <= refChip->toFPA->x->nY; j++) {
    287                 double f1 = refChip->toFPA->x->coeffMask[i][j] ? 0.0 : map->x->coeff[1][0]*refChip->toFPA->x->coeff[i][j];
    288                 double f2 = refChip->toFPA->y->coeffMask[i][j] ? 0.0 : map->x->coeff[0][1]*refChip->toFPA->y->coeff[i][j];
    289                 toFPA->x->coeff[i][j] = f1 + f2;
    290 
    291                 double g1 = refChip->toFPA->x->coeffMask[i][j] ? 0.0 : map->y->coeff[1][0]*refChip->toFPA->x->coeff[i][j];
    292                 double g2 = refChip->toFPA->y->coeffMask[i][j] ? 0.0 : map->y->coeff[0][1]*refChip->toFPA->y->coeff[i][j];
    293                 toFPA->y->coeff[i][j] = g1 + g2;
    294             }
    295         }
    296         toFPA->x->coeff[0][0] += map->x->coeff[0][0];
    297         toFPA->y->coeff[0][0] += map->y->coeff[0][0];
    298 
    299         psRegion *region = pmChipPixels (obsChip);
    300         obsChip->toFPA   = toFPA;
    301         obsChip->fromFPA = psPlaneTransformInvert(NULL, obsChip->toFPA, *region, 50);
    302         psFree (region);
    303    
    304         // use the new position to re-try the match fit
    305         // select the raw objects for this readout
    306         psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.RAWSTARS");
    307         if (rawstars == NULL) { continue; }
    308 
    309         // select the raw objects for this readout
    310         psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
    311         if (refstars == NULL) { continue; }
    312 
    313         // the absolute minimum number of stars is 4 (for order = 1)
    314         if ((rawstars->n < 4) || (refstars->n < 4)) {
    315             readout->data_exists = false;
    316             psLogMsg ("psastro", 3, "insufficient rawstars (%ld) or refstars (%ld)",
    317                       rawstars->n, refstars->n);
    318             continue;
    319         }
    320 
    321         psastroUpdateChipToFPA (input->fpa, obsChip, rawstars, refstars);
    322 
    323         // XXX update the header with info to reflect the failure
    324         if (!psastroOneChipFit (input->fpa, obsChip, refstars, rawstars, recipe, updates)) {
    325             readout->data_exists = false;
    326             psLogMsg ("psastro", 3, "failed to find a solution\n");
    327             continue;
    328         }
    329 
    330         pmAstromWriteWCS (updates, input->fpa, obsChip, NONLIN_TOL);
    331     }
    332 
    333     psastroVisualPlotFixChips (input, xObs, yObs);
     213        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, obsChip->file_exists, obsChip->process);
     214        if (!obsChip->process || !obsChip->file_exists || !obsChip->data_exists) { continue; }
     215
     216        // set the chip astrometry using the astrom file
     217        pmChip *refChip = pmFPAviewThisChip (view, astrom->fpa);
     218
     219        // bad Astrometry test:  ref pixel or angle outside nominal
     220
     221        psPlane refPixel = {0.0, 0.0, 0.0, 0.0};
     222        psPlane obsCoord, refCoord, tmpCoord;
     223
     224        // find location of 0,0 pixel in focal plane coords for this chip
     225        psPlaneTransformApply (&obsCoord, obsChip->toFPA, &refPixel);
     226
     227        // find location of 0,0 pixel in focal plane coords for ref chip
     228        // apply the global field rotation and offset before comparing
     229        psPlaneTransformApply (&tmpCoord, refChip->toFPA, &refPixel);
     230        psPlaneTransformApply (&refCoord, map, &tmpCoord);
     231
     232        psPlane offPixel = {100.0, 0.0, 100.0, 0.0};
     233        psPlane obsOffPt, refOffPt;
     234
     235        // find location of 0,0 pixel in focal plane coords for this chip
     236        psPlaneTransformApply (&obsOffPt, obsChip->toFPA, &offPixel);
     237
     238        // find location of 0,0 pixel in focal plane coords for ref chip
     239        psPlaneTransformApply (&tmpCoord, refChip->toFPA, &offPixel);
     240        psPlaneTransformApply (&refOffPt, map, &tmpCoord);
     241
     242        double obsAngle = PM_DEG_RAD*atan2 (obsOffPt.y - obsCoord.y, obsOffPt.x - obsCoord.x);
     243        double refAngle = PM_DEG_RAD*atan2 (refOffPt.y - refCoord.y, refOffPt.x - refCoord.x);
     244
     245        bool badAstrom = false;
     246        badAstrom |= fabs(obsCoord.x - refCoord.x) > pixelTol;
     247        badAstrom |= fabs(obsCoord.y - refCoord.y) > pixelTol;
     248        badAstrom |= fabs(obsAngle   - refAngle)   > angleTol;
     249
     250        fprintf (stderr, "chip %d, angle: %f, pixel: %f,%f\n", view->chip, obsAngle - refAngle, obsCoord.x - refCoord.x, obsCoord.y - refCoord.y);
     251
     252        // XXX for now, just use first readout
     253        pmCell *cell = obsChip->cells->data[0];
     254        pmReadout *readout = cell->readouts->data[0];
     255
     256        // update the header (pull or create local view to entry on readout->analysis)
     257        psMetadata *updates = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
     258        if (!updates) {
     259            updates = psMetadataAlloc ();
     260            psMetadataAddMetadata (readout->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", updates);
     261            psFree (updates);
     262        }
     263
     264        psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_DX", PS_META_REPLACE, "chip x offset wrt model", obsCoord.x - refCoord.x);
     265        psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_DY", PS_META_REPLACE, "chip y offset wrt model", obsCoord.y - refCoord.y);
     266        psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_DT", PS_META_REPLACE, "chip rot offset wrt model", obsAngle - refAngle);
     267
     268        // for successful chips, save the measured offsets in the header
     269        if (!badAstrom) continue;
     270
     271        // XXX for now, let's just fail on the bad chips.  In the future, let's try to recover, but we still need to
     272        // catch the failures relative to the model
     273        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO", PS_META_REPLACE, "number of astrometry stars", 0);
     274        continue;
     275
     276        psLogMsg ("psastro", PS_LOG_INFO, "fixing chip %d, angle: %f, pixel: %f,%f\n",
     277                  view->chip, obsAngle - refAngle, obsCoord.x - refCoord.x, obsCoord.y - refCoord.y);
     278
     279        psFree (obsChip->toFPA);
     280        psFree (obsChip->fromFPA);
     281
     282        // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter
     283        // XXX this only works if toTPA is at most a linear transformation
     284        psPlaneTransform *toFPA = psPlaneTransformAlloc(refChip->toFPA->x->nX, refChip->toFPA->x->nY);
     285        for (int i = 0; i <= refChip->toFPA->x->nX; i++) {
     286            for (int j = 0; j <= refChip->toFPA->x->nY; j++) {
     287                double f1 = refChip->toFPA->x->coeffMask[i][j] ? 0.0 : map->x->coeff[1][0]*refChip->toFPA->x->coeff[i][j];
     288                double f2 = refChip->toFPA->y->coeffMask[i][j] ? 0.0 : map->x->coeff[0][1]*refChip->toFPA->y->coeff[i][j];
     289                toFPA->x->coeff[i][j] = f1 + f2;
     290
     291                double g1 = refChip->toFPA->x->coeffMask[i][j] ? 0.0 : map->y->coeff[1][0]*refChip->toFPA->x->coeff[i][j];
     292                double g2 = refChip->toFPA->y->coeffMask[i][j] ? 0.0 : map->y->coeff[0][1]*refChip->toFPA->y->coeff[i][j];
     293                toFPA->y->coeff[i][j] = g1 + g2;
     294            }
     295        }
     296        toFPA->x->coeff[0][0] += map->x->coeff[0][0];
     297        toFPA->y->coeff[0][0] += map->y->coeff[0][0];
     298
     299        psRegion *region = pmChipPixels (obsChip);
     300        obsChip->toFPA   = toFPA;
     301        obsChip->fromFPA = psPlaneTransformInvert(NULL, obsChip->toFPA, *region, 50);
     302        psFree (region);
     303
     304        // use the new position to re-try the match fit
     305        // select the raw objects for this readout
     306        psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.RAWSTARS");
     307        if (rawstars == NULL) { continue; }
     308
     309        // select the raw objects for this readout
     310        psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
     311        if (refstars == NULL) { continue; }
     312
     313        // the absolute minimum number of stars is 4 (for order = 1)
     314        if ((rawstars->n < 4) || (refstars->n < 4)) {
     315            readout->data_exists = false;
     316            psLogMsg ("psastro", 3, "insufficient rawstars (%ld) or refstars (%ld)",
     317                      rawstars->n, refstars->n);
     318            continue;
     319        }
     320
     321        psastroUpdateChipToFPA (input->fpa, obsChip, rawstars, refstars);
     322
     323        // XXX update the header with info to reflect the failure
     324        if (!psastroOneChipFit (input->fpa, obsChip, refstars, rawstars, recipe, updates)) {
     325            readout->data_exists = false;
     326            psLogMsg ("psastro", 3, "failed to find a solution\n");
     327            continue;
     328        }
     329
     330        pmAstromWriteWCS (updates, input->fpa, obsChip, NONLIN_TOL);
     331    }
     332
     333    pmAstromVisualPlotFixChips (input, xObs, yObs);
    334334    psFree (xObs);
    335335    psFree (yObs);
Note: See TracChangeset for help on using the changeset viewer.