LSST Applications g00274db5b6+edbf708997,g00d0e8bbd7+edbf708997,g199a45376c+5137f08352,g1fd858c14a+1d4b6db739,g262e1987ae+f4d9505c4f,g29ae962dfc+7156fb1a53,g2cef7863aa+73c82f25e4,g35bb328faa+edbf708997,g3e17d7035e+5b3adc59f5,g3fd5ace14f+852fa6fbcb,g47891489e3+6dc8069a4c,g53246c7159+edbf708997,g64539dfbff+9f17e571f4,g67b6fd64d1+6dc8069a4c,g74acd417e5+ae494d68d9,g786e29fd12+af89c03590,g7ae74a0b1c+a25e60b391,g7aefaa3e3d+536efcc10a,g7cc15d900a+d121454f8d,g87389fa792+a4172ec7da,g89139ef638+6dc8069a4c,g8d7436a09f+28c28d8d6d,g8ea07a8fe4+db21c37724,g92c671f44c+9f17e571f4,g98df359435+b2e6376b13,g99af87f6a8+b0f4ad7b8d,gac66b60396+966efe6077,gb88ae4c679+7dec8f19df,gbaa8f7a6c5+38b34f4976,gbf99507273+edbf708997,gc24b5d6ed1+9f17e571f4,gca7fc764a6+6dc8069a4c,gcc769fe2a4+97d0256649,gd7ef33dd92+6dc8069a4c,gdab6d2f7ff+ae494d68d9,gdbb4c4dda9+9f17e571f4,ge410e46f29+6dc8069a4c,geaed405ab2+e194be0d2b,w.2025.47
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, growOverride=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 204 of file detection.py.

Constructor & Destructor Documentation

◆ __init__()

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

Definition at line 234 of file detection.py.

234 def __init__(self, schema=None, **kwds):
235 pipeBase.Task.__init__(self, **kwds)
236 if schema is not None and self.config.thresholdPolarity == "both":
237 self.negativeFlagKey = schema.addField(
238 "is_negative", type="Flag",
239 doc="Set if source peak was detected as negative."
240 )
241 else:
242 if self.config.thresholdPolarity == "both":
243 self.log.warning("Detection polarity set to 'both', but no flag will be "
244 "set to distinguish between positive and negative detections")
245 self.negativeFlagKey = None
246 if self.config.reEstimateBackground:
247 self.makeSubtask("background")
248 if self.config.doTempLocalBackground:
249 self.makeSubtask("tempLocalBackground")
250 if self.config.doTempWideBackground:
251 self.makeSubtask("tempWideBackground")
252

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 399 of file detection.py.

399 def applyTempLocalBackground(self, exposure, middle, results):
400 """Apply a temporary local background subtraction
401
402 This temporary local background serves to suppress noise fluctuations
403 in the wings of bright objects.
404
405 Peaks in the footprints will be updated.
406
407 Parameters
408 ----------
409 exposure : `lsst.afw.image.Exposure`
410 Exposure for which to fit local background.
411 middle : `lsst.afw.image.MaskedImage`
412 Convolved image on which detection will be performed
413 (typically smaller than ``exposure`` because the
414 half-kernel has been removed around the edges).
415 results : `lsst.pipe.base.Struct`
416 Results of the 'detectFootprints' method, containing positive and
417 negative footprints (which contain the peak positions that we will
418 plot). This is a `Struct` with ``positive`` and ``negative``
419 elements that are of type `lsst.afw.detection.FootprintSet`.
420 """
421 # Subtract the local background from the smoothed image. Since we
422 # never use the smoothed again we don't need to worry about adding
423 # it back in.
424 bg = self.tempLocalBackground.fitBackground(exposure.getMaskedImage())
425 bgImage = bg.getImageF(self.tempLocalBackground.config.algorithm,
426 self.tempLocalBackground.config.undersampleStyle)
427 middle -= bgImage.Factory(bgImage, middle.getBBox())
428 if self.config.thresholdPolarity != "negative":
429 results.positiveThreshold = self.makeThreshold(middle, "positive")
430 self.updatePeaks(results.positive, middle, results.positiveThreshold)
431 if self.config.thresholdPolarity != "positive":
432 results.negativeThreshold = self.makeThreshold(middle, "negative")
433 self.updatePeaks(results.negative, middle, results.negativeThreshold)
434

