24__all__ = (
"SourceDetectionConfig",
"SourceDetectionTask",
"addExposures")
26from contextlib
import contextmanager
38import lsst.pipe.base
as pipeBase
39from .subtractBackground
import SubtractBackgroundTask
43 """Configuration parameters for the SourceDetectionTask
45 minPixels = pexConfig.RangeField(
46 doc="detected sources with fewer than the specified number of pixels will be ignored",
47 dtype=int, optional=
False, default=1, min=0,
49 isotropicGrow = pexConfig.Field(
50 doc=
"Pixels should be grown as isotropically as possible (slower)",
51 dtype=bool, optional=
False, default=
False,
53 combinedGrow = pexConfig.Field(
54 doc=
"Grow all footprints at the same time? This allows disconnected footprints to merge.",
55 dtype=bool, default=
True,
57 nSigmaToGrow = pexConfig.Field(
58 doc=
"Grow detections by nSigmaToGrow * [PSF RMS width]; if 0 then do not grow",
59 dtype=float, default=2.4,
61 returnOriginalFootprints = pexConfig.Field(
62 doc=
"Grow detections to set the image mask bits, but return the original (not-grown) footprints",
63 dtype=bool, optional=
False, default=
False,
65 thresholdValue = pexConfig.RangeField(
66 doc=
"Threshold for footprints; exact meaning and units depend on thresholdType.",
67 dtype=float, optional=
False, default=5.0, min=0.0,
69 includeThresholdMultiplier = pexConfig.RangeField(
70 doc=
"Include threshold relative to thresholdValue",
71 dtype=float, default=1.0, min=0.0,
73 thresholdType = pexConfig.ChoiceField(
74 doc=
"specifies the desired flavor of Threshold",
75 dtype=str, optional=
False, default=
"stdev",
77 "variance":
"threshold applied to image variance",
78 "stdev":
"threshold applied to image std deviation",
79 "value":
"threshold applied to image value",
80 "pixel_stdev":
"threshold applied to per-pixel std deviation",
83 thresholdPolarity = pexConfig.ChoiceField(
84 doc=
"specifies whether to detect positive, or negative sources, or both",
85 dtype=str, optional=
False, default=
"positive",
87 "positive":
"detect only positive sources",
88 "negative":
"detect only negative sources",
89 "both":
"detect both positive and negative sources",
92 adjustBackground = pexConfig.Field(
94 doc=
"Fiddle factor to add to the background; debugging only",
97 reEstimateBackground = pexConfig.Field(
99 doc=
"Estimate the background again after final source detection?",
100 default=
True, optional=
False,
102 background = pexConfig.ConfigurableField(
103 doc=
"Background re-estimation; ignored if reEstimateBackground false",
104 target=SubtractBackgroundTask,
106 tempLocalBackground = pexConfig.ConfigurableField(
107 doc=(
"A local (small-scale), temporary background estimation step run between "
108 "detecting above-threshold regions and detecting the peaks within "
109 "them; used to avoid detecting spuerious peaks in the wings."),
110 target=SubtractBackgroundTask,
112 doTempLocalBackground = pexConfig.Field(
114 doc=
"Enable temporary local background subtraction? (see tempLocalBackground)",
117 tempWideBackground = pexConfig.ConfigurableField(
118 doc=(
"A wide (large-scale) background estimation and removal before footprint and peak detection. "
119 "It is added back into the image after detection. The purpose is to suppress very large "
120 "footprints (e.g., from large artifacts) that the deblender may choke on."),
121 target=SubtractBackgroundTask,
123 doTempWideBackground = pexConfig.Field(
125 doc=
"Do temporary wide (large-scale) background subtraction before footprint detection?",
128 nPeaksMaxSimple = pexConfig.Field(
130 doc=(
"The maximum number of peaks in a Footprint before trying to "
131 "replace its peaks using the temporary local background"),
134 nSigmaForKernel = pexConfig.Field(
136 doc=(
"Multiple of PSF RMS size to use for convolution kernel bounding box size; "
137 "note that this is not a half-size. The size will be rounded up to the nearest odd integer"),
140 statsMask = pexConfig.ListField(
142 doc=
"Mask planes to ignore when calculating statistics of image (for thresholdType=stdev)",
143 default=[
'BAD',
'SAT',
'EDGE',
'NO_DATA'],
156 for maskPlane
in (
"DETECTED",
"DETECTED_NEGATIVE"):
162 """Create the detection task. Most arguments are simply passed onto pipe.base.Task.
169 Keyword arguments passed to `lsst.pipe.base.task.Task.__init__`
171 If schema is not None and configured
for 'both' detections,
172 a
'flags.negative' field will be added to label detections made
with a
177 This task can add fields to the schema, so any code calling this task must ensure that
178 these columns are indeed present
in the input match list.
181 ConfigClass = SourceDetectionConfig
182 _DefaultName = "sourceDetection"
185 pipeBase.Task.__init__(self, **kwds)
186 if schema
is not None and self.config.thresholdPolarity ==
"both":
188 "flags_negative", type=
"Flag",
189 doc=
"set if source was detected as significantly negative"
192 if self.config.thresholdPolarity ==
"both":
193 self.log.warning(
"Detection polarity set to 'both', but no flag will be "
194 "set to distinguish between positive and negative detections")
196 if self.config.reEstimateBackground:
197 self.makeSubtask(
"background")
198 if self.config.doTempLocalBackground:
199 self.makeSubtask(
"tempLocalBackground")
200 if self.config.doTempWideBackground:
201 self.makeSubtask(
"tempWideBackground")
204 def run(self, table, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None):
205 """Run source detection and create a SourceCatalog of detections.
210 Table object that will be used to create the SourceCatalog.
212 Exposure to process; DETECTED mask plane will be set in-place.
214 If
True, smooth the image before detection using a Gaussian of width
215 ``sigma``,
or the measured PSF width. Set to
False when running on
216 e.g. a pre-convolved image,
or a mask plane.
218 Sigma of PSF (pixels); used
for smoothing
and to grow detections;
219 if None then measure the sigma of the PSF of the exposure
221 Clear DETECTED{,_NEGATIVE} planes before running detection.
223 Exposure identifier; unused by this implementation, but used
for
224 RNG seed by subclasses.
228 result : `lsst.pipe.base.Struct`
232 The result resturned by `detectFootprints`
233 (`lsst.pipe.base.Struct`).
238 If flags.negative
is needed, but isn
't in table's schema.
239 lsst.pipe.base.TaskError
240 If sigma=
None, doSmooth=
True and the exposure has no PSF.
244 If you want to avoid dealing
with Sources
and Tables, you can use
248 raise ValueError(
"Table has incorrect Schema")
249 results = self.
detectFootprints(exposure=exposure, doSmooth=doSmooth, sigma=sigma,
250 clearMask=clearMask, expId=expId)
251 sources = afwTable.SourceCatalog(table)
252 sources.reserve(results.numPos + results.numNeg)
254 results.negative.makeSources(sources)
256 for record
in sources:
259 results.positive.makeSources(sources)
260 results.fpSets = results.copy()
261 results.sources = sources
264 def display(self, exposure, results, convolvedImage=None):
265 """Display detections if so configured
267 Displays the ``exposure`` in frame 0, overlays the detection peaks.
269 Requires that ``lsstDebug`` has been set up correctly, so that
270 ``
lsstDebug.Info(
"lsst.meas.algorithms.detection")`` evaluates `
True`.
272 If the ``convolvedImage``
is non-`
None`
and
274 ``convolvedImage`` will be displayed
in frame 1.
279 Exposure to display, on which will be plotted the detections.
280 results : `lsst.pipe.base.Struct`
281 Results of the
'detectFootprints' method, containing positive
and
282 negative footprints (which contain the peak positions that we will
283 plot). This
is a `Struct`
with ``positive``
and ``negative``
286 Convolved image used
for thresholding.
299 afwDisplay.setDefaultMaskTransparency(75)
301 disp0 = afwDisplay.Display(frame=0)
302 disp0.mtv(exposure, title=
"detection")
304 def plotPeaks(fps, ctype):
307 with disp0.Buffering():
308 for fp
in fps.getFootprints():
309 for pp
in fp.getPeaks():
310 disp0.dot(
"+", pp.getFx(), pp.getFy(), ctype=ctype)
311 plotPeaks(results.positive,
"yellow")
312 plotPeaks(results.negative,
"red")
314 if convolvedImage
and display > 1:
315 disp1 = afwDisplay.Display(frame=1)
316 disp1.mtv(convolvedImage, title=
"PSF smoothed")
319 """Apply a temporary local background subtraction
321 This temporary local background serves to suppress noise fluctuations
322 in the wings of bright objects.
324 Peaks
in the footprints will be updated.
329 Exposure
for which to fit local background.
331 Convolved image on which detection will be performed
332 (typically smaller than ``exposure`` because the
333 half-kernel has been removed around the edges).
334 results : `lsst.pipe.base.Struct`
335 Results of the
'detectFootprints' method, containing positive
and
336 negative footprints (which contain the peak positions that we will
337 plot). This
is a `Struct`
with ``positive``
and ``negative``
343 bg = self.tempLocalBackground.fitBackground(exposure.getMaskedImage())
344 bgImage = bg.getImageF(self.tempLocalBackground.config.algorithm,
345 self.tempLocalBackground.config.undersampleStyle)
346 middle -= bgImage.Factory(bgImage, middle.getBBox())
349 if self.config.thresholdPolarity !=
"negative":
350 self.
updatePeaks(results.positive, middle, thresholdPos)
351 if self.config.thresholdPolarity !=
"positive":
352 self.
updatePeaks(results.negative, middle, thresholdNeg)
355 """Clear the DETECTED and DETECTED_NEGATIVE mask planes
357 Removes any previous detection mask in preparation
for a new
365 mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask(
"DETECTED_NEGATIVE"))
368 """Calculate size of smoothing kernel
370 Uses the ``nSigmaForKernel`` configuration parameter. Note
371 that that is the full width of the kernel bounding box
372 (so a value of 7 means 3.5 sigma on either side of center).
373 The value will be rounded up to the nearest odd integer.
378 Gaussian sigma of smoothing kernel.
383 Size of the smoothing kernel.
385 return (int(sigma * self.config.nSigmaForKernel + 0.5)//2)*2 + 1
388 """Retrieve the PSF for an exposure
390 If ``sigma`` is provided, we make a ``GaussianPsf``
with that,
391 otherwise use the one
from the ``exposure``.
396 Exposure
from which to retrieve the PSF.
397 sigma : `float`, optional
398 Gaussian sigma to use
if provided.
403 PSF to use
for detection.
406 psf = exposure.getPsf()
408 raise RuntimeError(
"Unable to determine PSF to use for detection: no sigma provided")
409 sigma = psf.computeShape().getDeterminantRadius()
411 psf = afwDet.GaussianPsf(size, size, sigma)
415 """Convolve the image with the PSF
417 We convolve the image with a Gaussian approximation to the PSF,
418 because this
is separable
and therefore fast. It
's technically a
419 correlation rather than a convolution, but since we use a symmetric
420 Gaussian there's no difference.
422 The convolution can be disabled with ``doSmooth=
False``. If we do
423 convolve, we mask the edges
as ``EDGE``
and return the convolved image
424 with the edges removed. This
is because we can
't convolve the edges
425 because the kernel would extend off the image.
432 PSF to convolve with (actually
with a Gaussian approximation
435 Actually do the convolution? Set to
False when running on
436 e.g. a pre-convolved image,
or a mask plane.
438 Return Struct contents
439 ----------------------
441 Convolved image, without the edges.
443 Gaussian sigma used
for the convolution.
445 self.metadata.set("doSmooth", doSmooth)
446 sigma = psf.computeShape().getDeterminantRadius()
447 self.metadata.set(
"sigma", sigma)
450 middle = maskedImage.Factory(maskedImage, deep=
True)
451 return pipeBase.Struct(middle=middle, sigma=sigma)
456 self.metadata.set(
"smoothingKernelWidth", kWidth)
457 gaussFunc = afwMath.GaussianFunction1D(sigma)
458 gaussKernel = afwMath.SeparableKernel(kWidth, kWidth, gaussFunc, gaussFunc)
460 convolvedImage = maskedImage.Factory(maskedImage.getBBox())
462 afwMath.convolve(convolvedImage, maskedImage, gaussKernel, afwMath.ConvolutionControl())
466 goodBBox = gaussKernel.shrinkBBox(convolvedImage.getBBox())
467 middle = convolvedImage.Factory(convolvedImage, goodBBox, afwImage.PARENT,
False)
471 self.
setEdgeBits(maskedImage, goodBBox, maskedImage.getMask().getPlaneBitMask(
"EDGE"))
473 return pipeBase.Struct(middle=middle, sigma=sigma)
476 """Apply thresholds to the convolved image
478 Identifies ``Footprint``s, both positive and negative.
480 The threshold can be modified by the provided multiplication
486 Convolved image to threshold.
488 Bounding box of unconvolved image.
490 Multiplier
for the configured threshold.
492 Return Struct contents
493 ----------------------
495 Positive detection footprints,
if configured.
497 Negative detection footprints,
if configured.
499 Multiplier
for the configured threshold.
501 results = pipeBase.Struct(positive=None, negative=
None, factor=factor)
503 if self.config.reEstimateBackground
or self.config.thresholdPolarity !=
"negative":
504 threshold = self.
makeThreshold(middle,
"positive", factor=factor)
505 results.positive = afwDet.FootprintSet(
509 self.config.minPixels
511 results.positive.setRegion(bbox)
512 if self.config.reEstimateBackground
or self.config.thresholdPolarity !=
"positive":
513 threshold = self.
makeThreshold(middle,
"negative", factor=factor)
514 results.negative = afwDet.FootprintSet(
518 self.config.minPixels
520 results.negative.setRegion(bbox)
525 """Finalize the detected footprints
527 Grows the footprints, sets the ``DETECTED`` and ``DETECTED_NEGATIVE``
528 mask planes,
and logs the results.
530 ``numPos`` (number of positive footprints), ``numPosPeaks`` (number
531 of positive peaks), ``numNeg`` (number of negative footprints),
532 ``numNegPeaks`` (number of negative peaks) entries are added to the
538 Mask image on which to flag detected pixels.
539 results : `lsst.pipe.base.Struct`
540 Struct of detection results, including ``positive``
and
541 ``negative`` entries; modified.
543 Gaussian sigma of PSF.
545 Multiplier
for the configured threshold.
547 for polarity, maskName
in ((
"positive",
"DETECTED"), (
"negative",
"DETECTED_NEGATIVE")):
548 fpSet = getattr(results, polarity)
551 if self.config.nSigmaToGrow > 0:
552 nGrow = int((self.config.nSigmaToGrow * sigma) + 0.5)
553 self.metadata.set(
"nGrow", nGrow)
554 if self.config.combinedGrow:
555 fpSet = afwDet.FootprintSet(fpSet, nGrow, self.config.isotropicGrow)
557 stencil = (afwGeom.Stencil.CIRCLE
if self.config.isotropicGrow
else
558 afwGeom.Stencil.MANHATTAN)
560 fp.dilate(nGrow, stencil)
561 fpSet.setMask(mask, maskName)
562 if not self.config.returnOriginalFootprints:
563 setattr(results, polarity, fpSet)
566 results.numPosPeaks = 0
568 results.numNegPeaks = 0
572 if results.positive
is not None:
573 results.numPos = len(results.positive.getFootprints())
574 results.numPosPeaks = sum(len(fp.getPeaks())
for fp
in results.positive.getFootprints())
575 positive =
" %d positive peaks in %d footprints" % (results.numPosPeaks, results.numPos)
576 if results.negative
is not None:
577 results.numNeg = len(results.negative.getFootprints())
578 results.numNegPeaks = sum(len(fp.getPeaks())
for fp
in results.negative.getFootprints())
579 negative =
" %d negative peaks in %d footprints" % (results.numNegPeaks, results.numNeg)
581 self.log.info(
"Detected%s%s%s to %g %s",
582 positive,
" and" if positive
and negative
else "", negative,
583 self.config.thresholdValue*self.config.includeThresholdMultiplier*factor,
584 "DN" if self.config.thresholdType ==
"value" else "sigma")
587 """Estimate the background after detection
592 Image on which to estimate the background.
593 backgrounds : `lsst.afw.math.BackgroundList`
594 List of backgrounds; modified.
598 bg : `lsst.afw.math.backgroundMI`
599 Empirical background model.
601 bg = self.background.fitBackground(maskedImage)
602 if self.config.adjustBackground:
603 self.log.warning(
"Fiddling the background by %g", self.config.adjustBackground)
604 bg += self.config.adjustBackground
605 self.log.info(
"Resubtracting the background after object detection")
606 maskedImage -= bg.getImageF(self.background.config.algorithm,
607 self.background.config.undersampleStyle)
609 actrl = bg.getBackgroundControl().getApproximateControl()
610 backgrounds.append((bg, getattr(afwMath.Interpolate, self.background.config.algorithm),
611 bg.getAsUsedUndersampleStyle(), actrl.getStyle(), actrl.getOrderX(),
612 actrl.getOrderY(), actrl.getWeighting()))
616 """Clear unwanted results from the Struct of results
618 If we specifically want only positive or only negative detections,
619 drop the ones we don
't want, and its associated mask plane.
625 results : `lsst.pipe.base.Struct`
626 Detection results, with ``positive``
and ``negative`` elements;
629 if self.config.thresholdPolarity ==
"positive":
630 if self.config.reEstimateBackground:
631 mask &= ~mask.getPlaneBitMask(
"DETECTED_NEGATIVE")
632 results.negative =
None
633 elif self.config.thresholdPolarity ==
"negative":
634 if self.config.reEstimateBackground:
635 mask &= ~mask.getPlaneBitMask(
"DETECTED")
636 results.positive =
None
639 def detectFootprints(self, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None):
640 """Detect footprints on an exposure.
645 Exposure to process; DETECTED{,_NEGATIVE} mask plane will be
647 doSmooth : `bool`, optional
648 If
True, smooth the image before detection using a Gaussian
649 of width ``sigma``,
or the measured PSF width of ``exposure``.
650 Set to
False when running on e.g. a pre-convolved image,
or a mask
652 sigma : `float`, optional
653 Gaussian Sigma of PSF (pixels); used
for smoothing
and to grow
654 detections;
if `
None` then measure the sigma of the PSF of the
656 clearMask : `bool`, optional
657 Clear both DETECTED
and DETECTED_NEGATIVE planes before running
659 expId : `dict`, optional
660 Exposure identifier; unused by this implementation, but used
for
661 RNG seed by subclasses.
663 Return Struct contents
664 ----------------------
666 Positive polarity footprints (may be `
None`)
668 Negative polarity footprints (may be `
None`)
670 Number of footprints
in positive
or 0
if detection polarity was
673 Number of footprints
in negative
or 0
if detection polarity was
675 background : `lsst.afw.math.BackgroundList`
676 Re-estimated background. `
None`
if
677 ``reEstimateBackground==
False``.
679 Multiplication factor applied to the configured detection
682 maskedImage = exposure.maskedImage
687 psf = self.
getPsf(exposure, sigma=sigma)
689 convolveResults = self.
convolveImage(maskedImage, psf, doSmooth=doSmooth)
690 middle = convolveResults.middle
691 sigma = convolveResults.sigma
694 results.background = afwMath.BackgroundList()
695 if self.config.doTempLocalBackground:
699 if self.config.reEstimateBackground:
703 self.
display(exposure, results, middle)
708 """Make an afw.detection.Threshold object corresponding to the task's
709 configuration and the statistics of the given image.
714 Image to measure noise statistics
from if needed.
715 thresholdParity: `str`
716 One of
"positive" or "negative", to set the kind of fluctuations
717 the Threshold will detect.
719 Factor by which to multiply the configured detection threshold.
720 This
is useful
for tweaking the detection threshold slightly.
727 parity = False if thresholdParity ==
"negative" else True
728 thresholdValue = self.config.thresholdValue
729 thresholdType = self.config.thresholdType
730 if self.config.thresholdType ==
'stdev':
731 bad = image.getMask().getPlaneBitMask(self.config.statsMask)
732 sctrl = afwMath.StatisticsControl()
733 sctrl.setAndMask(bad)
734 stats = afwMath.makeStatistics(image, afwMath.STDEVCLIP, sctrl)
735 thresholdValue *= stats.getValue(afwMath.STDEVCLIP)
736 thresholdType =
'value'
738 threshold = afwDet.createThreshold(thresholdValue*factor, thresholdType, parity)
739 threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier)
743 """Update the Peaks in a FootprintSet by detecting new Footprints and
744 Peaks in an image
and using the new Peaks instead of the old ones.
749 Set of Footprints whose Peaks should be updated.
751 Image to detect new Footprints
and Peak
in.
753 Threshold object
for detection.
755 Input Footprints
with fewer Peaks than self.config.nPeaksMaxSimple
756 are
not modified,
and if no new Peaks are detected
in an input
757 Footprint, the brightest original Peak
in that Footprint
is kept.
759 for footprint
in fpSet.getFootprints():
760 oldPeaks = footprint.getPeaks()
761 if len(oldPeaks) <= self.config.nPeaksMaxSimple:
766 sub = image.Factory(image, footprint.getBBox())
767 fpSetForPeaks = afwDet.FootprintSet(
771 self.config.minPixels
773 newPeaks = afwDet.PeakCatalog(oldPeaks.getTable())
774 for fpForPeaks
in fpSetForPeaks.getFootprints():
775 for peak
in fpForPeaks.getPeaks():
776 if footprint.contains(peak.getI()):
777 newPeaks.append(peak)
778 if len(newPeaks) > 0:
780 oldPeaks.extend(newPeaks)
786 """Set the edgeBitmask bits for all of maskedImage outside goodBBox
791 Image on which to set edge bits in the mask.
793 Bounding box of good pixels,
in ``LOCAL`` coordinates.
795 Bit mask to OR
with the existing mask bits
in the region
796 outside ``goodBBox``.
798 msk = maskedImage.getMask()
800 mx0, my0 = maskedImage.getXY0()
801 for x0, y0, w, h
in ([0, 0,
802 msk.getWidth(), goodBBox.getBeginY() - my0],
803 [0, goodBBox.getEndY() - my0, msk.getWidth(),
804 maskedImage.getHeight() - (goodBBox.getEndY() - my0)],
806 goodBBox.getBeginX() - mx0, msk.getHeight()],
807 [goodBBox.getEndX() - mx0, 0,
808 maskedImage.getWidth() - (goodBBox.getEndX() - mx0), msk.getHeight()],
812 edgeMask |= edgeBitmask
816 """Context manager for removing wide (large-scale) background
818 Removing a wide (large-scale) background helps to suppress the
819 detection of large footprints that may overwhelm the deblender.
820 It does, however, set a limit on the maximum scale of objects.
822 The background that we remove will be restored upon exit from
828 Exposure on which to remove large-scale background.
832 context : context manager
833 Context manager that will ensure the temporary wide background
836 doTempWideBackground = self.config.doTempWideBackground
837 if doTempWideBackground:
838 self.log.info(
"Applying temporary wide background subtraction")
839 original = exposure.maskedImage.image.array[:].copy()
840 self.tempWideBackground.
run(exposure).background
843 image = exposure.maskedImage.image
844 mask = exposure.maskedImage.mask
845 noData = mask.array & mask.getPlaneBitMask(
"NO_DATA") > 0
846 isGood = mask.array & mask.getPlaneBitMask(self.config.statsMask) == 0
847 image.array[noData] = np.median(image.array[~noData & isGood])
851 if doTempWideBackground:
852 exposure.maskedImage.image.array[:] = original
856 """Add a set of exposures together.
861 Sequence of exposures to add.
866 An exposure of the same size as each exposure
in ``exposureList``,
867 with the metadata
from ``exposureList[0]``
and a masked image equal
868 to the sum of all the exposure
's masked images.
870 exposure0 = exposureList[0]
871 image0 = exposure0.getMaskedImage()
873 addedImage = image0.Factory(image0, True)
874 addedImage.setXY0(image0.getXY0())
876 for exposure
in exposureList[1:]:
877 image = exposure.getMaskedImage()
880 addedExposure = exposure0.Factory(addedImage, exposure0.getWcs())
def tempWideBackgroundContext(self, exposure)
def getPsf(self, exposure, sigma=None)
def __init__(self, schema=None, **kwds)
def makeThreshold(self, image, thresholdParity, factor=1.0)
def run(self, table, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None)
def convolveImage(self, maskedImage, psf, doSmooth=True)
def applyTempLocalBackground(self, exposure, middle, results)
def detectFootprints(self, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None)
def reEstimateBackground(self, maskedImage, backgrounds)
def updatePeaks(self, fpSet, image, threshold)
def finalizeFootprints(self, mask, results, sigma, factor=1.0)
def setEdgeBits(maskedImage, goodBBox, edgeBitmask)
def clearUnwantedResults(self, mask, results)
def clearMask(self, mask)
def display(self, exposure, results, convolvedImage=None)
def applyThreshold(self, middle, bbox, factor=1.0)
def calculateKernelSize(self, sigma)
def addExposures(exposureList)