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
31from ..image._multiband
import tripleFromSingles, tripleFromArrays, makeTripleFromKwargs
32from ..maskedImage
import MaskedImage
36 """The PSF could not be computed due to incomplete data
42 """Get a multiband PSF image
44 The PSF Kernel Image is computed
for each band
45 and combined into a (filter, y, x) array.
50 The list of PSFs
in each band.
51 position : `Point2D`
or `tuple`
52 Coordinates to evaluate the PSF.
53 bands: `list`
or `str`
54 List of names
for each band
58 The multiband PSF image.
62 if not isinstance(position, Point2D):
63 position = Point2D(position[0], position[1])
65 for bidx, psfModel
in enumerate(psfModels):
68 psf = psfModel.computeKernelImage(position)
70 psf = psfModel.computeImage(position)
72 except InvalidParameterError:
78 msg =
"Failed to compute PSF at {} in band {}"
81 left = np.min([psf.getBBox().getMinX()
for psf
in psfs])
82 bottom = np.min([psf.getBBox().getMinY()
for psf
in psfs])
83 right = np.max([psf.getBBox().getMaxX()
for psf
in psfs])
84 top = np.max([psf.getBBox().getMaxY()
for psf
in psfs])
85 bbox =
Box2I(Point2I(left, bottom), Point2I(right, top))
86 psfs = np.array([projectImage(psf, bbox).array
for psf
in psfs])
91 """MultibandExposure class
93 This class acts as
a container for multiple `afw.Exposure` objects.
94 All exposures must have the same bounding box,
and the associated
95 images must all have the same data type.
97 See `MultibandTripleBase`
for parameter definitions.
99 def __init__(self, filters, image, mask, variance, psfs=None):
100 super().
__init__(filters, image, mask, variance)
102 for psf, exposure
in zip(psfs, self.
singles):
107 """Construct a MultibandImage from a collection of single band images
109 see `tripleFromExposures` for a description of parameters
111 psfs = [s.getPsf() for s
in singles]
112 return tripleFromSingles(MultibandExposure, filters, singles, psfs=psfs)
116 """Construct a MultibandExposure from a collection of arrays
118 see `tripleFromArrays` for a description of parameters
120 return tripleFromArrays(MultibandExposure, filters, image, mask, variance, bbox)
123 def fromKwargs(filters, filterKwargs, singleType=ExposureF, **kwargs):
124 """Build a MultibandImage from a set of keyword arguments
126 see `makeTripleFromKwargs` for a description of parameters
128 return makeTripleFromKwargs(MultibandExposure, filters, filterKwargs, singleType, **kwargs)
130 def _buildSingles(self, image=None, mask=None, variance=None):
131 """Make a new list of single band objects
136 List of `Image` objects that represent the image in each band.
138 List of `Mask` objects that represent the mask
in each band.
140 List of `Image` objects that represent the variance
in each band.
145 Tuple of `MaskedImage` objects
for each band,
146 where the `image`, `mask`,
and `variance` of each `single`
147 point to the multiband objects.
157 dtype = image.array.dtype
159 maskedImage =
MaskedImage(image=image[f], mask=mask[f], variance=variance[f], dtype=dtype)
160 single = Exposure(maskedImage, dtype=dtype)
161 singles.append(single)
162 return tuple(singles)
166 """Load a multiband exposure from a butler
168 Because each band is stored
in a separate exposure file,
169 this method can be used to load all of the exposures
for
174 butler: `lsst.daf.butler.Butler`
175 Butler connection to use to load the single band
177 bands: `list`
or `str`
178 List of names
for each band
180 Arguments to the Butler.
182 Keyword arguments to
pass to the Butler
183 that are the same
in all bands.
187 result: `MultibandExposure`
188 The new `MultibandExposure` created by combining all of the
189 single band exposures.
194 exposures.append(butler.get(*args, band=band, **kwargs))
195 return MultibandExposure.fromExposures(bands, exposures)
198 """Get a multiband PSF image
200 The PSF Kernel Image is computed
for each band
201 and combined into a (filter, y, x) array
and stored
203 The result
is not cached, so
if the same PSF
is expected
204 to be used multiple times it
is a good idea to store the
205 result
in another variable.
209 position: `Point2D`
or `tuple`
210 Coordinates to evaluate the PSF.
214 self._psfImage: array
215 The multiband PSF image.
225 """Get a multiband PSF image
227 The PSF Kernel Image is computed
for each band
228 and combined into a (filter, y, x) array
and stored
230 The result
is not cached, so
if the same PSF
is expected
231 to be used multiple times it
is a good idea to store the
232 result
in another variable.
236 position: `Point2D`
or `tuple`
237 Coordinates to evaluate the PSF. If `position`
is `
None`
238 then `Psf.getAveragePosition()`
is used.
242 self._psfImage: array
243 The multiband PSF image.
253 """Extract the PSF model in each band
260 return [s.getPsf()
for s
in self]
262 def _slice(self, filters, filterIndex, indices):
263 """Slice the current object and return the result
265 See `Multiband._slice` for a list of the parameters.
266 This overwrites the base method to attach the PSF to
267 each individual exposure.
269 image = self.image._slice(filters, filterIndex, indices)
270 if self.
mask is not None:
271 mask = self.
_mask._slice(filters, filterIndex, indices)
275 variance = self.
_variance._slice(filters, filterIndex, indices)
280 if isinstance(image, MultibandPixel):
282 assert isinstance(mask, MultibandPixel)
283 if variance
is not None:
284 assert isinstance(variance, MultibandPixel)
285 return (image, mask, variance)
295 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.
def computePsfKernelImage(self, position)
def fromExposures(filters, singles)
def fromButler(butler, bands, *args, **kwargs)
def __init__(self, filters, image, mask, variance, psfs=None)
def fromArrays(filters, image, mask, variance, bbox=None)
def fromKwargs(filters, filterKwargs, singleType=ExposureF, **kwargs)
def computePsfImage(self, position=None)
An integer coordinate rectangle.
def computePsfImage(psfModels, position, bands, useKernelImage=True)