21__all__ = [
"tractBuilderRegistry",
"BaseTractBuilder",
22 "LegacyTractBuilder",
"CellTractBuilder"]
27from collections.abc
import Iterable
31from .patchInfo
import PatchInfo
32from .detail
import Index2D
36 """Configuration that is to be shared amongst all tract builders."""
41 """Base class for algorithms that define patches within the tract.
45 config : `lsst.pexConfig.Config`
46 Input for configuring the algorithm
52 """Set up the patches of a particular size in a tract.
54 We grow the tract bounding box to hold an exact multiple of
55 the desired size (patchInnerDimensions or
56 numCellsPerPatchInner*cellInnerDimensions),
while keeping
57 the center roughly the same. We
return the final tract
58 bounding box,
and the number of patches
in each dimension
64 Minimum bounding box
for tract
71 final bounding box, number of patches
75 bboxMin = bbox.getMin()
76 bboxDim = bbox.getDimensions()
77 numPatchesList = [0, 0]
78 for i, innerDim
in enumerate(self._patchInnerDimensions):
79 num = (bboxDim[i] + innerDim - 1) // innerDim
80 deltaDim = (innerDim*num) - bboxDim[i]
82 bboxDim[i] = innerDim * num
83 bboxMin[i] -= deltaDim // 2
84 numPatchesList[i] = num
85 numPatches =
Index2D(*numPatchesList)
92 return bbox, numPatches
95 return self._patchBorder
99 """Return information for the specified patch.
104 Index of patch,
as Index2D
or pair of ints;
105 or a sequential index
as returned by getSequentialPatchIndex;
106 negative values are
not supported.
108 WCS associated
with the tract.
113 The patch info
for that index.
118 If index
is out of range.
120 raise NotImplementedError(
"Must be implemented by a subclass")
123 """Get dimensions of inner region of the patches (all are the same)
125 return self._patchInnerDimensions
128 """Return a single integer that uniquely identifies
129 the given patch within this tract.
137 sequentialIndex : `int`
139 index = patchInfo.getIndex()
143 """Return a single integer that uniquely identifies
144 the patch index within the tract.
152 sequentialIndex : `int`
154 if isinstance(index, Index2D):
157 if not isinstance(index, Iterable):
158 raise ValueError(
"Input index is not an iterable.")
160 raise ValueError(
"Input index does not have two values.")
163 return nx*_index.y + _index.x
166 """Convert sequential index into patch index (x,y) pair.
170 sequentialIndex : `int`
177 x = sequentialIndex % nx
178 y = sequentialIndex // nx
183 """Get a packed config suitable for using in a sha1.
191 configPacked : `bytes`
193 raise NotImplementedError(
"Must be implemented by a subclass")
197 patchInnerDimensions = pexConfig.ListField(
198 doc=
"dimensions of inner region of patches (x,y pixels)",
201 default=(4000, 4000),
203 patchBorder = pexConfig.Field(
204 doc=
"border between patch inner and outer bbox (pixels)",
211 ConfigClass = LegacyTractBuilderConfig
217 for val
in config.patchInnerDimensions))
224 raise RuntimeError(
"Programmer error; this should always be initialized.")
225 if isinstance(index, Index2D):
228 if isinstance(index, numbers.Number):
232 if (
not 0 <= _index.x < self.
_numPatches_numPatches.x) \
233 or (
not 0 <= _index.y < self.
_numPatches_numPatches.y):
234 raise IndexError(
"Patch index %s is not in range [0-%d, 0-%d]" %
238 if not self.
_tractBBox_tractBBox.contains(innerBBox):
240 "Bug: patch index %s valid but inner bbox=%s not contained in tract bbox=%s" %
241 (_index, innerBBox, self.
_tractBBox_tractBBox))
254 subConfig = config.tractBuilder[config.tractBuilder.name]
255 configPacked = struct.pack(
257 subConfig.patchInnerDimensions[0],
258 subConfig.patchInnerDimensions[1],
259 subConfig.patchBorder,
262 config.projection.encode(
'ascii'),
270 cellInnerDimensions = pexConfig.ListField(
271 doc=
"dimensions of inner region of cells (x,y pixels)",
276 cellBorder = pexConfig.Field(
277 doc=
"Border between cell inner and outer bbox (pixels)",
281 numCellsPerPatchInner = pexConfig.Field(
282 doc=
"Number of cells per inner patch.",
286 numCellsInPatchBorder = pexConfig.Field(
287 doc=
"Number of cells in the patch border (outside the inner patch region).",
294 raise ValueError(
"cellInnerDimensions must be 2 ints.")
297 raise ValueError(
"cellInnerDimensions must be equal (for square cells).")
301 ConfigClass = CellTractBuilderConfig
307 for val
in config.cellInnerDimensions))
312 for val
in config.cellInnerDimensions))
314 self.
_patchBorder_patchBorder = config.numCellsInPatchBorder*config.cellInnerDimensions[0] + self.
_cellBorder_cellBorder
320 raise RuntimeError(
"Programmer error; this should always be initialized.")
321 if isinstance(index, Index2D):
324 if isinstance(index, numbers.Number):
328 if (
not 0 <= _index.x < self.
_numPatches_numPatches.x) \
329 or (
not 0 <= _index.y < self.
_numPatches_numPatches.y):
330 raise IndexError(
"Patch index %s is not in range [0-%d, 0-%d]" %
334 if not self.
_tractBBox_tractBBox.contains(innerBBox):
336 "Bug: patch index %s valid but inner bbox=%s not contained in tract bbox=%s" %
337 (_index, innerBBox, self.
_tractBBox_tractBBox))
354 subConfig = config.tractBuilder[config.tractBuilder.name]
355 configPacked = struct.pack(
357 subConfig.cellInnerDimensions[0],
358 subConfig.cellInnerDimensions[1],
359 subConfig.cellBorder,
360 subConfig.numCellsPerPatchInner,
361 subConfig.numCellsInPatchBorder,
364 config.projection.encode(
'ascii'),
371tractBuilderRegistry = pexConfig.makeRegistry(
372 doc=
"A registry of Tract Builders (subclasses of BaseTractBuilder)",
375tractBuilderRegistry.register(
"legacy", LegacyTractBuilder)
376tractBuilderRegistry.register(
"cells", CellTractBuilder)
def getSequentialPatchIndexFromPair(self, index)
def getPatchIndexPair(self, sequentialIndex)
def getPatchInnerDimensions(self)
def getPackedConfig(self, config)
def __init__(self, config)
def getPatchInfo(self, index, tractWcs)
def setupPatches(self, minBBox, wcs)
def getSequentialPatchIndex(self, patchInfo)
def __init__(self, config)
def getPatchInfo(self, index, tractWcs)
def getPackedConfig(self, config)
def __init__(self, config)
def getPatchInfo(self, index, tractWcs)
def getPackedConfig(self, config)