28 from .sourceSelector
import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
30 from functools
import reduce
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",
49 !Select sources that are useful for astrometry. 51 Good astrometry sources have high signal/noise, are non-blended, and 52 did not have certain "bad" flags set during source extraction. They need not 53 be PSF sources, just have reliable centroids. 55 ConfigClass = AstrometrySourceSelectorConfig
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():
77 bad = reduce(
lambda x, y: np.logical_or(x, sourceCat.get(y)), self.config.badFlags,
False)
79 result = sourceCat[good & ~bad]
81 result = table.SourceCatalog(sourceCat.table)
82 for i, source
in enumerate(sourceCat):
85 return Struct(sourceCat=result)
87 def _getSchemaKeys(self, schema):
88 """Extract and save the necessary keys from schema with asKey.""" 97 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
99 self.
saturatedKey = schema[
"base_PixelFlags_flag_saturated"].asKey()
101 fluxPrefix =
"slot_%sFlux_" % (self.config.sourceFluxType,)
102 self.
fluxKey = schema[fluxPrefix +
"flux"].asKey()
106 def _isMultiple_vector(self, sourceCat):
107 """Return True for each source that is likely multiple sources.""" 110 for i, cat
in enumerate(sourceCat):
111 footprint = cat.getFootprint()
112 test[i] |= (footprint
is not None)
and (len(footprint.getPeaks()) > 1)
115 def _isMultiple(self, source):
116 """Return True if source is likely multiple sources.""" 119 footprint = source.getFootprint()
120 return footprint
is not None and len(footprint.getPeaks()) > 1
122 def _hasCentroid_vector(self, sourceCat):
123 """Return True for each source that has a valid centroid""" 124 def checkNonfiniteCentroid():
125 """Return True for sources with non-finite centroids.""" 126 return ~np.isfinite(sourceCat.get(self.
centroidXKey)) | \
128 assert ~checkNonfiniteCentroid().any(), \
129 "Centroids not finite for %d unflagged sources." % (checkNonfiniteCentroid().sum())
134 def _hasCentroid(self, source):
135 """Return True if the source has a valid centroid""" 136 assert np.all(np.isfinite(source.getCentroid())),
'Centroid not finite for source: %s' % source
137 return np.all(np.isfinite(source.getCentroidErr()))
and not source.getCentroidFlag()
139 def _goodSN_vector(self, sourceCat):
140 """Return True for each source that has Signal/Noise > config.minSnr.""" 141 if self.config.minSnr <= 0:
144 with np.errstate(invalid=
"ignore"):
147 def _goodSN(self, source):
148 """Return True if source has Signal/Noise > config.minSnr.""" 149 return (self.config.minSnr <= 0
or 152 def _isUsable_vector(self, sourceCat):
154 Return True for each source that is usable for matching, even if it may 155 have a poor centroid. 157 For a source to be usable it must: 158 - have a valid centroid 160 - have a valid flux (of the type specified in this object's constructor) 161 - have adequate signal-to-noise 169 def _isUsable(self, source):
171 Return True if the source is usable for matching, even if it may have a 174 For a source to be usable it must: 175 - have a valid centroid 177 - have a valid flux (of the type specified in this object's constructor) 178 - have adequate signal-to-noise 185 def _isGood_vector(self, sourceCat):
187 Return True for each source that is usable for matching and likely has a 190 The additional tests for a good centroid, beyond isUsable, are: 191 - not interpolated in the center 201 def _isGood(self, source):
203 Return True if source is usable for matching and likely has a good centroid. 205 The additional tests for a good centroid, beyond isUsable, are: 206 - not interpolated in the center 213 and not source.get(self.
edgeKey)
216 sourceSelectorRegistry.register(
"astrometry", AstrometrySourceSelectorTask)
def _isGood_vector(self, sourceCat)
def __init__(self, args, kwargs)
def selectSources(self, sourceCat, matches=None)
def _hasCentroid_vector(self, sourceCat)
def _isUsable(self, source)
def _isMultiple(self, source)
def _isGood(self, source)
def _goodSN_vector(self, sourceCat)
def _isMultiple_vector(self, sourceCat)
def _getSchemaKeys(self, schema)
def _goodSN(self, source)
def _hasCentroid(self, source)
def _isUsable_vector(self, sourceCat)
Base class for source selectors.