23 from __future__
import absolute_import, division, print_function
28 import lsst.pex.config
as pexConfig
29 from .sourceSelector
import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
30 from lsst.pipe.base
import Struct
31 from functools
import reduce
35 sourceFluxType = pexConfig.Field(
36 doc=
"Type of source flux; typically one of Ap or Psf",
40 minSnr = pexConfig.Field(
42 doc=
"Minimum allowed signal-to-noise ratio for sources used for matching "
43 "(in the flux specified by sourceFluxType); <= 0 for no limit",
50 !Select sources that are useful for matching.
52 Good matching sources have high signal/noise, are non-blended. They need not
53 be PSF sources, just have reliable centroids.
55 ConfigClass = MatcherSourceSelectorConfig
58 BaseSourceSelectorTask.__init__(self, *args, **kwargs)
62 !Return a catalog of sources: a subset of sourceCat.
64 If sourceCat is cotiguous in memory, will use vectorized tests for ~100x
65 execution speed advantage over non-contiguous catalogs. This would be
66 even faster if we didn't have to check footprints for multiple peaks.
68 @param[in] sourceCat catalog of sources that may be sources
69 (an lsst.afw.table.SourceCatalog)
71 @return a pipeBase.Struct containing:
72 - sourceCat a catalog of sources
76 if sourceCat.isContiguous():
78 result = sourceCat[good]
80 result = table.SourceCatalog(sourceCat.table)
81 for i, source
in enumerate(sourceCat):
84 return Struct(sourceCat=result)
86 def _getSchemaKeys(self, schema):
87 """Extract and save the necessary keys from schema with asKey."""
93 fluxPrefix =
"slot_%sFlux_" % (self.config.sourceFluxType,)
95 self.
fluxKey = schema[fluxPrefix +
"flux"].asKey()
99 def _isParent_vector(self, sourceCat):
100 """Return True for each source that is the parent source."""
101 test = (sourceCat.get(self.
parentKey) == 0)
104 def _isParent(self, source):
105 """Return True if source is the parent source."""
110 def _hasCentroid_vector(self, sourceCat):
111 """Return True for each source that has a valid centroid"""
116 def _hasCentroid(self, source):
117 """Return True if the source has a valid centroid"""
118 centroid = source.getCentroid()
119 return np.all(np.isfinite(centroid))
and not source.getCentroidFlag()
121 def _goodSN_vector(self, sourceCat):
122 """Return True for each source that has Signal/Noise > config.minSnr."""
123 if self.config.minSnr <= 0:
128 def _goodSN(self, source):
129 """Return True if source has Signal/Noise > config.minSnr."""
130 return (self.config.minSnr <= 0
or
133 def _isUsable_vector(self, sourceCat):
135 Return True for each source that is usable for matching, even if it may
136 have a poor centroid.
138 For a source to be usable it must:
139 - have a valid centroid
141 - have a valid flux (of the type specified in this object's constructor)
142 - have adequate signal-to-noise
149 def _isUsable(self, source):
151 Return True if the source is usable for matching, even if it may have a
154 For a source to be usable it must:
155 - have a valid centroid
157 - have a valid flux (of the type specified in this object's constructor)
158 - have adequate signal-to-noise
168 !Select sources that are useful for matching.
170 Good matching sources have high signal/noise, are non-blended. They need not
171 be PSF sources, just have reliable centroids. This inherited class adds
172 the removal of saturated, interpolated, and edge_key objects to the set of
173 bad flags. It is a temporary addition designed preserve the source selction
174 used in matchOptimisticB. Once matchPessimisticB is adopted as the default
175 source selector the class will be removed and the saturated, interpoalted, and
176 edge_key flags will be added to the matcherSourceSelector class.
178 TODO: Once DM-10399 is complete an RFC will be filed to make matchPessimisticB
179 the default matcher this class will replace matcherSourceSelector with this source
180 selector resulting in only one matcherSourceSeletor. The ticket describing
181 this work is DM-10800.
183 def _getSchemaKeys(self, schema):
184 """Extract and save the necessary keys from schema with asKey."""
185 MatcherSourceSelectorTask._getSchemaKeys(self, schema)
187 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
191 def _isUsable_vector(self, sourceCat):
193 Return True for each source that is usable for matching, even if it may
194 have a poor centroid.
196 For a source to be usable it must:
197 - have a valid centroid
199 - have a valid flux (of the type specified in this object's constructor)
200 - have adequate signal-to-noise
202 result = MatcherSourceSelectorTask._isUsable_vector(self, sourceCat)
205 & ~sourceCat.get(self.
edgeKey) \
209 def _isUsable(self, source):
211 Return True if the source is usable for matching, even if it may have a
214 For a source to be usable it must:
215 - have a valid centroid
217 - have a valid flux (of the type specified in this object's constructor)
218 - have adequate signal-to-noise
220 result = MatcherSourceSelectorTask._isUsable(self, source)
223 and not source.get(self.
edgeKey) \
228 sourceSelectorRegistry.register(
"matcher", MatcherSourceSelectorTask)
229 sourceSelectorRegistry.register(
"matcherPessimistic",
230 MatcherPessimisticSourceSelectorTask)