lsst.afw
g3a5ebb7d8a+28b83bf6a5
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
afw
table
catalogMatches.py
Go to the documentation of this file.
1
# This file is part of afw.
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__ = [
"makeMergedSchema"
,
"copyIntoCatalog"
,
23
"matchesToCatalog"
,
"matchesFromCatalog"
,
"copyAliasMapWithPrefix"
,
24
"reindexCatalog"
]
25
26
import
os.path
27
28
import
numpy
as
np
29
30
from
._schema
import
Schema
31
from
._schemaMapper
import
SchemaMapper
32
from
._base
import
BaseCatalog
33
from
._table
import
SimpleTable
34
from
._simple
import
SimpleCatalog
35
from
._source
import
SourceCatalog, SourceTable
36
from
._match
import
ReferenceMatch
37
38
from
lsst.utils
import
getPackageDir
39
40
41
def
makeMapper
(sourceSchema, targetSchema, sourcePrefix=None, targetPrefix=None):
42
"""Create a SchemaMapper between the input source and target schemas.
43
44
Parameters
45
----------
46
sourceSchema : :py:class:`lsst.afw.table.Schema`
47
Input source schema that fields will be mapped from.
48
targetSchema : :py:class:`lsst.afw.table.Schema`
49
Target schema that fields will be mapped to.
50
sourcePrefix : `str`, optional
51
If set, only those keys with that prefix will be mapped.
52
targetPrefix : `str`, optional
53
If set, prepend it to the mapped (target) key name.
54
55
Returns
56
-------
57
SchemaMapper : :py:class:`lsst.afw.table.SchemaMapper`
58
Mapping between source and target schemas.
59
"""
60
m =
SchemaMapper
(sourceSchema, targetSchema)
61
for
key, field
in
sourceSchema:
62
keyName = field.getName()
63
if
sourcePrefix
is
not
None
:
64
if
not
keyName.startswith(sourcePrefix):
65
continue
66
else
:
67
keyName = field.getName().replace(sourcePrefix,
""
, 1)
68
m.addMapping(key, (targetPrefix
or
""
) + keyName)
69
return
m
70
71
72
def
makeMergedSchema
(sourceSchema, targetSchema, sourcePrefix=None, targetPrefix=None):
73
"""Return a schema that is a deep copy of a mapping between source and target schemas.
74
75
Parameters
76
----------
77
sourceSchema : :py:class:`lsst.afw.table.Schema`
78
Input source schema that fields will be mapped from.
79
targetSchema : :py:class:`lsst.afw.atable.Schema`
80
Target schema that fields will be mapped to.
81
sourcePrefix : `str`, optional
82
If set, only those keys with that prefix will be mapped.
83
targetPrefix : `str`, optional
84
If set, prepend it to the mapped (target) key name.
85
86
Returns
87
-------
88
schema : :py:class:`lsst.afw.table.Schema`
89
Schema that is the result of the mapping between source and target schemas.
90
"""
91
return
makeMapper
(sourceSchema, targetSchema, sourcePrefix, targetPrefix).getOutputSchema()
92
93
94
def
copyIntoCatalog
(catalog, target, sourceSchema=None, sourcePrefix=None, targetPrefix=None):
95
"""Copy entries from one Catalog into another.
96
97
Parameters
98
----------
99
catalog : :py:class:`lsst.afw.table.base.Catalog`
100
Source catalog to be copied from.
101
target : :py:class:`lsst.afw.table.base.Catalog`
102
Target catalog to be copied to (edited in place).
103
sourceSchema : :py:class:`lsst.afw.table.Schema`, optional
104
Schema of source catalog.
105
sourcePrefix : `str`, optional
106
If set, only those keys with that prefix will be copied.
107
targetPrefix : `str`, optional
108
If set, prepend it to the copied (target) key name
109
110
Returns
111
-------
112
target : :py:class:`lsst.afw.table.base.Catalog`
113
Target catalog that is edited in place.
114
"""
115
if
sourceSchema
is
None
:
116
sourceSchema = catalog.schema
117
118
targetSchema = target.schema
119
target.reserve(len(catalog))
120
for
i
in
range(len(target), len(catalog)):
121
target.addNew()
122
123
if
len(catalog) != len(target):
124
raise
RuntimeError(f
"Length mismatch: {len(catalog)} vs {len(target)}"
)
125
126
m =
makeMapper
(sourceSchema, targetSchema, sourcePrefix, targetPrefix)
127
for
rFrom, rTo
in
zip(catalog, target):
128
rTo.assign(rFrom, m)
129
130
131
def
matchesToCatalog
(matches, matchMeta):
132
"""Denormalise matches into a Catalog of "unpacked matches".
133
134
Parameters
135
----------
136
matches : `~lsst.afw.table.match.SimpleMatch`
137
Unpacked matches, i.e. a list of Match objects whose schema
138
has "first" and "second" attributes which, resepectively,
139
contain the reference and source catalog entries, and a
140
"distance" field (the measured distance between the reference
141
and source objects).
142
matchMeta : `~lsst.daf.base.PropertySet`
143
Metadata for matches (must have .add attribute).
144
145
Returns
146
-------
147
mergedCatalog : :py:class:`lsst.afw.table.BaseCatalog`
148
Catalog of matches (with ``ref_`` and ``src_`` prefix identifiers for
149
referece and source entries, respectively, including alias
150
maps from reference and source catalogs)
151
"""
152
if
len(matches) == 0:
153
raise
RuntimeError(
"No matches provided."
)
154
155
refSchema = matches[0].first.getSchema()
156
srcSchema = matches[0].second.getSchema()
157
158
mergedSchema =
makeMergedSchema
(refSchema,
Schema
(), targetPrefix=
"ref_"
)
159
mergedSchema =
makeMergedSchema
(
160
srcSchema, mergedSchema, targetPrefix=
"src_"
)
161
162
mergedSchema =
copyAliasMapWithPrefix
(refSchema, mergedSchema, prefix=
"ref_"
)
163
mergedSchema =
copyAliasMapWithPrefix
(srcSchema, mergedSchema, prefix=
"src_"
)
164
165
distKey = mergedSchema.addField(
166
"distance"
, type=np.float64, doc=
"Distance between ref and src"
)
167
168
mergedCatalog =
BaseCatalog
(mergedSchema)
169
copyIntoCatalog
([m.first
for
m
in
matches], mergedCatalog,
170
sourceSchema=refSchema, targetPrefix=
"ref_"
)
171
copyIntoCatalog
([m.second
for
m
in
matches], mergedCatalog,
172
sourceSchema=srcSchema, targetPrefix=
"src_"
)
173
for
m, r
in
zip(matches, mergedCatalog):
174
r.set(distKey, m.distance)
175
176
# obtain reference catalog name if one is setup
177
try
:
178
catalogName = os.path.basename(getPackageDir(
"astrometry_net_data"
))
179
except
LookupError:
180
catalogName =
"NOT_SET"
181
matchMeta.add(
"REFCAT"
, catalogName)
182
mergedCatalog.getTable().setMetadata(matchMeta)
183
184
return
mergedCatalog
185
186
187
def
matchesFromCatalog
(catalog, sourceSlotConfig=None):
188
"""Generate a list of ReferenceMatches from a Catalog of "unpacked matches".
189
190
Parameters
191
----------
192
catalog : :py:class:`lsst.afw.table.BaseCatalog`
193
Catalog of matches. Must have schema where reference entries
194
are prefixed with ``ref_`` and source entries are prefixed with
195
``src_``.
196
sourceSlotConfig : `lsst.meas.base.baseMeasurement.SourceSlotConfig`, optional
197
Configuration for source slots.
198
199
Returns
200
-------
201
matches : :py:class:`lsst.afw.table.ReferenceMatch`
202
List of matches.
203
"""
204
refSchema =
makeMergedSchema
(
205
catalog.schema, SimpleTable.makeMinimalSchema(), sourcePrefix=
"ref_"
)
206
refCatalog =
SimpleCatalog
(refSchema)
207
copyIntoCatalog
(catalog, refCatalog, sourcePrefix=
"ref_"
)
208
209
srcSchema =
makeMergedSchema
(
210
catalog.schema, SourceTable.makeMinimalSchema(), sourcePrefix=
"src_"
)
211
srcCatalog =
SourceCatalog
(srcSchema)
212
copyIntoCatalog
(catalog, srcCatalog, sourcePrefix=
"src_"
)
213
214
if
sourceSlotConfig
is
not
None
:
215
sourceSlotConfig.setupSchema(srcCatalog.schema)
216
217
matches = []
218
distKey = catalog.schema.find(
"distance"
).key
219
for
ref, src, cat
in
zip(refCatalog, srcCatalog, catalog):
220
matches.append(
ReferenceMatch
(ref, src, cat[distKey]))
221
222
return
matches
223
224
225
def
copyAliasMapWithPrefix
(inSchema, outSchema, prefix=""):
226
"""Copy an alias map from one schema into another.
227
228
This copies the alias map of one schema into another, optionally
229
prepending a prefix to both the "from" and "to" names of the alias
230
(the example use case here is for the "match" catalog created by
231
`lsst.meas.astrom.denormalizeMatches` where prefixes ``src_`` and
232
``ref_`` are added to the source and reference field entries,
233
respectively).
234
235
Parameters
236
----------
237
inSchema : `lsst.afw.table.Schema`
238
The input schema whose `lsst.afw.table.AliasMap` is to be
239
copied to ``outSchema``.
240
outSchema : `lsst.afw.table.Schema`
241
The output schema into which the `lsst.afw.table.AliasMap`
242
from ``inSchema`` is to be copied (modified in place).
243
prefix : `str`, optional
244
An optional prefix to add to both the "from" and "to" names
245
of the alias (default is an empty string).
246
247
Returns
248
-------
249
outSchema : `lsst.afw.table.Schema`
250
The output schema with the alias mappings from `inSchema`
251
added.
252
"""
253
for
k, v
in
inSchema.getAliasMap().items():
254
outSchema.getAliasMap().set(prefix + k, prefix + v)
255
256
return
outSchema
257
258
259
def
reindexCatalog
(catalog, indices, deep=True):
260
"""Apply a numpy index array to an afw Catalog
261
262
Parameters
263
----------
264
catalog : `lsst.afw.table.SourceCatalog`
265
Catalog to reindex.
266
indices : `numpy.ndarray` of `int`
267
Index array.
268
deep : `bool`
269
Whether or not to make a deep copy of the original catalog.
270
271
Returns
272
-------
273
new : subclass of `lsst.afw.table.BaseCatalog`
274
Reindexed catalog. Records are shallow copies of those in ``catalog``.
275
"""
276
new =
SourceCatalog
(catalog.table.clone()
if
deep
else
catalog.table)
277
records = [catalog[int(ii)]
for
ii
in
indices]
278
new.extend(records, deep=deep)
279
return
new
lsst::afw::table._schema.Schema
Definition
_schema.py:91
lsst::afw::table._schemaMapper.SchemaMapper
Definition
_schemaMapper.py:32
lsst::afw::table._source.SourceCatalog
Definition
_source.py:33
lsst::afw::table::CatalogT< BaseRecord >
lsst::afw::table::SortedCatalogT< SimpleRecord >
lsst::afw::table.catalogMatches.makeMapper
makeMapper(sourceSchema, targetSchema, sourcePrefix=None, targetPrefix=None)
Definition
catalogMatches.py:41
lsst::afw::table.catalogMatches.copyAliasMapWithPrefix
copyAliasMapWithPrefix(inSchema, outSchema, prefix="")
Definition
catalogMatches.py:225
lsst::afw::table.catalogMatches.matchesFromCatalog
matchesFromCatalog(catalog, sourceSlotConfig=None)
Definition
catalogMatches.py:187
lsst::afw::table.catalogMatches.reindexCatalog
reindexCatalog(catalog, indices, deep=True)
Definition
catalogMatches.py:259
lsst::afw::table.catalogMatches.copyIntoCatalog
copyIntoCatalog(catalog, target, sourceSchema=None, sourcePrefix=None, targetPrefix=None)
Definition
catalogMatches.py:94
lsst::afw::table.catalogMatches.matchesToCatalog
matchesToCatalog(matches, matchMeta)
Definition
catalogMatches.py:131
lsst::afw::table.catalogMatches.makeMergedSchema
makeMergedSchema(sourceSchema, targetSchema, sourcePrefix=None, targetPrefix=None)
Definition
catalogMatches.py:72
lsst.utils
lsst::afw::table::Match< SimpleRecord, SourceRecord >
Generated on
for lsst.afw by
1.17.0