LSST Applications g04e9c324dd+8c5ae1fdc5,g0644efc3f0+366663dc37,g123d84c11c+8c5ae1fdc5,g1ec0fe41b4+6ec6b74de1,g1fd858c14a+1be88e80db,g3533f9d6cb+366663dc37,g35bb328faa+8c5ae1fdc5,g35ef7ab7cf+285dd5b202,g53246c7159+8c5ae1fdc5,g60b5630c4e+366663dc37,g663da51e9b+41529343ca,g6735e52a0d+29de3d959a,g67b6fd64d1+57193d00fb,g7605de067c+8f72e4d2dc,g78460c75b0+7e33a9eb6d,g786e29fd12+668abc6043,g844c57033c+03ddc13274,g8852436030+e345a59dd4,g89139ef638+57193d00fb,g989de1cb63+57193d00fb,g9a0bdda227+852181cf57,g9f33ca652e+a2d35689ce,ga1e959baac+5fbc491aed,ga2f891cd6c+366663dc37,gabe3b4be73+8856018cbb,gabf8522325+cc757f8247,gac2eed3f23+57193d00fb,gb1101e3267+f6b489998a,gb89ab40317+57193d00fb,gcf25f946ba+e345a59dd4,gd107969129+227687db21,gd6cbbdb0b4+8e46defd2a,gde0f65d7ad+2dad650f79,ge278dab8ac+2322f1d6ea,ge410e46f29+57193d00fb,gf30d85a44d+8e3077faf9,gf5e32f922b+8c5ae1fdc5,gff02db199a+5c78c1866e,w.2025.28
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.meas.algorithms.detection.SourceDetectionTask Class Reference
Inheritance diagram for lsst.meas.algorithms.detection.SourceDetectionTask:
lsst.meas.algorithms.dynamicDetection.DynamicDetectionTask

Public Member Functions

 __init__ (self, schema=None, **kwds)
 
 run (self, table, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None, background=None, backgroundToPhotometricRatio=None)
 
 display (self, exposure, results, convolvedImage=None)
 
 applyTempLocalBackground (self, exposure, middle, results)
 
 clearMask (self, mask)
 
 calculateKernelSize (self, sigma)
 
 getPsf (self, exposure, sigma=None)
 
 convolveImage (self, maskedImage, psf, doSmooth=True)
 
 applyThreshold (self, middle, bbox, factor=1.0, factorNeg=None)
 
 finalizeFootprints (self, mask, results, sigma, factor=1.0, factorNeg=None)
 
 reEstimateBackground (self, maskedImage, backgrounds, backgroundToPhotometricRatio=None)
 
 clearUnwantedResults (self, mask, results)
 
 detectFootprints (self, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None, background=None, backgroundToPhotometricRatio=None)
 
 removeBadPixels (self, middle)
 
 setPeakSignificance (self, exposure, footprints, threshold, negative=False)
 
 makeThreshold (self, image, thresholdParity, factor=1.0)
 
 updatePeaks (self, fpSet, image, threshold)
 
 tempWideBackgroundContext (self, exposure)
 

Static Public Member Functions

 setEdgeBits (maskedImage, goodBBox, edgeBitmask)
 

Public Attributes

 negativeFlagKey
 

Static Public Attributes

 ConfigClass = SourceDetectionConfig
 

Static Protected Attributes

str _DefaultName = "sourceDetection"
 

Detailed Description

Detect peaks and footprints of sources in an image.

This task expects the image to have been background subtracted first.
Running detection on images with a non-zero-centered background may result
in a single source detected on the entire image containing thousands of
peaks, or other pathological outputs.

Parameters
----------
schema : `lsst.afw.table.Schema`
    Schema object used to create the output `lsst.afw.table.SourceCatalog`
**kwds
    Keyword arguments passed to `lsst.pipe.base.Task.__init__`

If schema is not None and configured for 'both' detections,
a 'flags.negative' field will be added to label detections made with a
negative threshold.

Notes
-----
This task convolves the image with a Gaussian approximation to the PSF,
matched to the sigma of the input exposure, because this is separable and
fast. The PSF would have to be very non-Gaussian or non-circular for this
approximation to have a significant impact on the signal-to-noise of the
detected sources.

Definition at line 177 of file detection.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.meas.algorithms.detection.SourceDetectionTask.__init__ ( self,
schema = None,
** kwds )

Definition at line 207 of file detection.py.

207 def __init__(self, schema=None, **kwds):
208 pipeBase.Task.__init__(self, **kwds)
209 if schema is not None and self.config.thresholdPolarity == "both":
210 self.negativeFlagKey = schema.addField(
211 "is_negative", type="Flag",
212 doc="Set if source peak was detected as negative."
213 )
214 else:
215 if self.config.thresholdPolarity == "both":
216 self.log.warning("Detection polarity set to 'both', but no flag will be "
217 "set to distinguish between positive and negative detections")
218 self.negativeFlagKey = None
219 if self.config.reEstimateBackground:
220 self.makeSubtask("background")
221 if self.config.doTempLocalBackground:
222 self.makeSubtask("tempLocalBackground")
223 if self.config.doTempWideBackground:
224 self.makeSubtask("tempWideBackground")
225

Member Function Documentation

◆ applyTempLocalBackground()

lsst.meas.algorithms.detection.SourceDetectionTask.applyTempLocalBackground ( self,
exposure,
middle,
results )
Apply a temporary local background subtraction

This temporary local background serves to suppress noise fluctuations
in the wings of bright objects.

Peaks in the footprints will be updated.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure for which to fit local background.
middle : `lsst.afw.image.MaskedImage`
    Convolved image on which detection will be performed
    (typically smaller than ``exposure`` because the
    half-kernel has been removed around the edges).
results : `lsst.pipe.base.Struct`
    Results of the 'detectFootprints' method, containing positive and
    negative footprints (which contain the peak positions that we will
    plot). This is a `Struct` with ``positive`` and ``negative``
    elements that are of type `lsst.afw.detection.FootprintSet`.

Definition at line 372 of file detection.py.

372 def applyTempLocalBackground(self, exposure, middle, results):
373 """Apply a temporary local background subtraction
374
375 This temporary local background serves to suppress noise fluctuations
376 in the wings of bright objects.
377
378 Peaks in the footprints will be updated.
379
380 Parameters
381 ----------
382 exposure : `lsst.afw.image.Exposure`
383 Exposure for which to fit local background.
384 middle : `lsst.afw.image.MaskedImage`
385 Convolved image on which detection will be performed
386 (typically smaller than ``exposure`` because the
387 half-kernel has been removed around the edges).
388 results : `lsst.pipe.base.Struct`
389 Results of the 'detectFootprints' method, containing positive and
390 negative footprints (which contain the peak positions that we will
391 plot). This is a `Struct` with ``positive`` and ``negative``
392 elements that are of type `lsst.afw.detection.FootprintSet`.
393 """
394 # Subtract the local background from the smoothed image. Since we
395 # never use the smoothed again we don't need to worry about adding
396 # it back in.
397 bg = self.tempLocalBackground.fitBackground(exposure.getMaskedImage())
398 bgImage = bg.getImageF(self.tempLocalBackground.config.algorithm,
399 self.tempLocalBackground.config.undersampleStyle)
400 middle -= bgImage.Factory(bgImage, middle.getBBox())
401 if self.config.thresholdPolarity != "negative":
402 results.positiveThreshold = self.makeThreshold(middle, "positive")
403 self.updatePeaks(results.positive, middle, results.positiveThreshold)
404 if self.config.thresholdPolarity != "positive":
405 results.negativeThreshold = self.makeThreshold(middle, "negative")
406 self.updatePeaks(results.negative, middle, results.negativeThreshold)
407

