Changeset 27532 for trunk/psphot/src
- Timestamp:
- Mar 30, 2010, 1:33:47 PM (16 years ago)
- Location:
- trunk/psphot/src
- Files:
-
- 10 edited
- 2 copied
-
psphot.h (modified) (2 diffs)
-
psphotEfficiency.c (modified) (14 diffs)
-
psphotFitSourcesLinear.c (modified) (5 diffs)
-
psphotFitSourcesLinearStack.c (modified) (2 diffs)
-
psphotKernelFromPSF.c (modified) (2 diffs)
-
psphotMagnitudes.c (modified) (3 diffs)
-
psphotMakeResiduals.c (modified) (1 diff)
-
psphotReadout.c (modified) (1 diff)
-
psphotSourceMerge.c (copied) (copied from branches/eam_branches/20100225/psphot/src/psphotSourceMerge.c )
-
psphotSourceSize.c (modified) (21 diffs)
-
psphotStackChisqImage.c (copied) (copied from branches/eam_branches/20100225/psphot/src/psphotStackChisqImage.c )
-
psphotVisual.c (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/psphot.h
r26894 r27532 92 92 93 93 bool psphotFitSourcesLinear (pmConfig *config, const pmFPAview *view, bool final); 94 bool psphotFitSourcesLinearReadout (p mConfig *config, const pmFPAview *view, const char *filename, int index, bool final);94 bool psphotFitSourcesLinearReadout (psMetadata *recipe, pmReadout *readout, psArray *sources, pmPSF *psf, bool final); 95 95 96 96 bool psphotSourceSize (pmConfig *config, const pmFPAview *view, bool getPSFsize); … … 119 119 120 120 bool psphotMagnitudes (pmConfig *config, const pmFPAview *view); 121 bool psphotMagnitudesReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);121 bool psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf); 122 122 bool psphotMagnitudes_Threaded (psThreadJob *job); 123 123 -
trunk/psphot/src/psphotEfficiency.c
r26894 r27532 4 4 PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_LIMITS) // Mask to apply to models 5 5 6 //#define TESTING 7 8 9 # if 0 6 # define TESTING 0 10 7 11 8 // Calculate the limiting magnitude for an image … … 19 16 float *covarFactor,// Covariance factor 20 17 const pmReadout *ro, // Readout of interest 21 const pmPSF *psf,// Point-spread function18 pmPSF *psf, // Point-spread function 22 19 float thresh, // Threshold for source identification 23 20 float smoothSigma, // Gaussian smoothing sigma … … 152 149 } 153 150 154 # endif155 156 151 bool psphotEfficiency (pmConfig *config, const pmFPAview *view) 157 152 { … … 178 173 bool psphotEfficiencyReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) 179 174 { 180 # if 0181 175 bool status = true; 182 176 … … 206 200 207 201 // Collect recipe information 208 float fwhmMajor = psMetadataLookupF32(NULL, recipe, "FWHM_MAJ"); // PSF size in x 209 float fwhmMinor = psMetadataLookupF32(NULL, recipe, "FWHM_MIN"); // PSF size in y 202 float smoothNsigma = psMetadataLookupF32(&status, recipe, "PEAKS_SMOOTH_NSIGMA"); // Smoothing limit 203 psAssert (status && isfinite(smoothNsigma), "Unable to find PEAKS_SMOOTH_NSIGMA in recipe (or invalid value)"); 204 205 float thresh = psMetadataLookupF32(&status, recipe, "PEAKS_NSIGMA_LIMIT_2"); 206 psAssert (status && isfinite(thresh), "Unable to find PEAKS_NSIGMA_LIMIT_2 in recipe (or invalid value)"); 207 208 psVector *magOffsets = psMetadataLookupVector(&status, recipe, "EFF.MAG"); // Magnitude offsets 209 psAssert (status, "Unable to find EFF.MAG F32 vector in recipe"); 210 psAssert (magOffsets->type.type == PS_TYPE_F32, "Unable to find EFF.MAG F32 vector in recipe"); 211 212 int numSources = psMetadataLookupS32(&status, recipe, "EFF.NUM"); // Number of sources for each bin 213 psAssert (status && (numSources > 0), "Unable to find EFF.NUM in recipe (or invalid value)"); 214 215 float minGauss = psMetadataLookupF32(&status, recipe, "PEAKS_MIN_GAUSS"); // Minimum valid fraction of kernel 216 psAssert (status && isfinite(minGauss), "PEAKS_MIN_GAUSS is not set in recipe (or invalid)"); 217 218 // find the PSF size information (why is this not part of the psf structure?) 219 float fwhmMajor = psMetadataLookupF32(NULL, readout->analysis, "FWHM_MAJ"); // PSF size in x 220 float fwhmMinor = psMetadataLookupF32(NULL, readout->analysis, "FWHM_MIN"); // PSF size in y 210 221 if (!isfinite(fwhmMajor) || !isfinite(fwhmMinor) || fwhmMajor == 0.0 || fwhmMinor == 0.0) { 211 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FWHM_MAJ and FWHM_MIN in recipe"); 212 return false; 213 } 214 float smoothNsigma = psMetadataLookupF32(NULL, recipe, "PEAKS_SMOOTH_NSIGMA"); // Smoothing limit 215 if (!isfinite(smoothNsigma)) { 216 psError(PSPHOT_ERR_CONFIG, false, "Unable to find PEAKS_SMOOTH_NSIGMA in recipe"); 217 return false; 218 } 219 float thresh = psMetadataLookupF32(NULL, recipe, "PEAKS_NSIGMA_LIMIT_2"); 220 if (!isfinite(thresh)) { 221 psError(PSPHOT_ERR_CONFIG, false, "Unable to find PEAKS_NSIGMA_LIMIT_2 in recipe"); 222 return false; 223 } 224 psVector *magOffsets = psMetadataLookupVector(NULL, recipe, "EFF.MAG"); // Magnitude offsets 225 if (!magOffsets || magOffsets->type.type != PS_TYPE_F32) { 226 psError(PSPHOT_ERR_CONFIG, false, "Unable to find EFF.MAG F32 vector in recipe"); 227 return NULL; 228 } 229 int numSources = psMetadataLookupS32(NULL, recipe, "EFF.NUM"); // Number of sources for each bin 230 if (numSources == 0) { 231 psError(PSPHOT_ERR_CONFIG, false, "Unable to find EFF.NUM in recipe"); 232 return NULL; 233 } 234 float minGauss = psMetadataLookupF32(NULL, recipe, "PEAKS_MIN_GAUSS"); // Minimum valid fraction of kernel 235 if (!isfinite(minGauss)) { 236 psWarning("PEAKS_MIN_GAUSS is not set in recipe; using default value"); 237 minGauss = 0.5; 222 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FWHM_MAJ and FWHM_MIN in readout->analysis"); 223 return false; 238 224 } 239 225 … … 246 232 // remove all sources, adding noise for subtracted sources 247 233 psphotRemoveAllSources(realSources, recipe); 248 // psphotAddNoise(readout, realSources, recipe); 249 250 251 #if defined(TESTING) && 0 234 235 #if TESTING 252 236 { 253 237 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); … … 278 262 } 279 263 280 #if defTESTING264 #if TESTING 281 265 psphotSaveImage(NULL, readout->image, "orig_image.fits"); 282 266 psphotSaveImage(NULL, readout->variance, "orig_variance.fits"); … … 293 277 } 294 278 295 #if defTESTING279 #if TESTING 296 280 psphotSaveImage(NULL, readout->image, "fake_image.fits"); 297 281 psphotSaveImage(NULL, readout->variance, "fake_variance.fits"); … … 408 392 psFree(significance); 409 393 410 if (!psphotFitSourcesLinear (readout, fakeSourcesAll, recipe, psf, true)) {394 if (!psphotFitSourcesLinearReadout(recipe, readout, fakeSourcesAll, psf, true)) { 411 395 psError(PS_ERR_UNKNOWN, false, "Unable to perform linear fit on fake sources."); 412 396 psFree(fakeSources); … … 415 399 } 416 400 417 // Disable aperture corrections ; casting away const!401 // Disable aperture corrections (save current value) 418 402 pmTrend2D *apTrend = psf->ApTrend; // Aperture trend 419 ((pmPSF*)psf)->ApTrend = NULL;420 421 if (!psphotMagnitudes (config, readout, view, fakeSourcesAll, psf)) {403 psf->ApTrend = NULL; 404 405 if (!psphotMagnitudesReadout(config, recipe, view, readout, fakeSourcesAll, psf)) { 422 406 psError(PS_ERR_UNKNOWN, false, "Unable to measure magnitudes of fake sources."); 423 407 psFree(fakeSources); 424 408 psFree(count); 425 ((pmPSF*)psf)->ApTrend = apTrend; // Casting away const!409 psf->ApTrend = apTrend; // Casting away const! 426 410 return false; 427 411 } 428 412 psFree(fakeSourcesAll); 429 413 430 // Re -enable aperture corrections; casting away const!431 ((pmPSF*)psf)->ApTrend = apTrend;414 // Replace aperture corrections 415 psf->ApTrend = apTrend; 432 416 433 417 psVector *magDiffMean = psVectorAlloc(numBins, PS_TYPE_F32); // Mean difference in magnitude for each bin … … 443 427 psVectorInit(magMask, 0); 444 428 445 #if defTESTING429 #if TESTING 446 430 psString name = NULL; 447 431 psStringAppend(&name, "fake_%d.dat", i); … … 459 443 } 460 444 461 #if defTESTING445 #if TESTING 462 446 fprintf(file, "%f %f %f %f %f %f %f\n", source->peak->xf, source->peak->yf, 463 447 source->modelPSF->params->data.F32[PM_PAR_XPOS], … … 495 479 } 496 480 497 #if defTESTING481 #if TESTING 498 482 fclose(file); 499 483 #endif … … 520 504 psLogMsg("psphot", PS_LOG_INFO, "Detection efficiency: %lf sec\n", psTimerClear("psphot.fake")); 521 505 522 # endif523 524 506 return true; 525 507 } -
trunk/psphot/src/psphotFitSourcesLinear.c
r26894 r27532 17 17 bool status = true; 18 18 19 // select the appropriate recipe information 20 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 21 assert (recipe); 22 19 23 int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM"); 20 24 psAssert (status, "programming error: must define PSPHOT.INPUT.NUM"); … … 22 26 // loop over the available readouts 23 27 for (int i = 0; i < num; i++) { 24 if (!psphotFitSourcesLinearReadout (config, view, "PSPHOT.INPUT", i, final)) { 28 29 // find the currently selected readout 30 pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", i); // File of interest 31 psAssert (file, "missing file?"); 32 33 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 34 psAssert (readout, "missing readout?"); 35 36 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 37 psAssert (detections, "missing detections?"); 38 39 psArray *sources = detections->allSources; 40 psAssert (sources, "missing sources?"); 41 42 pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF"); 43 psAssert (psf, "missing psf?"); 44 45 if (!psphotFitSourcesLinearReadout (recipe, readout, sources, psf, final)) { 25 46 psError (PSPHOT_ERR_CONFIG, false, "failed to fit sources (linear) for PSPHOT.INPUT entry %d", i); 26 47 return false; … … 30 51 } 31 52 32 bool psphotFitSourcesLinearReadout (p mConfig *config, const pmFPAview *view, const char *filename, int index, bool final) {53 bool psphotFitSourcesLinearReadout (psMetadata *recipe, pmReadout *readout, psArray *sources, pmPSF *psf, bool final) { 33 54 34 55 bool status; … … 36 57 float y; 37 58 float f; 38 // float r;39 40 // select the appropriate recipe information41 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);42 assert (recipe);43 44 // find the currently selected readout45 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest46 psAssert (file, "missing file?");47 48 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);49 psAssert (readout, "missing readout?");50 51 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");52 psAssert (detections, "missing detections?");53 54 psArray *sources = detections->allSources;55 psAssert (sources, "missing sources?");56 59 57 60 if (!sources->n) { … … 59 62 return true; 60 63 } 61 62 pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");63 psAssert (sources, "missing psf?");64 64 65 65 psTimerStart ("psphot.linear"); -
trunk/psphot/src/psphotFitSourcesLinearStack.c
r25755 r27532 9 9 // these are used to determine the simultaneous linear fit of fluxes. 10 10 // the analysis is performed wrt the simulated pixel values 11 12 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, psImageMaskType markVal);13 11 14 12 bool psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final) { … … 194 192 return true; 195 193 } 196 197 // Calculate the weight terms for the sky fit component of the matrix. This function operates198 // on the pixels which correspond to all of the sources of interest. These elements fill in199 // the border matrix components in the sparse matrix equation.200 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, psImageMaskType markVal) {201 202 // generate the image-wide weight terms203 // turn on MARK for all image pixels204 psRegion fullArray = psRegionSet (0, 0, 0, 0);205 fullArray = psRegionForImage (readout->mask, fullArray);206 psImageMaskRegion (readout->mask, fullArray, "OR", markVal);207 208 // turn off MARK for all object pixels209 for (int i = 0; i < sources->n; i++) {210 pmSource *source = sources->data[i];211 pmModel *model = pmSourceGetModel (NULL, source);212 if (model == NULL) continue;213 float x = model->params->data.F32[PM_PAR_XPOS];214 float y = model->params->data.F32[PM_PAR_YPOS];215 psImageMaskCircle (source->maskView, x, y, model->radiusFit, "AND", PS_NOT_IMAGE_MASK(markVal));216 }217 218 // accumulate the image statistics from the masked regions219 psF32 **image = readout->image->data.F32;220 psF32 **variance = readout->variance->data.F32;221 psImageMaskType **mask = readout->mask->data.PS_TYPE_IMAGE_MASK_DATA;222 223 double w, x, y, x2, xy, y2, xc, yc, wt, f, fo, fx, fy;224 w = x = y = x2 = xy = y2 = fo = fx = fy = 0;225 226 int col0 = readout->image->col0;227 int row0 = readout->image->row0;228 229 for (int j = 0; j < readout->image->numRows; j++) {230 for (int i = 0; i < readout->image->numCols; i++) {231 if (mask[j][i]) continue;232 if (constant_weights) {233 wt = 1.0;234 } else {235 wt = variance[j][i];236 }237 f = image[j][i];238 w += 1/wt;239 fo += f/wt;240 }241 }242 243 // turn off MARK for all image pixels244 psImageMaskRegion (readout->mask, fullArray, "AND", PS_NOT_IMAGE_MASK(markVal));245 246 // set the Border T elements247 psSparseBorderElementG (border, 0, fo);248 psSparseBorderElementT (border, 0, 0, w);249 250 return true;251 } -
trunk/psphot/src/psphotKernelFromPSF.c
r17396 r27532 4 4 5 5 assert (source); 6 assert (source->psf Flux); // XXX build if needed?6 assert (source->psfImage); // XXX build if needed? 7 7 8 int x0 = source->peak->xf - source->psf Flux->col0;9 int y0 = source->peak->yf - source->psf Flux->row0;8 int x0 = source->peak->xf - source->psfImage->col0; 9 int y0 = source->peak->yf - source->psfImage->row0; 10 10 11 11 // need to decide on the size: dynamically? statically? … … 17 17 // if the realized PSF for this object does not cover the full kernel, give up for now 18 18 if (x0 + psf->xMin < 0) goto escape; 19 if (x0 + psf->xMax >= source->psf Flux->numCols) goto escape;19 if (x0 + psf->xMax >= source->psfImage->numCols) goto escape; 20 20 if (y0 + psf->yMin < 0) goto escape; 21 if (y0 + psf->yMax >= source->psf Flux->numRows) goto escape;21 if (y0 + psf->yMax >= source->psfImage->numRows) goto escape; 22 22 23 23 double sum = 0.0; 24 24 for (int j = psf->yMin; j <= psf->yMax; j++) { 25 25 for (int i = psf->xMin; i <= psf->xMax; i++) { 26 double value = source->psf Flux->data.F32[y0 + j][x0 + i];26 double value = source->psfImage->data.F32[y0 + j][x0 + i]; 27 27 psf->kernel[j][i] = value; 28 28 sum += value; -
trunk/psphot/src/psphotMagnitudes.c
r26894 r27532 14 14 // loop over the available readouts 15 15 for (int i = 0; i < num; i++) { 16 if (!psphotMagnitudesReadout (config, view, "PSPHOT.INPUT", i, recipe)) { 16 17 // find the currently selected readout 18 pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", i); // File of interest 19 psAssert (file, "missing file?"); 20 21 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 22 psAssert (readout, "missing readout?"); 23 24 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 25 psAssert (detections, "missing detections?"); 26 27 psArray *sources = detections->allSources; 28 psAssert (sources, "missing sources?"); 29 30 pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF"); 31 psAssert (psf, "missing psf?"); 32 33 if (!psphotMagnitudesReadout (config, recipe, view, readout, sources, psf)) { 17 34 psError (PSPHOT_ERR_CONFIG, false, "failed to measure magnitudes for PSPHOT.INPUT entry %d", i); 18 35 return false; … … 22 39 } 23 40 24 bool psphotMagnitudesReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {41 bool psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf) { 25 42 26 43 bool status = false; 27 44 int Nap = 0; 28 45 46 if (!sources->n) { 47 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source magnitudes"); 48 return true; 49 } 50 29 51 psTimerStart ("psphot.mags"); 30 31 // find the currently selected readout32 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest33 psAssert (file, "missing file?");34 35 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);36 psAssert (readout, "missing readout?");37 38 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");39 psAssert (detections, "missing detections?");40 41 psArray *sources = detections->allSources;42 psAssert (sources, "missing sources?");43 44 if (!sources->n) {45 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");46 return true;47 }48 49 pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");50 psAssert (psf, "missing psf?");51 52 52 53 // determine the number of allowed threads … … 79 80 } 80 81 81 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");82 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH"); 82 83 bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); 84 bool DIFF_STATS = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); 83 85 84 86 pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_APCORR | PM_SOURCE_PHOT_WEIGHT; 85 87 if (!IGNORE_GROWTH) photMode |= PM_SOURCE_PHOT_GROWTH; 86 88 if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP; 89 if (DIFF_STATS) photMode |= PM_SOURCE_PHOT_DIFFSTATS; 87 90 88 91 // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts) -
trunk/psphot/src/psphotMakeResiduals.c
r25755 r27532 305 305 if (fabs(resid->Ro->data.F32[oy][ox]) < pixelSN*dRo/sqrt(nKeep)) { 306 306 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 307 resid->Ro->data.F32[oy][ox] = 0.0; 308 resid->Rx->data.F32[oy][ox] = 0.0; 309 resid->Ry->data.F32[oy][ox] = 0.0; 307 310 } 308 311 } -
trunk/psphot/src/psphotReadout.c
r26894 r27532 91 91 return psphotReadoutCleanup (config, view); 92 92 } 93 if (!strcasecmp (breakPt, "MOMENTS")) {94 return psphotReadoutCleanup(config, view);95 }96 97 93 // if we were not supplied a PSF model, determine the IQ stats here (detections->newSources) 98 94 if (!psphotImageQuality (config, view)) { // pass 1 99 95 psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality"); 96 return psphotReadoutCleanup(config, view); 97 } 98 if (!strcasecmp (breakPt, "MOMENTS")) { 100 99 return psphotReadoutCleanup(config, view); 101 100 } -
trunk/psphot/src/psphotSourceSize.c
r26894 r27532 13 13 float soft; 14 14 int grow; 15 int xtest, ytest; 16 bool apply; // apply CR mask? 15 17 } psphotSourceSizeOptions; 16 18 … … 22 24 bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal); 23 25 bool psphotMaskCosmicRayFootprintCheck (psArray *sources); 26 int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh); 24 27 25 28 // we need to call this function after sources have been fitted to the PSF model and … … 101 104 assert (status); 102 105 106 // XXX recipe name is not great 107 options.xtest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.XTEST"); 108 options.ytest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.YTEST"); 109 assert (status); 110 103 111 options.grow = psMetadataLookupS32(&status, recipe, "PSPHOT.CR.GROW"); // Growth size for CRs 104 112 if (!status || options.grow < 0) { … … 111 119 psWarning("PSPHOT.CR.NSIGMA.SOFTEN not set; defaulting to zero."); 112 120 options.soft = 0.0; 121 } 122 123 options.apply = psMetadataLookupBool(&status, recipe, "PSPHOT.CRMASK.APPLY"); // Growth size for CRs 124 if (!status) { 125 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSPHOT.CRMASK.APPLY is not defined."); 126 return false; 113 127 } 114 128 … … 239 253 continue; 240 254 } 255 // psphotVisualPlotSourceSize (recipe, readout->analysis, sources); 241 256 } 242 257 … … 244 259 } 245 260 261 # define SIZE_SN_LIM 10 246 262 bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) { 247 263 … … 285 301 } 286 302 287 // we are basically classifying by moments ; use the default if not found303 // we are basically classifying by moments 288 304 psAssert (source->moments, "why is this source missing moments?"); 289 305 if (source->mode & noMoments) { … … 292 308 } 293 309 310 // convert to Mmaj, Mmin: 294 311 psF32 Mxx = source->moments->Mxx; 295 312 psF32 Myy = source->moments->Myy; … … 315 332 float apMag = -2.5*log10(source->moments->Sum); 316 333 float dMag = source->psfMag - apMag; 317 float nSigma = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr); 318 319 source->extNsigma = nSigma; 320 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 334 335 // set nSigma to include both systematic and poisson error terms 336 // XXX the 'poisson error' contribution for size is probably wrong... 337 float nSigmaMAG = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr); 338 float nSigmaMXX = (Mxx - psfClump->X) / hypot(psfClump->dX, psfClump->X*psfClump->X*source->errMag); 339 float nSigmaMYY = (Myy - psfClump->Y) / hypot(psfClump->dY, psfClump->Y*psfClump->Y*source->errMag); 340 341 // partially-masked sources are more likely to be mis-measured PSFs 342 float sizeBias = 1.0; 343 if (source->pixWeight < 0.9) { 344 sizeBias = 3.0; 345 } 346 347 float minMxx = psfClump->X - sizeBias*options->nSigmaMoments*psfClump->dX; 348 float minMyy = psfClump->Y - sizeBias*options->nSigmaMoments*psfClump->dY; 349 350 // include MAG, MXX, and MYY? 351 source->extNsigma = nSigmaMAG; 352 353 // notes to clarify the source size classification rules: 354 // * a defect should be functionally equivalent to a cosmic ray 355 // * CR & defect should have a faintess limit (min S/N) 356 // * SAT stars should not be faint, but defects may? 321 357 322 358 // Anything within this region is a probably PSF-like object. Saturated stars may land 323 359 // in this region, but are detected elsewhere on the basis of their peak value. 324 bool isPSF = ((fabs(nSigma) < options->nSigmaApResid) && 325 (fabs(Mxx - psfClump->X) < options->nSigmaMoments*psfClump->dX) && 326 (fabs(Myy - psfClump->Y) < options->nSigmaMoments*psfClump->dY)); 360 bool isPSF = (fabs(nSigmaMAG) < options->nSigmaApResid) && (fabs(nSigmaMXX) < sizeBias*options->nSigmaMoments) && (fabs(nSigmaMYY) < sizeBias*options->nSigmaMoments); 327 361 if (isPSF) { 328 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g PSF\t%g %g\n", 329 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 330 options->nSigmaApResid,options->nSigmaMoments); 362 psTrace("psphotSourceClassRegion.PSF",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g PSF\t%g %g\n", 363 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG, 364 options->nSigmaApResid,sizeBias*options->nSigmaMoments); 365 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 331 366 Npsf ++; 332 367 continue; … … 336 371 // Defects may also be marked as SATSTAR -- XXX deactivate this flag? 337 372 // XXX this rule is not great 338 if ((Mxx < psfClump->X) || (Myy < psfClump->Y)) { 339 340 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g CR\t%g %g\n", 341 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 342 options->nSigmaApResid,options->nSigmaMoments); 373 // XXX only accept brightish detections as CRs 374 // (nSigmaMAG < -options->nSigmaApResid) || 375 bool isCR = isCR = (source->errMag < 1.0 / SIZE_SN_LIM) && ((Mxx < minMxx) || (Myy < minMyy)); 376 if (isCR) { 377 psTrace("psphotSourceClassRegion.CR",4,"CLASS: %g %g %f\t%g %g %g %g %g %g\t%g %g\t%g CR\t%g %g\n", 378 source->peak->xf,source->peak->yf,source->pixWeight,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG, 379 options->nSigmaApResid,sizeBias*options->nSigmaMoments); 343 380 source->mode |= PM_SOURCE_MODE_DEFECT; 381 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_CR_CANDIDATE; 344 382 Ncr ++; 345 383 continue; … … 349 387 // just large saturated regions. 350 388 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 351 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g SAT\t%g %g\n",352 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma,353 options->nSigmaApResid,options->nSigmaMoments);354 389 psTrace("psphotSourceClassRegion.SAT",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g SAT\t%g %g\n", 390 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG, 391 options->nSigmaApResid,sizeBias*options->nSigmaMoments); 392 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 355 393 Nsat ++; 356 394 continue; … … 358 396 359 397 // XXX allow the Mxx, Myy to be less than psfClump->X,Y (by some nSigma)? 360 bool isEXT = (nSigma > options->nSigmaApResid) || ((Mxx > psfClump->X) && (Myy > psfClump->Y));398 bool isEXT = (nSigmaMAG > options->nSigmaApResid) || (Mxx > minMxx) || (Myy > minMyy); 361 399 if (isEXT) { 362 psTrace("psphot .czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g Ext\t%g %g\n",363 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma ,364 options->nSigmaApResid, options->nSigmaMoments);400 psTrace("psphotSourceClassRegion.EXT",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g Ext\t%g %g\n", 401 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG, 402 options->nSigmaApResid,sizeBias*options->nSigmaMoments); 365 403 366 404 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 405 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 367 406 Next ++; 368 407 continue; 369 408 } 370 psTrace("psphot .czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g Unk\t%g %g\n",371 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma ,372 options->nSigmaApResid, options->nSigmaMoments);409 psTrace("psphotSourceClassRegion.MISS",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g Unk\t%g %g\n", 410 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG, 411 options->nSigmaApResid,sizeBias*options->nSigmaMoments); 373 412 374 psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigma); 413 // sources that reach here are probably too faint for a reasonable source size measurement 414 // psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigmaMAG); 415 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 375 416 Nmiss ++; 376 417 } … … 385 426 bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) { 386 427 428 psTimerStart ("psphot.cr"); 429 430 int nMasked = 0; 387 431 for (int i = 0; i < sources->n; i++) { 388 432 pmSource *source = sources->data[i]; … … 393 437 continue; 394 438 } 439 440 // only check candidates marked above 441 if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_CR_CANDIDATE)) { 442 psTrace("psphot", 7, "Not calculating source size since it has already been measured\n"); 443 continue; 444 } 445 446 // skip unless this source is thought to be a cosmic ray. flag the detection and mask the pixels 447 // XXX this may be degenerate with the above test 448 if (!(source->mode & PM_SOURCE_MODE_DEFECT)) continue; 395 449 396 450 // Integer position of peak … … 402 456 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 403 457 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 404 // psTrace("psphot.czw", 2, "Not calculating crNsigma due to edge\n");405 458 continue; 406 459 } 407 460 408 // this source is thought to be a cosmic ray. flag the detection and mask the pixels 409 if (source->mode & PM_SOURCE_MODE_DEFECT) { 410 // XXX this is running slowly and is too agressive, but it more-or-less works 411 // psphotMaskCosmicRayCZW(readout, source, options->crMask); 412 413 // XXX these are the old versions which we are not using 414 // psphotMaskCosmicRay (readout->mask, source, maskVal, crMask); 415 // psphotMaskCosmicRay_Old (source, maskVal, crMask); 416 } 461 // XXX for testing, only CRMASK a single source: 462 if (options->xtest && (fabs(source->peak->xf - options->xtest) > 5)) continue; 463 if (options->ytest && (fabs(source->peak->yf - options->ytest) > 5)) continue; 464 465 // replace object in image 466 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 467 pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal); 468 } 469 470 // XXX this is running slowly and is too agressive, but it more-or-less works 471 psTrace("psphot", 6, "mask cosmic ray at %f, %f\n", source->peak->xf, source->peak->yf); 472 if (options->apply) { 473 psphotMaskCosmicRay(readout, source, options->crMask); 474 } else { 475 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 476 } 477 nMasked ++; 478 479 // re-subtract the object, leave local sky 480 pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal); 417 481 } 418 482 … … 430 494 } 431 495 496 psLogMsg ("psphot.cr", PS_LOG_INFO, "mask CR: %d masked in %f sec\n", nMasked, psTimerMark ("psphot.cr")); 497 432 498 // XXX test : save the mask image 433 499 if (0) { 434 500 psphotSaveImage (NULL, readout->mask, "mask.fits"); 435 501 } 502 436 503 return true; 437 504 } 505 506 # define DUMPPICS 0 507 # define LIMIT_XRANGE(X, IMAGE) { X = PS_MIN(PS_MAX(0, X), IMAGE->numCols); } 508 # define LIMIT_YRANGE(Y, IMAGE) { Y = PS_MIN(PS_MAX(0, Y), IMAGE->numRows); } 438 509 439 510 // Comments by CZW 20091209 : Mechanics of how to identify CR pixels taken from "Cosmic-Ray … … 448 519 pmFootprint *footprint = peak->footprint; 449 520 450 int xm = footprint->bbox.x0;451 int xM = footprint->bbox.x1;452 int ym = footprint->bbox.y0;453 int yM = footprint->bbox.y1;454 455 if (xm < 0) { xm = 0; }456 if (ym < 0) { ym = 0; }457 if (xM > mask->numCols) { xM = mask->numCols; }458 if (yM > mask->numRows) { yM = mask->numRows; }459 int dx = xM - xm;460 int dy = yM - ym;461 462 521 // Bounding boxes are inclusive of final pixel 463 // XXX ensure dx,dy do not become too large here 464 dx++; 465 dy++; 522 int xs = footprint->bbox.x0; 523 int xe = footprint->bbox.x1 + 1; 524 int ys = footprint->bbox.y0; 525 int ye = footprint->bbox.y1 + 1; 526 527 LIMIT_XRANGE(xs, mask); 528 LIMIT_XRANGE(xe, mask); 529 LIMIT_YRANGE(ys, mask); 530 LIMIT_YRANGE(ye, mask); 531 532 int dx = xe - xs; 533 int dy = ye - ys; 466 534 467 535 psImage *image= readout->image; 468 536 psImage *variance = readout->variance; 469 537 470 int binning = 1; 471 float sigma_thresh = 2.0; 472 int iteration = 0; 473 int max_iter = 5; 474 float noise_factor = 5.0 / 4.0; // Intrinsic to the Laplacian making noise spikes spikier. 538 int binning = 2; 539 float sigma_thresh = 3.0; 540 int max_iter = 1; // XXX with isophot masking, we only want to do a single pass 475 541 476 542 // Temporary images. 477 543 psImage *mypix = psImageAlloc(dx,dy,image->type.type); 544 psImage *myfix = psImageAlloc(dx,dy,image->type.type); 478 545 psImage *myvar = psImageAlloc(dx,dy,image->type.type); 479 546 psImage *binned = psImageAlloc(dx * binning,dy * binning,image->type.type); … … 482 549 psImage *mymask = psImageAlloc(dx,dy,PS_TYPE_IMAGE_MASK); 483 550 484 int x,y;485 551 // Load my copy of things. 486 for ( x = 0; x < dx; x++) {487 for ( y = 0; y < dy; y++) {488 psImageSet(mypix,x,y,psImageGet(image,x+xm,y+ym));489 psImageSet(myvar,x,y,psImageGet(variance,x+xm,y+ym));552 for (int y = 0; y < dy; y++) { 553 for (int x = 0; x < dx; x++) { 554 mypix->data.F32[y][x] = image->data.F32[y+ys][x+xs]; 555 myvar->data.F32[y][x] = variance->data.F32[y+ys][x+xs]; 490 556 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0x00; 491 557 } … … 495 561 pmSpan *sp = footprint->spans->data[i]; 496 562 for (int j = sp->x0; j <= sp->x1; j++) { 497 y = sp->y - ym;498 x = j - xm;563 int y = sp->y - ys; 564 int x = j - xs; 499 565 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= 0x01; 500 566 } 501 567 } 502 568 503 int CRpix_count = 0; 504 do { 505 CRpix_count = 0; 506 // Zero out my temp images. 507 for (x = 0; x < binning * dx; x++) { 508 for (y = 0; y < binning * dy; y++) { 509 psImageSet(binned,x,y,0.0); 510 psImageSet(conved,x,y,0.0); 511 psImageSet(edges,x/binning,y/ binning,0.0); 569 int nCRpix = 1; // force at least one pass... 570 for (int iteration = 0; (iteration < max_iter) && (nCRpix > 0); iteration++) { 571 nCRpix = 0; 572 psImageInit (binned, 0.0); 573 psImageInit (conved, 0.0); 574 psImageInit (edges, 0.0); 575 576 // Make subsampled image. Maybe this should be called "unbinned" or something 577 for (int y = 0; y < binning * dy; y++) { 578 int yraw = y / binning; 579 for (int x = 0; x < binning * dx; x++) { 580 int xraw = x / binning; 581 binned->data.F32[y][x] = mypix->data.F32[yraw][xraw]; 512 582 } 513 } 514 // Make subsampled image. Maybe this should be called "unbinned" or something 515 for (x = 0; x < binning * dx; x++) { 516 for (y = 0; y < binning * dy; y++) { 517 psImageSet(binned,x,y,psImageGet(mypix,x / binning,y / binning)); 583 } 584 585 // Apply Laplace transform (kernel = [[0 -0.25 0][-0.25 1 -0.25][0 -0.25 0]]), clipping at zero 586 for (int y = 1; y < binning * dy - 1; y++) { 587 for (int x = 1; x < binning * dx - 1; x++) { 588 float value = binned->data.F32[y][x] - 0.25 * 589 (binned->data.F32[y+0][x-1] + binned->data.F32[y+0][x+1] + 590 binned->data.F32[y-1][x+0] + binned->data.F32[y+1][x+0]); 591 value = PS_MAX(0.0, value); 592 593 conved->data.F32[y][x] = value; 518 594 } 519 595 } 520 // Apply Laplace transform (kernel = [[0 -0.25 0][-0.25 1 -0.25][0 -0.25 0]]), clipping at zero 521 for (x = 1; x < dx - 1; x++) { 522 for (y = 1; y < dy - 1; y++) { 523 psImageSet(conved,x,y,psImageGet(binned,x,y) - 0.25 * 524 (psImageGet(binned,x-1,y) + psImageGet(binned,x+1,y) + 525 psImageGet(binned,x,y-1) + psImageGet(binned,x,y+1))); 526 if (psImageGet(conved,x,y) < 0.0) { 527 psImageSet(conved,x,y,0.0); 528 } 596 597 // Create an edge map by rebinning 598 for (int y = 0; y < binning * dy; y++) { 599 int yraw = y / binning; 600 for (int x = 0; x < binning * dx; x++) { 601 int xraw = x / binning; 602 edges->data.F32[yraw][xraw] += conved->data.F32[y][x]; 529 603 } 530 604 } 531 // Create an edge map by rebinning 532 for (x = 0; x < binning * dx; x++) { 533 for (y = 0; y < binning * dy; y++) { 534 psImageSet(edges,x / binning, y / binning, 535 psImageGet(edges, x / binning, y / binning) + 536 psImageGet(conved,x,y)); 537 } 538 } 539 // Modify my mask if we're above the significance threshold 540 for (x = 0; x < dx; x++) { 541 for (y = 0; y < dy; y++) { 542 if ( psImageGet(edges,x,y) / (binning * sqrt(noise_factor * psImageGet(myvar,x,y))) > sigma_thresh ) { 543 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x01) { 544 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= 0x40; 545 CRpix_count++; 546 } 547 } 548 } 549 } 550 605 606 // coordinate of peak in subimage pixels: 607 int xPeak = peak->x - xs; 608 int yPeak = peak->y - ys; 609 610 // Modify my mask if we're above the significance threshold, but only for connected pixels 611 nCRpix = psphotMaskCosmicRayConnected (xPeak, yPeak, mymask, myvar, edges, binning, sigma_thresh); 612 613 # if DUMPPICS 614 psphotSaveImage (NULL, mypix, "crmask.pix.fits"); 615 # endif 616 617 // XXX do not repair the pixels in isophot version 618 # if 0 551 619 // "Repair" Masked pixels for the next round. 552 for (x = 1; x < dx - 1; x++) { 553 for (y = 1; y < dy - 1; y++) { 554 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) { 555 psImageSet(mypix,x,y,0.25 * 556 (psImageGet(mypix,x-1,y) + psImageGet(mypix,x+1,y) + 557 psImageGet(mypix,x,y-1) + psImageGet(mypix,x,y+1))); 558 } 559 } 560 } 561 562 # if 0 563 if ((psTraceGetLevel("psphot.czw") >= 2)&&(abs(xm - 2770) < 5)&&(abs(ym - 2581) < 5)&&(iteration == 0)) { 564 psTrace("psphot.czw",2,"TRACEMOTRON %d %d %d %d %d\n",xm,ym,dx,dy,iteration); 565 psphotSaveImage (NULL, mypix, "czw.pix.fits"); 566 psphotSaveImage (NULL, myvar, "czw.var.fits"); 567 psphotSaveImage (NULL, binned, "czw.binn.fits"); 568 psphotSaveImage (NULL, conved, "czw.conv.fits"); 569 psphotSaveImage (NULL, edges, "czw.edge.fits"); 570 psphotSaveImage (NULL, mymask, "czw.mask.fits"); 571 } 572 # endif 573 574 psTrace("psphot.czw",2,"Iter: %d Count: %d",iteration,CRpix_count); 575 iteration++; 576 } while ((iteration < max_iter)&&(CRpix_count > 0)); 577 578 // A solitary masked pixel is likely a lie. Remove those. 579 for (x = 0; x < dx; x++) { 580 for (y = 0; y < dy; y++) { 581 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) { 582 if ((x-1 >= 0)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x-1] & 0x40)) { 620 for (int y = 1; y < dy - 1; y++) { 621 for (int x = 1; x < dx - 1; x++) { 622 if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40)) { 623 myfix->data.F32[y][x] = mypix->data.F32[y][x]; 583 624 continue; 584 625 } 585 if ((y-1 >= 0)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y-1][x] & 0x40)) { 586 continue; 587 } 588 if ((x+1 < dx)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x+1] & 0x40)) { 589 continue; 590 } 591 if ((y+1 < dy)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y+1][x] & 0x40)) { 592 continue; 593 } 594 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] ^= 0x40; 626 myfix->data.F32[y][x] = 0.25 * 627 (mypix->data.F32[y+0][x-1] + mypix->data.F32[y+0][x+1] + 628 mypix->data.F32[y-1][x+0] + mypix->data.F32[y+1][x+0]); 595 629 } 596 630 } 597 } 598 599 // transfer temporary mask to real mask 600 for (x = 0; x < dx; x++) { 601 for (y = 0; y < dy; y++) { 631 632 // "Repair" Masked pixels for the next round. 633 for (int y = 1; y < dy - 1; y++) { 634 for (int x = 1; x < dx - 1; x++) { 635 mypix->data.F32[y][x] = myfix->data.F32[y][x]; 636 } 637 } 638 # endif 639 640 # if DUMPPICS 641 fprintf (stderr, "CRMASK %d %d %d %d %d\n", xs, ys, dx, dy, iteration); 642 psphotSaveImage (NULL, mypix, "crmask.fix.fits"); 643 psphotSaveImage (NULL, myvar, "crmask.var.fits"); 644 psphotSaveImage (NULL, binned, "crmask.binn.fits"); 645 psphotSaveImage (NULL, conved, "crmask.conv.fits"); 646 psphotSaveImage (NULL, edges, "crmask.edge.fits"); 647 psphotSaveImage (NULL, mymask, "crmask.mask.fits"); 648 # endif 649 psTrace("psphot.czw",2,"Iter: %d Count: %d",iteration, nCRpix); 650 } 651 652 # if 0 653 // A solitary masked pixel is likely a lie. Remove those 654 // XXX can't we use nCRpix == 1 to test for these? 655 for (int x = 0; x < dx; x++) { 656 for (int y = 0; y < dy; y++) { 657 if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40)) continue; 658 if ((x-1 >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x-1] & 0x40)) { 659 continue; 660 } 661 if ((y-1 >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y-1][x] & 0x40)) { 662 continue; 663 } 664 if ((x+1 < dx) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x+1] & 0x40)) { 665 continue; 666 } 667 if ((y+1 < dy) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y+1][x] & 0x40)) { 668 continue; 669 } 670 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] ^= 0x40; 671 } 672 } 673 # endif 674 675 // transfer temporary mask to real mask & count masked pixels 676 nCRpix = 0; 677 for (int x = 0; x < dx; x++) { 678 for (int y = 0; y < dy; y++) { 602 679 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) { 603 mask->data.PS_TYPE_IMAGE_MASK_DATA[y+ym+mask->row0][x+xm+mask->col0] |= maskVal; 680 mask->data.PS_TYPE_IMAGE_MASK_DATA[y+ys+mask->row0][x+xs+mask->col0] |= maskVal; 681 nCRpix ++; 604 682 } 605 683 } … … 607 685 608 686 // XXX if we decide this REALLY is a cosmic ray, set the CR_LIMIT bit 609 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 687 if (nCRpix > 1) { 688 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 689 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 690 } 691 // fprintf (stderr, "CRMASK %d %d %d %d %d\n", peak->x, peak->y, dx, dy, nCRpix); 610 692 611 693 psFree(mypix); 694 psFree(myfix); 612 695 psFree(myvar); 613 696 psFree(binned); … … 680 763 } 681 764 return true; 765 } 766 767 # define VERBOSE 0 768 int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh) { 769 770 int xLo, xRo; 771 int nCRpix = 0; 772 773 float noise_factor = 5.0 / 4.0; // Intrinsic to the Laplacian making noise spikes spikier. 774 775 // mark the pixels in this row to the left, then the right. stay within footprint 776 int xL = xPeak; // find the range of valid pixels in this row 777 int xR = xPeak; 778 for (int ix = xPeak; (ix >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] & 0x01); ix--) { 779 float noise = binning * sqrt(noise_factor * myvar->data.F32[yPeak][ix]); 780 float value = edges->data.F32[yPeak][ix] / noise; 781 if (value < sigma_thresh ) break; 782 mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] |= 0x40; 783 xL = ix; 784 nCRpix ++; 785 if (VERBOSE) fprintf (stderr, "mark %d,%d (%d) : %d - %d\n", ix, yPeak, nCRpix, xL, xR); 786 } 787 for (int ix = xPeak; (ix < mymask->numCols) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] & 0x01); ix++) { 788 float noise = binning * sqrt(noise_factor * myvar->data.F32[yPeak][ix]); 789 float value = edges->data.F32[yPeak][ix] / noise; 790 if (value < sigma_thresh ) break; 791 mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] |= 0x40; 792 xR = ix; 793 nCRpix ++; 794 if (VERBOSE) fprintf (stderr, "mark %d,%d (%d) : %d - %d\n", ix, yPeak, nCRpix, xL, xR); 795 } 796 // xL and xR mark the first and last valid pixel in the row 797 798 // for each of the neighboring rows, mark the high pixels if they touch the range xL to xR 799 xLo = PS_MAX(xL - 1, 0); 800 xRo = PS_MIN(xR + 1, mymask->numCols); 801 802 // first go down: 803 for (int iy = yPeak - 1; iy >= 0; iy--) { 804 805 int xLn = -1; 806 int xRn = -1; 807 int newPix = 0; 808 809 // mark the pixels in the good range 810 for (int ix = xLo; ix < xRo; ix++) { 811 if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01)) continue; // only use pixels in the footprint 812 float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]); 813 float value = edges->data.F32[iy][ix] / noise; 814 if (value < sigma_thresh ) continue; 815 mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40; 816 if (xLn == -1) xLn = ix; // first valid pixel in this row 817 xRn = ix; // last valid pixel in this row 818 nCRpix ++; 819 newPix ++; 820 if (VERBOSE) fprintf (stderr, "mark C %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn); 821 } 822 823 // mark the pixels to the left of the good range 824 for (int ix = xLo; (ix >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix--) { 825 float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]); 826 float value = edges->data.F32[iy][ix] / noise; 827 if (value < sigma_thresh ) break; 828 mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40; 829 if (xRn == -1) xRn = ix; // last valid pixel in this row 830 xLn = ix; 831 nCRpix ++; 832 newPix ++; 833 if (VERBOSE) fprintf (stderr, "mark L %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn); 834 } 835 836 // mark the pixels to the right of the good range 837 for (int ix = xRo; (ix < mymask->numCols) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix++) { 838 float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]); 839 float value = edges->data.F32[iy][ix] / noise; 840 if (value < sigma_thresh ) break; 841 mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40; 842 if (xLn == -1) xLn = ix; // first valid pixel in this row 843 xRn = ix; 844 nCRpix ++; 845 newPix ++; 846 if (VERBOSE) fprintf (stderr, "mark R %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn); 847 } 848 if (newPix == 0) break; 849 xLo = PS_MAX(xLn - 1, 0); 850 xRo = PS_MIN(xRn + 1, mymask->numCols); 851 } 852 853 xLo = PS_MAX(xL - 1, 0); 854 xRo = PS_MIN(xR + 1, mymask->numCols); 855 856 // next go up: 857 for (int iy = yPeak + 1; iy < mymask->numRows; iy++) { 858 859 int xLn = -1; 860 int xRn = -1; 861 int newPix = 0; 862 863 // mark the pixels in the good range 864 for (int ix = xLo; ix < xRo; ix++) { 865 if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01)) continue; // only use pixels in the footprint 866 float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]); 867 float value = edges->data.F32[iy][ix] / noise; 868 if (value < sigma_thresh ) continue; 869 mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40; 870 if (xLn == -1) xLn = ix; // first valid pixel in this row 871 xRn = ix; // last valid pixel in this row 872 nCRpix ++; 873 newPix ++; 874 if (VERBOSE) fprintf (stderr, "mark C %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn); 875 } 876 877 // mark the pixels to the left of the good range 878 for (int ix = xLo; (ix >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix--) { 879 float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]); 880 float value = edges->data.F32[iy][ix] / noise; 881 if (value < sigma_thresh ) break; 882 mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40; 883 if (xRn == -1) xRn = ix; // last valid pixel in this row 884 xLn = ix; 885 nCRpix ++; 886 newPix ++; 887 if (VERBOSE) fprintf (stderr, "mark L %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn); 888 } 889 890 // mark the pixels to the right of the good range 891 for (int ix = xRo; (ix < mymask->numCols) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix++) { 892 float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]); 893 float value = edges->data.F32[iy][ix] / noise; 894 if (value < sigma_thresh ) break; 895 mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40; 896 if (xLn == -1) xLn = ix; // first valid pixel in this row 897 xRn = ix; 898 nCRpix ++; 899 newPix ++; 900 if (VERBOSE) fprintf (stderr, "mark R %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn); 901 } 902 if (newPix == 0) break; 903 xLo = PS_MAX(xLn - 1, 0); 904 xRo = PS_MIN(xRn + 1, mymask->numCols); 905 } 906 907 return nCRpix; 682 908 } 683 909 -
trunk/psphot/src/psphotVisual.c
r26894 r27532 1099 1099 psFree (outsat); 1100 1100 return true; 1101 } 1102 1103 static void plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1) 1104 { 1105 float x[2], y[2]; 1106 x[0] = x0; 1107 x[1] = x1; 1108 y[0] = y0; 1109 y[1] = y1; 1110 KapaPrepPlot (myKapa, 2, graphdata); 1111 KapaPlotVector (myKapa, 2, x, "x"); 1112 KapaPlotVector (myKapa, 2, y, "y"); 1101 1113 } 1102 1114 … … 1138 1150 } 1139 1151 1152 // generate model profiles (major and minor axis): 1153 // create a model with theta = 0.0 so major and minor axes are equiv to x and y: 1154 psEllipseShape rawShape, rotShape; 1155 1156 rawShape.sx = source->modelPSF->params->data.F32[PM_PAR_SXX] / M_SQRT2; 1157 rawShape.sy = source->modelPSF->params->data.F32[PM_PAR_SYY] / M_SQRT2; 1158 rawShape.sxy = source->modelPSF->params->data.F32[PM_PAR_SXY]; 1159 1160 psEllipseAxes axes = psEllipseShapeToAxes (rawShape, 20.0); 1161 1162 axes.theta = 0.0; 1163 1164 rotShape = psEllipseAxesToShape (axes); 1165 1166 psVector *params = psVectorAlloc(source->modelPSF->params->n, PS_TYPE_F32); 1167 for (int i = 0; i < source->modelPSF->params->n; i++) { 1168 params->data.F32[i] = source->modelPSF->params->data.F32[i]; 1169 } 1170 params->data.F32[PM_PAR_SXX] = rotShape.sx * M_SQRT2; 1171 params->data.F32[PM_PAR_SYY] = rotShape.sy * M_SQRT2; 1172 params->data.F32[PM_PAR_SXY] = rotShape.sxy; 1173 params->data.F32[PM_PAR_XPOS] = 0.0; 1174 params->data.F32[PM_PAR_YPOS] = 0.0; 1175 1176 psVector *rmod = psVectorAlloc(300, PS_TYPE_F32); 1177 psVector *fmaj = psVectorAlloc(300, PS_TYPE_F32); 1178 psVector *fmin = psVectorAlloc(300, PS_TYPE_F32); 1179 1180 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 1181 1182 float r = 0.0; 1183 for (int i = 0; i < rmod->n; i++) { 1184 r = i*0.1; 1185 rmod->data.F32[i] = r; 1186 1187 coord->data.F32[1] = r; 1188 coord->data.F32[0] = 0.0; 1189 fmaj->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord)); 1190 1191 coord->data.F32[0] = r; 1192 coord->data.F32[1] = 0.0; 1193 fmin->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord)); 1194 } 1195 psFree (coord); 1196 psFree (params); 1197 1198 float FWHM_MAJOR = 2.0*source->modelPSF->modelRadius (source->modelPSF->params, 0.5*source->modelPSF->params->data.F32[PM_PAR_I0]); 1199 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 1200 if (FWHM_MAJOR < FWHM_MINOR) PS_SWAP (FWHM_MAJOR, FWHM_MINOR); 1201 1202 psEllipseMoments emoments; 1203 emoments.x2 = source->moments->Mxx; 1204 emoments.xy = source->moments->Mxy; 1205 emoments.y2 = source->moments->Myy; 1206 axes = psEllipseMomentsToAxes (emoments, 20.0); 1207 float MOMENTS_MAJOR = 2.355*axes.major; 1208 float MOMENTS_MINOR = 2.355*axes.minor; 1209 1210 float logHM = log10(0.5*source->modelPSF->params->data.F32[PM_PAR_I0]); 1211 1140 1212 // reset source Add/Sub state to recorded 1141 1213 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); … … 1174 1246 KapaPlotVector (myKapa, nb, fb->data.F32, "y"); 1175 1247 1248 graphdata.color = KapaColorByName ("blue"); 1249 graphdata.ptype = 0; 1250 graphdata.size = 0.0; 1251 graphdata.style = 0; 1252 KapaPrepPlot (myKapa, rmod->n, &graphdata); 1253 KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x"); 1254 KapaPlotVector (myKapa, rmod->n, fmin->data.F32, "y"); 1255 plotline (myKapa, &graphdata, 0.0, logHM, 30.0, logHM); 1256 plotline (myKapa, &graphdata, 0.5*FWHM_MINOR, 0.0, 0.5*FWHM_MINOR, 5.0); 1257 graphdata.ltype = 1; 1258 plotline (myKapa, &graphdata, 0.5*MOMENTS_MINOR, 0.0, 0.5*MOMENTS_MINOR, 5.0); 1259 graphdata.ltype = 0; 1260 1261 graphdata.color = KapaColorByName ("green"); 1262 graphdata.ptype = 0; 1263 graphdata.size = 0.0; 1264 graphdata.style = 0; 1265 KapaPrepPlot (myKapa, rmod->n, &graphdata); 1266 KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x"); 1267 KapaPlotVector (myKapa, rmod->n, fmaj->data.F32, "y"); 1268 plotline (myKapa, &graphdata, 0.5*FWHM_MAJOR, 0.0, 0.5*FWHM_MAJOR, 5.0); 1269 graphdata.ltype = 1; 1270 plotline (myKapa, &graphdata, 0.5*MOMENTS_MAJOR, 0.0, 0.5*MOMENTS_MAJOR, 5.0); 1271 graphdata.ltype = 0; 1272 1273 for (int i = 0; i < rmod->n; i++) { 1274 rmod->data.F32[i] = log10(rmod->data.F32[i]); 1275 } 1276 1176 1277 // ** loglog ** 1177 1278 KapaSelectSection (myKapa, "loglog"); … … 1182 1283 graphdata.ymin = -0.05; 1183 1284 graphdata.ymax = +5.05; 1285 graphdata.color = KapaColorByName ("black"); 1184 1286 KapaSetLimits (myKapa, &graphdata); 1185 1287 … … 1204 1306 KapaPlotVector (myKapa, nb, Rb->data.F32, "x"); 1205 1307 KapaPlotVector (myKapa, nb, fb->data.F32, "y"); 1308 1309 graphdata.color = KapaColorByName ("blue"); 1310 graphdata.ptype = 0; 1311 graphdata.size = 0.0; 1312 graphdata.style = 0; 1313 KapaPrepPlot (myKapa, rmod->n, &graphdata); 1314 KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x"); 1315 KapaPlotVector (myKapa, rmod->n, fmin->data.F32, "y"); 1316 1317 graphdata.color = KapaColorByName ("green"); 1318 graphdata.ptype = 0; 1319 graphdata.size = 0.0; 1320 graphdata.style = 0; 1321 KapaPrepPlot (myKapa, rmod->n, &graphdata); 1322 KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x"); 1323 KapaPlotVector (myKapa, rmod->n, fmaj->data.F32, "y"); 1324 1325 psFree (rmod); 1326 psFree (fmin); 1327 psFree (fmaj); 1206 1328 1207 1329 psFree (rg); … … 1392 1514 if (source == NULL) continue; 1393 1515 1394 // if (source->type != type) continue;1395 1516 if (mode) { 1396 1517 if (keep) { … … 1516 1637 psVector *sDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1517 1638 1639 psVector *xLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1640 psVector *yLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1641 psVector *mLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1642 psVector *sLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1643 1518 1644 psVector *xCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1519 1645 psVector *yCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); … … 1526 1652 int nPSF = 0; 1527 1653 int nDEF = 0; 1654 int nLOW = 0; 1528 1655 int nCR = 0; 1529 1656 for (int i = 0; i < sources->n; i++) { 1530 1657 pmSource *source = sources->data[i]; 1531 1658 if (source->moments == NULL) continue; 1659 1660 // only plot the measured sources... 1661 if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue; 1532 1662 1533 1663 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) { … … 1561 1691 continue; 1562 1692 } 1563 if ((source->mode & PM_SOURCE_MODE_CR_LIMIT) || (source->mode & PM_SOURCE_MODE_SATSTAR)) { 1693 if (source->errMag > 0.1) { 1694 xLOW->data.F32[nLOW] = source->moments->Mxx; 1695 yLOW->data.F32[nLOW] = source->moments->Myy; 1696 mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum); 1697 sLOW->data.F32[nLOW] = source->extNsigma; 1698 nLOW++; 1564 1699 continue; 1565 1700 } … … 1570 1705 nPSF++; 1571 1706 } 1707 1572 1708 xSAT->n = nSAT; 1573 1709 ySAT->n = nSAT; … … 1594 1730 mDEF->n = nDEF; 1595 1731 sDEF->n = nDEF; 1732 1733 xLOW->n = nLOW; 1734 yLOW->n = nLOW; 1735 mLOW->n = nLOW; 1736 sLOW->n = nLOW; 1596 1737 1597 1738 // four sections: MxxMyy, MagMxx, MagMyy, MagSigma … … 1657 1798 KapaPlotVector (myKapa, nSAT, ySAT->data.F32, "y"); 1658 1799 1800 graphdata.color = KapaColorByName ("black"); 1801 graphdata.ptype = 7; 1802 graphdata.size = 1.0; 1803 graphdata.style = 2; 1804 KapaPrepPlot (myKapa, nLOW, &graphdata); 1805 KapaPlotVector (myKapa, nLOW, xLOW->data.F32, "x"); 1806 KapaPlotVector (myKapa, nLOW, yLOW->data.F32, "y"); 1807 1659 1808 // second section: MagMyy 1660 1809 section.dx = 0.75; … … 1668 1817 graphdata.color = KapaColorByName ("black"); 1669 1818 graphdata.xmin = -17.1; 1670 graphdata.xmax = - 7.9;1819 graphdata.xmax = -6.9; 1671 1820 graphdata.ymin = Ymin; 1672 1821 graphdata.ymax = Ymax; … … 1730 1879 graphdata.xmin = Xmin; 1731 1880 graphdata.xmax = Xmax; 1732 graphdata.ymin = - 7.9;1881 graphdata.ymin = -6.9; 1733 1882 graphdata.ymax = -17.1; 1734 1883 KapaSetLimits (myKapa, &graphdata); … … 1789 1938 1790 1939 graphdata.color = KapaColorByName ("black"); 1791 graphdata.xmax = - 7.9;1940 graphdata.xmax = -6.9; 1792 1941 graphdata.xmin = -17.1; 1793 1942 graphdata.ymin = -20.1;
Note:
See TracChangeset
for help on using the changeset viewer.
