lsst.ip.diffim  16.0-8-g4aca173+6
diaCatalogSourceSelector.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2016 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 import numpy as np
24 
25 from lsst.pipe.base import Struct
26 import lsst.pex.config as pexConfig
27 import lsst.afw.display.ds9 as ds9
28 import lsst.meas.algorithms as measAlg
29 
30 __all__ = ["DiaCatalogSourceSelectorConfig", "DiaCatalogSourceSelectorTask"]
31 
32 
33 class DiaCatalogSourceSelectorConfig(measAlg.BaseStarSelectorConfig):
34  # Selection cuts on the input source catalog
35  fluxLim = pexConfig.Field(
36  doc="specify the minimum psfFlux for good Kernel Candidates",
37  dtype=float,
38  default=0.0,
39  check=lambda x: x >= 0.0,
40  )
41  fluxMax = pexConfig.Field(
42  doc="specify the maximum psfFlux for good Kernel Candidates (ignored if == 0)",
43  dtype=float,
44  default=0.0,
45  check=lambda x: x >= 0.0,
46  )
47  # Selection cuts on the reference catalog
48  selectStar = pexConfig.Field(
49  doc="Select objects that are flagged as stars",
50  dtype=bool,
51  default=True
52  )
53  selectGalaxy = pexConfig.Field(
54  doc="Select objects that are flagged as galaxies",
55  dtype=bool,
56  default=False
57  )
58  includeVariable = pexConfig.Field(
59  doc="Include objects that are known to be variable",
60  dtype=bool,
61  default=False
62  )
63  grMin = pexConfig.Field(
64  doc="Minimum g-r color for selection (inclusive)",
65  dtype=float,
66  default=0.0
67  )
68  grMax = pexConfig.Field(
69  doc="Maximum g-r color for selection (inclusive)",
70  dtype=float,
71  default=3.0
72  )
73 
74  def setDefaults(self):
75  measAlg.BaseStarSelectorConfig.setDefaults(self)
76  self.badFlags = [
77  "base_PixelFlags_flag_edge",
78  "base_PixelFlags_flag_interpolatedCenter",
79  "base_PixelFlags_flag_saturatedCenter",
80  "slot_Centroid_flag",
81  ]
82 
83 
84 class CheckSource(object):
85  """A functor to check whether a source has any flags set that should cause it to be labeled bad."""
86 
87  def __init__(self, table, fluxLim, fluxMax, badFlags):
88  self.keys = [table.getSchema().find(name).key for name in badFlags]
89  self.fluxLim = fluxLim
90  self.fluxMax = fluxMax
91 
92  def __call__(self, source):
93  for k in self.keys:
94  if source.get(k):
95  return False
96  if self.fluxLim is not None and source.getPsfFlux() < self.fluxLim: # ignore faint objects
97  return False
98  if self.fluxMax != 0.0 and source.getPsfFlux() > self.fluxMax: # ignore bright objects
99  return False
100  return True
101 
102 
108 
109 
110 @pexConfig.registerConfigurable("diaCatalog", measAlg.sourceSelectorRegistry)
111 class DiaCatalogSourceSelectorTask(measAlg.BaseSourceSelectorTask):
112  """!Select sources for Kernel candidates
113 
114  @anchor DiaCatalogSourceSelectorTask_
115 
116  @section ip_diffim_diaCatalogSourceSelector_Contents Contents
117 
118  - @ref ip_diffim_diaCatalogSourceSelector_Purpose
119  - @ref ip_diffim_diaCatalogSourceSelector_Initialize
120  - @ref ip_diffim_diaCatalogSourceSelector_IO
121  - @ref ip_diffim_diaCatalogSourceSelector_Config
122  - @ref ip_diffim_diaCatalogSourceSelector_Debug
123 
124  @section ip_diffim_diaCatalogSourceSelector_Purpose Description
125 
126  A naive star selector based on second moments. Use with caution.
127 
128  @section ip_diffim_diaCatalogSourceSelector_Initialize Task initialisation
129 
130  @copydoc \_\_init\_\_
131 
132  @section ip_diffim_diaCatalogSourceSelector_IO Invoking the Task
133 
134  Like all star selectors, the main method is `run`.
135 
136  @section ip_diffim_diaCatalogSourceSelector_Config Configuration parameters
137 
138  See @ref DiaCatalogSourceSelectorConfig
139 
140  @section ip_diffim_diaCatalogSourceSelector_Debug Debug variables
141 
142  DiaCatalogSourceSelectorTask has a debug dictionary with the following keys:
143  <dl>
144  <dt>display
145  <dd>bool; if True display debug information
146  <dt>displayExposure
147  <dd>bool; if True display exposure
148  <dt>pauseAtEnd
149  <dd>bool; if True wait after displaying everything and wait for user input
150  </dl>
151 
152  For example, put something like:
153  @code{.py}
154  import lsstDebug
155  def DebugInfo(name):
156  di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
157  if name.endswith("catalogStarSelector"):
158  di.display = True
159 
160  return di
161 
162  lsstDebug.Info = DebugInfo
163  @endcode
164  into your `debug.py` file and run your task with the `--debug` flag.
165  """
166  ConfigClass = DiaCatalogSourceSelectorConfig
167  usesMatches = True # selectStars uses (requires) its matches argument
168 
169  def selectSources(self, sourceCat, matches=None, exposure=None):
170  """Return a selection of sources for Kernel candidates.
171 
172  Parameters:
173  -----------
174  sourceCat : `lsst.afw.table.SourceCatalog`
175  Catalog of sources to select from.
176  This catalog must be contiguous in memory.
177  matches : `list` of `lsst.afw.table.ReferenceMatch`
178  A match vector as produced by meas_astrom.
179  exposure : `lsst.afw.image.Exposure` or None
180  The exposure the catalog was built from; used for debug display.
181 
182  Return
183  ------
184  struct : `lsst.pipe.base.Struct`
185  The struct contains the following data:
186 
187  - selected : `array` of `bool``
188  Boolean array of sources that were selected, same length as
189  sourceCat.
190  """
191  import lsstDebug
192  display = lsstDebug.Info(__name__).display
193  displayExposure = lsstDebug.Info(__name__).displayExposure
194  pauseAtEnd = lsstDebug.Info(__name__).pauseAtEnd
195 
196  if matches is None:
197  raise RuntimeError("DiaCatalogSourceSelector requires matches")
198 
199  mi = exposure.getMaskedImage()
200 
201  if display:
202  if displayExposure:
203  ds9.mtv(mi, title="Kernel candidates", frame=lsstDebug.frame)
204  #
205  # Look for flags in each Source
206  #
207  isGoodSource = CheckSource(sourceCat, self.config.fluxLim, self.config.fluxMax, self.config.badFlags)
208 
209  # Go through and find all the acceptable candidates in the catalogue
210  selected = np.zeros(len(sourceCat), dtype=bool)
211 
212  if display and displayExposure:
213  symbs = []
214  ctypes = []
215 
216  doColorCut = True
217 
218  refSchema = matches[0][0].schema
219  rRefFluxField = measAlg.getRefFluxField(refSchema, "r")
220  gRefFluxField = measAlg.getRefFluxField(refSchema, "g")
221  for i, (ref, source, d) in enumerate(matches):
222  if not isGoodSource(source):
223  if display and displayExposure:
224  symbs.append("+")
225  ctypes.append(ds9.RED)
226  else:
227  isStar = not ref.get("resolved")
228  isVar = not ref.get("photometric")
229  gMag = None
230  rMag = None
231  if doColorCut:
232  try:
233  gMag = -2.5 * np.log10(ref.get(gRefFluxField))
234  rMag = -2.5 * np.log10(ref.get(rRefFluxField))
235  except KeyError:
236  self.log.warn("Cannot cut on color info; fields 'g' and 'r' do not exist")
237  doColorCut = False
238  isRightColor = True
239  else:
240  isRightColor = (gMag-rMag) >= self.config.grMin and (gMag-rMag) <= self.config.grMax
241 
242  isRightType = (self.config.selectStar and isStar) or (self.config.selectGalaxy and not isStar)
243  isRightVar = (self.config.includeVariable) or (self.config.includeVariable is isVar)
244  if isRightType and isRightVar and isRightColor:
245  selected[i] = True
246  if display and displayExposure:
247  symbs.append("+")
248  ctypes.append(ds9.GREEN)
249  elif display and displayExposure:
250  symbs.append("o")
251  ctypes.append(ds9.BLUE)
252 
253  if display and displayExposure:
254  with ds9.Buffering():
255  for (ref, source, d), symb, ctype in zip(matches, symbs, ctypes):
256  if display and displayExposure:
257  ds9.dot(symb, source.getX() - mi.getX0(), source.getY() - mi.getY0(),
258  size=4, ctype=ctype, frame=lsstDebug.frame)
259 
260  if display:
261  lsstDebug.frame += 1
262  if pauseAtEnd:
263  input("Continue? y[es] p[db] ")
264 
265  return Struct(selected=selected)
def __init__(self, table, fluxLim, fluxMax, badFlags)