◆ applyThreshold()

lsst.meas.algorithms.detection.SourceDetectionTask.applyThreshold ( self,
middle,
bbox,
factor = 1.0,
factorNeg = None )
Apply thresholds to the convolved image

Identifies `~lsst.afw.detection.Footprint`\s, both positive and negative.
The threshold can be modified by the provided multiplication
``factor``.

Parameters
----------
middle : `lsst.afw.image.MaskedImage`
    Convolved image to threshold.
bbox : `lsst.geom.Box2I`
    Bounding box of unconvolved image.
factor : `float`
    Multiplier for the configured threshold.
factorNeg : `float` or `None`
    Multiplier for the configured threshold for negative detection polarity.
    If `None`, will be set equal to ``factor`` (i.e. equal to the factor used
    for positive detection polarity).

Returns
-------
results : `lsst.pipe.base.Struct`
    The `~lsst.pipe.base.Struct` contains:

    ``positive``
        Positive detection footprints, if configured.
        (`lsst.afw.detection.FootprintSet` or `None`)
    ``negative``
        Negative detection footprints, if configured.
        (`lsst.afw.detection.FootprintSet` or `None`)
    ``factor``
        Multiplier for the configured threshold.
        (`float`)
    ``factorNeg``
        Multiplier for the configured threshold for negative detection polarity.
        (`float`)

Definition at line 537 of file detection.py.

537 def applyThreshold(self, middle, bbox, factor=1.0, factorNeg=None):
538 r"""Apply thresholds to the convolved image
539
540 Identifies `~lsst.afw.detection.Footprint`\s, both positive and negative.
541 The threshold can be modified by the provided multiplication
542 ``factor``.
543
544 Parameters
545 ----------
546 middle : `lsst.afw.image.MaskedImage`
547 Convolved image to threshold.
548 bbox : `lsst.geom.Box2I`
549 Bounding box of unconvolved image.
550 factor : `float`
551 Multiplier for the configured threshold.
552 factorNeg : `float` or `None`
553 Multiplier for the configured threshold for negative detection polarity.
554 If `None`, will be set equal to ``factor`` (i.e. equal to the factor used
555 for positive detection polarity).
556
557 Returns
558 -------
559 results : `lsst.pipe.base.Struct`
560 The `~lsst.pipe.base.Struct` contains:
561
562 ``positive``
563 Positive detection footprints, if configured.
564 (`lsst.afw.detection.FootprintSet` or `None`)
565 ``negative``
566 Negative detection footprints, if configured.
567 (`lsst.afw.detection.FootprintSet` or `None`)
568 ``factor``
569 Multiplier for the configured threshold.
570 (`float`)
571 ``factorNeg``
572 Multiplier for the configured threshold for negative detection polarity.
573 (`float`)
574 """
575 if factorNeg is None:
576 factorNeg = factor
577 self.log.info("Setting factor for negative detections equal to that for positive "
578 "detections: %f", factor)
579 results = pipeBase.Struct(positive=None, negative=None, factor=factor, factorNeg=factorNeg,
580 positiveThreshold=None, negativeThreshold=None)
581 # Detect the Footprints (peaks may be replaced if doTempLocalBackground)
582 if self.config.reEstimateBackground or self.config.thresholdPolarity != "negative":
583 results.positiveThreshold = self.makeThreshold(middle, "positive", factor=factor)
584 results.positive = afwDet.FootprintSet(
585 middle,
586 results.positiveThreshold,
587 "DETECTED",
588 self.config.minPixels
589 )
590 results.positive.setRegion(bbox)
591 if self.config.reEstimateBackground or self.config.thresholdPolarity != "positive":
592 results.negativeThreshold = self.makeThreshold(middle, "negative", factor=factorNeg)
593 results.negative = afwDet.FootprintSet(
594 middle,
595 results.negativeThreshold,
596 "DETECTED_NEGATIVE",
597 self.config.minPixels
598 )
599 results.negative.setRegion(bbox)
600
601 return results
602
A set of Footprints, associated with a MaskedImage.

◆ calculateKernelSize()

lsst.meas.algorithms.detection.SourceDetectionTask.calculateKernelSize ( self,
sigma )
Calculate the size of the smoothing kernel.

Uses the ``nSigmaForKernel`` configuration parameter. Note
that that is the full width of the kernel bounding box
(so a value of 7 means 3.5 sigma on either side of center).
The value will be rounded up to the nearest odd integer.

Parameters
----------
sigma : `float`
    Gaussian sigma of smoothing kernel.

Returns
-------
size : `int`
    Size of the smoothing kernel.

Definition at line 421 of file detection.py.

421 def calculateKernelSize(self, sigma):
422 """Calculate the size of the smoothing kernel.
423
424 Uses the ``nSigmaForKernel`` configuration parameter. Note
425 that that is the full width of the kernel bounding box
426 (so a value of 7 means 3.5 sigma on either side of center).
427 The value will be rounded up to the nearest odd integer.
428
429 Parameters
430 ----------
431 sigma : `float`
432 Gaussian sigma of smoothing kernel.
433
434 Returns
435 -------
436 size : `int`
437 Size of the smoothing kernel.
438 """
439 return (int(sigma * self.config.nSigmaForKernel + 0.5)//2)*2 + 1 # make sure it is odd
440

◆ clearMask()

lsst.meas.algorithms.detection.SourceDetectionTask.clearMask ( self,
mask )
Clear the DETECTED and DETECTED_NEGATIVE mask planes.

Removes any previous detection mask in preparation for a new
detection pass.

Parameters
----------
mask : `lsst.afw.image.Mask`
    Mask to be cleared.

Definition at line 408 of file detection.py.

408 def clearMask(self, mask):
409 """Clear the DETECTED and DETECTED_NEGATIVE mask planes.
410
411 Removes any previous detection mask in preparation for a new
412 detection pass.
413
414 Parameters
415 ----------
416 mask : `lsst.afw.image.Mask`
417 Mask to be cleared.
418 """
419 mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask("DETECTED_NEGATIVE"))
420

◆ clearUnwantedResults()

lsst.meas.algorithms.detection.SourceDetectionTask.clearUnwantedResults ( self,
mask,
results )
Clear unwanted results from the Struct of results

If we specifically want only positive or only negative detections,
drop the ones we don't want, and its associated mask plane.

Parameters
----------
mask : `lsst.afw.image.Mask`
    Mask image.
results : `lsst.pipe.base.Struct`
    Detection results, with ``positive`` and ``negative`` elements;
    modified.

Definition at line 711 of file detection.py.

