IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 17870


Ignore:
Timestamp:
May 30, 2008, 4:09:46 PM (18 years ago)
Author:
eugene
Message:

fix errors in calculation of sig image; API change: sig image is now actual S/N2

Location:
trunk/psphot/src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/psphot.h

    r17828 r17870  
    5151// used by psphotFindDetections
    5252psImage        *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal);
    53 psArray        *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal);
     53psArray        *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax);
    5454bool            psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal);
    5555psErrorCode     psphotCullPeaks(const psImage *img, const psImage *weight, const psMetadata *recipe, psArray *footprints);
  • trunk/psphot/src/psphotFindDetections.c

    r17444 r17870  
    66    bool status;
    77    int pass;
     8    float NSIGMA_PEAK = 25.0;
     9    int NMAX = 0;
    810
    911    psTimerStart ("psphot");
     
    2022        detections = pmDetectionsAlloc();
    2123        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);
    2226    } else {
    2327        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) ?
    2430    }
     31
     32    float threshold = PS_SQR(NSIGMA_PEAK);
    2533
    2634    // move the old peaks array (if it exists) to oldPeaks
     
    3442
    3543    // 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);
    3746
    3847    // optionally merge peaks into footprints
     
    4756// if we use the footprints, the output peaks list contains both old and new peaks,
    4857// 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 to
    51 // be "have PSF"
  • trunk/psphot/src/psphotFindFootprints.c

    r17516 r17870  
    1818    PS_ASSERT (status, false);
    1919
    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?
    2222
    23     float threshold = PS_SQR(FOOTPRINT_NSIGMA_LIMIT)/effArea;
     23    float threshold = PS_SQR(FOOTPRINT_NSIGMA_LIMIT);
    2424
    2525    int growRadius = 0;
     
    3131    PS_ASSERT (status, false);
    3232
    33     // XXX do we need to use the same threshold here as for peaks?  does it make sense for
    34     // these to be different?
    35 
    3633    // find the raw footprints & assign the peaks to those footprints
    3734    psArray *footprints = pmFootprintsFind (significance, threshold, npixMin);
     
    3936    // XXX handle the error conditions here
    4037
    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
    4339    psFree (detections->peaks);
    4440
  • trunk/psphot/src/psphotFindPeaks.c

    r17444 r17870  
    11# include "psphotInternal.h"
    22
    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
     6psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax) {
    57
    6 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) {
    7 
    8     float NSIGMA_PEAK;
    98    bool status = false;
    109
    11     // smooth the image and weight map
    1210    psTimerStart ("peaks");
    13 
    14     // signal/noise limit for the detected peaks
    15     // 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 smoothing
    27     // gaussian SIGMA.  a peak in the significance image has an effective S/N for faint sources
    28     // 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 noise
    30     // 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 in
    33     // terms of significance peak counts Io, for a desired S/N limit corresponds to
    34     // S/N = sqrt(Io)*4*pi*sigma_sm^2
    35     // 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 pixel
    39     }
    40     if (pass == 1) {
    41         effArea = 4.0*M_PI; // XXX better than nothing but still fairly poor
    42     }
    43 
    44     float threshold = PS_SQR(NSIGMA_PEAK) / effArea;
    45 
    46     // record the actual effective area and peak threshold
    47     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);
    4911
    5012    // find the peaks in the smoothed image
     
    5921    }
    6022
    61     // correct the peak values to S/N = sqrt(value*effArea)
     23    // correct the peak values to S/N = sqrt(significance)
    6224    // get the peak flux from the unsmoothed image
    6325    // the peak pixel coords are guaranteed to be on the image
     
    6628    for (int i = 0; i < peaks->n; i++) {
    6729        pmPeak *peak = peaks->data[i];
    68         peak->SN = sqrt(peak->value*effArea);
     30        peak->SN = sqrt(peak->value);
    6931        peak->flux = readout->image->data.F32[peak->y-row0][peak->x-col0];
    7032    }
    7133
    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;
    8443    }
    8544
    8645    // optional dump of all peak data
    87     // XXX need a better check for this option
    8846    char *output = psMetadataLookupStr (&status, recipe, "PEAKS_OUTPUT_FILE");
    89     if (status && (output != NULL) && (output[0])) {
     47    if (output && strcasecmp (output, "NONE")) {
    9048        pmPeaksWriteText (peaks, output);
    9149    }
     
    9553
    9654}
    97 
  • trunk/psphot/src/psphotOutput.c

    r16611 r17870  
    4444    // optional dump of all rough source data
    4545    char *output = psMetadataLookupStr (&status, recipe, "MOMENTS_OUTPUT_FILE");
    46     if (!status) return false;
    47     if (output == NULL) return false;
     46    if (!output) return false;
    4847    if (output[0] == 0) return false;
     48    if (!strcasecmp (output, "NONE")) return false;
    4949
    5050    pmMomentsWriteText (sources, output);
  • trunk/psphot/src/psphotReadout.c

    r17828 r17870  
    117117    psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);
    118118
     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
    119139    // identify CRs and extended sources
    120140    psphotSourceSize (readout, sources, recipe, 0);
  • trunk/psphot/src/psphotSignificanceImage.c

    r17443 r17870  
    11# include "psphotInternal.h"
    22
    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.
    56psImage *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) {
    67
     
    3435    psLogMsg ("psphot", PS_LOG_MINUTIA, "smooth image: %f sec\n", psTimerMark ("smooth"));
    3536
    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.
    3743    psImage *smooth_wt = psImageCopy (NULL, readout->weight, PS_TYPE_F32);
    3844    psImageSmoothMaskF32 (smooth_wt, readout->mask, maskVal, SIGMA_SMTH/sqrt(2), NSIGMA_SMTH);
     
    5157    }
    5258
    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
    5484    for (int j = 0; j < smooth_im->numRows; j++) {
    5585        for (int i = 0; i < smooth_im->numCols; i++) {
     
    5888                smooth_im->data.F32[j][i] = 0.0;
    5989            } 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];
    6191            }
    6292        }
     
    75105    return smooth_im;
    76106}
     107
Note: See TracChangeset for help on using the changeset viewer.