LSST Applications g0265f82a02+d6b5cd48b5,g02d81e74bb+a41d3748ce,g1470d8bcf6+6be6c9203b,g2079a07aa2+14824f138e,g212a7c68fe+a4f2ea4efa,g2305ad1205+72971fe858,g295015adf3+ab2c85acae,g2bbee38e9b+d6b5cd48b5,g337abbeb29+d6b5cd48b5,g3ddfee87b4+31b3a28dff,g487adcacf7+082e807817,g50ff169b8f+5929b3527e,g52b1c1532d+a6fc98d2e7,g591dd9f2cf+b2918d57ae,g5a732f18d5+66d966b544,g64a986408d+a41d3748ce,g858d7b2824+a41d3748ce,g8a8a8dda67+a6fc98d2e7,g99cad8db69+7fe4acdf18,g9ddcbc5298+d4bad12328,ga1e77700b3+246acaaf9c,ga8c6da7877+84af8b3ff8,gb0e22166c9+3863383f4c,gb6a65358fc+d6b5cd48b5,gba4ed39666+9664299f35,gbb8dafda3b+d8d527deb2,gc07e1c2157+b2dbe6b631,gc120e1dc64+61440b2abb,gc28159a63d+d6b5cd48b5,gcf0d15dbbd+31b3a28dff,gdaeeff99f8+a38ce5ea23,ge6526c86ff+39927bb362,ge79ae78c31+d6b5cd48b5,gee10cc3b42+a6fc98d2e7,gf1cff7945b+a41d3748ce,v24.1.5.rc1
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Static Protected Attributes | List of all members
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)
 
 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)
 
 clearUnwantedResults (self, mask, results)
 
 detectFootprints (self, exposure, doSmooth=True, sigma=None, clearMask=True, expId=None, background=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 170 of file detection.py.

Constructor & Destructor Documentation

◆ __init__()

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

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

Definition at line 200 of file detection.py.

200 def __init__(self, schema=None, **kwds):
201 pipeBase.Task.__init__(self, **kwds)
202 if schema is not None and self.config.thresholdPolarity == "both":
203 self.negativeFlagKey = schema.addField(
204 "flags_negative", type="Flag",
205 doc="set if source was detected as significantly negative"
206 )
207 else:
208 if self.config.thresholdPolarity == "both":
209 self.log.warning("Detection polarity set to 'both', but no flag will be "
210 "set to distinguish between positive and negative detections")
211 self.negativeFlagKey = None
212 if self.config.reEstimateBackground:
213 self.makeSubtask("background")
214 if self.config.doTempLocalBackground:
215 self.makeSubtask("tempLocalBackground")
216 if self.config.doTempWideBackground:
217 self.makeSubtask("tempWideBackground")
218

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

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

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

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

409 def calculateKernelSize(self, sigma):
410 """Calculate the size of the smoothing kernel.
411
412 Uses the ``nSigmaForKernel`` configuration parameter. Note
413 that that is the full width of the kernel bounding box
414 (so a value of 7 means 3.5 sigma on either side of center).
415 The value will be rounded up to the nearest odd integer.
416
417 Parameters
418 ----------
419 sigma : `float`
420 Gaussian sigma of smoothing kernel.
421
422 Returns
423 -------
424 size : `int`
425 Size of the smoothing kernel.
426 """
427 return (int(sigma * self.config.nSigmaForKernel + 0.5)//2)*2 + 1 # make sure it is odd
428

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

396 def clearMask(self, mask):
397 """Clear the DETECTED and DETECTED_NEGATIVE mask planes.
398
399 Removes any previous detection mask in preparation for a new
400 detection pass.
401
402 Parameters
403 ----------
404 mask : `lsst.afw.image.Mask`
405 Mask to be cleared.
406 """
407 mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask("DETECTED_NEGATIVE"))
408

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

690 def clearUnwantedResults(self, mask, results):
691 """Clear unwanted results from the Struct of results
692
693 If we specifically want only positive or only negative detections,
694 drop the ones we don't want, and its associated mask plane.
695
696 Parameters
697 ----------
698 mask : `lsst.afw.image.Mask`
699 Mask image.
700 results : `lsst.pipe.base.Struct`
701 Detection results, with ``positive`` and ``negative`` elements;
702 modified.
703 """
704 if self.config.thresholdPolarity == "positive":
705 if self.config.reEstimateBackground:
706 mask &= ~mask.getPlaneBitMask("DETECTED_NEGATIVE")
707 results.negative = None
708 elif self.config.thresholdPolarity == "negative":
709 if self.config.reEstimateBackground:
710 mask &= ~mask.getPlaneBitMask("DETECTED")
711 results.positive = None
712

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

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

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

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

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

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

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

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

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

429 def getPsf(self, exposure, sigma=None):
430 """Create a single Gaussian PSF for an exposure.
431
432 If ``sigma`` is provided, we make a `~lsst.afw.detection.GaussianPsf`
433 with that, otherwise use the sigma from the psf of the ``exposure`` to
434 make the `~lsst.afw.detection.GaussianPsf`.
435
436 Parameters
437 ----------
438 exposure : `lsst.afw.image.Exposure`
439 Exposure from which to retrieve the PSF.
440 sigma : `float`, optional
441 Gaussian sigma to use if provided.
442
443 Returns
444 -------
445 psf : `lsst.afw.detection.GaussianPsf`
446 PSF to use for detection.
447
448 Raises
449 ------
450 RuntimeError
451 Raised if ``sigma`` is not provided and ``exposure`` does not
452 contain a ``Psf`` object.
453 """
454 if sigma is None:
455 psf = exposure.getPsf()
456 if psf is None:
457 raise RuntimeError("Unable to determine PSF to use for detection: no sigma provided")
458 sigma = psf.computeShape(psf.getAveragePosition()).getDeterminantRadius()
459 size = self.calculateKernelSize(sigma)
460 psf = afwDet.GaussianPsf(size, size, sigma)
461 return psf
462
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 870 of file detection.py.

870 def makeThreshold(self, image, thresholdParity, factor=1.0):
871 """Make an afw.detection.Threshold object corresponding to the task's
872 configuration and the statistics of the given image.
873
874 Parameters
875 ----------
876 image : `afw.image.MaskedImage`
877 Image to measure noise statistics from if needed.
878 thresholdParity: `str`
879 One of "positive" or "negative", to set the kind of fluctuations
880 the Threshold will detect.
881 factor : `float`
882 Factor by which to multiply the configured detection threshold.
883 This is useful for tweaking the detection threshold slightly.
884
885 Returns
886 -------
887 threshold : `lsst.afw.detection.Threshold`
888 Detection threshold.
889 """
890 parity = False if thresholdParity == "negative" else True
891 thresholdValue = self.config.thresholdValue
892 thresholdType = self.config.thresholdType
893 if self.config.thresholdType == 'stdev':
894 bad = image.getMask().getPlaneBitMask(self.config.statsMask)
896 sctrl.setAndMask(bad)
897 stats = afwMath.makeStatistics(image, afwMath.STDEVCLIP, sctrl)
898 thresholdValue *= stats.getValue(afwMath.STDEVCLIP)
899 thresholdType = 'value'
900
901 threshold = afwDet.createThreshold(thresholdValue*factor, thresholdType, parity)
902 threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier)
903 self.log.debug("Detection threshold: %s", threshold)
904 return threshold
905
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 )
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.

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