711 def clearUnwantedResults(self, mask, results):
712 """Clear unwanted results from the Struct of results
713
714 If we specifically want only positive or only negative detections,
715 drop the ones we don't want, and its associated mask plane.
716
717 Parameters
718 ----------
719 mask : `lsst.afw.image.Mask`
720 Mask image.
721 results : `lsst.pipe.base.Struct`
722 Detection results, with ``positive`` and ``negative`` elements;
723 modified.
724 """
725 if self.config.thresholdPolarity == "positive":
726 if self.config.reEstimateBackground:
727 mask &= ~mask.getPlaneBitMask("DETECTED_NEGATIVE")
728 results.negative = None
729 elif self.config.thresholdPolarity == "negative":
730 if self.config.reEstimateBackground:
731 mask &= ~mask.getPlaneBitMask("DETECTED")
732 results.positive = None
733

◆ convolveImage()

lsst.meas.algorithms.detection.SourceDetectionTask.convolveImage ( self,
maskedImage,
psf,
doSmooth = True )
Convolve the image with the PSF.

We convolve the image with a Gaussian approximation to the PSF,
because this is separable and therefore fast. It's technically a
correlation rather than a convolution, but since we use a symmetric
Gaussian there's no difference.

The convolution can be disabled with ``doSmooth=False``. If we do
convolve, we mask the edges as ``EDGE`` and return the convolved image
with the edges removed. This is because we can't convolve the edges
because the kernel would extend off the image.

Parameters
----------
maskedImage : `lsst.afw.image.MaskedImage`
    Image to convolve.
psf : `lsst.afw.detection.Psf`
    PSF to convolve with (actually with a Gaussian approximation
    to it).
doSmooth : `bool`
    Actually do the convolution? Set to False when running on
    e.g. a pre-convolved image, or a mask plane.

Returns
-------
results : `lsst.pipe.base.Struct`
    The `~lsst.pipe.base.Struct` contains:

    ``middle``
        Convolved image, without the edges. (`lsst.afw.image.MaskedImage`)
    ``sigma``
        Gaussian sigma used for the convolution. (`float`)

Definition at line 475 of file detection.py.

475 def convolveImage(self, maskedImage, psf, doSmooth=True):
476 """Convolve the image with the PSF.
477
478 We convolve the image with a Gaussian approximation to the PSF,
479 because this is separable and therefore fast. It's technically a
480 correlation rather than a convolution, but since we use a symmetric
481 Gaussian there's no difference.
482
483 The convolution can be disabled with ``doSmooth=False``. If we do
484 convolve, we mask the edges as ``EDGE`` and return the convolved image
485 with the edges removed. This is because we can't convolve the edges
486 because the kernel would extend off the image.
487
488 Parameters
489 ----------
490 maskedImage : `lsst.afw.image.MaskedImage`
491 Image to convolve.
492 psf : `lsst.afw.detection.Psf`
493 PSF to convolve with (actually with a Gaussian approximation
494 to it).
495 doSmooth : `bool`
496 Actually do the convolution? Set to False when running on
497 e.g. a pre-convolved image, or a mask plane.
498
499 Returns
500 -------
501 results : `lsst.pipe.base.Struct`
502 The `~lsst.pipe.base.Struct` contains:
503
504 ``middle``
505 Convolved image, without the edges. (`lsst.afw.image.MaskedImage`)
506 ``sigma``
507 Gaussian sigma used for the convolution. (`float`)
508 """
509 self.metadata["doSmooth"] = doSmooth
510 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
511 self.metadata["sigma"] = sigma
512
513 if not doSmooth:
514 middle = maskedImage.Factory(maskedImage, deep=True)
515 return pipeBase.Struct(middle=middle, sigma=sigma)
516
517 # Smooth using a Gaussian (which is separable, hence fast) of width sigma
518 # Make a SingleGaussian (separable) kernel with the 'sigma'
519 kWidth = self.calculateKernelSize(sigma)
520 self.metadata["smoothingKernelWidth"] = kWidth
521 gaussFunc = afwMath.GaussianFunction1D(sigma)
522 gaussKernel = afwMath.SeparableKernel(kWidth, kWidth, gaussFunc, gaussFunc)
523
524 convolvedImage = maskedImage.Factory(maskedImage.getBBox())
525
526 afwMath.convolve(convolvedImage, maskedImage, gaussKernel, afwMath.ConvolutionControl())
527
528 # Only search psf-smoothed part of frame
529 goodBBox = gaussKernel.shrinkBBox(convolvedImage.getBBox())
530 middle = convolvedImage.Factory(convolvedImage, goodBBox, afwImage.PARENT, False)
531
532 # Mark the parts of the image outside goodBBox as EDGE
533 self.setEdgeBits(maskedImage, goodBBox, maskedImage.getMask().getPlaneBitMask("EDGE"))
534
535 return pipeBase.Struct(middle=middle, sigma=sigma)
536
Parameters to control convolution.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
Definition Kernel.h:860
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.

◆ detectFootprints()

lsst.meas.algorithms.detection.SourceDetectionTask.detectFootprints ( self,
exposure,
doSmooth = True,
sigma = None,
clearMask = True,
expId = None,
background = None,
backgroundToPhotometricRatio = None )
Detect footprints on an exposure.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to process; DETECTED{,_NEGATIVE} mask plane will be
    set in-place.
doSmooth : `bool`, optional
    If True, smooth the image before detection using a Gaussian
    of width ``sigma``, or the measured PSF width of ``exposure``.
    Set to False when running on e.g. a pre-convolved image, or a mask
    plane.
sigma : `float`, optional
    Gaussian Sigma of PSF (pixels); used for smoothing and to grow
    detections; if `None` then measure the sigma of the PSF of the
    ``exposure``.
clearMask : `bool`, optional
    Clear both DETECTED and DETECTED_NEGATIVE planes before running
    detection.
expId : `dict`, optional
    Exposure identifier; unused by this implementation, but used for
    RNG seed by subclasses.
background : `lsst.afw.math.BackgroundList`, optional
    Background that was already subtracted from the exposure; will be
    modified in-place if ``reEstimateBackground=True``.
backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
    Image to convert photometric-flattened image to
    background-flattened image if ``reEstimateBackground=True`` and
    exposure has been photometric-flattened.

Returns
-------
results : `lsst.pipe.base.Struct`
    A `~lsst.pipe.base.Struct` containing:

    ``positive``
        Positive polarity footprints.
        (`lsst.afw.detection.FootprintSet` or `None`)
    ``negative``
        Negative polarity footprints.
        (`lsst.afw.detection.FootprintSet` or `None`)
    ``numPos``
        Number of footprints in positive or 0 if detection polarity was
        negative. (`int`)
    ``numNeg``
        Number of footprints in negative or 0 if detection polarity was
        positive. (`int`)
    ``background``
        Re-estimated background.  `None` or the input ``background``
        if ``reEstimateBackground==False``.
        (`lsst.afw.math.BackgroundList`)
    ``factor``
        Multiplication factor applied to the configured detection
        threshold. (`float`)

Reimplemented in lsst.meas.algorithms.dynamicDetection.DynamicDetectionTask.

Definition at line 735 of file detection.py.

