24__all__ = (
"SourceDetectionConfig",
"SourceDetectionTask",
"addExposures")
26from contextlib
import contextmanager
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)
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")
319 disp2 = afwDisplay.Display(frame=2)
320 disp2.mtv(afwImage.ImageF(np.sqrt(exposure.variance.array)), title=
"stddev")
323 """Apply a temporary local background subtraction
325 This temporary local background serves to suppress noise fluctuations
326 in the wings of bright objects.
328 Peaks
in the footprints will be updated.
333 Exposure
for which to fit local background.
335 Convolved image on which detection will be performed
336 (typically smaller than ``exposure`` because the
337 half-kernel has been removed around the edges).
338 results : `lsst.pipe.base.Struct`
339 Results of the
'detectFootprints' method, containing positive
and
340 negative footprints (which contain the peak positions that we will
341 plot). This
is a `Struct`
with ``positive``
and ``negative``
347 bg = self.tempLocalBackground.fitBackground(exposure.getMaskedImage())
348 bgImage = bg.getImageF(self.tempLocalBackground.config.algorithm,
349 self.tempLocalBackground.config.undersampleStyle)
350 middle -= bgImage.Factory(bgImage, middle.getBBox())
351 if self.config.thresholdPolarity !=
"negative":
352 results.positiveThreshold = self.
makeThresholdmakeThreshold(middle,
"positive")
353 self.
updatePeaksupdatePeaks(results.positive, middle, results.positiveThreshold)
354 if self.config.thresholdPolarity !=
"positive":
355 results.negativeThreshold = self.
makeThresholdmakeThreshold(middle,
"negative")
356 self.
updatePeaksupdatePeaks(results.negative, middle, results.negativeThreshold)
359 """Clear the DETECTED and DETECTED_NEGATIVE mask planes
361 Removes any previous detection mask in preparation
for a new
369 mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask(
"DETECTED_NEGATIVE"))
372 """Calculate size of smoothing kernel
374 Uses the ``nSigmaForKernel`` configuration parameter. Note
375 that that is the full width of the kernel bounding box
376 (so a value of 7 means 3.5 sigma on either side of center).
377 The value will be rounded up to the nearest odd integer.
382 Gaussian sigma of smoothing kernel.
387 Size of the smoothing kernel.
389 return (
int(sigma * self.config.nSigmaForKernel + 0.5)//2)*2 + 1
392 """Retrieve the PSF for an exposure
394 If ``sigma`` is provided, we make a ``GaussianPsf``
with that,
395 otherwise use the one
from the ``exposure``.
400 Exposure
from which to retrieve the PSF.
401 sigma : `float`, optional
402 Gaussian sigma to use
if provided.
407 PSF to use
for detection.
410 psf = exposure.getPsf()
412 raise RuntimeError(
"Unable to determine PSF to use for detection: no sigma provided")
413 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
419 """Convolve the image with the PSF
421 We convolve the image with a Gaussian approximation to the PSF,
422 because this
is separable
and therefore fast. It
's technically a
423 correlation rather than a convolution, but since we use a symmetric
424 Gaussian there's no difference.
426 The convolution can be disabled with ``doSmooth=
False``. If we do
427 convolve, we mask the edges
as ``EDGE``
and return the convolved image
428 with the edges removed. This
is because we can
't convolve the edges
429 because the kernel would extend off the image.
436 PSF to convolve with (actually
with a Gaussian approximation
439 Actually do the convolution? Set to
False when running on
440 e.g. a pre-convolved image,
or a mask plane.
442 Return Struct contents
443 ----------------------
445 Convolved image, without the edges.
447 Gaussian sigma used
for the convolution.
449 self.metadata["doSmooth"] = doSmooth
450 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
451 self.metadata[
"sigma"] = sigma
454 middle = maskedImage.Factory(maskedImage, deep=
True)
455 return pipeBase.Struct(middle=middle, sigma=sigma)
460 self.metadata[
"smoothingKernelWidth"] = kWidth
461 gaussFunc = afwMath.GaussianFunction1D(sigma)
464 convolvedImage = maskedImage.Factory(maskedImage.getBBox())
470 goodBBox = gaussKernel.shrinkBBox(convolvedImage.getBBox())
471 middle = convolvedImage.Factory(convolvedImage, goodBBox, afwImage.PARENT,
False)
475 self.
setEdgeBitssetEdgeBits(maskedImage, goodBBox, maskedImage.getMask().getPlaneBitMask(
"EDGE"))
477 return pipeBase.Struct(middle=middle, sigma=sigma)
480 """Apply thresholds to the convolved image
482 Identifies ``Footprint``s, both positive and negative.
484 The threshold can be modified by the provided multiplication
490 Convolved image to threshold.
492 Bounding box of unconvolved image.
494 Multiplier
for the configured threshold.
496 Return Struct contents
497 ----------------------
499 Positive detection footprints,
if configured.
501 Negative detection footprints,
if configured.
503 Multiplier
for the configured threshold.
505 results = pipeBase.Struct(positive=None, negative=
None, factor=factor,
506 positiveThreshold=
None, negativeThreshold=
None)
508 if self.config.reEstimateBackground
or self.config.thresholdPolarity !=
"negative":
509 results.positiveThreshold = self.
makeThresholdmakeThreshold(middle,
"positive", factor=factor)
512 results.positiveThreshold,
514 self.config.minPixels
516 results.positive.setRegion(bbox)
517 if self.config.reEstimateBackground
or self.config.thresholdPolarity !=
"positive":
518 results.negativeThreshold = self.
makeThresholdmakeThreshold(middle,
"negative", factor=factor)
521 results.negativeThreshold,
523 self.config.minPixels
525 results.negative.setRegion(bbox)
530 """Finalize the detected footprints
532 Grows the footprints, sets the ``DETECTED`` and ``DETECTED_NEGATIVE``
533 mask planes,
and logs the results.
535 ``numPos`` (number of positive footprints), ``numPosPeaks`` (number
536 of positive peaks), ``numNeg`` (number of negative footprints),
537 ``numNegPeaks`` (number of negative peaks) entries are added to the
543 Mask image on which to flag detected pixels.
544 results : `lsst.pipe.base.Struct`
545 Struct of detection results, including ``positive``
and
546 ``negative`` entries; modified.
548 Gaussian sigma of PSF.
550 Multiplier
for the configured threshold.
552 for polarity, maskName
in ((
"positive",
"DETECTED"), (
"negative",
"DETECTED_NEGATIVE")):
553 fpSet = getattr(results, polarity)
556 if self.config.nSigmaToGrow > 0:
557 nGrow =
int((self.config.nSigmaToGrow * sigma) + 0.5)
558 self.metadata[
"nGrow"] = nGrow
559 if self.config.combinedGrow:
562 stencil = (afwGeom.Stencil.CIRCLE
if self.config.isotropicGrow
else
563 afwGeom.Stencil.MANHATTAN)
565 fp.dilate(nGrow, stencil)
566 fpSet.setMask(mask, maskName)
567 if not self.config.returnOriginalFootprints:
568 setattr(results, polarity, fpSet)
571 results.numPosPeaks = 0
573 results.numNegPeaks = 0
577 if results.positive
is not None:
578 results.numPos = len(results.positive.getFootprints())
579 results.numPosPeaks = sum(len(fp.getPeaks())
for fp
in results.positive.getFootprints())
580 positive =
" %d positive peaks in %d footprints" % (results.numPosPeaks, results.numPos)
581 if results.negative
is not None:
582 results.numNeg = len(results.negative.getFootprints())
583 results.numNegPeaks = sum(len(fp.getPeaks())
for fp
in results.negative.getFootprints())
584 negative =
" %d negative peaks in %d footprints" % (results.numNegPeaks, results.numNeg)
586 self.log.
info(
"Detected%s%s%s to %g %s",
587 positive,
" and" if positive
and negative
else "", negative,
588 self.config.thresholdValue*self.config.includeThresholdMultiplier*factor,
589 "DN" if self.config.thresholdType ==
"value" else "sigma")
592 """Estimate the background after detection
597 Image on which to estimate the background.
599 List of backgrounds; modified.
603 bg : `lsst.afw.math.backgroundMI`
604 Empirical background model.
606 bg = self.background.fitBackground(maskedImage)
607 if self.config.adjustBackground:
608 self.log.
warning(
"Fiddling the background by %g", self.config.adjustBackground)
609 bg += self.config.adjustBackground
610 self.log.
info(
"Resubtracting the background after object detection")
611 maskedImage -= bg.getImageF(self.background.config.algorithm,
612 self.background.config.undersampleStyle)
614 actrl = bg.getBackgroundControl().getApproximateControl()
616 bg.getAsUsedUndersampleStyle(), actrl.getStyle(), actrl.getOrderX(),
617 actrl.getOrderY(), actrl.getWeighting()))
621 """Clear unwanted results from the Struct of results
623 If we specifically want only positive or only negative detections,
624 drop the ones we don
't want, and its associated mask plane.
630 results : `lsst.pipe.base.Struct`
631 Detection results, with ``positive``
and ``negative`` elements;
634 if self.config.thresholdPolarity ==
"positive":
635 if self.config.reEstimateBackground:
636 mask &= ~mask.getPlaneBitMask(
"DETECTED_NEGATIVE")
637 results.negative =
None
638 elif self.config.thresholdPolarity ==
"negative":
639 if self.config.reEstimateBackground:
640 mask &= ~mask.getPlaneBitMask(
"DETECTED")
641 results.positive =
None
644 def detectFootprints(self, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None):
645 """Detect footprints on an exposure.
650 Exposure to process; DETECTED{,_NEGATIVE} mask plane will be
652 doSmooth : `bool`, optional
653 If
True, smooth the image before detection using a Gaussian
654 of width ``sigma``,
or the measured PSF width of ``exposure``.
655 Set to
False when running on e.g. a pre-convolved image,
or a mask
657 sigma : `float`, optional
658 Gaussian Sigma of PSF (pixels); used
for smoothing
and to grow
659 detections;
if `
None` then measure the sigma of the PSF of the
661 clearMask : `bool`, optional
662 Clear both DETECTED
and DETECTED_NEGATIVE planes before running
664 expId : `dict`, optional
665 Exposure identifier; unused by this implementation, but used
for
666 RNG seed by subclasses.
668 Return Struct contents
669 ----------------------
671 Positive polarity footprints (may be `
None`)
673 Negative polarity footprints (may be `
None`)
675 Number of footprints
in positive
or 0
if detection polarity was
678 Number of footprints
in negative
or 0
if detection polarity was
681 Re-estimated background. `
None`
if
682 ``reEstimateBackground==
False``.
684 Multiplication factor applied to the configured detection
687 maskedImage = exposure.maskedImage
690 self.
clearMaskclearMask(maskedImage.getMask())
692 psf = self.
getPsfgetPsf(exposure, sigma=sigma)
694 convolveResults = self.
convolveImageconvolveImage(maskedImage, psf, doSmooth=doSmooth)
695 middle = convolveResults.middle
696 sigma = convolveResults.sigma
698 results = self.
applyThresholdapplyThreshold(middle, maskedImage.getBBox())
700 if self.config.doTempLocalBackground:
707 results.positive = self.
setPeakSignificancesetPeakSignificance(middle, results.positive, results.positiveThreshold)
708 results.negative = self.
setPeakSignificancesetPeakSignificance(middle, results.negative, results.negativeThreshold,
711 if self.config.reEstimateBackground:
716 self.
displaydisplay(exposure, results, middle)
721 """Set the significance of each detected peak to the pixel value divided
722 by the appropriate standard-deviation for ``config.thresholdType``.
724 Only sets significance
for "stdev" and "pixel_stdev" thresholdTypes;
725 we leave it undefined
for "value" and "variance" as it does
not have a
726 well-defined meaning
in those cases.
731 Exposure that footprints were detected on, likely the convolved,
732 local background-subtracted image.
734 Footprints detected on the image.
736 Threshold used to find footprints.
737 negative : `bool`, optional
738 Are we calculating
for negative sources?
740 if footprints
is None or footprints.getFootprints() == []:
742 polarity = -1
if negative
else 1
746 mapper.addMinimalSchema(footprints.getFootprints()[0].peaks.schema)
747 mapper.addOutputField(
"significance", type=float,
748 doc=
"Ratio of peak value to configured standard deviation.")
754 for old, new
in zip(footprints.getFootprints(), newFootprints.getFootprints()):
756 newPeaks.extend(old.peaks, mapper=mapper)
757 new.getPeaks().clear()
758 new.setPeakCatalog(newPeaks)
761 if self.config.thresholdType ==
"pixel_stdev":
762 for footprint
in newFootprints.getFootprints():
763 footprint.updatePeakSignificance(exposure.variance, polarity)
764 elif self.config.thresholdType ==
"stdev":
765 sigma = threshold.getValue() / self.config.thresholdValue
766 for footprint
in newFootprints.getFootprints():
767 footprint.updatePeakSignificance(polarity*sigma)
769 for footprint
in newFootprints.getFootprints():
770 for peak
in footprint.peaks:
771 peak[
"significance"] = 0
776 """Make an afw.detection.Threshold object corresponding to the task's
777 configuration and the statistics of the given image.
782 Image to measure noise statistics
from if needed.
783 thresholdParity: `str`
784 One of
"positive" or "negative", to set the kind of fluctuations
785 the Threshold will detect.
787 Factor by which to multiply the configured detection threshold.
788 This
is useful
for tweaking the detection threshold slightly.
795 parity = False if thresholdParity ==
"negative" else True
796 thresholdValue = self.config.thresholdValue
797 thresholdType = self.config.thresholdType
798 if self.config.thresholdType ==
'stdev':
799 bad = image.getMask().getPlaneBitMask(self.config.statsMask)
801 sctrl.setAndMask(bad)
803 thresholdValue *= stats.getValue(afwMath.STDEVCLIP)
804 thresholdType =
'value'
807 threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier)
808 self.log.
debug(
"Detection threshold: %s", threshold)
812 """Update the Peaks in a FootprintSet by detecting new Footprints and
813 Peaks in an image
and using the new Peaks instead of the old ones.
818 Set of Footprints whose Peaks should be updated.
820 Image to detect new Footprints
and Peak
in.
822 Threshold object
for detection.
824 Input Footprints
with fewer Peaks than self.config.nPeaksMaxSimple
825 are
not modified,
and if no new Peaks are detected
in an input
826 Footprint, the brightest original Peak
in that Footprint
is kept.
828 for footprint
in fpSet.getFootprints():
829 oldPeaks = footprint.getPeaks()
830 if len(oldPeaks) <= self.config.nPeaksMaxSimple:
835 sub = image.Factory(image, footprint.getBBox())
840 self.config.minPixels
843 for fpForPeaks
in fpSetForPeaks.getFootprints():
844 for peak
in fpForPeaks.getPeaks():
845 if footprint.contains(peak.getI()):
846 newPeaks.append(peak)
847 if len(newPeaks) > 0:
849 oldPeaks.extend(newPeaks)
855 """Set the edgeBitmask bits for all of maskedImage outside goodBBox
860 Image on which to set edge bits in the mask.
862 Bounding box of good pixels,
in ``LOCAL`` coordinates.
864 Bit mask to OR
with the existing mask bits
in the region
865 outside ``goodBBox``.
867 msk = maskedImage.getMask()
869 mx0, my0 = maskedImage.getXY0()
870 for x0, y0, w, h
in ([0, 0,
871 msk.getWidth(), goodBBox.getBeginY() - my0],
872 [0, goodBBox.getEndY() - my0, msk.getWidth(),
873 maskedImage.getHeight() - (goodBBox.getEndY() - my0)],
875 goodBBox.getBeginX() - mx0, msk.getHeight()],
876 [goodBBox.getEndX() - mx0, 0,
877 maskedImage.getWidth() - (goodBBox.getEndX() - mx0), msk.getHeight()],
881 edgeMask |= edgeBitmask
885 """Context manager for removing wide (large-scale) background
887 Removing a wide (large-scale) background helps to suppress the
888 detection of large footprints that may overwhelm the deblender.
889 It does, however, set a limit on the maximum scale of objects.
891 The background that we remove will be restored upon exit from
897 Exposure on which to remove large-scale background.
901 context : context manager
902 Context manager that will ensure the temporary wide background
905 doTempWideBackground = self.config.doTempWideBackground
906 if doTempWideBackground:
907 self.log.
info(
"Applying temporary wide background subtraction")
908 original = exposure.maskedImage.image.array[:].copy()
909 self.tempWideBackground.
run(exposure).background
912 image = exposure.maskedImage.image
913 mask = exposure.maskedImage.mask
914 noData = mask.array & mask.getPlaneBitMask(
"NO_DATA") > 0
915 isGood = mask.array & mask.getPlaneBitMask(self.config.statsMask) == 0
916 image.array[noData] = np.median(image.array[~noData & isGood])
920 if doTempWideBackground:
921 exposure.maskedImage.image.array[:] = original
925 """Add a set of exposures together.
930 Sequence of exposures to add.
935 An exposure of the same size as each exposure
in ``exposureList``,
936 with the metadata
from ``exposureList[0]``
and a masked image equal
937 to the sum of all the exposure
's masked images.
939 exposure0 = exposureList[0]
940 image0 = exposure0.getMaskedImage()
942 addedImage = image0.Factory(image0, True)
943 addedImage.setXY0(image0.getXY0())
945 for exposure
in exposureList[1:]:
946 image = exposure.getMaskedImage()
949 addedExposure = exposure0.Factory(addedImage, exposure0.getWcs())
A circularly symmetric Gaussian Psf class with no spatial variation, intended mostly for testing purp...
A polymorphic base class for representing an image's Point Spread Function.
A Threshold is used to pass a threshold value to detection algorithms.
A class to contain the data, WCS, and other information needed to describe an image of the sky.
A class to represent a 2-dimensional array of pixels.
Represent a 2-dimensional array of bitmask pixels.
A class to manipulate images, masks, and variance as a single object.
Parameters to control convolution.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
Pass parameters to a Statistics object.
Defines the fields and offsets for a table.
A mapping between the keys of two Schemas, used to copy data between them.
Table class that contains measurements made on a single exposure.
An integer coordinate rectangle.
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 setPeakSignificance(self, exposure, footprints, threshold, negative=False)
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)
Threshold createThreshold(const double value, const std::string type="value", const bool polarity=true)
Factory method for creating Threshold objects.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output image.
def addExposures(exposureList)