Changeset 20144
- Timestamp:
- Oct 14, 2008, 10:14:51 AM (18 years ago)
- File:
-
- 1 edited
-
trunk/psphot/src/psphotSourceSize.c (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/psphotSourceSize.c
r19915 r20144 2 2 # include <gsl/gsl_sf_gamma.h> 3 3 4 float psphotModelContour (psImage *image, psImage *weight, psImage *mask, psMaskType maskVal, pmModel *model, float Ro); 4 static float psphotModelContour(const psImage *image, const psImage *weight, const psImage *mask, 5 psMaskType maskVal, const pmModel *model, float Ro); 5 6 6 7 // we need to call this function after sources have been fitted to the PSF model and … … 10 11 // deviation from the psf model at the r = FWHM/2 position 11 12 12 bool psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first)13 bool psphotSourceSize(pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first) 13 14 { 14 15 15 bool status; 16 16 … … 41 41 42 42 // skip source if it was already measured 43 if (isfinite(source->crNsigma)) continue; 43 if (isfinite(source->crNsigma)) { 44 psTrace("psphot", 7, "Not calculating extNsigma,crNsigma since already measured\n"); 45 continue; 46 } 44 47 45 48 // source must have been subtracted 46 if (!(source->mode & PM_SOURCE_MODE_SUBTRACTED)) continue; 49 if (!(source->mode & PM_SOURCE_MODE_SUBTRACTED)) { 50 psTrace("psphot", 7, "Not calculating extNsigma,crNsigma since source is not subtracted\n"); 51 continue; 52 } 47 53 48 54 psF32 **resid = source->pixels->data.F32; … … 51 57 52 58 // check for extendedness: measure the delta flux significance at the 1 sigma contour 53 source->extNsigma = psphotModelContour (source->pixels, source->weight, source->maskObj, maskVal, source->modelPSF, 1.0); 59 source->extNsigma = psphotModelContour(source->pixels, source->weight, source->maskObj, maskVal, 60 source->modelPSF, 1.0); 54 61 55 62 // XXX prevent a source from being both CR and EXT? 56 63 if (source->extNsigma > EXT_NSIGMA_LIMIT) { 57 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 58 } 59 64 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 65 } 66 67 // Integer position of peak 60 68 int xPeak = source->peak->xf - source->pixels->col0 + 0.5; 61 69 int yPeak = source->peak->yf - source->pixels->row0 + 0.5; … … 63 71 // XXX for now, skip sources which are too close to a boundary 64 72 // XXX raise a flag? 65 if (xPeak < 1) continue; 66 if (xPeak > source->pixels->numCols - 2) continue; 67 if (yPeak < 1) continue; 68 if (yPeak > source->pixels->numRows - 2) continue; 73 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 || 74 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 75 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 76 continue; 77 } 69 78 70 79 // XXX for now, just skip any sources with masked pixels … … 73 82 for (int iy = -1; (iy <= +1) && keep; iy++) { 74 83 for (int ix = -1; (ix <= +1) && keep; ix++) { 75 if (mask[yPeak+iy][xPeak+ix]) { keep &= false; } 76 } 77 } 78 if (!keep) continue; 79 80 if (mask[yPeak][xPeak] & maskVal) continue; 81 82 // XXX need to deal with edge peaks... and mask 83 float nX = 0; 84 float nY = 0; 85 float nL = 0; 86 float nR = 0; 87 88 if (!(mask[yPeak+0][xPeak-1] & maskVal) && !(mask[yPeak+0][xPeak+1] & maskVal)) { 89 float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1]; 90 float dcX = 4*weight[yPeak][xPeak] + weight[yPeak+0][xPeak-1] + weight[yPeak+0][xPeak+1]; 91 nX = cX / sqrt(dcX); 92 } 93 94 if (!(mask[yPeak-1][xPeak+0] & maskVal) && !(mask[yPeak+1][xPeak+0] & maskVal)) { 95 float cY = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak+0] - resid[yPeak+1][xPeak+0]; 96 float dcY = 4*weight[yPeak][xPeak] + weight[yPeak-1][xPeak+0] + weight[yPeak+1][xPeak+0]; 97 nY = cY / sqrt(dcY); 98 } 99 100 if (!(mask[yPeak-1][xPeak-1] & maskVal) && !(mask[yPeak+1][xPeak+1] & maskVal)) { 101 float dcL = 4*weight[yPeak][xPeak] + weight[yPeak-1][xPeak-1] + weight[yPeak+1][xPeak+1]; 102 float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1]; 103 nL = cL / sqrt(dcL); 104 } 105 106 if (!(mask[yPeak+1][xPeak-1] & maskVal) && !(mask[yPeak-1][xPeak+1] & maskVal)) { 107 float dcR = 4*weight[yPeak][xPeak] + weight[yPeak+1][xPeak-1] + weight[yPeak-1][xPeak+1]; 108 float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1]; 109 nR = cR / sqrt(dcR); 110 } 84 if (mask[yPeak+iy][xPeak+ix] & maskVal) { 85 keep = false; 86 } 87 } 88 } 89 if (!keep) { 90 psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n"); 91 continue; 92 } 93 94 // Compare the central pixel with those on either side, for the four possible lines through it. 95 96 // Across the middle: y = 0 97 float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1]; 98 float dcX = 4*weight[yPeak][xPeak] + weight[yPeak+0][xPeak-1] + weight[yPeak+0][xPeak+1]; 99 float nX = cX / sqrtf(dcX); 100 101 // Up the centre: x = 0 102 float cY = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak+0] - resid[yPeak+1][xPeak+0]; 103 float dcY = 4*weight[yPeak][xPeak] + weight[yPeak-1][xPeak+0] + weight[yPeak+1][xPeak+0]; 104 float nY = cY / sqrtf(dcY); 105 106 // Diagonal: x = y 107 float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1]; 108 float dcL = 4*weight[yPeak][xPeak] + weight[yPeak-1][xPeak-1] + weight[yPeak+1][xPeak+1]; 109 float nL = cL / sqrtf(dcL); 110 111 // Diagonal: x = - y 112 float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1]; 113 float dcR = 4*weight[yPeak][xPeak] + weight[yPeak+1][xPeak-1] + weight[yPeak-1][xPeak+1]; 114 float nR = cR / sqrtf(dcR); 111 115 112 116 // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2) … … 118 122 // not strictly accurate: overcounts the chisq contribution from the center pixel (by 119 123 // factor of 4); also biases a bit low if any pixels are masked 120 // XXX I am not sure I want to keep this value...121 source->psfChisq = PS_SQR (nX) + PS_SQR (nY) + PS_SQR (nX) + PS_SQR(nR);124 // XXX I am not sure I want to keep this value... 125 source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nX) + PS_SQR(nR); 122 126 123 127 float fCR = 0.0; … … 156 160 psImage *weight = source->weight; 157 161 162 // XXX This should be a recipe variable 158 163 # define SN_LIMIT 5.0 159 164 … … 232 237 233 238 // given the PSF ellipse parameters, navigate around the 1sigma contour, return the total 234 // deviation in sigmas. This is measure on the residual image - should we ignore negative239 // deviation in sigmas. This is measured on the residual image - should we ignore negative 235 240 // deviations? 236 float psphotModelContour (psImage *image, psImage *weight, psImage *mask, psMaskType maskVal, pmModel *model, float Ro) { 237 238 psF32 *PAR = model->params->data.F32; 239 240 // Ro = (x / SXX)^2 + (y / SYY)^2 + x y SXY; 241 static float psphotModelContour(const psImage *image, const psImage *weight, const psImage *mask, 242 psMaskType maskVal, const pmModel *model, float Ro) 243 { 244 psF32 *PAR = model->params->data.F32; // Model parameters 245 float sxx = PAR[PM_PAR_SXX], sxy = PAR[PM_PAR_SXY], syy = PAR[PM_PAR_SYY]; // Ellipse parameters 246 247 // We treat the contour as an ellipse: 248 // Ro = (x / SXX)^2 + (y / SYY)^2 + x y SXY 241 249 // y^2 (1/SYY^2) + y (x SXY) + (x / SXX)^2 - Ro = 0; 242 // y = [-(x SXY) +/- sqrt ((x SXY)^2 - 4 (1/SYY^2) ((x/SXX)^2 - Ro))] * [SYY^2 / 2]; 243 // y = [-B +/- sqrt (B^2 - 4 A C)] / [2 A]; 244 245 // min/max value of x is where T -> 0 246 // solve this for x2: 247 float Q = Ro * PS_SQR(PAR[PM_PAR_SXX]) / (1.0 - PS_SQR(PAR[PM_PAR_SXX]*PAR[PM_PAR_SYY]*PAR[PM_PAR_SXY]) / 4.0); 248 if (Q < 0.0) return NAN; // ellipse is imaginary 249 250 int xMax = sqrt(Q); 251 int xMin = -1.0*xMax; 252 253 int nPts = 0; 254 float nSigma = 0.0; 255 256 for (int x = xMin; x <= xMax; x++) { 257 float A = PS_SQR (1.0 / PAR[PM_PAR_SYY]); 258 float B = x * PAR[PM_PAR_SXY]; 259 float C = PS_SQR (x / PAR[PM_PAR_SXX]) - Ro; 260 250 // This is a quadratic, Ay^2 + By + C with A = 1/SYY^2, B = x*SXY, C = (x / SXX)^2 - Ro 251 // The solution is y = [-B +/- sqrt (B^2 - 4 A C)] / [2 A], so: 252 // y = [-(x SXY) +/- sqrt ((x SXY)^2 - 4 (1/SYY^2) ((x/SXX)^2 - Ro))] * [SYY^2 / 2] 253 254 // min/max value of x is where B^2 - 4AC = 0; solve this for x 255 float Q = Ro * PS_SQR(sxx) / (1.0 - PS_SQR(sxx * syy * sxy) / 4.0); 256 if (Q < 0.0) { 257 // ellipse is imaginary 258 return NAN; 259 } 260 261 int radius = sqrtf(Q) + 0.5; // Radius of ellipse 262 int nPts = 0; // Number of points in ellipse 263 float nSigma = 0.0; // 264 265 for (int x = -radius; x <= radius; x++) { 266 // Polynomial coefficients 267 float A = PS_SQR (1.0 / syy); 268 float B = x * sxy; 269 float C = PS_SQR (x / sxx) - Ro; 261 270 float T = PS_SQR(B) - 4*A*C; 262 if (T < 0.0) continue; 263 271 if (T < 0.0) { 272 continue; 273 } 274 275 // y position in source frame 264 276 float yP = (-B + sqrt (T)) / (2.0 * A); 265 277 float yM = (-B - sqrt (T)) / (2.0 * A); 266 278 279 // Get the closest pixel positions (image frame) 267 280 int xPix = x + PAR[PM_PAR_XPOS] - image->col0 + 0.5; 268 281 int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5; 269 282 int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5; 270 283 271 if (xPix < 0) continue; 272 if (xPix >= image->numCols) continue; 273 274 if ((yPixM >= 0) && (yPixM < image->numRows)) { 275 if (!mask || !(mask->data.U8[yPixM][xPix] & maskVal)) { 276 float dSigma = image->data.F32[yPixM][xPix] / sqrt (weight->data.F32[yPixM][xPix]); 277 nSigma += dSigma; 278 nPts ++; 279 } 280 } 281 282 if (yPixM == yPixP) continue; 283 284 if ((yPixP >= 0) && (yPixP < image->numRows)) { 285 if (!mask || !(mask->data.U8[yPixP][xPix] & maskVal)) { 286 float dSigma = image->data.F32[yPixP][xPix] / sqrt (weight->data.F32[yPixP][xPix]); 287 nSigma += dSigma; 288 nPts ++; 289 } 284 if (xPix < 0 || xPix >= image->numCols) { 285 continue; 286 } 287 288 if (yPixM >= 0 && yPixM < image->numRows && 289 !(mask && (mask->data.PS_TYPE_MASK_DATA[yPixM][xPix] & maskVal))) { 290 float dSigma = image->data.F32[yPixM][xPix] / sqrtf(weight->data.F32[yPixM][xPix]); 291 nSigma += dSigma; 292 nPts++; 293 } 294 295 if (yPixM == yPixP) { 296 continue; 297 } 298 299 if (yPixP >= 0 && yPixP < image->numRows && 300 !(mask && (mask->data.PS_TYPE_MASK_DATA[yPixP][xPix] & maskVal))) { 301 float dSigma = image->data.F32[yPixP][xPix] / sqrtf(weight->data.F32[yPixP][xPix]); 302 nSigma += dSigma; 303 nPts++; 290 304 } 291 305 }
Note:
See TracChangeset
for help on using the changeset viewer.
