24 __all__ = [
"MatcherSourceSelectorConfig",
"MatcherSourceSelectorTask"]
29 from .sourceSelector
import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
30 from lsst.pipe.base
import Struct
34 sourceFluxType = pexConfig.Field(
35 doc=
"Type of source flux; typically one of Ap or Psf",
39 minSnr = pexConfig.Field(
41 doc=
"Minimum allowed signal-to-noise ratio for sources used for matching "
42 "(in the flux specified by sourceFluxType); <= 0 for no limit",
45 excludePixelFlags = pexConfig.Field(
47 doc=
"Exclude objects that have saturated, interpolated, or edge "
48 "pixels using PixelFlags. For matchOptimisticB set this to False "
49 "to recover previous matcher selector behavior.",
54 @pexConfig.registerConfigurable("matcher", sourceSelectorRegistry)
56 """Select sources that are useful for matching.
58 Good matching sources have high signal/noise, are non-blended. They need not
59 be PSF sources, just have reliable centroids.
61 Distinguished from astrometrySourceSelector because it is more lenient
62 (i.e. not checking footprints or bad flags).
64 ConfigClass = MatcherSourceSelectorConfig
67 BaseSourceSelectorTask.__init__(self, *args, **kwargs)
70 """Return a selection of sources that are useful for matching.
74 sourceCat : `lsst.afw.table.SourceCatalog`
75 Catalog of sources to select from.
76 This catalog must be contiguous in memory.
77 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
78 Ignored in this SourceSelector.
79 exposure : `lsst.afw.image.Exposure` or None
80 The exposure the catalog was built from; used for debug display.
84 struct : `lsst.pipe.base.Struct`
85 The struct contains the following data:
87 - selected : `array` of `bool``
88 Boolean array of sources that were selected, same length as
94 if self.config.excludePixelFlags:
95 good = good & self.
_isGood_isGood(sourceCat)
96 return Struct(selected=good)
98 def _getSchemaKeys(self, schema):
99 """Extract and save the necessary keys from schema with asKey.
106 fluxPrefix =
"slot_%sFlux_" % (self.config.sourceFluxType,)
108 self.
fluxKeyfluxKey = schema[fluxPrefix +
"instFlux"].asKey()
110 self.
fluxErrKeyfluxErrKey = schema[fluxPrefix +
"instFluxErr"].asKey()
112 self.
edgeKeyedgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
114 self.
saturatedKeysaturatedKey = schema[
"base_PixelFlags_flag_saturated"].asKey()
116 def _isParent(self, sourceCat):
117 """Return True for each source that is the parent source.
119 test = (sourceCat.get(self.
parentKeyparentKey) == 0)
122 def _hasCentroid(self, sourceCat):
123 """Return True for each source that has a valid centroid
125 return np.isfinite(sourceCat.get(self.
centroidXKeycentroidXKey)) \
126 & np.isfinite(sourceCat.get(self.
centroidYKeycentroidYKey)) \
129 def _goodSN(self, sourceCat):
130 """Return True for each source that has Signal/Noise > config.minSnr.
132 if self.config.minSnr <= 0:
135 with np.errstate(invalid=
"ignore"):
136 return sourceCat.get(self.
fluxKeyfluxKey)/sourceCat.get(self.
fluxErrKeyfluxErrKey) > self.config.minSnr
138 def _isUsable(self, sourceCat):
140 Return True for each source that is usable for matching, even if it may
141 have a poor centroid.
143 For a source to be usable it must:
144 - have a valid centroid
146 - have a valid instFlux (of the type specified in this object's constructor)
147 - have adequate signal-to-noise
151 & self.
_goodSN_goodSN(sourceCat) \
154 def _isGood(self, sourceCat):
156 Return True for each source that is usable for matching, even if it may
157 have a poor centroid.
159 For a source to be usable it must:
160 - Not be on a CCD edge.
161 - Not have an interpolated pixel within 3x3 around their centroid.
162 - Not have a saturated pixel in their footprint.
164 return ~sourceCat.get(self.
edgeKeyedgeKey) & \
def selectSources(self, sourceCat, matches=None, exposure=None)
def _goodSN(self, sourceCat)
def _hasCentroid(self, sourceCat)
def __init__(self, *args, **kwargs)
def _isParent(self, sourceCat)
def _getSchemaKeys(self, schema)
def _isGood(self, sourceCat)
def _isUsable(self, sourceCat)