◆ 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 566 of file detection.py.

566 def applyThreshold(self, middle, bbox, factor=1.0, factorNeg=None):
567 r"""Apply thresholds to the convolved image
568
569 Identifies `~lsst.afw.detection.Footprint`\s, both positive and negative.
570 The threshold can be modified by the provided multiplication
571 ``factor``.
572
573 Parameters
574 ----------
575 middle : `lsst.afw.image.MaskedImage`
576 Convolved image to threshold.
577 bbox : `lsst.geom.Box2I`
578 Bounding box of unconvolved image.
579 factor : `float`
580 Multiplier for the configured threshold.
581 factorNeg : `float` or `None`
582 Multiplier for the configured threshold for negative detection polarity.
583 If `None`, will be set equal to ``factor`` (i.e. equal to the factor used
584 for positive detection polarity).
585
586 Returns
587 -------
588 results : `lsst.pipe.base.Struct`
589 The `~lsst.pipe.base.Struct` contains:
590
591 ``positive``
592 Positive detection footprints, if configured.
593 (`lsst.afw.detection.FootprintSet` or `None`)
594 ``negative``
595 Negative detection footprints, if configured.
596 (`lsst.afw.detection.FootprintSet` or `None`)
597 ``factor``
598 Multiplier for the configured threshold.
599 (`float`)
600 ``factorNeg``
601 Multiplier for the configured threshold for negative detection polarity.
602 (`float`)
603 """
604 if factorNeg is None:
605 factorNeg = factor
606 self.log.info("Setting factor for negative detections equal to that for positive "
607 "detections: %f", factor)
608 results = pipeBase.Struct(positive=None, negative=None, factor=factor, factorNeg=factorNeg,
609 positiveThreshold=None, negativeThreshold=None)
610 # Detect the Footprints (peaks may be replaced if doTempLocalBackground)
611 if self.config.reEstimateBackground or self.config.thresholdPolarity != "negative":
612 results.positiveThreshold = self.makeThreshold(middle, "positive", factor=factor)
613 results.positive = afwDet.FootprintSet(
614 middle,
615 results.positiveThreshold,
616 "DETECTED",
617 self.config.minPixels
618 )
619 results.positive.setRegion(bbox)
620 if self.config.reEstimateBackground or self.config.thresholdPolarity != "positive":
621 results.negativeThreshold = self.makeThreshold(middle, "negative", factor=factorNeg)
622 results.negative = afwDet.FootprintSet(
623 middle,
624 results.negativeThreshold,
625 "DETECTED_NEGATIVE",
626 self.config.minPixels
627 )
628 results.negative.setRegion(bbox)
629
630 return results
631
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 448 of file detection.py.

448 def calculateKernelSize(self, sigma):
449 """Calculate the size of the smoothing kernel.
450
451 Uses the ``nSigmaForKernel`` configuration parameter. Note
452 that that is the full width of the kernel bounding box
453 (so a value of 7 means 3.5 sigma on either side of center).
454 The value will be rounded up to the nearest odd integer.
455
456 Parameters
457 ----------
458 sigma : `float`
459 Gaussian sigma of smoothing kernel.
460
461 Returns
462 -------
463 size : `int`
464 Size of the smoothing kernel.
465 """
466 return (int(sigma * self.config.nSigmaForKernel + 0.5)//2)*2 + 1 # make sure it is odd
467

◆ 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 435 of file detection.py.

435 def clearMask(self, mask):
436 """Clear the DETECTED and DETECTED_NEGATIVE mask planes.
437
438 Removes any previous detection mask in preparation for a new
439 detection pass.
440
441 Parameters
442 ----------
443 mask : `lsst.afw.image.Mask`
444 Mask to be cleared.
445 """
446 mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask("DETECTED_NEGATIVE"))
447

◆ 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 744 of file detection.py.

744 def clearUnwantedResults(self, mask, results):
745 """Clear unwanted results from the Struct of results
746
747 If we specifically want only positive or only negative detections,
748 drop the ones we don't want, and its associated mask plane.
749
750 Parameters
751 ----------
752 mask : `lsst.afw.image.Mask`
753 Mask image.
754 results : `lsst.pipe.base.Struct`
755 Detection results, with ``positive`` and ``negative`` elements;
756 modified.
757 """
758 if self.config.thresholdPolarity == "positive":
759 if self.config.reEstimateBackground:
760 mask &= ~mask.getPlaneBitMask("DETECTED_NEGATIVE")
761 results.negative = None
762 elif self.config.thresholdPolarity == "negative":
763 if self.config.reEstimateBackground:
764 mask &= ~mask.getPlaneBitMask("DETECTED")
765 results.positive = None
766

