lsst.ip.diffim  15.0-5-g0db841d+1
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.afw.table import SourceCatalog
26 from lsst.pipe.base import Struct
27 import lsst.pex.config as pexConfig
28 import lsst.afw.display.ds9 as ds9
29 import lsst.meas.algorithms as measAlg
30 
31 __all__ = ["DiaCatalogSourceSelectorConfig", "DiaCatalogSourceSelectorTask"]
32 
33 
34 class DiaCatalogSourceSelectorConfig(measAlg.BaseStarSelectorConfig):
35  # Selection cuts on the input source catalog
36  fluxLim = pexConfig.Field(
37  doc="specify the minimum psfFlux for good Kernel Candidates",
38  dtype=float,
39  default=0.0,
40  check=lambda x: x >= 0.0,
41  )
42  fluxMax = pexConfig.Field(
43  doc="specify the maximum psfFlux for good Kernel Candidates (ignored if == 0)",
44  dtype=float,
45  default=0.0,
46  check=lambda x: x >= 0.0,
47  )
48  # Selection cuts on the reference catalog
49  selectStar = pexConfig.Field(
50  doc="Select objects that are flagged as stars",
51  dtype=bool,
52  default=True
53  )
54  selectGalaxy = pexConfig.Field(
55  doc="Select objects that are flagged as galaxies",
56  dtype=bool,
57  default=False
58  )
59  includeVariable = pexConfig.Field(
60  doc="Include objects that are known to be variable",
61  dtype=bool,
62  default=False
63  )
64  grMin = pexConfig.Field(
65  doc="Minimum g-r color for selection (inclusive)",
66  dtype=float,
67  default=0.0
68  )
69  grMax = pexConfig.Field(
70  doc="Maximum g-r color for selection (inclusive)",
71  dtype=float,
72  default=3.0
73  )
74 
75  def setDefaults(self):
76  measAlg.BaseStarSelectorConfig.setDefaults(self)
77  self.badFlags = [
78  "base_PixelFlags_flag_edge",
79  "base_PixelFlags_flag_interpolatedCenter",
80  "base_PixelFlags_flag_saturatedCenter",
81  "slot_Centroid_flag",
82  ]
83 
84 
85 class CheckSource(object):
86  """A functor to check whether a source has any flags set that should cause it to be labeled bad."""
87 
88  def __init__(self, table, fluxLim, fluxMax, badFlags):
89  self.keys = [table.getSchema().find(name).key for name in badFlags]
90  self.fluxLim = fluxLim
91  self.fluxMax = fluxMax
92 
93  def __call__(self, source):
94  for k in self.keys:
95  if source.get(k):
96  return False
97  if self.fluxLim is not None and source.getPsfFlux() < self.fluxLim: # ignore faint objects
98  return False
99  if self.fluxMax != 0.0 and source.getPsfFlux() > self.fluxMax: # ignore bright objects
100  return False
101  return True
102 
103 
109 
110 
111 class DiaCatalogSourceSelectorTask(measAlg.BaseStarSelectorTask):
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 selectStars(self, exposure, sourceCat, matches=None):
170  """Select sources for Kernel candidates
171 
172  @param[in] exposure the exposure containing the sources
173  @param[in] sourceCat catalog of sources that may be stars (an lsst.afw.table.SourceCatalog)
174  @param[in] matches a match vector as produced by meas_astrom; required
175  (defaults to None to match the StarSelector API and improve error handling)
176 
177  @return an lsst.pipe.base.Struct containing:
178  - starCat a list of sources to be used as kernel candidates
179  """
180  import lsstDebug
181  display = lsstDebug.Info(__name__).display
182  displayExposure = lsstDebug.Info(__name__).displayExposure
183  pauseAtEnd = lsstDebug.Info(__name__).pauseAtEnd
184 
185  if matches is None:
186  raise RuntimeError("DiaCatalogSourceSelector requires matches")
187 
188  mi = exposure.getMaskedImage()
189 
190  if display:
191  if displayExposure:
192  ds9.mtv(mi, title="Kernel candidates", frame=lsstDebug.frame)
193  #
194  # Look for flags in each Source
195  #
196  isGoodSource = CheckSource(sourceCat, self.config.fluxLim, self.config.fluxMax, self.config.badFlags)
197 
198  #
199  # Go through and find all the acceptable candidates in the catalogue
200  #
201  starCat = SourceCatalog(sourceCat.schema)
202 
203  if display and displayExposure:
204  symbs = []
205  ctypes = []
206 
207  doColorCut = True
208 
209  refSchema = matches[0][0].schema
210  rRefFluxField = measAlg.getRefFluxField(refSchema, "r")
211  gRefFluxField = measAlg.getRefFluxField(refSchema, "g")
212  for ref, source, d in matches:
213  if not isGoodSource(source):
214  if display and displayExposure:
215  symbs.append("+")
216  ctypes.append(ds9.RED)
217  else:
218  isStar = not ref.get("resolved")
219  isVar = not ref.get("photometric")
220  gMag = None
221  rMag = None
222  if doColorCut:
223  try:
224  gMag = -2.5 * np.log10(ref.get(gRefFluxField))
225  rMag = -2.5 * np.log10(ref.get(rRefFluxField))
226  except KeyError:
227  self.log.warn("Cannot cut on color info; fields 'g' and 'r' do not exist")
228  doColorCut = False
229  isRightColor = True
230  else:
231  isRightColor = (gMag-rMag) >= self.config.grMin and (gMag-rMag) <= self.config.grMax
232 
233  isRightType = (self.config.selectStar and isStar) or (self.config.selectGalaxy and not isStar)
234  isRightVar = (self.config.includeVariable) or (self.config.includeVariable is isVar)
235  if isRightType and isRightVar and isRightColor:
236  starCat.append(source)
237  if display and displayExposure:
238  symbs.append("+")
239  ctypes.append(ds9.GREEN)
240  elif display and displayExposure:
241  symbs.append("o")
242  ctypes.append(ds9.BLUE)
243 
244  if display and displayExposure:
245  with ds9.Buffering():
246  for (ref, source, d), symb, ctype in zip(matches, symbs, ctypes):
247  if display and displayExposure:
248  ds9.dot(symb, source.getX() - mi.getX0(), source.getY() - mi.getY0(),
249  size=4, ctype=ctype, frame=lsstDebug.frame)
250 
251  if display:
252  lsstDebug.frame += 1
253  if pauseAtEnd:
254  input("Continue? y[es] p[db] ")
255 
256  return Struct(
257  starCat=starCat,
258  )
259 
260 
261 measAlg.starSelectorRegistry.register("diacatalog", DiaCatalogSourceSelectorTask)
def __init__(self, table, fluxLim, fluxMax, badFlags)