736 background=None, backgroundToPhotometricRatio=None):
737 """Detect footprints on an exposure.
738
739 Parameters
740 ----------
741 exposure : `lsst.afw.image.Exposure`
742 Exposure to process; DETECTED{,_NEGATIVE} mask plane will be
743 set in-place.
744 doSmooth : `bool`, optional
745 If True, smooth the image before detection using a Gaussian
746 of width ``sigma``, or the measured PSF width of ``exposure``.
747 Set to False when running on e.g. a pre-convolved image, or a mask
748 plane.
749 sigma : `float`, optional
750 Gaussian Sigma of PSF (pixels); used for smoothing and to grow
751 detections; if `None` then measure the sigma of the PSF of the
752 ``exposure``.
753 clearMask : `bool`, optional
754 Clear both DETECTED and DETECTED_NEGATIVE planes before running
755 detection.
756 expId : `dict`, optional
757 Exposure identifier; unused by this implementation, but used for
758 RNG seed by subclasses.
759 background : `lsst.afw.math.BackgroundList`, optional
760 Background that was already subtracted from the exposure; will be
761 modified in-place if ``reEstimateBackground=True``.
762 backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
763 Image to convert photometric-flattened image to
764 background-flattened image if ``reEstimateBackground=True`` and
765 exposure has been photometric-flattened.
766
767 Returns
768 -------
769 results : `lsst.pipe.base.Struct`
770 A `~lsst.pipe.base.Struct` containing:
771
772 ``positive``
773 Positive polarity footprints.
774 (`lsst.afw.detection.FootprintSet` or `None`)
775 ``negative``
776 Negative polarity footprints.
777 (`lsst.afw.detection.FootprintSet` or `None`)
778 ``numPos``
779 Number of footprints in positive or 0 if detection polarity was
780 negative. (`int`)
781 ``numNeg``
782 Number of footprints in negative or 0 if detection polarity was
783 positive. (`int`)
784 ``background``
785 Re-estimated background. `None` or the input ``background``
786 if ``reEstimateBackground==False``.
787 (`lsst.afw.math.BackgroundList`)
788 ``factor``
789 Multiplication factor applied to the configured detection
790 threshold. (`float`)
791 """
792 maskedImage = exposure.maskedImage
793
794 if clearMask:
795 self.clearMask(maskedImage.getMask())
796
797 psf = self.getPsf(exposure, sigma=sigma)
798 with self.tempWideBackgroundContext(exposure):
799 convolveResults = self.convolveImage(maskedImage, psf, doSmooth=doSmooth)
800 middle = convolveResults.middle
801 sigma = convolveResults.sigma
802 self.removeBadPixels(middle)
803
804 results = self.applyThreshold(middle, maskedImage.getBBox())
805 results.background = background if background is not None else afwMath.BackgroundList()
806
807 if self.config.doTempLocalBackground:
808 self.applyTempLocalBackground(exposure, middle, results)
809 self.finalizeFootprints(maskedImage.mask, results, sigma)
810
811 # Compute the significance of peaks after the peaks have been
812 # finalized and after local background correction/updatePeaks, so
813 # that the significance represents the "final" detection S/N.
814 results.positive = self.setPeakSignificance(middle, results.positive, results.positiveThreshold)
815 results.negative = self.setPeakSignificance(middle, results.negative, results.negativeThreshold,
816 negative=True)
817
818 if self.config.reEstimateBackground:
819 self.reEstimateBackground(
820 maskedImage,
821 results.background,
822 backgroundToPhotometricRatio=backgroundToPhotometricRatio,
823 )
824
825 self.clearUnwantedResults(maskedImage.getMask(), results)
826
827 self.display(exposure, results, middle)
828
829 return results
830

◆ display()

lsst.meas.algorithms.detection.SourceDetectionTask.display ( self,
exposure,
results,
convolvedImage = None )
Display detections if so configured

Displays the ``exposure`` in frame 0, overlays the detection peaks.

Requires that ``lsstDebug`` has been set up correctly, so that
``lsstDebug.Info("lsst.meas.algorithms.detection")`` evaluates `True`.

If the ``convolvedImage`` is non-`None` and
``lsstDebug.Info("lsst.meas.algorithms.detection") > 1``, the
``convolvedImage`` will be displayed in frame 1.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to display, on which will be plotted the detections.
results : `lsst.pipe.base.Struct`
    Results of the 'detectFootprints' method, containing positive and
    negative footprints (which contain the peak positions that we will
    plot). This is a `Struct` with ``positive`` and ``negative``
    elements that are of type `lsst.afw.detection.FootprintSet`.
convolvedImage : `lsst.afw.image.Image`, optional
    Convolved image used for thresholding.

Definition at line 315 of file detection.py.

315 def display(self, exposure, results, convolvedImage=None):
316 """Display detections if so configured
317
318 Displays the ``exposure`` in frame 0, overlays the detection peaks.
319
320 Requires that ``lsstDebug`` has been set up correctly, so that
321 ``lsstDebug.Info("lsst.meas.algorithms.detection")`` evaluates `True`.
322
323 If the ``convolvedImage`` is non-`None` and
324 ``lsstDebug.Info("lsst.meas.algorithms.detection") > 1``, the
325 ``convolvedImage`` will be displayed in frame 1.
326
327 Parameters
328 ----------
329 exposure : `lsst.afw.image.Exposure`
330 Exposure to display, on which will be plotted the detections.
331 results : `lsst.pipe.base.Struct`
332 Results of the 'detectFootprints' method, containing positive and
333 negative footprints (which contain the peak positions that we will
334 plot). This is a `Struct` with ``positive`` and ``negative``
335 elements that are of type `lsst.afw.detection.FootprintSet`.
336 convolvedImage : `lsst.afw.image.Image`, optional
337 Convolved image used for thresholding.
338 """
339 try:
340 import lsstDebug
341 display = lsstDebug.Info(__name__).display
342 except ImportError:
343 try:
344 display
345 except NameError:
346 display = False
347 if not display:
348 return
349
350 afwDisplay.setDefaultMaskTransparency(75)
351
352 disp0 = afwDisplay.Display(frame=0)
353 disp0.mtv(exposure, title="detection")
354
355 def plotPeaks(fps, ctype):
356 if fps is None:
357 return
358 with disp0.Buffering():
359 for fp in fps.getFootprints():
360 for pp in fp.getPeaks():
361 disp0.dot("+", pp.getFx(), pp.getFy(), ctype=ctype)
362 plotPeaks(results.positive, "yellow")
363 plotPeaks(results.negative, "red")
364
365 if convolvedImage and display > 1:
366 disp1 = afwDisplay.Display(frame=1)
367 disp1.mtv(convolvedImage, title="PSF smoothed")
368
369 disp2 = afwDisplay.Display(frame=2)
370 disp2.mtv(afwImage.ImageF(np.sqrt(exposure.variance.array)), title="stddev")
371

◆ finalizeFootprints()

lsst.meas.algorithms.detection.SourceDetectionTask.finalizeFootprints ( self,
mask,
results,
sigma,
factor = 1.0,
factorNeg = None )
Finalize the detected footprints.

Grow the footprints, set the ``DETECTED`` and ``DETECTED_NEGATIVE``
mask planes, and log the results.

``numPos`` (number of positive footprints), ``numPosPeaks`` (number
of positive peaks), ``numNeg`` (number of negative footprints),
``numNegPeaks`` (number of negative peaks) entries are added to the
``results`` struct.