◆ 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 504 of file detection.py.

504 def convolveImage(self, maskedImage, psf, doSmooth=True):
505 """Convolve the image with the PSF.
506
507 We convolve the image with a Gaussian approximation to the PSF,
508 because this is separable and therefore fast. It's technically a
509 correlation rather than a convolution, but since we use a symmetric
510 Gaussian there's no difference.
511
512 The convolution can be disabled with ``doSmooth=False``. If we do
513 convolve, we mask the edges as ``EDGE`` and return the convolved image
514 with the edges removed. This is because we can't convolve the edges
515 because the kernel would extend off the image.
516
517 Parameters
518 ----------
519 maskedImage : `lsst.afw.image.MaskedImage`
520 Image to convolve.
521 psf : `lsst.afw.detection.Psf`
522 PSF to convolve with (actually with a Gaussian approximation
523 to it).
524 doSmooth : `bool`
525 Actually do the convolution? Set to False when running on
526 e.g. a pre-convolved image, or a mask plane.
527
528 Returns
529 -------
530 results : `lsst.pipe.base.Struct`
531 The `~lsst.pipe.base.Struct` contains:
532
533 ``middle``
534 Convolved image, without the edges. (`lsst.afw.image.MaskedImage`)
535 ``sigma``
536 Gaussian sigma used for the convolution. (`float`)
537 """
538 self.metadata["doSmooth"] = doSmooth
539 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
540 self.metadata["sigma"] = sigma
541
542 if not doSmooth:
543 middle = maskedImage.Factory(maskedImage, deep=True)
544 return pipeBase.Struct(middle=middle, sigma=sigma)
545
546 # Smooth using a Gaussian (which is separable, hence fast) of width sigma
547 # Make a SingleGaussian (separable) kernel with the 'sigma'
548 kWidth = self.calculateKernelSize(sigma)
549 self.metadata["smoothingKernelWidth"] = kWidth
550 gaussFunc = afwMath.GaussianFunction1D(sigma)
551 gaussKernel = afwMath.SeparableKernel(kWidth, kWidth, gaussFunc, gaussFunc)
552
553 convolvedImage = maskedImage.Factory(maskedImage.getBBox())
554
555 afwMath.convolve(convolvedImage, maskedImage, gaussKernel, afwMath.ConvolutionControl())
556
557 # Only search psf-smoothed part of frame
558 goodBBox = gaussKernel.shrinkBBox(convolvedImage.getBBox())
559 middle = convolvedImage.Factory(convolvedImage, goodBBox, afwImage.PARENT, False)
560
561 # Mark the parts of the image outside goodBBox as EDGE
562 self.setEdgeBits(maskedImage, goodBBox, maskedImage.getMask().getPlaneBitMask("EDGE"))
563
564 return pipeBase.Struct(middle=middle, sigma=sigma)
565
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 768 of file detection.py.

