Coverage for python/lsst/cell_coadds/_stitched_coadd.py: 51%
55 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-01 13:29 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-01 13:29 +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__ = ("StitchedCoadd",)
26from collections.abc import Iterator, Set
27from typing import TYPE_CHECKING
29from lsst.afw.image import ExposureF, FilterLabel, PhotoCalib
30from lsst.geom import Box2I
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
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
42class StitchedCoadd(StitchedImagePlanes, CommonComponentsProperties):
43 """A lazy-evaluation coadd that stitches together images from adjacent
44 cells.
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``.
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.
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 """
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
82 @property
83 def bbox(self) -> Box2I:
84 # Docstring inherited.
85 return self._bbox
87 @property
88 def grid(self) -> UniformGrid:
89 """Object that defines the piecewise grid (of inner cell regions) that
90 this object stitches together.
92 This may include cells outside the region covered by these image
93 planes.
94 """
95 return self._cell_coadd.grid
97 def _iter_cell_planes(self) -> Iterator[ImagePlanes]:
98 # Docstring inherited.
99 for cell in self._cell_coadd.cells.values():
100 yield cell.inner
102 @property
103 def n_noise_realizations(self) -> int:
104 # Docstring inherited.
105 return self._cell_coadd.n_noise_realizations
107 @property
108 def mask_fraction_names(self) -> Set[str]:
109 # Docstring inherited.
110 return self._cell_coadd.mask_fraction_names
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
122 @property
123 def common(self) -> CommonComponents:
124 # Docstring inherited.
125 return self._cell_coadd.common
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))
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)
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.
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)
156 return result