Coverage for python/lsst/cell_coadds/_image_planes.py: 69%

69 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-28 09:16 +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/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ( 

25 "ImagePlanes", 

26 "OwnedImagePlanes", 

27 "ViewImagePlanes", 

28) 

29 

30from abc import ABC, abstractmethod 

31from collections.abc import Callable, Sequence 

32from typing import TYPE_CHECKING 

33 

34from lsst.afw.image import MaskedImageF 

35 

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 

39 

40 from .typing_helpers import ImageLike 

41 

42 

43class ImagePlanes(ABC): 

44 """Struct interface for the image-like planes we coadd. 

45 

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 """ 

51 

52 @property 

53 @abstractmethod 

54 def bbox(self) -> Box2I: 

55 """The bounding box common to all image planes.""" 

56 raise NotImplementedError() 

57 

58 @property 

59 @abstractmethod 

60 def image(self) -> ImageLike: 

61 """The data image itself.""" 

62 raise NotImplementedError() 

63 

64 @property 

65 @abstractmethod 

66 def mask(self) -> Mask: 

67 """An integer bitmask.""" 

68 raise NotImplementedError() 

69 

70 @property 

71 @abstractmethod 

72 def variance(self) -> ImageLike: 

73 """Per-pixel variances for the image.""" 

74 raise NotImplementedError() 

75 

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() 

83 

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() 

91 

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) 

97 

98 

99class OwnedImagePlanes(ImagePlanes): 

100 """An implementation of the `ImagePlanes` interface backed by actual 

101 afw objects. 

102 """ 

103 

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) 

118 

119 @property 

120 def bbox(self) -> Box2I: 

121 # Docstring inherited. 

122 return self._image.getBBox() 

123 

124 @property 

125 def image(self) -> ImageLike: 

126 # Docstring inherited. 

127 return self._image 

128 

129 @property 

130 def mask(self) -> Mask: 

131 # Docstring inherited. 

132 return self._mask 

133 

134 @property 

135 def variance(self) -> ImageLike: 

136 # Docstring inherited. 

137 return self._variance 

138 

139 @property 

140 def mask_fractions(self) -> ImageLike | None: 

141 # Docstring inherited. 

142 return self._mask_fractions 

143 

144 @property 

145 def noise_realizations(self) -> Sequence[ImageLike]: 

146 # Docstring inherited. 

147 return self._noise_realizations 

148 

149 

150class ViewImagePlanes(ImagePlanes): 

151 """An implementation of the `ImagePlanes` interface that extracts views 

152 from another target `ImagePlanes` instance. 

153 

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 """ 

163 

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 

170 

171 @property 

172 def bbox(self) -> Box2I: 

173 # Docstring inherited. 

174 return self._bbox 

175 

176 @property 

177 def image(self) -> ImageLike: 

178 # Docstring inherited. 

179 return self._make_view(self._target.image) 

180 

181 @property 

182 def mask(self) -> Mask: 

183 # Docstring inherited. 

184 return self._make_view(self._target.mask) 

185 

186 @property 

187 def variance(self) -> ImageLike: 

188 # Docstring inherited. 

189 return self._make_view(self._target.variance) 

190 

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) 

196 

197 return None 

198 

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)