Definition at line 661 of file detection.py.

661 def reEstimateBackground(self, maskedImage, backgrounds):
662 """Estimate the background after detection
663
664 Parameters
665 ----------
666 maskedImage : `lsst.afw.image.MaskedImage`
667 Image on which to estimate the background.
668 backgrounds : `lsst.afw.math.BackgroundList`
669 List of backgrounds; modified.
670
671 Returns
672 -------
673 bg : `lsst.afw.math.backgroundMI`
674 Empirical background model.
675 """
676 bg = self.background.fitBackground(maskedImage)
677 if self.config.adjustBackground:
678 self.log.warning("Fiddling the background by %g", self.config.adjustBackground)
679 bg += self.config.adjustBackground
680 self.log.info("Resubtracting the background after object detection")
681 maskedImage -= bg.getImageF(self.background.config.algorithm,
682 self.background.config.undersampleStyle)
683
684 actrl = bg.getBackgroundControl().getApproximateControl()
685 backgrounds.append((bg, getattr(afwMath.Interpolate, self.background.config.algorithm),
686 bg.getAsUsedUndersampleStyle(), actrl.getStyle(), actrl.getOrderX(),
687 actrl.getOrderY(), actrl.getWeighting()))
688 return bg
689

◆ removeBadPixels()

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

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

