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(
103 description=
"Information about the star in the cutout.",
106 def deserialize(self, archive: InputArchive[Any], *, bbox: Box |
None =
None) -> ExtendedPsfCandidate:
107 masked_image = super().
deserialize(archive, bbox=bbox)
109 self.psf_kernel_image.
deserialize(archive)
if self.psf_kernel_image
is not None else None
113 mask=masked_image.mask,
114 variance=masked_image.variance,
115 psf_kernel_image=psf_kernel_image,
116 star_info=self.star_info,
117 )._finish_deserialize(self)
121 """A Pydantic model to represent serialized `ExtendedPsfCandidates`."""
123 candidates: list[ExtendedPsfCandidateSerializationModel[P]] = Field(
124 default_factory=list,
125 description=
"The candidate cutouts in this collection.",
128 def deserialize(self, archive: InputArchive[Any]) -> ExtendedPsfCandidates:
130 [candidate_model.deserialize(archive)
for candidate_model
in self.candidates],
131 metadata=self.metadata,
136 """A cutout centered on a star, with associated metadata.
140 image : `~lsst.images.Image`
141 The main data image for this star cutout.
142 mask : `~lsst.images.Mask`, optional
143 Bitmask that annotates the main image's pixels.
144 variance : `~lsst.images.Image`, optional
145 Per-pixel variance estimates for the image.
146 mask_schema : `~lsst.images.MaskSchema`, optional
147 Schema for the mask, required if a mask is provided.
148 projection : `~lsst.images.Projection`, optional
149 Projection to map pixels to the sky.
150 metadata : `dict` [`str`, `MetadataValue`], optional
151 Additional metadata to associate with this cutout.
152 psf_kernel_image : `~lsst.images.Image`, optional
153 Kernel image of the PSF at the cutout center.
154 star_info : `ExtendedPsfCandidateInfo`, optional
155 Information about the star in the cutout.
159 psf_kernel_image : `~lsst.images.Image`
160 Kernel image of the PSF at the cutout center.
161 star_info : `ExtendedPsfCandidateInfo`
162 Information about the star in this cutout.
169 mask: Mask |
None =
None,
170 variance: Image |
None =
None,
171 mask_schema: MaskSchema |
None =
None,
172 projection: Projection |
None =
None,
173 metadata: dict[str, MetadataValue] |
None =
None,
174 psf_kernel_image: Image |
None =
None,
175 star_info: ExtendedPsfCandidateInfo |
None =
None,
181 mask_schema=mask_schema,
182 projection=projection,
189 def __getitem__(self, bbox: Box | EllipsisType) -> ExtendedPsfCandidate:
193 return self._transfer_metadata(
197 mask=self.mask[bbox],
198 variance=self.variance[bbox],
206 return f
"ExtendedPsfCandidate({self.image!s}, {list(self.mask.schema.names)}, {self.star_info})"
210 f
"ExtendedPsfCandidate({self.image!r}, mask_schema={self.mask.schema!r}, "
211 f
"star_info={self.star_info!r})"
216 """Kernel image of the PSF at the cutout center."""
218 raise RuntimeError(
"No PSF kernel image is attached to this ExtendedPsfCandidate.")
223 """Return the ExtendedPsfCandidateInfo associated with this star."""
226 def copy(self) -> ExtendedPsfCandidate:
227 """Deep-copy the star cutout, metadata, and star info."""
228 return self._transfer_metadata(
230 image=self._image.
copy(),
231 mask=self._mask.
copy(),
232 variance=self._variance.
copy(),
239 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfCandidateSerializationModel:
240 masked_image_model = super().
serialize(archive)
241 serialized_psf_kernel_image = (
242 archive.serialize_direct(
250 **masked_image_model.model_dump(),
251 psf_kernel_image=serialized_psf_kernel_image,
256 def _get_archive_tree_type[P: BaseModel](
257 pointer_type: type[P],
258 ) -> type[ExtendedPsfCandidateSerializationModel[P]]:
259 return ExtendedPsfCandidateSerializationModel[pointer_type]
263 """A collection of star cutouts.
267 candidates : `Iterable` [`ExtendedPsfCandidate`]
268 Collection of `ExtendedPsfCandidate` instances.
269 metadata : `dict` [`str`, `MetadataValue`], optional
270 Global metadata associated with the collection.
274 metadata : `dict` [`str`, `MetadataValue`]
275 Global metadata associated with the collection.
276 ref_id_map : `dict` [`int`, `ExtendedPsfCandidate`]
277 A mapping from reference IDs to `ExtendedPsfCandidate` objects.
278 Only includes candidates with valid reference IDs.
283 candidates: Sequence[ExtendedPsfCandidate],
284 metadata: dict[str, MetadataValue] |
None =
None,
287 self.
_metadata = {}
if metadata
is None else dict(metadata)
289 candidate.star_info.ref_id: candidate
290 for candidate
in self
291 if candidate.star_info.ref_id
is not None
298 if isinstance(index, slice):
306 return f
"ExtendedPsfCandidates(length={len(self)})"
312 """Return the collection's global metadata as a dict."""
317 """Map reference IDs to `ExtendedPsfCandidate` objects."""
321 def read_fits(cls, url: ResourcePathExpression) -> ExtendedPsfCandidates:
322 """Read a collection from a FITS file.
327 URL of the file to read; may be any type supported by
328 `lsst.resources.ResourcePath`.
330 return fits.read(cls, url).deserialized
333 """Write the collection to a FITS file.
338 Name of the file to write to. Must not already exist.
340 fits.write(self, filename)
342 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfCandidatesSerializationModel:
345 archive.serialize_direct(f
"candidate_{index}", candidate.serialize)
346 for index, candidate
in enumerate(self.
_candidates)
352 def _get_archive_tree_type[P: BaseModel](
353 pointer_type: type[P],
354 ) -> type[ExtendedPsfCandidatesSerializationModel[P]]:
355 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