22from __future__
import annotations
25 "ExtendedPsfImageInfo",
26 "ExtendedPsfImageSerializationModel",
31from types
import EllipsisType
32from typing
import Any, ClassVar
35from astropy.units
import UnitBase
36from pydantic
import BaseModel, Field
38from lsst.images
import Box, GeneralizedImage, Image, ImageSerializationModel
39from lsst.images.serialization
import ArchiveTree, InputArchive, MetadataValue, OutputArchive
41from .extended_psf_fit
import ExtendedPsfFit, ExtendedPsfMoffatFit
45 """Additional information about an `ExtendedPsfImage`.
49 n_stars : `int`, optional
50 Number of stars used to construct the extended PSF image.
53 n_stars: int |
None =
None
56 attrs =
", ".join(f
"{k}={v!r}" for k, v
in self.__dict__.items())
57 return f
"ExtendedPsfImageInfo({attrs})"
63 """A multi-plane image with data (image) and variance planes, and the
64 results of a profile fit to the image.
68 image : `~lsst.images.Image`
70 variance : `~lsst.images.Image`, optional
71 The per-pixel uncertainty of the main image as an image of variance
72 values. Must have the same bounding box as ``image`` if provided, and
73 its units must be the square of ``image.unit`` or `None`.
74 Values default to ``1.0``. Any attached ``sky_projection`` is replaced
76 info : `ExtendedPsfImageInfo`, optional
77 Additional information about how the extended PSF image was
79 fit : `ExtendedPsfFit`, optional
80 The results of a profile fit to the image.
81 metadata : `dict` [`str`, `MetadataValue`], optional
82 Arbitrary flexible metadata to associate with the image.
86 image : `~lsst.images.Image`
88 variance : `~lsst.images.Image`
89 The per-pixel uncertainty of the main image as an image of variance
91 info : `ExtendedPsfImageInfo`
92 Additional information about how the extended PSF image was
94 fit : `ExtendedPsfFit`
95 The results of a profile fit to the image.
102 variance: Image |
None =
None,
103 info: ExtendedPsfImageInfo |
None =
None,
104 fit: ExtendedPsfFit |
None =
None,
105 metadata: dict[str, MetadataValue] |
None =
None,
113 unit=
None if image.unit
is None else image.unit**2,
116 if image.bbox != variance.bbox:
117 raise ValueError(f
"Image ({image.bbox}) and variance ({variance.bbox}) bboxes do not agree.")
118 if image.unit
is None:
119 if variance.unit
is not None:
120 raise ValueError(f
"Image has no units but variance does ({variance.unit}).")
121 elif variance.unit
is None:
122 variance = variance.view(unit=image.unit**2)
123 elif variance.unit != image.unit**2:
125 f
"Variance unit ({variance.unit}) should be the square of the image unit ({image.unit})."
138 """The main image plane (`Image`)."""
143 """The variance plane (`Image`)."""
148 """The bounding box shared by both image planes (`Box`)."""
152 def unit(self) -> UnitBase | None:
153 """The units of the image plane (`astropy.units.Unit` | `None`)."""
158 """The projection that maps the pixel grid to the sky.
160 ExtendedPsfImage does not support attached projections,
161 so this always returns `None`.
166 def info(self) -> ExtendedPsfImageInfo:
167 """Additional information about the image (`ExtendedPsfImageInfo`)."""
171 def fit(self) -> ExtendedPsfFit:
172 """The results of a profile fit to the image."""
175 def __getitem__(self, bbox: Box | EllipsisType) -> ExtendedPsfImage:
179 return self._transfer_metadata(
189 def __setitem__(self, bbox: Box | EllipsisType, value: ExtendedPsfImage) ->
None:
190 self.
_image[bbox] = value.image
194 return f
"ExtendedPsfImage({self.image!s}, info={self.info!r}, fit={self.fit!r})"
198 def copy(self) -> ExtendedPsfImage:
199 """Deep-copy the profile image and metadata."""
200 return self._transfer_metadata(
204 info=self.
_info.model_copy(),
205 fit=self.
_fit.model_copy(),
210 def serialize(self, archive: OutputArchive[Any]) -> ExtendedPsfImageSerializationModel:
211 """Serialize the Extended PSF image to an output archive.
218 serialized_image = archive.serialize_direct(
219 "image", functools.partial(self.
image.serialize, save_projection=
False)
221 serialized_variance = archive.serialize_direct(
222 "variance", functools.partial(self.
variance.serialize, save_projection=
False)
224 serialized_info = self.
info
225 serialized_fit = self.
fit
227 image=serialized_image,
228 variance=serialized_variance,
229 info=serialized_info,
231 metadata=self.metadata,
236 model: ExtendedPsfImageSerializationModel[Any], archive: InputArchive[Any], *, bbox: Box |
None =
None
237 ) -> ExtendedPsfImage:
238 """Deserialize an image from an input archive.
243 A Pydantic model representation of the image, holding references
244 to data stored in the archive.
246 Archive to read from.
248 Bounding box of a subimage to read instead.
250 return model.deserialize(archive, bbox=bbox)
253 def _get_archive_tree_type[P: BaseModel](
254 pointer_type: type[P],
255 ) -> type[ExtendedPsfImageSerializationModel[P]]:
256 """Return the serialization model type for this object for an archive
257 type that uses the given pointer type.
259 return ExtendedPsfImageSerializationModel[pointer_type]
263 """A Pydantic model used to represent a serialized `ExtendedPsfImage`."""
265 SCHEMA_NAME: ClassVar[str] =
"extended_psf_image"
266 SCHEMA_VERSION: ClassVar[str] =
"1.0.0"
267 MIN_READ_VERSION: ClassVar[int] = 1
268 PUBLIC_TYPE: ClassVar[type] = ExtendedPsfImage
270 image: ImageSerializationModel[P] = Field(
271 description=
"The main data image.",
273 variance: ImageSerializationModel[P] = Field(
274 description=
"Per-pixel variance estimates for the main image."
276 info: ExtendedPsfImageInfo = Field(
277 description=
"Additional information about the extended PSF image.",
279 fit: ExtendedPsfMoffatFit | ExtendedPsfFit = Field(
280 description=
"The results of an extended PSF fit to the image.",
285 """The bounding box of the image."""
286 return self.image.bbox
288 def deserialize(self, archive: InputArchive[Any], *, bbox: Box |
None =
None) -> ExtendedPsfImage:
289 """Deserialize an image from an input archive.
294 Archive to read from.
296 Bounding box of a subimage to read instead.
299 variance = self.variance.
deserialize(archive, bbox=bbox)
305 )._finish_deserialize(self)
None __setitem__(self, Box|EllipsisType bbox, ExtendedPsfImage value)
ExtendedPsfImageInfo info(self)
ExtendedPsfImage __getitem__(self, Box|EllipsisType bbox)
ExtendedPsfImage copy(self)
ExtendedPsfImage deserialize(ExtendedPsfImageSerializationModel[Any] model, InputArchive[Any] archive, *, Box|None bbox=None)
ExtendedPsfImageSerializationModel serialize(self, OutputArchive[Any] archive)
__init__(self, Image image, *, Image|None variance=None, ExtendedPsfImageInfo|None info=None, ExtendedPsfFit|None fit=None, dict[str, MetadataValue]|None metadata=None)
None sky_projection(self)
ExtendedPsfImageInfo _info
ExtendedPsfImage deserialize(self, InputArchive[Any] archive, *, Box|None bbox=None)
ImageSerializationModel variance
ExtendedPsfImageInfo info
ImageSerializationModel image