lsst.meas.astrom  15.0-6-g81517ef+1
catalogStarSelector.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 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 __all__ = ["CatalogStarSelectorConfig", "CatalogStarSelectorTask"]
24 
25 import numpy as np
26 
27 from lsst.meas.algorithms import BaseSourceSelectorTask, sourceSelectorRegistry
28 from lsst.pipe.base import Struct
29 import lsst.pex.config as pexConfig
30 import lsst.afw.display.ds9 as ds9
31 
32 
33 class CatalogStarSelectorConfig(BaseSourceSelectorTask.ConfigClass):
34  fluxLim = pexConfig.RangeField(
35  doc="specify the minimum psfFlux for good Psf Candidates",
36  dtype=float,
37  default=0.0,
38  min=0.0,
39  )
40  fluxMax = pexConfig.RangeField(
41  doc="specify the maximum psfFlux for good Psf Candidates (ignored if == 0)",
42  dtype=float,
43  default=0.0,
44  min=0.0,
45  )
46  badFlags = pexConfig.ListField(
47  doc="List of flags which cause a source to be rejected as bad",
48  dtype=str,
49  default=[
50  "base_PixelFlags_flag_edge",
51  "base_PixelFlags_flag_interpolatedCenter",
52  "base_PixelFlags_flag_saturatedCenter",
53  ],
54  )
55 
56 
58  """A functor to check whether a source has any flags set that should cause it to be labeled bad."""
59 
60  def __init__(self, table, fluxLim, fluxMax, badFlags):
61  self.keys = [table.getSchema().find(name).key for name in badFlags]
62  self.keys.append(table.getCentroidFlagKey())
63  self.fluxLim = fluxLim
64  self.fluxMax = fluxMax
65 
66  def __call__(self, source):
67  for k in self.keys:
68  if source.get(k):
69  return False
70  if self.fluxLim is not None and source.getPsfFlux() < self.fluxLim: # ignore faint objects
71  return False
72  if self.fluxMax != 0.0 and source.getPsfFlux() > self.fluxMax: # ignore bright objects
73  return False
74  return True
75 
76 # \addtogroup LSST_task_documentation
77 # \{
78 # \page CatalogStarSelectorTask
79 # \ref CatalogStarSelectorTask_ "CatalogStarSelectorTask"
80 # \copybrief CatalogStarSelectorTask
81 # \}
82 
83 
84 @pexConfig.registerConfigurable("catalog", sourceSelectorRegistry)
86  """!Select stars based on a reference catalog
87 
88  @anchor CatalogStarSelectorTask_
89 
90  @section meas_astrom_catalogStarSelector_Contents Contents
91 
92  - @ref meas_astrom_catalogStarSelector_Purpose
93  - @ref meas_astrom_catalogStarSelector_Initialize
94  - @ref meas_astrom_catalogStarSelector_IO
95  - @ref meas_astrom_catalogStarSelector_Config
96  - @ref meas_astrom_catalogStarSelector_Debug
97 
98  @section meas_astrom_catalogStarSelector_Purpose Description
99 
100  Select stars using a match list: select sources where the matching reference object is unresolved,
101  plus the source passes the following tests:
102  - no flag from config.badFlags is set
103  - psf flux >= config.fluxLim
104  - psf flux <= config.fluxMax (not checked if fluxMax == 0)
105 
106  @section meas_astrom_catalogStarSelector_Initialize Task initialisation
107 
108  @copydoc \_\_init\_\_
109 
110  @section meas_astrom_catalogStarSelector_IO Invoking the Task
111 
112  Like all star selectors, the main method is `run`. Unlike most star selectors,
113  this one requires the `matches` argument (the `usesMatches` property is true).
114 
115  @section meas_astrom_catalogStarSelector_Config Configuration parameters
116 
117  See @ref CatalogStarSelectorConfig
118 
119  @section meas_astrom_catalogStarSelector_Debug Debug variables
120 
121  CatalogStarSelectorTask has a debug dictionary with the following keys:
122  <dl>
123  <dt>display
124  <dd>bool; if True display debug information
125  <dt>pauseAtEnd
126  <dd>bool; if True wait after displaying everything and wait for user input
127  </dl>
128 
129  For example, put something like:
130  @code{.py}
131  import lsstDebug
132  def DebugInfo(name):
133  di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
134  if name.endswith("catalogStarSelector"):
135  di.display = True
136 
137  return di
138 
139  lsstDebug.Info = DebugInfo
140  @endcode
141  into your `debug.py` file and run your task with the `--debug` flag.
142  """
143  ConfigClass = CatalogStarSelectorConfig
144  usesMatches = True # `run` and `selectStars` require the `matches` argument
145 
146  def selectSources(self, sourceCat, matches=None, exposure=None):
147  """Return a selection of sources based on reference catalog matches.
148 
149  Parameters
150  ----------
151  sourceCat : `lsst.afw.table.SourceCatalog`
152  Catalog of sources to select from.
153  This catalog must be contiguous in memory.
154  matches : `list` of `lsst.afw.table.ReferenceMatch`
155  A match vector as produced by meas_astrom; required.
156  exposure : `lsst.afw.image.Exposure` or None
157  The exposure the catalog was built from; used for debug display.
158 
159  Return
160  ------
161  struct : `lsst.pipe.base.Struct`
162  The struct contains the following data:
163 
164  - selected : `numpy.ndarray` of `bool``
165  Boolean array of sources that were selected, same length as
166  sourceCat.
167  """
168  import lsstDebug
169  debugInfo = lsstDebug.Info(__name__)
170  display = debugInfo.display
171  pauseAtEnd = debugInfo.pauseAtEnd # pause when done
172 
173  if matches is None:
174  raise RuntimeError("CatalogStarSelectorTask requires matches")
175 
176  mi = exposure.getMaskedImage()
177 
178  if display:
179  frame = 1
180  ds9.mtv(mi, frame=frame, title="PSF candidates")
181 
182  isGoodSource = CheckSource(sourceCat, self.config.fluxLim, self.config.fluxMax, self.config.badFlags)
183  good = np.array([isGoodSource(record) for record in sourceCat])
184 
185  with ds9.Buffering():
186  for ref, source, d in matches:
187  if not ref.get("resolved"):
188  if not isGoodSource(source):
189  symb, ctype = "+", ds9.RED
190  else:
191  symb, ctype = "+", ds9.GREEN
192 
193  if display:
194  ds9.dot(symb, source.getX() - mi.getX0(), source.getY() - mi.getY0(),
195  size=4, frame=frame, ctype=ctype)
196 
197  if display and pauseAtEnd:
198  input("Continue? y[es] p[db] ")
199 
200  return Struct(selected=good)
def selectSources(self, sourceCat, matches=None, exposure=None)
def __init__(self, table, fluxLim, fluxMax, badFlags)