Definition at line 802 of file detection.py.

802 def removeBadPixels(self, middle):
803 """Set the significance of flagged pixels to zero.
804
805 Parameters
806 ----------
807 middle : `lsst.afw.image.ExposureF`
808 Score or maximum likelihood difference image.
809 The image plane will be modified in place.
810 """
811 badPixelMask = lsst.afw.image.Mask.getPlaneBitMask(self.config.excludeMaskPlanes)
812 badPixels = middle.mask.array & badPixelMask > 0
813 middle.image.array[badPixels] = 0
814
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
Definition Mask.cc:376

◆ run()

lsst.meas.algorithms.detection.SourceDetectionTask.run ( self,
table,
exposure,
doSmooth = True,
sigma = None,
clearMask = True,
expId = None,
background = 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``.

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

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

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

949 def setEdgeBits(maskedImage, goodBBox, edgeBitmask):
950 """Set the edgeBitmask bits for all of maskedImage outside goodBBox
951
952 Parameters
953 ----------
954 maskedImage : `lsst.afw.image.MaskedImage`
955 Image on which to set edge bits in the mask.
956 goodBBox : `lsst.geom.Box2I`
957 Bounding box of good pixels, in ``LOCAL`` coordinates.
958 edgeBitmask : `lsst.afw.image.MaskPixel`
959 Bit mask to OR with the existing mask bits in the region
960 outside ``goodBBox``.
961 """
962 msk = maskedImage.getMask()
963
964 mx0, my0 = maskedImage.getXY0()
965 for x0, y0, w, h in ([0, 0,
966 msk.getWidth(), goodBBox.getBeginY() - my0],
967 [0, goodBBox.getEndY() - my0, msk.getWidth(),
968 maskedImage.getHeight() - (goodBBox.getEndY() - my0)],
969 [0, 0,
970 goodBBox.getBeginX() - mx0, msk.getHeight()],
971 [goodBBox.getEndX() - mx0, 0,
972 maskedImage.getWidth() - (goodBBox.getEndX() - mx0), msk.getHeight()],
973 ):
974 edgeMask = msk.Factory(msk, lsst.geom.BoxI(lsst.geom.PointI(x0, y0),
975 lsst.geom.ExtentI(w, h)), afwImage.LOCAL)
976 edgeMask |= edgeBitmask
977
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 815 of file detection.py.

815 def setPeakSignificance(self, exposure, footprints, threshold, negative=False):
816 """Set the significance of each detected peak to the pixel value divided
817 by the appropriate standard-deviation for ``config.thresholdType``.
818
819 Only sets significance for "stdev" and "pixel_stdev" thresholdTypes;
820 we leave it undefined for "value" and "variance" as it does not have a
821 well-defined meaning in those cases.
822
823 Parameters
824 ----------
825 exposure : `lsst.afw.image.Exposure`
826 Exposure that footprints were detected on, likely the convolved,
827 local background-subtracted image.
828 footprints : `lsst.afw.detection.FootprintSet`
829 Footprints detected on the image.
830 threshold : `lsst.afw.detection.Threshold`
831 Threshold used to find footprints.
832 negative : `bool`, optional
833 Are we calculating for negative sources?
834 """
835 if footprints is None or footprints.getFootprints() == []:
836 return footprints
837 polarity = -1 if negative else 1
838
839 # All incoming footprints have the same schema.
840 mapper = afwTable.SchemaMapper(footprints.getFootprints()[0].peaks.schema)
841 mapper.addMinimalSchema(footprints.getFootprints()[0].peaks.schema)
842 mapper.addOutputField("significance", type=float,
843 doc="Ratio of peak value to configured standard deviation.")
844
845 # Copy the old peaks to the new ones with a significance field.
846 # Do this independent of the threshold type, so we always have a
847 # significance field.
848 newFootprints = afwDet.FootprintSet(footprints)
849 for old, new in zip(footprints.getFootprints(), newFootprints.getFootprints()):
850 newPeaks = afwDet.PeakCatalog(mapper.getOutputSchema())
851 newPeaks.extend(old.peaks, mapper=mapper)
852 new.getPeaks().clear()
853 new.setPeakCatalog(newPeaks)
854
855 # Compute the significance values.
856 if self.config.thresholdType == "pixel_stdev":
857 for footprint in newFootprints.getFootprints():
858 footprint.updatePeakSignificance(exposure.variance, polarity)
859 elif self.config.thresholdType == "stdev":
860 sigma = threshold.getValue() / self.config.thresholdValue
861 for footprint in newFootprints.getFootprints():
862 footprint.updatePeakSignificance(polarity*sigma)
863 else:
864 for footprint in newFootprints.getFootprints():
865 for peak in footprint.peaks:
866 peak["significance"] = 0
867
868 return newFootprints
869
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 979 of file detection.py.

979 def tempWideBackgroundContext(self, exposure):
980 """Context manager for removing wide (large-scale) background
981
982 Removing a wide (large-scale) background helps to suppress the
983 detection of large footprints that may overwhelm the deblender.
984 It does, however, set a limit on the maximum scale of objects.
985
986 The background that we remove will be restored upon exit from
987 the context manager.
988
989 Parameters
990 ----------
991 exposure : `lsst.afw.image.Exposure`
992 Exposure on which to remove large-scale background.
993
994 Returns
995 -------
996 context : context manager
997 Context manager that will ensure the temporary wide background
998 is restored.
999 """
1000 doTempWideBackground = self.config.doTempWideBackground
1001 if doTempWideBackground:
1002 self.log.info("Applying temporary wide background subtraction")
1003 original = exposure.maskedImage.image.array[:].copy()
1004 self.tempWideBackground.run(exposure).background
1005 # Remove NO_DATA regions (e.g., edge of the field-of-view); these can cause detections after
1006 # subtraction because of extrapolation of the background model into areas with no constraints.
1007 image = exposure.maskedImage.image
1008 mask = exposure.maskedImage.mask
1009 noData = mask.array & mask.getPlaneBitMask("NO_DATA") > 0
1010 isGood = mask.array & mask.getPlaneBitMask(self.config.statsMask) == 0
1011 image.array[noData] = np.median(image.array[~noData & isGood])
1012 try:
1013 yield
1014 finally:
1015 if doTempWideBackground:
1016 exposure.maskedImage.image.array[:] = original
1017
1018

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

906 def updatePeaks(self, fpSet, image, threshold):
907 """Update the Peaks in a FootprintSet by detecting new Footprints and
908 Peaks in an image and using the new Peaks instead of the old ones.
909
910 Parameters
911 ----------
912 fpSet : `afw.detection.FootprintSet`
913 Set of Footprints whose Peaks should be updated.
914 image : `afw.image.MaskedImage`
915 Image to detect new Footprints and Peak in.
916 threshold : `afw.detection.Threshold`
917 Threshold object for detection.
918
919 Input Footprints with fewer Peaks than self.config.nPeaksMaxSimple
920 are not modified, and if no new Peaks are detected in an input
921 Footprint, the brightest original Peak in that Footprint is kept.
922 """
923 for footprint in fpSet.getFootprints():
924 oldPeaks = footprint.getPeaks()
925 if len(oldPeaks) <= self.config.nPeaksMaxSimple:
926 continue
927 # We detect a new FootprintSet within each non-simple Footprint's
928 # bbox to avoid a big O(N^2) comparison between the two sets of
929 # Footprints.
930 sub = image.Factory(image, footprint.getBBox())
931 fpSetForPeaks = afwDet.FootprintSet(
932 sub,
933 threshold,
934 "", # don't set a mask plane
935 self.config.minPixels
936 )
937 newPeaks = afwDet.PeakCatalog(oldPeaks.getTable())
938 for fpForPeaks in fpSetForPeaks.getFootprints():
939 for peak in fpForPeaks.getPeaks():
940 if footprint.contains(peak.getI()):
941 newPeaks.append(peak)
942 if len(newPeaks) > 0:
943 del oldPeaks[:]
944 oldPeaks.extend(newPeaks)
945 else:
946 del oldPeaks[1:]
947

Member Data Documentation

◆ _DefaultName

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

Definition at line 198 of file detection.py.

◆ ConfigClass

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

Definition at line 197 of file detection.py.

◆ negativeFlagKey

lsst.meas.algorithms.detection.SourceDetectionTask.negativeFlagKey

Definition at line 203 of file detection.py.


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