Parameters
----------
mask : `lsst.afw.image.Mask`
    Mask image on which to flag detected pixels.
results : `lsst.pipe.base.Struct`
    Struct of detection results, including ``positive`` and
    ``negative`` entries; modified.
sigma : `float`
    Gaussian sigma of PSF.
factor : `float`
    Multiplier for the configured threshold. Note that this is only
    used here for logging purposes.
factorNeg : `float` or `None`
    Multiplier used for the negative detection polarity threshold.
    If `None`, a factor equal to ``factor`` (i.e. equal to the one used
    for positive detection polarity) is assumed. Note that this is only
    used here for logging purposes.

Definition at line 603 of file detection.py.

603 def finalizeFootprints(self, mask, results, sigma, factor=1.0, factorNeg=None):
604 """Finalize the detected footprints.
605
606 Grow the footprints, set the ``DETECTED`` and ``DETECTED_NEGATIVE``
607 mask planes, and log the results.
608
609 ``numPos`` (number of positive footprints), ``numPosPeaks`` (number
610 of positive peaks), ``numNeg`` (number of negative footprints),
611 ``numNegPeaks`` (number of negative peaks) entries are added to the
612 ``results`` struct.
613
614 Parameters
615 ----------
616 mask : `lsst.afw.image.Mask`
617 Mask image on which to flag detected pixels.
618 results : `lsst.pipe.base.Struct`
619 Struct of detection results, including ``positive`` and
620 ``negative`` entries; modified.
621 sigma : `float`
622 Gaussian sigma of PSF.
623 factor : `float`
624 Multiplier for the configured threshold. Note that this is only
625 used here for logging purposes.
626 factorNeg : `float` or `None`
627 Multiplier used for the negative detection polarity threshold.
628 If `None`, a factor equal to ``factor`` (i.e. equal to the one used
629 for positive detection polarity) is assumed. Note that this is only
630 used here for logging purposes.
631 """
632 factorNeg = factor if factorNeg is None else factorNeg
633 for polarity, maskName in (("positive", "DETECTED"), ("negative", "DETECTED_NEGATIVE")):
634 fpSet = getattr(results, polarity)
635 if fpSet is None:
636 continue
637 if self.config.nSigmaToGrow > 0:
638 nGrow = int((self.config.nSigmaToGrow * sigma) + 0.5)
639 self.metadata["nGrow"] = nGrow
640 if self.config.combinedGrow:
641 fpSet = afwDet.FootprintSet(fpSet, nGrow, self.config.isotropicGrow)
642 else:
643 stencil = (afwGeom.Stencil.CIRCLE if self.config.isotropicGrow else
644 afwGeom.Stencil.MANHATTAN)
645 for fp in fpSet:
646 fp.dilate(nGrow, stencil)
647 fpSet.setMask(mask, maskName)
648 if not self.config.returnOriginalFootprints:
649 setattr(results, polarity, fpSet)
650
651 results.numPos = 0
652 results.numPosPeaks = 0
653 results.numNeg = 0
654 results.numNegPeaks = 0
655 positive = ""
656 negative = ""
657
658 if results.positive is not None:
659 results.numPos = len(results.positive.getFootprints())
660 results.numPosPeaks = sum(len(fp.getPeaks()) for fp in results.positive.getFootprints())
661 positive = " %d positive peaks in %d footprints" % (results.numPosPeaks, results.numPos)
662 if results.negative is not None:
663 results.numNeg = len(results.negative.getFootprints())
664 results.numNegPeaks = sum(len(fp.getPeaks()) for fp in results.negative.getFootprints())
665 negative = " %d negative peaks in %d footprints" % (results.numNegPeaks, results.numNeg)
666
667 self.log.info("Detected%s%s%s to %g +ve and %g -ve %s",
668 positive, " and" if positive and negative else "", negative,
669 self.config.thresholdValue*self.config.includeThresholdMultiplier*factor,
670 self.config.thresholdValue*self.config.includeThresholdMultiplier*factorNeg,
671 "DN" if self.config.thresholdType == "value" else "sigma")
672

◆ getPsf()

lsst.meas.algorithms.detection.SourceDetectionTask.getPsf ( self,
exposure,
sigma = None )
Create a single Gaussian PSF for an exposure.

If ``sigma`` is provided, we make a `~lsst.afw.detection.GaussianPsf`
with that, otherwise use the sigma from the psf of the ``exposure`` to
make the `~lsst.afw.detection.GaussianPsf`.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure from which to retrieve the PSF.
sigma : `float`, optional
    Gaussian sigma to use if provided.

Returns
-------
psf : `lsst.afw.detection.GaussianPsf`
    PSF to use for detection.

Raises
------
RuntimeError
    Raised if ``sigma`` is not provided and ``exposure`` does not
    contain a ``Psf`` object.

Definition at line 441 of file detection.py.

441 def getPsf(self, exposure, sigma=None):
442 """Create a single Gaussian PSF for an exposure.
443
444 If ``sigma`` is provided, we make a `~lsst.afw.detection.GaussianPsf`
445 with that, otherwise use the sigma from the psf of the ``exposure`` to
446 make the `~lsst.afw.detection.GaussianPsf`.
447
448 Parameters
449 ----------
450 exposure : `lsst.afw.image.Exposure`
451 Exposure from which to retrieve the PSF.
452 sigma : `float`, optional
453 Gaussian sigma to use if provided.
454
455 Returns
456 -------
457 psf : `lsst.afw.detection.GaussianPsf`
458 PSF to use for detection.
459
460 Raises
461 ------
462 RuntimeError
463 Raised if ``sigma`` is not provided and ``exposure`` does not
464 contain a ``Psf`` object.
465 """
466 if sigma is None:
467 psf = exposure.getPsf()
468 if psf is None:
469 raise RuntimeError("Unable to determine PSF to use for detection: no sigma provided")
470 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
471 size = self.calculateKernelSize(sigma)
472 psf = afwDet.GaussianPsf(size, size, sigma)
473 return psf
474
A circularly symmetric Gaussian Psf class with no spatial variation, intended mostly for testing purp...
Definition GaussianPsf.h:42

◆ makeThreshold()

lsst.meas.algorithms.detection.SourceDetectionTask.makeThreshold ( self,
image,
thresholdParity,
factor = 1.0 )
Make an afw.detection.Threshold object corresponding to the task's
configuration and the statistics of the given image.

Parameters
----------
image : `afw.image.MaskedImage`
    Image to measure noise statistics from if needed.
thresholdParity: `str`
    One of "positive" or "negative", to set the kind of fluctuations
    the Threshold will detect.
factor : `float`
    Factor by which to multiply the configured detection threshold.
    This is useful for tweaking the detection threshold slightly.

Returns
-------
threshold : `lsst.afw.detection.Threshold`
    Detection threshold.

Definition at line 899 of file detection.py.