769 background=None, backgroundToPhotometricRatio=None):
770 """Detect footprints on an exposure.
771
772 Parameters
773 ----------
774 exposure : `lsst.afw.image.Exposure`
775 Exposure to process; DETECTED{,_NEGATIVE} mask plane will be
776 set in-place.
777 doSmooth : `bool`, optional
778 If True, smooth the image before detection using a Gaussian
779 of width ``sigma``, or the measured PSF width of ``exposure``.
780 Set to False when running on e.g. a pre-convolved image, or a mask
781 plane.
782 sigma : `float`, optional
783 Gaussian Sigma of PSF (pixels); used for smoothing and to grow
784 detections; if `None` then measure the sigma of the PSF of the
785 ``exposure``.
786 clearMask : `bool`, optional
787 Clear both DETECTED and DETECTED_NEGATIVE planes before running
788 detection.
789 expId : `dict`, optional
790 Exposure identifier; unused by this implementation, but used for
791 RNG seed by subclasses.
792 background : `lsst.afw.math.BackgroundList`, optional
793 Background that was already subtracted from the exposure; will be
794 modified in-place if ``reEstimateBackground=True``.
795 backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
796 Image to convert photometric-flattened image to
797 background-flattened image if ``reEstimateBackground=True`` and
798 exposure has been photometric-flattened.
799
800 Returns
801 -------
802 results : `lsst.pipe.base.Struct`
803 A `~lsst.pipe.base.Struct` containing:
804
805 ``positive``
806 Positive polarity footprints.
807 (`lsst.afw.detection.FootprintSet` or `None`)
808 ``negative``
809 Negative polarity footprints.
810 (`lsst.afw.detection.FootprintSet` or `None`)
811 ``numPos``
812 Number of footprints in positive or 0 if detection polarity was
813 negative. (`int`)
814 ``numNeg``
815 Number of footprints in negative or 0 if detection polarity was
816 positive. (`int`)
817 ``background``
818 Re-estimated background. `None` or the input ``background``
819 if ``reEstimateBackground==False``.
820 (`lsst.afw.math.BackgroundList`)
821 ``factor``
822 Multiplication factor applied to the configured detection
823 threshold. (`float`)
824 """
825 maskedImage = exposure.maskedImage
826
827 if clearMask:
828 self.clearMask(maskedImage.getMask())
829
830 psf = self.getPsf(exposure, sigma=sigma)
831 with self.tempWideBackgroundContext(exposure):
832 convolveResults = self.convolveImage(maskedImage, psf, doSmooth=doSmooth)
833 middle = convolveResults.middle
834 sigma = convolveResults.sigma
835 self.removeBadPixels(middle)
836
837 results = self.applyThreshold(middle, maskedImage.getBBox())
838 results.background = background if background is not None else afwMath.BackgroundList()
839
840 if self.config.doTempLocalBackground:
841 self.applyTempLocalBackground(exposure, middle, results)
842 self.finalizeFootprints(maskedImage.mask, results, sigma)
843
844 # Compute the significance of peaks after the peaks have been
845 # finalized and after local background correction/updatePeaks, so
846 # that the significance represents the "final" detection S/N.
847 results.positive = self.setPeakSignificance(middle, results.positive, results.positiveThreshold)
848 results.negative = self.setPeakSignificance(middle, results.negative, results.negativeThreshold,
849 negative=True)
850
851 if self.config.reEstimateBackground:
852 self.reEstimateBackground(
853 maskedImage,
854 results.background,
855 backgroundToPhotometricRatio=backgroundToPhotometricRatio,
856 )
857
858 self.clearUnwantedResults(maskedImage.getMask(), results)
859
860 self.display(exposure, results, middle)
861
862 return results
863

◆ 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 342 of file detection.py.

342 def display(self, exposure, results, convolvedImage=None):
343 """Display detections if so configured
344
345 Displays the ``exposure`` in frame 0, overlays the detection peaks.
346
347 Requires that ``lsstDebug`` has been set up correctly, so that
348 ``lsstDebug.Info("lsst.meas.algorithms.detection")`` evaluates `True`.
349
350 If the ``convolvedImage`` is non-`None` and
351 ``lsstDebug.Info("lsst.meas.algorithms.detection") > 1``, the
352 ``convolvedImage`` will be displayed in frame 1.
353
354 Parameters
355 ----------
356 exposure : `lsst.afw.image.Exposure`
357 Exposure to display, on which will be plotted the detections.
358 results : `lsst.pipe.base.Struct`
359 Results of the 'detectFootprints' method, containing positive and
360 negative footprints (which contain the peak positions that we will
361 plot). This is a `Struct` with ``positive`` and ``negative``
362 elements that are of type `lsst.afw.detection.FootprintSet`.
363 convolvedImage : `lsst.afw.image.Image`, optional
364 Convolved image used for thresholding.
365 """
366 try:
367 import lsstDebug
368 display = lsstDebug.Info(__name__).display
369 except ImportError:
370 try:
371 display
372 except NameError:
373 display = False
374 if not display:
375 return
376
377 afwDisplay.setDefaultMaskTransparency(75)
378
379 disp0 = afwDisplay.Display(frame=0)
380 disp0.mtv(exposure, title="detection")
381
382 def plotPeaks(fps, ctype):
383 if fps is None:
384 return
385 with disp0.Buffering():
386 for fp in fps.getFootprints():
387 for pp in fp.getPeaks():
388 disp0.dot("+", pp.getFx(), pp.getFy(), ctype=ctype)
389 plotPeaks(results.positive, "yellow")
390 plotPeaks(results.negative, "red")
391
392 if convolvedImage and display > 1:
393 disp1 = afwDisplay.Display(frame=1)
394 disp1.mtv(convolvedImage, title="PSF smoothed")
395
396 disp2 = afwDisplay.Display(frame=2)
397 disp2.mtv(afwImage.ImageF(np.sqrt(exposure.variance.array)), title="stddev")
398

