Coverage for python/lsst/cell_coadds/_stitched_coadd.py: 51%

55 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-03-26 03:49 -0700

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__ = ("StitchedCoadd",) 

25 

26from collections.abc import Iterator, Set 

27from typing import TYPE_CHECKING 

28 

29from lsst.afw.image import ExposureF, FilterLabel, PhotoCalib 

30from lsst.geom import Box2I 

31 

32from ._common_components import CoaddUnits, CommonComponents, CommonComponentsProperties 

33from ._image_planes import ImagePlanes 

34from ._stitched_image_planes import StitchedImagePlanes 

35from ._stitched_psf import StitchedPsf 

36from ._uniform_grid import UniformGrid 

37 

38if TYPE_CHECKING: 38 ↛ 39line 38 didn't jump to line 39, because the condition on line 38 was never true

39 from ._multiple_cell_coadd import MultipleCellCoadd 

40 

41 

42class StitchedCoadd(StitchedImagePlanes, CommonComponentsProperties): 

43 """A lazy-evaluation coadd that stitches together images from adjacent 

44 cells. 

45 

46 Parameters 

47 ---------- 

48 cell_coadd : `MultipleCellCoadd` 

49 Cell-based coadd to stitch together. 

50 bbox : `Box2I`, optional 

51 The region over which a contiguous coadd is desired. Defaults to 

52 ``cell_coadd.inner_bbox``. 

53 

54 Notes 

55 ----- 

56 This class simply inserts subimages from each cell into the full image, 

57 doing so when an attribute is first accessed to avoid stitching together 

58 planes that may never be accessed. 

59 

60 A `StitchedCoadd` cannot be serialized in FITS format directly. Instead, 

61 the recommended way is to serialize the `MultipleCellCoadd` instance that 

62 was used to construct the object and reconstruct the `StitchedCoadd` by 

63 calling the `stitch` method on it. A less recommended way is to call the 

64 `asExposure` method to get an `lsst.afw.image.Exposure` object and persist 

65 that to the disk. 

66 """ 

67 

68 def __init__(self, cell_coadd: MultipleCellCoadd, *, bbox: Box2I | None = None): 

69 super().__init__() 

70 if bbox is None: 

71 bbox = cell_coadd.outer_bbox 

72 elif not cell_coadd.outer_bbox.contains(bbox): 

73 raise ValueError( 

74 f"Cell coadd inner bounding box {cell_coadd.outer_bbox} does not " 

75 f"contain stitch target area {bbox}." 

76 ) 

77 self._bbox = bbox 

78 self._cell_coadd = cell_coadd 

79 self._psf: StitchedPsf | None = None 

80 self._common = cell_coadd.common 

81 

82 @property 

83 def bbox(self) -> Box2I: 

84 # Docstring inherited. 

85 return self._bbox 

86 

87 @property 

88 def grid(self) -> UniformGrid: 

89 """Object that defines the piecewise grid (of inner cell regions) that 

90 this object stitches together. 

91 

92 This may include cells outside the region covered by these image 

93 planes. 

94 """ 

95 return self._cell_coadd.grid 

96 

97 def _iter_cell_planes(self) -> Iterator[ImagePlanes]: 

98 # Docstring inherited. 

99 for cell in self._cell_coadd.cells.values(): 

100 yield cell.inner 

101 

102 @property 

103 def n_noise_realizations(self) -> int: 

104 # Docstring inherited. 

105 return self._cell_coadd.n_noise_realizations 

106 

107 @property 

108 def mask_fraction_names(self) -> Set[str]: 

109 # Docstring inherited. 

110 return self._cell_coadd.mask_fraction_names 

111 

112 @property 

113 def psf(self) -> StitchedPsf: 

114 """The piecewise PSF of this image.""" 

115 if self._psf is None: 

116 self._psf = StitchedPsf( 

117 self._cell_coadd.cells.rebuild_transformed(lambda cell: cell.psf_image.convertD()), 

118 self._cell_coadd.grid, 

119 ) 

120 return self._psf 

121 

122 @property 

123 def common(self) -> CommonComponents: 

124 # Docstring inherited. 

125 return self._cell_coadd.common 

126 

127 def asExposure(self) -> ExposureF: 

128 """Return an `lsst.afw.image.Exposure` view of this piecewise image.""" 

129 result = ExposureF(self.asMaskedImage()) 

130 # Exposure components derived from "common" components are all simple. 

131 result.setWcs(self._cell_coadd.wcs) 

132 result.setFilter(FilterLabel(band=self.band)) 

133 if self.units is CoaddUnits.nJy: 

134 result.setPhotoCalib(PhotoCalib(1.0)) 

135 

136 # We can't do result.setId here, because: 

137 # 

138 # - we don't know whether this should be a packed tract+patch+band ID 

139 # or just a tract+patch ID; 

140 # 

141 # - we don't know how to pack the information we have anyway. 

142 # 

143 # Maybe DM-31924 will provide a solution to at least the latter. 

144 # result.setId(self._cell_coadd.identifiers.patch) 

145 

146 # We could add CoaddInputs here, but without WCS, PSF, etc in them; 

147 # it's not clear that's good enough or even useful, given that the cell 

148 # provide a much more clean view of what the inputs are at any given 

149 # point. 

150 

151 # PSF is the first of many components that need piecewise 

152 # implementations. More to do here for at least aperture corrections 

153 # and transmission curves. 

154 result.setPsf(self.psf) 

155 

156 return result