899 def makeThreshold(self, image, thresholdParity, factor=1.0):
900 """Make an afw.detection.Threshold object corresponding to the task's
901 configuration and the statistics of the given image.
902
903 Parameters
904 ----------
905 image : `afw.image.MaskedImage`
906 Image to measure noise statistics from if needed.
907 thresholdParity: `str`
908 One of "positive" or "negative", to set the kind of fluctuations
909 the Threshold will detect.
910 factor : `float`
911 Factor by which to multiply the configured detection threshold.
912 This is useful for tweaking the detection threshold slightly.
913
914 Returns
915 -------
916 threshold : `lsst.afw.detection.Threshold`
917 Detection threshold.
918 """
919 parity = False if thresholdParity == "negative" else True
920 thresholdValue = self.config.thresholdValue
921 thresholdType = self.config.thresholdType
922 if self.config.thresholdType == 'stdev':
923 bad = image.getMask().getPlaneBitMask(self.config.statsMask)
925 sctrl.setAndMask(bad)
926 stats = afwMath.makeStatistics(image, afwMath.STDEVCLIP, sctrl)
927 thresholdValue *= stats.getValue(afwMath.STDEVCLIP)
928 thresholdType = 'value'
929
930 threshold = afwDet.createThreshold(thresholdValue*factor, thresholdType, parity)
931 threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier)
932 self.log.debug("Detection threshold: %s", threshold)
933 return threshold
934
Pass parameters to a Statistics object.
Definition Statistics.h:83
Threshold createThreshold(const double value, const std::string type="value", const bool polarity=true)
Factory method for creating Threshold objects.
Definition Threshold.cc:109
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)
Definition Statistics.h:361

◆ reEstimateBackground()

lsst.meas.algorithms.detection.SourceDetectionTask.reEstimateBackground ( self,
maskedImage,
backgrounds,
backgroundToPhotometricRatio = None )
Estimate the background after detection

Parameters
----------
maskedImage : `lsst.afw.image.MaskedImage`
    Image on which to estimate the background.
backgrounds : `lsst.afw.math.BackgroundList`
    List of backgrounds; modified.
backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
    Image to multiply a photometrically-flattened image by to obtain a
    background-flattened image.
    Only used if ``config.doApplyFlatBackgroundRatio`` is ``True``.

Returns
-------
bg : `lsst.afw.math.backgroundMI`
    Empirical background model.

Definition at line 673 of file detection.py.

673 def reEstimateBackground(self, maskedImage, backgrounds, backgroundToPhotometricRatio=None):
674 """Estimate the background after detection
675
676 Parameters
677 ----------
678 maskedImage : `lsst.afw.image.MaskedImage`
679 Image on which to estimate the background.
680 backgrounds : `lsst.afw.math.BackgroundList`
681 List of backgrounds; modified.
682 backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
683 Image to multiply a photometrically-flattened image by to obtain a
684 background-flattened image.
685 Only used if ``config.doApplyFlatBackgroundRatio`` is ``True``.
686
687 Returns
688 -------
689 bg : `lsst.afw.math.backgroundMI`
690 Empirical background model.
691 """
692 with backgroundFlatContext(
693 maskedImage,
694 self.config.doApplyFlatBackgroundRatio,
695 backgroundToPhotometricRatio=backgroundToPhotometricRatio,
696 ):
697 bg = self.background.fitBackground(maskedImage)
698 if self.config.adjustBackground:
699 self.log.warning("Fiddling the background by %g", self.config.adjustBackground)
700 bg += self.config.adjustBackground
701 self.log.info("Resubtracting the background after object detection")
702 maskedImage -= bg.getImageF(self.background.config.algorithm,
703 self.background.config.undersampleStyle)
704
705 actrl = bg.getBackgroundControl().getApproximateControl()
706 backgrounds.append((bg, getattr(afwMath.Interpolate, self.background.config.algorithm),
707 bg.getAsUsedUndersampleStyle(), actrl.getStyle(), actrl.getOrderX(),
708 actrl.getOrderY(), actrl.getWeighting()))
709 return bg
710

◆ removeBadPixels()

lsst.meas.algorithms.detection.SourceDetectionTask.removeBadPixels ( self,
middle )
Set the significance of flagged pixels to zero.

Parameters
----------
middle : `lsst.afw.image.Exposure`
    Score or maximum likelihood difference image.
    The image plane will be modified in place.

Definition at line 831 of file detection.py.

831 def removeBadPixels(self, middle):
832 """Set the significance of flagged pixels to zero.
833
834 Parameters
835 ----------
836 middle : `lsst.afw.image.Exposure`
837 Score or maximum likelihood difference image.
838 The image plane will be modified in place.
839 """
840 badPixelMask = middle.mask.getPlaneBitMask(self.config.excludeMaskPlanes)
841 badPixels = middle.mask.array & badPixelMask > 0
842 middle.image.array[badPixels] = 0
843

◆ run()

lsst.meas.algorithms.detection.SourceDetectionTask.run ( self,
table,
exposure,
doSmooth = True,
sigma = None,
clearMask = True,
expId = None,
background = None,
backgroundToPhotometricRatio = None )
Detect sources and return catalog(s) of detections.

    Parameters
    ----------
    table : `lsst.afw.table.SourceTable`
        Table object that will be used to create the SourceCatalog.
    exposure : `lsst.afw.image.Exposure`
        Exposure to process; DETECTED mask plane will be set in-place.
    doSmooth : `bool`, optional
        If True, smooth the image before detection using a Gaussian of width
        ``sigma``, or the measured PSF width. Set to False when running on
        e.g. a pre-convolved image, or a mask plane.
    sigma : `float`, optional
        Sigma of PSF (pixels); used for smoothing and to grow detections;
        if None then measure the sigma of the PSF of the exposure
    clearMask : `bool`, optional
        Clear DETECTED{,_NEGATIVE} planes before running detection.
    expId : `int`, optional
        Exposure identifier; unused by this implementation, but used for
        RNG seed by subclasses.
    background : `lsst.afw.math.BackgroundList`, optional
        Background that was already subtracted from the exposure; will be
        modified in-place if ``reEstimateBackground=True``.
    backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
        Image to convert photometric-flattened image to
        background-flattened image if ``reEstimateBackground=True`` and
        exposure has been photometric-flattened.

    Returns
    -------
    result : `lsst.pipe.base.Struct`
        The `~lsst.pipe.base.Struct` contains:

        ``sources``
            Detected sources on the exposure.
            (`lsst.afw.table.SourceCatalog`)
        ``positive``
            Positive polarity footprints.
            (`lsst.afw.detection.FootprintSet` or `None`)
        ``negative``
            Negative polarity footprints.
            (`lsst.afw.detection.FootprintSet` or `None`)
        ``numPos``
            Number of footprints in positive or 0 if detection polarity was
            negative. (`int`)
        ``numNeg``
            Number of footprints in negative or 0 if detection polarity was
            positive. (`int`)
        ``background``
            Re-estimated background. `None` if
            ``reEstimateBackground==False``.
            (`lsst.afw.math.BackgroundList`)
        ``factor``
            Multiplication factor applied to the configured detection
            threshold. (`float`)

    Raises
    ------
    ValueError
        Raised if flags.negative is needed, but isn't in table's schema.
    lsst.pipe.base.TaskError
        Raised if sigma=None, doSmooth=True and the exposure has no PSF.

    Notes
    -----
    If you want to avoid dealing with Sources and Tables, you can use
    `detectFootprints()` to just get the
    `~lsst.afw.detection.FootprintSet`\s.