◆ finalizeFootprints()

lsst.meas.algorithms.detection.SourceDetectionTask.finalizeFootprints ( self,
mask,
results,
sigma,
factor = 1.0,
factorNeg = None,
growOverride = 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 632 of file detection.py.

632 def finalizeFootprints(self, mask, results, sigma, factor=1.0, factorNeg=None, growOverride=None):
633 """Finalize the detected footprints.
634
635 Grow the footprints, set the ``DETECTED`` and ``DETECTED_NEGATIVE``
636 mask planes, and log the results.
637
638 ``numPos`` (number of positive footprints), ``numPosPeaks`` (number
639 of positive peaks), ``numNeg`` (number of negative footprints),
640 ``numNegPeaks`` (number of negative peaks) entries are added to the
641 ``results`` struct.
642
643 Parameters
644 ----------
645 mask : `lsst.afw.image.Mask`
646 Mask image on which to flag detected pixels.
647 results : `lsst.pipe.base.Struct`
648 Struct of detection results, including ``positive`` and
649 ``negative`` entries; modified.
650 sigma : `float`
651 Gaussian sigma of PSF.
652 factor : `float`
653 Multiplier for the configured threshold. Note that this is only
654 used here for logging purposes.
655 factorNeg : `float` or `None`
656 Multiplier used for the negative detection polarity threshold.
657 If `None`, a factor equal to ``factor`` (i.e. equal to the one used
658 for positive detection polarity) is assumed. Note that this is only
659 used here for logging purposes.
660 """
661 if growOverride is not None:
662 self.log.warning("config.nSigmaToGrow is set to %.2f, but the caller has set "
663 "growOverride to %.2f, so the footprints will be grown by "
664 "%.2f sigma.", self.config.nSigmaToGrow, growOverride, growOverride)
665 factorNeg = factor if factorNeg is None else factorNeg
666 for polarity, maskName in (("positive", "DETECTED"), ("negative", "DETECTED_NEGATIVE")):
667 fpSet = getattr(results, polarity)
668 if fpSet is None:
669 continue
670 if self.config.nSigmaToGrow > 0:
671 nGrow = int((self.config.nSigmaToGrow * sigma) + 0.5)
672 self.metadata["nGrow"] = nGrow
673 if self.config.combinedGrow:
674 fpSet = afwDet.FootprintSet(fpSet, nGrow, self.config.isotropicGrow)
675 else:
676 stencil = (afwGeom.Stencil.CIRCLE if self.config.isotropicGrow else
677 afwGeom.Stencil.MANHATTAN)
678 for fp in fpSet:
679 fp.dilate(nGrow, stencil)
680 fpSet.setMask(mask, maskName)
681 if not self.config.returnOriginalFootprints:
682 setattr(results, polarity, fpSet)
683
684 results.numPos = 0
685 results.numPosPeaks = 0
686 results.numNeg = 0
687 results.numNegPeaks = 0
688 positive = ""
689 negative = ""
690
691 if results.positive is not None:
692 results.numPos = len(results.positive.getFootprints())
693 results.numPosPeaks = sum(len(fp.getPeaks()) for fp in results.positive.getFootprints())
694 positive = " %d positive peaks in %d footprints" % (results.numPosPeaks, results.numPos)
695 if results.negative is not None:
696 results.numNeg = len(results.negative.getFootprints())
697 results.numNegPeaks = sum(len(fp.getPeaks()) for fp in results.negative.getFootprints())
698 negative = " %d negative peaks in %d footprints" % (results.numNegPeaks, results.numNeg)
699
700 self.log.info("Detected%s%s%s to %g +ve and %g -ve %s",
701 positive, " and" if positive and negative else "", negative,
702 self.config.thresholdValue*self.config.includeThresholdMultiplier*factor,
703 self.config.thresholdValue*self.config.includeThresholdMultiplier*factorNeg,
704 "DN" if self.config.thresholdType == "value" else "sigma")
705

◆ 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 468 of file detection.py.

468 def getPsf(self, exposure, sigma=None):
469 """Create a single Gaussian PSF for an exposure.
470
471 If ``sigma`` is provided, we make a `~lsst.afw.detection.GaussianPsf`
472 with that, otherwise use the sigma from the psf of the ``exposure`` to
473 make the `~lsst.afw.detection.GaussianPsf`.
474
475 Parameters
476 ----------
477 exposure : `lsst.afw.image.Exposure`
478 Exposure from which to retrieve the PSF.
479 sigma : `float`, optional
480 Gaussian sigma to use if provided.
481
482 Returns
483 -------
484 psf : `lsst.afw.detection.GaussianPsf`
485 PSF to use for detection.
486
487 Raises
488 ------
489 RuntimeError
490 Raised if ``sigma`` is not provided and ``exposure`` does not
491 contain a ``Psf`` object.
492 """
493 if sigma is None:
494 psf = exposure.getPsf()
495 if psf is None:
496 raise PsfGenerationError("Unable to determine PSF to use for detection: no sigma provided")
497 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
498 if not np.isfinite(sigma) or sigma <= 0.0:
499 raise PsfGenerationError("Invalid sigma=%s for PSF used in detection" % (sigma,))
500 size = self.calculateKernelSize(sigma)
501 psf = afwDet.GaussianPsf(size, size, sigma)
502 return psf
503
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 932 of file detection.py.

932 def makeThreshold(self, image, thresholdParity, factor=1.0):
933 """Make an afw.detection.Threshold object corresponding to the task's
934 configuration and the statistics of the given image.
935
936 Parameters
937 ----------
938 image : `afw.image.MaskedImage`
939 Image to measure noise statistics from if needed.
940 thresholdParity: `str`
941 One of "positive" or "negative", to set the kind of fluctuations
942 the Threshold will detect.
943 factor : `float`
944 Factor by which to multiply the configured detection threshold.
945 This is useful for tweaking the detection threshold slightly.
946
947 Returns
948 -------
949 threshold : `lsst.afw.detection.Threshold`
950 Detection threshold.
951 """
952 parity = False if thresholdParity == "negative" else True
953 thresholdValue = self.config.thresholdValue
954 thresholdType = self.config.thresholdType
955 if self.config.thresholdType == 'stdev':
956 bad = image.getMask().getPlaneBitMask(self.config.statsMask)
958 sctrl.setAndMask(bad)
959 stats = afwMath.makeStatistics(image, afwMath.STDEVCLIP, sctrl)
960 thresholdValue *= stats.getValue(afwMath.STDEVCLIP)
961 thresholdType = 'value'
962
963 threshold = afwDet.createThreshold(thresholdValue*factor, thresholdType, parity)
964 threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier)
965 self.log.debug("Detection threshold: %s", threshold)
966 return threshold
967
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 706 of file detection.py.

