Coverage for python/lsst/cell_coadds/_single_cell_coadd.py: 52%
57 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-10-14 02:24 -0700
« prev ^ index » next coverage.py v7.10.6, created at 2025-10-14 02:24 -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/>.
22from __future__ import annotations
24__all__ = ("SingleCellCoadd",)
26from collections.abc import Iterable, Set
27from typing import TYPE_CHECKING
29from lsst.afw.image import ImageD, ImageF
30from lsst.geom import Box2I
32from ._coadd_ap_corr_map import EMPTY_AP_CORR_MAP
33from ._common_components import CommonComponents, CommonComponentsProperties
34from ._image_planes import ViewImagePlanes
35from .typing_helpers import ImageLike, SingleCellCoaddApCorrMap
37if TYPE_CHECKING: 37 ↛ 38line 37 didn't jump to line 38 because the condition on line 37 was never true
38 from ._identifiers import CellIdentifiers, ObservationIdentifiers
39 from ._image_planes import ImagePlanes, OwnedImagePlanes
42class SingleCellCoadd(CommonComponentsProperties):
43 """A single coadd cell, built only from input images that completely
44 overlap that cell.
46 Parameters
47 ----------
48 outer : `OwnedImagePlanes`
49 The actual coadded images.
50 psf : `ImageD`
51 The coadded PSF image.
52 inner_bbox : `Box2I`
53 The bounding box of the inner region of this cell; must be disjoint
54 with but adjacent to all other cell inner regions.
55 inputs : `Iterable` [`ObservationIdentifiers`]
56 Identifiers of observations that contributed to this cell.
57 common : `CommonComponents`
58 Image attributes common to all cells in a patch.
59 identifiers : `CellIdentifiers`
60 Struct of identifiers for this cell.
61 aperture_correction_map : `frozendict` [`str`, `float`], optional
62 Mapping of algorithm name to aperture correction value for this cell.
64 Notes
65 -----
66 At present we assume a single PSF image per cell is sufficient to capture
67 spatial variability, which seems adequate given the results we have so far
68 and the cell sizes we intend to use.
69 """
71 def __init__(
72 self,
73 outer: OwnedImagePlanes,
74 *,
75 psf: ImageD,
76 inner_bbox: Box2I,
77 inputs: Iterable[ObservationIdentifiers],
78 common: CommonComponents,
79 identifiers: CellIdentifiers,
80 aperture_correction_map: SingleCellCoaddApCorrMap = EMPTY_AP_CORR_MAP,
81 ):
82 assert outer.bbox.contains(
83 inner_bbox
84 ), f"Cell inner bbox {inner_bbox} is not contained by outer bbox {outer.bbox}."
85 self._outer = outer
86 self._psf = psf
87 self._inner_bbox = inner_bbox
88 self._inner = ViewImagePlanes(outer, bbox=inner_bbox, make_view=self.make_view)
89 self._common = common
90 # Remove any duplicate elements in the input, sorted them and make
91 # them an immutable sequence.
92 # TODO: Remove support for inputs as None when bumping to v1.0 .
93 self._inputs = tuple(sorted(set(inputs))) if inputs else ()
94 self._identifiers = identifiers
95 self._aperture_correction_map = aperture_correction_map
97 @property
98 def inner(self) -> ImagePlanes:
99 """Image planes within the inner region of this cell that is disjoint
100 with all other cell inner regions.
101 """
102 return self._inner
104 @property
105 def outer(self) -> ImagePlanes:
106 """Image planes within the full outer region of this cell."""
107 return self._outer
109 @property
110 def psf_image(self) -> ImageF:
111 """The coadded PSF image."""
112 return self._psf
114 @property
115 # TODO: Remove the option of returning empty tuple in v1.0.
116 def inputs(self) -> tuple[ObservationIdentifiers, ...] | tuple[()]:
117 """Identifiers for the input images that contributed to this cell,
118 sorted by their `visit` attribute first, and then by `detector`.
119 """
120 return self._inputs
122 @property
123 def visit_count(self) -> int:
124 """Number of visits that contributed to this cell."""
125 return len(self.inputs)
127 @property
128 def identifiers(self) -> CellIdentifiers:
129 """Struct of unique identifiers for this cell."""
130 # This overrides the patch-level property from
131 # CommonComponentsProperties to provide cell-level information.
132 return self._identifiers
134 @property
135 def common(self) -> CommonComponents:
136 # Docstring inherited.
137 return self._common
139 @property
140 def aperture_correction_map(self) -> SingleCellCoaddApCorrMap:
141 """Mapping of algorithm name to aperture correction values.
143 Returns
144 -------
145 aperture_correction_map : `frozendict` [`str`, float]
146 Mapping of algorithm name to aperture correction values.
147 """
148 return self._aperture_correction_map
150 @property
151 def aperture_corrected_algorithms(self) -> Set[str]:
152 """An iterable of algorithm names that have aperture correction values.
154 Returns
155 -------
156 aperture_corrected_algorithms : `tuple` [`str`, ...]
157 List of algorithms that have aperture correction values.
158 """
159 if self._aperture_correction_map:
160 return self._aperture_correction_map.keys()
162 return set()
164 def make_view(self, image: ImageLike, bbox: Box2I | None = None) -> ImageLike:
165 """Make a view of an image, optionally within a given bounding box.
167 Parameters
168 ----------
169 image : `ImageLike`
170 The image to make a view of.
171 bbox : `Box2I`, optional
172 The bounding box within which to make the view.
174 Returns
175 -------
176 image_view: `ImageLike`
177 The view of the image.
178 """
179 if bbox is None:
180 bbox = self._inner_bbox
181 return image[bbox]