Definition at line 227 of file detection.py.

228 background=None, backgroundToPhotometricRatio=None):
229 r"""Detect sources and return catalog(s) of detections.
230
231 Parameters
232 ----------
233 table : `lsst.afw.table.SourceTable`
234 Table object that will be used to create the SourceCatalog.
235 exposure : `lsst.afw.image.Exposure`
236 Exposure to process; DETECTED mask plane will be set in-place.
237 doSmooth : `bool`, optional
238 If True, smooth the image before detection using a Gaussian of width
239 ``sigma``, or the measured PSF width. Set to False when running on
240 e.g. a pre-convolved image, or a mask plane.
241 sigma : `float`, optional
242 Sigma of PSF (pixels); used for smoothing and to grow detections;
243 if None then measure the sigma of the PSF of the exposure
244 clearMask : `bool`, optional
245 Clear DETECTED{,_NEGATIVE} planes before running detection.
246 expId : `int`, optional
247 Exposure identifier; unused by this implementation, but used for
248 RNG seed by subclasses.
249 background : `lsst.afw.math.BackgroundList`, optional
250 Background that was already subtracted from the exposure; will be
251 modified in-place if ``reEstimateBackground=True``.
252 backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
253 Image to convert photometric-flattened image to
254 background-flattened image if ``reEstimateBackground=True`` and
255 exposure has been photometric-flattened.
256
257 Returns
258 -------
259 result : `lsst.pipe.base.Struct`
260 The `~lsst.pipe.base.Struct` contains:
261
262 ``sources``
263 Detected sources on the exposure.
264 (`lsst.afw.table.SourceCatalog`)
265 ``positive``
266 Positive polarity footprints.
267 (`lsst.afw.detection.FootprintSet` or `None`)
268 ``negative``
269 Negative polarity footprints.
270 (`lsst.afw.detection.FootprintSet` or `None`)
271 ``numPos``
272 Number of footprints in positive or 0 if detection polarity was
273 negative. (`int`)
274 ``numNeg``
275 Number of footprints in negative or 0 if detection polarity was
276 positive. (`int`)
277 ``background``
278 Re-estimated background. `None` if
279 ``reEstimateBackground==False``.
280 (`lsst.afw.math.BackgroundList`)
281 ``factor``
282 Multiplication factor applied to the configured detection
283 threshold. (`float`)
284
285 Raises
286 ------
287 ValueError
288 Raised if flags.negative is needed, but isn't in table's schema.
289 lsst.pipe.base.TaskError
290 Raised if sigma=None, doSmooth=True and the exposure has no PSF.
291
292 Notes
293 -----
294 If you want to avoid dealing with Sources and Tables, you can use
295 `detectFootprints()` to just get the
296 `~lsst.afw.detection.FootprintSet`\s.
297 """
298 if self.negativeFlagKey is not None and self.negativeFlagKey not in table.getSchema():
299 raise ValueError("Table has incorrect Schema")
300 results = self.detectFootprints(exposure=exposure, doSmooth=doSmooth, sigma=sigma,
301 clearMask=clearMask, expId=expId, background=background,
302 backgroundToPhotometricRatio=backgroundToPhotometricRatio)
303 sources = afwTable.SourceCatalog(table)
304 sources.reserve(results.numPos + results.numNeg)
305 if results.negative:
306 results.negative.makeSources(sources)
307 if self.negativeFlagKey:
308 for record in sources:
309 record.set(self.negativeFlagKey, True)
310 if results.positive:
311 results.positive.makeSources(sources)
312 results.sources = sources
313 return results
314

◆ setEdgeBits()

lsst.meas.algorithms.detection.SourceDetectionTask.setEdgeBits ( maskedImage,
goodBBox,
edgeBitmask )
static
Set the edgeBitmask bits for all of maskedImage outside goodBBox

Parameters
----------
maskedImage : `lsst.afw.image.MaskedImage`
    Image on which to set edge bits in the mask.
goodBBox : `lsst.geom.Box2I`
    Bounding box of good pixels, in ``LOCAL`` coordinates.
edgeBitmask : `lsst.afw.image.MaskPixel`
    Bit mask to OR with the existing mask bits in the region
    outside ``goodBBox``.

Definition at line 978 of file detection.py.

978 def setEdgeBits(maskedImage, goodBBox, edgeBitmask):
979 """Set the edgeBitmask bits for all of maskedImage outside goodBBox
980
981 Parameters
982 ----------
983 maskedImage : `lsst.afw.image.MaskedImage`
984 Image on which to set edge bits in the mask.
985 goodBBox : `lsst.geom.Box2I`
986 Bounding box of good pixels, in ``LOCAL`` coordinates.
987 edgeBitmask : `lsst.afw.image.MaskPixel`
988 Bit mask to OR with the existing mask bits in the region
989 outside ``goodBBox``.
990 """
991 msk = maskedImage.getMask()
992
993 mx0, my0 = maskedImage.getXY0()
994 for x0, y0, w, h in ([0, 0,
995 msk.getWidth(), goodBBox.getBeginY() - my0],
996 [0, goodBBox.getEndY() - my0, msk.getWidth(),
997 maskedImage.getHeight() - (goodBBox.getEndY() - my0)],
998 [0, 0,
999 goodBBox.getBeginX() - mx0, msk.getHeight()],
1000 [goodBBox.getEndX() - mx0, 0,
1001 maskedImage.getWidth() - (goodBBox.getEndX() - mx0), msk.getHeight()],
1002 ):
1003 edgeMask = msk.Factory(msk, lsst.geom.BoxI(lsst.geom.PointI(x0, y0),
1004 lsst.geom.ExtentI(w, h)), afwImage.LOCAL)
1005 edgeMask |= edgeBitmask
1006
An integer coordinate rectangle.
Definition Box.h:55

◆ setPeakSignificance()

lsst.meas.algorithms.detection.SourceDetectionTask.setPeakSignificance ( self,
exposure,
footprints,
threshold,
negative = False )
Set the significance of each detected peak to the pixel value divided
by the appropriate standard-deviation for ``config.thresholdType``.

Only sets significance for "stdev" and "pixel_stdev" thresholdTypes;
we leave it undefined for "value" and "variance" as it does not have a
well-defined meaning in those cases.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure that footprints were detected on, likely the convolved,
    local background-subtracted image.
footprints : `lsst.afw.detection.FootprintSet`
    Footprints detected on the image.
threshold : `lsst.afw.detection.Threshold`
    Threshold used to find footprints.
negative : `bool`, optional
    Are we calculating for negative sources?

Definition at line 844 of file detection.py.

