IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 24, 2005, 5:38:37 AM (21 years ago)
Author:
eugene
Message:

adding model tests

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/pspsf.c

    r4251 r4375  
    3434    test->modelFLT    = psArrayAlloc (sources->n);
    3535    test->modelPSF    = psArrayAlloc (sources->n);
    36     test->metricStats = NULL;
    3736    test->metric      = psVectorAlloc (sources->n, PS_TYPE_F64);
     37    test->fitMag      = psVectorAlloc (sources->n, PS_TYPE_F64);
    3838    test->mask        = psVectorAlloc (sources->n, PS_TYPE_U8);
     39    test->ApResid     = 0;
     40    test->dApResid    = 0;
     41    test->skyBias     = 0;
    3942
    4043    for (int i = 0; i < test->modelFLT->n; i++) {
     44        test->mask->data.U8[i]  = 0;
    4145        test->modelFLT->data[i] = NULL;
    4246        test->modelPSF->data[i] = NULL;
    43         test->mask->data.U8[i]  = 0;
     47        test->metric->data.F64[i] = 0;
     48        test->fitMag->data.F64[i] = 0;
    4449    }   
    4550    return (test);
    4651}
    4752
     53// test->mask values indicate reason source was rejected:
     54// 1: outlier in psf polynomial fit
     55// 2: flt model failed to converge
     56// 3: psf model failed to converge
     57// 4: invalid source photometry
    4858pmPSF_Test *pmPSF_TestModel (psArray *sources, char *modelName, float RADIUS)
    4959{
    50  
     60    bool status;
     61    float obsMag;
     62    float fitMag;
    5163    float x;
    5264    float y;
    53     bool status;
    5465    int Nflt = 0;
    5566    int Npsf = 0;
    56     psVector *metricMask = psVectorAlloc (sources->n, PS_TYPE_U8);
     67
    5768    pmPSF_Test *test = pmPSF_TestAlloc (sources, modelName);
    5869
     
    6677
    6778        // set temporary object mask and fit object
    68         // fit model as FLT, not PSF (mask & skip poor fits)
     79        // fit model as FLT, not PSF
    6980        psImageKeepCircle (source->mask, x, y, RADIUS, OR, 0x80);
    7081        status = pmSourceFitModel (source, model, false);
    7182        psImageKeepCircle (source->mask, x, y, RADIUS, AND, 0x7f);
    7283
     84        // exclude the poor fits
    7385        if (!status) {
    74           test->mask->data.U8[i] = 1;
     86          test->mask->data.U8[i] = 2;
    7587          continue;
    7688        }
     
    8496    // stage 2: construct a psf (pmPSF) from this collection of model fits
    8597    pmPSFFromModels (test->psf, test->modelFLT, test->mask);
    86    
    87     // count valid sources
    88     int Nkeep = 0;
    89     for (int i = 0; i < sources->n; i++) {
    90       if (test->mask->data.U8[i]) continue;
    91       Nkeep++;
    92     }
    93     psTrace ("psphot.psftest", 3, "keeping %d of %d PSF candidates\n", Nkeep, sources->n);
    9498
    9599    // stage 3: refit with fixed shape parameters
    96100    psTimerStart ("fit");
    97101    for (int i = 0; i < test->sources->n; i++) {
     102        // masked for: bad model fit, outlier in parameters
     103        if (test->mask->data.U8[i]) continue;
     104
    98105        psSource *source = test->sources->data[i];
    99106        psModel  *modelFLT = test->modelFLT->data[i];
    100107
    101         // masked for: bad model fit, outlier in parameters
    102         if (test->mask->data.U8[i]) continue;
    103         if (modelFLT == NULL) {
    104           psLogMsg ("psphot.psftest", 2, "programming error: missing model not masked\n");
    105           continue;
    106         }
    107         psModel  *modelPSF = psModelFromPSF (modelFLT, test->psf); // set shape for this model
     108        // set shape for this model based on PSF
     109        psModel *modelPSF = psModelFromPSF (modelFLT, test->psf);
    108110        x = source->peak->x;
    109111        y = source->peak->y;
     
    111113        psImageKeepCircle (source->mask, x, y, RADIUS, OR, 0x80);
    112114        status = pmSourceFitModel (source, modelPSF, true);
    113         psImageKeepCircle (source->mask, x, y, RADIUS, AND, 0x7f);
    114115
    115116        // skip poor fits
    116117        if (!status) {
    117           test->mask->data.U8[i] = 1;
    118           continue;
     118            test->mask->data.U8[i] = 3;
     119            goto next_source;
    119120        }
     121
     122        // otherwise, save the resulting model
    120123        test->modelPSF->data[i] = modelPSF;
     124
     125        // XXX : use a different aperture radius from the fit radius?
     126        // XXX : use a different estimator for the local sky?
     127        // XXX : pass 'source' as input?
     128        if (!pmSourcePhotometry (&fitMag, &obsMag, modelPSF, source->pixels, source->mask)) {
     129            test->mask->data.U8[i] = 4;
     130            goto next_source;
     131        }           
     132
     133        test->metric->data.F64[i] = obsMag - fitMag;
     134        test->fitMag->data.F64[i] = fitMag;
    121135        Npsf ++;
     136
     137    next_source:
     138        psImageKeepCircle (source->mask, x, y, RADIUS, AND, 0x7f);
     139
    122140    }
    123141    psLogMsg ("psphot.psftest", 4, "fit psf:   %f sec for %d sources\n", psTimerMark ("fit"), sources->n);
     
    125143    DumpModelFits (test->modelPSF, "modelsPSF.dat");
    126144
    127     // stage 4: measure PSF metric (Ap-Fit)
    128     // should I be saving the aperture photometry for all sources?
    129     // save the metric for all stars
    130     for (int i = 0; i < test->sources->n; i++) {
    131 
    132         float obsSum = 0;
    133         float fitSum = 0;
    134      
    135         // is this metricMask redundant with test->mask ?
    136         metricMask->data.U8[i] = 1;
    137         test->metric->data.F64[i] = 0;
    138 
    139         if (test->mask->data.U8[i]) continue;
    140 
    141         psModel *model = test->modelPSF->data[i];
    142         if (model == NULL) {
    143           psLogMsg ("psphot.psftest", 2, "programming error: missing model not masked\n");
    144           continue;
    145         }
    146 
    147         psImage *image = ((psSource *)test->sources->data[i])->pixels;
    148         psImage *mask  = ((psSource *)test->sources->data[i])->mask;
    149 
    150         // this metric is Ap-Fit
    151         float sky = model->params->data.F32[0];
    152         for (int ix = 0; ix < image->numCols; ix++) {
    153             for (int iy = 0; iy < image->numRows; iy++) {
    154                 if (mask->data.U8[iy][ix]) continue;
    155                 obsSum += image->data.F32[iy][ix] - sky;
    156                 fitSum += psModelEval (model, image, ix, iy) - sky;
    157             }
    158         }
    159         // fprintf (stderr, "%d %f %f  %f\n", i, obsSum, fitSum, test->metric->data.F64[i]);
    160         // keep the good metrics
    161         if ((fitSum > 0) && (obsSum > 0)) {
    162             metricMask->data.U8[i] = 0;
    163             test->metric->data.F64[i] = -2.5*log10(obsSum/fitSum);
    164         } else {
    165           test->mask->data.U8[i] = 1;
    166         }
    167     }
    168 
    169     // XXX use robust stats, not clipped stats
    170     psStats *stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
    171     psVectorStats (stats, test->metric, NULL, metricMask, 1);
    172     test->metricStats = stats;
    173     psLogMsg ("psphot.pspsf", 3, "test model %s, metric: %f +/- %f\n", modelName, stats->clippedMean, stats->clippedStdev);
     145    // XXX this function wants aperture radius from pmSourcePhotometry
     146    pmPSFMetricModel (test, RADIUS);
     147    psLogMsg ("psphot.pspsf", 3, "test model %s, ap-fit: %f +/- %f, sky bias: %f\n",
     148              modelName, test->ApResid, test->dApResid, test->skyBias);
    174149    return (test);
    175150}
     
    181156    // construct the fit vectors from the collection of objects
    182157    // use the mask to ignore missing fits
    183     psVector *x = psVectorAlloc (models->n, PS_TYPE_F64);
    184     psVector *y = psVectorAlloc (models->n, PS_TYPE_F64);
    185     psVector *z = psVectorAlloc (models->n, PS_TYPE_F64);
     158    psVector *x  = psVectorAlloc (models->n, PS_TYPE_F64);
     159    psVector *y  = psVectorAlloc (models->n, PS_TYPE_F64);
     160    psVector *z  = psVectorAlloc (models->n, PS_TYPE_F64);
    186161    psVector *dz = psVectorAlloc (models->n, PS_TYPE_F64);
    187162
     
    208183            // XXX EAM : this is fragile: psf(Nparams) = model(Nparams) - 4
    209184        }
    210         // if (n != x->n) psAbort ("pmPSFFromModels", "programming error: mismatched number of NULL models\n");
    211185
    212186        psf->params->data[i] = RobustFit2D (psf->params->data[i], mask, x, y, z, dz);
     187        // psTrace ("psphot.psftest", 3, "keeping %d of %d PSF candidates (PSF param %d)\n", Nkeep, mask->n, i);
    213188        // psPolynomial2DDump (psf->params->data[i]);
    214 
    215         // count valid sources
    216         int Nkeep = 0;
    217         for (int j = 0; j < mask->n; j++) {
    218           if (mask->data.U8[j]) continue;
    219           Nkeep++;
    220         }
    221         psTrace ("psphot.psftest", 3, "keeping %d of %d PSF candidates (PSF param %d)\n", Nkeep, mask->n, i);
    222 
    223189    }
    224190    return (true);
     
    241207}
    242208
     209bool pmPSFMetricModel (pmPSF_Test *test, float RADIUS) {
     210
     211  float dBin;
     212  int   nKeep, nSkip;
     213 
     214
     215  // the measured (aperture - fit) magnitudes (dA == test->metric)
     216  //   depend on both the true ap-fit (dAo) and the bias in the sky measurement:
     217  //     dA = dAo + dsky/flux
     218  //   where flux is the flux of the star
     219  // we fit this trend to find the infinite flux aperture correction (dAo),
     220  //   the nominal sky bias (dsky), and the error on dAo
     221  // the values of dA are contaminated by stars with close neighbors in the aperture
     222  //   we use an outlier rejection to avoid this bias
     223
     224  // rflux = ten(0.4*fitMag);
     225  psVector *rflux = psVectorAlloc (test->sources->n, PS_TYPE_F64);
     226  for (int i = 0; i < test->sources->n; i++) {
     227    if (test->mask->data.U8[i]) continue;
     228    rflux->data.F64[i] = pow(10.0, 0.4*test->fitMag->data.F64[i]);
     229  }
     230  // psScalar *t1 = psScalar(0.4);
     231  // psVector *v1 = psBinaryOp (NULL, test->fitMag, "*", t1);
     232  // psVector *rflux = psUnaryOp (NULL, v1, "ten");
     233  // psFree (t1);
     234  // psFree (v1);
     235
     236  // find min and max of (1/flux):
     237  psStats *stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX);
     238  psVectorStats (stats, rflux, NULL, test->mask, 0xff);
     239 
     240  // build binned versions of rflux, metric
     241  dBin = (stats->max - stats->min) / 10.0;
     242  psVector *rfBin = psVectorCreate (stats->min, stats->max, dBin, PS_TYPE_F64);
     243  psVector *daBin = psVectorAlloc (rfBin->n, PS_TYPE_F64);
     244  psVector *maskB = psVectorAlloc (rfBin->n, PS_TYPE_U8);
     245  psFree (stats);
     246
     247  psTrace ("psphot.metricmodel", 3, "rflux max: %g, min: %g, delta: %g\n", stats->max, stats->min, dBin);
     248
     249  for (int i = 0; i < daBin->n; i++) {
     250
     251    psVector *tmp = psVectorAlloc (test->sources->n, PS_TYPE_F64);
     252    tmp->n = 0;
     253
     254    // accumulate data within bin range
     255    for (int j = 0; j < test->sources->n; j++) {
     256      // masked for: bad model fit, outlier in parameters
     257      if (test->mask->data.U8[j]) continue;
     258   
     259      // skip points with extreme dA values
     260      if (fabs(test->metric->data.F64[j]) > 0.5) continue;
     261
     262      // skip points outside of this bin
     263      if (rflux->data.F64[j] < rfBin->data.F64[i] - 0.5*dBin) continue;
     264      if (rflux->data.F64[j] > rfBin->data.F64[i] + 0.5*dBin) continue;
     265
     266      tmp->data.F64[tmp->n] = test->metric->data.F64[j];
     267      tmp->n ++;
     268    }
     269
     270    // is this a valid point?
     271    maskB->data.U8[i] = 0;
     272    if (tmp->n < 2) {
     273      maskB->data.U8[i] = 1;
     274      continue;
     275    }
     276
     277    // dA values are contaminated with low outliers
     278    // measure statistics only on upper 50% of points
     279    psVectorSort (tmp, tmp);
     280    nKeep = 0.5*tmp->n;
     281    nSkip = tmp->n - nKeep;
     282
     283    psVector *tmp2 = psVectorAlloc (nKeep, PS_TYPE_F64);
     284    for (int j = 0; j < tmp2->n; j++) {
     285      tmp2->data.F64[j] = tmp->data.F64[j + nSkip];
     286    }
     287
     288    stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
     289    psVectorStats (stats, tmp2, NULL, NULL, 0);
     290    psTrace ("psphot.metricmodel", 4, "rfBin %d (%g): %d pts, %g\n", i, rfBin->data.F64[i], tmp->n, stats->sampleMedian);
     291
     292    daBin->data.F64[i] = stats->sampleMedian;
     293  }
     294
     295  // linear fit to rfBin, daBin
     296  psPolynomial1D *poly = Polynomial1DAlloc (1, PS_POLYNOMIAL_ORD);
     297  poly = VectorFitPolynomial1DOrd_EAM (poly, maskB, rfBin, daBin, NULL);
     298
     299  psVector *daBinFit = Polynomial1DEvalVector_EAM (poly, rfBin);
     300  psVector *daResid  = (psVector *) psBinaryOp (NULL, (void *) daBin, "-", (void *) daBinFit);
     301
     302  stats = psStatsAlloc (PS_STAT_CLIPPED_STDEV);
     303  stats = psVectorStats (stats, daResid, NULL, maskB, 1);
     304
     305  test->ApResid = poly->coeff[0];
     306  test->dApResid = stats->clippedStdev;
     307  test->skyBias = poly->coeff[1] / (M_PI * PS_SQR(RADIUS));
     308
     309  return true;
     310}
Note: See TracChangeset for help on using the changeset viewer.