22 __all__ = [
"MultibandFootprint"]
32 from .
import Footprint, makeHeavyFootprint
36 """Create a Footprint from a set of Images
40 images : `lsst.afw.image.MultibandImage` or list of `lsst.afw.image.Image`, array
41 Images to extract the footprint from
43 All pixels above `thresh` will be included in the footprint
44 xy0 : `lsst.geom.Point2I`
45 Location of the minimum value of the images bounding box
46 (if images is an array, otherwise the image bounding box is used).
50 spans : `lsst.afw.geom.SpanSet`
51 Union of all spans in the images above the threshold
52 imageBBox : `lsst.afw.detection.Box2I`
53 Bounding box for the input images.
56 if not hasattr(thresh,
"__len__"):
57 thresh = [thresh] * len(images)
61 if isinstance(images, MultibandBase)
or isinstance(images[0], Image):
63 for n, image
in enumerate(images):
64 mask = image.array > thresh[n]
65 mask =
Mask(mask.astype(np.int32), xy0=image.getBBox().getMin())
66 spans = spans.union(SpanSet.fromMask(mask))
67 imageBBox = images[0].getBBox()
70 thresh = np.array(thresh)
73 mask = np.any(images > thresh[:,
None,
None], axis=0)
74 mask =
Mask(mask.astype(np.int32), xy0=xy0)
75 spans = SpanSet.fromMask(mask)
76 imageBBox = mask.getBBox()
77 return spans, imageBBox
81 """Create an image of a HeavyFootprint
85 heavy : `HeavyFootprint`
86 The HeavyFootprint to insert into the image
88 Number to fill the pixels in the image that are not
91 Bounding box of the output image.
93 This should be either a `MaskedImage` or `Image` and describes
94 the type of the output image.
98 image : `lsst.afw.image.MaskedImage` or `lsst.afw.image.Image`
99 An image defined by `bbox` and padded with `fill` that
100 contains the projected flux in `heavy`.
103 bbox = heavy.getBBox()
104 image = imageType(bbox, dtype=heavy.getImageArray().dtype)
111 """Multiband Footprint class
113 A `MultibandFootprint` is a collection of HeavyFootprints that have
114 the same `SpanSet` and `peakCatalog` but different flux in each band.
119 List of filter names.
121 A list of single band `HeavyFootprint` objects.
122 Each `HeavyFootprint` should have the same `PeakCatalog`
123 and the same `SpanSet`, however to save CPU cycles there
124 is no internal check for consistency of the peak catalog.
130 if not all([heavy.getSpans() == spans
for heavy
in singles]):
131 raise ValueError(
"All HeavyFootprints in singles are expected to have the same SpanSet")
135 footprint.setPeakCatalog(singles[0].
getPeaks())
139 def fromArrays(filters, image, mask=None, variance=None, footprint=None, xy0=None, thresh=0, peaks=None):
140 """Create a `MultibandFootprint` from an `image`, `mask`, `variance`
145 List of filter names.
147 An array to convert into `lsst.afw.detection.HeavyFootprint` objects.
148 Only pixels above the `thresh` value for at least one band
149 will be included in the `SpanSet` and resulting footprints.
151 Mask for the `image` array.
153 Variance of the `image` array.
154 footprint : `Footprint`
155 `Footprint` that contains the `SpanSet` and `PeakCatalog`
156 to use for the `HeavyFootprint` in each band.
157 If `footprint` is `None` then the `thresh` is used to create a
158 `Footprint` based on the pixels above the `thresh` value.
160 If `image` is an array and `footprint` is `None` then specifying
161 `xy0` gives the location of the minimum `x` and `y` value of the
163 thresh : `float` or list of floats
164 Threshold in each band (or the same threshold to be used in all bands)
165 to include a pixel in the `SpanSet` of the `MultibandFootprint`.
166 If `Footprint` is not `None` then `thresh` is ignored.
167 peaks : `PeakCatalog`
168 Catalog containing information about the peaks located in the
173 result : `MultibandFootprint`
174 MultibandFootprint created from the arrays
177 if footprint
is None:
181 imageBBox = footprint.getBBox()
183 if peaks
is not None:
184 footprint.setPeakCatalog(peaks)
185 mMaskedImage = MultibandMaskedImage.fromArrays(filters, image, mask, variance, imageBBox)
186 singles = [
makeHeavyFootprint(footprint, maskedImage)
for maskedImage
in mMaskedImage]
190 def fromImages(filters, image, mask=None, variance=None, footprint=None, thresh=0, peaks=None):
191 """Create a `MultibandFootprint` from an `image`, `mask`, `variance`
196 List of filter names.
197 image : `lsst.afw.image.MultibandImage`, or list of `lsst.afw.image.Image`
198 A `lsst.afw.image.MultibandImage` (or collection of images in each band)
199 to convert into `HeavyFootprint` objects.
200 Only pixels above the `thresh` value for at least one band
201 will be included in the `SpanSet` and resulting footprints.
202 mask : `MultibandMask` or list of `Mask`
203 Mask for the `image`.
204 variance : `lsst.afw.image.MultibandImage`, or list of `lsst.afw.image.Image`
205 Variance of the `image`.
206 thresh : `float` or `list` of floats
207 Threshold in each band (or the same threshold to be used in all bands)
208 to include a pixel in the `SpanSet` of the `MultibandFootprint`.
209 If `Footprint` is not `None` then `thresh` is ignored.
210 peaks : `PeakCatalog`
211 Catalog containing information about the peaks located in the
216 result : `MultibandFootprint`
217 MultibandFootprint created from the image, mask, and variance
220 if footprint
is None:
224 if peaks
is not None:
225 footprint.setPeakCatalog(peaks)
227 singles = [
makeHeavyFootprint(footprint, maskedImage)
for maskedImage
in mMaskedImage]
232 """Create a `MultibandFootprint` from a list of `MaskedImage`
234 See `fromImages` for a description of the parameters not listed below
238 maskedImages : `list` of `lsst.afw.image.MaskedImage`
239 MaskedImages to extract the single band heavy footprints from.
240 Like `fromImages`, if a `footprint` is not specified then all
241 pixels above `thresh` will be used, and `peaks` will be added
242 to the `PeakCatalog`.
246 result : `MultibandFootprint`
247 MultibandFootprint created from the image, mask, and variance
249 image = [maskedImage.image
for maskedImage
in maskedImages]
250 mask = [maskedImage.mask
for maskedImage
in maskedImages]
251 variance = [maskedImage.variance
for maskedImage
in maskedImages]
252 return MultibandFootprint.fromImages(filters, image, mask, variance, footprint, thresh, peaks)
255 """Get the full `SpanSet`"""
260 """Common SpanSet and peak catalog for the single band footprints"""
265 """MultibandMaskedImage that the footprints present a view into"""
266 return self._mMaskedImage
270 """`SpanSet` of the `MultibandFootprint`"""
274 """Get the `PeakCatalog`"""
279 """`PeakCatalog` of the `MultibandFootprint`"""
282 def _slice(self, filters, filterIndex, indices):
283 """Slice the current object and return the result
285 `MultibandFootprint` objects cannot be sliced along the image
286 dimension, so an error is thrown if `indices` has any elements.
288 See `Multiband._slice` for a list of the parameters.
291 raise IndexError(
"MultibandFootprints can only be sliced in the filter dimension")
293 if isinstance(filterIndex, slice):
294 singles = self.
singlessingles[filterIndex]
296 singles = [self.
singlessingles[idx]
for idx
in filterIndex]
300 def getImage(self, bbox=None, fill=np.nan, imageType=MultibandMaskedImage):
301 """Convert a `MultibandFootprint` to a `MultibandImage`
303 This returns the heavy footprints converted into an `MultibandImage` or
304 `MultibandMaskedImage` (depending on `imageType`).
305 This might be different than the internal `mMaskedImage` property
306 of the `MultibandFootprint`, as the `mMaskedImage` might contain
307 some non-zero pixels not contained in the footprint but present in
313 Bounding box of the resulting image.
314 If no bounding box is specified, then the bounding box
315 of the footprint is used.
317 Value to use for any pixel in the resulting image
318 outside of the `SpanSet`.
320 This should be either a `MultibandMaskedImage`
321 or `MultibandImage` and describes the type of the output image.
325 result : `MultibandBase`
326 The resulting `MultibandImage` or `MultibandMaskedImage` created
327 from the `MultibandHeavyFootprint`.
329 if imageType == MultibandMaskedImage:
330 singleType = MaskedImage
331 elif imageType == MultibandImage:
334 raise TypeError(
"Expected imageType to be either MultibandImage or MultibandMaskedImage")
336 mMaskedImage = imageType.fromImages(self.
filtersfilters, maskedImages)
340 """Copy the current object
345 Whether or not to make a deep copy
349 result : `MultibandFootprint`
350 The cloned footprint.
355 footprint.addPeak(peak.getX(), peak.getY(), peak.getValue())
356 mMaskedImage = self.
getImagegetImage()
357 filters = tuple([f
for f
in self.
filtersfilters])
358 result = MultibandFootprint.fromMaskedImages(filters, mMaskedImage, footprint)
A compact representation of a collection of pixels.
def heavyFootprintToImage(heavy, fill=np.nan, bbox=None, imageType=MaskedImage)
def getSpanSetFromImages(images, thresh=0, xy0=None)
HeavyFootprint< ImagePixelT, MaskPixelT, VariancePixelT > makeHeavyFootprint(Footprint const &foot, lsst::afw::image::MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > const &img, HeavyFootprintCtrl const *ctrl=nullptr)
Create a HeavyFootprint with footprint defined by the given Footprint and pixel values from the given...
lsst::afw::detection::Footprint Footprint
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.