22 __all__ = [
"MultibandFootprint"]
28 from lsst.afw.image import Mask, Image, MaskedImage, MultibandImage, MultibandMaskedImage
30 from .
import Footprint, makeHeavyFootprint
34 """Create a Footprint from a set of Images 38 images: `MultibandImage` or list of `Image`, array 39 Images to extract the footprint from 41 All pixels above `thresh` will be included in the footprint 43 Location of the minimum value of the images bounding box 44 (if images is an array, otherwise the image bounding box is used). 49 Union of all spans in the images above the threshold 51 Bounding box for the input images. 54 if not hasattr(thresh,
"__len__"):
55 thresh = [thresh] * len(images)
59 if isinstance(images, MultibandBase)
or isinstance(images[0], Image):
61 for n, image
in enumerate(images):
62 mask = image.array > thresh[n]
63 mask =
Mask(mask.astype(np.int32), xy0=image.getBBox().getMin())
64 spans = spans.union(SpanSet.fromMask(mask))
65 imageBBox = images[0].getBBox()
68 thresh = np.array(thresh)
71 mask = np.any(images > thresh[:,
None,
None], axis=0)
72 mask =
Mask(mask.astype(np.int32), xy0=xy0)
73 spans = SpanSet.fromMask(mask)
74 imageBBox = mask.getBBox()
75 return spans, imageBBox
79 """Create an image of a HeavyFootprint 83 heavy: `HeavyFootprint` 84 The HeavyFootprint to insert into the image 86 Number to fill the pixels in the image that are not 89 Bounding box of the output image. 91 This should be either a `MaskedImage` or `Image` and describes 92 the type of the output image. 96 image: `MaskedImage` or `Image` 97 An image defined by `bbox` and padded with `fill` that 98 contains the projected flux in `heavy`. 101 bbox = heavy.getBBox()
102 image = imageType(bbox, dtype=heavy.getImageArray().dtype)
109 """Multiband Footprint class 111 A `MultibandFootprint` is a collection of HeavyFootprints that have 112 the same `SpanSet` and `peakCatalog` but different flux in each band. 117 List of filter names. 119 A list of single band `HeavyFootprint` objects. 120 Each `HeavyFootprint` should have the same `PeakCatalog` 121 and the same `SpanSet`, however to save CPU cycles there 122 is no internal check for consistency of the peak catalog. 128 if not all([heavy.getSpans() == spans
for heavy
in singles]):
129 raise ValueError(
"All HeavyFootprints in singles are expected to have the same SpanSet")
133 footprint.setPeakCatalog(singles[0].
getPeaks())
137 def fromArrays(filters, image, mask=None, variance=None, footprint=None, xy0=None, thresh=0, peaks=None):
138 """Create a `MultibandFootprint` from an `image`, `mask`, `variance` 143 List of filter names. 145 An array to convert into `HeavyFootprint` objects. 146 Only pixels above the `thresh` value for at least one band 147 will be included in the `SpanSet` and resulting footprints. 149 Mask for the `image` array. 151 Variance of the `image` array. 152 footprint: `Footprint` 153 `Footprint` that contains the `SpanSet` and `PeakCatalog` 154 to use for the `HeavyFootprint` in each band. 155 If `footprint` is `None` then the `thresh` is used to create a 156 `Footprint` based on the pixels above the `thresh` value. 158 If `image` is an array and `footprint` is `None` then specifying 159 `xy0` gives the location of the minimum `x` and `y` value of the 161 thresh: float or list of floats 162 Threshold in each band (or the same threshold to be used in all bands) 163 to include a pixel in the `SpanSet` of the `MultibandFootprint`. 164 If `Footprint` is not `None` then `thresh` is ignored. 166 Catalog containing information about the peaks located in the 171 result: `MultibandFootprint` 172 MultibandFootprint created from the arrays 175 if footprint
is None:
179 imageBBox = footprint.getBBox()
181 if peaks
is not None:
182 footprint.setPeakCatalog(peaks)
183 mMaskedImage = MultibandMaskedImage.fromArrays(filters, image, mask, variance, imageBBox)
184 singles = [
makeHeavyFootprint(footprint, maskedImage)
for maskedImage
in mMaskedImage]
188 def fromImages(filters, image, mask=None, variance=None, footprint=None, thresh=0, peaks=None):
189 """Create a `MultibandFootprint` from an `image`, `mask`, `variance` 194 List of filter names. 195 image: `MultibandImage`, or list of `Image` 196 A `MultibandImage` (or collection of images in each band) 197 to convert into `HeavyFootprint` objects. 198 Only pixels above the `thresh` value for at least one band 199 will be included in the `SpanSet` and resulting footprints. 200 mask: `MultibandMask` or list of `Mask` 201 Mask for the `image`. 202 variance: `MultibandImage`, or list of `Image` 203 Variance of the `image`. 204 thresh: `float` or `list` of floats 205 Threshold in each band (or the same threshold to be used in all bands) 206 to include a pixel in the `SpanSet` of the `MultibandFootprint`. 207 If `Footprint` is not `None` then `thresh` is ignored. 209 Catalog containing information about the peaks located in the 214 result: `MultibandFootprint` 215 MultibandFootprint created from the image, mask, and variance 218 if footprint
is None:
222 if peaks
is not None:
223 footprint.setPeakCatalog(peaks)
225 singles = [
makeHeavyFootprint(footprint, maskedImage)
for maskedImage
in mMaskedImage]
230 """Create a `MultibandFootprint` from a list of `MaskedImage` 232 See `fromImages` for a description of the parameters not listed below 236 maskedImages: `list` of `MaskedImage` 237 MaskedImages to extract the single band heavy footprints from. 238 Like `fromImage`, if a `footprint` is not specified then all 239 pixels above `thresh` will be used, and `peaks` will be added 240 to the `PeakCatalog`. 244 result: `MultibandFootprint` 245 MultibandFootprint created from the image, mask, and variance 247 image = [maskedImage.image
for maskedImage
in maskedImages]
248 mask = [maskedImage.mask
for maskedImage
in maskedImages]
249 variance = [maskedImage.variance
for maskedImage
in maskedImages]
250 return MultibandFootprint.fromImages(filters, image, mask, variance, footprint, thresh, peaks)
253 """Get the full `SpanSet`""" 258 """Common SpanSet and peak catalog for the single band footprints""" 263 """MultibandMaskedImage that the footprints present a view into""" 264 return self._mMaskedImage
268 """`SpanSet` of the `MultibandFootprint`""" 272 """Get the `PeakCatalog`""" 277 """`PeakCatalog` of the `MultibandFootprint`""" 280 def _slice(self, filters, filterIndex, indices):
281 """Slice the current object and return the result 283 `MultibandFootprint` objects cannot be sliced along the image 284 dimension, so an error is thrown if `indices` has any elements. 286 See `Multiband._slice` for a list of the parameters. 289 raise IndexError(
"MultibandFootprints can only be sliced in the filter dimension")
291 if isinstance(filterIndex, slice):
292 singles = self.
singles[filterIndex]
294 singles = [self.
singles[idx]
for idx
in filterIndex]
298 def getImage(self, bbox=None, fill=np.nan, imageType=MultibandMaskedImage):
299 """Convert a `MultibandFootprint` to a `MultibandImage` 301 This returns the heavy footprints converted into an `MultibandImage` or 302 `MultibandMaskedImage` (depending on `imageType`). 303 This might be different than the internal `mMaskedImage` property 304 of the `MultibandFootprint`, as the `mMaskedImage` might contain 305 some non-zero pixels not contained in the footprint but present in 311 Bounding box of the resulting image. 312 If no bounding box is specified, then the bounding box 313 of the footprint is used. 315 Value to use for any pixel in the resulting image 316 outside of the `SpanSet`. 318 This should be either a `MultibandMaskedImage` 319 or `MultibandImage` and describes the type of the output image. 323 result: `MultibandBase` 324 The resulting `MultibandImage` or `MultibandMaskedImage` created 325 from the `MultibandHeavyFootprint`. 327 if imageType == MultibandMaskedImage:
328 singleType = MaskedImage
329 elif imageType == MultibandImage:
332 raise TypeError(
"Expected imageType to be either MultibandImage or MultibandMaskedImage")
334 mMaskedImage = imageType.fromImages(self.
filters, maskedImages)
338 """Copy the current object 343 Whether or not to make a deep copy 347 result: `MultibandFootprint` 348 The cloned footprint. 353 footprint.addPeak(peak.getX(), peak.getY(), peak.getValue())
355 filters = tuple([f
for f
in self.
filters])
356 result = MultibandFootprint.fromMaskedImages(filters, mMaskedImage, footprint)
def heavyFootprintToImage(heavy, fill=np.nan, bbox=None, imageType=MaskedImage)
def getSpanSetFromImages(images, thresh=0, xy0=None)
A compact representation of a collection of pixels.
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.
Represent a 2-dimensional array of bitmask pixels.
lsst::afw::detection::Footprint Footprint
HeavyFootprint< ImagePixelT, MaskPixelT, VariancePixelT > makeHeavyFootprint(Footprint const &foot, lsst::afw::image::MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > const &img, HeavyFootprintCtrl const *ctrl=NULL)
Create a HeavyFootprint with footprint defined by the given Footprint and pixel values from the given...