706 def reEstimateBackground(self, maskedImage, backgrounds, backgroundToPhotometricRatio=None):
707 """Estimate the background after detection
708
709 Parameters
710 ----------
711 maskedImage : `lsst.afw.image.MaskedImage`
712 Image on which to estimate the background.
713 backgrounds : `lsst.afw.math.BackgroundList`
714 List of backgrounds; modified.
715 backgroundToPhotometricRatio : `lsst.afw.image.Image`, optional
716 Image to multiply a photometrically-flattened image by to obtain a
717 background-flattened image.
718 Only used if ``config.doApplyFlatBackgroundRatio`` is ``True``.
719
720 Returns
721 -------
722 bg : `lsst.afw.math.backgroundMI`
723 Empirical background model.
724 """
725 with backgroundFlatContext(
726 maskedImage,
727 self.config.doApplyFlatBackgroundRatio,
728 backgroundToPhotometricRatio=backgroundToPhotometricRatio,
729 ):
730 bg = self.background.fitBackground(maskedImage)
731 if self.config.adjustBackground:
732 self.log.warning("Fiddling the background by %g", self.config.adjustBackground)
733 bg += self.config.adjustBackground
734 self.log.info("Resubtracting the background after object detection")
735 maskedImage -= bg.getImageF(self.background.config.algorithm,
736 self.background.config.undersampleStyle)
737
738 actrl = bg.getBackgroundControl().getApproximateControl()
739 backgrounds.append((bg, getattr(afwMath.Interpolate, self.background.config.algorithm),
740 bg.getAsUsedUndersampleStyle(), actrl.getStyle(), actrl.getOrderX(),
741 actrl.getOrderY(), actrl.getWeighting()))
742 return bg
743

