LSST Applications g0603fd7c41+501e3db9f9,g0aad566f14+23d8574c86,g0dd44d6229+a1a4c8b791,g2079a07aa2+86d27d4dc4,g2305ad1205+a62672bbc1,g2bbee38e9b+047b288a59,g337abbeb29+047b288a59,g33d1c0ed96+047b288a59,g3a166c0a6a+047b288a59,g3d1719c13e+23d8574c86,g487adcacf7+cb7fd919b2,g4be5004598+23d8574c86,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+4a9e435310,g63cd9335cc+585e252eca,g858d7b2824+23d8574c86,g88963caddf+0cb8e002cc,g99cad8db69+43388bcaec,g9ddcbc5298+9a081db1e4,ga1e77700b3+a912195c07,gae0086650b+585e252eca,gb0e22166c9+60f28cb32d,gb2522980b2+793639e996,gb3a676b8dc+b4feba26a1,gb4b16eec92+63f8520565,gba4ed39666+c2a2e4ac27,gbb8dafda3b+a5d255a82e,gc120e1dc64+d820f8acdb,gc28159a63d+047b288a59,gc3e9b769f7+f4f1cc6b50,gcf0d15dbbd+a1a4c8b791,gdaeeff99f8+f9a426f77a,gdb0af172c8+b6d5496702,ge79ae78c31+047b288a59,w.2024.19
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | List of all members
lsst.scarlet.lite.image.Image Class Reference

Public Member Functions

 __init__ (self, np.ndarray data, Sequence|None bands=None, tuple[int, int]|None yx0=None)
 
tuple[int,...] shape (self)
 
DTypeLike dtype (self)
 
tuple bands (self)
 
int n_bands (self)
 
bool is_multiband (self)
 
int height (self)
 
int width (self)
 
tuple[int, int] yx0 (self)
 
int y0 (self)
 
int x0 (self)
 
Box bbox (self)
 
np.ndarray data (self)
 
tuple[int,...]|slice spectral_indices (self, Sequence|slice bands)
 
tuple[tuple[int,...]|slice, tuple[int,...]|slice] matched_spectral_indices (self, Image other)
 
tuple[tuple[slice,...], tuple[slice,...]] matched_slices (self, Box bbox)
 
Image project (self, object|tuple[object]|None bands=None, Box|None bbox=None)
 
tuple[tuple[int,...]|slice, slice, slice] multiband_slices (self)
 
Image insert_into (self, Image image, Callable op=operator.add)
 
Image insert (self, Image image, Callable op=operator.add)
 
Image repeat (self, tuple bands)
 
Image copy (self, order=None)
 
 copy_with (self, np.ndarray|None data=None, str|None order=None, tuple[str,...]|None bands=None, tuple[int, int]|None yx0=None)
 
Image __eq__ (self, object other)
 
Image __ne__ (self, object other)
 
Image __ge__ (self, Image|ScalarLike other)
 
Image __le__ (self, Image|ScalarLike other)
 
Image __gt__ (self, Image|ScalarLike other)
 
Image __lt__ (self, Image|ScalarLike other)
 
 __neg__ (self)
 
 __pos__ (self)
 
 __invert__ (self)
 
Image __add__ (self, Image|ScalarLike other)
 
Image __iadd__ (self, Image|ScalarLike other)
 
Image __radd__ (self, Image|ScalarLike other)
 
Image __sub__ (self, Image|ScalarLike other)
 
Image __isub__ (self, Image|ScalarLike other)
 
Image __rsub__ (self, Image|ScalarLike other)
 
Image __mul__ (self, Image|ScalarLike other)
 
Image __imul__ (self, Image|ScalarLike other)
 
Image __rmul__ (self, Image|ScalarLike other)
 
Image __truediv__ (self, Image|ScalarLike other)
 
Image __itruediv__ (self, Image|ScalarLike other)
 
Image __rtruediv__ (self, Image|ScalarLike other)
 
Image __floordiv__ (self, Image|ScalarLike other)
 
Image __ifloordiv__ (self, Image|ScalarLike other)
 
Image __rfloordiv__ (self, Image|ScalarLike other)
 
Image __pow__ (self, Image|ScalarLike other)
 
Image __ipow__ (self, Image|ScalarLike other)
 
Image __rpow__ (self, Image|ScalarLike other)
 
Image __mod__ (self, Image|ScalarLike other)
 
Image __imod__ (self, Image|ScalarLike other)
 
Image __rmod__ (self, Image|ScalarLike other)
 
Image __and__ (self, Image|ScalarLike other)
 
Image __iand__ (self, Image|ScalarLike other)
 
Image __rand__ (self, Image|ScalarLike other)
 
Image __or__ (self, Image|ScalarLike other)
 
Image __ior__ (self, Image|ScalarLike other)
 
Image __ror__ (self, Image|ScalarLike other)
 
Image __xor__ (self, Image|ScalarLike other)
 
Image __ixor__ (self, Image|ScalarLike other)
 
Image __rxor__ (self, Image|ScalarLike other)
 
Image __lshift__ (self, ScalarLike other)
 
Image __ilshift__ (self, ScalarLike other)
 
Image __rlshift__ (self, ScalarLike other)
 
Image __rshift__ (self, ScalarLike other)
 
Image __irshift__ (self, ScalarLike other)
 
Image __rrshift__ (self, ScalarLike other)
 
 __str__ (self)
 
tuple[tuple[slice,...], tuple[slice,...]] overlapped_slices (self, Box bbox)
 
Image __getitem__ (self, Any indices)
 
Image __setitem__ (self, indices, Image value)
 

Static Public Member Functions

Image from_box (Box bbox, tuple|None bands=None, DTypeLike dtype=float)
 

Public Attributes

 bands
 
 n_bands
 
 bbox
 

Protected Member Functions

Image _i_update (self, Callable op, Image|ScalarLike other)
 
Image _check_equality (self, Image|ScalarLike other, Callable op)
 
bool _is_spectral_index (self, Any index)
 
tuple[slice, slice] _get_box_slices (self, Box bbox)
 
Image _get_sliced (self, Any indices, Image|None value=None)
 

Protected Attributes

 _data
 
 _yx0
 
 _bands
 

Detailed Description

A numpy array with an origin and (optional) bands

This class contains a 2D numpy array with the addition of an
origin (``yx0``) and an optional first index (``bands``) that
allows an immutable named index to be used.

Notes
-----
One of the main limitations of using numpy arrays to store image data
is the lack of an ``origin`` attribute that allows an array to retain
knowledge of it's location in a larger scene.
For example, if a numpy array ``x`` is sliced, eg. ``x[10:20, 30:40]``
the result will be a new ``10x10`` numpy array that has no meta
data to inform the user that it was sliced from a larger image.
In addition, astrophysical images are also multi-band data cubes,
with a 2D image in each band (in fact this is the simplifying
assumption that distinguishes scarlet lite from scarlet main).
However, the ordering of the bands during processing might differ from
the ordering of the bands to display multiband data.
So a mechanism was also desired to simplify the sorting and index of
an image by band name.

