22from __future__
import annotations
25 "ExtendedPsfCandidateInfo",
26 "ExtendedPsfCandidateSerializationModel",
27 "ExtendedPsfCandidatesSerializationModel",
28 "ExtendedPsfCandidate",
29 "ExtendedPsfCandidates",
33from collections.abc
import Sequence
34from types
import EllipsisType
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 psf_kernel_image: ImageSerializationModel[P] |
None = Field(
100 description=
"Kernel image of the PSF at the cutout center.",
102 star_info: ExtendedPsfCandidateInfo = Field(description=
"Information about the star in the cutout.")
104 def deserialize(self, archive: InputArchive[Any], *, bbox: Box |
None =
None) -> ExtendedPsfCandidate:
105 masked_image = super().
deserialize(archive, bbox=bbox)
107 self.psf_kernel_image.
deserialize(archive)
if self.psf_kernel_image
is not None else None
111 mask=masked_image.mask,
112 variance=masked_image.variance,
113 psf_kernel_image=psf_kernel_image,
114 star_info=self.star_info,
115 )._finish_deserialize(self)
119 """A Pydantic model to represent serialized `ExtendedPsfCandidates`."""
121 candidates: list[ExtendedPsfCandidateSerializationModel[P]] = Field(
122 default_factory=list,
123 description=
"The candidate cutouts in this collection.",
126 def deserialize(self, archive: InputArchive[Any]) -> ExtendedPsfCandidates:
128 [candidate_model.deserialize(archive)
for candidate_model
in self.candidates],
129 metadata=self.metadata,
134 """A cutout centered on a star, with associated metadata.
138 image : `~lsst.images.Image`
139 The main data image for this star cutout.
140 mask : `~lsst.images.Mask`, optional
141 Bitmask that annotates the main image's pixels.
142 variance : `~lsst.images.Image`, optional
143 Per-pixel variance estimates for the image.
144 mask_schema : `~lsst.images.MaskSchema`, optional
145 Schema for the mask, required if a mask is provided.
146 projection : `~lsst.images.Projection`, optional
147 Projection to map pixels to the sky.
148 metadata : `dict` [`str`, `MetadataValue`], optional
149 Additional metadata to associate with this cutout.
150 psf_kernel_image : `~lsst.images.Image`, optional
151 Kernel image of the PSF at the cutout center.
152 star_info : `ExtendedPsfCandidateInfo`, optional
153 Information about the star in the cutout.
157 psf_kernel_image : `~lsst.images.Image`
158 Kernel image of the PSF at the cutout center.
159 star_info : `ExtendedPsfCandidateInfo`
160 Information about the star in this cutout.
167 mask: Mask |
None =
None,
168 variance: Image |
None =
None,
169 mask_schema: MaskSchema |
None =
None,
170 projection: Projection |
None =
None,
171 metadata: dict[str, MetadataValue] |
None =
None,
172 psf_kernel_image: Image |
None =
None,
173 star_info: ExtendedPsfCandidateInfo |
None =
None,
179 mask_schema=mask_schema,
180 projection=projection,
187 def __getitem__(self, bbox: Box | EllipsisType) -> ExtendedPsfCandidate:
191 return self._transfer_metadata(
195 mask=self.mask[bbox],
196 variance=self.variance[bbox],
204 return f
"ExtendedPsfCandidate({self.image!s}, {list(self.mask.schema.names)}, {self.star_info})"
208 f
"ExtendedPsfCandidate({self.image!r}, mask_schema={self.mask.schema!r}, "
209 f
"star_info={self.star_info!r})"
214 """Kernel image of the PSF at the cutout center."""
216 raise RuntimeError(
"No PSF kernel image is attached to this ExtendedPsfCandidate.")
221 """Return the ExtendedPsfCandidateInfo associated with this star."""
224 def copy(self) -> ExtendedPsfCandidate:
225 """Deep-copy the star cutout, metadata, and star info."""
226 return self._transfer_metadata(
228 image=self._image.
copy(),
229 mask=self._mask.
copy(),
230 variance=self._variance.
copy(),
237 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfCandidateSerializationModel:
238 masked_image_model = super().
serialize(archive)
239 serialized_psf_kernel_image = (
240 archive.serialize_direct(
248 **masked_image_model.model_dump(),
249 psf_kernel_image=serialized_psf_kernel_image,
254 def _get_archive_tree_type[P: BaseModel](
255 pointer_type: type[P],
256 ) -> type[ExtendedPsfCandidateSerializationModel[P]]:
257 return ExtendedPsfCandidateSerializationModel[pointer_type]
261 """A collection of star cutouts.
265 candidates : `Iterable` [`ExtendedPsfCandidate`]
266 Collection of `ExtendedPsfCandidate` instances.
267 metadata : `dict` [`str`, `MetadataValue`], optional
268 Global metadata associated with the collection.
272 metadata : `dict` [`str`, `MetadataValue`]
273 Global metadata associated with the collection.
274 ref_id_map : `dict` [`int`, `ExtendedPsfCandidate`]
275 A mapping from reference IDs to `ExtendedPsfCandidate` objects.
276 Only includes candidates with valid reference IDs.
281 candidates: Sequence[ExtendedPsfCandidate],
282 metadata: dict[str, MetadataValue] |
None =
None,
285 self.
_metadata = {}
if metadata
is None else dict(metadata)
287 candidate.star_info.ref_id: candidate
288 for candidate
in self
289 if candidate.star_info.ref_id
is not None
296 if isinstance(index, slice):
304 return f
"ExtendedPsfCandidates(length={len(self)})"
310 """Return the collection's global metadata as a dict."""
315 """Map reference IDs to `ExtendedPsfCandidate` objects."""
319 def read_fits(cls, url: ResourcePathExpression) -> ExtendedPsfCandidates:
320 """Read a collection from a FITS file.
325 URL of the file to read; may be any type supported by
326 `lsst.resources.ResourcePath`.
328 return fits.read(cls, url).deserialized
331 """Write the collection to a FITS file.
336 Name of the file to write to. Must not already exist.
338 fits.write(self, filename)
340 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfCandidatesSerializationModel:
343 archive.serialize_direct(f
"candidate_{index}", candidate.serialize)
344 for index, candidate
in enumerate(self.
_candidates)
350 def _get_archive_tree_type[P: BaseModel](
351 pointer_type: type[P],
352 ) -> type[ExtendedPsfCandidatesSerializationModel[P]]:
353 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