◆ 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 864 of file detection.py.

864 def removeBadPixels(self, middle):
865 """Set the significance of flagged pixels to zero.
866
867 Parameters
868 ----------
869 middle : `lsst.afw.image.Exposure`
870 Score or maximum likelihood difference image.
871 The image plane will be modified in place.
872 """
873 badPixelMask = middle.mask.getPlaneBitMask(self.config.excludeMaskPlanes)
874 badPixels = middle.mask.array & badPixelMask > 0
875 middle.image.array[badPixels] = 0
876

◆ 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 254 of file detection.py.

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

◆ 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 1011 of file detection.py.

1011 def setEdgeBits(maskedImage, goodBBox, edgeBitmask):
1012 """Set the edgeBitmask bits for all of maskedImage outside goodBBox
1013
1014 Parameters
1015 ----------
1016 maskedImage : `lsst.afw.image.MaskedImage`
1017 Image on which to set edge bits in the mask.
1018 goodBBox : `lsst.geom.Box2I`
1019 Bounding box of good pixels, in ``LOCAL`` coordinates.
1020 edgeBitmask : `lsst.afw.image.MaskPixel`
1021 Bit mask to OR with the existing mask bits in the region
1022 outside ``goodBBox``.
1023 """
1024 msk = maskedImage.getMask()
1025
1026 mx0, my0 = maskedImage.getXY0()
1027 for x0, y0, w, h in ([0, 0,
1028 msk.getWidth(), goodBBox.getBeginY() - my0],
1029 [0, goodBBox.getEndY() - my0, msk.getWidth(),
1030 maskedImage.getHeight() - (goodBBox.getEndY() - my0)],
1031 [0, 0,
1032 goodBBox.getBeginX() - mx0, msk.getHeight()],
1033 [goodBBox.getEndX() - mx0, 0,
1034 maskedImage.getWidth() - (goodBBox.getEndX() - mx0), msk.getHeight()],
1035 ):
1036 edgeMask = msk.Factory(msk, lsst.geom.BoxI(lsst.geom.PointI(x0, y0),
1037 lsst.geom.ExtentI(w, h)), afwImage.LOCAL)
1038 edgeMask |= edgeBitmask
1039
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 877 of file detection.py.

877 def setPeakSignificance(self, exposure, footprints, threshold, negative=False):
878 """Set the significance of each detected peak to the pixel value divided
879 by the appropriate standard-deviation for ``config.thresholdType``.
880
881 Only sets significance for "stdev" and "pixel_stdev" thresholdTypes;
882 we leave it undefined for "value" and "variance" as it does not have a
883 well-defined meaning in those cases.
884
885 Parameters
886 ----------
887 exposure : `lsst.afw.image.Exposure`
888 Exposure that footprints were detected on, likely the convolved,
889 local background-subtracted image.
890 footprints : `lsst.afw.detection.FootprintSet`
891 Footprints detected on the image.
892 threshold : `lsst.afw.detection.Threshold`
893 Threshold used to find footprints.
894 negative : `bool`, optional
895 Are we calculating for negative sources?
896 """
897 if footprints is None or footprints.getFootprints() == []:
898 return footprints
899 polarity = -1 if negative else 1
900
901 # All incoming footprints have the same schema.
902 mapper = afwTable.SchemaMapper(footprints.getFootprints()[0].peaks.schema)
903 mapper.addMinimalSchema(footprints.getFootprints()[0].peaks.schema)
904 mapper.addOutputField("significance", type=float,
905 doc="Ratio of peak value to configured standard deviation.")
906
907 # Copy the old peaks to the new ones with a significance field.
908 # Do this independent of the threshold type, so we always have a
909 # significance field.
910 newFootprints = afwDet.FootprintSet(footprints)
911 for old, new in zip(footprints.getFootprints(), newFootprints.getFootprints()):
912 newPeaks = afwDet.PeakCatalog(mapper.getOutputSchema())
913 newPeaks.extend(old.peaks, mapper=mapper)
914 new.getPeaks().clear()
915 new.setPeakCatalog(newPeaks)
916
917 # Compute the significance values.
918 if self.config.thresholdType == "pixel_stdev":
919 for footprint in newFootprints.getFootprints():
920 footprint.updatePeakSignificance(exposure.variance, polarity)
921 elif self.config.thresholdType == "stdev":
922 sigma = threshold.getValue() / self.config.thresholdValue
923 for footprint in newFootprints.getFootprints():
924 footprint.updatePeakSignificance(polarity*sigma)
925 else:
926 for footprint in newFootprints.getFootprints():
927 for peak in footprint.peaks:
928 peak["significance"] = 0
929
930 return newFootprints
931
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 1041 of file detection.py.

