LSSTApplications  16.0-10-g0ee56ad+5,16.0-11-ga33d1f2+5,16.0-12-g3ef5c14+3,16.0-12-g71e5ef5+18,16.0-12-gbdf3636+3,16.0-13-g118c103+3,16.0-13-g8f68b0a+3,16.0-15-gbf5c1cb+4,16.0-16-gfd17674+3,16.0-17-g7c01f5c+3,16.0-18-g0a50484+1,16.0-20-ga20f992+8,16.0-21-g0e05fd4+6,16.0-21-g15e2d33+4,16.0-22-g62d8060+4,16.0-22-g847a80f+4,16.0-25-gf00d9b8+1,16.0-28-g3990c221+4,16.0-3-gf928089+3,16.0-32-g88a4f23+5,16.0-34-gd7987ad+3,16.0-37-gc7333cb+2,16.0-4-g10fc685+2,16.0-4-g18f3627+26,16.0-4-g5f3a788+26,16.0-5-gaf5c3d7+4,16.0-5-gcc1f4bb+1,16.0-6-g3b92700+4,16.0-6-g4412fcd+3,16.0-6-g7235603+4,16.0-69-g2562ce1b+2,16.0-8-g14ebd58+4,16.0-8-g2df868b+1,16.0-8-g4cec79c+6,16.0-8-gadf6c7a+1,16.0-8-gfc7ad86,16.0-82-g59ec2a54a+1,16.0-9-g5400cdc+2,16.0-9-ge6233d7+5,master-g2880f2d8cf+3,v17.0.rc1
LSSTDataManagementBasePackage
matcherSourceSelector.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 #
4 # Copyright 2008-2017 AURA/LSST.
5 #
6 # This product includes software developed by the
7 # LSST Project (http://www.lsst.org/).
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the LSST License Statement and
20 # the GNU General Public License along with this program. If not,
21 # see <https://www.lsstcorp.org/LegalNotices/>.
22 #
23 
24 import numpy as np
25 
26 import lsst.pex.config as pexConfig
27 from .sourceSelector import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
28 from lsst.pipe.base import Struct
29 
30 
32  sourceFluxType = pexConfig.Field(
33  doc="Type of source flux; typically one of Ap or Psf",
34  dtype=str,
35  default="Ap",
36  )
37  minSnr = pexConfig.Field(
38  dtype=float,
39  doc="Minimum allowed signal-to-noise ratio for sources used for matching "
40  "(in the flux specified by sourceFluxType); <= 0 for no limit",
41  default=40,
42  )
43 
44 
45 @pexConfig.registerConfigurable("matcher", sourceSelectorRegistry)
47  """Select sources that are useful for matching.
48 
49  Good matching sources have high signal/noise, are non-blended. They need not
50  be PSF sources, just have reliable centroids.
51 
52  Distinguished from astrometrySourceSelector because it is more lenient
53  (i.e. not checking footprints or bad flags).
54  """
55  ConfigClass = MatcherSourceSelectorConfig
56 
57  def __init__(self, *args, **kwargs):
58  BaseSourceSelectorTask.__init__(self, *args, **kwargs)
59 
60  def selectSources(self, sourceCat, matches=None, exposure=None):
61  """Return a selection of sources that are useful for matching.
62 
63  Parameters:
64  -----------
65  sourceCat : `lsst.afw.table.SourceCatalog`
66  Catalog of sources to select from.
67  This catalog must be contiguous in memory.
68  matches : `list` of `lsst.afw.table.ReferenceMatch` or None
69  Ignored in this SourceSelector.
70  exposure : `lsst.afw.image.Exposure` or None
71  The exposure the catalog was built from; used for debug display.
72 
73  Return
74  ------
75  struct : `lsst.pipe.base.Struct`
76  The struct contains the following data:
77 
78  - selected : `array` of `bool``
79  Boolean array of sources that were selected, same length as
80  sourceCat.
81  """
82  self._getSchemaKeys(sourceCat.schema)
83 
84  good = self._isUsable(sourceCat)
85  return Struct(selected=good)
86 
87  def _getSchemaKeys(self, schema):
88  """Extract and save the necessary keys from schema with asKey."""
89  self.parentKey = schema["parent"].asKey()
90  self.centroidXKey = schema["slot_Centroid_x"].asKey()
91  self.centroidYKey = schema["slot_Centroid_y"].asKey()
92  self.centroidFlagKey = schema["slot_Centroid_flag"].asKey()
93 
94  fluxPrefix = "slot_%sFlux_" % (self.config.sourceFluxType,)
95  self.fluxField = fluxPrefix + "instFlux"
96  self.fluxKey = schema[fluxPrefix + "instFlux"].asKey()
97  self.fluxFlagKey = schema[fluxPrefix + "flag"].asKey()
98  self.fluxErrKey = schema[fluxPrefix + "instFluxErr"].asKey()
99 
100  def _isParent(self, sourceCat):
101  """Return True for each source that is the parent source."""
102  test = (sourceCat.get(self.parentKey) == 0)
103  return test
104 
105  def _hasCentroid(self, sourceCat):
106  """Return True for each source that has a valid centroid"""
107  return np.isfinite(sourceCat.get(self.centroidXKey)) \
108  & np.isfinite(sourceCat.get(self.centroidYKey)) \
109  & ~sourceCat.get(self.centroidFlagKey)
110 
111  def _goodSN(self, sourceCat):
112  """Return True for each source that has Signal/Noise > config.minSnr."""
113  if self.config.minSnr <= 0:
114  return True
115  else:
116  with np.errstate(invalid="ignore"): # suppress NAN warnings
117  return sourceCat.get(self.fluxKey)/sourceCat.get(self.fluxErrKey) > self.config.minSnr
118 
119  def _isUsable(self, sourceCat):
120  """
121  Return True for each source that is usable for matching, even if it may
122  have a poor centroid.
123 
124  For a source to be usable it must:
125  - have a valid centroid
126  - not be deblended
127  - have a valid instFlux (of the type specified in this object's constructor)
128  - have adequate signal-to-noise
129  """
130  return self._hasCentroid(sourceCat) \
131  & self._isParent(sourceCat) \
132  & self._goodSN(sourceCat) \
133  & ~sourceCat.get(self.fluxFlagKey)
134 
135 
136 @pexConfig.registerConfigurable("matcherPessimistic", sourceSelectorRegistry)
138  """Select sources that are useful for matching.
139 
140  Good matching sources have high signal/noise, are non-blended. They need not
141  be PSF sources, just have reliable centroids. This inherited class adds
142  the removal of saturated, interpolated, and edge_key objects to the set of
143  bad flags. It is a temporary addition designed preserve the source selction
144  used in matchOptimisticB. Once matchPessimisticB is adopted as the default
145  source selector the class will be removed and the saturated, interpoalted, and
146  edge_key flags will be added to the matcherSourceSelector class.
147 
148  TODO: Once DM-10399 is complete an RFC will be filed to make matchPessimisticB
149  the default matcher this class will replace matcherSourceSelector with this source
150  selector resulting in only one matcherSourceSeletor. The ticket describing
151  this work is DM-10800.
152  """
153  def _getSchemaKeys(self, schema):
154  """Extract and save the necessary keys from schema with asKey."""
155  MatcherSourceSelectorTask._getSchemaKeys(self, schema)
156 
157  self.edgeKey = schema["base_PixelFlags_flag_edge"].asKey()
158  self.interpolatedCenterKey = schema["base_PixelFlags_flag_interpolatedCenter"].asKey()
159  self.saturatedKey = schema["base_PixelFlags_flag_saturated"].asKey()
160 
161  def _isUsable(self, sourceCat):
162  """
163  Return True for each source that is usable for matching, even if it may
164  have a poor centroid.
165 
166  For a source to be usable it must:
167  - have a valid centroid
168  - not be deblended
169  - have a valid instFlux (of the type specified in this object's constructor)
170  - have adequate signal-to-noise
171  """
172  result = MatcherSourceSelectorTask._isUsable(self, sourceCat)
173 
174  return result \
175  & ~sourceCat.get(self.edgeKey) \
176  & ~sourceCat.get(self.interpolatedCenterKey) \
177  & ~sourceCat.get(self.saturatedKey)
def selectSources(self, sourceCat, matches=None, exposure=None)