lsst.meas.algorithms
g4a7591d645+ff8a1bd350
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
meas
algorithms
setPrimaryFlags.py
Go to the documentation of this file.
1
# This file is part of meas_algorithms.
2
#
3
# Developed for the LSST Data Management System.
4
# This product includes software developed by the LSST Project
5
# (https://www.lsst.org).
6
# See the COPYRIGHT file at the top-level directory of this distribution
7
# for details of code ownership.
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 GNU General Public License
20
# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22
__all__ = [
"SetPrimaryFlagsConfig"
,
"SetPrimaryFlagsTask"
]
23
24
import
numpy
as
np
25
26
from
lsst.pex.config
import
Config, ListField
27
from
lsst.pipe.base
import
Task
28
from
lsst.geom
import
Box2D
29
30
31
class
SetPrimaryFlagsConfig
(Config):
32
pseudoFilterList = ListField(dtype=str, default=[
'sky'
],
33
doc=
"Names of filters which should never be primary"
)
34
35
36
class
SetPrimaryFlagsTask
(Task):
37
"""Set the ``isPrimary`` flag and either various blendedness, or
38
patch/tract flags to a catalog (for single frame or coadd catalogs,
39
respectively), based on other properties of the sources.
40
41
Parameters
42
----------
43
schema : `lsst.afw.table.Schema`
44
Source catalog schema to add fields to.
45
isSingleFrame : `bool`
46
Flag specifying if task is operating with single frame imaging.
47
includeDeblend : `bool`
48
Include deblend information in isPrimary and add blendedness fields?
49
50
Notes
51
-----
52
The tests for this task still live in
53
``pipe_tasks/tests/test_isPrimaryFlag.py``; see discussion on DM-42720.
54
"""
55
56
_DefaultName =
"setPrimaryFlags"
57
ConfigClass = SetPrimaryFlagsConfig
58
59
def
__init__
(self, *, schema, isSingleFrame=False, **kwargs):
60
super().
__init__
(**kwargs)
61
self.
schema
= schema
62
self.
isSingleFrame
= isSingleFrame
63
self.
includeDeblend
=
False
64
if
not
self.
isSingleFrame
:
65
primaryDoc = (
"True if source has no children and is in the inner region of a coadd patch "
66
"and is in the inner region of a coadd tract "
67
"and is not \"detected\" in a pseudo-filter (see config.pseudoFilterList)"
)
68
self.
isPatchInnerKey
= self.
schema
.addField(
69
"detect_isPatchInner"
, type=
"Flag"
,
70
doc=
"True if source is in the inner region of a coadd patch"
,
71
)
72
self.
isTractInnerKey
= self.
schema
.addField(
73
"detect_isTractInner"
, type=
"Flag"
,
74
doc=
"True if source is in the inner region of a coadd tract"
,
75
)
76
else
:
77
primaryDoc =
"True if source has no children and is not a sky source."
78
self.
isPrimaryKey
= self.
schema
.addField(
79
"detect_isPrimary"
, type=
"Flag"
,
80
doc=primaryDoc,
81
)
82
83
if
"deblend_nChild"
in
schema.getNames():
84
self.
includeDeblend
=
True
85
self.
isDeblendedSourceKey
= self.
schema
.addField(
86
"detect_isDeblendedSource"
, type=
"Flag"
,
87
doc=primaryDoc +
" and is either an unblended isolated source or a "
88
"deblended child from a parent with 'deblend_nChild' > 1"
)
89
self.
fromBlendKey
= self.
schema
.addField(
90
"detect_fromBlend"
, type=
"Flag"
,
91
doc=
"This source is deblended from a parent with more than one child."
92
)
93
self.
isIsolatedKey
= self.
schema
.addField(
94
"detect_isIsolated"
, type=
"Flag"
,
95
doc=
"This source is not a part of a blend."
96
)
97
if
"deblend_scarletFlux"
in
schema.getNames():
98
self.
isDeblendedModelKey
= self.
schema
.addField(
99
"detect_isDeblendedModelSource"
, type=
"Flag"
,
100
doc=primaryDoc +
" and is a deblended child"
)
101
else
:
102
self.
isDeblendedModelKey
=
None
103
104
def
run
(self, sources, skyMap=None, tractInfo=None, patchInfo=None):
105
"""Set isPrimary and related flags on sources.
106
107
For coadded imaging, the `isPrimary` flag returns True when an object
108
has no children, is in the inner region of a coadd patch, is in the
109
inner region of a coadd trach, and is not detected in a pseudo-filter
110
(e.g., a sky_object).
111
For single frame imaging, the isPrimary flag returns True when a
112
source has no children and is not a sky source.
113
114
Parameters
115
----------
116
sources : `lsst.afw.table.SourceCatalog`
117
A sourceTable. Reads in centroid fields and an nChild field.
118
Writes is-patch-inner, is-tract-inner, and is-primary flags.
119
skyMap : `lsst.skymap.BaseSkyMap`
120
Sky tessellation object
121
tractInfo : `lsst.skymap.TractInfo`, optional
122
Tract object; required if ``self.isSingleFrame`` is False.
123
patchInfo : `lsst.skymap.PatchInfo`
124
Patch object; required if ``self.isSingleFrame`` is False.
125
"""
126
# Mark whether sources are contained within the inner regions of the
127
# given tract/patch and are not "pseudo" (e.g. sky) sources.
128
if
not
self.
isSingleFrame
:
129
isPatchInner =
getPatchInner
(sources, patchInfo)
130
isTractInner =
getTractInner
(sources, tractInfo, skyMap)
131
isPseudo = self.
_getPseudoSources
(sources)
132
isPrimary = isTractInner & isPatchInner & ~isPseudo
133
134
sources[self.
isPatchInnerKey
] = isPatchInner
135
sources[self.
isTractInnerKey
] = isTractInner
136
else
:
137
# Mark all of the sky sources in SingleFrame images
138
# (if they were added)
139
if
"sky_source"
in
sources.schema:
140
isSky = sources[
"sky_source"
]
141
else
:
142
isSky = np.zeros(len(sources), dtype=bool)
143
isPrimary = ~isSky
144
145
if
self.
includeDeblend
:
146
result =
getDeblendPrimaryFlags
(sources)
147
fromBlend, isIsolated, isDeblendedSource, isDeblendedModelSource = result
148
sources[self.
fromBlendKey
] = fromBlend
149
sources[self.
isIsolatedKey
] = isIsolated
150
sources[self.
isDeblendedSourceKey
] = isDeblendedSource
151
if
self.
isDeblendedModelKey
is
not
None
:
152
sources[self.
isDeblendedModelKey
] = isDeblendedModelSource
153
isPrimary = isPrimary & isDeblendedSource
154
155
sources[self.
isPrimaryKey
] = isPrimary
156
157
def
_getPseudoSources
(self, sources):
158
"""Get a flag that marks pseudo sources.
159
160
Some categories of sources, for example sky objects, are not really
161
detected sources and should not be considered primary sources.
162
163
Parameters
164
----------
165
sources : `lsst.afw.table.SourceCatalog`
166
The catalog of sources for which to identify "pseudo"
167
(e.g. sky) objects.
168
169
Returns
170
-------
171
isPseudo : array-like of `bool`
172
True for each source that is a pseudo source.
173
Note: to remove pseudo sources use `~isPseudo`.
174
"""
175
# Filter out sources that should never be primary.
176
isPseudo = np.zeros(len(sources), dtype=bool)
177
for
filt
in
self.config.pseudoFilterList:
178
try
:
179
pseudoFilterKey = self.
schema
.find(
"merge_peak_%s"
% filt).getKey()
180
isPseudo |= sources[pseudoFilterKey]
181
except
KeyError:
182
self.log.warning(
"merge_peak is not set for pseudo-filter %s"
, filt)
183
return
isPseudo
184
185
186
def
getPatchInner
(sources, patchInfo):
187
"""Set a flag for each source if it is in the innerBBox of a patch.
188
189
Parameters
190
----------
191
sources : `lsst.afw.table.SourceCatalog`
192
A sourceCatalog with pre-calculated centroids.
193
patchInfo : `lsst.skymap.PatchInfo`
194
Information about a `SkyMap` `Patch`.
195
196
Returns
197
-------
198
isPatchInner : array-like of `bool`
199
`True` for each source that has a centroid
200
in the inner region of a patch.
201
"""
202
# Extract the centroid position for all the sources
203
x = sources[
"slot_Centroid_x"
]
204
y = sources[
"slot_Centroid_y"
]
205
centroidFlag = sources[
"slot_Centroid_flag"
]
206
207
# set inner flags for each source and set primary flags for
208
# sources with no children (or all sources if deblend info not available)
209
innerFloatBBox =
Box2D
(patchInfo.getInnerBBox())
210
inInner = innerFloatBBox.contains(x, y)
211
212
# When the centroider fails, we can still fall back to the peak,
213
# but we don't trust that quite as much -
214
# so we use a slightly smaller box for the patch comparison.
215
shrunkInnerFloatBBox =
Box2D
(innerFloatBBox)
216
shrunkInnerFloatBBox.grow(-1)
217
inShrunkInner = shrunkInnerFloatBBox.contains(x, y)
218
219
# Flag sources contained in the inner region of a patch
220
isPatchInner = (centroidFlag & inShrunkInner) | (~centroidFlag & inInner)
221
return
isPatchInner
222
223
224
def
getTractInner
(sources, tractInfo, skyMap):
225
"""Set a flag for each source that the skyMap includes in tractInfo.
226
227
Parameters
228
----------
229
sources : `lsst.afw.table.SourceCatalog`
230
A sourceCatalog with pre-calculated centroids.
231
tractInfo : `lsst.skymap.TractInfo`
232
Tract object
233
skyMap : `lsst.skymap.BaseSkyMap`
234
Sky tessellation object
235
236
Returns
237
-------
238
isTractInner : array-like of `bool`
239
True if the skyMap.findTract method returns
240
the same tract as tractInfo.
241
"""
242
tractId = tractInfo.getId()
243
isTractInner = np.array([skyMap.findTract(s.getCoord()).getId() == tractId
for
s
in
sources])
244
return
isTractInner
245
246
247
def
getDeblendPrimaryFlags
(sources):
248
"""Get flags generated by the deblender.
249
250
scarlet is different than meas_deblender in that it is not
251
(necessarily) flux conserving. For consistency in scarlet,
252
all of the parents with only a single child (isolated sources)
253
need to be deblended. This creates a question: which type
254
of isolated source should we make measurements on, the
255
undeblended "parent" or the deblended child?
256
For that reason we distinguish between a DeblendedSource,
257
which is a source that has no children and uses the
258
isolated parents, and a DeblendedModelSource, which uses
259
the scarlet models for both isolated and blended sources.
260
In the case of meas_deblender, DeblendedModelSource is
261
`None` because it is not contained in the output catalog.
262
263
Parameters
264
----------
265
sources : `lsst.afw.table.SourceCatalog`
266
A sourceCatalog that has already been deblended using
267
either meas_extensions_scarlet or meas_deblender.
268
269
Returns
270
-------
271
fromBlend : array-like of `bool`
272
True for each source modeled by the deblender from a `Peak`
273
in a parent footprint that contained at least one other `Peak`.
274
While these models can be approximated as isolated,
275
and measurements are made on them as if that's the case,
276
we know deblending to introduce biases in the shape and centroid
277
of objects and it is important to know that the sources that these
278
models are based on are all bleneded in the true image.
279
isIsolated : array-like of `bool`
280
True for isolated sources, regardless of whether or not they
281
were modeled by the deblender.
282
isDeblendedSource : array-like of `bool`
283
True for each source that is a "DeblendedSource" as defined above.
284
isDeblendedModelSource : array-like of `bool`
285
True for each source that is a "DeblendedSourceModel"
286
as defined above.
287
"""
288
parent = sources[
"parent"
]
289
290
if
"deblend_scarletFlux"
in
sources.schema:
291
# The number of peaks in the parent footprint
292
parentNChild = sources[
"deblend_parentNChild"
]
293
# The number of peaks in the deconvolved-parent footprint
294
blendNChild = sources[
"deblend_blendNChild"
]
295
fromBlend = parentNChild > 1
296
isIsolated = (blendNChild == 0) | (parentNChild == 1)
297
isDeblendedSource = (blendNChild == 0) | (parentNChild > 1)
298
isDeblendedModelSource = parent != 0
299
else
:
300
nChildKey =
"deblend_nChild"
301
nChild = sources[nChildKey]
302
parent = sources[
"parent"
]
303
# Set the flags for meas_deblender
304
fromBlend = parent != 0
305
isIsolated = (nChild == 0) & (parent == 0)
306
isDeblendedSource = nChild == 0
307
isDeblendedModelSource =
None
308
return
fromBlend, isIsolated, isDeblendedSource, isDeblendedModelSource
lsst::geom::Box2D
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsConfig
Definition
setPrimaryFlags.py:31
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask
Definition
setPrimaryFlags.py:36
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.run
run(self, sources, skyMap=None, tractInfo=None, patchInfo=None)
Definition
setPrimaryFlags.py:104
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isPrimaryKey
isPrimaryKey
Definition
setPrimaryFlags.py:78
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.fromBlendKey
fromBlendKey
Definition
setPrimaryFlags.py:89
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask._getPseudoSources
_getPseudoSources(self, sources)
Definition
setPrimaryFlags.py:157
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isIsolatedKey
isIsolatedKey
Definition
setPrimaryFlags.py:93
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isDeblendedModelKey
isDeblendedModelKey
Definition
setPrimaryFlags.py:98
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.schema
schema
Definition
setPrimaryFlags.py:61
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isTractInnerKey
isTractInnerKey
Definition
setPrimaryFlags.py:72
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isSingleFrame
isSingleFrame
Definition
setPrimaryFlags.py:62
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isPatchInnerKey
isPatchInnerKey
Definition
setPrimaryFlags.py:68
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.__init__
__init__(self, *, schema, isSingleFrame=False, **kwargs)
Definition
setPrimaryFlags.py:59
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.isDeblendedSourceKey
isDeblendedSourceKey
Definition
setPrimaryFlags.py:85
lsst::meas::algorithms.setPrimaryFlags.SetPrimaryFlagsTask.includeDeblend
bool includeDeblend
Definition
setPrimaryFlags.py:63
lsst::geom
lsst::meas::algorithms.setPrimaryFlags.getTractInner
getTractInner(sources, tractInfo, skyMap)
Definition
setPrimaryFlags.py:224
lsst::meas::algorithms.setPrimaryFlags.getDeblendPrimaryFlags
getDeblendPrimaryFlags(sources)
Definition
setPrimaryFlags.py:247
lsst::meas::algorithms.setPrimaryFlags.getPatchInner
getPatchInner(sources, patchInfo)
Definition
setPrimaryFlags.py:186
lsst::pex::config
lsst.pipe.base
Generated on
for lsst.meas.algorithms by
1.17.0