Changeset 4375 for trunk/psphot/src/pspsf.c
- Timestamp:
- Jun 24, 2005, 5:38:37 AM (21 years ago)
- File:
-
- 1 edited
-
trunk/psphot/src/pspsf.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/pspsf.c
r4251 r4375 34 34 test->modelFLT = psArrayAlloc (sources->n); 35 35 test->modelPSF = psArrayAlloc (sources->n); 36 test->metricStats = NULL;37 36 test->metric = psVectorAlloc (sources->n, PS_TYPE_F64); 37 test->fitMag = psVectorAlloc (sources->n, PS_TYPE_F64); 38 38 test->mask = psVectorAlloc (sources->n, PS_TYPE_U8); 39 test->ApResid = 0; 40 test->dApResid = 0; 41 test->skyBias = 0; 39 42 40 43 for (int i = 0; i < test->modelFLT->n; i++) { 44 test->mask->data.U8[i] = 0; 41 45 test->modelFLT->data[i] = NULL; 42 46 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; 44 49 } 45 50 return (test); 46 51 } 47 52 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 48 58 pmPSF_Test *pmPSF_TestModel (psArray *sources, char *modelName, float RADIUS) 49 59 { 50 60 bool status; 61 float obsMag; 62 float fitMag; 51 63 float x; 52 64 float y; 53 bool status;54 65 int Nflt = 0; 55 66 int Npsf = 0; 56 psVector *metricMask = psVectorAlloc (sources->n, PS_TYPE_U8); 67 57 68 pmPSF_Test *test = pmPSF_TestAlloc (sources, modelName); 58 69 … … 66 77 67 78 // 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 69 80 psImageKeepCircle (source->mask, x, y, RADIUS, OR, 0x80); 70 81 status = pmSourceFitModel (source, model, false); 71 82 psImageKeepCircle (source->mask, x, y, RADIUS, AND, 0x7f); 72 83 84 // exclude the poor fits 73 85 if (!status) { 74 test->mask->data.U8[i] = 1;86 test->mask->data.U8[i] = 2; 75 87 continue; 76 88 } … … 84 96 // stage 2: construct a psf (pmPSF) from this collection of model fits 85 97 pmPSFFromModels (test->psf, test->modelFLT, test->mask); 86 87 // count valid sources88 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);94 98 95 99 // stage 3: refit with fixed shape parameters 96 100 psTimerStart ("fit"); 97 101 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 98 105 psSource *source = test->sources->data[i]; 99 106 psModel *modelFLT = test->modelFLT->data[i]; 100 107 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); 108 110 x = source->peak->x; 109 111 y = source->peak->y; … … 111 113 psImageKeepCircle (source->mask, x, y, RADIUS, OR, 0x80); 112 114 status = pmSourceFitModel (source, modelPSF, true); 113 psImageKeepCircle (source->mask, x, y, RADIUS, AND, 0x7f);114 115 115 116 // skip poor fits 116 117 if (!status) { 117 test->mask->data.U8[i] = 1;118 continue;118 test->mask->data.U8[i] = 3; 119 goto next_source; 119 120 } 121 122 // otherwise, save the resulting model 120 123 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; 121 135 Npsf ++; 136 137 next_source: 138 psImageKeepCircle (source->mask, x, y, RADIUS, AND, 0x7f); 139 122 140 } 123 141 psLogMsg ("psphot.psftest", 4, "fit psf: %f sec for %d sources\n", psTimerMark ("fit"), sources->n); … … 125 143 DumpModelFits (test->modelPSF, "modelsPSF.dat"); 126 144 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); 174 149 return (test); 175 150 } … … 181 156 // construct the fit vectors from the collection of objects 182 157 // 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); 186 161 psVector *dz = psVectorAlloc (models->n, PS_TYPE_F64); 187 162 … … 208 183 // XXX EAM : this is fragile: psf(Nparams) = model(Nparams) - 4 209 184 } 210 // if (n != x->n) psAbort ("pmPSFFromModels", "programming error: mismatched number of NULL models\n");211 185 212 186 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); 213 188 // psPolynomial2DDump (psf->params->data[i]); 214 215 // count valid sources216 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 223 189 } 224 190 return (true); … … 241 207 } 242 208 209 bool 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.
