LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
matcherSourceSelector.py
Go to the documentation of this file.
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__all__ = ["MatcherSourceSelectorConfig", "MatcherSourceSelectorTask"]
25
26import numpy as np
27
28import lsst.pex.config as pexConfig
29from .sourceSelector import BaseSourceSelectorConfig, BaseSourceSelectorTask, sourceSelectorRegistry
30from lsst.pipe.base import Struct
31
32
34 sourceFluxType = pexConfig.Field(
35 doc="Type of source flux; typically one of Ap or Psf",
36 dtype=str,
37 default="Ap",
38 )
39 minSnr = pexConfig.Field(
40 dtype=float,
41 doc="Minimum allowed signal-to-noise ratio for sources used for matching "
42 "(in the flux specified by sourceFluxType); <= 0 for no limit",
43 default=40,
44 )
45 excludePixelFlags = pexConfig.Field(
46 dtype=bool,
47 doc="Exclude objects that have saturated, interpolated, or edge "
48 "pixels using PixelFlags. For matchOptimisticB set this to False "
49 "to recover previous matcher selector behavior.",
50 default=True,
51 )
52
53
54@pexConfig.registerConfigurable("matcher", sourceSelectorRegistry)
56 """Select sources that are useful for matching.
57
58 Good matching sources have high signal/noise, are non-blended. They need not
59 be PSF sources, just have reliable centroids.
60
61 Distinguished from astrometrySourceSelector because it is more lenient
62 (i.e. not checking footprints or bad flags).
63 """
64 ConfigClass = MatcherSourceSelectorConfig
65
66 def __init__(self, *args, **kwargs):
67 BaseSourceSelectorTask.__init__(self, *args, **kwargs)
68
69 def selectSources(self, sourceCat, matches=None, exposure=None):
70 """Return a selection of sources that are useful for matching.
71
72 Parameters:
73 -----------
75 Catalog of sources to select from.
76 This catalog must be contiguous in memory.
77 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
78 Ignored in this SourceSelector.
79 exposure : `lsst.afw.image.Exposure` or None
80 The exposure the catalog was built from; used for debug display.
81
82 Return
83 ------
84 struct : `lsst.pipe.base.Struct`
85 The struct contains the following data:
86
87 - selected : `array` of `bool``
88 Boolean array of sources that were selected, same length as
89 sourceCat.
90 """
91 self._getSchemaKeys_getSchemaKeys(sourceCat.schema)
92
93 good = self._isUsable_isUsable(sourceCat)
94 if self.config.excludePixelFlags:
95 good = good & self._isGood_isGood(sourceCat)
96 return Struct(selected=good)
97
98 def _getSchemaKeys(self, schema):
99 """Extract and save the necessary keys from schema with asKey.
100 """
101 self.parentKeyparentKey = schema["parent"].asKey()
102 self.centroidXKeycentroidXKey = schema["slot_Centroid_x"].asKey()
103 self.centroidYKeycentroidYKey = schema["slot_Centroid_y"].asKey()
104 self.centroidFlagKeycentroidFlagKey = schema["slot_Centroid_flag"].asKey()
105
106 fluxPrefix = "slot_%sFlux_" % (self.config.sourceFluxType,)
107 self.fluxFieldfluxField = fluxPrefix + "instFlux"
108 self.fluxKeyfluxKey = schema[fluxPrefix + "instFlux"].asKey()
109 self.fluxFlagKeyfluxFlagKey = schema[fluxPrefix + "flag"].asKey()
110 self.fluxErrKeyfluxErrKey = schema[fluxPrefix + "instFluxErr"].asKey()
111
112 self.edgeKeyedgeKey = schema["base_PixelFlags_flag_edge"].asKey()
113 self.interpolatedCenterKeyinterpolatedCenterKey = schema["base_PixelFlags_flag_interpolatedCenter"].asKey()
114 self.saturatedKeysaturatedKey = schema["base_PixelFlags_flag_saturated"].asKey()
115
116 def _isParent(self, sourceCat):
117 """Return True for each source that is the parent source.
118 """
119 test = (sourceCat.get(self.parentKeyparentKey) == 0)
120 return test
121
122 def _hasCentroid(self, sourceCat):
123 """Return True for each source that has a valid centroid
124 """
125 return np.isfinite(sourceCat.get(self.centroidXKeycentroidXKey)) \
126 & np.isfinite(sourceCat.get(self.centroidYKeycentroidYKey)) \
127 & ~sourceCat.get(self.centroidFlagKeycentroidFlagKey)
128
129 def _goodSN(self, sourceCat):
130 """Return True for each source that has Signal/Noise > config.minSnr.
131 """
132 if self.config.minSnr <= 0:
133 return True
134 else:
135 with np.errstate(invalid="ignore"): # suppress NAN warnings
136 return sourceCat.get(self.fluxKeyfluxKey)/sourceCat.get(self.fluxErrKeyfluxErrKey) > self.config.minSnr
137
138 def _isUsable(self, sourceCat):
139 """
140 Return True for each source that is usable for matching, even if it may
141 have a poor centroid.
142
143 For a source to be usable it must:
144 - have a valid centroid
145 - not be deblended
146 - have a valid instFlux (of the type specified in this object's constructor)
147 - have adequate signal-to-noise
148 """
149 return self._hasCentroid_hasCentroid(sourceCat) \
150 & self._isParent_isParent(sourceCat) \
151 & self._goodSN_goodSN(sourceCat) \
152 & ~sourceCat.get(self.fluxFlagKeyfluxFlagKey)
153
154 def _isGood(self, sourceCat):
155 """
156 Return True for each source that is usable for matching, even if it may
157 have a poor centroid.
158
159 For a source to be usable it must:
160 - Not be on a CCD edge.
161 - Not have an interpolated pixel within 3x3 around their centroid.
162 - Not have a saturated pixel in their footprint.
163 """
164 return ~sourceCat.get(self.edgeKeyedgeKey) & \
165 ~sourceCat.get(self.interpolatedCenterKeyinterpolatedCenterKey) & \
166 ~sourceCat.get(self.saturatedKeysaturatedKey)
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72
def selectSources(self, sourceCat, matches=None, exposure=None)
Lightweight representation of a geometric match between two records.
Definition: Match.h:67