Changeset 31361
- Timestamp:
- Apr 24, 2011, 10:09:38 PM (15 years ago)
- Location:
- branches/eam_branches/ipp-20110404/psModules/src
- Files:
-
- 1 added
- 13 edited
-
camera/pmFPAMaskWeight.c (modified) (1 diff)
-
imcombine/pmPSFEnvelope.c (modified) (1 diff)
-
objects/Makefile.am (modified) (1 diff)
-
objects/pmGrowthCurve.c (modified) (1 diff)
-
objects/pmGrowthCurveGenerate.c (modified) (2 diffs)
-
objects/pmGrowthCurveGenerate.h (added)
-
objects/pmPSF.h (modified) (1 diff)
-
objects/pmPSF_IO.c (modified) (4 diffs)
-
objects/pmSource.h (modified) (3 diffs)
-
objects/pmSourceIO_CMF_PS1_V3.c (modified) (4 diffs)
-
objects/pmSourceMoments.c (modified) (21 diffs)
-
objects/pmSourcePhotometry.c (modified) (9 diffs)
-
objects/pmSourceUtils.h (modified) (1 diff)
-
psmodules.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20110404/psModules/src/camera/pmFPAMaskWeight.c
r29544 r31361 587 587 double imageValue, varianceValue; // Image and variance value from interpolation 588 588 psImageMaskType maskValue = 0; // Mask value from interpolation 589 psImageInterpolateStatus status = psImageInterpolate(&imageValue, &varianceValue, &maskValue, x, y, interp); 589 590 // interpolate to pixel center (index + 0.5) 591 psImageInterpolateStatus status = psImageInterpolate(&imageValue, &varianceValue, &maskValue, x + 0.5, y + 0.5, interp); 590 592 if (status == PS_INTERPOLATE_STATUS_ERROR || status == PS_INTERPOLATE_STATUS_OFF) { 591 593 psError(PS_ERR_UNKNOWN, false, "Unable to interpolate readout at %d,%d", x, y); -
branches/eam_branches/ipp-20110404/psModules/src/imcombine/pmPSFEnvelope.c
r29543 r31361 380 380 381 381 // measure the source moments: tophat windowing, no pixel S/N cutoff 382 if (!pmSourceMoments(source, maxRadius, 0.0, 0.0, maskVal)) {382 if (!pmSourceMoments(source, maxRadius, 0.0, 0.0, 0.0, maskVal)) { 383 383 // Can't do anything about it; limp along as best we can 384 384 psErrorClear(); -
branches/eam_branches/ipp-20110404/psModules/src/objects/Makefile.am
r31153 r31361 114 114 pmTrend2D.h \ 115 115 pmGrowthCurve.h \ 116 pmGrowthCurveGenerate.h \ 116 117 pmSourceMatch.h \ 117 118 pmDetEff.h \ -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmGrowthCurve.c
r29004 r31361 81 81 while (radius < Rlin) { 82 82 // fprintf (stderr, "r: %f\n", radius); 83 psVectorAppend (growth->radius, radius );83 psVectorAppend (growth->radius, radius - 0.001); 84 84 radius += 1.0; 85 85 } 86 86 while (radius < maxRadius) { 87 87 // fprintf (stderr, "r: %f\n", radius); 88 psVectorAppend (growth->radius, radius );88 psVectorAppend (growth->radius, radius - 0.001); 89 89 radius *= fR; 90 90 radius = (int) (radius + 0.5); -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmGrowthCurveGenerate.c
r31327 r31361 50 50 51 51 #include "pmSourcePhotometry.h" 52 53 pmGrowthCurve *pmGrowthCurveForPosition (psImage *image, pmPSF *psf, bool ignore, psImageMaskType maskVal, psImageMaskType markVal, float xc, float yc); 52 #include "pmGrowthCurveGenerate.h" 54 53 55 54 /*****************************************************************************/ … … 226 225 return growth; 227 226 } 227 228 // we generate the growth curve for the center of the image with the specified psf model 229 bool pmGrowthCurveGenerateFromSources (pmReadout *readout, pmPSF *psf, psArray *sources, bool INTERPOLATE_AP, psImageMaskType maskVal, psImageMaskType markVal) 230 { 231 PS_ASSERT_PTR_NON_NULL(readout, false); 232 PS_ASSERT_PTR_NON_NULL(readout->image, false); 233 234 // maskVal is used to test for rejected pixels, and must include markVal 235 maskVal |= markVal; 236 237 pmSourcePhotometryMode photMode = INTERPOLATE_AP ? PM_SOURCE_PHOT_INTERP : 0; 238 239 // measure the growth curve for each PSF source and average them together 240 psArray *growths = psArrayAllocEmpty (100); 241 242 for (int i = 0; i < sources->n; i++) { 243 244 pmSource *source = sources->data[i]; 245 246 if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue; 247 248 pmGrowthCurve *growth = pmGrowthCurveForSource (source, psf, photMode, maskVal, markVal); 249 if (!growth) continue; 250 251 psArrayAdd (growths, 100, growth); 252 psFree (growth); 253 } 254 psAssert (growths->n, "cannot build growth curve (no valid PSF stars?)"); 255 256 # if (0) 257 FILE *f = fopen ("growth.dat", "w"); 258 assert (f); 259 260 for (int j = 0; j < psf->growth->radius->n; j++) { 261 262 fprintf (f, "%f : ", psf->growth->radius->data.F32[j]); 263 264 // XXX dump the growth curves: 265 for (int i = 0; i < growths->n; i++) { 266 267 pmGrowthCurve *growth = growths->data[i]; 268 if (!growth) continue; 269 270 fprintf (f, "%8.4f ", growth->apMag->data.F32[j]); 271 } 272 fprintf (f, "\n"); 273 } 274 fclose (f); 275 # endif 276 277 // just use a simple sample median to get the 'best' value from each growth curve... 278 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN); 279 280 psVector *values = psVectorAlloc (growths->n, PS_DATA_F32); 281 282 // loop over a range of source fluxes 283 // no need to interpolate since we have forced the object center 284 // to 0.5, 0.5 above 285 for (int i = 0; i < psf->growth->radius->n; i++) { 286 287 // median the values for each radial bin 288 values->n = 0; 289 for (int j = 0; j < growths->n; j++) { 290 pmGrowthCurve *growth = growths->data[j]; 291 if (!isfinite(growth->apMag->data.F32[i])) continue; 292 psVectorAppend (values, growth->apMag->data.F32[i] - growth->fitMag); 293 } 294 if (values->n == 0) { 295 psf->growth->apMag->data.F32[i] = NAN; 296 } else { 297 if (!psVectorStats (stats, values, NULL, NULL, 0)) { 298 psError(PS_ERR_UNKNOWN, false, "failure to measure stats"); 299 return false; 300 } 301 psf->growth->apMag->data.F32[i] = stats->sampleMedian; 302 } 303 } 304 305 psf->growth->fitMag = psf->growth->apMag->data.F32[psf->growth->radius->n-1]; 306 psf->growth->apRef = psVectorInterpolate (psf->growth->radius, psf->growth->apMag, psf->growth->refRadius); 307 psf->growth->apLoss = psf->growth->fitMag - psf->growth->apRef; 308 309 psLogMsg ("psphot.growth", 4, "GrowthCurve : apLoss : %f (fitMag - apMag @ ref : %f - %f)\n", psf->growth->apLoss, psf->growth->fitMag, psf->growth->apRef); 310 311 psFree (growths); 312 psFree (stats); 313 psFree (values); 314 315 return true; 316 } 317 318 pmGrowthCurve *pmGrowthCurveForSource (pmSource *source, pmPSF *psf, pmSourcePhotometryMode photMode, psImageMaskType maskVal, psImageMaskType markVal) { 319 320 float radius; 321 322 assert (psf->growth); 323 324 float minRadius = psf->growth->radius->data.F32[0]; 325 pmGrowthCurve *growth = pmGrowthCurveAlloc (minRadius, psf->growth->maxRadius, psf->growth->refRadius); 326 327 // measure the fitMag for this source (for normalization) 328 // pmSourcePhotometryModel (&fitMag, NULL, source->psfModel); 329 growth->fitMag = source->psfMag; 330 331 float xc = source->peak->xf; 332 float yc = source->peak->yf; 333 334 // Loop over the range of radii 335 for (int i = 0; i < growth->radius->n; i++) { 336 337 radius = growth->radius->data.F32[i]; 338 339 // mask the given aperture and measure the apMag 340 psImageKeepCircle (source->maskObj, xc, yc, radius, "OR", markVal); 341 342 if (!pmSourceMagnitudes (source, psf, photMode, maskVal, markVal, radius)) { 343 psFree (growth); 344 return NULL; 345 } 346 347 // if (!pmSourcePhotometryAper (NULL, &apMag, NULL, NULL, NULL, source->pixels, NULL, source->maskObj, maskVal)) { 348 // psFree (growth); 349 // return NULL; 350 // } 351 352 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); // clear the circular mask 353 354 growth->apMag->data.F32[i] = source->apMag; 355 } 356 return growth; 357 } 358 359 # if (0) 360 // solve for the best growth and the offsets per star to minimize the scatter 361 362 // generate the per-star and per-radius sums 363 int Nradius = psf->growth->radius->n; 364 int Nstar = growths->n; 365 366 psVector *Mstar = psVectorAlloc (Nstar, PS_DATA_F32); 367 psVector *Mradius = psVectorAlloc (Nradius, PS_DATA_F32); 368 369 psVectorInit (Mstar, 0.0); 370 psVectorInit (Mradius, 0.0); 371 372 for (int i = 0; i < Nstar; i++) { 373 pmGrowthCurve *growth = growths->data[i]; 374 for (int j = 0; j < Nradius; j++) { 375 Mstar->data.F32[i] += growth->apMag->data.F32[j]; 376 Mradius->data.F32[j] += growth->apMag->data.F32[j]; 377 } 378 } 379 380 psImage *A = psImageAlloc(Nstar + Nradius, Nstar + Nradius, PS_DATA_F32); 381 psVector *B = psVectorAlloc(Nstar + Nradius, PS_DATA_F32); 382 383 psImageInit (A, 0.0); 384 psVectorInit (B, 0.0); 385 386 for (int i = 0; i < Nstar; i++) { 387 A->data.F32[i][i] = Nradius; 388 B->data.F32[i] = Mstar->data.F32[i]; 389 } 390 for (int i = 0; i < Nradius; i++) { 391 int j = i + Nstar; 392 A->data.F32[j][j] = Nstar; 393 B->data.F32[j] = Mradius->data.F32[i]; 394 } 395 396 if (!psMatrixGJSolve(A, B)) { 397 psAbort("GJ failure"); 398 } 399 400 for (int i = 0; i < Nradius; i++) { 401 psf->growth->apMag->data.F32[i] = B->data.F32[Nstar+i]; 402 } 403 404 // XXX this analysis produces a biased growth curve: points with small radius are more 405 // likely to err on the side of being too faint (bacause of mis-aligned aperture), while on 406 // the bright side the tend to be too bright (because of contaminating neighbors). Bright 407 // stars are less likely to be biased, 408 409 // XXX at this point, we could iterate and exclude some of the stars with low data quality 410 // XXX we could also weight the above by flux or something 411 412 # endif -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmPSF.h
r29004 r31361 94 94 double pmPSF_SXYtoModel (psF32 *fittedPar); 95 95 96 bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psImageMaskType maskVal, psImageMaskType mark);97 96 pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...); 98 97 -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmPSF_IO.c
r31339 r31361 65 65 bool pmPSFmodelRead_ApTrend (pmPSF *psf, pmFPAfile *file); 66 66 bool pmPSFmodelWrite_ApTrend (pmFPAfile *file, pmPSF *psf); 67 68 bool pmPSFmodelRead_GrowthCurve (pmPSF *psf, pmFPAfile *file); 69 bool pmPSFmodelWrite_GrowthCurve (pmFPAfile *file, pmPSF *psf); 67 70 68 71 bool pmPSFmodelCheckDataStatusForView (const pmFPAview *view, const pmFPAfile *file) … … 600 603 if (!pmPSFmodelWrite_ApTrend(file, psf)) { 601 604 psError(psErrorCodeLast(), false, "Unable to write PSF ApTrend"); 605 return false; 606 } 607 608 if (!pmPSFmodelWrite_GrowthCurve(file, psf)) { 609 psError(psErrorCodeLast(), false, "Unable to write PSF Growth Curve"); 602 610 return false; 603 611 } … … 1104 1112 } 1105 1113 1114 if (!pmPSFmodelRead_GrowthCurve(psf, file)) { 1115 psError(psErrorCodeLast(), false, "Unable to read PSF Growth Curve"); 1116 return false; 1117 } 1118 1106 1119 psMetadataAdd (chipAnalysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_DATA_UNKNOWN, "psphot psf", psf); 1107 1120 psFree (psf); … … 1230 1243 } 1231 1244 1245 // write aperture trend to a FITS table 1246 bool pmPSFmodelWrite_GrowthCurve (pmFPAfile *file, pmPSF *psf) { 1247 1248 pmGrowthCurve *growth = psf->growth; 1249 if (growth == NULL) { 1250 psWarning ("no PSF Growth Curve to write out, skipping"); 1251 return true; 1252 } 1253 1254 // we need to write a header for the table, 1255 psMetadata *header = psMetadataAlloc(); 1256 1257 psMetadataAddF32 (header, PS_LIST_TAIL, "GROWTH_MIN_RAD", 0, "", growth->radius->data.F32[0]); 1258 psMetadataAddF32 (header, PS_LIST_TAIL, "GROWTH_MAX_RAD", 0, "", growth->maxRadius); 1259 psMetadataAddF32 (header, PS_LIST_TAIL, "GROWTH_REF_RAD", 0, "", growth->refRadius); 1260 psMetadataAddF32 (header, PS_LIST_TAIL, "GROWTH_AP_LOSS", 0, "", growth->apLoss); 1261 psMetadataAddF32 (header, PS_LIST_TAIL, "GROWTH_AP_REF", 0, "", growth->apRef); 1262 psMetadataAddF32 (header, PS_LIST_TAIL, "GROWTH_FIT_MAG", 0, "", growth->fitMag); 1263 1264 // build a FITS table of the ApTrend (only 1) 1265 psArray *table = psArrayAllocEmpty (100); 1266 for (int i = 0; i < growth->apMag->n; i++) { 1267 psMetadata *row = psMetadataAlloc (); 1268 psMetadataAddF32 (row, PS_LIST_TAIL, "RADIUS", 0, "", growth->radius->data.F32[i]); 1269 psMetadataAddF32 (row, PS_LIST_TAIL, "AP_MAG", 0, "", growth->apMag->data.F32[i]); 1270 psArrayAdd (table, 100, row); 1271 psFree (row); 1272 } 1273 1274 // write an empty FITS segment if we have no PSF information 1275 if (table->n == 0) { 1276 psError(PM_ERR_PROG, true, "No PSF data to write."); 1277 psFree(table); 1278 psFree(header); 1279 return false; 1280 } 1281 1282 psTrace ("pmFPAfile", 5, "writing psf Growth Curve data %s\n", "GROWTH_CURVE"); 1283 if (!psFitsWriteTable(file->fits, header, table, "GROWTH_CURVE")) { 1284 psError(psErrorCodeLast(), false, "Error writing psf table data %s\n", "GROWTH_CURVE"); 1285 psFree(table); 1286 psFree(header); 1287 return false; 1288 } 1289 1290 psFree (table); 1291 psFree (header); 1292 return true; 1293 } 1294 1295 // read aperture trend to a FITS table 1296 bool pmPSFmodelRead_GrowthCurve (pmPSF *psf, pmFPAfile *file) { 1297 1298 bool status; 1299 1300 // move fits pointer to AP_TREND section 1301 // advance to the table data extension 1302 if (!psFitsMoveExtNameClean (file->fits, "GROWTH_CURVE")) { 1303 psWarning ("no Growth Curve data in PSF file, skipping"); 1304 return true; 1305 } 1306 1307 psMetadata *header = psFitsReadHeader (NULL, file->fits); 1308 if (!header) { 1309 psError(psErrorCodeLast(), false, "Unable to read GROWTH_CURVE header."); 1310 return false; 1311 } 1312 1313 // read the raw table data 1314 psArray *table = psFitsReadTable (file->fits); 1315 if (!table) { 1316 psError(psErrorCodeLast(), false, "Unable to read GROWTH_CURVE table."); 1317 psFree(header); 1318 return false; 1319 } 1320 1321 float minRadius = psMetadataLookupF32 (&status, header, "GROWTH_MIN_RAD"); if (!status) return false; 1322 float maxRadius = psMetadataLookupF32 (&status, header, "GROWTH_MAX_RAD"); if (!status) return false; 1323 float refRadius = psMetadataLookupF32 (&status, header, "GROWTH_REF_RAD"); if (!status) return false; 1324 1325 psf->growth = pmGrowthCurveAlloc(minRadius, maxRadius, refRadius); 1326 1327 psf->growth->apLoss = psMetadataLookupF32 (&status, header, "GROWTH_AP_LOSS"); if (!status) return false; 1328 psf->growth->apRef = psMetadataLookupF32 (&status, header, "GROWTH_AP_REF"); if (!status) return false; 1329 psf->growth->fitMag = psMetadataLookupF32 (&status, header, "GROWTH_FIT_MAG"); if (!status) return false; 1330 1331 // fill in the matching psf->params entries 1332 for (int i = 0; i < table->n; i++) { 1333 psMetadata *row = table->data[i]; 1334 psf->growth->apMag->data.F32[i] = psMetadataLookupF32 (&status, row, "AP_MAG"); if (!status) return false; 1335 } 1336 1337 psFree (header); 1338 psFree (table); 1339 return true; 1340 } 1341 1232 1342 bool pmPSFmodelReadPSFClump (psMetadata *analysis, psMetadata *header) { 1233 1343 -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmSource.h
r31153 r31361 82 82 psArray *blends; ///< collection of sources thought to be confused with object 83 83 float psfMag; ///< calculated from flux in modelPSF 84 float psfMagErr; ///< error in psfMag 84 85 float psfFlux; ///< calculated from flux in modelPSF 85 float psfFluxErr; ///< calculated from flux in modelPSF 86 float extMag; ///< calculated from flux in modelEXT 87 float errMag; ///< error in psfMag OR extMag (depending on type) 86 float psfFluxErr; ///< error in psfFlux 87 float extMag; ///< calculated from flux in modelEXT -- NOTE this is not actually used 88 88 float apMag; ///< apMag corresponding to psfMag or extMag (depending on type) 89 89 float apMagRaw; ///< raw mag in given aperture … … 254 254 float sigma, ///< size of Gaussian window function (<= 0.0 -> skip window) 255 255 float minSN, ///< minimum pixel significance 256 float minKronRadius, ///< minimum pixel significance 256 257 psImageMaskType maskVal 257 258 ); … … 273 274 float xGuess, float yGuess); 274 275 276 float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM); 277 275 278 pmModel *pmSourceGetModel (bool *isPSF, const pmSource *source); 276 279 -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmSourceIO_CMF_PS1_V3.c
r31153 r31361 116 116 psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE", PS_DATA_F32, "plate scale at source (arcsec/pixel)", outputs.pltScale); 117 117 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG", PS_DATA_F32, "PSF fit instrumental magnitude", source->psfMag); 118 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude", source-> errMag);118 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude", source->psfMagErr); 119 119 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX", PS_DATA_F32, "PSF fit instrumental flux (counts)", source->psfFlux); 120 120 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX_SIG",PS_DATA_F32, "Sigma of PSF instrumental flux", source->psfFluxErr); … … 161 161 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER", PS_DATA_F32, "Kron Flux (in 2.5 R1)", moments.Kinner); 162 162 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER", PS_DATA_F32, "Kron Flux (in 2.5 R1)", moments.Kouter); 163 164 // Do NOT write these : not consistent with the definition of PS1_V3 in Ohana/src/libautocode/dev/cmf-ps1-v3.d 163 165 // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_FLUX", PS_DATA_F32, "Kron Flux (in 1.0 R1)", moments.KronCore); 164 // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_ERROR", PS_DATA_F32, "Kron Error (in 1.0 R1)", moments.KronCoreErr);166 // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_ERROR", PS_DATA_F32, "Kron Error (in 1.0 R1)", moments.KronCoreErr); 165 167 psMetadataAdd (row, PS_LIST_TAIL, "FLAGS", PS_DATA_U32, "psphot analysis flags", source->mode); 166 168 psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2", PS_DATA_U32, "psphot analysis flags", source->mode2); … … 270 272 // XXX use these to determine PAR[PM_PAR_I0]? 271 273 source->psfMag = psMetadataLookupF32 (&status, row, "PSF_INST_MAG"); 272 source-> errMag= psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");274 source->psfMagErr = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG"); 273 275 source->apMag = psMetadataLookupF32 (&status, row, "AP_MAG"); 274 276 275 277 // XXX this scaling is incorrect: does not include the 2 \pi AREA factor 276 278 PAR[PM_PAR_I0] = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN; 277 dPAR[PM_PAR_I0] = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source-> errMag: NAN;279 dPAR[PM_PAR_I0] = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->psfMagErr : NAN; 278 280 279 281 pmPSF_AxesToModel (PAR, axes); … … 292 294 293 295 // we no longer sort by S/N, only flux 294 // if (isfinite (source-> errMag) && (source->errMag> 0.0)) {295 // source->peak->SN = 1.0 / source-> errMag;296 // if (isfinite (source->psfMagErr) && (source->psfMagErr > 0.0)) { 297 // source->peak->SN = 1.0 / source->psfMagErr; 296 298 // } else { 297 299 // source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmSourceMoments.c
r31327 r31361 66 66 // if mode & EXTERNAL or mode2 & MATCHED, do not re-calculate the centroid (use peak as centroid) 67 67 68 bool pmSourceMoments(pmSource *source, psF32 radius, psF32 sigma, psF32 minSN, psImageMaskType maskVal)68 bool pmSourceMoments(pmSource *source, float radius, float sigma, float minSN, float minKronRadius, psImageMaskType maskVal) 69 69 { 70 70 PS_ASSERT_PTR_NON_NULL(source, false); … … 74 74 75 75 // this function assumes the sky has been well-subtracted for the image 76 psF32sky = 0.0;76 float sky = 0.0; 77 77 78 78 if (source->moments == NULL) { … … 80 80 } 81 81 82 psF32Sum = 0.0;83 psF32Var = 0.0;84 psF32SumCore = 0.0;85 psF32VarCore = 0.0;86 psF32R2 = PS_SQR(radius);87 psF32minSN2 = PS_SQR(minSN);88 psF32rsigma2 = 0.5 / PS_SQR(sigma);82 float Sum = 0.0; 83 float Var = 0.0; 84 float SumCore = 0.0; 85 float VarCore = 0.0; 86 float R2 = PS_SQR(radius); 87 float minSN2 = PS_SQR(minSN); 88 float rsigma2 = 0.5 / PS_SQR(sigma); 89 89 90 90 // a note about coordinates: coordinates of objects throughout psphot refer to the primary … … 109 109 // Xn = SUM (x - xc)^n * (z - sky) 110 110 111 psF32RFW = 0.0;112 psF32RHW = 0.0;113 114 psF32RF = 0.0;115 psF32RH = 0.0;116 psF32RS = 0.0;117 psF32XX = 0.0;118 psF32XY = 0.0;119 psF32YY = 0.0;120 psF32XXX = 0.0;121 psF32XXY = 0.0;122 psF32XYY = 0.0;123 psF32YYY = 0.0;124 psF32XXXX = 0.0;125 psF32XXXY = 0.0;126 psF32XXYY = 0.0;127 psF32XYYY = 0.0;128 psF32YYYY = 0.0;111 float RFW = 0.0; 112 float RHW = 0.0; 113 114 float RF = 0.0; 115 float RH = 0.0; 116 float RS = 0.0; 117 float XX = 0.0; 118 float XY = 0.0; 119 float YY = 0.0; 120 float XXX = 0.0; 121 float XXY = 0.0; 122 float XYY = 0.0; 123 float YYY = 0.0; 124 float XXXX = 0.0; 125 float XXXY = 0.0; 126 float XXYY = 0.0; 127 float XYYY = 0.0; 128 float YYYY = 0.0; 129 129 130 130 Sum = 0.0; // the second pass may include slightly different pixels, re-determine Sum … … 140 140 // center of mass in subimage. Note: the calculation below uses pixel index, so we correct 141 141 // xCM, yCM from pixel coords to pixel index here. 142 psF32xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage143 psF32yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage142 float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage 143 float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage 144 144 145 145 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 146 146 147 psF32yDiff = row - yCM;147 float yDiff = row - yCM; 148 148 if (fabs(yDiff) > radius) continue; 149 149 150 psF32*vPix = source->pixels->data.F32[row];151 psF32*vWgt = source->variance->data.F32[row];150 float *vPix = source->pixels->data.F32[row]; 151 float *vWgt = source->variance->data.F32[row]; 152 152 153 153 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row]; … … 164 164 if (isnan(*vPix)) continue; 165 165 166 psF32xDiff = col - xCM;166 float xDiff = col - xCM; 167 167 if (fabs(xDiff) > radius) continue; 168 168 169 169 // radius is just a function of (xDiff, yDiff) 170 psF32r2 = PS_SQR(xDiff) + PS_SQR(yDiff);170 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 171 171 if (r2 > R2) continue; 172 172 173 psF32fDiff = *vPix - sky;174 psF32pDiff = fDiff;175 psF32wDiff = *vWgt;173 float fDiff = *vPix - sky; 174 float pDiff = fDiff; 175 float wDiff = *vWgt; 176 176 177 177 // skip pixels below specified significance level. this is allowed, but should be … … 184 184 // weighting over weights the sky for faint sources 185 185 if (sigma > 0.0) { 186 psF32z = r2 * rsigma2;186 float z = r2 * rsigma2; 187 187 assert (z >= 0.0); 188 psF32weight = exp(-z);188 float weight = exp(-z); 189 189 190 190 wDiff *= weight; … … 195 195 196 196 // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?) 197 psF32r = sqrt(r2);198 psF32rf = r * fDiff;199 psF32rh = sqrt(r) * fDiff;200 psF32rs = fDiff;201 202 psF32rfw = r * pDiff;203 psF32rhw = sqrt(r) * pDiff;204 205 psF32x = xDiff * pDiff;206 psF32y = yDiff * pDiff;207 208 psF32xx = xDiff * x;209 psF32xy = xDiff * y;210 psF32yy = yDiff * y;211 212 psF32xxx = xDiff * xx / r;213 psF32xxy = xDiff * xy / r;214 psF32xyy = xDiff * yy / r;215 psF32yyy = yDiff * yy / r;216 217 psF32xxxx = xDiff * xxx / r2;218 psF32xxxy = xDiff * xxy / r2;219 psF32xxyy = xDiff * xyy / r2;220 psF32xyyy = xDiff * yyy / r2;221 psF32yyyy = yDiff * yyy / r2;197 float r = sqrt(r2); 198 float rf = r * fDiff; 199 float rh = sqrt(r) * fDiff; 200 float rs = fDiff; 201 202 float rfw = r * pDiff; 203 float rhw = sqrt(r) * pDiff; 204 205 float x = xDiff * pDiff; 206 float y = yDiff * pDiff; 207 208 float xx = xDiff * x; 209 float xy = xDiff * y; 210 float yy = yDiff * y; 211 212 float xxx = xDiff * xx / r; 213 float xxy = xDiff * xy / r; 214 float xyy = xDiff * yy / r; 215 float yyy = yDiff * yy / r; 216 217 float xxxx = xDiff * xxx / r2; 218 float xxxy = xDiff * xxy / r2; 219 float xxyy = xDiff * xyy / r2; 220 float xyyy = xDiff * yyy / r2; 221 float yyyy = yDiff * yyy / r2; 222 222 223 223 RF += rf; … … 245 245 } 246 246 247 // if Mrf (first radial moment) is << sigma, we are getting into low-significance 248 // territory. saturate at 0.75*sigma. conversely, if Mrf is > radius, we are clearly 249 // making an error. saturate at radius. 250 source->moments->Mrf = MIN(radius, MAX(0.75*sigma, RF/RS)); 251 source->moments->Mrh = MIN(radius, MAX(0.75*sigma, RH/RS)); 247 source->moments->Mrf = RF/RS; 248 source->moments->Mrh = RH/RS; 252 249 253 250 source->moments->Mxx = XX/Sum; … … 266 263 source->moments->Myyyy = YYYY/Sum; 267 264 268 // XXX TEST:269 // source->moments->KronFinner = RFW/Sum;270 // source->moments->KronFouter = sigma;271 272 // Calculate the Kron magnitude (make this block optional?) 273 float radKinner = 1.0* source->moments->Mrf;274 float radKron = 2.5* source->moments->Mrf;275 float radKouter = 4.0* source->moments->Mrf;265 // if Mrf (first radial moment) is very small, we are getting into low-significance 266 // territory. saturate at minKronRadius. conversely, if Mrf is > radius, we are clearly 267 // making an error. saturate at radius. 268 float kronRefRadius = MIN(radius, MAX(minKronRadius, source->moments->Mrf)); 269 270 float radKinner = 1.0*kronRefRadius; 271 float radKron = 2.5*kronRefRadius; 272 float radKouter = 4.0*kronRefRadius; 276 273 277 274 int nKronPix = 0; … … 285 282 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 286 283 287 psF32yDiff = row - yCM;284 float yDiff = row - yCM; 288 285 if (fabs(yDiff) > radKouter) continue; 289 286 290 psF32*vPix = source->pixels->data.F32[row];291 psF32*vWgt = source->variance->data.F32[row];287 float *vPix = source->pixels->data.F32[row]; 288 float *vWgt = source->variance->data.F32[row]; 292 289 293 290 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row]; … … 304 301 if (isnan(*vPix)) continue; 305 302 306 psF32xDiff = col - xCM;303 float xDiff = col - xCM; 307 304 if (fabs(xDiff) > radKouter) continue; 308 305 309 306 // radKron is just a function of (xDiff, yDiff) 310 psF32r2 = PS_SQR(xDiff) + PS_SQR(yDiff);311 312 psF32pDiff = *vPix - sky;313 psF32wDiff = *vWgt;307 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 308 309 float pDiff = *vPix - sky; 310 float wDiff = *vWgt; 314 311 315 312 // skip pixels below specified significance level. this is allowed, but should be … … 318 315 if (PS_SQR(pDiff) < minSN2*wDiff) continue; 319 316 320 psF32r = sqrt(r2);317 float r = sqrt(r2); 321 318 if (r < radKron) { 322 319 Sum += pDiff; … … 363 360 } 364 361 365 bool pmSourceMomentsGetCentroid(pmSource *source, psF32 radius, psF32 sigma, psF32minSN, psImageMaskType maskVal, float xGuess, float yGuess) {362 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) { 366 363 367 364 // First Pass: calculate the first moments (these are subtracted from the coordinates below) … … 370 367 // .. etc 371 368 372 psF32sky = 0.0;373 374 psF32peakPixel = -PS_MAX_F32;369 float sky = 0.0; 370 371 float peakPixel = -PS_MAX_F32; 375 372 psS32 numPixels = 0; 376 psF32Sum = 0.0;377 psF32Var = 0.0;378 psF32X1 = 0.0;379 psF32Y1 = 0.0;380 psF32R2 = PS_SQR(radius);381 psF32minSN2 = PS_SQR(minSN);382 psF32rsigma2 = 0.5 / PS_SQR(sigma);373 float Sum = 0.0; 374 float Var = 0.0; 375 float X1 = 0.0; 376 float Y1 = 0.0; 377 float R2 = PS_SQR(radius); 378 float minSN2 = PS_SQR(minSN); 379 float rsigma2 = 0.5 / PS_SQR(sigma); 383 380 384 381 float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage … … 386 383 387 384 // we are guaranteed to have a valid pixel and variance at this location (right? right?) 388 // psF32weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);385 // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]); 389 386 // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel"); 390 387 // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel"); … … 398 395 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 399 396 400 psF32yDiff = row + 0.5 - yPeak;397 float yDiff = row + 0.5 - yPeak; 401 398 if (fabs(yDiff) > radius) continue; 402 399 403 psF32*vPix = source->pixels->data.F32[row];404 psF32*vWgt = source->variance->data.F32[row];400 float *vPix = source->pixels->data.F32[row]; 401 float *vWgt = source->variance->data.F32[row]; 405 402 406 403 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row]; … … 417 414 if (isnan(*vPix)) continue; 418 415 419 psF32xDiff = col + 0.5 - xPeak;416 float xDiff = col + 0.5 - xPeak; 420 417 if (fabs(xDiff) > radius) continue; 421 418 422 419 // radius is just a function of (xDiff, yDiff) 423 psF32r2 = PS_SQR(xDiff) + PS_SQR(yDiff);420 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 424 421 if (r2 > R2) continue; 425 422 426 psF32pDiff = *vPix - sky;427 psF32wDiff = *vWgt;423 float pDiff = *vPix - sky; 424 float wDiff = *vWgt; 428 425 429 426 // skip pixels below specified significance level. for a PSFs, this … … 438 435 // weighting over weights the sky for faint sources 439 436 if (sigma > 0.0) { 440 psF32z = r2*rsigma2;437 float z = r2*rsigma2; 441 438 assert (z >= 0.0); 442 psF32weight = exp(-z);439 float weight = exp(-z); 443 440 444 441 wDiff *= weight; … … 449 446 Sum += pDiff; 450 447 451 psF32xWght = xDiff * pDiff;452 psF32yWght = yDiff * pDiff;448 float xWght = xDiff * pDiff; 449 float yWght = yDiff * pDiff; 453 450 454 451 X1 += xWght; … … 507 504 return true; 508 505 } 506 507 float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) { 508 509 psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32); 510 511 for (int i = 0; i < sources->n; i++) { 512 pmSource *src = sources->data[i]; // Source of interest 513 if (!src || !src->moments) { 514 continue; 515 } 516 517 if (src->mode & PM_SOURCE_MODE_BLEND) { 518 continue; 519 } 520 521 if (!src->moments->nPixels) continue; 522 523 if (src->moments->SN < PSF_SN_LIM) continue; 524 525 // XXX put in Mxx,Myy cut based on clump location 526 527 psVectorAppend(radii, src->moments->Mrf); 528 } 529 530 // find the peak in this image 531 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN); 532 533 if (!psVectorStats (stats, radii, NULL, NULL, 0)) { 534 psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n"); 535 psFree(stats); 536 return NAN; 537 } 538 539 float minRadius = stats->sampleMedian; 540 541 psFree(radii); 542 psFree(stats); 543 return minRadius; 544 } 545 -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmSourcePhotometry.c
r31340 r31361 82 82 - apMag : only if S/N > AP_MIN_SN 83 83 : is optionally corrected for curve-of-growth if: 84 - the source is a STAR (PSF)85 84 - the option is selected (mode & PM_SOURCE_PHOT_GROWTH) 86 85 - psfMag : all sources with non-NULL modelPSF 87 86 : is optionally corrected for aperture residual if: 88 - the source is a STAR (PSF)89 87 - the option is selected (mode & PM_SOURCE_PHOT_APCORR) 90 91 88 - extMag : all sources with non-NULL modelEXT 92 89 **/ … … 100 97 101 98 int status = false; 102 bool isPSF;103 99 float x, y; 104 100 float SN; 105 pmModel *model;106 101 107 102 source->psfMag = NAN; 108 103 source->extMag = NAN; 109 source-> errMag= NAN;104 source->psfMagErr = NAN; 110 105 source->apMag = NAN; 111 106 source->apMagRaw = NAN; … … 113 108 source->apFluxErr = NAN; 114 109 115 // we must have a valid model 116 // XXX allow aperture magnitudes for sources without a model 117 model = pmSourceGetModel (&isPSF, source); 118 if (model == NULL) { 119 psTrace ("psModules.objects", 3, "fail mag : no valid model"); 110 // XXXXXX review: 111 // Select the 'best' model -- this is used for PSF_QF,_PERFECT & ???. isPSF is true if this 112 // object is a PSF (not extended). We must have a valid model. XXX NOTE: allow aperture 113 // magnitudes for sources without a model 114 115 // select the psf model 116 pmModel *modelPSF = source->modelPSF; 117 if (modelPSF == NULL) { 118 psTrace ("psModules.objects", 3, "fail mag : no valid PSF model"); 120 119 return false; 121 120 } 122 121 123 // XXX handle negative flux, low-significance124 if (model ->dparams->data.F32[PM_PAR_I0] > 0) {125 SN = fabs(model ->params->data.F32[PM_PAR_I0] / model->dparams->data.F32[PM_PAR_I0]);126 source-> errMag= 1.0 / SN;122 // get the error on the PSF model magnitude 123 if (modelPSF->dparams->data.F32[PM_PAR_I0] > 0) { 124 SN = fabs(modelPSF->params->data.F32[PM_PAR_I0] / modelPSF->dparams->data.F32[PM_PAR_I0]); 125 source->psfMagErr = 1.0 / SN; 127 126 } else { 128 127 SN = NAN; 129 source->errMag = NAN; 130 } 131 x = model->params->data.F32[PM_PAR_XPOS]; 132 y = model->params->data.F32[PM_PAR_YPOS]; 128 source->psfMagErr = NAN; 129 } 130 // the source position is used to recenter the aperture for ap photometry 131 x = modelPSF->params->data.F32[PM_PAR_XPOS]; 132 y = modelPSF->params->data.F32[PM_PAR_YPOS]; 133 133 134 134 // measure PSF model photometry 135 // XXX TEST: do not use flux scale 136 // XXX NOTE: turn this back on? 137 if (0 && psf->FluxScale) { 138 // the source peak pixel is guaranteed to be on the image, and only minimally different from the source center 139 double fluxScale = pmTrend2DEval (psf->FluxScale, (float)source->peak->x, (float)source->peak->y); 140 psAssert (isfinite(fluxScale), "how can the flux scale be invalid? source at %d, %d\n", source->peak->x, source->peak->y); 141 psAssert (fluxScale > 0.0, "how can the flux scale be negative? source at %d, %d\n", source->peak->x, source->peak->y); 142 source->psfFlux = fluxScale * source->modelPSF->params->data.F32[PM_PAR_I0]; 143 source->psfFluxErr = fluxScale * source->modelPSF->dparams->data.F32[PM_PAR_I0]; 144 source->psfMag = -2.5*log10(source->psfFlux); 145 } else { 146 status = pmSourcePhotometryModel (&source->psfMag, &source->psfFlux, source->modelPSF); 147 source->psfFluxErr = source->psfFlux * (source->modelPSF->dparams->data.F32[PM_PAR_I0] / source->modelPSF->params->data.F32[PM_PAR_I0]); 148 } 135 status = pmSourcePhotometryModel (&source->psfMag, &source->psfFlux, modelPSF); 136 source->psfFluxErr = source->psfFlux * source->psfMagErr; 137 138 # if (0) 139 // XXX NOTE: old code to use the flux scale. test & turn this back on? if so, need to save with psf model 140 // the source peak pixel is guaranteed to be on the image, and only minimally different from the source center 141 double fluxScale = pmTrend2DEval (psf->FluxScale, (float)source->peak->x, (float)source->peak->y); 142 psAssert (isfinite(fluxScale), "how can the flux scale be invalid? source at %d, %d\n", source->peak->x, source->peak->y); 143 psAssert (fluxScale > 0.0, "how can the flux scale be negative? source at %d, %d\n", source->peak->x, source->peak->y); 144 source->psfFlux = fluxScale * modelPSF->params->data.F32[PM_PAR_I0]; 145 source->psfFluxErr = fluxScale * modelPSF->dparams->data.F32[PM_PAR_I0]; 146 source->psfMag = -2.5*log10(source->psfFlux); 147 # endif 149 148 150 149 if (mode == PM_SOURCE_PHOT_PSFONLY) { … … 152 151 } 153 152 153 // get the EXT model photometry (all EXT models) 154 154 // if we have a collection of model fits, check if one of them is a pointer to modelEXT 155 155 if (source->modelFits) { … … 172 172 } 173 173 174 // for PSFs, correct both apMag and psfMag to same system, consistent with infinite flux star in aperture RADIUS 175 // XXX add a flag for "ap_mag is corrected?" 176 if ((mode & PM_SOURCE_PHOT_APCORR) && isPSF && psf && psf->ApTrend) { 174 // Correct psfMag to match aperture magnitude system (NOTE : Growth curve is already applied to ApTrend) 175 if ((mode & PM_SOURCE_PHOT_APCORR) && psf && psf->ApTrend) { 177 176 // the source peak pixel is guaranteed to be on the image, and only minimally different from the source center 178 177 double apTrend = pmTrend2DEval (psf->ApTrend, (float)source->peak->x, (float)source->peak->y); … … 182 181 } 183 182 184 // measure the contribution of included pixels 183 // measure the contribution of included pixels to the PSF model fit 185 184 if (mode & PM_SOURCE_PHOT_WEIGHT) { 186 pmSourcePixelWeight (source, model , source->maskObj, maskVal, radius);185 pmSourcePixelWeight (source, modelPSF, source->maskObj, maskVal, radius); 187 186 } 188 187 … … 218 217 y += dy; 219 218 220 if (!psImageShiftMask(&flux, &mask, source->pixels, source->maskObj, maskVal, dx, dy, 221 NAN, 0xff, PS_INTERPOLATE_BIQUADRATIC)) { 219 // if (!psImageShiftMask(&flux, &mask, source->pixels, source->maskObj, maskVal, dx, dy, NAN, 0xff, PS_INTERPOLATE_LANCZOS2)) { 220 // if (!psImageShiftMask(&flux, &mask, source->pixels, source->maskObj, maskVal, dx, dy, NAN, 0xff, PS_INTERPOLATE_BIQUADRATIC)) { 221 if (!psImageShiftMask(&flux, &mask, source->pixels, source->maskObj, maskVal, dx, dy, NAN, 0xff, PS_INTERPOLATE_BILINEAR)) { 222 222 // Not much we can do about it 223 223 psErrorClear(); … … 233 233 234 234 // measure object aperture photometry 235 status = pmSourcePhotometryAperSource (source, model , flux, variance, mask, maskVal);235 status = pmSourcePhotometryAperSource (source, modelPSF, flux, variance, mask, maskVal); 236 236 if (!status) { 237 237 psTrace ("psModules.objects", 3, "fail mag : bad Ap Mag"); … … 242 242 // detection limits (esp near bright neighbors) 243 243 source->apMag = source->apMagRaw; 244 if (isfinite (source->apMag) && isPSF &&psf) {244 if (isfinite (source->apMag) && psf) { 245 245 if (psf->growth && (mode & PM_SOURCE_PHOT_GROWTH)) { 246 source->apMag = source->apMagRaw + pmGrowthCurveCorrect (psf->growth, source->apRadius); 247 // XXX correct the apFlux? 246 float apOffset = pmGrowthCurveCorrect (psf->growth, source->apRadius); 247 source->apMag = source->apMagRaw + apOffset; 248 source->apFlux *= pow(10.0, -0.4*apOffset); 249 source->apFluxErr *= pow(10.0, -0.4*apOffset); 248 250 } 249 251 } -
branches/eam_branches/ipp-20110404/psModules/src/objects/pmSourceUtils.h
r14652 r31361 38 38 39 39 /// @} 40 # endif /* PM_ MODEL_CLASS_H */40 # endif /* PM_SOURCE_UTILS_H */ -
branches/eam_branches/ipp-20110404/psModules/src/psmodules.h
r30623 r31361 148 148 #include <pmModelUtils.h> 149 149 #include <pmSourcePhotometry.h> 150 #include <pmGrowthCurveGenerate.h> 150 151 #include <pmSourceVisual.h> 151 152 #include <pmSourceMatch.h>
Note:
See TracChangeset
for help on using the changeset viewer.
