LSSTApplications  19.0.0-14-gb0260a2+72efe9b372,20.0.0+7927753e06,20.0.0+8829bf0056,20.0.0+995114c5d2,20.0.0+b6f4b2abd1,20.0.0+bddc4f4cbe,20.0.0-1-g253301a+8829bf0056,20.0.0-1-g2b7511a+0d71a2d77f,20.0.0-1-g5b95a8c+7461dd0434,20.0.0-12-g321c96ea+23efe4bbff,20.0.0-16-gfab17e72e+fdf35455f6,20.0.0-2-g0070d88+ba3ffc8f0b,20.0.0-2-g4dae9ad+ee58a624b3,20.0.0-2-g61b8584+5d3db074ba,20.0.0-2-gb780d76+d529cf1a41,20.0.0-2-ged6426c+226a441f5f,20.0.0-2-gf072044+8829bf0056,20.0.0-2-gf1f7952+ee58a624b3,20.0.0-20-geae50cf+e37fec0aee,20.0.0-25-g3dcad98+544a109665,20.0.0-25-g5eafb0f+ee58a624b3,20.0.0-27-g64178ef+f1f297b00a,20.0.0-3-g4cc78c6+e0676b0dc8,20.0.0-3-g8f21e14+4fd2c12c9a,20.0.0-3-gbd60e8c+187b78b4b8,20.0.0-3-gbecbe05+48431fa087,20.0.0-38-ge4adf513+a12e1f8e37,20.0.0-4-g97dc21a+544a109665,20.0.0-4-gb4befbc+087873070b,20.0.0-4-gf910f65+5d3db074ba,20.0.0-5-gdfe0fee+199202a608,20.0.0-5-gfbfe500+d529cf1a41,20.0.0-6-g64f541c+d529cf1a41,20.0.0-6-g9a5b7a1+a1cd37312e,20.0.0-68-ga3f3dda+5fca18c6a4,20.0.0-9-g4aef684+e18322736b,w.2020.45
LSSTDataManagementBasePackage
astrometrySourceSelector.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 """Select sources that are useful for astrometry.
24 
25 Such sources have good signal-to-noise, are well centroided, not blended,
26 and not flagged with a handful of "bad" flags.
27 """
28 
29 import numpy as np
30 
31 import lsst.pex.config as pexConfig
32 from .sourceSelector import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
33 from lsst.pipe.base import Struct
34 from functools import reduce
35 
36 
38  badFlags = pexConfig.ListField(
39  doc="List of flags which cause a source to be rejected as bad",
40  dtype=str,
41  default=[
42  "base_PixelFlags_flag_edge",
43  "base_PixelFlags_flag_interpolatedCenter",
44  "base_PixelFlags_flag_saturatedCenter",
45  "base_PixelFlags_flag_crCenter",
46  "base_PixelFlags_flag_bad",
47  ],
48  )
49  sourceFluxType = pexConfig.Field(
50  doc="Type of source flux; typically one of Ap or Psf",
51  dtype=str,
52  default="Ap",
53  )
54  minSnr = pexConfig.Field(
55  dtype=float,
56  doc="Minimum allowed signal-to-noise ratio for sources used for matching "
57  "(in the flux specified by sourceFluxType); <= 0 for no limit",
58  default=10,
59  )
60 
61 
62 @pexConfig.registerConfigurable("astrometry", sourceSelectorRegistry)
64  """Select sources that are useful for astrometry.
65 
66  Good astrometry sources have high signal/noise, are non-blended, and
67  did not have certain "bad" flags set during source extraction. They need not
68  be PSF sources, just have reliable centroids.
69  """
70  ConfigClass = AstrometrySourceSelectorConfig
71 
72  def __init__(self, *args, **kwargs):
73  BaseSourceSelectorTask.__init__(self, *args, **kwargs)
74 
75  def selectSources(self, sourceCat, matches=None, exposure=None):
76  """Return a selection of sources that are useful for astrometry.
77 
78  Parameters:
79  -----------
80  sourceCat : `lsst.afw.table.SourceCatalog`
81  Catalog of sources to select from.
82  This catalog must be contiguous in memory.
83  matches : `list` of `lsst.afw.table.ReferenceMatch` or None
84  Ignored in this SourceSelector.
85  exposure : `lsst.afw.image.Exposure` or None
86  The exposure the catalog was built from; used for debug display.
87 
88  Return
89  ------
90  struct : `lsst.pipe.base.Struct`
91  The struct contains the following data:
92 
93  - selected : `array` of `bool``
94  Boolean array of sources that were selected, same length as
95  sourceCat.
96  """
97  self._getSchemaKeys(sourceCat.schema)
98 
99  bad = reduce(lambda x, y: np.logical_or(x, sourceCat.get(y)), self.config.badFlags, False)
100  good = self._isGood(sourceCat)
101  return Struct(selected=good & ~bad)
102 
103  def _getSchemaKeys(self, schema):
104  """Extract and save the necessary keys from schema with asKey.
105  """
106  self.parentKey = schema["parent"].asKey()
107  self.nChildKey = schema["deblend_nChild"].asKey()
108  self.centroidXKey = schema["slot_Centroid_x"].asKey()
109  self.centroidYKey = schema["slot_Centroid_y"].asKey()
110  self.centroidXErrKey = schema["slot_Centroid_xErr"].asKey()
111  self.centroidYErrKey = schema["slot_Centroid_yErr"].asKey()
112  self.centroidFlagKey = schema["slot_Centroid_flag"].asKey()
113 
114  self.edgeKey = schema["base_PixelFlags_flag_edge"].asKey()
115  self.interpolatedCenterKey = schema["base_PixelFlags_flag_interpolatedCenter"].asKey()
116  self.saturatedKey = schema["base_PixelFlags_flag_saturated"].asKey()
117 
118  fluxPrefix = "slot_%sFlux_" % (self.config.sourceFluxType,)
119  self.instFluxKey = schema[fluxPrefix + "instFlux"].asKey()
120  self.fluxFlagKey = schema[fluxPrefix + "flag"].asKey()
121  self.instFluxErrKey = schema[fluxPrefix + "instFluxErr"].asKey()
122 
123  def _isMultiple(self, sourceCat):
124  """Return True for each source that is likely multiple sources.
125  """
126  test = (sourceCat.get(self.parentKey) != 0) | (sourceCat.get(self.nChildKey) != 0)
127  # have to currently manage footprints on a source-by-source basis.
128  for i, cat in enumerate(sourceCat):
129  footprint = cat.getFootprint()
130  test[i] |= (footprint is not None) and (len(footprint.getPeaks()) > 1)
131  return test
132 
133  def _hasCentroid(self, sourceCat):
134  """Return True for each source that has a valid centroid
135  """
136  def checkNonfiniteCentroid():
137  """Return True for sources with non-finite centroids.
138  """
139  return ~np.isfinite(sourceCat.get(self.centroidXKey)) | \
140  ~np.isfinite(sourceCat.get(self.centroidYKey))
141  assert ~checkNonfiniteCentroid().any(), \
142  "Centroids not finite for %d unflagged sources." % (checkNonfiniteCentroid().sum())
143  return np.isfinite(sourceCat.get(self.centroidXErrKey)) \
144  & np.isfinite(sourceCat.get(self.centroidYErrKey)) \
145  & ~sourceCat.get(self.centroidFlagKey)
146 
147  def _goodSN(self, sourceCat):
148  """Return True for each source that has Signal/Noise > config.minSnr.
149  """
150  if self.config.minSnr <= 0:
151  return True
152  else:
153  with np.errstate(invalid="ignore"): # suppress NAN warnings
154  return sourceCat.get(self.instFluxKey)/sourceCat.get(self.instFluxErrKey) > self.config.minSnr
155 
156  def _isUsable(self, sourceCat):
157  """Return True for each source that is usable for matching, even if it may
158  have a poor centroid.
159 
160  For a source to be usable it must:
161  - have a valid centroid
162  - not be deblended
163  - have a valid flux (of the type specified in this object's constructor)
164  - have adequate signal-to-noise
165  """
166 
167  return self._hasCentroid(sourceCat) \
168  & ~self._isMultiple(sourceCat) \
169  & self._goodSN(sourceCat) \
170  & ~sourceCat.get(self.fluxFlagKey)
171 
172  def _isGood(self, sourceCat):
173  """Return True for each source that is usable for matching and likely has a
174  good centroid.
175 
176  The additional tests for a good centroid, beyond isUsable, are:
177  - not interpolated in the center
178  - not saturated
179  - not near the edge
180  """
181 
182  return self._isUsable(sourceCat) \
183  & ~sourceCat.get(self.saturatedKey) \
184  & ~sourceCat.get(self.interpolatedCenterKey) \
185  & ~sourceCat.get(self.edgeKey)
186 
187  def _isBadFlagged(self, source):
188  """Return True if any of config.badFlags are set for this source.
189  """
190  return any(source.get(flag) for flag in self.config.badFlags)
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.centroidYKey
centroidYKey
Definition: astrometrySourceSelector.py:109
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.edgeKey
edgeKey
Definition: astrometrySourceSelector.py:114
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask._isUsable
def _isUsable(self, sourceCat)
Definition: astrometrySourceSelector.py:156
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.selectSources
def selectSources(self, sourceCat, matches=None, exposure=None)
Definition: astrometrySourceSelector.py:75
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.__init__
def __init__(self, *args, **kwargs)
Definition: astrometrySourceSelector.py:72
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.interpolatedCenterKey
interpolatedCenterKey
Definition: astrometrySourceSelector.py:115
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask._isMultiple
def _isMultiple(self, sourceCat)
Definition: astrometrySourceSelector.py:123
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask._hasCentroid
def _hasCentroid(self, sourceCat)
Definition: astrometrySourceSelector.py:133
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.centroidXErrKey
centroidXErrKey
Definition: astrometrySourceSelector.py:110
lsst::meas::algorithms.sourceSelector.BaseSourceSelectorConfig
Definition: sourceSelector.py:41
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorConfig
Definition: astrometrySourceSelector.py:37
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.nChildKey
nChildKey
Definition: astrometrySourceSelector.py:107
lsst.pipe.base.struct.Struct
Definition: struct.py:26
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.instFluxKey
instFluxKey
Definition: astrometrySourceSelector.py:119
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.parentKey
parentKey
Definition: astrometrySourceSelector.py:106
lsst.pex.config
Definition: __init__.py:1
lsst::meas::algorithms.sourceSelector.BaseSourceSelectorTask
Definition: sourceSelector.py:45
lsst::geom::any
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
Definition: CoordinateExpr.h:89
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.centroidYErrKey
centroidYErrKey
Definition: astrometrySourceSelector.py:111
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.instFluxErrKey
instFluxErrKey
Definition: astrometrySourceSelector.py:121
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.fluxFlagKey
fluxFlagKey
Definition: astrometrySourceSelector.py:120
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.saturatedKey
saturatedKey
Definition: astrometrySourceSelector.py:116
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.centroidFlagKey
centroidFlagKey
Definition: astrometrySourceSelector.py:112
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask.centroidXKey
centroidXKey
Definition: astrometrySourceSelector.py:108
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask._goodSN
def _goodSN(self, sourceCat)
Definition: astrometrySourceSelector.py:147
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask._isGood
def _isGood(self, sourceCat)
Definition: astrometrySourceSelector.py:172
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask._getSchemaKeys
def _getSchemaKeys(self, schema)
Definition: astrometrySourceSelector.py:103
lsst.pipe.base
Definition: __init__.py:1
lsst::meas::algorithms.astrometrySourceSelector.AstrometrySourceSelectorTask
Definition: astrometrySourceSelector.py:63