1041 def tempWideBackgroundContext(self, exposure):
1042 """Context manager for removing wide (large-scale) background
1043
1044 Removing a wide (large-scale) background helps to suppress the
1045 detection of large footprints that may overwhelm the deblender.
1046 It does, however, set a limit on the maximum scale of objects.
1047
1048 The background that we remove will be restored upon exit from
1049 the context manager.
1050
1051 Parameters
1052 ----------
1053 exposure : `lsst.afw.image.Exposure`
1054 Exposure on which to remove large-scale background.
1055
1056 Returns
1057 -------
1058 context : context manager
1059 Context manager that will ensure the temporary wide background
1060 is restored.
1061 """
1062 doTempWideBackground = self.config.doTempWideBackground
1063 if doTempWideBackground:
1064 self.log.info("Applying temporary wide background subtraction")
1065 original = exposure.maskedImage.image.array[:].copy()
1066 self.tempWideBackground.run(exposure).background
1067 # Remove NO_DATA regions (e.g., edge of the field-of-view); these can cause detections after
1068 # subtraction because of extrapolation of the background model into areas with no constraints.
1069 image = exposure.maskedImage.image
1070 mask = exposure.maskedImage.mask
1071 noData = mask.array & mask.getPlaneBitMask("NO_DATA") > 0
1072 isGood = mask.array & mask.getPlaneBitMask(self.config.statsMask) == 0
1073 image.array[noData] = np.median(image.array[~noData & isGood])
1074 try:
1075 yield
1076 finally:
1077 if doTempWideBackground:
1078 exposure.maskedImage.image.array[:] = original
1079
1080

◆ 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 968 of file detection.py.

968 def updatePeaks(self, fpSet, image, threshold):
969 """Update the Peaks in a FootprintSet by detecting new Footprints and
970 Peaks in an image and using the new Peaks instead of the old ones.
971
972 Parameters
973 ----------
974 fpSet : `afw.detection.FootprintSet`
975 Set of Footprints whose Peaks should be updated.
976 image : `afw.image.MaskedImage`
977 Image to detect new Footprints and Peak in.
978 threshold : `afw.detection.Threshold`
979 Threshold object for detection.
980
981 Input Footprints with fewer Peaks than self.config.nPeaksMaxSimple
982 are not modified, and if no new Peaks are detected in an input
983 Footprint, the brightest original Peak in that Footprint is kept.
984 """
985 for footprint in fpSet.getFootprints():
986 oldPeaks = footprint.getPeaks()
987 if len(oldPeaks) <= self.config.nPeaksMaxSimple:
988 continue
989 # We detect a new FootprintSet within each non-simple Footprint's
990 # bbox to avoid a big O(N^2) comparison between the two sets of
991 # Footprints.
992 sub = image.Factory(image, footprint.getBBox())
993 fpSetForPeaks = afwDet.FootprintSet(
994 sub,
995 threshold,
996 "", # don't set a mask plane
997 self.config.minPixels
998 )
999 newPeaks = afwDet.PeakCatalog(oldPeaks.getTable())
1000 for fpForPeaks in fpSetForPeaks.getFootprints():
1001 for peak in fpForPeaks.getPeaks():
1002 if footprint.contains(peak.getI()):
1003 newPeaks.append(peak)
1004 if len(newPeaks) > 0:
1005 del oldPeaks[:]
1006 oldPeaks.extend(newPeaks)
1007 else:
1008 del oldPeaks[1:]
1009

Member Data Documentation

◆ _DefaultName

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

Definition at line 232 of file detection.py.

◆ ConfigClass

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

Definition at line 231 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 237 of file detection.py.


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