Changeset 36340
- Timestamp:
- Dec 4, 2013, 1:57:28 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20130904/psphot/src/psphotSourceSize.c
r35180 r36340 1 1 # include "psphotInternal.h" 2 # include <gsl/gsl_sf_gamma.h> 3 2 3 // this structure is only used internally to simplify the function parameters 4 4 typedef struct { 5 5 psImageMaskType maskVal; … … 13 13 bool altDiffExt; 14 14 float altDiffExtThresh; 15 bool extFitAll;16 bool extFitAllReadout;17 float extFitAllThresh;18 15 float soft; 19 16 int grow; … … 33 30 bool psphotSourceSelectCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options); 34 31 bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal, int maxWindowCR); 35 bool psphotMaskCosmicRayFootprintCheck (psArray *sources);36 32 int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh); 37 33 float psphotSourceSizeFindThreshold (psVector *value, psVector *mask, int maskValue, float minValue, float maxValue, float delta, float guess, float fraction); … … 41 37 42 38 // we need to call this function after sources have been fitted to the PSF model and 43 // subtracted. To determine the CR-nature, this function examines the 9 pixels in the 3x3 44 // square containing the peak and compares the observed flux to the model. To determine 45 // the EXT-nature, this function measures the amount of positive or negative total 46 // deviation from the psf model at the r = FWHM/2 position 39 // subtracted. 47 40 48 41 // for now, let's store the detections on the readout->analysis for each readout … … 121 114 assert (status); 122 115 123 // XXX recipe name is not great 116 // XXX recipe name is not great (NOTE : not used!) 124 117 options.nSigmaMoments = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.MOMENTS"); 125 118 assert (status); 126 119 127 // Optional extended source measurement algorithm to improve diff image trails120 // Optional algorithm to define if a source is extended (used by DIFF analysis) 128 121 options.altDiffExt = psMetadataLookupBool(&status, recipe, "PSPHOT.EXT.DIFF.ALTERNATE"); 129 122 assert (status); 123 130 124 // Threshold for this alternate method 131 125 options.altDiffExtThresh = psMetadataLookupF32(&status, recipe, "PSPHOT.EXT.DIFF.ALTERNATE.THRESH"); 132 126 assert (status); 133 // Option to enable fitting of all objects with extended model. 134 options.extFitAll = psMetadataLookupBool(&status, recipe, "PSPHOT.EXT.FIT.ALL.SOURCES"); 135 assert (status); 136 // Fitting everything is fine, but if the source density is high, we probably shouldn't. 137 options.extFitAllThresh = psMetadataLookupF32(&status, recipe, "PSPHOT.EXT.FIT.ALL.THRESH"); 138 assert (status); 139 127 140 128 // location of a single test source 141 129 options.xtest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.XTEST"); … … 422 410 423 411 psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4s %4s %4s %4s %4s", "Npsf", "Next", "Nsat", "Ncr", "Nskip"); 424 // Determine if this readout is above the threshold to ext fit all sources 425 options->extFitAllReadout = false; 426 if (options->extFitAll) { 427 float maskFrac = psMetadataLookupF32(&status,readout->analysis,"READOUT.MASK.FRAC"); 428 if (status) { 429 maskFrac = 0.0; 430 } 431 if (sources->n * (1.0 - maskFrac) > options->extFitAllThresh) { 432 options->extFitAllReadout = false; 433 } 434 else { 435 options->extFitAllReadout = true; 436 } 437 } 438 412 439 413 if (!psphotSourceClassRegion (NULL, &psfClump, sources, recipe, psf, options)) { 440 414 psLogMsg ("psphot", 4, "Failed to determine source classification for full image\n"); … … 444 418 return true; 445 419 420 // NOTE : this section is deactivated (EAM : I think we were getting poor boundary effects?) 446 421 int nRegions = psMetadataLookupS32 (&status, readout->analysis, "PSF.CLUMP.NREGIONS"); 447 422 for (int i = 0; i < nRegions; i ++) { … … 582 557 // * SAT stars should not be faint, but defects may? 583 558 584 // If the recipe requests we do extended source fits to everything, set585 // the EXT_LIMIT flag586 if (options->extFitAllReadout) {587 psTrace("psphotSourceClassRegion.EXTALT",10,"In extFitAll: %d %d\n",options->extFitAll,options->extFitAllReadout);588 source->mode |= PM_SOURCE_MODE_EXT_LIMIT;589 }590 559 // Defects may not always match CRs from peak curvature analysis 591 560 // Defects may also be marked as SATSTAR -- XXX deactivate this flag? … … 595 564 596 565 // saturated star (too many saturated pixels or peak above saturation limit). These 597 // may also be saturated galaxies, or just large saturated regions. 566 // may also be saturated galaxies, or just large saturated regions. They are never 567 // marked as 'extended' 598 568 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 599 569 psTrace("psphotSourceClassRegion.SAT",4,"CLASS: %g %g\t%g %g\t%g %g\t%g %g\t%g SAT\n", … … 604 574 } 605 575 606 // any sources missing a large fraction should just be treated as PSFs 576 // any sources missing a large fraction should just be treated as PSFs. They are never 577 // marked as 'extended' 607 578 if ((source->pixWeightNotBad < 0.9) || (source->pixWeightNotPoor < 0.9)) { 608 579 psTrace("psphotSourceClassRegion.PSF",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g PSF\t%g %g\n", … … 639 610 continue; 640 611 } 612 641 613 // Alternate extended source limit calculation 642 614 if (options->altDiffExt) { … … 968 940 } 969 941 970 bool psphotMaskCosmicRayFootprintCheck (psArray *sources) {971 #ifdef CHECK_FOOTPRINTS972 // This gets really expensive for complex images973 for (int i = 0; i < sources->n; i++) {974 pmSource *source = sources->data[i];975 pmPeak *peak = source->peak;976 pmFootprint *footprint = peak->footprint;977 if (!footprint) continue;978 for (int j = 0; j < footprint->spans->n; j++) {979 pmSpan *sp = footprint->spans->data[j];980 psAssert (sp, "missing span");981 }982 }983 #endif984 return true;985 }986 987 /**** ------ old versions of cosmic ray masking ----- ****/988 989 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);990 991 // This attempt to mask the cosmic rays used the isophotal boundary992 bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {993 994 // replace the source flux995 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);996 997 // flag this as a CR998 source->mode |= PM_SOURCE_MODE_CR_LIMIT;999 pmPeak *peak = source->peak;1000 psAssert (peak, "NULL peak");1001 1002 // grab the matching footprint1003 pmFootprint *footprint = peak->footprint;1004 if (!footprint) {1005 psTrace("psphot.czw",2,"Using isophot CR mask code.");1006 1007 // if we have not footprint, use the old code to mask by isophot1008 psphotMaskCosmicRayIsophot (source, maskVal, crMask);1009 return true;1010 }1011 1012 if (!footprint->spans) {1013 psTrace("psphot.czw",2,"Using isophot CR mask code.");1014 1015 // if we have no footprint, use the old code to mask by isophot1016 psphotMaskCosmicRayIsophot (source, maskVal, crMask);1017 return true;1018 }1019 psphotMaskCosmicRayIsophot (source, maskVal, crMask);1020 // mask all of the pixels covered by the spans of the footprint1021 for (int j = 1; j < footprint->spans->n; j++) {1022 pmSpan *span1 = footprint->spans->data[j];1023 1024 int iy = span1->y;1025 int xs = span1->x0;1026 int xe = span1->x1;1027 1028 for (int ix = xs; ix < xe; ix++) {1029 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;1030 }1031 }1032 return true;1033 }1034 1035 942 # define VERBOSE 0 1036 943 int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh) { … … 1176 1083 } 1177 1084 1178 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {1179 1180 source->mode |= PM_SOURCE_MODE_CR_LIMIT;1181 pmPeak *peak = source->peak;1182 psAssert (peak, "NULL peak");1183 1184 psImage *mask = source->maskView;1185 psImage *pixels = source->pixels;1186 psImage *variance = source->variance;1187 1188 // XXX This should be a recipe variable1189 # define SN_LIMIT 5.01190 1191 int xo = peak->x - pixels->col0;1192 int yo = peak->y - pixels->row0;1193 1194 // mark the pixels in this row to the left, then the right1195 for (int ix = xo; ix >= 0; ix--) {1196 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);1197 if (SN > SN_LIMIT) {1198 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;1199 }1200 }1201 for (int ix = xo + 1; ix < pixels->numCols; ix++) {1202 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);1203 if (SN > SN_LIMIT) {1204 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;1205 }1206 }1207 1208 // for each of the neighboring rows, mark the high pixels if they have a marked neighbor1209 // first go up:1210 for (int iy = PS_MIN(yo, mask->numRows-2); iy >= 0; iy--) {1211 // mark the pixels in this row to the left, then the right1212 for (int ix = 0; ix < pixels->numCols; ix++) {1213 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);1214 if (SN < SN_LIMIT) continue;1215 1216 bool valid = false;1217 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix] & crMask);1218 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix-1] & crMask) : 0;1219 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix+1] & crMask) : 0;1220 1221 if (!valid) continue;1222 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;1223 }1224 }1225 // next go down:1226 for (int iy = PS_MIN(yo+1, mask->numRows-1); iy < pixels->numRows; iy++) {1227 // mark the pixels in this row to the left, then the right1228 for (int ix = 0; ix < pixels->numCols; ix++) {1229 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);1230 if (SN < SN_LIMIT) continue;1231 1232 bool valid = false;1233 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix] & crMask);1234 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix-1] & crMask) : 0;1235 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix+1] & crMask) : 0;1236 1237 if (!valid) continue;1238 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;1239 }1240 }1241 return true;1242 }1243 1244 // given the PSF ellipse parameters, navigate around the 1sigma contour, return the total1245 // deviation in sigmas. This is measured on the residual image - should we ignore negative1246 // deviations? NOTE: This function was an early attempt to classify extended objects, and is1247 // no longer used by psphot.1248 float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask,1249 psImageMaskType maskVal, const pmModel *model, float Ro)1250 {1251 psF32 *PAR = model->params->data.F32; // Model parameters1252 float sxx = PAR[PM_PAR_SXX], sxy = PAR[PM_PAR_SXY], syy = PAR[PM_PAR_SYY]; // Ellipse parameters1253 1254 // We treat the contour as an ellipse:1255 // Ro = (x / SXX)^2 + (y / SYY)^2 + x y SXY1256 // y^2 (1/SYY^2) + y (x SXY) + (x / SXX)^2 - Ro = 0;1257 // This is a quadratic, Ay^2 + By + C with A = 1/SYY^2, B = x*SXY, C = (x / SXX)^2 - Ro1258 // The solution is y = [-B +/- sqrt (B^2 - 4 A C)] / [2 A], so:1259 // y = [-(x SXY) +/- sqrt ((x SXY)^2 - 4 (1/SYY^2) ((x/SXX)^2 - Ro))] * [SYY^2 / 2]1260 1261 // min/max value of x is where B^2 - 4AC = 0; solve this for x1262 float Q = Ro * PS_SQR(sxx) / (1.0 - PS_SQR(sxx * syy * sxy) / 4.0);1263 if (Q < 0.0) {1264 // ellipse is imaginary1265 return NAN;1266 }1267 1268 int radius = sqrtf(Q) + 0.5; // Radius of ellipse1269 int nPts = 0; // Number of points in ellipse1270 float nSigma = 0.0; //1271 1272 for (int x = -radius; x <= radius; x++) {1273 // Polynomial coefficients1274 // XXX Should we be using the centre of the pixel as x or x+0.5?1275 float A = PS_SQR (1.0 / syy);1276 float B = x * sxy;1277 float C = PS_SQR (x / sxx) - Ro;1278 float T = PS_SQR(B) - 4*A*C;1279 if (T < 0.0) {1280 continue;1281 }1282 1283 // y position in source frame1284 float yP = (-B + sqrt (T)) / (2.0 * A);1285 float yM = (-B - sqrt (T)) / (2.0 * A);1286 1287 // Get the closest pixel positions (image frame)1288 int xPix = x + PAR[PM_PAR_XPOS] - image->col0 + 0.5;1289 int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5;1290 int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5;1291 1292 if (xPix < 0 || xPix >= image->numCols) {1293 continue;1294 }1295 1296 if (yPixM >= 0 && yPixM < image->numRows &&1297 !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixM][xPix] & maskVal))) {1298 float dSigma = image->data.F32[yPixM][xPix] / sqrtf(variance->data.F32[yPixM][xPix]);1299 nSigma += dSigma;1300 nPts++;1301 }1302 1303 if (yPixM == yPixP) {1304 continue;1305 }1306 1307 if (yPixP >= 0 && yPixP < image->numRows &&1308 !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixP][xPix] & maskVal))) {1309 float dSigma = image->data.F32[yPixP][xPix] / sqrtf(variance->data.F32[yPixP][xPix]);1310 nSigma += dSigma;1311 nPts++;1312 }1313 }1314 nSigma /= nPts;1315 return nSigma;1316 }1317 1318 // this was an old attempt to identify cosmic rays based on the peak curvature1319 bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {1320 1321 // classify the sources based on the CR test (place this in a function?)1322 // XXX use an internal flag to mark sources which have already been measured1323 for (int i = 0; i < sources->n; i++) {1324 pmSource *source = sources->data[i];1325 1326 // skip source if it was already measured1327 if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) {1328 psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");1329 continue;1330 }1331 1332 // source must have been subtracted1333 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) {1334 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED;1335 psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n");1336 continue;1337 }1338 1339 psF32 **resid = source->pixels->data.F32;1340 psF32 **variance = source->variance->data.F32;1341 psImageMaskType **mask = source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;1342 1343 // Integer position of peak1344 int xPeak = source->peak->xf - source->pixels->col0 + 0.5;1345 int yPeak = source->peak->yf - source->pixels->row0 + 0.5;1346 1347 // Skip sources which are too close to a boundary. These are mostly caught as DEFECT1348 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 ||1349 yPeak < 1 || yPeak > source->pixels->numRows - 2) {1350 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n");1351 continue;1352 }1353 1354 // Skip sources with masked pixels. These are mostly caught as DEFECT1355 bool keep = true;1356 for (int iy = -1; (iy <= +1) && keep; iy++) {1357 for (int ix = -1; (ix <= +1) && keep; ix++) {1358 if (mask[yPeak+iy][xPeak+ix] & options->maskVal) {1359 keep = false;1360 }1361 }1362 }1363 if (!keep) {1364 psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n");1365 continue;1366 }1367 1368 // Compare the central pixel with those on either side, for the four possible lines through it.1369 1370 // Soften variances (add systematic error)1371 float softening = options->soft * PS_SQR(source->peak->rawFlux); // Softening for variances1372 1373 // Across the middle: y = 01374 float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1];1375 float dcX = 4*variance[yPeak][xPeak] + variance[yPeak+0][xPeak-1] + variance[yPeak+0][xPeak+1];1376 float nX = cX / sqrtf(dcX + softening);1377 1378 // Up the centre: x = 01379 float cY = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak+0] - resid[yPeak+1][xPeak+0];1380 float dcY = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak+0] + variance[yPeak+1][xPeak+0];1381 float nY = cY / sqrtf(dcY + softening);1382 1383 // Diagonal: x = y1384 float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1];1385 float dcL = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak-1] + variance[yPeak+1][xPeak+1];1386 float nL = cL / sqrtf(dcL + softening);1387 1388 // Diagonal: x = - y1389 float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1];1390 float dcR = 4*variance[yPeak][xPeak] + variance[yPeak+1][xPeak-1] + variance[yPeak-1][xPeak+1];1391 float nR = cR / sqrtf(dcR + softening);1392 1393 // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2)1394 // Ndof = 4 ? (four measurements, no free parameters)1395 // XXX this value is going to be biased low because of systematic errors.1396 // we need to calibrate it somehow1397 // source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq);1398 1399 // not strictly accurate: overcounts the chisq contribution from the center pixel (by1400 // factor of 4); also biases a bit low if any pixels are masked1401 // XXX I am not sure I want to keep this value...1402 source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nL) + PS_SQR(nR);1403 1404 float fCR = 0.0;1405 int nCR = 0;1406 if (nX > 0.0) {1407 fCR += nX;1408 nCR ++;1409 }1410 if (nY > 0.0) {1411 fCR += nY;1412 nCR ++;1413 }1414 if (nL > 0.0) {1415 fCR += nL;1416 nCR ++;1417 }1418 if (nR > 0.0) {1419 fCR += nR;1420 nCR ++;1421 }1422 source->crNsigma = (nCR > 0) ? fCR / nCR : 0.0;1423 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;1424 1425 if (!isfinite(source->crNsigma)) {1426 continue;1427 }1428 1429 // this source is thought to be a cosmic ray. flag the detection and mask the pixels1430 if (source->crNsigma > options->nSigmaCR) {1431 source->mode |= PM_SOURCE_MODE_CR_LIMIT;1432 // XXX still testing... : psphotMaskCosmicRay (readout->mask, source, maskVal, crMask);1433 // XXX acting strange... psphotMaskCosmicRay_Old (source, maskVal, crMask);1434 }1435 }1436 1437 // now that we have masked pixels associated with CRs, we can grow the mask1438 if (options->grow > 0) {1439 bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask1440 psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow);1441 psImageConvolveSetThreads(oldThreads);1442 if (!newMask) {1443 psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask");1444 return false;1445 }1446 psFree(readout->mask);1447 readout->mask = newMask;1448 }1449 return true;1450 }1451 1452 1085 float psphotSourceSizeFindThreshold (psVector *value, psVector *mask, int maskValue, float minValue, float maxValue, float delta, float guess, float fraction) { 1453 1086
Note:
See TracChangeset
for help on using the changeset viewer.
