IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42439


Ignore:
Timestamp:
Mar 26, 2023, 11:04:35 AM (3 years ago)
Author:
eugene
Message:

psphotFindFeatures now works well to reject sources on trails from Moments and PSF analysis

Location:
branches/eam_branches/ipp-20230313
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20230313/psModules/src/objects/pmSource.c

    r40810 r42439  
    456456            }
    457457
     458            // skip sources associated with possible detector features
     459            if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue;
     460
    458461            float Mxx = source->moments->Mxx, Myy = source->moments->Myy; // Second moments
    459462            float ar = Mxx / Myy;       // Radius
     
    752755                continue;
    753756            }
     757
     758            // skip sources associated with possible detector features
     759            if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue;
    754760
    755761            // the rest are probable stellar objects
  • branches/eam_branches/ipp-20230313/psphot/src/psphot.h

    r42435 r42439  
    592592extern bool psphotINpsphotStack;
    593593
    594 bool psphotFindFeatures (psArray *sources);
     594bool psphotFindFeatures (pmReadout *readout, psArray *sources);
    595595
    596596
  • branches/eam_branches/ipp-20230313/psphot/src/psphotFindFeatures.c

    r42435 r42439  
    11# include "psphotInternal.h"
     2
     3/* Use Hough transform to detect strong linear features (e.g., satellite trails) in the image.
     4   Sources which are plausibly associated with the feature are marked in the MODE2 bits.  These
     5   sources are excluded from the analysis of the moments and selection of the PSF stars.
     6   Weaknesses:
     7   - the angular samples and the length bins are hard-wired at 1 degree x 10 pixels.
     8   - the minimum significance in the Hough image and the minimum number of sources associated
     9     with the feature are hard-wired.
     10   - the distance of a source from the feature is only calculated in 1D.  The code is not careful
     11     about the center of the linear feature compared to the edges of the bin.
     12   - the features detected in the Hough transform are used to select sources which are then
     13     fitted to a line.  The line is used to select sources again and re-fit.  Only two steps
     14     are rigidly defined without a clear iteration end criterion.
     15
     16 */
    217
    318# define DCOS(THETA) cos(THETA*PS_RAD_DEG)
     
    2439bool psphotFindFeatures_HoughSigma (psphotFindFeatures_HoughInfo *myHough);
    2540float psphotFindFeatures_LineLength (float radius, float theta, int *edges, int NXpix, int NYpix);
     41int psphotFindFeatures_PeaksOnTrail (psArray *sources, float theta, float radius, float Rdel);
     42bool psphotFindFeatures_HoughFree (psphotFindFeatures_HoughInfo *myHough);
    2643
    2744bool psphotSavePeaks (char *filename, psArray *sources) {
     
    3855}
    3956
     57bool psphotSavePoints (char *filename, psVector *x, psVector *y) {
     58
     59    FILE *ftest = fopen (filename, "w");
     60    for (int i = 0; i < x->n; i++) {
     61        fprintf (ftest, "%f %f\n", x->data.F32[i], y->data.F32[i]);
     62    }
     63    fclose (ftest);
     64    return true;
     65}
     66
    4067// examine the x,y distribution of the sources and attempt to find sources which are due to
    4168// specific finds of features.  For example, a bunch of detections in a line could be a
    4269// satellite and should not be used for PSF modeling
    4370
    44 bool psphotFindFeatures (psArray *sources) {
     71bool psphotFindFeatures (pmReadout *readout, psArray *sources) {
    4572   
    4673    psphotFindFeatures_HoughInfo myHough;
    4774   
     75    int NXpix = readout->image->numCols;
     76    int NYpix = readout->image->numRows;
     77
    4878    // calculate the Hough transform for the source positions
    49     psphotFindFeatures_HoughInit (&myHough, 5000, 5000, 10.0);
    50     psphotSaveImage (NULL, myHough.fArea, "hough.fr.fits");
     79    psphotFindFeatures_HoughInit (&myHough, NXpix, NYpix, 10.0);
    5180   
    5281    // generate the hough transform for the collection of sources
     
    83112            float theta  = line->x;
    84113            float radius = line->y*myHough.Rdel + myHough.Rmin;
    85             fprintf (stderr, "trail %d : %f %f (%f : %f)\n", i, theta, radius, hough, nsigma);
    86 
    87             float cosTheta = DCOS(theta);
    88             float sinTheta = DSIN(theta);
    89 
    90             int nPeaksOnThisTrail = 0;
    91 
    92             // mark all sources within myHough->Rdel pix of this line
    93             // I should probably calculate the distance from the line in 2D perpendicular direction
    94             // NOTE: I am marking the sources on this trail, but if it does not have enough
    95             // matches, it is not counted as a real peak.
    96             for (int j = 0; j < sources->n; j++) {
    97                 pmSource *source = sources->data[j];
    98                 if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue; // ignore sources already found
    99 
    100                 pmPeak *peak = source->peak;
    101                 if ((theta > 45) && (theta < 135)) {
    102                     float yLine = (radius - peak->x*cosTheta) / sinTheta;
    103                     if (fabs(peak->y - yLine) < myHough.Rdel) {
    104                         source->mode2 |= PM_SOURCE_MODE2_ON_LINE;
    105                         nPeaksOnThisTrail ++;
    106                     }
    107                 } else {
    108                     float xLine = (radius - peak->y*sinTheta) / cosTheta;
    109                     if (fabs(peak->x - xLine) < myHough.Rdel) {
    110                         source->mode2 |= PM_SOURCE_MODE2_ON_LINE;
    111                         nPeaksOnThisTrail ++;
    112                     }
    113                 }
    114             }
    115            
     114            psLogMsg ("psphot", PS_LOG_INFO, "trail %d : %f %f (%f : %f)\n", i, theta, radius, hough, nsigma);
     115
     116            int nPeaksOnThisTrail = psphotFindFeatures_PeaksOnTrail (sources, theta, radius, myHough.Rdel);
     117
    116118            if (nPeaksOnThisTrail < HOUGH_MIN_SOURCES) continue;
    117119
     
    123125        psFree (lines);
    124126    }
    125     fprintf (stderr, "found %d peaks in %d trails\n", nPeaksOnTrails, nTrails);
    126     psphotSavePeaks ("test.peaks.dat", sources);
    127 
     127    psphotFindFeatures_HoughFree (&myHough);
     128    psLogMsg ("psphot", PS_LOG_INFO, "found %d peaks in %d trails\n", nPeaksOnTrails, nTrails);
     129
     130    return true;
     131}
     132
     133bool psphotFindFeatures_HoughFree (psphotFindFeatures_HoughInfo *myHough) {
     134
     135    psFree (myHough->fArea);
     136    psFree (myHough->image);
     137    psFree (myHough->sigma);
    128138    return true;
    129139}
     
    221231    }
    222232    return true;
     233}
     234
     235// mark all sources within myHough->Rdel pix of this line
     236// I should probably calculate the distance from the line in 2D perpendicular direction
     237// NOTE: I am marking the sources on this trail, but if it does not have enough
     238// matches, it is not counted as a real peak.
     239
     240int psphotFindFeatures_PeaksOnTrail (psArray *sources, float theta, float radius, float Rdel) {
     241
     242    float cosTheta = DCOS(theta);
     243    float sinTheta = DSIN(theta);
     244
     245    // find sources in the line and fit to 1D polynomial
     246    psVector *xpos = psVectorAllocEmpty (100, PS_TYPE_F32);
     247    psVector *ypos = psVectorAllocEmpty (100, PS_TYPE_F32);
     248    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 1);
     249
     250    // if the angle is shallow, use image (x,y), otherwise use image (y,x)
     251    bool noFlip = !((theta > 45) && (theta < 135));
     252
     253    // select only sources close to the line
     254    for (int j = 0; j < sources->n; j++) {
     255        pmSource *source = sources->data[j];
     256        if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue; // ignore sources already found
     257
     258        pmPeak *peak = source->peak;
     259        if (noFlip) {
     260            float yLine = (radius - peak->x*cosTheta) / sinTheta;
     261            if (fabs(peak->y - yLine) > Rdel) continue;
     262            psVectorAppend (xpos, peak->xf);
     263            psVectorAppend (ypos, peak->yf);
     264        } else {
     265            float xLine = (radius - peak->y*sinTheta) / cosTheta;
     266            if (fabs(peak->x - xLine) > Rdel) continue;
     267            psVectorAppend (xpos, peak->yf);
     268            psVectorAppend (ypos, peak->xf);
     269        }
     270    }
     271    if (xpos->n < HOUGH_MIN_SOURCES) goto escape;
     272
     273    // fit the line
     274    if (!psVectorFitPolynomial1D (poly, NULL, 0, ypos, NULL, xpos)) {
     275        psError(PS_ERR_UNKNOWN, true, "Failed to find a good trail fit");
     276        goto escape;
     277    }
     278
     279    // reset vector lengths
     280    xpos->n = 0;
     281    ypos->n = 0;
     282
     283    // select sources close to the line and refit
     284    // select only sources close to the line
     285    for (int j = 0; j < sources->n; j++) {
     286        pmSource *source = sources->data[j];
     287        if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue; // ignore sources already found
     288
     289        pmPeak *peak = source->peak;
     290        if (noFlip) {
     291            float yLine = psPolynomial1DEval (poly, peak->x);
     292            if (fabs(peak->y - yLine) > Rdel) continue;
     293            psVectorAppend (xpos, peak->xf);
     294            psVectorAppend (ypos, peak->yf);
     295        } else {
     296            float xLine = psPolynomial1DEval (poly, peak->y);
     297            if (fabs(peak->x - xLine) > Rdel) continue;
     298            psVectorAppend (xpos, peak->yf);
     299            psVectorAppend (ypos, peak->xf);
     300        }
     301    }
     302    if (xpos->n < HOUGH_MIN_SOURCES) goto escape;
     303
     304    if (!psVectorFitPolynomial1D (poly, NULL, 0, ypos, NULL, xpos)) {
     305        psError(PS_ERR_UNKNOWN, true, "Failed to find a good trail fit");
     306        goto escape;
     307    }
     308
     309    // mark sources close to the line
     310    int nPeaksOnThisTrail = 0;
     311    for (int j = 0; j < sources->n; j++) {
     312        pmSource *source = sources->data[j];
     313        if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue; // ignore sources already found
     314
     315        pmPeak *peak = source->peak;
     316        if (noFlip) {
     317            float yLine = psPolynomial1DEval (poly, peak->x);
     318            if (fabs(peak->y - yLine) > Rdel) continue;
     319        } else {
     320            float xLine = psPolynomial1DEval (poly, peak->y);
     321            if (fabs(peak->x - xLine) > Rdel) continue;
     322        }
     323        source->mode2 |= PM_SOURCE_MODE2_ON_LINE;
     324        nPeaksOnThisTrail ++;
     325    }
     326    if (nPeaksOnThisTrail < HOUGH_MIN_SOURCES) goto escape;
     327
     328    psFree (xpos);
     329    psFree (ypos);
     330    psFree (poly);
     331    return nPeaksOnThisTrail;
     332
     333escape:
     334    psFree (xpos);
     335    psFree (ypos);
     336    psFree (poly);
     337    return false;
    223338}
    224339
     
    320435    return 0.0;
    321436}
    322 
    323 
    324 /*
    325   x = (radius - y*sinTheta) / cosTheta;
    326   y = (radius - x*cosTheta) / sinTheta;
    327 */
    328 
    329 /*
    330     // find peaks in this image
    331     // what is a statistically significant peak?
    332     psStats *stats = psStatsAlloc (PS_STAT_MAX | PS_STAT_SAMPLE_STDEV);
    333     if (!psImageStats (stats, HoughImage, NULL, 0)) {
    334         psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
    335         psFree(stats);
    336         psFree(HoughImage);
    337         return false;
    338     }
    339 */
    340 
    341 /*
    342         int nTrails = 0;
    343         for (int iLine = 0; iLine < lines->n; iLine++) {
    344             pmPeak *line = lines->data[iLine];
    345             float theta  = line->x;
    346             float radius = line->y*Rdel + Rmin;
    347 
    348             float hough = HoughImage->data.F32[line->y][line->x];
    349             float sigma = HoughSigma->data.F32[line->y][line->x];
    350             fprintf (stderr, "trail %d : %f %f (%f : %f)\n", iLine, theta, radius, hough, sigma);
    351 
    352             float cosTheta = DCOS(theta);
    353             float sinTheta = DSIN(theta);
    354 
    355             // XXX I can probably calculate the distance from the line in a more exact fashion...
    356             for (int i = 0; i < sources->n; i++) {
    357                 pmSource *source = sources->data[i];
    358                 pmPeak *peak = source->peak;
    359                 if ((theta > 45) && (theta < 135)) {
    360                     float yLine = (radius - peak->x*cosTheta) / sinTheta;
    361                     if (fabs(peak->y - yLine) < 10.0) {
    362                         source->mode2 |= PM_SOURCE_MODE2_ON_LINE;
    363                         nTrails ++;
    364                     }
    365                 } else {
    366                     float xLine = (radius - peak->y*sinTheta) / cosTheta;
    367                     if (fabs(peak->x - xLine) < 10.0) {
    368                         source->mode2 |= PM_SOURCE_MODE2_ON_LINE;
    369                         nTrails ++;
    370                     }
    371                 }
    372             }
    373         }
    374 */
  • branches/eam_branches/ipp-20230313/psphot/src/psphotSourceStats.c

    r42435 r42439  
    144144    }
    145145
    146     // XXX I want to identify sources which are on lines.  these can be excluded from
    147     // the Moments and PSF analysis
    148 
    149     psphotFindFeatures (sources);
    150 
    151146    if (setWindow) {
     147        // identify sources on lines, drop from MomentsWindow analysis
     148        psphotFindFeatures (readout, sources);
     149
    152150        if (!psphotSetMomentsWindow(recipe, readout->analysis, sources, maskVal)) {
    153151            psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
Note: See TracChangeset for help on using the changeset viewer.