Changeset 6873 for trunk/psModules/src/objects/pmPSFtry.c
- Timestamp:
- Apr 17, 2006, 8:10:08 AM (20 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/objects/pmPSFtry.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects/pmPSFtry.c
r6511 r6873 5 5 * @author EAM, IfA 6 6 * 7 * @version $Revision: 1. 5$ $Name: not supported by cvs2svn $8 * @date $Date: 2006-0 3-04 01:01:33$7 * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2006-04-17 18:10:08 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 13 13 14 14 # include <pslib.h> 15 # include "pmObjects.h" 16 # include "pmPSF.h" 17 # include "pmPSFtry.h" 18 # include "pmModelGroup.h" 15 #include "pmHDU.h" 16 #include "pmFPA.h" 17 #include "pmPeaks.h" 18 #include "pmMoments.h" 19 #include "pmModel.h" 20 #include "pmSource.h" 21 #include "pmGrowthCurve.h" 22 #include "pmPSF.h" 23 #include "pmPSFtry.h" 24 #include "pmModelGroup.h" 25 #include "pmSourceFitModel.h" 26 #include "pmSourcePhotometry.h" 19 27 20 28 // ******** pmPSFtry functions ************************************************** … … 33 41 psFree (test->psf); 34 42 psFree (test->sources); 35 psFree (test->model FLT);43 psFree (test->modelEXT); 36 44 psFree (test->modelPSF); 37 45 psFree (test->metric); … … 42 50 43 51 // allocate a pmPSFtry based on the desired sources and the model (identified by name) 44 pmPSFtry *pmPSFtryAlloc (psArray *sources, char *modelName )52 pmPSFtry *pmPSFtryAlloc (psArray *sources, char *modelName, bool poissonErrors) 45 53 { 46 54 … … 51 59 // XXX probably need to increment ref counter 52 60 type = pmModelSetType (modelName); 53 test->psf = pmPSFAlloc (type );61 test->psf = pmPSFAlloc (type, poissonErrors); 54 62 test->sources = psMemIncrRefCounter(sources); 55 test->model FLT = psArrayAlloc (sources->n);63 test->modelEXT = psArrayAlloc (sources->n); 56 64 test->modelPSF = psArrayAlloc (sources->n); 57 65 test->metric = psVectorAlloc (sources->n, PS_TYPE_F64); … … 59 67 test->mask = psVectorAlloc (sources->n, PS_TYPE_U8); 60 68 61 test->modelFLT->n = test->modelFLT->nalloc; 62 test->modelPSF->n = test->modelPSF->nalloc; 63 test->metric->n = test->metric->nalloc; 64 test->fitMag->n = test->fitMag->nalloc; 65 test->mask->n = test->mask->nalloc; 66 67 for (int i = 0; i < test->modelFLT->n; i++) { 69 for (int i = 0; i < test->modelEXT->n; i++) { 68 70 test->mask->data.U8[i] = 0; 69 test->model FLT->data[i] = NULL;71 test->modelEXT->data[i] = NULL; 70 72 test->modelPSF->data[i] = NULL; 71 73 test->metric->data.F64[i] = 0; … … 86 88 // mask values indicate the reason the source was rejected: 87 89 88 pmPSFtry *pmPSFtryModel (psArray *sources, char *modelName, float RADIUS )90 pmPSFtry *pmPSFtryModel (psArray *sources, char *modelName, float RADIUS, bool poissonErrors) 89 91 { 90 92 bool status; … … 93 95 float x; 94 96 float y; 95 int N flt = 0;97 int Next = 0; 96 98 int Npsf = 0; 97 99 98 pmPSFtry *psfTry = pmPSFtryAlloc (sources, modelName );100 pmPSFtry *psfTry = pmPSFtryAlloc (sources, modelName, poissonErrors); 99 101 100 102 // stage 1: fit an independent model (freeModel) to all sources … … 108 110 109 111 // set temporary object mask and fit object 110 // fit model as FLT, not PSF 111 psImageKeepCircle (source->mask, x, y, RADIUS, "OR", PSPHOT_MASK_MARKED); 112 status = pmSourceFitModel (source, model, false); 113 psImageKeepCircle (source->mask, x, y, RADIUS, "AND", ~PSPHOT_MASK_MARKED); 112 // fit model as EXT, not PSF 113 114 psImageKeepCircle (source->mask, x, y, RADIUS, "OR", PM_SOURCE_MASK_MARKED); 115 status = pmSourceFitModel (source, model, PM_SOURCE_FIT_EXT); 116 psImageKeepCircle (source->mask, x, y, RADIUS, "AND", ~PM_SOURCE_MASK_MARKED); 114 117 115 118 // exclude the poor fits 116 119 if (!status) { 117 psfTry->mask->data.U8[i] = PSFTRY_MASK_ FLT_FAIL;120 psfTry->mask->data.U8[i] = PSFTRY_MASK_EXT_FAIL; 118 121 psFree (model); 119 122 continue; 120 123 } 121 psfTry->modelFLT->data[i] = model; 122 Nflt ++; 123 } 124 psLogMsg ("psphot.psftry", 4, "fit flt: %f sec for %d sources\n", psTimerMark ("fit"), sources->n); 125 psTrace ("psphot.psftry", 3, "keeping %d of %d PSF candidates (FLT)\n", Nflt, sources->n); 126 127 // make this optional? 128 // DumpModelFits (psfTry->modelFLT, "modelsFLT.dat"); 124 psfTry->modelEXT->data[i] = model; 125 Next ++; 126 } 127 psLogMsg ("psphot.psftry", 4, "fit ext: %f sec for %d sources\n", psTimerMark ("fit"), sources->n); 128 psTrace ("psphot.psftry", 3, "keeping %d of %d PSF candidates (EXT)\n", Next, sources->n); 129 129 130 130 // stage 2: construct a psf (pmPSF) from this collection of model fits 131 pmPSFFromModels (psfTry->psf, psfTry->model FLT, psfTry->mask);131 pmPSFFromModels (psfTry->psf, psfTry->modelEXT, psfTry->mask); 132 132 133 133 // stage 3: refit with fixed shape parameters … … 139 139 140 140 pmSource *source = psfTry->sources->data[i]; 141 pmModel *model FLT = psfTry->modelFLT->data[i];141 pmModel *modelEXT = psfTry->modelEXT->data[i]; 142 142 143 143 // set shape for this model based on PSF 144 pmModel *modelPSF = pmModelFromPSF (model FLT, psfTry->psf);144 pmModel *modelPSF = pmModelFromPSF (modelEXT, psfTry->psf); 145 145 x = source->peak->x; 146 146 y = source->peak->y; 147 147 148 psImageKeepCircle (source->mask, x, y, RADIUS, "OR", P SPHOT_MASK_MARKED);149 status = pmSourceFitModel (source, modelPSF, true);148 psImageKeepCircle (source->mask, x, y, RADIUS, "OR", PM_SOURCE_MASK_MARKED); 149 status = pmSourceFitModel (source, modelPSF, PM_SOURCE_FIT_PSF); 150 150 151 151 // skip poor fits … … 162 162 // XXX : use a different estimator for the local sky? 163 163 // XXX : pass 'source' as input? 164 if (!pmSourcePhotometry (&fitMag, &obsMag, modelPSF, source->pixels, source->mask)) { 164 if (!pmSourcePhotometryModel (&fitMag, modelPSF)) { 165 psfTry->mask->data.U8[i] = PSFTRY_MASK_BAD_PHOT; 166 goto next_source; 167 } 168 if (!pmSourcePhotometryAper (&obsMag, modelPSF, source->pixels, source->mask)) { 165 169 psfTry->mask->data.U8[i] = PSFTRY_MASK_BAD_PHOT; 166 170 goto next_source; … … 172 176 173 177 next_source: 174 psImageKeepCircle (source->mask, x, y, RADIUS, "AND", ~PSPHOT_MASK_MARKED); 175 176 } 178 psImageKeepCircle (source->mask, x, y, RADIUS, "AND", ~PM_SOURCE_MASK_MARKED); 179 180 } 181 psfTry->psf->nPSFstars = Npsf; 182 177 183 psLogMsg ("psphot.psftry", 4, "fit psf: %f sec for %d sources\n", psTimerMark ("fit"), sources->n); 178 184 psTrace ("psphot.psftry", 3, "keeping %d of %d PSF candidates (PSF)\n", Npsf, sources->n); 179 185 180 // make this optional 181 // DumpModelFits (psfTry->modelPSF, "modelsPSF.dat"); 186 // measure the chi-square trend as a function of flux (PAR[1]) 187 // this should be linear for Poisson errors and quadratic for constant sky errors 188 psVector *flux = psVectorAlloc (psfTry->sources->n, PS_TYPE_F64); 189 psVector *chisq = psVectorAlloc (psfTry->sources->n, PS_TYPE_F64); 190 psVector *mask = psVectorAlloc (psfTry->sources->n, PS_TYPE_MASK); 191 192 // write sources with models first 193 for (int i = 0; i < psfTry->sources->n; i++) { 194 pmModel *model = psfTry->modelPSF->data[i]; 195 if (model == NULL) { 196 flux->data.F64[i] = 0.0; 197 chisq->data.F64[i] = 0.0; 198 mask->data.U8[i] = 1; 199 } else { 200 flux->data.F64[i] = model->params->data.F32[1]; 201 chisq->data.F64[i] = model[0].chisq/model[0].nDOF; 202 mask->data.U8[i] = 0; 203 } 204 } 205 // use 3hi/3lo sigma clipping on the r2rflux vs metric fit 206 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 207 stats->clipSigma = 3.0; 208 stats->clipIter = 3; 209 // linear clipped fit of ApResid to r2rflux 210 psVectorClipFitPolynomial1D (psfTry->psf->ChiTrend, stats, mask, 1, chisq, NULL, flux); 211 for (int i = 0; i < psfTry->psf->ChiTrend->nX + 1; i++) { 212 psLogMsg ("pmPSFtry", 4, "chisq vs flux fit term %d: %f +/- %f\n", i, psfTry->psf->ChiTrend->coeff[i]*pow(10000, i), psfTry->psf->ChiTrend->coeffErr[i]); 213 } 214 psLogMsg ("pmPSFtry", 4, "chisq vs flux fit: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev); 215 psFree (stats); 216 psFree (flux); 217 psFree (chisq); 182 218 183 219 // XXX this function wants aperture radius for pmSourcePhotometry 184 pmPSFtryMetric_Alt (psfTry, RADIUS); 185 psLogMsg ("psphot.pspsf", 3, "try model %s, ap-fit: %f +/- %f, sky bias: %f\n", 186 modelName, 187 psfTry->psf->ApResid, 188 psfTry->psf->dApResid, 189 psfTry->psf->skyBias); 220 pmPSFtryMetric (psfTry, RADIUS); 221 psLogMsg ("psphot.pspsf", 3, "try model %s, ap-fit: %f +/- %f : sky bias: %f\n", 222 modelName, psfTry->psf->ApResid, psfTry->psf->dApResid, psfTry->psf->skyBias); 190 223 191 224 return (psfTry); 192 225 } 193 226 194 195 227 bool pmPSFtryMetric (pmPSFtry *psfTry, float RADIUS) 196 228 { 197 198 float dBin;199 int nKeep, nSkip;200 201 229 // the measured (aperture - fit) magnitudes (dA == psfTry->metric) 202 230 // depend on both the true ap-fit (dAo) and the bias in the sky measurement: … … 208 236 // we use an outlier rejection to avoid this bias 209 237 210 // rflux = ten(0.4*fitMag); 211 psVector *rflux = psVectorAlloc (psfTry->sources->n, PS_TYPE_F64); 212 rflux->n = rflux->nalloc; 238 // r2rflux = radius^2 * ten(0.4*fitMag); 239 psVector *r2rflux = psVectorAlloc (psfTry->sources->n, PS_TYPE_F64); 213 240 for (int i = 0; i < psfTry->sources->n; i++) { 214 241 if (psfTry->mask->data.U8[i] & PSFTRY_MASK_ALL) 215 242 continue; 216 rflux->data.F64[i] = pow(10.0, 0.4*psfTry->fitMag->data.F64[i]); 217 } 218 219 // find min and max of (1/flux): 220 psStats *stats = psStatsAlloc (PS_STAT_MIN | PS_STAT_MAX); 221 psVectorStats (stats, rflux, NULL, psfTry->mask, PSFTRY_MASK_ALL); 222 223 // build binned versions of rflux, metric 224 dBin = (stats->max - stats->min) / 10.0; 225 psVector *rfBin = psVectorCreate(NULL, stats->min, stats->max, dBin, PS_TYPE_F64); 226 psVector *daBin = psVectorAlloc (rfBin->n, PS_TYPE_F64); 227 psVector *maskB = psVectorAlloc (rfBin->n, PS_TYPE_U8); 228 daBin->n = daBin->nalloc; 229 maskB->n = maskB->nalloc; 230 psFree (stats); 231 232 psTrace ("psphot.metricmodel", 3, "rflux max: %g, min: %g, delta: %g\n", stats->max, stats->min, dBin); 233 234 // group data in daBin bins, measure lower 50% mean 235 for (int i = 0; i < daBin->n; i++) { 236 237 psVector *tmp = psVectorAlloc (psfTry->sources->n, PS_TYPE_F64); 238 tmp->n = 0; 239 240 // accumulate data within bin range 241 for (int j = 0; j < psfTry->sources->n; j++) { 242 // masked for: bad model fit, outlier in parameters 243 if (psfTry->mask->data.U8[j] & PSFTRY_MASK_ALL) 244 continue; 245 246 // skip points with extreme dA values 247 if (fabs(psfTry->metric->data.F64[j]) > 0.5) 248 continue; 249 250 // skip points outside of this bin 251 if (rflux->data.F64[j] < rfBin->data.F64[i] - 0.5*dBin) 252 continue; 253 if (rflux->data.F64[j] > rfBin->data.F64[i] + 0.5*dBin) 254 continue; 255 256 tmp->data.F64[tmp->n] = psfTry->metric->data.F64[j]; 257 tmp->n ++; 258 } 259 260 // is this a valid point? 261 maskB->data.U8[i] = 0; 262 if (tmp->n < 2) { 263 maskB->data.U8[i] = 1; 264 psFree (tmp); 265 continue; 266 } 267 268 // dA values are contaminated with low outliers 269 // measure statistics only on upper 50% of points 270 // this would be easier if we could sort in reverse: 271 // 272 // psVectorSort (tmp, tmp); 273 // tmp->n = 0.5*tmp->n; 274 // stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN); 275 // psVectorStats (stats, tmp, NULL, NULL, 0); 276 // psTrace ("psphot.metricmodel", 4, "rfBin %d (%g): %d pts, %g\n", i, rfBin->data.F64[i], tmp->n, stats->sampleMedian); 277 278 psVectorSort (tmp, tmp); 279 nKeep = 0.5*tmp->n; 280 nSkip = tmp->n - nKeep; 281 282 psVector *tmp2 = psVectorAlloc (nKeep, PS_TYPE_F64); 283 tmp2->n = tmp2->nalloc; 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 psFree (stats); 295 psFree (tmp); 296 psFree (tmp2); 297 } 298 299 // linear fit to rfBin, daBin 300 psPolynomial1D *poly = psPolynomial1DAlloc(1, PS_POLYNOMIAL_ORD); 301 psStats *fitstat = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 302 poly = psVectorClipFitPolynomial1D (poly, fitstat, maskB, 1, daBin, NULL, rfBin); 303 304 // XXX EAM : this is the intended API (cycle 7? cycle 8?) 305 // poly = psVectorFitPolynomial1D(poly, maskB, 1, daBin, NULL, rfBin); 306 307 // XXX EAM : replace this when the above version is implemented 308 // poly = psVectorFitPolynomial1DOrd(poly, maskB, rfBin, daBin, NULL); 309 310 psVector *daBinFit = psPolynomial1DEvalVector (poly, rfBin); 311 psVector *daResid = (psVector *) psBinaryOp (NULL, (void *) daBin, "-", (void *) daBinFit); 312 313 stats = psStatsAlloc (PS_STAT_CLIPPED_STDEV); 314 stats = psVectorStats (stats, daResid, NULL, maskB, 1); 315 316 psfTry->psf->ApResid = poly->coeff[0]; 317 psfTry->psf->dApResid = stats->clippedStdev; 318 psfTry->psf->skyBias = poly->coeff[1] / (M_PI * PS_SQR(RADIUS)); 319 320 psFree (rflux); 321 psFree (rfBin); 322 psFree (daBin); 323 psFree (maskB); 324 psFree (daBinFit); 325 psFree (daResid); 326 psFree (poly); 327 psFree (stats); 328 psFree (fitstat); 329 330 return true; 331 } 332 333 bool pmPSFtryMetric_Alt (pmPSFtry *try 334 , float RADIUS) 335 { 336 337 // the measured (aperture - fit) magnitudes (dA == try->metric) 338 // depend on both the true ap-fit (dAo) and the bias in the sky measurement: 339 // dA = dAo + dsky/flux 340 // where flux is the flux of the star 341 // we fit this trend to find the infinite flux aperture correction (dAo), 342 // the nominal sky bias (dsky), and the error on dAo 343 // the values of dA are contaminated by stars with close neighbors in the aperture 344 // we use an outlier rejection to avoid this bias 345 346 // rflux = ten(0.4*fitMag); 347 psVector *rflux = psVectorAlloc (try 348 ->sources->n, PS_TYPE_F64); 349 rflux->n = rflux->nalloc; 350 for (int i = 0; i < try 351 ->sources->n; i++) { 352 if (try 353 ->mask->data.U8[i] & PSFTRY_MASK_ALL) continue; 354 rflux->data.F64[i] = pow(10.0, 0.4*try 355 ->fitMag->data.F64[i]); 356 } 357 358 // XXX EAM : try 3hi/1lo sigma clipping on the rflux vs metric fit 243 r2rflux->data.F64[i] = PS_SQR(RADIUS) * pow(10.0, 0.4*psfTry->fitMag->data.F64[i]); 244 } 245 246 // use 3hi/1lo sigma clipping on the r2rflux vs metric fit 359 247 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 360 361 // XXX EAM362 248 stats->min = 1.0; 363 249 stats->max = 3.0; 364 250 stats->clipIter = 3; 365 251 366 // linear clipped fit to rfBin, daBin 367 psPolynomial1D *poly = psPolynomial1DAlloc (1, PS_POLYNOMIAL_ORD); 368 poly = psVectorClipFitPolynomial1D (poly, stats, try 369 ->mask, PSFTRY_MASK_ALL, try 370 ->metric, NULL, rflux); 371 fprintf (stderr, "fit stats: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev); 372 373 try 374 ->psf->ApResid = poly->coeff[0]; 375 try 376 ->psf->dApResid = stats->sampleStdev; 377 try 378 ->psf->skyBias = poly->coeff[1] / (M_PI * PS_SQR(RADIUS)); 379 380 fprintf (stderr, "*******************************************************************************\n"); 381 382 FILE *f; 383 f = fopen ("apresid.dat", "w"); 384 if (f == NULL) 385 psAbort ("pmPSFtry", "can't open output file"); 386 387 for (int i = 0; i < try 388 ->sources->n; i++) { 389 fprintf (f, "%3d %8.4f %12.5e %8.4f %3d\n", i, try 390 ->fitMag->data.F64[i], rflux->data.F64[i], try 391 ->metric->data.F64[i], try 392 ->mask->data.U8[i]); 393 } 394 fclose (f); 395 396 psFree (rflux); 252 // fit ApTrend only to r2rflux, ignore x,y,flux variations for now 253 // linear clipped fit of ApResid to r2rflux 254 psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 1); 255 poly = psVectorClipFitPolynomial1D (poly, stats, psfTry->mask, PSFTRY_MASK_ALL, psfTry->metric, NULL, r2rflux); 256 psLogMsg ("pmPSFtryMetric", 4, "fit stats: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev); 257 258 pmPSF_MaskApTrend (psfTry->psf, PM_PSF_SKYBIAS); 259 psfTry->psf->ApTrend->coeff[0][0][0][0] = poly->coeff[0]; 260 psfTry->psf->ApTrend->coeff[0][0][1][0] = 0; 261 262 psfTry->psf->skyBias = poly->coeff[1]; 263 psfTry->psf->ApResid = poly->coeff[0]; 264 psfTry->psf->dApResid = stats->sampleStdev; 265 266 psFree (r2rflux); 397 267 psFree (poly); 398 268 psFree (stats); 399 269 400 // psFree (daFit);401 // psFree (daResid);402 403 270 return true; 404 271 } 272 273 /* 274 (aprMag' - fitMag) = rflux*skyBias + ApTrend(x,y) 275 (aprMag - rflux*skyBias) - fitMag = ApTrend(x,y) 276 (aprMag - rflux*skyBias) = fitMag + ApTrend(x,y) 277 */ 278
Note:
See TracChangeset
for help on using the changeset viewer.
