IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 9, 2008, 2:39:01 PM (18 years ago)
Author:
beaumont
Message:

merged mainline into branch. resolved conflicts. added plots.

Location:
branches/cnb_branch_20080830/psastro/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/cnb_branch_20080830/psastro/src

    • Property svn:ignore
      •  

        old new  
        1515psastroModel
        1616gpcModel
         17psastroModelFit
  • branches/cnb_branch_20080830/psastro/src/psastroAstromGuess.c

    r17933 r20033  
    11# include "psastroInternal.h"
     2# define DEBUG 0
    23
    34// this function loads the header WCS astrometry terms into the fpa terms and applies the
     
    2829    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSASTRO_RECIPE);
    2930    if (!recipe) {
    30         psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!");
    31         return false;
     31        psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!");
     32        return false;
    3233    }
    3334
     
    3536    bool useModel = psMetadataLookupBool (&status, config->arguments, "PSASTRO.USE.MODEL");
    3637    if (!status) {
    37         useModel = psMetadataLookupBool (&status, recipe, "PSASTRO.USE.MODEL");
     38        useModel = psMetadataLookupBool (&status, recipe, "PSASTRO.USE.MODEL");
    3839    }
    3940
     
    4142    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
    4243    if (!input) {
    43         psError(PSASTRO_ERR_CONFIG, true, "Can't find input data");
    44         return false;
     44        psError(PSASTRO_ERR_CONFIG, true, "Can't find input data");
     45        return false;
    4546    }
    4647
     
    4849    double pixelScale = psMetadataLookupF32 (&status, recipe, "PSASTRO.PIXEL.SCALE");
    4950    if (!status) {
    50         psError(PS_ERR_IO, true, "Failed to lookup pixel scale");
    51         return false;
    52     }
     51        psError(PS_ERR_IO, true, "Failed to lookup pixel scale");
     52        return false;
     53    }
     54
     55    psVector *cornerL = psVectorAllocEmpty (100, PS_TYPE_F32);
     56    psVector *cornerM = psVectorAllocEmpty (100, PS_TYPE_F32);
     57    psVector *cornerP = psVectorAllocEmpty (100, PS_TYPE_F32);
     58    psVector *cornerQ = psVectorAllocEmpty (100, PS_TYPE_F32);
     59    psVector *cornerR = psVectorAllocEmpty (100, PS_TYPE_F32);
     60    psVector *cornerD = psVectorAllocEmpty (100, PS_TYPE_F32);
    5361
    5462    pmFPA *fpa = input->fpa;
     63
     64    if (DEBUG) psastroDumpCorners ("corners.up.guess1.dat", "corners.dn.guess1.dat", fpa);
    5565
    5666    // load mosaic-level astrometry?
    5767    bool bilevelAstrometry = false;
    5868    if (!useModel) {
    59         psastroAstromGuessSetFPA (fpa, &bilevelAstrometry);
     69        psastroAstromGuessSetFPA (fpa, &bilevelAstrometry);
    6070    }
    6171
     
    6575        if (!chip->process || !chip->file_exists || !chip->data_exists) { continue; }
    6676
    67         if (!useModel) {
    68             if (!psastroAstromGuessSetChip (fpa, chip, view, pixelScale, bilevelAstrometry)) continue;
    69         }
     77        if (!useModel) {
     78            if (!psastroAstromGuessSetChip (fpa, chip, view, pixelScale, bilevelAstrometry)) continue;
     79        }
    7080
    7181        if (newFPA) {
    7282            newFPA = false;
    73             while (fpa->toSky->R <        0) fpa->toSky->R += 2.0*M_PI;
    74             while (fpa->toSky->R > 2.0*M_PI) fpa->toSky->R -= 2.0*M_PI;
     83            while (fpa->toSky->R <        0) fpa->toSky->R += 2.0*M_PI;
     84            while (fpa->toSky->R > 2.0*M_PI) fpa->toSky->R -= 2.0*M_PI;
    7585            RAminSky = fpa->toSky->R - M_PI;
    7686            RAmaxSky = fpa->toSky->R + M_PI;
     87        }
     88
     89        // report and save the current best guess for the chip 0,0 pixel coordinates
     90        {
     91            psPlane ptCH, ptFP, ptTP;
     92            psSphere ptSky;
     93
     94            ptCH.x = 0;
     95            ptCH.y = 0;
     96            psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     97            psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
     98            psDeproject (&ptSky, &ptTP, fpa->toSky);
     99            psLogMsg ("psastro", 3, "0,0 pix for chip %3d = %f,%f\n", view->chip, DEG_RAD*ptSky.r, DEG_RAD*ptSky.d);
     100
     101            psVectorAppend (cornerL, ptFP.x);
     102            psVectorAppend (cornerM, ptFP.y);
     103            psVectorAppend (cornerP, ptTP.x);
     104            psVectorAppend (cornerQ, ptTP.y);
     105            psVectorAppend (cornerR, ptSky.r);
     106            psVectorAppend (cornerD, ptSky.d);
    77107        }
    78108
     
    86116                if (! readout->data_exists) { continue; }
    87117
    88                 // report the current best guess for the cell 0,0 pixel coordinate
    89                 {
    90                   psPlane ptCH, ptFP, ptTP;
    91                   psSphere ptSky;
    92 
    93                   ptCH.x = 0;
    94                   ptCH.y = 0;
    95                   psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
    96                   psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
    97                   psDeproject (&ptSky, &ptTP, fpa->toSky);
    98                   psLogMsg ("psastro", 2, "0,0 pix for chip,cell %d,%d = %f,%f\n", view->chip, view->cell, DEG_RAD*ptSky.r, DEG_RAD*ptSky.d);
    99                 }
    100 
    101118                psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.RAWSTARS");
    102119                if (rawstars == NULL) { continue; }
    103120
    104                 *nStars += rawstars->n;
     121                *nStars += rawstars->n;
    105122                for (int i = 0; i < rawstars->n; i++) {
    106123                    pmAstromObj *raw = rawstars->data[i];
     
    121138                }
    122139
    123                 // dump or plot the resulting projected positions
    124                 if (psTraceGetLevel("psastro.dump") > 0) {
    125                     psastroDumpRawstars (rawstars, fpa, chip);
    126                 }
    127 
    128                 if (psTraceGetLevel("psastro.plot") > 0) {
    129                     psastroPlotRawstars (rawstars, fpa, chip, recipe);
    130                 }
     140                // dump or plot the resulting projected positions
     141                if (psTraceGetLevel("psastro.dump") > 0) {
     142                    psastroDumpRawstars (rawstars, fpa, chip);
     143                }
     144
     145                if (psTraceGetLevel("psastro.plot") > 0) {
     146                    psastroPlotRawstars (rawstars, fpa, chip, recipe);
     147                }
    131148            }
    132149        }
    133150    }
     151
     152    if (DEBUG) psastroDumpCorners ("corners.up.guess2.dat", "corners.dn.guess2.dat", fpa);
    134153
    135154    // how many total sources are available to us?
    136155    psMetadataAddS32 (recipe, PS_LIST_TAIL, "NTOTSTAR",  PS_META_REPLACE, "", *nStars);
    137156    if (*nStars == 0) {
    138         psLogMsg ("psastro", 2, "no sources available for astrometry\n");
    139         psFree (view);
    140         return true;
    141     }
    142 
    143     psLogMsg ("psastro", 2, "loaded raw data from %f,%f to %f,%f\n", 
    144               DEG_RAD*RAmin, DEG_RAD*DECmin,
    145               DEG_RAD*RAmax, DEG_RAD*DECmax);
     157        psLogMsg ("psastro", 2, "no sources available for astrometry\n");
     158        psFree (view);
     159        return true;
     160    }
     161
     162    psLogMsg ("psastro", 2, "loaded raw data from %f,%f to %f,%f\n",
     163              DEG_RAD*RAmin, DEG_RAD*DECmin,
     164              DEG_RAD*RAmax, DEG_RAD*DECmax);
    146165
    147166    psMetadataAddF32 (recipe, PS_LIST_TAIL, "RA_MIN",  PS_META_REPLACE, "", RAmin);
     
    149168    psMetadataAddF32 (recipe, PS_LIST_TAIL, "DEC_MIN", PS_META_REPLACE, "", DECmin);
    150169    psMetadataAddF32 (recipe, PS_LIST_TAIL, "DEC_MAX", PS_META_REPLACE, "", DECmax);
     170
     171    psMetadataAddVector (input->fpa->analysis, PS_LIST_TAIL, "CORNER.L", PS_META_REPLACE, "corner pixel", cornerL);
     172    psMetadataAddVector (input->fpa->analysis, PS_LIST_TAIL, "CORNER.M", PS_META_REPLACE, "corner pixel", cornerM);
     173    psMetadataAddVector (input->fpa->analysis, PS_LIST_TAIL, "CORNER.P", PS_META_REPLACE, "corner pixel", cornerP);
     174    psMetadataAddVector (input->fpa->analysis, PS_LIST_TAIL, "CORNER.Q", PS_META_REPLACE, "corner pixel", cornerQ);
     175    psMetadataAddVector (input->fpa->analysis, PS_LIST_TAIL, "CORNER.R", PS_META_REPLACE, "corner pixel", cornerR);
     176    psMetadataAddVector (input->fpa->analysis, PS_LIST_TAIL, "CORNER.D", PS_META_REPLACE, "corner pixel", cornerD);
     177
     178    psFree (cornerL);
     179    psFree (cornerM);
     180    psFree (cornerP);
     181    psFree (cornerQ);
     182    psFree (cornerR);
     183    psFree (cornerD);
    151184
    152185    psFree (view);
     
    168201    pmHDU *hdu = pmFPAviewThisHDU (view, fpa);
    169202    if (bilevelAstrometry) {
    170         if (!pmAstromReadBilevelChip (chip, hdu->header)) {
    171             psWarning("Could not get WCS information from header for chip %d, skipping", view->chip);
    172             return false;
    173         }
     203        if (!pmAstromReadBilevelChip (chip, hdu->header)) {
     204            psWarning("Could not get WCS information from header for chip %d, skipping", view->chip);
     205            return false;
     206        }
    174207    } else {
    175         if (!pmAstromReadWCS (fpa, chip, hdu->header, pixelScale)) {
    176             psWarning("Could not get WCS information from header for chip %d, skipping", view->chip);
    177             return false;
    178         }
     208        if (!pmAstromReadWCS (fpa, chip, hdu->header, pixelScale)) {
     209            psWarning("Could not get WCS information from header for chip %d, skipping", view->chip);
     210            return false;
     211        }
    179212    }
    180213    return true;
     
    190223    // load mosaic-level astrometry?
    191224    if (phu) {
    192         char *ctype = psMetadataLookupStr (NULL, phu->header, "CTYPE1");
    193         if (ctype) {
    194             *bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
    195         }
     225        char *ctype = psMetadataLookupStr (NULL, phu->header, "CTYPE1");
     226        if (ctype) {
     227            *bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
     228        }
    196229    }
    197230    if (*bilevelAstrometry) {
    198         pmAstromReadBilevelMosaic (fpa, phu->header);
    199     } 
     231        pmAstromReadBilevelMosaic (fpa, phu->header);
     232    }
    200233    psFree (view);
    201234    return true;
    202235}
     236
     237// we made a guess at the beginning; how does the guess compare with the result?
     238bool psastroAstromGuessCheck (pmConfig *config) {
     239
     240    bool status;
     241
     242    // select the input data sources
     243    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
     244    if (!input) {
     245        psError(PSASTRO_ERR_CONFIG, true, "Can't find input data");
     246        return false;
     247    }
     248
     249    pmFPA *fpa = input->fpa;
     250
     251    psVector *cornerLo = psMetadataLookupPtr (&status, input->fpa->analysis, "CORNER.L");
     252    psVector *cornerMo = psMetadataLookupPtr (&status, input->fpa->analysis, "CORNER.M");
     253    psVector *cornerPo = psMetadataLookupPtr (&status, input->fpa->analysis, "CORNER.P");
     254    psVector *cornerQo = psMetadataLookupPtr (&status, input->fpa->analysis, "CORNER.Q");
     255    psVector *cornerRo = psMetadataLookupPtr (&status, input->fpa->analysis, "CORNER.R");
     256    psVector *cornerDo = psMetadataLookupPtr (&status, input->fpa->analysis, "CORNER.D");
     257
     258    if (cornerLo->n < 3) return true;
     259
     260    psVector *cornerLn = psVectorAllocEmpty (100, PS_TYPE_F32);
     261    psVector *cornerMn = psVectorAllocEmpty (100, PS_TYPE_F32);
     262    psVector *cornerPn = psVectorAllocEmpty (100, PS_TYPE_F32);
     263    psVector *cornerQn = psVectorAllocEmpty (100, PS_TYPE_F32);
     264    psVector *cornerRn = psVectorAllocEmpty (100, PS_TYPE_F32);
     265    psVector *cornerDn = psVectorAllocEmpty (100, PS_TYPE_F32);
     266
     267    if (DEBUG) psastroDumpCorners ("corners.up.guess3.dat", "corners.dn.guess3.dat", fpa);
     268
     269    pmChip *chip = NULL;
     270    pmFPAview *view = pmFPAviewAlloc (0);
     271
     272    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
     273        if (!chip->process || !chip->file_exists || !chip->data_exists) { continue; }
     274
     275        psPlane ptCH, ptFP, ptTP;
     276        psSphere ptSky;
     277
     278        ptCH.x = 0;
     279        ptCH.y = 0;
     280        psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     281        psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
     282        psDeproject (&ptSky, &ptTP, fpa->toSky);
     283        psLogMsg ("psastro", 3, "0,0 pix for chip %3d = %f,%f\n", view->chip, DEG_RAD*ptSky.r, DEG_RAD*ptSky.d);
     284
     285        // new corner locations based on the calibrated astrometry
     286        psVectorAppend (cornerLn, ptFP.x);
     287        psVectorAppend (cornerMn, ptFP.y);
     288        psVectorAppend (cornerPn, ptTP.x);
     289        psVectorAppend (cornerQn, ptTP.y);
     290        psVectorAppend (cornerRn, ptSky.r);
     291        psVectorAppend (cornerDn, ptSky.d);
     292    }
     293
     294    // compare the old R,D values projected to the same tangent plane as the new R,D values:
     295
     296    psVector *cornerPs = psVectorAllocEmpty (100, PS_TYPE_F32);
     297    psVector *cornerQs = psVectorAllocEmpty (100, PS_TYPE_F32);
     298
     299    for (int i = 0; i < cornerRo->n; i++) {
     300
     301        psPlane ptTP;
     302        psSphere ptSky;
     303
     304        ptSky.r = cornerRo->data.F32[i];
     305        ptSky.d = cornerDo->data.F32[i];
     306
     307        psProject (&ptTP, &ptSky, fpa->toSky);
     308        psVectorAppend (cornerPs, ptTP.x);
     309        psVectorAppend (cornerQs, ptTP.y);
     310    }
     311
     312    psPlaneTransform *map = psPlaneTransformAlloc (1, 1);
     313    map->x->coeffMask[1][1] = PS_POLY_MASK_SET;
     314    map->y->coeffMask[1][1] = PS_POLY_MASK_SET;
     315
     316    psVectorFitPolynomial2D (map->x, NULL, 0, cornerPn, NULL, cornerPs, cornerQs);
     317    psVectorFitPolynomial2D (map->y, NULL, 0, cornerQn, NULL, cornerPs, cornerQs);
     318
     319    // apply the linear fit...
     320    psVector *cornerPf = psPolynomial2DEvalVector (map->x, cornerPs, cornerQs);
     321    psVector *cornerQf = psPolynomial2DEvalVector (map->y, cornerPs, cornerQs);
     322
     323    // ...and calculate the residual between Pn,Qn and Pf,Qf
     324    psVector *cornerPd = (psVector *) psBinaryOp (NULL, cornerPn, "-", cornerPf);
     325    psVector *cornerQd = (psVector *) psBinaryOp (NULL, cornerQn, "-", cornerQf);
     326
     327    psStats *statsP = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
     328    psStats *statsQ = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
     329
     330    psVectorStats (statsP, cornerPd, NULL, NULL, 0);
     331    psVectorStats (statsQ, cornerQd, NULL, NULL, 0);
     332
     333    float angle = atan2 (map->y->coeff[1][0], map->x->coeff[1][0]);
     334    float scale = hypot (map->y->coeff[1][0], map->x->coeff[1][0]);
     335
     336    psLogMsg ("psastro", 3, "boresite offset  : %f,%f\n", map->x->coeff[0][0], map->y->coeff[0][0]);
     337    psLogMsg ("psastro", 3, "boresite angle   : %f, scale: %f", angle*PS_DEG_RAD, scale);
     338    psLogMsg ("psastro", 3, "boresite scatter : %f,%f\n", statsP->sampleStdev, statsQ->sampleStdev);
     339
     340    // write the elapsed time here; this will be updated in psastroMosaicAstrometry, if called
     341    psMetadata *header = psMetadataLookupMetadata (&status, input->fpa->analysis, "PSASTRO.HEADER");
     342    if (!header) {
     343        header = psMetadataAlloc();
     344        psMetadataAddMetadata (input->fpa->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", header);
     345        psFree (header);  // drop this reference
     346    }
     347
     348    psMetadataAddF32 (header, PS_LIST_TAIL, "AST_R0", PS_META_REPLACE, "boresite offset in RA (TP units)", map->x->coeff[0][0]);
     349    psMetadataAddF32 (header, PS_LIST_TAIL, "AST_D0", PS_META_REPLACE, "boresite offset in DEC (TP units)", map->y->coeff[0][0]);
     350    psMetadataAddF32 (header, PS_LIST_TAIL, "AST_T0", PS_META_REPLACE, "boresite angle (degrees)", angle*PS_DEG_RAD);
     351    psMetadataAddF32 (header, PS_LIST_TAIL, "AST_S0", PS_META_REPLACE, "boresite scale correction", scale);
     352    psMetadataAddF32 (header, PS_LIST_TAIL, "AST_RS", PS_META_REPLACE, "boresite scatter in RA (TP units)", statsP->sampleStdev);
     353    psMetadataAddF32 (header, PS_LIST_TAIL, "AST_DS", PS_META_REPLACE, "boresite scatter in DEC (TP units)", statsQ->sampleStdev);
     354
     355    if (0) {
     356        FILE *f = fopen ("corners.dat", "w");
     357        for (int i = 0; i < cornerRo->n; i++) {
     358            fprintf (f, "%10.6f %10.6f  %9.2f %9.2f  %9.2f %9.2f  |  %10.6f %10.6f  %9.2f %9.2f  %9.2f %9.2f\n",
     359                     cornerRn->data.F32[i], cornerDn->data.F32[i], cornerPn->data.F32[i], cornerQn->data.F32[i], cornerLn->data.F32[i], cornerMn->data.F32[i],
     360                     cornerRo->data.F32[i], cornerDo->data.F32[i], cornerPo->data.F32[i], cornerQo->data.F32[i], cornerLo->data.F32[i], cornerMo->data.F32[i]);
     361        }
     362        fclose (f);
     363    }
     364
     365    psFree (cornerPf);
     366    psFree (cornerQf);
     367    psFree (cornerPd);
     368    psFree (cornerQd);
     369
     370    psFree (statsP);
     371    psFree (statsQ);
     372
     373    psFree (cornerLn);
     374    psFree (cornerMn);
     375    psFree (cornerPn);
     376    psFree (cornerQn);
     377    psFree (cornerRn);
     378    psFree (cornerDn);
     379    psFree (cornerPs);
     380    psFree (cornerQs);
     381    psFree (map);
     382    psFree (view);
     383
     384
     385    return true;
     386}
Note: See TracChangeset for help on using the changeset viewer.