IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42843 for trunk/psModules


Ignore:
Timestamp:
May 9, 2025, 11:28:49 AM (12 months ago)
Author:
eugene
Message:

optionally allow PSF star positions to be fitted during PSF model construction (default false); option to allow PSF clump analysis to use clipped stats (default) or robust stats; use select circular region of 2nd moment space, not square region; for bright (S/N > 25) externally-supplied sources, use the centroid (Mx,My) value instead of the peak

Location:
trunk/psModules
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules

  • trunk/psModules/src/objects/pmPSF.h

    r36858 r42843  
    7979    bool          poissonErrorsParams; ///< use poission errors for model parameter fitting
    8080
     81    bool          fitPSFstarCoords; // Allow the PSF star positions to fit in the full fit? (pmPSFtryFitEXT)
    8182    bool          chiFluxTrend;         // Fit a trend in Chi2 as a function of flux?
    8283    pmSourceFitOptions *fitOptions;
  • trunk/psModules/src/objects/pmPSFtryFitEXT.c

    r36856 r42843  
    7373
    7474    // in this segment, we are fitting the full PSF model class (shape unconstrained)
    75     options->fitOptions->mode = PM_SOURCE_FIT_EXT;
    76 
     75    if (options->fitPSFstarCoords) {
     76      options->fitOptions->mode = PM_SOURCE_FIT_FULL;
     77    } else {
     78      options->fitOptions->mode = PM_SOURCE_FIT_EXT;
     79    }
    7780    // maskVal is used to test for rejected pixels, and must include markVal
    7881    maskVal |= markVal;
  • trunk/psModules/src/objects/pmSource.c

    r40810 r42843  
    407407*****************************************************************************/
    408408
    409 pmPSFClump pmSourcePSFClump(psImage **savedImage, psRegion *region, psArray *sources, float PSF_SN_LIM, float PSF_CLUMP_GRID_SCALE, psF32 SX_MAX, psF32 SY_MAX, psF32 SX_MIN, psF32 SY_MIN, psF32 AR_MAX)
     409pmPSFClump pmSourcePSFClump(psImage **savedImage, psRegion *region, psArray *sources, float PSF_SN_LIM, float PSF_CLUMP_GRID_SCALE, psF32 SX_MAX, psF32 SY_MAX, psF32 SX_MIN, psF32 SY_MIN, psF32 AR_MAX, bool useClippedMean)
    410410{
    411411    psTrace("psModules.objects", 10, "---- begin ----\n");
     
    455455                continue;
    456456            }
     457
     458            // skip sources associated with possible detector features
     459            if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue;
    457460
    458461            float Mxx = source->moments->Mxx, Myy = source->moments->Myy; // Second moments
     
    598601        }
    599602
    600         // measures stats of Sx, Sy
    601         stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
    602 
    603         if (!psVectorStats (stats, tmpSx, NULL, NULL, 0)) {
    604             psError(PS_ERR_UNKNOWN, false, "failed to measure Sx stats");
    605             return (emptyClump);
    606         }
    607         psfClump.X  = stats->clippedMean;
    608         psfClump.dX = hypot(stats->clippedStdev, PSF_CLUMP_GRID_SCALE);
    609 
    610         if (!psVectorStats (stats, tmpSy, NULL, NULL, 0)) {
    611             psError(PS_ERR_UNKNOWN, false, "failed to measure Sy stats");
    612             return (emptyClump);
    613         }
    614         psfClump.Y  = stats->clippedMean;
    615         psfClump.dY = hypot(stats->clippedStdev, PSF_CLUMP_GRID_SCALE);
     603        // measures stats of Sx, Sy
     604        if (useClippedMean) {
     605          stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
     606        } else {
     607          stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
     608        }
     609
     610        if (!psVectorStats (stats, tmpSx, NULL, NULL, 0)) {
     611          psError(PS_ERR_UNKNOWN, false, "failed to measure Sx stats");
     612          return (emptyClump);
     613        }
     614        psfClump.X  = psStatsGetValue (stats, psStatsMeanOption (stats->options));
     615        psfClump.dX = psStatsGetValue (stats, psStatsStdevOption (stats->options));
     616        psfClump.dX = hypot(psfClump.dX, PSF_CLUMP_GRID_SCALE);
     617
     618        if (!psVectorStats (stats, tmpSy, NULL, NULL, 0)) {
     619          psError(PS_ERR_UNKNOWN, false, "failed to measure Sy stats");
     620          return (emptyClump);
     621        }
     622        psfClump.Y  = psStatsGetValue (stats, psStatsMeanOption (stats->options));
     623        psfClump.dY = psStatsGetValue (stats, psStatsStdevOption (stats->options));
     624        psfClump.dY = hypot(psfClump.dX, PSF_CLUMP_GRID_SCALE);             
    616625
    617626        psTrace ("psModules.objects", 2, "clump  X,  Y: %f, %f\n", psfClump.X, psfClump.Y);
     
    746755            }
    747756
     757            psF32 radius = hypot ((sigX-clump.X)/clump.dX, (sigY-clump.Y)/clump.dY);
     758
     759            // XXX this is crude cut to avoid using extended sources in the PSF model
     760            // psphot will update this analysis based on the PSF - Kron mags
    748761            // likely unsaturated extended source (too large to be stellar)
    749             if (sigX > clump.X + 3*clump.dX || sigY > clump.Y + 3*clump.dY) {
     762            // XXX old test: if (sigX > clump.X + 3*clump.dX || sigY > clump.Y + 3*clump.dY) {
     763
     764            if (radius > 2.0) {
    750765                source->type = PM_SOURCE_TYPE_EXTENDED;
    751766                Next ++;
    752767                continue;
    753768            }
     769
     770            // skip sources associated with possible detector features
     771            if (source->mode2 & PM_SOURCE_MODE2_ON_LINE) continue;
    754772
    755773            // the rest are probable stellar objects
     
    762780
    763781            // PSF star (within 1.5 sigma of clump center, S/N > limit)
    764             psF32 radius = hypot ((sigX-clump.X)/clump.dX, (sigY-clump.Y)/clump.dY);
    765782            if ((source->moments->SN > PSF_SN_LIM) && (radius < PSF_CLUMP_NSIGMA)) {
    766783                source->type = PM_SOURCE_TYPE_STAR;
  • trunk/psModules/src/objects/pmSource.h

    r37321 r42843  
    245245    psF32 SX_MIN,
    246246    psF32 SY_MIN,
    247     psF32 AR_MAX
     247    psF32 AR_MAX,
     248    bool useClippedMean                 ///< use clipped mean & stdev to define clump, else robust
    248249);
    249250
  • trunk/psModules/src/objects/pmSourceFitModel.c

    r42093 r42843  
    189189        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_XPOS] = 0;
    190190        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 0;
     191        break;
     192      case PM_SOURCE_FIT_FULL:
     193        // PSFstar Full model fits all shape params and Xo, Yo, Io (not sky)
     194        nParams = params->n - 1;
     195        psVectorInit (constraint->paramMask, 0);
     196        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    191197        break;
    192198      case PM_SOURCE_FIT_EXT:
     
    270276    model->nPar = nParams;
    271277
    272     psTrace ("psModules.objects", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);
     278    psTrace ("psModules.objects", 4, "niter: %d, chisq: %f, status: %d", myMin->iter, myMin->value, fitStatus);
    273279
    274280    // save the resulting chisq, nDOF, nIter
  • trunk/psModules/src/objects/pmSourceFitModel.h

    r42093 r42843  
    1818    PM_SOURCE_FIT_PSF,
    1919    PM_SOURCE_FIT_EXT,
     20    PM_SOURCE_FIT_FULL,
    2021    PM_SOURCE_FIT_PSF_AND_SKY,
    2122    PM_SOURCE_FIT_EXT_AND_SKY,
  • trunk/psModules/src/objects/pmSourceMasks.h

    r42293 r42843  
    4747    PM_SOURCE_MODE2_MATCHED               = 0x00000004, ///< source generated based on another image
    4848    PM_SOURCE_MODE2_ON_SPIKE              = 0x00000008, ///< > 25% of (PSF-weighted) pixels land on diffraction spike
     49
    4950    PM_SOURCE_MODE2_ON_STARCORE           = 0x00000010, ///< > 25% of (PSF-weighted) pixels land on starcore
    5051    PM_SOURCE_MODE2_ON_BURNTOOL           = 0x00000020, ///< > 25% of (PSF-weighted) pixels land on burntool
    5152    PM_SOURCE_MODE2_ON_CONVPOOR           = 0x00000040, ///< > 25% of (PSF-weighted) pixels land on convpoor
    5253    PM_SOURCE_MODE2_PASS1_SRC             = 0x00000080, ///< source detected in first pass analysis
     54
    5355    PM_SOURCE_MODE2_HAS_BRIGHTER_NEIGHBOR = 0x00000100, ///< peak is not the brightest in its footprint
    5456    PM_SOURCE_MODE2_BRIGHT_NEIGHBOR_1     = 0x00000200, ///< flux_n / (r^2 flux_p) > 1
    5557    PM_SOURCE_MODE2_BRIGHT_NEIGHBOR_10    = 0x00000400, ///< flux_n / (r^2 flux_p) > 10
    5658    PM_SOURCE_MODE2_DIFF_SELF_MATCH       = 0x00000800, ///< positive detection match is probably this source
     59
    5760    PM_SOURCE_MODE2_SATSTAR_PROFILE       = 0x00001000, ///< saturated source is modeled with a radial profile
    58 
    5961    PM_SOURCE_MODE2_ECONTOUR_FEW_PTS      = 0x00002000, ///< too few points to measure the elliptical contour
    6062    PM_SOURCE_MODE2_RADBIN_NAN_CENTER     = 0x00004000, ///< radial bins failed with too many NaN center bin
    6163    PM_SOURCE_MODE2_PETRO_NAN_CENTER      = 0x00008000, ///< petrosian radial bins failed with too many NaN center bin
     64
    6265    PM_SOURCE_MODE2_PETRO_NO_PROFILE      = 0x00010000, ///< petrosian not build because radial bins missing
    63 
    6466    PM_SOURCE_MODE2_PETRO_INSIG_RATIO     = 0x00020000, ///< insignificant measurement of petrosian ratio
    6567    PM_SOURCE_MODE2_PETRO_RATIO_ZEROBIN   = 0x00040000, ///< petrosian ratio in the 0th bin (likely bad)
    66    
    6768    PM_SOURCE_MODE2_EXT_FITS_RUN          = 0x00080000, ///< we attempted to run extended fits on this source
     69
    6870    PM_SOURCE_MODE2_EXT_FITS_FAIL         = 0x00100000, ///< at least one of the model fits failed
    6971    PM_SOURCE_MODE2_EXT_FITS_RETRY        = 0x00200000, ///< one of the model fits was re-tried with new window
    7072    PM_SOURCE_MODE2_EXT_FITS_NONE         = 0x00400000, ///< ALL of the model fits failed
    71    
    7273    PM_SOURCE_MODE2_ON_GHOST              = 0x00800000, ///< > 25% of (PSF-weighted) pixels land on ghost
     74
    7375    PM_SOURCE_MODE2_ON_CROSSTALK          = 0x01000000, ///< peaks land on electronic crostalk
    7476    PM_SOURCE_MODE2_ON_CTE                = 0x02000000, ///< peaks land on CTE region
     77    PM_SOURCE_MODE2_ON_LINE               = 0x04000000, ///< peaks land on Linear feature
    7578
    7679   
  • trunk/psModules/src/objects/pmSourceMoments.c

    r42484 r42843  
    231231    }
    232232
    233     // we only update the centroid if the position is not supplied from elsewhere
     233    // For faint externally-supplied sources, the centroids are unreliable.
     234    // In those cases, we should keep the peak position instead of the centroid position.
    234235    bool skipCentroid = false;
    235236    skipCentroid |= (source->mode  & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions
     
    245246    }
    246247
    247     // only skip negative sum sources if the sources are not forced
     248    // Skip negative-sum sources, but only if the sources are not forced (externally supplied)
    248249    if (!skipCentroid && (Sum <= 0)) {
    249250        psTrace ("psModules.objects", 3, "insufficient significant pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum);
     
    259260    psTrace ("psModules.objects", 5, "id: %d, sky: %f  Mx: %f  My: %f  Sum: %f  X1: %f  Y1: %f  Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels);
    260261
     262    // XXX EAM : I need to move this block so I can use SN to choose if we keep the centroids or not
     263    source->moments->Sum = Sum;
     264    source->moments->SN  = Sum / sqrt(Var);
     265    source->moments->Peak = peakPixel;
     266    source->moments->nPixels = numPixels;
     267
    261268    // add back offset of peak in primary image
    262269    // also offset from pixel index to pixel coordinate
     
    264271    // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords
    265272
    266     if (skipCentroid) {
     273    // XXX for a test, do NOT skip the centroid for relatively strong sources, even if forced
     274    // XXX this is a somewhat arbitrary limit.  use PSF_SN_LIM (see below) instead?
     275    if (skipCentroid && (source->moments->SN < 25)) {
    267276        source->moments->Mx = source->peak->xf;
    268277        source->moments->My = source->peak->yf;
     
    270279        if ((fabs(Mx) > radius) || (fabs(My) > radius)) {
    271280            psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y);
     281
     282            // XXX should we really be rejecting these sources, or just keeping the peak position?
    272283            return (false);
     284
     285            source->moments->Mx = source->peak->xf;
     286            source->moments->My = source->peak->yf;
     287            return (true);
    273288        }
    274289        source->moments->Mx = Mx + xGuess;
    275290        source->moments->My = My + yGuess;
    276291    }
    277 
    278     source->moments->Sum = Sum;
    279     source->moments->SN  = Sum / sqrt(Var);
    280     source->moments->Peak = peakPixel;
    281     source->moments->nPixels = numPixels;
    282292
    283293    return true;
Note: See TracChangeset for help on using the changeset viewer.