23"""Select sources that are useful for astrometry.
25Such sources have good signal-to-noise, are well centroided, not blended,
26and not flagged with a handful of "bad" flags.
29__all__ = [
"AstrometrySourceSelectorConfig",
"AstrometrySourceSelectorTask"]
34from .sourceSelector
import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
36from functools
import reduce
40 badFlags = pexConfig.ListField(
41 doc=
"List of flags which cause a source to be rejected as bad",
44 "base_PixelFlags_flag_edge",
45 "base_PixelFlags_flag_interpolatedCenter",
46 "base_PixelFlags_flag_saturatedCenter",
47 "base_PixelFlags_flag_crCenter",
48 "base_PixelFlags_flag_bad",
51 sourceFluxType = pexConfig.Field(
52 doc=
"Type of source flux; typically one of Ap or Psf",
56 minSnr = pexConfig.Field(
58 doc=
"Minimum allowed signal-to-noise ratio for sources used for matching "
59 "(in the flux specified by sourceFluxType); <= 0 for no limit",
64@pexConfig.registerConfigurable("astrometry", sourceSelectorRegistry)
66 """Select sources that are useful for astrometry.
68 Good astrometry sources have high signal/noise, are non-blended, and
69 did
not have certain
"bad" flags set during source extraction. They need
not
70 be PSF sources, just have reliable centroids.
72 ConfigClass = AstrometrySourceSelectorConfig
75 BaseSourceSelectorTask.__init__(self, *args, **kwargs)
78 """Return a selection of sources that are useful for astrometry.
83 Catalog of sources to select from.
84 This catalog must be contiguous
in memory.
86 Ignored
in this SourceSelector.
88 The exposure the catalog was built
from; used
for debug display.
92 struct : `lsst.pipe.base.Struct`
93 The struct contains the following data:
96 Boolean array of sources that were selected, same length
as
97 sourceCat. (`numpy.ndarray` of `bool`)
101 bad = reduce(lambda x, y: np.logical_or(x, sourceCat.get(y)), self.config.badFlags,
False)
103 return Struct(selected=good & ~bad)
106 """Extract and save the necessary keys from schema with asKey.
116 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
120 fluxPrefix =
"slot_%sFlux_" % (self.config.sourceFluxType,)
126 """Return True for each source that is likely multiple sources.
130 for i, cat
in enumerate(sourceCat):
131 footprint = cat.getFootprint()
132 test[i] |= (footprint
is not None)
and (len(footprint.getPeaks()) > 1)
136 """Return True for each source that has a valid centroid
138 def checkNonfiniteCentroid():
139 """Return True for sources with non-finite centroids.
141 return ~np.isfinite(sourceCat.get(self.
centroidXKey)) | \
143 assert ~checkNonfiniteCentroid().any(), \
144 "Centroids not finite for %d unflagged sources." % (checkNonfiniteCentroid().sum())
150 """Return True for each source that has Signal/Noise > config.minSnr.
152 if self.config.minSnr <= 0:
155 with np.errstate(invalid=
"ignore"):
159 """Return True for each source that is usable for matching, even if it may
160 have a poor centroid.
162 For a source to be usable it must:
163 - have a valid centroid
165 - have a valid flux (of the type specified
in this object
's constructor)
166 - have adequate signal-to-noise
175 """Return True for each source that is usable for matching and likely has a
178 The additional tests for a good centroid, beyond isUsable, are:
179 -
not interpolated
in the center
190 """Return True if any of config.badFlags are set for this source.
192 return any(source.get(flag)
for flag
in self.config.badFlags)
def _hasCentroid(self, sourceCat)
def _isUsable(self, sourceCat)
def __init__(self, *args, **kwargs)
def selectSources(self, sourceCat, matches=None, exposure=None)
def _isMultiple(self, sourceCat)
def _isBadFlagged(self, source)
def _isGood(self, sourceCat)
def _getSchemaKeys(self, schema)
def _goodSN(self, sourceCat)