22__all__ = [
"MultibandExposure",
"computePsfImage",
"IncompleteDataError"]
26from lsst.geom import Point2D, Point2I, Box2I
28from .
import Exposure, ExposureF
29from ..utils
import projectImage
30from .._image._multiband
import MultibandTripleBase, MultibandPixel, MultibandImage
31from .._image._multiband
import tripleFromSingles, tripleFromArrays, makeTripleFromKwargs
32from .._maskedImage
import MaskedImage
36 """The PSF could not be computed due to incomplete data
40 missingBands: `list[str]`
41 The bands for which the PSF could
not be calculated.
43 The point at which the PSF could
not be calcualted
in the
45 partialPsf: `MultibandImage`
46 The image of the PSF using only the bands that successfully
51 bands : `list` of `str`
52 The full list of bands
in the `MultibandExposure` generating
55 def __init__(self, bands, position, partialPsf):
56 missingBands = [band
for band
in bands
if band
not in partialPsf.filters]
61 message = f
"Failed to compute PSF at {position} in {missingBands}"
66 """Get a multiband PSF image
68 The PSF Image or PSF Kernel Image
is computed
for each band
69 and combined into a (filter, y, x) array.
74 The list of PSFs
in each band.
75 position : `Point2D`
or `tuple`
76 Coordinates to evaluate the PSF.
77 useKernelImage: `bool`
78 Execute ``Psf.computeKernelImage`` when ``
True`,
79 ``PSF/computeImage`` when ``
False``.
84 The multiband PSF image.
88 if not isinstance(position, Point2D):
89 position = Point2D(position[0], position[1])
93 for band, psfModel
in psfModels.items():
96 psf = psfModel.computeKernelImage(position)
98 psf = psfModel.computeImage(position)
100 except InvalidParameterError:
103 left = np.min([psf.getBBox().getMinX()
for psf
in psfs.values()])
104 bottom = np.min([psf.getBBox().getMinY()
for psf
in psfs.values()])
105 right = np.max([psf.getBBox().getMaxX()
for psf
in psfs.values()])
106 top = np.max([psf.getBBox().getMaxY()
for psf
in psfs.values()])
107 bbox =
Box2I(Point2I(left, bottom), Point2I(right, top))
109 psf_images = [projectImage(psf, bbox)
for psf
in psfs.values()]
111 mPsf = MultibandImage.fromImages(
list(psfs.keys()), psf_images)
120 """MultibandExposure class
122 This class acts as
a container for multiple `afw.Exposure` objects.
123 All exposures must have the same bounding box,
and the associated
124 images must all have the same data type.
126 See `MultibandTripleBase`
for parameter definitions.
128 def __init__(self, filters, image, mask, variance, psfs=None):
129 super().
__init__(filters, image, mask, variance)
136 """Construct a MultibandImage from a collection of single band images
138 see `tripleFromExposures` for a description of parameters
140 psfs = [s.getPsf() for s
in singles]
141 return tripleFromSingles(MultibandExposure, filters, singles, psfs=psfs)
145 """Construct a MultibandExposure from a collection of arrays
147 see `tripleFromArrays` for a description of parameters
149 return tripleFromArrays(MultibandExposure, filters, image, mask, variance, bbox)
152 def fromKwargs(filters, filterKwargs, singleType=ExposureF, **kwargs):
153 """Build a MultibandImage from a set of keyword arguments
155 see `makeTripleFromKwargs` for a description of parameters
157 return makeTripleFromKwargs(MultibandExposure, filters, filterKwargs, singleType, **kwargs)
160 """Make a new list of single band objects
165 List of `Image` objects that represent the image in each band.
167 List of `Mask` objects that represent the mask
in each band.
169 List of `Image` objects that represent the variance
in each band.
174 Tuple of `MaskedImage` objects
for each band,
175 where the `image`, `mask`,
and `variance` of each `single`
176 point to the multiband objects.
186 dtype = image.array.dtype
188 maskedImage =
MaskedImage(image=image[f], mask=mask[f], variance=variance[f], dtype=dtype)
189 single = Exposure(maskedImage, dtype=dtype)
190 singles.append(single)
191 return tuple(singles)
195 """Load a multiband exposure from a butler
197 Because each band is stored
in a separate exposure file,
198 this method can be used to load all of the exposures
for
203 butler: `lsst.daf.butler.Butler`
204 Butler connection to use to load the single band
206 bands: `list`
or `str`
207 List of names
for each band
209 Arguments to the Butler.
211 Keyword arguments to
pass to the Butler
212 that are the same
in all bands.
216 result: `MultibandExposure`
217 The new `MultibandExposure` created by combining all of the
218 single band exposures.
223 exposures.append(butler.get(*args, band=band, **kwargs))
224 return MultibandExposure.fromExposures(bands, exposures)
227 """Get a multiband PSF image
229 The PSF Kernel Image is computed
for each band
230 and combined into a (filter, y, x) array
and stored
232 The result
is not cached, so
if the same PSF
is expected
233 to be used multiple times it
is a good idea to store the
234 result
in another variable.
238 position: `Point2D`
or `tuple`
239 Coordinates to evaluate the PSF.
243 self._psfImage: array
244 The multiband PSF image.
253 """Get a multiband PSF image
255 The PSF Kernel Image is computed
for each band
256 and combined into a (filter, y, x) array
and stored
258 The result
is not cached, so
if the same PSF
is expected
259 to be used multiple times it
is a good idea to store the
260 result
in another variable.
264 position: `Point2D`
or `tuple`
265 Coordinates to evaluate the PSF. If `position`
is `
None`
266 then `Psf.getAveragePosition()`
is used.
270 self._psfImage: array
271 The multiband PSF image.
280 """Extract the PSF model in each band
289 def _slice(self, filters, filterIndex, indices):
290 """Slice the current object and return the result
292 See `Multiband._slice` for a list of the parameters.
293 This overwrites the base method to attach the PSF to
294 each individual exposure.
296 image = self.image._slice(filters, filterIndex, indices)
297 if self.
mask is not None:
298 mask = self.
_mask.
_slice(filters, filterIndex, indices)
307 if isinstance(image, MultibandPixel):
309 assert isinstance(mask, MultibandPixel)
310 if variance
is not None:
311 assert isinstance(variance, MultibandPixel)
312 return (image, mask, variance)
315 psfs = [_psfs[band]
for band
in filters]
325 assert all([r.getBBox() == result._bbox
for r
in [result._mask, result._variance]])
A polymorphic base class for representing an image's Point Spread Function.
__init__(self, bands, position, partialPsf)
_buildSingles(self, image=None, mask=None, variance=None)
computePsfKernelImage(self, position)
computePsfImage(self, position=None)
__init__(self, filters, image, mask, variance, psfs=None)
fromArrays(filters, image, mask, variance, bbox=None)
fromButler(butler, bands, *args, **kwargs)
fromKwargs(filters, filterKwargs, singleType=ExposureF, **kwargs)
fromExposures(filters, singles)
_slice(self, filters, filterIndex, indices)
An integer coordinate rectangle.
daf::base::PropertyList * list
computePsfImage(psfModels, position, useKernelImage=True)