24__all__ = (
"SourceDetectionConfig",
"SourceDetectionTask",
"addExposures")
26from contextlib
import contextmanager
38import lsst.pipe.base
as pipeBase
39from lsst.utils.timer
import timeMethod
40from .subtractBackground
import SubtractBackgroundTask
44 """Configuration parameters for the SourceDetectionTask
46 minPixels = pexConfig.RangeField(
47 doc="detected sources with fewer than the specified number of pixels will be ignored",
48 dtype=int, optional=
False, default=1, min=0,
50 isotropicGrow = pexConfig.Field(
51 doc=
"Pixels should be grown as isotropically as possible (slower)",
52 dtype=bool, optional=
False, default=
False,
54 combinedGrow = pexConfig.Field(
55 doc=
"Grow all footprints at the same time? This allows disconnected footprints to merge.",
56 dtype=bool, default=
True,
58 nSigmaToGrow = pexConfig.Field(
59 doc=
"Grow detections by nSigmaToGrow * [PSF RMS width]; if 0 then do not grow",
60 dtype=float, default=2.4,
62 returnOriginalFootprints = pexConfig.Field(
63 doc=
"Grow detections to set the image mask bits, but return the original (not-grown) footprints",
64 dtype=bool, optional=
False, default=
False,
66 thresholdValue = pexConfig.RangeField(
67 doc=
"Threshold for footprints; exact meaning and units depend on thresholdType.",
68 dtype=float, optional=
False, default=5.0, min=0.0,
70 includeThresholdMultiplier = pexConfig.RangeField(
71 doc=
"Include threshold relative to thresholdValue",
72 dtype=float, default=1.0, min=0.0,
74 thresholdType = pexConfig.ChoiceField(
75 doc=
"specifies the desired flavor of Threshold",
76 dtype=str, optional=
False, default=
"stdev",
78 "variance":
"threshold applied to image variance",
79 "stdev":
"threshold applied to image std deviation",
80 "value":
"threshold applied to image value",
81 "pixel_stdev":
"threshold applied to per-pixel std deviation",
84 thresholdPolarity = pexConfig.ChoiceField(
85 doc=
"specifies whether to detect positive, or negative sources, or both",
86 dtype=str, optional=
False, default=
"positive",
88 "positive":
"detect only positive sources",
89 "negative":
"detect only negative sources",
90 "both":
"detect both positive and negative sources",
93 adjustBackground = pexConfig.Field(
95 doc=
"Fiddle factor to add to the background; debugging only",
98 reEstimateBackground = pexConfig.Field(
100 doc=
"Estimate the background again after final source detection?",
101 default=
True, optional=
False,
103 background = pexConfig.ConfigurableField(
104 doc=
"Background re-estimation; ignored if reEstimateBackground false",
105 target=SubtractBackgroundTask,
107 tempLocalBackground = pexConfig.ConfigurableField(
108 doc=(
"A local (small-scale), temporary background estimation step run between "
109 "detecting above-threshold regions and detecting the peaks within "
110 "them; used to avoid detecting spuerious peaks in the wings."),
111 target=SubtractBackgroundTask,
113 doTempLocalBackground = pexConfig.Field(
115 doc=
"Enable temporary local background subtraction? (see tempLocalBackground)",
118 tempWideBackground = pexConfig.ConfigurableField(
119 doc=(
"A wide (large-scale) background estimation and removal before footprint and peak detection. "
120 "It is added back into the image after detection. The purpose is to suppress very large "
121 "footprints (e.g., from large artifacts) that the deblender may choke on."),
122 target=SubtractBackgroundTask,
124 doTempWideBackground = pexConfig.Field(
126 doc=
"Do temporary wide (large-scale) background subtraction before footprint detection?",
129 nPeaksMaxSimple = pexConfig.Field(
131 doc=(
"The maximum number of peaks in a Footprint before trying to "
132 "replace its peaks using the temporary local background"),
135 nSigmaForKernel = pexConfig.Field(
137 doc=(
"Multiple of PSF RMS size to use for convolution kernel bounding box size; "
138 "note that this is not a half-size. The size will be rounded up to the nearest odd integer"),
141 statsMask = pexConfig.ListField(
143 doc=
"Mask planes to ignore when calculating statistics of image (for thresholdType=stdev)",
144 default=[
'BAD',
'SAT',
'EDGE',
'NO_DATA'],
157 for maskPlane
in (
"DETECTED",
"DETECTED_NEGATIVE"):
163 """Create the detection task. Most arguments are simply passed onto pipe.base.Task.
170 Keyword arguments passed to `lsst.pipe.base.task.Task.__init__`
172 If schema is not None and configured
for 'both' detections,
173 a
'flags.negative' field will be added to label detections made
with a
178 This task can add fields to the schema, so any code calling this task must ensure that
179 these columns are indeed present
in the input match list.
182 ConfigClass = SourceDetectionConfig
183 _DefaultName = "sourceDetection"
186 pipeBase.Task.__init__(self, **kwds)
187 if schema
is not None and self.config.thresholdPolarity ==
"both":
189 "flags_negative", type=
"Flag",
190 doc=
"set if source was detected as significantly negative"
193 if self.config.thresholdPolarity ==
"both":
194 self.log.warning(
"Detection polarity set to 'both', but no flag will be "
195 "set to distinguish between positive and negative detections")
197 if self.config.reEstimateBackground:
198 self.makeSubtask(
"background")
199 if self.config.doTempLocalBackground:
200 self.makeSubtask(
"tempLocalBackground")
201 if self.config.doTempWideBackground:
202 self.makeSubtask(
"tempWideBackground")
205 def run(self, table, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None):
206 """Run source detection and create a SourceCatalog of detections.
211 Table object that will be used to create the SourceCatalog.
213 Exposure to process; DETECTED mask plane will be set in-place.
215 If
True, smooth the image before detection using a Gaussian of width
216 ``sigma``,
or the measured PSF width. Set to
False when running on
217 e.g. a pre-convolved image,
or a mask plane.
219 Sigma of PSF (pixels); used
for smoothing
and to grow detections;
220 if None then measure the sigma of the PSF of the exposure
222 Clear DETECTED{,_NEGATIVE} planes before running detection.
224 Exposure identifier; unused by this implementation, but used
for
225 RNG seed by subclasses.
229 result : `lsst.pipe.base.Struct`
233 The result resturned by `detectFootprints`
234 (`lsst.pipe.base.Struct`).
239 If flags.negative
is needed, but isn
't in table's schema.
240 lsst.pipe.base.TaskError
241 If sigma=
None, doSmooth=
True and the exposure has no PSF.
245 If you want to avoid dealing
with Sources
and Tables, you can use
249 raise ValueError(
"Table has incorrect Schema")
250 results = self.
detectFootprintsdetectFootprints(exposure=exposure, doSmooth=doSmooth, sigma=sigma,
251 clearMask=clearMask, expId=expId)
252 sources = afwTable.SourceCatalog(table)
253 sources.reserve(results.numPos + results.numNeg)
255 results.negative.makeSources(sources)
257 for record
in sources:
260 results.positive.makeSources(sources)
261 results.fpSets = results.copy()
262 results.sources = sources
265 def display(self, exposure, results, convolvedImage=None):
266 """Display detections if so configured
268 Displays the ``exposure`` in frame 0, overlays the detection peaks.
270 Requires that ``lsstDebug`` has been set up correctly, so that
271 ``
lsstDebug.Info(
"lsst.meas.algorithms.detection")`` evaluates `
True`.
273 If the ``convolvedImage``
is non-`
None`
and
275 ``convolvedImage`` will be displayed
in frame 1.
280 Exposure to display, on which will be plotted the detections.
281 results : `lsst.pipe.base.Struct`
282 Results of the
'detectFootprints' method, containing positive
and
283 negative footprints (which contain the peak positions that we will
284 plot). This
is a `Struct`
with ``positive``
and ``negative``
287 Convolved image used
for thresholding.
300 afwDisplay.setDefaultMaskTransparency(75)
302 disp0 = afwDisplay.Display(frame=0)
303 disp0.mtv(exposure, title=
"detection")
305 def plotPeaks(fps, ctype):
308 with disp0.Buffering():
309 for fp
in fps.getFootprints():
310 for pp
in fp.getPeaks():
311 disp0.dot(
"+", pp.getFx(), pp.getFy(), ctype=ctype)
312 plotPeaks(results.positive,
"yellow")
313 plotPeaks(results.negative,
"red")
315 if convolvedImage
and display > 1:
316 disp1 = afwDisplay.Display(frame=1)
317 disp1.mtv(convolvedImage, title=
"PSF smoothed")
320 """Apply a temporary local background subtraction
322 This temporary local background serves to suppress noise fluctuations
323 in the wings of bright objects.
325 Peaks
in the footprints will be updated.
330 Exposure
for which to fit local background.
332 Convolved image on which detection will be performed
333 (typically smaller than ``exposure`` because the
334 half-kernel has been removed around the edges).
335 results : `lsst.pipe.base.Struct`
336 Results of the
'detectFootprints' method, containing positive
and
337 negative footprints (which contain the peak positions that we will
338 plot). This
is a `Struct`
with ``positive``
and ``negative``
344 bg = self.tempLocalBackground.fitBackground(exposure.getMaskedImage())
345 bgImage = bg.getImageF(self.tempLocalBackground.config.algorithm,
346 self.tempLocalBackground.config.undersampleStyle)
347 middle -= bgImage.Factory(bgImage, middle.getBBox())
348 thresholdPos = self.
makeThresholdmakeThreshold(middle,
"positive")
349 thresholdNeg = self.
makeThresholdmakeThreshold(middle,
"negative")
350 if self.config.thresholdPolarity !=
"negative":
351 self.
updatePeaksupdatePeaks(results.positive, middle, thresholdPos)
352 if self.config.thresholdPolarity !=
"positive":
353 self.
updatePeaksupdatePeaks(results.negative, middle, thresholdNeg)
356 """Clear the DETECTED and DETECTED_NEGATIVE mask planes
358 Removes any previous detection mask in preparation
for a new
366 mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask(
"DETECTED_NEGATIVE"))
369 """Calculate size of smoothing kernel
371 Uses the ``nSigmaForKernel`` configuration parameter. Note
372 that that is the full width of the kernel bounding box
373 (so a value of 7 means 3.5 sigma on either side of center).
374 The value will be rounded up to the nearest odd integer.
379 Gaussian sigma of smoothing kernel.
384 Size of the smoothing kernel.
386 return (int(sigma * self.config.nSigmaForKernel + 0.5)//2)*2 + 1
389 """Retrieve the PSF for an exposure
391 If ``sigma`` is provided, we make a ``GaussianPsf``
with that,
392 otherwise use the one
from the ``exposure``.
397 Exposure
from which to retrieve the PSF.
398 sigma : `float`, optional
399 Gaussian sigma to use
if provided.
404 PSF to use
for detection.
407 psf = exposure.getPsf()
409 raise RuntimeError(
"Unable to determine PSF to use for detection: no sigma provided")
410 sigma = psf.computeShape().getDeterminantRadius()
412 psf = afwDet.GaussianPsf(size, size, sigma)
416 """Convolve the image with the PSF
418 We convolve the image with a Gaussian approximation to the PSF,
419 because this
is separable
and therefore fast. It
's technically a
420 correlation rather than a convolution, but since we use a symmetric
421 Gaussian there's no difference.
423 The convolution can be disabled with ``doSmooth=
False``. If we do
424 convolve, we mask the edges
as ``EDGE``
and return the convolved image
425 with the edges removed. This
is because we can
't convolve the edges
426 because the kernel would extend off the image.
433 PSF to convolve with (actually
with a Gaussian approximation
436 Actually do the convolution? Set to
False when running on
437 e.g. a pre-convolved image,
or a mask plane.
439 Return Struct contents
440 ----------------------
442 Convolved image, without the edges.
444 Gaussian sigma used
for the convolution.
446 self.metadata["doSmooth"] = doSmooth
447 sigma = psf.computeShape().getDeterminantRadius()
448 self.metadata[
"sigma"] = sigma
451 middle = maskedImage.Factory(maskedImage, deep=
True)
452 return pipeBase.Struct(middle=middle, sigma=sigma)
457 self.metadata[
"smoothingKernelWidth"] = kWidth
458 gaussFunc = afwMath.GaussianFunction1D(sigma)
459 gaussKernel = afwMath.SeparableKernel(kWidth, kWidth, gaussFunc, gaussFunc)
461 convolvedImage = maskedImage.Factory(maskedImage.getBBox())
463 afwMath.convolve(convolvedImage, maskedImage, gaussKernel, afwMath.ConvolutionControl())
467 goodBBox = gaussKernel.shrinkBBox(convolvedImage.getBBox())
468 middle = convolvedImage.Factory(convolvedImage, goodBBox, afwImage.PARENT,
False)
472 self.
setEdgeBitssetEdgeBits(maskedImage, goodBBox, maskedImage.getMask().getPlaneBitMask(
"EDGE"))
474 return pipeBase.Struct(middle=middle, sigma=sigma)
477 """Apply thresholds to the convolved image
479 Identifies ``Footprint``s, both positive and negative.
481 The threshold can be modified by the provided multiplication
487 Convolved image to threshold.
489 Bounding box of unconvolved image.
491 Multiplier
for the configured threshold.
493 Return Struct contents
494 ----------------------
496 Positive detection footprints,
if configured.
498 Negative detection footprints,
if configured.
500 Multiplier
for the configured threshold.
502 results = pipeBase.Struct(positive=None, negative=
None, factor=factor)
504 if self.config.reEstimateBackground
or self.config.thresholdPolarity !=
"negative":
505 threshold = self.
makeThresholdmakeThreshold(middle,
"positive", factor=factor)
506 results.positive = afwDet.FootprintSet(
510 self.config.minPixels
512 results.positive.setRegion(bbox)
513 if self.config.reEstimateBackground
or self.config.thresholdPolarity !=
"positive":
514 threshold = self.
makeThresholdmakeThreshold(middle,
"negative", factor=factor)
515 results.negative = afwDet.FootprintSet(
519 self.config.minPixels
521 results.negative.setRegion(bbox)
526 """Finalize the detected footprints
528 Grows the footprints, sets the ``DETECTED`` and ``DETECTED_NEGATIVE``
529 mask planes,
and logs the results.
531 ``numPos`` (number of positive footprints), ``numPosPeaks`` (number
532 of positive peaks), ``numNeg`` (number of negative footprints),
533 ``numNegPeaks`` (number of negative peaks) entries are added to the
539 Mask image on which to flag detected pixels.
540 results : `lsst.pipe.base.Struct`
541 Struct of detection results, including ``positive``
and
542 ``negative`` entries; modified.
544 Gaussian sigma of PSF.
546 Multiplier
for the configured threshold.
548 for polarity, maskName
in ((
"positive",
"DETECTED"), (
"negative",
"DETECTED_NEGATIVE")):
549 fpSet = getattr(results, polarity)
552 if self.config.nSigmaToGrow > 0:
553 nGrow = int((self.config.nSigmaToGrow * sigma) + 0.5)
554 self.metadata[
"nGrow"] = nGrow
555 if self.config.combinedGrow:
556 fpSet = afwDet.FootprintSet(fpSet, nGrow, self.config.isotropicGrow)
558 stencil = (afwGeom.Stencil.CIRCLE
if self.config.isotropicGrow
else
559 afwGeom.Stencil.MANHATTAN)
561 fp.dilate(nGrow, stencil)
562 fpSet.setMask(mask, maskName)
563 if not self.config.returnOriginalFootprints:
564 setattr(results, polarity, fpSet)
567 results.numPosPeaks = 0
569 results.numNegPeaks = 0
573 if results.positive
is not None:
574 results.numPos = len(results.positive.getFootprints())
575 results.numPosPeaks = sum(len(fp.getPeaks())
for fp
in results.positive.getFootprints())
576 positive =
" %d positive peaks in %d footprints" % (results.numPosPeaks, results.numPos)
577 if results.negative
is not None:
578 results.numNeg = len(results.negative.getFootprints())
579 results.numNegPeaks = sum(len(fp.getPeaks())
for fp
in results.negative.getFootprints())
580 negative =
" %d negative peaks in %d footprints" % (results.numNegPeaks, results.numNeg)
582 self.log.info(
"Detected%s%s%s to %g %s",
583 positive,
" and" if positive
and negative
else "", negative,
584 self.config.thresholdValue*self.config.includeThresholdMultiplier*factor,
585 "DN" if self.config.thresholdType ==
"value" else "sigma")
588 """Estimate the background after detection
593 Image on which to estimate the background.
594 backgrounds : `lsst.afw.math.BackgroundList`
595 List of backgrounds; modified.
599 bg : `lsst.afw.math.backgroundMI`
600 Empirical background model.
602 bg = self.background.fitBackground(maskedImage)
603 if self.config.adjustBackground:
604 self.log.warning(
"Fiddling the background by %g", self.config.adjustBackground)
605 bg += self.config.adjustBackground
606 self.log.info(
"Resubtracting the background after object detection")
607 maskedImage -= bg.getImageF(self.background.config.algorithm,
608 self.background.config.undersampleStyle)
610 actrl = bg.getBackgroundControl().getApproximateControl()
611 backgrounds.append((bg, getattr(afwMath.Interpolate, self.background.config.algorithm),
612 bg.getAsUsedUndersampleStyle(), actrl.getStyle(), actrl.getOrderX(),
613 actrl.getOrderY(), actrl.getWeighting()))
617 """Clear unwanted results from the Struct of results
619 If we specifically want only positive or only negative detections,
620 drop the ones we don
't want, and its associated mask plane.
626 results : `lsst.pipe.base.Struct`
627 Detection results, with ``positive``
and ``negative`` elements;
630 if self.config.thresholdPolarity ==
"positive":
631 if self.config.reEstimateBackground:
632 mask &= ~mask.getPlaneBitMask(
"DETECTED_NEGATIVE")
633 results.negative =
None
634 elif self.config.thresholdPolarity ==
"negative":
635 if self.config.reEstimateBackground:
636 mask &= ~mask.getPlaneBitMask(
"DETECTED")
637 results.positive =
None
640 def detectFootprints(self, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None):
641 """Detect footprints on an exposure.
646 Exposure to process; DETECTED{,_NEGATIVE} mask plane will be
648 doSmooth : `bool`, optional
649 If
True, smooth the image before detection using a Gaussian
650 of width ``sigma``,
or the measured PSF width of ``exposure``.
651 Set to
False when running on e.g. a pre-convolved image,
or a mask
653 sigma : `float`, optional
654 Gaussian Sigma of PSF (pixels); used
for smoothing
and to grow
655 detections;
if `
None` then measure the sigma of the PSF of the
657 clearMask : `bool`, optional
658 Clear both DETECTED
and DETECTED_NEGATIVE planes before running
660 expId : `dict`, optional
661 Exposure identifier; unused by this implementation, but used
for
662 RNG seed by subclasses.
664 Return Struct contents
665 ----------------------
667 Positive polarity footprints (may be `
None`)
669 Negative polarity footprints (may be `
None`)
671 Number of footprints
in positive
or 0
if detection polarity was
674 Number of footprints
in negative
or 0
if detection polarity was
676 background : `lsst.afw.math.BackgroundList`
677 Re-estimated background. `
None`
if
678 ``reEstimateBackground==
False``.
680 Multiplication factor applied to the configured detection
683 maskedImage = exposure.maskedImage
686 self.
clearMaskclearMask(maskedImage.getMask())
688 psf = self.
getPsfgetPsf(exposure, sigma=sigma)
690 convolveResults = self.
convolveImageconvolveImage(maskedImage, psf, doSmooth=doSmooth)
691 middle = convolveResults.middle
692 sigma = convolveResults.sigma
694 results = self.
applyThresholdapplyThreshold(middle, maskedImage.getBBox())
695 results.background = afwMath.BackgroundList()
696 if self.config.doTempLocalBackground:
700 if self.config.reEstimateBackground:
704 self.
displaydisplay(exposure, results, middle)
709 """Make an afw.detection.Threshold object corresponding to the task's
710 configuration and the statistics of the given image.
715 Image to measure noise statistics
from if needed.
716 thresholdParity: `str`
717 One of
"positive" or "negative", to set the kind of fluctuations
718 the Threshold will detect.
720 Factor by which to multiply the configured detection threshold.
721 This
is useful
for tweaking the detection threshold slightly.
728 parity = False if thresholdParity ==
"negative" else True
729 thresholdValue = self.config.thresholdValue
730 thresholdType = self.config.thresholdType
731 if self.config.thresholdType ==
'stdev':
732 bad = image.getMask().getPlaneBitMask(self.config.statsMask)
733 sctrl = afwMath.StatisticsControl()
734 sctrl.setAndMask(bad)
735 stats = afwMath.makeStatistics(image, afwMath.STDEVCLIP, sctrl)
736 thresholdValue *= stats.getValue(afwMath.STDEVCLIP)
737 thresholdType =
'value'
739 threshold = afwDet.createThreshold(thresholdValue*factor, thresholdType, parity)
740 threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier)
744 """Update the Peaks in a FootprintSet by detecting new Footprints and
745 Peaks in an image
and using the new Peaks instead of the old ones.
750 Set of Footprints whose Peaks should be updated.
752 Image to detect new Footprints
and Peak
in.
754 Threshold object
for detection.
756 Input Footprints
with fewer Peaks than self.config.nPeaksMaxSimple
757 are
not modified,
and if no new Peaks are detected
in an input
758 Footprint, the brightest original Peak
in that Footprint
is kept.
760 for footprint
in fpSet.getFootprints():
761 oldPeaks = footprint.getPeaks()
762 if len(oldPeaks) <= self.config.nPeaksMaxSimple:
767 sub = image.Factory(image, footprint.getBBox())
768 fpSetForPeaks = afwDet.FootprintSet(
772 self.config.minPixels
774 newPeaks = afwDet.PeakCatalog(oldPeaks.getTable())
775 for fpForPeaks
in fpSetForPeaks.getFootprints():
776 for peak
in fpForPeaks.getPeaks():
777 if footprint.contains(peak.getI()):
778 newPeaks.append(peak)
779 if len(newPeaks) > 0:
781 oldPeaks.extend(newPeaks)
787 """Set the edgeBitmask bits for all of maskedImage outside goodBBox
792 Image on which to set edge bits in the mask.
794 Bounding box of good pixels,
in ``LOCAL`` coordinates.
796 Bit mask to OR
with the existing mask bits
in the region
797 outside ``goodBBox``.
799 msk = maskedImage.getMask()
801 mx0, my0 = maskedImage.getXY0()
802 for x0, y0, w, h
in ([0, 0,
803 msk.getWidth(), goodBBox.getBeginY() - my0],
804 [0, goodBBox.getEndY() - my0, msk.getWidth(),
805 maskedImage.getHeight() - (goodBBox.getEndY() - my0)],
807 goodBBox.getBeginX() - mx0, msk.getHeight()],
808 [goodBBox.getEndX() - mx0, 0,
809 maskedImage.getWidth() - (goodBBox.getEndX() - mx0), msk.getHeight()],
813 edgeMask |= edgeBitmask
817 """Context manager for removing wide (large-scale) background
819 Removing a wide (large-scale) background helps to suppress the
820 detection of large footprints that may overwhelm the deblender.
821 It does, however, set a limit on the maximum scale of objects.
823 The background that we remove will be restored upon exit from
829 Exposure on which to remove large-scale background.
833 context : context manager
834 Context manager that will ensure the temporary wide background
837 doTempWideBackground = self.config.doTempWideBackground
838 if doTempWideBackground:
839 self.log.info(
"Applying temporary wide background subtraction")
840 original = exposure.maskedImage.image.array[:].copy()
841 self.tempWideBackground.
run(exposure).background
844 image = exposure.maskedImage.image
845 mask = exposure.maskedImage.mask
846 noData = mask.array & mask.getPlaneBitMask(
"NO_DATA") > 0
847 isGood = mask.array & mask.getPlaneBitMask(self.config.statsMask) == 0
848 image.array[noData] = np.median(image.array[~noData & isGood])
852 if doTempWideBackground:
853 exposure.maskedImage.image.array[:] = original
857 """Add a set of exposures together.
862 Sequence of exposures to add.
867 An exposure of the same size as each exposure
in ``exposureList``,
868 with the metadata
from ``exposureList[0]``
and a masked image equal
869 to the sum of all the exposure
's masked images.
871 exposure0 = exposureList[0]
872 image0 = exposure0.getMaskedImage()
874 addedImage = image0.Factory(image0, True)
875 addedImage.setXY0(image0.getXY0())
877 for exposure
in exposureList[1:]:
878 image = exposure.getMaskedImage()
881 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)