22from __future__
import annotations
25 "ExtendedPsfCandidateInfo",
26 "ExtendedPsfCandidateSerializationModel",
27 "ExtendedPsfCandidatesSerializationModel",
28 "ExtendedPsfCandidate",
29 "ExtendedPsfCandidates",
33from collections.abc
import Sequence
34from types
import EllipsisType
35from typing
import Any, ClassVar
37from pydantic
import BaseModel, Field
39from lsst.images
import (
42 ImageSerializationModel,
45 MaskedImageSerializationModel,
50from lsst.images.serialization
import ArchiveTree, InputArchive, MetadataValue, OutputArchive, Quantity
51from lsst.images.utils
import is_none
52from lsst.resources
import ResourcePathExpression
56 """Information about a star in an `ExtendedPsfCandidate`.
60 visit : `int`, optional
61 The visit during which the star was observed.
62 detector : `int`, optional
63 The detector on which the star was observed.
64 ref_id : `int`, optional
65 The reference catalog ID for the star.
66 ref_mag : `float`, optional
67 The reference magnitude for the star.
68 position_x : `float`, optional
69 The x-coordinate of the star in the focal plane.
70 position_y : `float`, optional
71 The y-coordinate of the star in the focal plane.
72 focal_plane_radius : `~lsst.images.utils.Quantity`, optional
73 The radius of the star from the center of the focal plane.
74 focal_plane_angle : `~lsst.images.utils.Quantity`, optional
75 The angle of the star in the focal plane, measured from the +x axis.
78 visit: int |
None =
None
79 detector: int |
None =
None
80 ref_id: int |
None =
None
81 ref_mag: float |
None =
None
82 position_x: float |
None =
None
83 position_y: float |
None =
None
84 focal_plane_radius: Quantity |
None =
None
85 focal_plane_angle: Quantity |
None =
None
88 attrs =
", ".join(f
"{k}={v!r}" for k, v
in self.__dict__.items())
89 return f
"ExtendedPsfCandidateInfo({attrs})"
95 """A Pydantic model to represent a serialized `ExtendedPsfCandidate`."""
97 SCHEMA_NAME: ClassVar[str] =
"extended_psf_candidate"
98 SCHEMA_VERSION: ClassVar[str] =
"1.0.0"
99 MIN_READ_VERSION: ClassVar[int] = 1
101 psf_kernel_image: ImageSerializationModel[P] |
None = Field(
104 description=
"Kernel image of the PSF at the cutout center.",
106 star_info: ExtendedPsfCandidateInfo = Field(
107 description=
"Information about the star in the cutout.",
110 def deserialize(self, archive: InputArchive[Any], *, bbox: Box |
None =
None) -> ExtendedPsfCandidate:
111 masked_image = super().
deserialize(archive, bbox=bbox)
113 self.psf_kernel_image.
deserialize(archive)
if self.psf_kernel_image
is not None else None
117 mask=masked_image.mask,
118 variance=masked_image.variance,
119 psf_kernel_image=psf_kernel_image,
120 star_info=self.star_info,
121 )._finish_deserialize(self)
125 """A Pydantic model to represent serialized `ExtendedPsfCandidates`."""
127 SCHEMA_NAME: ClassVar[str] =
"extended_psf_candidates"
128 SCHEMA_VERSION: ClassVar[str] =
"1.0.0"
129 MIN_READ_VERSION: ClassVar[int] = 1
131 candidates: list[ExtendedPsfCandidateSerializationModel[P]] = Field(
132 default_factory=list,
133 description=
"The candidate cutouts in this collection.",
136 def deserialize(self, archive: InputArchive[Any]) -> ExtendedPsfCandidates:
138 [candidate_model.deserialize(archive)
for candidate_model
in self.candidates],
139 metadata=self.metadata,
144 """A cutout centered on a star, with associated metadata.
148 image : `~lsst.images.Image`
149 The main data image for this star cutout.
150 mask : `~lsst.images.Mask`, optional
151 Bitmask that annotates the main image's pixels.
152 variance : `~lsst.images.Image`, optional
153 Per-pixel variance estimates for the image.
154 mask_schema : `~lsst.images.MaskSchema`, optional
155 Schema for the mask, required if a mask is provided.
156 projection : `~lsst.images.Projection`, optional
157 Projection to map pixels to the sky.
158 metadata : `dict` [`str`, `MetadataValue`], optional
159 Additional metadata to associate with this cutout.
160 psf_kernel_image : `~lsst.images.Image`, optional
161 Kernel image of the PSF at the cutout center.
162 star_info : `ExtendedPsfCandidateInfo`, optional
163 Information about the star in the cutout.
167 psf_kernel_image : `~lsst.images.Image`
168 Kernel image of the PSF at the cutout center.
169 star_info : `ExtendedPsfCandidateInfo`
170 Information about the star in this cutout.
177 mask: Mask |
None =
None,
178 variance: Image |
None =
None,
179 mask_schema: MaskSchema |
None =
None,
180 projection: Projection |
None =
None,
181 metadata: dict[str, MetadataValue] |
None =
None,
182 psf_kernel_image: Image |
None =
None,
183 star_info: ExtendedPsfCandidateInfo |
None =
None,
189 mask_schema=mask_schema,
190 projection=projection,
197 def __getitem__(self, bbox: Box | EllipsisType) -> ExtendedPsfCandidate:
201 return self._transfer_metadata(
205 mask=self.mask[bbox],
206 variance=self.variance[bbox],
214 return f
"ExtendedPsfCandidate({self.image!s}, {list(self.mask.schema.names)}, {self.star_info})"
218 f
"ExtendedPsfCandidate({self.image!r}, mask_schema={self.mask.schema!r}, "
219 f
"star_info={self.star_info!r})"
224 """Kernel image of the PSF at the cutout center."""
226 raise RuntimeError(
"No PSF kernel image is attached to this ExtendedPsfCandidate.")
231 """Return the ExtendedPsfCandidateInfo associated with this star."""
234 def copy(self) -> ExtendedPsfCandidate:
235 """Deep-copy the star cutout, metadata, and star info."""
236 return self._transfer_metadata(
238 image=self._image.
copy(),
239 mask=self._mask.
copy(),
240 variance=self._variance.
copy(),
247 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfCandidateSerializationModel:
248 masked_image_model = super().
serialize(archive)
249 serialized_psf_kernel_image = (
250 archive.serialize_direct(
258 **masked_image_model.model_dump(),
259 psf_kernel_image=serialized_psf_kernel_image,
264 def _get_archive_tree_type[P: BaseModel](
265 pointer_type: type[P],
266 ) -> type[ExtendedPsfCandidateSerializationModel[P]]:
267 return ExtendedPsfCandidateSerializationModel[pointer_type]
271 """A collection of star cutouts.
275 candidates : `Iterable` [`ExtendedPsfCandidate`]
276 Collection of `ExtendedPsfCandidate` instances.
277 metadata : `dict` [`str`, `MetadataValue`], optional
278 Global metadata associated with the collection.
282 metadata : `dict` [`str`, `MetadataValue`]
283 Global metadata associated with the collection.
284 ref_id_map : `dict` [`int`, `ExtendedPsfCandidate`]
285 A mapping from reference IDs to `ExtendedPsfCandidate` objects.
286 Only includes candidates with valid reference IDs.
291 candidates: Sequence[ExtendedPsfCandidate],
292 metadata: dict[str, MetadataValue] |
None =
None,
295 self.
_metadata = {}
if metadata
is None else dict(metadata)
297 candidate.star_info.ref_id: candidate
298 for candidate
in self
299 if candidate.star_info.ref_id
is not None
306 if isinstance(index, slice):
314 return f
"ExtendedPsfCandidates(length={len(self)})"
320 """Return the collection's global metadata as a dict."""
325 """Map reference IDs to `ExtendedPsfCandidate` objects."""
329 def read_fits(cls, url: ResourcePathExpression) -> ExtendedPsfCandidates:
330 """Read a collection from a FITS file.
335 URL of the file to read; may be any type supported by
336 `lsst.resources.ResourcePath`.
338 return fits.read(cls, url).deserialized
341 """Write the collection to a FITS file.
346 Name of the file to write to. Must not already exist.
348 fits.write(self, filename)
350 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfCandidatesSerializationModel:
353 archive.serialize_direct(f
"candidate_{index}", candidate.serialize)
354 for index, candidate
in enumerate(self.
_candidates)
360 def _get_archive_tree_type[P: BaseModel](
361 pointer_type: type[P],
362 ) -> type[ExtendedPsfCandidatesSerializationModel[P]]:
363 return ExtendedPsfCandidatesSerializationModel[pointer_type]
ExtendedPsfCandidateInfo _star_info
ExtendedPsfCandidate copy(self)
ExtendedPsfCandidateSerializationModel serialize(self, OutputArchive[Any] archive)
Image psf_kernel_image(self)
ExtendedPsfCandidateInfo star_info(self)
ExtendedPsfCandidate __getitem__(self, Box|EllipsisType bbox)
__init__(self, Image image, *, Mask|None mask=None, Image|None variance=None, MaskSchema|None mask_schema=None, Projection|None projection=None, dict[str, MetadataValue]|None metadata=None, Image|None psf_kernel_image=None, ExtendedPsfCandidateInfo|None star_info=None)
ExtendedPsfCandidatesSerializationModel serialize(self, OutputArchive[Any] archive)
None write_fits(self, str filename)
ExtendedPsfCandidates read_fits(cls, ResourcePathExpression url)
__init__(self, Sequence[ExtendedPsfCandidate] candidates, dict[str, MetadataValue]|None metadata=None)
ExtendedPsfCandidate deserialize(self, InputArchive[Any] archive, *, Box|None bbox=None)
ExtendedPsfCandidateInfo star_info
ImageSerializationModel psf_kernel_image