2 from .image
import LOCAL, PARENT, ImageOrigin
4 __all__ = [
"supportSlicing"]
8 """Separate the actual slice from origin arguments to __getitem__ or
9 __setitem__, using PARENT for the origin if it is not provided.
13 sliceArgs : `tuple`, `Box2I`, or `Point2I`
14 The first argument passed to an image-like object's
15 ``__getitem__`` or ``__setitem__``.
19 sliceArgs : `tuple`, `Box2I`, or `Point2I`
20 The original sliceArgs passed in, with any ImageOrigin argument
22 origin : `ImageOrigin`
23 Enum value that sets whether or not to consider xy0 in positions.
25 See interpretSliceArgs for more information.
27 Intended primarily for internal use by `supportSlicing()`.
29 defaultOrigin = PARENT
31 if isinstance(sliceArgs[-1], ImageOrigin):
33 if len(sliceArgs) == 2:
34 return sliceArgs[0], sliceArgs[-1]
36 return sliceArgs[:-1], sliceArgs[-1]
39 return sliceArgs, defaultOrigin
41 return sliceArgs, defaultOrigin
45 """Handle negative indices passed to image accessors.
47 When negative indices are used in LOCAL coordinates, we interpret them as
48 relative to the upper bounds of the array, as in regular negative indexing
51 Using negative indices in PARENT coordinates is not allowed unless passed
52 via a `Point2I` or `Box2I`; the potential for confusion between actual
53 negative indices (when ``xy0 < 0``) and offsets relative to the upper
54 bounds of the array is too great.
58 index : `int` or `None`
59 1-d pixel index to interpret, as given by a caller to an image-like
60 object's ``__getitem__`` or ``__setitem__``.
62 Size of the image in the dimension corresponding to ``index``.
63 origin : `ImageOrigin`
64 Enum value that sets whether or not to consider xy0 in positions.
66 Index to return if `index` is None.
71 If ``origin==PARENT``, either the given ``index`` or ``default``.
72 If ``origin==LOCAL``, an equivalent index guaranteed to be nonnegative.
74 Intended primarily for internal use by `supportSlicing()`.
77 assert default
is not None
83 raise IndexError(
"Negative indices are not permitted with the PARENT origin. "
84 "Use LOCAL to use negative to index relative to the end, "
85 "and Point2I or Box2I indexing to access negative pixels "
86 "in PARENT coordinates.")
91 """Transform a tuple of slice objects into a Box2I, correctly handling negative indices.
93 see `interpretSliceArgs` for a description of parameters
97 box : `Box2I` or `None`
98 A box to use to create a subimage, or None if the slice refers to a
100 index: `tuple` or `None`
101 An ``(x, y)`` tuple of integers, or None if the slice refers to a
103 origin : `ImageOrigin`
104 Enum indicating whether to account for xy0.
107 if isinstance(slices, Point2I):
108 return None, slices, origin
109 elif isinstance(slices, Box2I):
110 return slices,
None, origin
114 if isinstance(x, slice):
115 assert isinstance(y, slice)
116 if x.step
is not None or y.step
is not None:
117 raise ValueError(
"Slices with steps are not supported in image indexing.")
118 begin =
Point2I(x.start, y.start)
120 return Box2I(begin, end - begin),
None, origin
122 assert not isinstance(y, slice)
123 return None,
Point2I(x, y), origin
127 """Transform arguments to __getitem__ or __setitem__ to a standard form.
131 sliceArgs : `tuple`, `Box2I`, or `Point2I`
132 Slice arguments passed directly to `__getitem__` or `__setitem__`.
133 bboxGetter : callable
134 Callable that accepts an ImageOrigin enum value and returns the
135 appropriate image bounding box. Usually the bound getBBox method
136 of an Image, Mask, or MaskedImage object.
141 Index or slice in the x dimension
143 Index or slice in the y dimension
144 origin : `ImageOrigin`
145 Either `PARENT` (coordinates respect XY0) or LOCAL
146 (coordinates do not respect XY0)
149 if isinstance(slices, Point2I):
150 return slices.getX(), slices.getY(), origin
151 elif isinstance(slices, Box2I):
152 x0 = slices.getMinX()
153 y0 = slices.getMinY()
154 return slice(x0, x0 + slices.getWidth()), slice(y0, y0 + slices.getHeight()), origin
155 elif isinstance(slices, slice):
156 if slices.start
is not None or slices.stop
is not None or slices.step
is not None:
157 raise TypeError(
"Single-dimension slices must not have bounds.")
164 bbox = bboxGetter(origin)
165 if isinstance(x, slice):
166 if isinstance(y, slice):
167 xSlice = slice(
handleNegativeIndex(x.start, bbox.getWidth(), origin, default=bbox.getBeginX()),
169 ySlice = slice(
handleNegativeIndex(y.start, bbox.getHeight(), origin, default=bbox.getBeginY()),
171 return xSlice, ySlice, origin
172 raise TypeError(
"Mixed indices of the form (slice, int) are not supported for images.")
174 if isinstance(y, slice):
175 raise TypeError(
"Mixed indices of the form (int, slice) are not supported for images.")
182 """Convert slicing format to numpy
184 LSST `afw` image-like objects use an `[x,y]` coordinate
185 convention, accept `Point2I` and `Box2I`
186 objects for slicing, and slice relative to the
187 bounding box `XY0` location;
188 while python and numpy use the convention `[y,x]`
189 with no `XY0`, so this method converts the `afw`
190 indices or slices into numpy indices or slices
194 sliceArgs: `sequence`, `Point2I` or `Box2I`
195 An `(xIndex, yIndex)` pair, or a single `(xIndex,)` tuple,
196 where `xIndex` and `yIndex` can be a `slice` or `int`,
197 or list of `int` objects, and if only a single `xIndex` is
198 given, a `Point2I` or `Box2I`.
199 bboxGetter : callable
200 Callable that accepts an ImageOrigin enum value and returns the
201 appropriate image bounding box. Usually the bound getBBox method
202 of an Image, Mask, or MaskedImage object.
207 Index or `slice` in the y dimension
209 Index or `slice` in the x dimension
211 Bounding box of the image.
212 If `bbox` is `None` then the result is a point and
213 not a subset of an image.
217 x0 = bboxGetter().getMinX()
218 y0 = bboxGetter().getMinY()
221 if isinstance(x, slice):
222 assert isinstance(y, slice)
224 x = slice(x.start - x0, x.stop - x0)
225 y = slice(y.start - y0, y.stop - y0)
231 elif origin != LOCAL:
232 raise ValueError(
"Unrecognized value for origin")
235 if isinstance(x, slice):
236 assert isinstance(y, slice)
238 Extent2I(x.stop-x.start, y.stop-y.start))
245 """Support image slicing
248 def Factory(self, *args, **kwargs):
249 """Return an object of this type
251 return cls(*args, **kwargs)
252 cls.Factory = Factory
255 """Return a deep copy of self"""
256 return cls(self,
True)
259 def __getitem__(self, imageSlice):
262 return self.subset(box, origin=origin)
263 return self._get(index, origin=origin)
264 cls.__getitem__ = __getitem__
266 def __setitem__(self, imageSlice, rhs):
269 if self.assign(rhs, box, origin)
is NotImplemented:
270 lhs = self.subset(box, origin=origin)
273 self._set(index, origin=origin, value=rhs)
274 cls.__setitem__ = __setitem__