22__all__ = [
"MultibandFootprint"]
32from .
import Footprint, makeHeavyFootprint
36 """Create a Footprint from a set of Images
41 Images to extract the footprint
from
43 All pixels above `thresh` will be included
in the footprint
45 Location of the minimum value of the images bounding box
46 (
if images
is an array, otherwise the image bounding box
is used).
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 """Multiband Footprint class
83 A `MultibandFootprint` is a collection of HeavyFootprints that have
84 the same `SpanSet`
and `peakCatalog` but different flux
in each band.
91 A list of single band `HeavyFootprint` objects.
92 Each `HeavyFootprint` should have the same `PeakCatalog`
93 and the same `SpanSet`, however to save CPU cycles there
94 is no internal check
for consistency of the peak catalog.
100 if not all([heavy.getSpans() == spans
for heavy
in singles]):
101 raise ValueError(
"All HeavyFootprints in singles are expected to have the same SpanSet")
105 footprint.setPeakCatalog(singles[0].
getPeaks())
109 def fromArrays(filters, image, mask=None, variance=None, footprint=None, xy0=None, thresh=0, peaks=None):
110 """Create a `MultibandFootprint` from an `image`, `mask`, `variance`
115 List of filter names.
118 Only pixels above the `thresh` value for at least one band
119 will be included
in the `SpanSet`
and resulting footprints.
121 Mask
for the `image` array.
123 Variance of the `image` array.
124 footprint : `Footprint`
125 `Footprint` that contains the `SpanSet`
and `PeakCatalog`
126 to use
for the `HeavyFootprint`
in each band.
127 If `footprint`
is `
None` then the `thresh`
is used to create a
128 `Footprint` based on the pixels above the `thresh` value.
130 If `image`
is an array
and `footprint`
is `
None` then specifying
131 `xy0` gives the location of the minimum `x`
and `y` value of the
133 thresh : `float`
or list of floats
134 Threshold
in each band (
or the same threshold to be used
in all bands)
135 to include a pixel
in the `SpanSet` of the `MultibandFootprint`.
136 If `Footprint`
is not `
None` then `thresh`
is ignored.
137 peaks : `PeakCatalog`
138 Catalog containing information about the peaks located
in the
143 result : `MultibandFootprint`
144 MultibandFootprint created
from the arrays
147 if footprint
is None:
151 imageBBox = footprint.getBBox()
153 if peaks
is not None:
154 footprint.setPeakCatalog(peaks)
155 mMaskedImage = MultibandMaskedImage.fromArrays(filters, image, mask, variance, imageBBox)
156 singles = [
makeHeavyFootprint(footprint, maskedImage)
for maskedImage
in mMaskedImage]
160 def fromImages(filters, image, mask=None, variance=None, footprint=None, thresh=0, peaks=None):
161 """Create a `MultibandFootprint` from an `image`, `mask`, `variance`
166 List of filter names.
169 to convert into `HeavyFootprint` objects.
170 Only pixels above the `thresh` value
for at least one band
171 will be included
in the `SpanSet`
and resulting footprints.
172 mask : `MultibandMask`
or list of `Mask`
173 Mask
for the `image`.
175 Variance of the `image`.
176 thresh : `float`
or `list` of floats
177 Threshold
in each band (
or the same threshold to be used
in all bands)
178 to include a pixel
in the `SpanSet` of the `MultibandFootprint`.
179 If `Footprint`
is not `
None` then `thresh`
is ignored.
180 peaks : `PeakCatalog`
181 Catalog containing information about the peaks located
in the
186 result : `MultibandFootprint`
187 MultibandFootprint created
from the image, mask,
and variance
190 if footprint
is None:
194 if peaks
is not None:
195 footprint.setPeakCatalog(peaks)
197 singles = [
makeHeavyFootprint(footprint, maskedImage)
for maskedImage
in mMaskedImage]
202 """Create a `MultibandFootprint` from a list of `MaskedImage`
204 See `fromImages` for a description of the parameters
not listed below
209 MaskedImages to extract the single band heavy footprints
from.
210 Like `fromImages`,
if a `footprint`
is not specified then all
211 pixels above `thresh` will be used,
and `peaks` will be added
212 to the `PeakCatalog`.
216 result : `MultibandFootprint`
217 MultibandFootprint created
from the image, mask,
and variance
219 image = [maskedImage.image for maskedImage
in maskedImages]
220 mask = [maskedImage.mask
for maskedImage
in maskedImages]
221 variance = [maskedImage.variance
for maskedImage
in maskedImages]
222 return MultibandFootprint.fromImages(filters, image, mask, variance, footprint, thresh, peaks)
225 """Get the full `SpanSet`"""
230 """Common SpanSet and peak catalog for the single band footprints"""
235 """MultibandMaskedImage that the footprints present a view into"""
236 return self._mMaskedImage
240 """`SpanSet` of the `MultibandFootprint`"""
244 """Get the `PeakCatalog`"""
249 """`PeakCatalog` of the `MultibandFootprint`"""
252 def _slice(self, filters, filterIndex, indices):
253 """Slice the current object and return the result
255 `MultibandFootprint` objects cannot be sliced along the image
256 dimension, so an error is thrown
if `indices` has any elements.
258 See `Multiband._slice`
for a list of the parameters.
261 raise IndexError(
"MultibandFootprints can only be sliced in the filter dimension")
263 if isinstance(filterIndex, slice):
264 singles = self.
singles[filterIndex]
266 singles = [self.
singles[idx]
for idx
in filterIndex]
270 def getImage(self, bbox=None, fill=np.nan, imageType=MultibandMaskedImage):
271 """Convert a `MultibandFootprint` to a `MultibandImage`
273 This returns the heavy footprints converted into an `MultibandImage` or
274 `MultibandMaskedImage` (depending on `imageType`).
275 This might be different than the internal `mMaskedImage` property
276 of the `MultibandFootprint`,
as the `mMaskedImage` might contain
277 some non-zero pixels
not contained
in the footprint but present
in
283 Bounding box of the resulting image.
284 If no bounding box
is specified, then the bounding box
285 of the footprint
is used.
287 Value to use
for any pixel
in the resulting image
288 outside of the `SpanSet`.
290 This should be either a `MultibandMaskedImage`
291 or `MultibandImage`
and describes the type of the output image.
295 result : `MultibandBase`
296 The resulting `MultibandImage`
or `MultibandMaskedImage` created
297 from the `MultibandHeavyFootprint`.
299 if imageType == MultibandMaskedImage:
300 singleType = MaskedImage
301 elif imageType == MultibandImage:
304 raise TypeError(
"Expected imageType to be either MultibandImage or MultibandMaskedImage")
305 maskedImages = [heavy.extractImage(fill, bbox, singleType)
for heavy
in self.
singles]
306 mMaskedImage = imageType.fromImages(self.
filters, maskedImages)
310 """Copy the current object
315 Whether or not to make a deep copy
319 result : `MultibandFootprint`
320 The cloned footprint.
325 footprint.addPeak(peak.getX(), peak.getY(), peak.getValue())
327 filters = tuple([f
for f
in self.
filters])
328 result = MultibandFootprint.fromMaskedImages(filters, mMaskedImage, footprint)
A compact representation of a collection of pixels.
A class to represent a 2-dimensional array of pixels.
A class to manipulate images, masks, and variance as a single object.
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