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=None):
56 if partialPsf
is None:
59 missingBands = [band
for band
in bands
if band
not in partialPsf.bands]
64 message = f
"Failed to compute PSF at {position} in {missingBands}"
69 """Get a multiband PSF image
71 The PSF Image or PSF Kernel Image is computed for each band
72 and combined into a (band, y, x) array.
76 psfModels : `dict[str, lsst.afw.detection.Psf]`
77 The list of PSFs in each band.
78 position : `Point2D` or `tuple`
79 Coordinates to evaluate the PSF.
80 useKernelImage: `bool`
81 Execute ``Psf.computeKernelImage`` when ``True`,
82 ``PSF/computeImage`` when ``False``.
86 psfs: `lsst.afw.image.MultibandImage`
87 The multiband PSF image.
91 if not isinstance(position, Point2D):
92 position =
Point2D(position[0], position[1])
96 for band, psfModel
in psfModels.items():
99 psf = psfModel.computeKernelImage(position)
101 psf = psfModel.computeImage(position)
103 except InvalidParameterError:
109 left = np.min([psf.getBBox().getMinX()
for psf
in psfs.values()])
110 bottom = np.min([psf.getBBox().getMinY()
for psf
in psfs.values()])
111 right = np.max([psf.getBBox().getMaxX()
for psf
in psfs.values()])
112 top = np.max([psf.getBBox().getMaxY()
for psf
in psfs.values()])
115 psf_images = [projectImage(psf, bbox)
for psf
in psfs.values()]
117 mPsf = MultibandImage.fromImages(list(psfs.keys()), psf_images)
126 """MultibandExposure class
128 This class acts as a container for multiple `afw.Exposure` objects.
129 All exposures must have the same bounding box, and the associated
130 images must all have the same data type.
132 See `MultibandTripleBase` for parameter definitions.
134 def __init__(self, bands, image, mask, variance, psfs=None):
135 super().
__init__(bands, image, mask, variance)
142 """Construct a MultibandImage from a collection of single band images
144 see `tripleFromExposures` for a description of parameters
146 psfs = [s.getPsf()
for s
in singles]
151 """Construct a MultibandExposure from a collection of arrays
153 see `tripleFromArrays` for a description of parameters
155 return tripleFromArrays(MultibandExposure, bands, image, mask, variance, bbox)
158 def fromKwargs(bands, bandKwargs, singleType=ExposureF, **kwargs):
159 """Build a MultibandImage from a set of keyword arguments
161 see `makeTripleFromKwargs` for a description of parameters
166 """Make a new list of single band objects
171 List of `Image` objects that represent the image in each band.
173 List of `Mask` objects that represent the mask in each band.
175 List of `Image` objects that represent the variance in each band.
180 Tuple of `MaskedImage` objects for each band,
181 where the `image`, `mask`, and `variance` of each `single`
182 point to the multiband objects.
192 dtype = image.array.dtype
194 maskedImage =
MaskedImage(image=image[f], mask=mask[f], variance=variance[f], dtype=dtype)
195 single =
Exposure(maskedImage, dtype=dtype)
196 singles.append(single)
197 return tuple(singles)
201 """Load a multiband exposure from a butler
203 Because each band is stored in a separate exposure file,
204 this method can be used to load all of the exposures for
209 butler: `lsst.daf.butler.Butler`
210 Butler connection to use to load the single band
212 bands: `list` or `str`
213 List of names for each band
215 Arguments to the Butler.
217 Keyword arguments to pass to the Butler
218 that are the same in all bands.
222 result: `MultibandExposure`
223 The new `MultibandExposure` created by combining all of the
224 single band exposures.
229 exposures.append(butler.get(*args, band=band, **kwargs))
230 return MultibandExposure.fromExposures(bands, exposures)
233 """Get a multiband PSF image
235 The PSF Kernel Image is computed for each band
236 and combined into a (band, y, x) array and stored
238 The result is not cached, so if the same PSF is expected
239 to be used multiple times it is a good idea to store the
240 result in another variable.
244 position: `Point2D` or `tuple`
245 Coordinates to evaluate the PSF.
249 self._psfImage: array
250 The multiband PSF image.
259 """Get a multiband PSF image
261 The PSF Kernel Image is computed for each band
262 and combined into a (band, y, x) array and stored
264 The result is not cached, so if the same PSF is expected
265 to be used multiple times it is a good idea to store the
266 result in another variable.
270 position: `Point2D` or `tuple`
271 Coordinates to evaluate the PSF. If `position` is `None`
272 then `Psf.getAveragePosition()` is used.
276 self._psfImage: array
277 The multiband PSF image.
286 """Extract the PSF model in each band
290 psfs : `dict` of `lsst.afw.detection.Psf`
293 return {band: self[band].getPsf()
for band
in self.
bands}
295 def _slice(self, bands, bandIndex, indices):
296 """Slice the current object and return the result
298 See `Multiband._slice` for a list of the parameters.
299 This overwrites the base method to attach the PSF to
300 each individual exposure.
302 image = self.
image.
_slice(bands, bandIndex, indices)
303 if self.
mask is not None:
304 mask = self.
_mask.
_slice(bands, bandIndex, indices)
313 if isinstance(image, MultibandPixel):
315 assert isinstance(mask, MultibandPixel)
316 if variance
is not None:
317 assert isinstance(variance, MultibandPixel)
318 return (image, mask, variance)
321 psfs = [_psfs[band]
for band
in bands]
331 assert all([r.getBBox() == result._bbox
for r
in [result._mask, result._variance]])
__init__(self, bands, position, partialPsf=None)
_buildSingles(self, image=None, mask=None, variance=None)
fromKwargs(bands, bandKwargs, singleType=ExposureF, **kwargs)
computePsfKernelImage(self, position)
computePsfImage(self, position=None)
fromArrays(bands, image, mask, variance, bbox=None)
_slice(self, bands, bandIndex, indices)
fromButler(butler, bands, *args, **kwargs)
fromExposures(bands, singles)
__init__(self, bands, image, mask, variance, psfs=None)
computePsfImage(psfModels, position, useKernelImage=True)
tripleFromArrays(cls, bands, image, mask, variance, bbox=None)
tripleFromSingles(cls, bands, singles, **kwargs)
makeTripleFromKwargs(cls, bands, bandKwargs, singleType, **kwargs)