844 def setPeakSignificance(self, exposure, footprints, threshold, negative=False):
845 """Set the significance of each detected peak to the pixel value divided
846 by the appropriate standard-deviation for ``config.thresholdType``.
847
848 Only sets significance for "stdev" and "pixel_stdev" thresholdTypes;
849 we leave it undefined for "value" and "variance" as it does not have a
850 well-defined meaning in those cases.
851
852 Parameters
853 ----------
854 exposure : `lsst.afw.image.Exposure`
855 Exposure that footprints were detected on, likely the convolved,
856 local background-subtracted image.
857 footprints : `lsst.afw.detection.FootprintSet`
858 Footprints detected on the image.
859 threshold : `lsst.afw.detection.Threshold`
860 Threshold used to find footprints.
861 negative : `bool`, optional
862 Are we calculating for negative sources?
863 """
864 if footprints is None or footprints.getFootprints() == []:
865 return footprints
866 polarity = -1 if negative else 1
867
868 # All incoming footprints have the same schema.
869 mapper = afwTable.SchemaMapper(footprints.getFootprints()[0].peaks.schema)
870 mapper.addMinimalSchema(footprints.getFootprints()[0].peaks.schema)
871 mapper.addOutputField("significance", type=float,
872 doc="Ratio of peak value to configured standard deviation.")
873
874 # Copy the old peaks to the new ones with a significance field.
875 # Do this independent of the threshold type, so we always have a
876 # significance field.
877 newFootprints = afwDet.FootprintSet(footprints)
878 for old, new in zip(footprints.getFootprints(), newFootprints.getFootprints()):
879 newPeaks = afwDet.PeakCatalog(mapper.getOutputSchema())
880 newPeaks.extend(old.peaks, mapper=mapper)
881 new.getPeaks().clear()
882 new.setPeakCatalog(newPeaks)
883
884 # Compute the significance values.
885 if self.config.thresholdType == "pixel_stdev":
886 for footprint in newFootprints.getFootprints():
887 footprint.updatePeakSignificance(exposure.variance, polarity)
888 elif self.config.thresholdType == "stdev":
889 sigma = threshold.getValue() / self.config.thresholdValue
890 for footprint in newFootprints.getFootprints():
891 footprint.updatePeakSignificance(polarity*sigma)
892 else:
893 for footprint in newFootprints.getFootprints():
894 for peak in footprint.peaks:
895 peak["significance"] = 0
896
897 return newFootprints
898
A mapping between the keys of two Schemas, used to copy data between them.

◆ tempWideBackgroundContext()

lsst.meas.algorithms.detection.SourceDetectionTask.tempWideBackgroundContext ( self,
exposure )
Context manager for removing wide (large-scale) background

Removing a wide (large-scale) background helps to suppress the
detection of large footprints that may overwhelm the deblender.
It does, however, set a limit on the maximum scale of objects.

The background that we remove will be restored upon exit from
the context manager.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure on which to remove large-scale background.

Returns
-------
context : context manager
    Context manager that will ensure the temporary wide background
    is restored.

Definition at line 1008 of file detection.py.

1008 def tempWideBackgroundContext(self, exposure):
1009 """Context manager for removing wide (large-scale) background
1010
1011 Removing a wide (large-scale) background helps to suppress the
1012 detection of large footprints that may overwhelm the deblender.
1013 It does, however, set a limit on the maximum scale of objects.
1014
1015 The background that we remove will be restored upon exit from
1016 the context manager.
1017
1018 Parameters
1019 ----------
1020 exposure : `lsst.afw.image.Exposure`
1021 Exposure on which to remove large-scale background.
1022
1023 Returns
1024 -------
1025 context : context manager
1026 Context manager that will ensure the temporary wide background
1027 is restored.
1028 """
1029 doTempWideBackground = self.config.doTempWideBackground
1030 if doTempWideBackground:
1031 self.log.info("Applying temporary wide background subtraction")
1032 original = exposure.maskedImage.image.array[:].copy()
1033 self.tempWideBackground.run(exposure).background
1034 # Remove NO_DATA regions (e.g., edge of the field-of-view); these can cause detections after
1035 # subtraction because of extrapolation of the background model into areas with no constraints.
1036 image = exposure.maskedImage.image
1037 mask = exposure.maskedImage.mask
1038 noData = mask.array & mask.getPlaneBitMask("NO_DATA") > 0
1039 isGood = mask.array & mask.getPlaneBitMask(self.config.statsMask) == 0
1040 image.array[noData] = np.median(image.array[~noData & isGood])
1041 try:
1042 yield
1043 finally:
1044 if doTempWideBackground:
1045 exposure.maskedImage.image.array[:] = original
1046
1047

◆ updatePeaks()

lsst.meas.algorithms.detection.SourceDetectionTask.updatePeaks ( self,
fpSet,
image,
threshold )
Update the Peaks in a FootprintSet by detecting new Footprints and
Peaks in an image and using the new Peaks instead of the old ones.

Parameters
----------
fpSet : `afw.detection.FootprintSet`
    Set of Footprints whose Peaks should be updated.
image : `afw.image.MaskedImage`
    Image to detect new Footprints and Peak in.
threshold : `afw.detection.Threshold`
    Threshold object for detection.

Input Footprints with fewer Peaks than self.config.nPeaksMaxSimple
are not modified, and if no new Peaks are detected in an input
Footprint, the brightest original Peak in that Footprint is kept.

Definition at line 935 of file detection.py.

935 def updatePeaks(self, fpSet, image, threshold):
936 """Update the Peaks in a FootprintSet by detecting new Footprints and
937 Peaks in an image and using the new Peaks instead of the old ones.
938
939 Parameters
940 ----------
941 fpSet : `afw.detection.FootprintSet`
942 Set of Footprints whose Peaks should be updated.
943 image : `afw.image.MaskedImage`
944 Image to detect new Footprints and Peak in.
945 threshold : `afw.detection.Threshold`
946 Threshold object for detection.
947
948 Input Footprints with fewer Peaks than self.config.nPeaksMaxSimple
949 are not modified, and if no new Peaks are detected in an input
950 Footprint, the brightest original Peak in that Footprint is kept.
951 """
952 for footprint in fpSet.getFootprints():
953 oldPeaks = footprint.getPeaks()
954 if len(oldPeaks) <= self.config.nPeaksMaxSimple:
955 continue
956 # We detect a new FootprintSet within each non-simple Footprint's
957 # bbox to avoid a big O(N^2) comparison between the two sets of
958 # Footprints.
959 sub = image.Factory(image, footprint.getBBox())
960 fpSetForPeaks = afwDet.FootprintSet(
961 sub,
962 threshold,
963 "", # don't set a mask plane
964 self.config.minPixels
965 )
966 newPeaks = afwDet.PeakCatalog(oldPeaks.getTable())
967 for fpForPeaks in fpSetForPeaks.getFootprints():
968 for peak in fpForPeaks.getPeaks():
969 if footprint.contains(peak.getI()):
970 newPeaks.append(peak)
971 if len(newPeaks) > 0:
972 del oldPeaks[:]
973 oldPeaks.extend(newPeaks)
974 else:
975 del oldPeaks[1:]
976

Member Data Documentation

◆ _DefaultName

str lsst.meas.algorithms.detection.SourceDetectionTask._DefaultName = "sourceDetection"
staticprotected

Definition at line 205 of file detection.py.

◆ ConfigClass

lsst.meas.algorithms.detection.SourceDetectionTask.ConfigClass = SourceDetectionConfig
static

Definition at line 204 of file detection.py.

◆ negativeFlagKey

lsst.meas.algorithms.detection.SourceDetectionTask.negativeFlagKey
Initial value:
= schema.addField(
"is_negative", type="Flag",
doc="Set if source peak was detected as negative."
)

Definition at line 210 of file detection.py.


The documentation for this class was generated from the following file: