lsst.skymap
g6512b7a353+6ecdf13bca
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
skymap
tractBuilder.py
Go to the documentation of this file.
1
# LSST Data Management System
2
# Copyright 2008, 2009, 2010 LSST Corporation.
3
#
4
# This product includes software developed by the
5
# LSST Project (http://www.lsst.org/).
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the LSST License Statement and
18
# the GNU General Public License along with this program. If not,
19
# see <http://www.lsstcorp.org/LegalNotices/>.
20
#
21
__all__ = [
"tractBuilderRegistry"
,
22
"BaseTractBuilderConfig"
,
"BaseTractBuilder"
,
23
"LegacyTractBuilderConfig"
,
"LegacyTractBuilder"
,
24
"CellTractBuilderConfig"
,
"CellTractBuilder"
]
25
26
import
abc
27
import
numbers
28
import
struct
29
from
collections.abc
import
Iterable
30
31
import
lsst.pex.config
as
pexConfig
32
import
lsst.geom
as
geom
33
from
.patchInfo
import
PatchInfo
34
from
.detail
import
Index2D
35
36
37
class
BaseTractBuilderConfig
(pexConfig.Config):
38
"""Configuration that is to be shared amongst all tract builders."""
39
pass
40
41
42
class
BaseTractBuilder
(metaclass=abc.ABCMeta):
43
"""Base class for algorithms that define patches within the tract.
44
45
Parameters
46
----------
47
config : `lsst.pexConfig.Config`
48
Input for configuring the algorithm
49
"""
50
def
__init__
(self, config):
51
self.
config
= config
52
53
def
setupPatches
(self, minBBox, wcs):
54
"""Set up the patches of a particular size in a tract.
55
56
We grow the tract bounding box to hold an exact multiple of
57
the desired size (patchInnerDimensions or
58
numCellsPerPatchInner*cellInnerDimensions), while keeping
59
the center roughly the same. We return the final tract
60
bounding box, and the number of patches in each dimension
61
(as an Index2D).
62
63
Parameters
64
----------
65
minBBox : `lsst.geom.Box2I`
66
Minimum bounding box for tract.
67
wcs : `lsst.afw.geom.SkyWcs`
68
Wcs object.
69
70
Returns
71
-------
72
bbox : `lsst.geom.Box2I`
73
final bounding box, number of patches.
74
numPatches : `lsst.skymap.Index2D`
75
"""
76
bbox =
geom.Box2I
(minBBox)
77
bboxMin = bbox.getMin()
78
bboxDim = bbox.getDimensions()
79
numPatchesList = [0, 0]
80
for
i, innerDim
in
enumerate(self.
_patchInnerDimensions
):
81
num = (bboxDim[i] + innerDim - 1) // innerDim
# round up
82
deltaDim = (innerDim*num) - bboxDim[i]
83
if
deltaDim > 0:
84
bboxDim[i] = innerDim * num
85
bboxMin[i] -= deltaDim // 2
86
numPatchesList[i] = num
87
numPatches =
Index2D
(*numPatchesList)
88
bbox =
geom.Box2I
(bboxMin, bboxDim)
89
self.
_numPatches
= numPatches
90
# The final tract BBox starts at zero.
91
self.
_tractBBox
=
geom.Box2I
(
geom.Point2I
(0, 0), bbox.getDimensions())
92
self.
_initialized
=
True
93
94
return
bbox, numPatches
95
96
def
getPatchBorder
(self):
97
return
self._patchBorder
98
99
@abc.abstractmethod
100
def
getPatchInfo
(self, index, tractWcs):
101
"""Return information for the specified patch.
102
103
Parameters
104
----------
105
index : `lsst.skymap.Index2D` or `~collections.abc.Iterable` of 2 `int`
106
Index of patch, as Index2D or pair of ints;
107
or a sequential index as returned by getSequentialPatchIndex;
108
negative values are not supported.
109
tractWcs : `lsst.afw.geom.SkyWcs`
110
WCS associated with the tract.
111
112
Returns
113
-------
114
result : `lsst.skymap.PatchInfo`
115
The patch info for that index.
116
117
Raises
118
------
119
IndexError
120
Raised if index is out of range.
121
"""
122
raise
NotImplementedError(
"Must be implemented by a subclass"
)
123
124
def
getPatchInnerDimensions
(self):
125
"""Get dimensions of inner region of the patches (all are the same)
126
"""
127
return
self.
_patchInnerDimensions
128
129
def
getSequentialPatchIndex
(self, patchInfo):
130
"""Return a single integer that uniquely identifies
131
the given patch within this tract.
132
133
Parameters
134
----------
135
patchInfo : `lsst.skymap.PatchInfo`
136
137
Returns
138
-------
139
sequentialIndex : `int`
140
"""
141
index = patchInfo.getIndex()
142
return
self.
getSequentialPatchIndexFromPair
(index)
143
144
def
getSequentialPatchIndexFromPair
(self, index):
145
"""Return a single integer that uniquely identifies
146
the patch index within the tract.
147
148
Parameters
149
----------
150
index : `lsst.skymap.Index2D` or `~collections.abc.Iterable` of 2 `int`
151
152
Returns
153
-------
154
sequentialIndex : `int`
155
"""
156
if
isinstance(index, Index2D):
157
_index = index
158
else
:
159
if
not
isinstance(index, Iterable):
160
raise
ValueError(
"Input index is not an iterable."
)
161
if
len(index) != 2:
162
raise
ValueError(
"Input index does not have two values."
)
163
_index =
Index2D
(*index)
164
nx, ny = self.
_numPatches
165
return
nx*_index.y + _index.x
166
167
def
getPatchIndexPair
(self, sequentialIndex):
168
"""Convert sequential index into patch index (x,y) pair.
169
170
Parameters
171
----------
172
sequentialIndex : `int`
173
174
Returns
175
-------
176
x, y : `lsst.skymap.Index2D`
177
"""
178
nx, ny = self.
_numPatches
179
x = sequentialIndex % nx
180
y = sequentialIndex // nx
181
return
Index2D
(x=x, y=y)
182
183
@abc.abstractmethod
184
def
getPackedConfig
(self, config):
185
"""Get a packed config suitable for using in a sha1.
186
187
Parameters
188
----------
189
config : `lsst.skymap.BaseTractBuilderConfig`
190
191
Returns
192
-------
193
configPacked : `bytes`
194
"""
195
raise
NotImplementedError(
"Must be implemented by a subclass"
)
196
197
198
class
LegacyTractBuilderConfig
(
BaseTractBuilderConfig
):
199
patchInnerDimensions = pexConfig.ListField(
200
doc=
"dimensions of inner region of patches (x,y pixels)"
,
201
dtype=int,
202
length=2,
203
default=(4000, 4000),
204
)
205
patchBorder = pexConfig.Field(
206
doc=
"border between patch inner and outer bbox (pixels)"
,
207
dtype=int,
208
default=100,
209
)
210
211
212
class
LegacyTractBuilder
(
BaseTractBuilder
):
213
ConfigClass = LegacyTractBuilderConfig
214
215
def
__init__
(self, config):
216
super().
__init__
(config)
217
218
self.
_patchInnerDimensions
=
geom.Extent2I
(*(val
219
for
val
in
config.patchInnerDimensions))
220
self.
_patchBorder
= config.patchBorder
221
self.
_initialized
=
False
222
223
def
getPatchInfo
(self, index, tractWcs):
224
# This should always be initialized
225
if
not
self.
_initialized
:
226
raise
RuntimeError(
"Programmer error; this should always be initialized."
)
227
if
isinstance(index, Index2D):
228
_index = index
229
else
:
230
if
isinstance(index, numbers.Number):
231
_index = self.
getPatchIndexPair
(index)
232
else
:
233
_index =
Index2D
(*index)
234
if
(
not
0 <= _index.x < self.
_numPatches
.x) \
235
or
(
not
0 <= _index.y < self.
_numPatches
.y):
236
raise
IndexError(
"Patch index %s is not in range [0-%d, 0-%d]"
%
237
(_index, self.
_numPatches
.x - 1, self.
_numPatches
.y - 1))
238
innerMin =
geom.Point2I
(*[_index[i] * self.
_patchInnerDimensions
[i]
for
i
in
range(2)])
239
innerBBox =
geom.Box2I
(innerMin, self.
_patchInnerDimensions
)
240
if
not
self.
_tractBBox
.contains(innerBBox):
241
raise
RuntimeError(
242
"Bug: patch index %s valid but inner bbox=%s not contained in tract bbox=%s"
%
243
(_index, innerBBox, self.
_tractBBox
))
244
outerBBox =
geom.Box2I
(innerBBox)
245
outerBBox.grow(self.
getPatchBorder
())
246
outerBBox.clip(self.
_tractBBox
)
247
return
PatchInfo
(
248
index=_index,
249
innerBBox=innerBBox,
250
outerBBox=outerBBox,
251
sequentialIndex=self.
getSequentialPatchIndexFromPair
(_index),
252
tractWcs=tractWcs
253
)
254
255
def
getPackedConfig
(self, config):
256
subConfig = config.tractBuilder[config.tractBuilder.name]
257
configPacked = struct.pack(
258
"<iiidd3sd"
,
259
subConfig.patchInnerDimensions[0],
260
subConfig.patchInnerDimensions[1],
261
subConfig.patchBorder,
262
config.tractOverlap,
263
config.pixelScale,
264
config.projection.encode(
'ascii'
),
265
config.rotation
266
)
267
268
return
configPacked
269
270
271
class
CellTractBuilderConfig
(
BaseTractBuilderConfig
):
272
cellInnerDimensions = pexConfig.ListField(
273
doc=
"dimensions of inner region of cells (x,y pixels)"
,
274
dtype=int,
275
length=2,
276
default=(150, 150),
277
)
278
cellBorder = pexConfig.Field(
279
doc=
"Border between cell inner and outer bbox (pixels)"
,
280
dtype=int,
281
default=50,
282
)
283
numCellsPerPatchInner = pexConfig.Field(
284
doc=
"Number of cells per inner patch."
,
285
dtype=int,
286
default=20,
287
)
288
numCellsInPatchBorder = pexConfig.Field(
289
doc=
"Number of cells in the patch border (outside the inner patch region)."
,
290
dtype=int,
291
default=1,
292
)
293
294
def
validate
(self):
295
if
len(self.
cellInnerDimensions
) != 2:
296
raise
ValueError(
"cellInnerDimensions must be 2 ints."
)
297
298
if
self.
cellInnerDimensions
[0] != self.
cellInnerDimensions
[1]:
299
raise
ValueError(
"cellInnerDimensions must be equal (for square cells)."
)
300
301
302
class
CellTractBuilder
(
BaseTractBuilder
):
303
ConfigClass = CellTractBuilderConfig
304
305
def
__init__
(self, config):
306
super().
__init__
(config)
307
308
self.
_cellInnerDimensions
=
geom.Extent2I
(*(val
309
for
val
in
config.cellInnerDimensions))
310
self.
_cellBorder
= config.cellBorder
311
self.
_numCellsPerPatchInner
= config.numCellsPerPatchInner
312
self.
_numCellsInPatchBorder
= config.numCellsInPatchBorder
313
self.
_patchInnerDimensions
=
geom.Extent2I
(*(val*self.
_numCellsPerPatchInner
314
for
val
in
config.cellInnerDimensions))
315
# The patch border is the number of cells in the border + the cell
316
# border.
317
self.
_patchBorder
= config.numCellsInPatchBorder*config.cellInnerDimensions[0] + self.
_cellBorder
318
self.
_initialized
=
False
319
320
def
getPatchInfo
(self, index, tractWcs):
321
# This should always be initialized
322
if
not
self.
_initialized
:
323
raise
RuntimeError(
"Programmer error; this should always be initialized."
)
324
if
isinstance(index, Index2D):
325
_index = index
326
else
:
327
if
isinstance(index, numbers.Number):
328
_index = self.
getPatchIndexPair
(index)
329
else
:
330
_index =
Index2D
(*index)
331
if
(
not
0 <= _index.x < self.
_numPatches
.x) \
332
or
(
not
0 <= _index.y < self.
_numPatches
.y):
333
raise
IndexError(
"Patch index %s is not in range [0-%d, 0-%d]"
%
334
(_index, self.
_numPatches
.x - 1, self.
_numPatches
.y - 1))
335
innerMin =
geom.Point2I
(*[_index[i]*self.
_patchInnerDimensions
[i]
for
i
in
range(2)])
336
innerBBox =
geom.Box2I
(innerMin, self.
_patchInnerDimensions
)
337
if
not
self.
_tractBBox
.contains(innerBBox):
338
raise
RuntimeError(
339
"Bug: patch index %s valid but inner bbox=%s not contained in tract bbox=%s"
%
340
(_index, innerBBox, self.
_tractBBox
))
341
outerBBox =
geom.Box2I
(innerBBox)
342
outerBBox.grow(self.
getPatchBorder
())
343
# We do not clip the patch for cell-based tracts.
344
return
PatchInfo
(
345
index=_index,
346
innerBBox=innerBBox,
347
outerBBox=outerBBox,
348
sequentialIndex=self.
getSequentialPatchIndexFromPair
(_index),
349
tractWcs=tractWcs,
350
cellInnerDimensions=self.
_cellInnerDimensions
,
351
cellBorder=self.
_cellBorder
,
352
numCellsPerPatchInner=self.
_numCellsPerPatchInner
,
353
numCellsInPatchBorder=self.
_numCellsInPatchBorder
354
)
355
356
def
getPackedConfig
(self, config):
357
subConfig = config.tractBuilder[config.tractBuilder.name]
358
configPacked = struct.pack(
359
"<iiiiidd3sd"
,
360
subConfig.cellInnerDimensions[0],
361
subConfig.cellInnerDimensions[1],
362
subConfig.cellBorder,
363
subConfig.numCellsPerPatchInner,
364
subConfig.numCellsInPatchBorder,
365
config.tractOverlap,
366
config.pixelScale,
367
config.projection.encode(
'ascii'
),
368
config.rotation
369
)
370
371
return
configPacked
372
373
374
tractBuilderRegistry = pexConfig.makeRegistry(
375
doc=
"A registry of Tract Builders (subclasses of BaseTractBuilder)"
,
376
)
377
378
tractBuilderRegistry.register(
"legacy"
, LegacyTractBuilder)
379
tractBuilderRegistry.register(
"cells"
, CellTractBuilder)
lsst::geom::Box2I
lsst::geom::Extent< int, 2 >
lsst::geom::Point< int, 2 >
lsst.skymap.detail.utils.Index2D
Definition
utils.py:81
lsst.skymap.patchInfo.PatchInfo
Definition
patchInfo.py:33
lsst.skymap.tractBuilder.BaseTractBuilderConfig
Definition
tractBuilder.py:37
lsst.skymap.tractBuilder.BaseTractBuilder
Definition
tractBuilder.py:42
lsst.skymap.tractBuilder.BaseTractBuilder.getPatchInfo
getPatchInfo(self, index, tractWcs)
Definition
tractBuilder.py:100
lsst.skymap.tractBuilder.BaseTractBuilder.getSequentialPatchIndex
getSequentialPatchIndex(self, patchInfo)
Definition
tractBuilder.py:129
lsst.skymap.tractBuilder.BaseTractBuilder.__init__
__init__(self, config)
Definition
tractBuilder.py:50
lsst.skymap.tractBuilder.BaseTractBuilder._patchInnerDimensions
_patchInnerDimensions
Definition
tractBuilder.py:80
lsst.skymap.tractBuilder.BaseTractBuilder._tractBBox
_tractBBox
Definition
tractBuilder.py:91
lsst.skymap.tractBuilder.BaseTractBuilder.setupPatches
setupPatches(self, minBBox, wcs)
Definition
tractBuilder.py:53
lsst.skymap.tractBuilder.BaseTractBuilder.getPatchIndexPair
getPatchIndexPair(self, sequentialIndex)
Definition
tractBuilder.py:167
lsst.skymap.tractBuilder.BaseTractBuilder.config
config
Definition
tractBuilder.py:51
lsst.skymap.tractBuilder.BaseTractBuilder.getPackedConfig
getPackedConfig(self, config)
Definition
tractBuilder.py:184
lsst.skymap.tractBuilder.BaseTractBuilder._numPatches
_numPatches
Definition
tractBuilder.py:89
lsst.skymap.tractBuilder.BaseTractBuilder._initialized
bool _initialized
Definition
tractBuilder.py:92
lsst.skymap.tractBuilder.BaseTractBuilder.getPatchInnerDimensions
getPatchInnerDimensions(self)
Definition
tractBuilder.py:124
lsst.skymap.tractBuilder.BaseTractBuilder.getPatchBorder
getPatchBorder(self)
Definition
tractBuilder.py:96
lsst.skymap.tractBuilder.BaseTractBuilder.getSequentialPatchIndexFromPair
getSequentialPatchIndexFromPair(self, index)
Definition
tractBuilder.py:144
lsst.skymap.tractBuilder.CellTractBuilderConfig
Definition
tractBuilder.py:271
lsst.skymap.tractBuilder.CellTractBuilderConfig.cellInnerDimensions
cellInnerDimensions
Definition
tractBuilder.py:272
lsst.skymap.tractBuilder.CellTractBuilderConfig.validate
validate(self)
Definition
tractBuilder.py:294
lsst.skymap.tractBuilder.CellTractBuilder
Definition
tractBuilder.py:302
lsst.skymap.tractBuilder.CellTractBuilder._numCellsInPatchBorder
_numCellsInPatchBorder
Definition
tractBuilder.py:312
lsst.skymap.tractBuilder.CellTractBuilder._cellInnerDimensions
_cellInnerDimensions
Definition
tractBuilder.py:308
lsst.skymap.tractBuilder.CellTractBuilder._cellBorder
_cellBorder
Definition
tractBuilder.py:310
lsst.skymap.tractBuilder.CellTractBuilder._numCellsPerPatchInner
_numCellsPerPatchInner
Definition
tractBuilder.py:311
lsst.skymap.tractBuilder.CellTractBuilder.__init__
__init__(self, config)
Definition
tractBuilder.py:305
lsst.skymap.tractBuilder.CellTractBuilder.getPatchInfo
getPatchInfo(self, index, tractWcs)
Definition
tractBuilder.py:320
lsst.skymap.tractBuilder.CellTractBuilder.getPackedConfig
getPackedConfig(self, config)
Definition
tractBuilder.py:356
lsst.skymap.tractBuilder.CellTractBuilder._patchBorder
_patchBorder
Definition
tractBuilder.py:317
lsst.skymap.tractBuilder.LegacyTractBuilderConfig
Definition
tractBuilder.py:198
lsst.skymap.tractBuilder.LegacyTractBuilder
Definition
tractBuilder.py:212
lsst.skymap.tractBuilder.LegacyTractBuilder.getPackedConfig
getPackedConfig(self, config)
Definition
tractBuilder.py:255
lsst.skymap.tractBuilder.LegacyTractBuilder.__init__
__init__(self, config)
Definition
tractBuilder.py:215
lsst.skymap.tractBuilder.LegacyTractBuilder.getPatchInfo
getPatchInfo(self, index, tractWcs)
Definition
tractBuilder.py:223
lsst.skymap.tractBuilder.LegacyTractBuilder._patchBorder
_patchBorder
Definition
tractBuilder.py:220
lsst::geom
lsst::pex::config
Generated on
for lsst.skymap by
1.17.0