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__