22 from __future__
import absolute_import, division, print_function
24 from builtins
import input
25 from builtins
import object
28 from lsst.afw.table
import SourceCatalog
29 from lsst.pipe.base
import Struct
30 import lsst.pex.config
as pexConfig
31 import lsst.afw.display.ds9
as ds9
32 import lsst.meas.algorithms
as measAlg
34 __all__ = [
"DiaCatalogSourceSelectorConfig",
"DiaCatalogSourceSelectorTask"]
39 fluxLim = pexConfig.Field(
40 doc=
"specify the minimum psfFlux for good Kernel Candidates",
43 check=
lambda x: x >= 0.0,
45 fluxMax = pexConfig.Field(
46 doc=
"specify the maximum psfFlux for good Kernel Candidates (ignored if == 0)",
49 check=
lambda x: x >= 0.0,
52 selectStar = pexConfig.Field(
53 doc=
"Select objects that are flagged as stars",
57 selectGalaxy = pexConfig.Field(
58 doc=
"Select objects that are flagged as galaxies",
62 includeVariable = pexConfig.Field(
63 doc=
"Include objects that are known to be variable",
67 grMin = pexConfig.Field(
68 doc=
"Minimum g-r color for selection (inclusive)",
72 grMax = pexConfig.Field(
73 doc=
"Maximum g-r color for selection (inclusive)",
79 measAlg.BaseStarSelectorConfig.setDefaults(self)
81 "base_PixelFlags_flag_edge",
82 "base_PixelFlags_flag_interpolatedCenter",
83 "base_PixelFlags_flag_saturatedCenter",
89 """A functor to check whether a source has any flags set that should cause it to be labeled bad."""
91 def __init__(self, table, fluxLim, fluxMax, badFlags):
92 self.
keys = [table.getSchema().find(name).key
for name
in badFlags]
100 if self.
fluxLim is not None and source.getPsfFlux() < self.
fluxLim:
115 """!Select sources for Kernel candidates
117 @anchor DiaCatalogSourceSelectorTask_
119 @section ip_diffim_diaCatalogSourceSelector_Contents Contents
121 - @ref ip_diffim_diaCatalogSourceSelector_Purpose
122 - @ref ip_diffim_diaCatalogSourceSelector_Initialize
123 - @ref ip_diffim_diaCatalogSourceSelector_IO
124 - @ref ip_diffim_diaCatalogSourceSelector_Config
125 - @ref ip_diffim_diaCatalogSourceSelector_Debug
127 @section ip_diffim_diaCatalogSourceSelector_Purpose Description
129 A naive star selector based on second moments. Use with caution.
131 @section ip_diffim_diaCatalogSourceSelector_Initialize Task initialisation
133 @copydoc \_\_init\_\_
135 @section ip_diffim_diaCatalogSourceSelector_IO Invoking the Task
137 Like all star selectors, the main method is `run`.
139 @section ip_diffim_diaCatalogSourceSelector_Config Configuration parameters
141 See @ref DiaCatalogSourceSelectorConfig
143 @section ip_diffim_diaCatalogSourceSelector_Debug Debug variables
145 DiaCatalogSourceSelectorTask has a debug dictionary with the following keys:
148 <dd>bool; if True display debug information
150 <dd>bool; if True display exposure
152 <dd>bool; if True wait after displaying everything and wait for user input
155 For example, put something like:
159 di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
160 if name.endswith("catalogStarSelector"):
165 lsstDebug.Info = DebugInfo
167 into your `debug.py` file and run your task with the `--debug` flag.
169 ConfigClass = DiaCatalogSourceSelectorConfig
173 """Select sources for Kernel candidates
175 @param[in] exposure the exposure containing the sources
176 @param[in] sourceCat catalog of sources that may be stars (an lsst.afw.table.SourceCatalog)
177 @param[in] matches a match vector as produced by meas_astrom; required
178 (defaults to None to match the StarSelector API and improve error handling)
180 @return an lsst.pipe.base.Struct containing:
181 - starCat a list of sources to be used as kernel candidates
184 display = lsstDebug.Info(__name__).display
185 displayExposure = lsstDebug.Info(__name__).displayExposure
186 pauseAtEnd = lsstDebug.Info(__name__).pauseAtEnd
189 raise RuntimeError(
"DiaCatalogSourceSelector requires matches")
191 mi = exposure.getMaskedImage()
195 ds9.mtv(mi, title=
"Kernel candidates", frame=lsstDebug.frame)
199 isGoodSource =
CheckSource(sourceCat, self.config.fluxLim, self.config.fluxMax, self.config.badFlags)
204 starCat = SourceCatalog(sourceCat.schema)
206 if display
and displayExposure:
212 refSchema = matches[0][0].schema
213 rRefFluxField = measAlg.getRefFluxField(refSchema,
"r")
214 gRefFluxField = measAlg.getRefFluxField(refSchema, "g")
215 for ref, source, d
in matches:
216 if not isGoodSource(source):
217 if display
and displayExposure:
219 ctypes.append(ds9.RED)
221 isStar =
not ref.get(
"resolved")
222 isVar =
not ref.get(
"photometric")
227 gMag = -2.5 * np.log10(ref.get(gRefFluxField))
228 rMag = -2.5 * np.log10(ref.get(rRefFluxField))
230 self.log.warn(
"Cannot cut on color info; fields 'g' and 'r' do not exist")
234 isRightColor = (gMag-rMag) >= self.config.grMin
and (gMag-rMag) <= self.config.grMax
236 isRightType = (self.config.selectStar
and isStar)
or (self.config.selectGalaxy
and not isStar)
237 isRightVar = (self.config.includeVariable)
or (self.config.includeVariable
is isVar)
238 if isRightType
and isRightVar
and isRightColor:
239 starCat.append(source)
240 if display
and displayExposure:
242 ctypes.append(ds9.GREEN)
243 elif display
and displayExposure:
245 ctypes.append(ds9.BLUE)
247 if display
and displayExposure:
248 with ds9.Buffering():
249 for (ref, source, d), symb, ctype
in zip(matches, symbs, ctypes):
250 if display
and displayExposure:
251 ds9.dot(symb, source.getX() - mi.getX0(), source.getY() - mi.getY0(),
252 size=4, ctype=ctype, frame=lsstDebug.frame)
257 input(
"Continue? y[es] p[db] ")
263 measAlg.starSelectorRegistry.register(
"diacatalog", DiaCatalogSourceSelectorTask)
Select sources for Kernel candidates.