24from lsst.pipe.base
import Struct
27import lsst.meas.algorithms
as measAlg
29__all__ = [
"DiaCatalogSourceSelectorConfig",
"DiaCatalogSourceSelectorTask"]
34 fluxLim = pexConfig.Field(
35 doc=
"specify the minimum psfFlux for good Kernel Candidates",
38 check=
lambda x: x >= 0.0,
40 fluxMax = pexConfig.Field(
41 doc=
"specify the maximum psfFlux for good Kernel Candidates (ignored if == 0)",
44 check=
lambda x: x >= 0.0,
47 selectStar = pexConfig.Field(
48 doc=
"Select objects that are flagged as stars",
52 selectGalaxy = pexConfig.Field(
53 doc=
"Select objects that are flagged as galaxies",
57 includeVariable = pexConfig.Field(
58 doc=
"Include objects that are known to be variable",
62 grMin = pexConfig.Field(
63 doc=
"Minimum g-r color for selection (inclusive)",
67 grMax = pexConfig.Field(
68 doc=
"Maximum g-r color for selection (inclusive)",
74 measAlg.BaseStarSelectorConfig.setDefaults(self)
76 "base_PixelFlags_flag_edge",
77 "base_PixelFlags_flag_interpolatedCenter",
78 "base_PixelFlags_flag_saturatedCenter",
84 """A functor to check whether a source has any flags set that should cause it to be labeled bad."""
86 def __init__(self, table, fluxLim, fluxMax, badFlags):
87 self.
keys = [table.getSchema().find(name).key
for name
in badFlags]
95 if self.
fluxLim is not None and source.getPsfInstFlux() < self.
fluxLim:
102@pexConfig.registerConfigurable("diaCatalog", measAlg.sourceSelectorRegistry)
104 """A task that selects sources for Kernel candidates.
106 A naive star selector based on second moments. Use with caution.
112 DiaCatalogSourceSelectorTask has a debug dictionary
with the following keys:
115 if True display debug information
116 displayExposure : `bool`
117 if True display exposure
119 if True wait after displaying everything
and wait
for user input
123 For example, put something like:
130 if name.endswith(
"diaCatalogSourceSelector"):
137 into your `debug.py` file
and run your task
with the `--debug` flag.
139 ConfigClass = DiaCatalogSourceSelectorConfig
143 """Return a selection of sources for Kernel candidates.
148 Catalog of sources to select from.
149 This catalog must be contiguous
in memory.
151 A match vector
as produced by meas_astrom.
153 The exposure the catalog was built
from; used
for debug display.
157 struct : `lsst.pipe.base.Struct`
158 The struct contains the following data:
160 - selected : `array` of `bool``
161 Boolean array of sources that were selected, same length
as
170 raise RuntimeError(
"DiaCatalogSourceSelector requires matches")
172 mi = exposure.getMaskedImage()
174 if display
and displayExposure:
175 disp = afwDisplay.Display(frame=lsstDebug.frame)
176 disp.mtv(mi, title=
"Kernel candidates")
180 isGoodSource =
CheckSource(sourceCat, self.config.fluxLim, self.config.fluxMax, self.config.badFlags)
183 selected = np.zeros(len(sourceCat), dtype=bool)
185 if display
and displayExposure:
191 refSchema = matches[0][0].schema
192 rRefFluxField = measAlg.getRefFluxField(refSchema,
"r")
193 gRefFluxField = measAlg.getRefFluxField(refSchema,
"g")
194 for i, (ref, source, d)
in enumerate(matches):
195 if not isGoodSource(source):
196 if display
and displayExposure:
198 ctypes.append(afwDisplay.RED)
200 isStar =
not ref.get(
"resolved")
201 isVar =
not ref.get(
"photometric")
206 gMag = -2.5 * np.log10(ref.get(gRefFluxField))
207 rMag = -2.5 * np.log10(ref.get(rRefFluxField))
209 self.log.warning(
"Cannot cut on color info; fields 'g' and 'r' do not exist")
213 isRightColor = (gMag-rMag) >= self.config.grMin
and (gMag-rMag) <= self.config.grMax
215 isRightType = (self.config.selectStar
and isStar)
or (self.config.selectGalaxy
and not isStar)
216 isRightVar = (self.config.includeVariable)
or (self.config.includeVariable
is isVar)
217 if isRightType
and isRightVar
and isRightColor:
219 if display
and displayExposure:
221 ctypes.append(afwDisplay.GREEN)
222 elif display
and displayExposure:
224 ctypes.append(afwDisplay.BLUE)
226 if display
and displayExposure:
227 disp = afwDisplay.Display(frame=lsstDebug.frame)
228 with disp.Buffering():
229 for (ref, source, d), symb, ctype
in zip(matches, symbs, ctypes):
230 disp.dot(symb, source.getX() - mi.getX0(), source.getY() - mi.getY0(),
236 input(
"Continue? y[es] p[db] ")
238 return Struct(selected=selected)
def __call__(self, source)
def __init__(self, table, fluxLim, fluxMax, badFlags)
def selectSources(self, sourceCat, matches=None, exposure=None)