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