Coverage for python/lsst/cell_coadds/_image_planes.py: 69%
69 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-24 10:25 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-24 10:25 +0000
1# This file is part of cell_coadds.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22from __future__ import annotations
24__all__ = (
25 "ImagePlanes",
26 "OwnedImagePlanes",
27 "ViewImagePlanes",
28)
30from abc import ABC, abstractmethod
31from collections.abc import Callable, Sequence
32from typing import TYPE_CHECKING
34from lsst.afw.image import MaskedImageF
36if TYPE_CHECKING: 36 ↛ 37line 36 didn't jump to line 37, because the condition on line 36 was never true
37 from lsst.afw.image import Mask
38 from lsst.geom import Box2I
40 from .typing_helpers import ImageLike
43class ImagePlanes(ABC):
44 """Struct interface for the image-like planes we coadd.
46 Notes
47 -----
48 The extends the set of planes in `lsst.afw.image.MaskedImage` by adding
49 noise realizations and "mask fraction" images.
50 """
52 @property
53 @abstractmethod
54 def bbox(self) -> Box2I:
55 """The bounding box common to all image planes."""
56 raise NotImplementedError()
58 @property
59 @abstractmethod
60 def image(self) -> ImageLike:
61 """The data image itself."""
62 raise NotImplementedError()
64 @property
65 @abstractmethod
66 def mask(self) -> Mask:
67 """An integer bitmask."""
68 raise NotImplementedError()
70 @property
71 @abstractmethod
72 def variance(self) -> ImageLike:
73 """Per-pixel variances for the image."""
74 raise NotImplementedError()
76 @property
77 @abstractmethod
78 def mask_fractions(self) -> ImageLike | None:
79 """The (weighted) fraction of masked pixels that contribute to each
80 pixel.
81 """
82 raise NotImplementedError()
84 @property
85 @abstractmethod
86 def noise_realizations(self) -> Sequence[ImageLike]:
87 """A sequence of noise realizations that were coadded with the same
88 operations that were appled to the data image.
89 """
90 raise NotImplementedError()
92 def asMaskedImage(self) -> MaskedImageF:
93 """Return an `lsst.afw.image.MaskedImage` view of the image, mask, and
94 variance planes.
95 """
96 return MaskedImageF(self.image, self.mask, self.variance)
99class OwnedImagePlanes(ImagePlanes):
100 """An implementation of the `ImagePlanes` interface backed by actual
101 afw objects.
102 """
104 def __init__(
105 self,
106 *,
107 image: ImageLike,
108 mask: Mask,
109 variance: ImageLike,
110 mask_fractions: ImageLike | None = None,
111 noise_realizations: Sequence[ImageLike] = (),
112 ):
113 self._image = image
114 self._mask = mask
115 self._variance = variance
116 self._mask_fractions = mask_fractions
117 self._noise_realizations = tuple(noise_realizations)
119 @property
120 def bbox(self) -> Box2I:
121 # Docstring inherited.
122 return self._image.getBBox()
124 @property
125 def image(self) -> ImageLike:
126 # Docstring inherited.
127 return self._image
129 @property
130 def mask(self) -> Mask:
131 # Docstring inherited.
132 return self._mask
134 @property
135 def variance(self) -> ImageLike:
136 # Docstring inherited.
137 return self._variance
139 @property
140 def mask_fractions(self) -> ImageLike | None:
141 # Docstring inherited.
142 return self._mask_fractions
144 @property
145 def noise_realizations(self) -> Sequence[ImageLike]:
146 # Docstring inherited.
147 return self._noise_realizations
150class ViewImagePlanes(ImagePlanes):
151 """An implementation of the `ImagePlanes` interface that extracts views
152 from another target `ImagePlanes` instance.
154 Parameters
155 ----------
156 target : `ImagePlanes`
157 Planes to construct views of.
158 make_view : `Callable`
159 Callable that takes an original image plane and returns a view into it.
160 bbox : `Box2I`, optional
161 Bounding box of the new image plane. Defaults to ``target.bbox``.
162 """
164 def __init__(
165 self, target: ImagePlanes, make_view: Callable[[ImageLike], ImageLike], bbox: Box2I | None = None
166 ):
167 self._target = target
168 self._bbox = bbox if bbox is not None else self._target.bbox
169 self._make_view = make_view
171 @property
172 def bbox(self) -> Box2I:
173 # Docstring inherited.
174 return self._bbox
176 @property
177 def image(self) -> ImageLike:
178 # Docstring inherited.
179 return self._make_view(self._target.image)
181 @property
182 def mask(self) -> Mask:
183 # Docstring inherited.
184 return self._make_view(self._target.mask)
186 @property
187 def variance(self) -> ImageLike:
188 # Docstring inherited.
189 return self._make_view(self._target.variance)
191 @property
192 def mask_fractions(self) -> ImageLike | None:
193 # Docstring inherited.
194 if self._target.mask_fractions is not None:
195 return self._make_view(self._target.mask_fractions)
197 return None
199 @property
200 def noise_realizations(self) -> Sequence[ImageLike]:
201 # Docstring inherited.
202 # We could make this even lazier with a custom Sequence class, but it
203 # doesn't seem worthwhile.
204 return tuple(self._make_view(r) for r in self._target.noise_realizations)