Changeset 17870
- Timestamp:
- May 30, 2008, 4:09:46 PM (18 years ago)
- Location:
- trunk/psphot/src
- Files:
-
- 7 edited
-
psphot.h (modified) (1 diff)
-
psphotFindDetections.c (modified) (4 diffs)
-
psphotFindFootprints.c (modified) (3 diffs)
-
psphotFindPeaks.c (modified) (4 diffs)
-
psphotOutput.c (modified) (1 diff)
-
psphotReadout.c (modified) (1 diff)
-
psphotSignificanceImage.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/psphot.h
r17828 r17870 51 51 // used by psphotFindDetections 52 52 psImage *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal); 53 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal);53 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax); 54 54 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal); 55 55 psErrorCode psphotCullPeaks(const psImage *img, const psImage *weight, const psMetadata *recipe, psArray *footprints); -
trunk/psphot/src/psphotFindDetections.c
r17444 r17870 6 6 bool status; 7 7 int pass; 8 float NSIGMA_PEAK = 25.0; 9 int NMAX = 0; 8 10 9 11 psTimerStart ("psphot"); … … 20 22 detections = pmDetectionsAlloc(); 21 23 pass = 1; 24 NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT"); PS_ASSERT (status, NULL); 25 NMAX = psMetadataLookupS32 (&status, recipe, "PEAKS_NMAX"); PS_ASSERT (status, NULL); 22 26 } else { 23 27 pass = 2; 28 NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT_2"); PS_ASSERT (status, NULL); 29 NMAX = 0; // unlimited number of peaks in final pass: allow a limit (PEAKS_NMAX_2) ? 24 30 } 31 32 float threshold = PS_SQR(NSIGMA_PEAK); 25 33 26 34 // move the old peaks array (if it exists) to oldPeaks … … 34 42 35 43 // detect the peaks in the significance image 36 detections->peaks = psphotFindPeaks (significance, readout, recipe, pass, maskVal); 44 detections->peaks = psphotFindPeaks (significance, readout, recipe, threshold, NMAX); 45 psMetadataAddF32 (recipe, PS_LIST_TAIL, "PEAK_THRESHOLD", PS_META_REPLACE, "Peak Detection Threshold", threshold); 37 46 38 47 // optionally merge peaks into footprints … … 47 56 // if we use the footprints, the output peaks list contains both old and new peaks, 48 57 // otherwise it only contains the new peaks. 49 50 // if psf is defined, we should treat this as pass "2", not "1". re-define this boolean to51 // be "have PSF" -
trunk/psphot/src/psphotFindFootprints.c
r17516 r17870 18 18 PS_ASSERT (status, false); 19 19 20 float effArea = psMetadataLookupF32 (&status, recipe, "EFFECTIVE_AREA");21 psAssert (status, "EFFECTIVE_AREA missing: call psphotFindPeaks first");20 // XXX do we need to use the same threshold here as for peaks? does it make sense for 21 // these to be different? 22 22 23 float threshold = PS_SQR(FOOTPRINT_NSIGMA_LIMIT) /effArea;23 float threshold = PS_SQR(FOOTPRINT_NSIGMA_LIMIT); 24 24 25 25 int growRadius = 0; … … 31 31 PS_ASSERT (status, false); 32 32 33 // XXX do we need to use the same threshold here as for peaks? does it make sense for34 // these to be different?35 36 33 // find the raw footprints & assign the peaks to those footprints 37 34 psArray *footprints = pmFootprintsFind (significance, threshold, npixMin); … … 39 36 // XXX handle the error conditions here 40 37 41 // footprints now owns the peaks; after culling (below), we will rebuild 42 // the peaks array 38 // footprints now owns the peaks; after culling (below), we will rebuild the peaks array 43 39 psFree (detections->peaks); 44 40 -
trunk/psphot/src/psphotFindPeaks.c
r17444 r17870 1 1 # include "psphotInternal.h" 2 2 3 // XXX let's make a better distinction between 'pass' and needing/having a PSF. 4 // In this function, we smooth the image, then search for the peaks 3 // Find peaks in the significance image above a threshold significance level. The significance 4 // image must be constructed to represent (S/N)^2. If nMax is non-zero, only return a maximum 5 // of nMax peaks 6 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax) { 5 7 6 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) {7 8 float NSIGMA_PEAK;9 8 bool status = false; 10 9 11 // smooth the image and weight map12 10 psTimerStart ("peaks"); 13 14 // signal/noise limit for the detected peaks15 // XXX this is a little lame: can we do something better than 'pass'?16 if (pass == 1) {17 NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT");18 } else {19 NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT_2");20 }21 PS_ASSERT (status, NULL);22 23 float SIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "SIGMA_SMOOTH");24 psAssert (status, "SIGMA_SMOOTH missing: call psphotSignificanceImage first");25 26 // we need to define the threshold based on the value of NSIGMA_PEAK and the applied smoothing27 // gaussian SIGMA. a peak in the significance image has an effective S/N for faint sources28 // of (S = Io*2pi*sigma_eff^2) / sqrt(Var), where sigma_eff^2 = sigma_obs^2 + sigma_sm^2.29 // the smoothing of the varience map does not affect the faint-source S/N since the noise30 // is constant under a faint source.31 32 // if sigma_sm = sigma_obs, then sigma_eff^2 = 2 sigma_sm^2. in this case, the threshold in33 // terms of significance peak counts Io, for a desired S/N limit corresponds to34 // S/N = sqrt(Io)*4*pi*sigma_sm^235 // thus, the threshold is:36 float effArea = 4.0*M_PI*PS_SQR(SIGMA_SMTH);37 if (effArea < 1) {38 effArea = 1; // never less than a pixel39 }40 if (pass == 1) {41 effArea = 4.0*M_PI; // XXX better than nothing but still fairly poor42 }43 44 float threshold = PS_SQR(NSIGMA_PEAK) / effArea;45 46 // record the actual effective area and peak threshold47 psMetadataAddF32 (recipe, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea);48 psMetadataAddF32 (recipe, PS_LIST_TAIL, "PEAK_THRESHOLD", PS_META_REPLACE, "Peak Detection Threshold", threshold);49 11 50 12 // find the peaks in the smoothed image … … 59 21 } 60 22 61 // correct the peak values to S/N = sqrt( value*effArea)23 // correct the peak values to S/N = sqrt(significance) 62 24 // get the peak flux from the unsmoothed image 63 25 // the peak pixel coords are guaranteed to be on the image … … 66 28 for (int i = 0; i < peaks->n; i++) { 67 29 pmPeak *peak = peaks->data[i]; 68 peak->SN = sqrt(peak->value *effArea);30 peak->SN = sqrt(peak->value); 69 31 peak->flux = readout->image->data.F32[peak->y-row0][peak->x-col0]; 70 32 } 71 33 72 // limit the total number of returned peak as specified 73 if (pass == 1) { 74 psArraySort (peaks, pmPeakSortBySN); 75 int NMAX = psMetadataLookupS32 (&status, recipe, "PEAKS_NMAX"); 76 if (NMAX && (peaks->n > NMAX)) { 77 psArray *tmpPeaks = psArrayAllocEmpty (NMAX); 78 for (int i = 0; i < NMAX; i++) { 79 psArrayAdd (tmpPeaks, 100, peaks->data[i]); 80 } 81 psFree (peaks); 82 peaks = tmpPeaks; 83 } 34 // limit the total number of returned peaks as specified 35 psArraySort (peaks, pmPeakSortBySN); 36 if (nMax && (peaks->n > nMax)) { 37 psArray *tmpPeaks = psArrayAllocEmpty (nMax); 38 for (int i = 0; i < nMax; i++) { 39 psArrayAdd (tmpPeaks, 100, peaks->data[i]); 40 } 41 psFree (peaks); 42 peaks = tmpPeaks; 84 43 } 85 44 86 45 // optional dump of all peak data 87 // XXX need a better check for this option88 46 char *output = psMetadataLookupStr (&status, recipe, "PEAKS_OUTPUT_FILE"); 89 if ( status && (output != NULL) && (output[0])) {47 if (output && strcasecmp (output, "NONE")) { 90 48 pmPeaksWriteText (peaks, output); 91 49 } … … 95 53 96 54 } 97 -
trunk/psphot/src/psphotOutput.c
r16611 r17870 44 44 // optional dump of all rough source data 45 45 char *output = psMetadataLookupStr (&status, recipe, "MOMENTS_OUTPUT_FILE"); 46 if (!status) return false; 47 if (output == NULL) return false; 46 if (!output) return false; 48 47 if (output[0] == 0) return false; 48 if (!strcasecmp (output, "NONE")) return false; 49 49 50 50 pmMomentsWriteText (sources, output); -
trunk/psphot/src/psphotReadout.c
r17828 r17870 117 117 psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE); 118 118 119 if (0) { 120 FILE *out = fopen ("out.dat", "w"); 121 122 for (int i = 0; i < sources->n; i++) { 123 pmSource *source = sources->data[i]; 124 if (!source) continue; 125 pmPeak *peak = source->peak; 126 if (!peak) continue; 127 pmModel *model = source->modelPSF; 128 if (!model) continue; 129 if (!model->params) continue; 130 131 fprintf (out, "%d %f %f %f %f %f %f\n", 132 i, peak->xf, peak->yf, peak->flux, peak->SN, 133 model->params->data.F32[PM_PAR_I0], 134 model->dparams->data.F32[PM_PAR_I0]); 135 } 136 fclose (out); 137 } 138 119 139 // identify CRs and extended sources 120 140 psphotSourceSize (readout, sources, recipe, 0); -
trunk/psphot/src/psphotSignificanceImage.c
r17443 r17870 1 1 # include "psphotInternal.h" 2 2 3 // In this function, we smooth the image, then search for the peaks 4 // if FWMH_X,Y have been recorded, use them; otherwise use PEAKS_SMOOTH_SIGMA 3 // In this function, we smooth the image and weight, then generate the significance image : 4 // (S/N)^2. If FWMH_X,Y have been recorded, use them, otherwise use PEAKS_SMOOTH_SIGMA for the 5 // smoothing kernel. 5 6 psImage *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) { 6 7 … … 34 35 psLogMsg ("psphot", PS_LOG_MINUTIA, "smooth image: %f sec\n", psTimerMark ("smooth")); 35 36 36 // smooth the weight, applying the mask as we go 37 // Smooth the weight, applying the mask as we go. The variance *should* be smoothed by the 38 // PSF^2, which does not have unity normalization (variance decreases as we smooth). 39 // Instead, we are smoothing with a Gaussian with sigma = SIGMA_SMTH/sqrt(2) with unity 40 // normalization. The resulting variance is a factor of 4*pi*SIGMA_SMTH^2 too large. We 41 // correct for this effect, and the effective area, in the calculation of the (S/N)^2 image 42 // below. 37 43 psImage *smooth_wt = psImageCopy (NULL, readout->weight, PS_TYPE_F32); 38 44 psImageSmoothMaskF32 (smooth_wt, readout->mask, maskVal, SIGMA_SMTH/sqrt(2), NSIGMA_SMTH); … … 51 57 } 52 58 53 // build the significance image on top of smooth_im 59 // We have an input image with PSF size sigma_r. We have smoothed it with a kernel of size 60 // sigma_s. The result is an image with PSF size sigma_o: sigma_o^2 = sigma_r^2 + 61 // sigma_s^2. Ideally, we are choosing sigma_s = sigma_r, in which case sigma_o^2 = 2 62 // sigma_s^2. If we do not know the input image PSF size (initial detection stage), then 63 // we are assuming that sigma_r = sigma_s. 64 65 // Build the significance image on top of smooth_im. We need to correct the ratio im/wt by 66 // two factors: 1) the error in the variance normalization above and 2) a factor to account 67 // for the relationship the peak value and the integrated flux, and the relationship 68 // between the per-pixel variance (var_i) and the total variance included in the flux 69 // measurement (effective area). These latter correction comes from: flux = Io * 70 // 2\pi\sigma_o^2 and total variance = var_i * 4\pi\sigma_o^2, thus (S/N)^2 = flux^2 / var 71 // = var_i \pi sigma_o^2 72 73 // thus: 74 // (S/N)^2 = (im^2 / wt) * (\pi \sigma_o^2 * 4 \sigma_s^2) 75 // (S/N)^2 = (im^2 / wt) * (\pi 2 \sigma_s^2 * 4 \sigma_s^2) 76 // (S/N)^2 = (im^2 / wt) * (\pi 8 \sigma_s^4) 77 78 float factor = 8.0 * PS_SQR(M_PI) * pow(SIGMA_SMTH, 4.0); 79 // record the effective area and significance scaling factor 80 float effArea = 8.0 * M_PI * PS_SQR(SIGMA_SMTH); 81 psMetadataAddF32 (recipe, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea); 82 psMetadataAddF32 (recipe, PS_LIST_TAIL, "SIGNIFICANCE_SCALE_FACTOR", PS_META_REPLACE, "Signicance scale factor", factor); 83 54 84 for (int j = 0; j < smooth_im->numRows; j++) { 55 85 for (int i = 0; i < smooth_im->numCols; i++) { … … 58 88 smooth_im->data.F32[j][i] = 0.0; 59 89 } else { 60 smooth_im->data.F32[j][i] = PS_SQR(value) / smooth_wt->data.F32[j][i];90 smooth_im->data.F32[j][i] = factor * PS_SQR(value) / smooth_wt->data.F32[j][i]; 61 91 } 62 92 } … … 75 105 return smooth_im; 76 106 } 107
Note:
See TracChangeset
for help on using the changeset viewer.