Thus, scarlet lite creates a numpy-array like class with the additional
``bands`` and ``yx0`` attributes to keep track of the bands contained
in an array and the origin of that array (we specify ``yx0`` as opposed
to ``xy0`` to be consistent with the default numpy/C++ ``(y, x)``
ordering of arrays as opposed to the traditional cartesian ``(x, y)``
ordering used in astronomy and other modules in the science pipelines.
While this may be a small source of confusion for the user,
it is consistent with the ordering in the original scarlet package and
ensures the consistency of scarlet lite images and python index slicing.

Examples
--------

The easiest way to create a new image is to use ``Image(numpy_array)``,
for example

>>> import numpy as np
>>> from lsst.scarlet.lite import Image
>>>
>>> x = np.arange(12).reshape(3, 4)
>>> image = Image(x)
>>> print(image)
Image:
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
  bands=()
  bbox=Box(shape=(3, 4), origin=(0, 0))

This will create a single band :py:class:`~lsst.scarlet.lite.Image` with
origin ``(0, 0)``.
To create a multi-band image the input array must have 3 dimensions and
the ``bands`` property must be specified:

>>> x = np.arange(24).reshape(2, 3, 4)
>>> image = Image(x, bands=("i", "z"))
>>> print(image)
Image:
 [[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]
<BLANKLINE>
 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
  bands=('i', 'z')
  bbox=Box(shape=(3, 4), origin=(0, 0))

It is also possible to create an empty single-band image using the
``from_box`` static method:

>>> from lsst.scarlet.lite import Box
>>> image = Image.from_box(Box((3, 4), (100, 120)))
>>> print(image)
Image:
 [[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
  bands=()
  bbox=Box(shape=(3, 4), origin=(100, 120))

Similarly, an empty multi-band image can be created by passing a tuple
of ``bands``:

>>> image = Image.from_box(Box((3, 4)), bands=("r", "i"))
>>> print(image)
Image:
 [[[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]
<BLANKLINE>
 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]]
  bands=('r', 'i')
  bbox=Box(shape=(3, 4), origin=(0, 0))

To select a sub-image use a ``Box`` to select a spatial region in either a
single-band or multi-band image:

>>> x = np.arange(60).reshape(3, 4, 5)
>>> image = Image(x, bands=("g", "r", "i"), yx0=(20, 30))
>>> bbox = Box((2, 2), (21, 32))
>>> print(image[bbox])
Image:
 [[[ 7  8]
  [12 13]]
<BLANKLINE>
 [[27 28]
  [32 33]]
<BLANKLINE>
 [[47 48]
  [52 53]]]
  bands=('g', 'r', 'i')
  bbox=Box(shape=(2, 2), origin=(21, 32))


To select a single-band image from a multi-band image,
pass the name of the band as an index:

>>> print(image["r"])
Image:
 [[20 21 22 23 24]
 [25 26 27 28 29]
 [30 31 32 33 34]
 [35 36 37 38 39]]
  bands=()
  bbox=Box(shape=(4, 5), origin=(20, 30))

Multi-band images can also be sliced in the spatial dimension, for example

>>> print(image["g":"r"])
Image:
 [[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]]
<BLANKLINE>
 [[20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]]]
  bands=('g', 'r')
  bbox=Box(shape=(4, 5), origin=(20, 30))

and

>>> print(image["r":"r"])
Image:
 [[[20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]]]
  bands=('r',)
  bbox=Box(shape=(4, 5), origin=(20, 30))

both extract a slice of a multi-band image.

.. warning::
    Unlike numerical indices, where ``slice(x, y)`` will select the
    subset of an array from ``x`` to ``y-1`` (excluding ``y``),
    a spectral slice of an ``Image`` will return the image slice
    including band ``y``.

It is also possible to change the order or index a subset of bands
in an image. For example:

>>> print(image[("r", "g", "i")])
Image:
 [[[20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]]
<BLANKLINE>
 [[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]]
<BLANKLINE>
 [[40 41 42 43 44]
  [45 46 47 48 49]
  [50 51 52 53 54]
  [55 56 57 58 59]]]
  bands=('r', 'g', 'i')
  bbox=Box(shape=(4, 5), origin=(20, 30))


will return a new image with the bands re-ordered.

Images can be combined using the standard arithmetic operations similar to
numpy arrays, including ``+, -, *, /, **`` etc, however, if two images are
combined with different bounding boxes, the _union_ of the two
boxes is used for the result. For example:

>>> image1 = Image(np.ones((2, 3, 4)), bands=tuple("gr"))
>>> image2 = Image(np.ones((2, 3, 4)), bands=tuple("gr"), yx0=(2, 3))
>>> result = image1 + image2
>>> print(result)
Image:
 [[[1. 1. 1. 1. 0. 0. 0.]
  [1. 1. 1. 1. 0. 0. 0.]
  [1. 1. 1. 2. 1. 1. 1.]
  [0. 0. 0. 1. 1. 1. 1.]
  [0. 0. 0. 1. 1. 1. 1.]]
<BLANKLINE>
 [[1. 1. 1. 1. 0. 0. 0.]
  [1. 1. 1. 1. 0. 0. 0.]
  [1. 1. 1. 2. 1. 1. 1.]
  [0. 0. 0. 1. 1. 1. 1.]
  [0. 0. 0. 1. 1. 1. 1.]]]
  bands=('g', 'r')
  bbox=Box(shape=(5, 7), origin=(0, 0))

If instead you want to additively ``insert`` image 1 into image 2,
so that they have the same bounding box as image 2, use

>>> _ = image2.insert(image1)
>>> print(image2)
Image:
 [[[2. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]
<BLANKLINE>
 [[2. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]]
  bands=('g', 'r')
  bbox=Box(shape=(3, 4), origin=(2, 3))

To insert an image using a different operation use

>>> from operator import truediv
>>> _ = image2.insert(image1, truediv)
>>> print(image2)
Image:
 [[[2. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]
<BLANKLINE>
 [[2. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]]
  bands=('g', 'r')
  bbox=Box(shape=(3, 4), origin=(2, 3))


However, depending on the operation you may get unexpected results
since now there could be ``NaN`` and ``inf`` values due to the zeros
in the non-overlapping regions.
Instead, to select only the overlap region one can use

>>> result = image1 / image2
>>> print(result[image1.bbox & image2.bbox])
Image:
 [[[0.5]]
<BLANKLINE>
 [[0.5]]]
  bands=('g', 'r')
  bbox=Box(shape=(1, 1), origin=(2, 3))


Parameters
----------
data:
    The array data for the image.
bands:
    The bands coving the image.
yx0:
    The (y, x) offset for the lower left of the image.

Definition at line 84 of file image.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.scarlet.lite.image.Image.__init__ ( self,
np.ndarray data,
Sequence | None bands = None,
tuple[int, int] | None yx0 = None )

Definition at line 358 of file image.py.

363 ):
364 if bands is None or len(bands) == 0:
365 # Using an empty tuple for the bands will result in a 2D image
366 bands = ()
367 assert len(data.shape) == 2
368 else:
369 bands = tuple(bands)
370 assert len(data.shape) == 3
371 if data.shape[0] != len(bands):
372 raise ValueError(f"Array has spectral size {data.shape[0]}, but {bands} bands")
373 if yx0 is None:
374 yx0 = (0, 0)
375 self._data = data
376 self._yx0 = yx0
377 self._bands = bands
378

Member Function Documentation

◆ __add__()

Image lsst.scarlet.lite.image.Image.__add__ ( self,
Image | ScalarLike other )
Combine this image and another image using addition.

Definition at line 860 of file image.py.

860 def __add__(self, other: Image | ScalarLike) -> Image:
861 """Combine this image and another image using addition."""
862 return _operate_on_images(self, other, operator.add)
863

◆ __and__()

Image lsst.scarlet.lite.image.Image.__and__ ( self,
Image | ScalarLike other )
Take the bitwise and of this and other.

Definition at line 970 of file image.py.

970 def __and__(self, other: Image | ScalarLike) -> Image:
971 """Take the bitwise and of this and other."""
972 return _operate_on_images(self, other, operator.and_)
973

◆ __eq__()

Image lsst.scarlet.lite.image.Image.__eq__ ( self,
object other )
Check if this image is equal to another.

Definition at line 814 of file image.py.

814 def __eq__(self, other: object) -> Image: # type: ignore
815 """Check if this image is equal to another."""
816 if not isinstance(other, Image) and not isinstance(other, ScalarTypes):
817 raise TypeError(f"Cannot compare an Image to {type(other)}.")
818 return self._check_equality(other, operator.eq) # type: ignore
819

◆ __floordiv__()

Image lsst.scarlet.lite.image.Image.__floordiv__ ( self,
Image | ScalarLike other )
Floor divide this image by `other` in place.

Definition at line 928 of file image.py.

928 def __floordiv__(self, other: Image | ScalarLike) -> Image:
929 """Floor divide this image by `other` in place."""
930 return _operate_on_images(self, other, operator.floordiv)
931

◆ __ge__()

Image lsst.scarlet.lite.image.Image.__ge__ ( self,
Image | ScalarLike other )
Check if this image is greater than or equal to another.

Definition at line 824 of file image.py.

824 def __ge__(self, other: Image | ScalarLike) -> Image:
825 """Check if this image is greater than or equal to another."""
826 if type(other) in ScalarTypes:
827 return self.copy_with(data=self.data >= other)
828 return self._check_equality(other, operator.ge)
829

◆ __getitem__()

Image lsst.scarlet.lite.image.Image.__getitem__ ( self,
Any indices )
Get the subset of an image

Parameters
----------
indices:
    The indices to select a subsection of the image.

Returns
-------
result:
    The resulting image obtained by selecting subsets of the iamge
    based on the `indices`.

Definition at line 1199 of file image.py.

1199 def __getitem__(self, indices: Any) -> Image:
1200 """Get the subset of an image
1201
1202 Parameters
1203 ----------
1204 indices:
1205 The indices to select a subsection of the image.
1206
1207 Returns
1208 -------
1209 result:
1210 The resulting image obtained by selecting subsets of the iamge
1211 based on the `indices`.
1212 """
1213 return self._get_sliced(indices)
1214

◆ __gt__()

Image lsst.scarlet.lite.image.Image.__gt__ ( self,
Image | ScalarLike other )
Check if this image is greater than or equal to another.

Definition at line 836 of file image.py.

836 def __gt__(self, other: Image | ScalarLike) -> Image:
837 """Check if this image is greater than or equal to another."""
838 if type(other) in ScalarTypes:
839 return self.copy_with(data=self.data > other)
840 return self._check_equality(other, operator.ge)
841

◆ __iadd__()

Image lsst.scarlet.lite.image.Image.__iadd__ ( self,
Image | ScalarLike other )
Combine this image and another image using addition and update
in place.

Definition at line 864 of file image.py.

864 def __iadd__(self, other: Image | ScalarLike) -> Image:
865 """Combine this image and another image using addition and update
866 in place.
867 """
868 return self._i_update(self.__add__, other)
869

◆ __iand__()

Image lsst.scarlet.lite.image.Image.__iand__ ( self,
Image | ScalarLike other )
Take the bitwise and of this and other in place.

Definition at line 974 of file image.py.

974 def __iand__(self, other: Image | ScalarLike) -> Image:
975 """Take the bitwise and of this and other in place."""
976 return self._i_update(self.__and__, other)
977

◆ __ifloordiv__()

Image lsst.scarlet.lite.image.Image.__ifloordiv__ ( self,
Image | ScalarLike other )
Floor divide this image by `other` in place.

Definition at line 932 of file image.py.

932 def __ifloordiv__(self, other: Image | ScalarLike) -> Image:
933 """Floor divide this image by `other` in place."""
934 return self._i_update(self.__floordiv__, other)
935

◆ __ilshift__()

Image lsst.scarlet.lite.image.Image.__ilshift__ ( self,
ScalarLike other )
Shift this image to the left by other bits in place.

Definition at line 1018 of file image.py.

1018 def __ilshift__(self, other: ScalarLike) -> Image:
1019 """Shift this image to the left by other bits in place."""
1020 self[:] = self.__lshift__(other)
1021 return self
1022

◆ __imod__()

Image lsst.scarlet.lite.image.Image.__imod__ ( self,
Image | ScalarLike other )
Take the modulus of this % other in place.

Definition at line 960 of file image.py.

960 def __imod__(self, other: Image | ScalarLike) -> Image:
961 """Take the modulus of this % other in place."""
962 return self._i_update(self.__mod__, other)
963

◆ __imul__()

Image lsst.scarlet.lite.image.Image.__imul__ ( self,
Image | ScalarLike other )
Combine this image and another image using multiplication,
with this image on the right.

Definition at line 900 of file image.py.

900 def __imul__(self, other: Image | ScalarLike) -> Image:
901 """Combine this image and another image using multiplication,
902 with this image on the right.
903 """
904 return self._i_update(self.__mul__, other)
905

◆ __invert__()

lsst.scarlet.lite.image.Image.__invert__ ( self)
Take the inverse (~) of the image.

Definition at line 856 of file image.py.

856 def __invert__(self):
857 """Take the inverse (~) of the image."""
858 return self.copy_with(data=~self._data)
859

◆ __ior__()

Image lsst.scarlet.lite.image.Image.__ior__ ( self,
Image | ScalarLike other )
Take the binary or of this or other in place.

Definition at line 988 of file image.py.

988 def __ior__(self, other: Image | ScalarLike) -> Image:
989 """Take the binary or of this or other in place."""
990 return self._i_update(self.__or__, other)
991

◆ __ipow__()

Image lsst.scarlet.lite.image.Image.__ipow__ ( self,
Image | ScalarLike other )
Raise this image to the `other` power in place.

Definition at line 946 of file image.py.

946 def __ipow__(self, other: Image | ScalarLike) -> Image:
947 """Raise this image to the `other` power in place."""
948 return self._i_update(self.__pow__, other)
949

◆ __irshift__()

Image lsst.scarlet.lite.image.Image.__irshift__ ( self,
ScalarLike other )
Shift this image to the right by other bits in place.

Definition at line 1033 of file image.py.

1033 def __irshift__(self, other: ScalarLike) -> Image:
1034 """Shift this image to the right by other bits in place."""
1035 self[:] = self.__rshift__(other)
1036 return self
1037

◆ __isub__()

Image lsst.scarlet.lite.image.Image.__isub__ ( self,
Image | ScalarLike other )
Combine this image and another image using subtraction,
with this image on the right.

Definition at line 882 of file image.py.

882 def __isub__(self, other: Image | ScalarLike) -> Image:
883 """Combine this image and another image using subtraction,
884 with this image on the right.
885 """
886 return self._i_update(self.__sub__, other)
887

◆ __itruediv__()

Image lsst.scarlet.lite.image.Image.__itruediv__ ( self,
Image | ScalarLike other )
Divide this image by `other` in place.

Definition at line 918 of file image.py.

918 def __itruediv__(self, other: Image | ScalarLike) -> Image:
919 """Divide this image by `other` in place."""
920 return self._i_update(self.__truediv__, other)
921

◆ __ixor__()

Image lsst.scarlet.lite.image.Image.__ixor__ ( self,
Image | ScalarLike other )
Take the binary xor of this xor other in place.

Definition at line 1002 of file image.py.

1002 def __ixor__(self, other: Image | ScalarLike) -> Image:
1003 """Take the binary xor of this xor other in place."""
1004 return self._i_update(self.__xor__, other)
1005

◆ __le__()

Image lsst.scarlet.lite.image.Image.__le__ ( self,
Image | ScalarLike other )
Check if this image is less than or equal to another.

Definition at line 830 of file image.py.

830 def __le__(self, other: Image | ScalarLike) -> Image:
831 """Check if this image is less than or equal to another."""
832 if type(other) in ScalarTypes:
833 return self.copy_with(data=self.data <= other)
834 return self._check_equality(other, operator.le)
835

◆ __lshift__()

Image lsst.scarlet.lite.image.Image.__lshift__ ( self,
ScalarLike other )
Shift this image to the left by other bits.

Definition at line 1012 of file image.py.

1012 def __lshift__(self, other: ScalarLike) -> Image:
1013 """Shift this image to the left by other bits."""
1014 if not issubclass(np.dtype(type(other)).type, np.integer):
1015 raise TypeError("Bit shifting an image can only be done with integers")
1016 return self.copy_with(data=self.data << other)
1017

◆ __lt__()

Image lsst.scarlet.lite.image.Image.__lt__ ( self,
Image | ScalarLike other )
Check if this image is less than or equal to another.

Definition at line 842 of file image.py.

842 def __lt__(self, other: Image | ScalarLike) -> Image:
843 """Check if this image is less than or equal to another."""
844 if type(other) in ScalarTypes:
845 return self.copy_with(data=self.data < other)
846 return self._check_equality(other, operator.le)
847

◆ __mod__()

Image lsst.scarlet.lite.image.Image.__mod__ ( self,
Image | ScalarLike other )
Take the modulus of this % other.

Definition at line 956 of file image.py.

956 def __mod__(self, other: Image | ScalarLike) -> Image:
957 """Take the modulus of this % other."""
958 return _operate_on_images(self, other, operator.mod)
959

◆ __mul__()

Image lsst.scarlet.lite.image.Image.__mul__ ( self,
Image | ScalarLike other )
Combine this image and another image using multiplication.

Definition at line 896 of file image.py.

896 def __mul__(self, other: Image | ScalarLike) -> Image:
897 """Combine this image and another image using multiplication."""
898 return _operate_on_images(self, other, operator.mul)
899

◆ __ne__()

Image lsst.scarlet.lite.image.Image.__ne__ ( self,
object other )
Check if this image is not equal to another.

Definition at line 820 of file image.py.

820 def __ne__(self, other: object) -> Image: # type: ignore
821 """Check if this image is not equal to another."""
822 return ~self.__eq__(other)
823

◆ __neg__()

lsst.scarlet.lite.image.Image.__neg__ ( self)
Take the negative of the image.

Definition at line 848 of file image.py.

848 def __neg__(self):
849 """Take the negative of the image."""
850 return self.copy_with(data=-self._data)
851

◆ __or__()

Image lsst.scarlet.lite.image.Image.__or__ ( self,
Image | ScalarLike other )
Take the binary or of this or other.

Definition at line 984 of file image.py.

984 def __or__(self, other: Image | ScalarLike) -> Image:
985 """Take the binary or of this or other."""
986 return _operate_on_images(self, other, operator.or_)
987

◆ __pos__()

lsst.scarlet.lite.image.Image.__pos__ ( self)
Make a copy using of the image.

Definition at line 852 of file image.py.

852 def __pos__(self):
853 """Make a copy using of the image."""
854 return self.copy()
855

◆ __pow__()

Image lsst.scarlet.lite.image.Image.__pow__ ( self,
Image | ScalarLike other )
Raise this image to the `other` power.

Definition at line 942 of file image.py.

942 def __pow__(self, other: Image | ScalarLike) -> Image:
943 """Raise this image to the `other` power."""
944 return _operate_on_images(self, other, operator.pow)
945

◆ __radd__()

Image lsst.scarlet.lite.image.Image.__radd__ ( self,
Image | ScalarLike other )
Combine this image and another image using addition,
with this image on the right.

Definition at line 870 of file image.py.

870 def __radd__(self, other: Image | ScalarLike) -> Image:
871 """Combine this image and another image using addition,
872 with this image on the right.
873 """
874 if type(other) in ScalarTypes:
875 return self.copy_with(data=other + self.data)
876 return cast(Image, other).__add__(self)
877

◆ __rand__()

Image lsst.scarlet.lite.image.Image.__rand__ ( self,
Image | ScalarLike other )
Take the bitwise and of other and this.

Definition at line 978 of file image.py.

978 def __rand__(self, other: Image | ScalarLike) -> Image:
979 """Take the bitwise and of other and this."""
980 if type(other) in ScalarTypes:
981 return self.copy_with(data=other & self.data)
982 return cast(Image, other).__and__(self)
983

◆ __rfloordiv__()

Image lsst.scarlet.lite.image.Image.__rfloordiv__ ( self,
Image | ScalarLike other )
Floor divide this image by `other` with this on the right.

Definition at line 936 of file image.py.

936 def __rfloordiv__(self, other: Image | ScalarLike) -> Image:
937 """Floor divide this image by `other` with this on the right."""
938 if type(other) in ScalarTypes:
939 return self.copy_with(data=other // self.data)
940 return cast(Image, other).__floordiv__(self)
941

◆ __rlshift__()

Image lsst.scarlet.lite.image.Image.__rlshift__ ( self,
ScalarLike other )
Shift other to the left by this image bits.

Definition at line 1023 of file image.py.

1023 def __rlshift__(self, other: ScalarLike) -> Image:
1024 """Shift other to the left by this image bits."""
1025 return self.copy_with(data=other << self.data)
1026

◆ __rmod__()

Image lsst.scarlet.lite.image.Image.__rmod__ ( self,
Image | ScalarLike other )
Take the modulus of other % this.

Definition at line 964 of file image.py.

964 def __rmod__(self, other: Image | ScalarLike) -> Image:
965 """Take the modulus of other % this."""
966 if type(other) in ScalarTypes:
967 return self.copy_with(data=other % self.data)
968 return cast(Image, other).__mod__(self)
969

◆ __rmul__()

Image lsst.scarlet.lite.image.Image.__rmul__ ( self,
Image | ScalarLike other )
Combine this image and another image using multiplication,
with this image on the right.

Definition at line 906 of file image.py.

906 def __rmul__(self, other: Image | ScalarLike) -> Image:
907 """Combine this image and another image using multiplication,
908 with this image on the right.
909 """
910 if type(other) in ScalarTypes:
911 return self.copy_with(data=other * self.data)
912 return cast(Image, other).__mul__(self)
913

◆ __ror__()

Image lsst.scarlet.lite.image.Image.__ror__ ( self,
Image | ScalarLike other )
Take the binary or of other or this.

Definition at line 992 of file image.py.

992 def __ror__(self, other: Image | ScalarLike) -> Image:
993 """Take the binary or of other or this."""
994 if type(other) in ScalarTypes:
995 return self.copy_with(data=other | self.data)
996 return cast(Image, other).__or__(self)
997

◆ __rpow__()

Image lsst.scarlet.lite.image.Image.__rpow__ ( self,
Image | ScalarLike other )
Raise this other to the power of this image.

Definition at line 950 of file image.py.

950 def __rpow__(self, other: Image | ScalarLike) -> Image:
951 """Raise this other to the power of this image."""
952 if type(other) in ScalarTypes:
953 return self.copy_with(data=other**self.data)
954 return cast(Image, other).__pow__(self)
955

◆ __rrshift__()

Image lsst.scarlet.lite.image.Image.__rrshift__ ( self,
ScalarLike other )
Shift other to the right by this image bits.

Definition at line 1038 of file image.py.

1038 def __rrshift__(self, other: ScalarLike) -> Image:
1039 """Shift other to the right by this image bits."""
1040 return self.copy_with(data=other >> self.data)
1041

◆ __rshift__()

Image lsst.scarlet.lite.image.Image.__rshift__ ( self,
ScalarLike other )
Shift this image to the right by other bits.

Definition at line 1027 of file image.py.

1027 def __rshift__(self, other: ScalarLike) -> Image:
1028 """Shift this image to the right by other bits."""
1029 if not issubclass(np.dtype(type(other)).type, np.integer):
1030 raise TypeError("Bit shifting an image can only be done with integers")
1031 return self.copy_with(data=self.data >> other)
1032

◆ __rsub__()

Image lsst.scarlet.lite.image.Image.__rsub__ ( self,
Image | ScalarLike other )
Combine this image and another image using subtraction,
with this image on the right.

Definition at line 888 of file image.py.

888 def __rsub__(self, other: Image | ScalarLike) -> Image:
889 """Combine this image and another image using subtraction,
890 with this image on the right.
891 """
892 if type(other) in ScalarTypes:
893 return self.copy_with(data=other - self.data)
894 return cast(Image, other).__sub__(self)
895

◆ __rtruediv__()

Image lsst.scarlet.lite.image.Image.__rtruediv__ ( self,
Image | ScalarLike other )
Divide this image by `other` with this on the right.

Definition at line 922 of file image.py.

922 def __rtruediv__(self, other: Image | ScalarLike) -> Image:
923 """Divide this image by `other` with this on the right."""
924 if type(other) in ScalarTypes:
925 return self.copy_with(data=other / self.data)
926 return cast(Image, other).__truediv__(self)
927

◆ __rxor__()

Image lsst.scarlet.lite.image.Image.__rxor__ ( self,
Image | ScalarLike other )
Take the binary xor of other xor this.

Definition at line 1006 of file image.py.

1006 def __rxor__(self, other: Image | ScalarLike) -> Image:
1007 """Take the binary xor of other xor this."""
1008 if type(other) in ScalarTypes:
1009 return self.copy_with(data=other ^ self.data)
1010 return cast(Image, other).__xor__(self)
1011

◆ __setitem__()

Image lsst.scarlet.lite.image.Image.__setitem__ ( self,
indices,
Image value )
Set a subset of an image to a given value

Parameters
----------
indices:
    The indices to select a subsection of the image.
value:
    The value to use for the subset of the image.

Returns
-------
result:
    The resulting image obtained by selecting subsets of the image
    based on the `indices`.

Definition at line 1215 of file image.py.

1215 def __setitem__(self, indices, value: Image) -> Image:
1216 """Set a subset of an image to a given value
1217
1218 Parameters
1219 ----------
1220 indices:
1221 The indices to select a subsection of the image.
1222 value:
1223 The value to use for the subset of the image.
1224
1225 Returns
1226 -------
1227 result:
1228 The resulting image obtained by selecting subsets of the image
1229 based on the `indices`.
1230 """
1231 return self._get_sliced(indices, value)
1232
1233

◆ __str__()

lsst.scarlet.lite.image.Image.__str__ ( self)
Display the image array, bands, and bounding box.

Definition at line 1042 of file image.py.

1042 def __str__(self):
1043 """Display the image array, bands, and bounding box."""
1044 return f"Image:\n {str(self.data)}\n bands={self.bands}\n bbox={self.bbox}"
1045

◆ __sub__()

Image lsst.scarlet.lite.image.Image.__sub__ ( self,
Image | ScalarLike other )
Combine this image and another image using subtraction.

Definition at line 878 of file image.py.

878 def __sub__(self, other: Image | ScalarLike) -> Image:
879 """Combine this image and another image using subtraction."""
880 return _operate_on_images(self, other, operator.sub)
881

◆ __truediv__()

Image lsst.scarlet.lite.image.Image.__truediv__ ( self,
Image | ScalarLike other )
Divide this image by `other`.

Definition at line 914 of file image.py.

914 def __truediv__(self, other: Image | ScalarLike) -> Image:
915 """Divide this image by `other`."""
916 return _operate_on_images(self, other, operator.truediv)
917

◆ __xor__()

Image lsst.scarlet.lite.image.Image.__xor__ ( self,
Image | ScalarLike other )
Take the binary xor of this xor other.

Definition at line 998 of file image.py.

998 def __xor__(self, other: Image | ScalarLike) -> Image:
999 """Take the binary xor of this xor other."""
1000 return _operate_on_images(self, other, operator.xor)
1001

◆ _check_equality()

Image lsst.scarlet.lite.image.Image._check_equality ( self,
Image | ScalarLike other,
Callable op )
protected
Compare this array to another.

This performs an element by element equality check.

Parameters
----------
other:
    The image to compare this image to.
op:
    The operator used for the comparision (==, !=, >=, <=).

Returns
-------
image: Image
    An image made by checking all of the elements in this array with
    another.

Raises
------
TypeError:
    If `other` is not an `Image`.
MismatchedBandsError:
    If `other` has different bands.
MismatchedBoxError:
    if `other` exists in a different bounding box.

Definition at line 771 of file image.py.

771 def _check_equality(self, other: Image | ScalarLike, op: Callable) -> Image:
772 """Compare this array to another.
773
774 This performs an element by element equality check.
775
776 Parameters
777 ----------
778 other:
779 The image to compare this image to.
780 op:
781 The operator used for the comparision (==, !=, >=, <=).
782
783 Returns
784 -------
785 image: Image
786 An image made by checking all of the elements in this array with
787 another.
788
789 Raises
790 ------
791 TypeError:
792 If `other` is not an `Image`.
793 MismatchedBandsError:
794 If `other` has different bands.
795 MismatchedBoxError:
796 if `other` exists in a different bounding box.
797 """
798 if isinstance(other, Image) and other.bands == self.bands and other.bbox == self.bbox:
799 return self.copy_with(data=op(self.data, other.data))
800
801 if not isinstance(other, Image):
802 if type(other) in ScalarTypes:
803 return self.copy_with(data=op(self.data, other))
804 raise TypeError(f"Cannot compare images to {type(other)}")
805
806 if other.bands != self.bands:
807 msg = f"Cannot compare images with mismatched bands: {self.bands} vs {other.bands}"
808 raise MismatchedBandsError(msg)
809
810 raise MismatchedBoxError(
811 f"Cannot compare images with different bounds boxes: {self.bbox} vs. {other.bbox}"
812 )
813

◆ _get_box_slices()

tuple[slice, slice] lsst.scarlet.lite.image.Image._get_box_slices ( self,
Box bbox )
protected
Get the slices of the image to insert it into the overlapping
region with `bbox`.

Definition at line 1070 of file image.py.

1070 def _get_box_slices(self, bbox: Box) -> tuple[slice, slice]:
1071 """Get the slices of the image to insert it into the overlapping
1072 region with `bbox`."""
1073 overlap = self.bbox & bbox
1074 if overlap != bbox:
1075 raise IndexError("Bounding box is outside of the image")
1076 origin = bbox.origin
1077 shape = bbox.shape
1078 y_start = origin[0] - self.yx0[0]
1079 y_stop = origin[0] + shape[0] - self.yx0[0]
1080 x_start = origin[1] - self.yx0[1]
1081 x_stop = origin[1] + shape[1] - self.yx0[1]
1082 y_index = slice(y_start, y_stop)
1083 x_index = slice(x_start, x_stop)
1084 return y_index, x_index
1085

◆ _get_sliced()

Image lsst.scarlet.lite.image.Image._get_sliced ( self,
Any indices,
Image | None value = None )
protected
Select a subset of an image

Parameters
----------
indices:
    The indices to select a subsection of the image.
    The spectral index can either be a tuple of indices,
    a slice of indices, or a single index used to select a
    single-band 2D image.
    The spatial index (if present) is a `Box`.

value:
    The value used to set this slice of the image.
    This allows the single `_get_sliced` method to be used for
    both getting a slice of an image and setting it.

Returns
-------
result: Image | np.ndarray
    The resulting image obtained by selecting subsets of the iamge
    based on the `indices`.

Definition at line 1086 of file image.py.

1086 def _get_sliced(self, indices: Any, value: Image | None = None) -> Image:
1087 """Select a subset of an image
1088
1089 Parameters
1090 ----------
1091 indices:
1092 The indices to select a subsection of the image.
1093 The spectral index can either be a tuple of indices,
1094 a slice of indices, or a single index used to select a
1095 single-band 2D image.
1096 The spatial index (if present) is a `Box`.
1097
1098 value:
1099 The value used to set this slice of the image.
1100 This allows the single `_get_sliced` method to be used for
1101 both getting a slice of an image and setting it.
1102
1103 Returns
1104 -------
1105 result: Image | np.ndarray
1106 The resulting image obtained by selecting subsets of the iamge
1107 based on the `indices`.
1108 """
1109 if not isinstance(indices, tuple):
1110 indices = (indices,)
1111
1112 if self.is_multiband:
1113 if self._is_spectral_index(indices[0]):
1114 if len(indices) > 1 and indices[1] in self.bands:
1115 # The indices are all band names,
1116 # so use them all as a spectral indices
1117 bands = indices
1118 spectral_index = self.spectral_indices(bands)
1119 y_index = x_index = slice(None)
1120 elif self._is_spectral_index(indices[0]):
1121 # The first index is a spectral index
1122 spectral_index = self.spectral_indices(indices[0])
1123 if isinstance(spectral_index, slice):
1124 bands = self.bands[spectral_index]
1125 elif len(spectral_index) == 1:
1126 bands = ()
1127 spectral_index = spectral_index[0] # type: ignore
1128 else:
1129 bands = tuple(self.bands[idx] for idx in spectral_index)
1130 indices = indices[1:]
1131 if len(indices) == 1:
1132 # The spatial index must be a bounding box
1133 if not isinstance(indices[0], Box):
1134 raise IndexError(f"Expected a Box for the spatial index but got {indices[1]}")
1135 y_index, x_index = self._get_box_slices(indices[0])
1136 elif len(indices) == 0:
1137 y_index = x_index = slice(None)
1138 else:
1139 raise IndexError(f"Too many spatial indices, expeected a Box bot got {indices}")
1140 full_index = (spectral_index, y_index, x_index)
1141 elif isinstance(indices[0], Box):
1142 bands = self.bands
1143 y_index, x_index = self._get_box_slices(indices[0])
1144 full_index = (slice(None), y_index, x_index)
1145 else:
1146 error = f"3D images can only be indexed by spectral indices or bounding boxes, got {indices}"
1147 raise IndexError(error)
1148 else:
1149 if len(indices) != 1 or not isinstance(indices[0], Box):
1150 raise IndexError(f"2D images can only be sliced by bounding box, got {indices}")
1151 bands = ()
1152 y_index, x_index = self._get_box_slices(indices[0])
1153 full_index = (y_index, x_index) # type: ignore
1154
1155 y0 = y_index.start
1156 if y0 is None:
1157 y0 = 0
1158
1159 x0 = x_index.start
1160 if x0 is None:
1161 x0 = 0
1162
1163 if value is None:
1164 # This is a getter,
1165 # so return an image with the data sliced properly
1166 yx0 = (y0 + self.yx0[0], x0 + self.yx0[1])
1167
1168 data = self.data[full_index]
1169
1170 if len(data.shape) == 2:
1171 # Only a single band was selected, so return that band
1172 return Image(data, yx0=yx0)
1173 return Image(data, bands=bands, yx0=yx0)
1174
1175 # Set the data
1176 self._data[full_index] = value.data
1177 return self
1178

◆ _i_update()

Image lsst.scarlet.lite.image.Image._i_update ( self,
Callable op,
Image | ScalarLike other )
protected
Update the data array in place.

This is typically implemented by `__i<op>__` methods,
like `__iadd__`, to apply an operator and update this image
with the data in place.

Parameters
----------
op:
    Operator used to combine this image with the `other` image.
other:
    The other image that is combined with this one using the operator
    `op`.

Returns
-------
image: Image
    This image, after being updated by the operator

Definition at line 737 of file image.py.

737 def _i_update(self, op: Callable, other: Image | ScalarLike) -> Image:
738 """Update the data array in place.
739
740 This is typically implemented by `__i<op>__` methods,
741 like `__iadd__`, to apply an operator and update this image
742 with the data in place.
743
744 Parameters
745 ----------
746 op:
747 Operator used to combine this image with the `other` image.
748 other:
749 The other image that is combined with this one using the operator
750 `op`.
751
752 Returns
753 -------
754 image: Image
755 This image, after being updated by the operator
756 """
757 dtype = get_combined_dtype(self.data, other)
758 if self.dtype != dtype:
759 if hasattr(other, "dtype"):
760 _dtype = cast(np.ndarray, other).dtype
761 else:
762 _dtype = type(other)
763 msg = f"Cannot update an array with type {self.dtype} with {_dtype}"
764 raise ValueError(msg)
765 result = op(other)
766 self._data[:] = result.data
767 self._bands = result.bands
768 self._yx0 = result.yx0
769 return self
770

◆ _is_spectral_index()

bool lsst.scarlet.lite.image.Image._is_spectral_index ( self,
Any index )
protected
Check to see if an index is a spectral index.

Parameters
----------
index:
    Either a slice, a tuple, or an element in `Image.bands`.

Returns
-------
result:
    ``True`` if `index` is band or tuple of bands.

Definition at line 1046 of file image.py.

1046 def _is_spectral_index(self, index: Any) -> bool:
1047 """Check to see if an index is a spectral index.
1048
1049 Parameters
1050 ----------
1051 index:
1052 Either a slice, a tuple, or an element in `Image.bands`.
1053
1054 Returns
1055 -------
1056 result:
1057 ``True`` if `index` is band or tuple of bands.
1058 """
1059 bands = self.bands
1060 if isinstance(index, slice):
1061 if index.start in bands or index.stop in bands or (index.start is None and index.stop is None):
1062 return True
1063 return False
1064 if index in self.bands:
1065 return True
1066 if isinstance(index, tuple) and index[0] in self.bands:
1067 return True
1068 return False
1069

◆ bands()

tuple lsst.scarlet.lite.image.Image.bands ( self)
The bands used in the image.

Definition at line 419 of file image.py.

419 def bands(self) -> tuple:
420 """The bands used in the image."""
421 return self._bands
422

◆ bbox()

Box lsst.scarlet.lite.image.Image.bbox ( self)
Bounding box for the special dimensions in the image.

Definition at line 463 of file image.py.

463 def bbox(self) -> Box:
464 """Bounding box for the special dimensions in the image."""
465 return Box(self.shape[-2:], self._yx0)
466
AmpInfoBoxKey bbox
Definition Amplifier.cc:117

◆ copy()

Image lsst.scarlet.lite.image.Image.copy ( self,
order = None )
Make a copy of this image.

Parameters
----------
order:
    The ordering to use for storing the bytes.
    This is unlikely to be needed, and just defaults to
    the numpy behavior (C) ordering.

Returns
-------
image: Image
    The copy of this image.

Definition at line 680 of file image.py.

680 def copy(self, order=None) -> Image:
681 """Make a copy of this image.
682
683 Parameters
684 ----------
685 order:
686 The ordering to use for storing the bytes.
687 This is unlikely to be needed, and just defaults to
688 the numpy behavior (C) ordering.
689
690 Returns
691 -------
692 image: Image
693 The copy of this image.
694 """
695 return self.copy_with(order=order)
696

◆ copy_with()

lsst.scarlet.lite.image.Image.copy_with ( self,
np.ndarray | None data = None,
str | None order = None,
tuple[str, ...] | None bands = None,
tuple[int, int] | None yx0 = None )
Copy of this image with some parameters updated.

Any parameters not specified by the user will be copied from the
current image.

Parameters
----------
data:
    An update for the data in the image.
order:
    The ordering for stored bytes, from numpy.copy.
bands:
    The bands that the resulting image will have.
    The number of bands must be the same as the first dimension
    in the data array.
yx0:
    The lower-left of the image bounding box.

Returns
-------
image: Image
    The copied image.

Definition at line 697 of file image.py.

703 ):
704 """Copy of this image with some parameters updated.
705
706 Any parameters not specified by the user will be copied from the
707 current image.
708
709 Parameters
710 ----------
711 data:
712 An update for the data in the image.
713 order:
714 The ordering for stored bytes, from numpy.copy.
715 bands:
716 The bands that the resulting image will have.
717 The number of bands must be the same as the first dimension
718 in the data array.
719 yx0:
720 The lower-left of the image bounding box.
721
722 Returns
723 -------
724 image: Image
725 The copied image.
726 """
727 if order is None:
728 order = "C"
729 if data is None:
730 data = self.data.copy(order) # type: ignore
731 if bands is None:
732 bands = self.bands
733 if yx0 is None:
734 yx0 = self.yx0
735 return Image(data, bands, yx0)
736

◆ data()

np.ndarray lsst.scarlet.lite.image.Image.data ( self)
The image viewed as a numpy array.

Definition at line 468 of file image.py.

468 def data(self) -> np.ndarray:
469 """The image viewed as a numpy array."""
470 return self._data
471
char * data
Definition BaseRecord.cc:61

◆ dtype()

DTypeLike lsst.scarlet.lite.image.Image.dtype ( self)
The numpy dtype of the image.

Definition at line 414 of file image.py.

414 def dtype(self) -> DTypeLike:
415 """The numpy dtype of the image."""
416 return self._data.dtype
417

◆ from_box()

Image lsst.scarlet.lite.image.Image.from_box ( Box bbox,
tuple | None bands = None,
DTypeLike dtype = float )
static
Initialize an empty image from a bounding Box and optional bands

Parameters
----------
bbox:
    The bounding box that contains the image.
bands:
    The bands for the image.
    If bands is `None` then a 2D image is created.
dtype:
    The numpy dtype of the image.

Returns
-------
image:
    An empty image contained in ``bbox`` with ``bands`` bands.

Definition at line 380 of file image.py.

380 def from_box(bbox: Box, bands: tuple | None = None, dtype: DTypeLike = float) -> Image:
381 """Initialize an empty image from a bounding Box and optional bands
382
383 Parameters
384 ----------
385 bbox:
386 The bounding box that contains the image.
387 bands:
388 The bands for the image.
389 If bands is `None` then a 2D image is created.
390 dtype:
391 The numpy dtype of the image.
392
393 Returns
394 -------
395 image:
396 An empty image contained in ``bbox`` with ``bands`` bands.
397 """
398 if bands is not None and len(bands) > 0:
399 shape = (len(bands),) + bbox.shape
400 else:
401 shape = bbox.shape
402 data = np.zeros(shape, dtype=dtype)
403 return Image(data, bands=bands, yx0=cast(tuple[int, int], bbox.origin))
404

◆ height()

int lsst.scarlet.lite.image.Image.height ( self)
Height of the image.

Definition at line 438 of file image.py.

438 def height(self) -> int:
439 """Height of the image."""
440 return self.shape[-2]
441

◆ insert()

Image lsst.scarlet.lite.image.Image.insert ( self,
Image image,
Callable op = operator.add )
Insert another image into this image in place.

Parameters
----------
image:
    The image to insert this image into.
op:
    The operator to use when combining the images.

Returns
-------
result:
    This instance with `image` inserted.

Definition at line 642 of file image.py.

642 def insert(self, image: Image, op: Callable = operator.add) -> Image:
643 """Insert another image into this image in place.
644
645 Parameters
646 ----------
647 image:
648 The image to insert this image into.
649 op:
650 The operator to use when combining the images.
651
652 Returns
653 -------
654 result:
655 This instance with `image` inserted.
656 """
657 return insert_image(self, image, op)
658

◆ insert_into()

Image lsst.scarlet.lite.image.Image.insert_into ( self,
Image image,
Callable op = operator.add )
Insert this image into another image in place.

Parameters
----------
image:
    The image to insert this image into.
op:
    The operator to use when combining the images.

Returns
-------
result:
    `image` updated by inserting this instance.

Definition at line 621 of file image.py.

625 ) -> Image:
626 """Insert this image into another image in place.
627
628 Parameters
629 ----------
630 image:
631 The image to insert this image into.
632 op:
633 The operator to use when combining the images.
634
635 Returns
636 -------
637 result:
638 `image` updated by inserting this instance.
639 """
640 return insert_image(image, self, op)
641

◆ is_multiband()

bool lsst.scarlet.lite.image.Image.is_multiband ( self)
Whether or not the image has a spectral dimension.

Definition at line 433 of file image.py.

433 def is_multiband(self) -> bool:
434 """Whether or not the image has a spectral dimension."""
435 return self.n_bands > 0
436

◆ matched_slices()

tuple[tuple[slice, ...], tuple[slice, ...]] lsst.scarlet.lite.image.Image.matched_slices ( self,
Box bbox )
Get the slices to match this image to a given bounding box

Parameters
----------
bbox:
    The bounding box to match this image to.

Returns
-------
result:
    Tuple of indices/slices to match this image to the given bbox.

Definition at line 548 of file image.py.

548 def matched_slices(self, bbox: Box) -> tuple[tuple[slice, ...], tuple[slice, ...]]:
549 """Get the slices to match this image to a given bounding box
550
551 Parameters
552 ----------
553 bbox:
554 The bounding box to match this image to.
555
556 Returns
557 -------
558 result:
559 Tuple of indices/slices to match this image to the given bbox.
560 """
561 if self.bbox == bbox:
562 # No need to slice, since the boxes match
563 _slice = (slice(None),) * bbox.ndim
564 return _slice, _slice
565
566 slices = self.bbox.overlapped_slices(bbox)
567 return slices
568

◆ matched_spectral_indices()

tuple[tuple[int, ...] | slice, tuple[int, ...] | slice] lsst.scarlet.lite.image.Image.matched_spectral_indices ( self,
Image other )
Match bands between two images

Parameters
----------
other:
    The other image to match spectral indices to.

Returns
-------
result:
    A tuple with a tuple of indices/slices for each dimension,
    including the spectral dimension.

Definition at line 513 of file image.py.

516 ) -> tuple[tuple[int, ...] | slice, tuple[int, ...] | slice]:
517 """Match bands between two images
518
519 Parameters
520 ----------
521 other:
522 The other image to match spectral indices to.
523
524 Returns
525 -------
526 result:
527 A tuple with a tuple of indices/slices for each dimension,
528 including the spectral dimension.
529 """
530 if self.bands == other.bands and self.n_bands != 0:
531 # The bands match
532 return slice(None), slice(None)
533 if self.n_bands == 0 and other.n_bands == 0:
534 # The images are 2D, so no spectral slicing is necessary
535 return (), ()
536 if self.n_bands == 0 and other.n_bands > 1:
537 err = "Attempted to insert a monochromatic image into a mutli-band image"
538 raise ValueError(err)
539 if other.n_bands == 0:
540 err = "Attempted to insert a multi-band image into a monochromatic image"
541 raise ValueError(err)
542
543 self_indices = cast(tuple[int, ...], self.spectral_indices(other.bands))
544 matched_bands = tuple(self.bands[bidx] for bidx in self_indices)
545 other_indices = cast(tuple[int, ...], other.spectral_indices(matched_bands))
546 return other_indices, self_indices
547

◆ multiband_slices()

tuple[tuple[int, ...] | slice, slice, slice] lsst.scarlet.lite.image.Image.multiband_slices ( self)
Return the slices required to slice a multiband image

Definition at line 617 of file image.py.

617 def multiband_slices(self) -> tuple[tuple[int, ...] | slice, slice, slice]:
618 """Return the slices required to slice a multiband image"""
619 return (self.spectral_indices(self.bands),) + self.bbox.slices # type: ignore
620

◆ n_bands()

int lsst.scarlet.lite.image.Image.n_bands ( self)
Number of bands in the image.

If `n_bands == 0` then the image is 2D and does not have a spectral
dimension.

Definition at line 424 of file image.py.

424 def n_bands(self) -> int:
425 """Number of bands in the image.
426
427 If `n_bands == 0` then the image is 2D and does not have a spectral
428 dimension.
429 """
430 return len(self._bands)
431

◆ overlapped_slices()

tuple[tuple[slice, ...], tuple[slice, ...]] lsst.scarlet.lite.image.Image.overlapped_slices ( self,
Box bbox )
Get the slices needed to insert this image into a bounding box.

Parameters
----------
bbox:
    The region to insert this image into.

Returns
-------
overlap:
    The slice of this image and the slice of the `bbox` required to
    insert the overlapping portion of this image.

Definition at line 1179 of file image.py.

1179 def overlapped_slices(self, bbox: Box) -> tuple[tuple[slice, ...], tuple[slice, ...]]:
1180 """Get the slices needed to insert this image into a bounding box.
1181
1182 Parameters
1183 ----------
1184 bbox:
1185 The region to insert this image into.
1186
1187 Returns
1188 -------
1189 overlap:
1190 The slice of this image and the slice of the `bbox` required to
1191 insert the overlapping portion of this image.
1192
1193 """
1194 overlap = self.bbox.overlapped_slices(bbox)
1195 if self.is_multiband:
1196 overlap = (slice(None),) + overlap[0], (slice(None),) + overlap[1]
1197 return overlap
1198

◆ project()

Image lsst.scarlet.lite.image.Image.project ( self,
object | tuple[object] | None bands = None,
Box | None bbox = None )
Project this image into a different set of bands

 Parameters
 ----------
 bands:
    Spectral bands to project this image into.
    Not all bands have to be contained in the image, and not all
    bands contained in the image have to be used in the projection.
 bbox:
    A bounding box to project the image into.

Results
-------
image:
    A new image creating by projecting this image into
    `bbox` and `bands`.

Definition at line 569 of file image.py.

573 ) -> Image:
574 """Project this image into a different set of bands
575
576 Parameters
577 ----------
578 bands:
579 Spectral bands to project this image into.
580 Not all bands have to be contained in the image, and not all
581 bands contained in the image have to be used in the projection.
582 bbox:
583 A bounding box to project the image into.
584
585 Results
586 -------
587 image:
588 A new image creating by projecting this image into
589 `bbox` and `bands`.
590 """
591 if bands is None:
592 bands = self.bands
593 if not isinstance(bands, tuple):
594 bands = (bands,)
595 if self.is_multiband:
596 indices = self.spectral_indices(bands)
597 data = self.data[indices, :]
598 else:
599 data = self.data
600
601 if bbox is None:
602 return Image(data, bands=bands, yx0=self.yx0)
603
604 if self.is_multiband:
605 image = np.zeros((len(bands),) + bbox.shape, dtype=data.dtype)
606 slices = bbox.overlapped_slices(self.bbox)
607 # Insert a slice for the spectral dimension
608 image[(slice(None),) + slices[0]] = data[(slice(None),) + slices[1]]
609 return Image(image, bands=bands, yx0=cast(tuple[int, int], bbox.origin))
610
611 image = np.zeros(bbox.shape, dtype=data.dtype)
612 slices = bbox.overlapped_slices(self.bbox)
613 image[slices[0]] = data[slices[1]]
614 return Image(image, bands=bands, yx0=cast(tuple[int, int], bbox.origin))
615

◆ repeat()

Image lsst.scarlet.lite.image.Image.repeat ( self,
tuple bands )
Project a 2D image into the spectral dimension

Parameters
----------
bands:
    The bands in the projected image.

Returns
-------
result: Image
    The 2D image repeated in each band in the spectral dimension.

Definition at line 659 of file image.py.

659 def repeat(self, bands: tuple) -> Image:
660 """Project a 2D image into the spectral dimension
661
662 Parameters
663 ----------
664 bands:
665 The bands in the projected image.
666
667 Returns
668 -------
669 result: Image
670 The 2D image repeated in each band in the spectral dimension.
671 """
672 if self.is_multiband:
673 raise ValueError("Image.repeat only works with 2D images")
674 return self.copy_with(
675 np.repeat(self.data[None, :, :], len(bands), axis=0),
676 bands=bands,
677 yx0=self.yx0,
678 )
679

◆ shape()

tuple[int, ...] lsst.scarlet.lite.image.Image.shape ( self)
The shape of the image.

This includes the spectral dimension, if there is one.

Definition at line 406 of file image.py.

406 def shape(self) -> tuple[int, ...]:
407 """The shape of the image.
408
409 This includes the spectral dimension, if there is one.
410 """
411 return self._data.shape
412

◆ spectral_indices()

tuple[int, ...] | slice lsst.scarlet.lite.image.Image.spectral_indices ( self,
Sequence | slice bands )
The indices to extract each band in `bands` in order from the image

This converts a band name, or list of band names,
into numerical indices that can be used to slice the internal numpy
`data` array.

Parameters
---------
bands:
    If `bands` is a list of band names, then the result will be an
    index corresponding to each band, in order.
    If `bands` is a slice, then the ``start`` and ``stop`` properties
    should be band names, and the result will be a slice with the
    appropriate indices to start at `bands.start` and end at
    `bands.stop`.

Returns
-------
band_indices:
    Tuple of indices for each band in this image.

Definition at line 472 of file image.py.

472 def spectral_indices(self, bands: Sequence | slice) -> tuple[int, ...] | slice:
473 """The indices to extract each band in `bands` in order from the image
474
475 This converts a band name, or list of band names,
476 into numerical indices that can be used to slice the internal numpy
477 `data` array.
478
479 Parameters
480 ---------
481 bands:
482 If `bands` is a list of band names, then the result will be an
483 index corresponding to each band, in order.
484 If `bands` is a slice, then the ``start`` and ``stop`` properties
485 should be band names, and the result will be a slice with the
486 appropriate indices to start at `bands.start` and end at
487 `bands.stop`.
488
489 Returns
490 -------
491 band_indices:
492 Tuple of indices for each band in this image.
493 """
494 if isinstance(bands, slice):
495 # Convert a slice of band names into a slice of array indices
496 # to select the appropriate slice.
497 if bands.start is None:
498 start = None
499 else:
500 start = self.bands.index(bands.start)
501 if bands.stop is None:
502 stop = None
503 else:
504 stop = self.bands.index(bands.stop) + 1
505 return slice(start, stop, bands.step)
506
507 if isinstance(bands, str):
508 return (self.bands.index(bands),)
509
510 band_indices = tuple(self.bands.index(band) for band in bands if band in self.bands)
511 return band_indices
512

◆ width()

int lsst.scarlet.lite.image.Image.width ( self)
Width of the image.

Definition at line 443 of file image.py.

443 def width(self) -> int:
444 """Width of the image."""
445 return self.shape[-1]
446

◆ x0()

int lsst.scarlet.lite.image.Image.x0 ( self)
Location of the x-offset.

Definition at line 458 of file image.py.

458 def x0(self) -> int:
459 """Location of the x-offset."""
460 return self._yx0[1]
461

◆ y0()

int lsst.scarlet.lite.image.Image.y0 ( self)
location of the y-offset.

Definition at line 453 of file image.py.

453 def y0(self) -> int:
454 """location of the y-offset."""
455 return self._yx0[0]
456

◆ yx0()

tuple[int, int] lsst.scarlet.lite.image.Image.yx0 ( self)
Origin of the image, in numpy/C++ y,x ordering.

Definition at line 448 of file image.py.

448 def yx0(self) -> tuple[int, int]:
449 """Origin of the image, in numpy/C++ y,x ordering."""
450 return self._yx0
451

Member Data Documentation

◆ _bands

lsst.scarlet.lite.image.Image._bands
protected

Definition at line 377 of file image.py.

◆ _data

lsst.scarlet.lite.image.Image._data
protected

Definition at line 375 of file image.py.

◆ _yx0

lsst.scarlet.lite.image.Image._yx0
protected

Definition at line 376 of file image.py.

◆ bands

lsst.scarlet.lite.image.Image.bands

Definition at line 530 of file image.py.

◆ bbox

lsst.scarlet.lite.image.Image.bbox

Definition at line 561 of file image.py.

◆ n_bands

lsst.scarlet.lite.image.Image.n_bands

Definition at line 533 of file image.py.


The documentation for this class was generated from the following file: