2626import lsst .afw .image
2727import lsst .afw .math
2828import lsst .geom
29- from lsst .ip .diffim .utils import evaluateMeanPsfFwhm , getPsfFwhm , computeDifferenceImageMetrics
29+ from lsst .ip .diffim .utils import evaluateMeanPsfFwhm , getPsfFwhm , computeDifferenceImageMetrics , checkMask
3030from lsst .meas .algorithms import ScaleVarianceTask , ScienceSourceSelectorTask
3131import lsst .pex .config
3232import lsst .pipe .base
@@ -268,9 +268,8 @@ class AlardLuptonSubtractBaseConfig(lsst.pex.config.Config):
268268 )
269269 excludeMaskPlanes = lsst .pex .config .ListField (
270270 dtype = str ,
271- default = ("NO_DATA" , "BAD" , "SAT" , "EDGE" , "FAKE" ),
272- doc = "Mask planes to exclude when selecting sources for PSF matching." ,
273- deprecated = "No longer used. Will be removed after v30"
271+ default = ("NO_DATA" , "BAD" , "SAT" , "EDGE" , "FAKE" , "HIGH_VARIANCE" ),
272+ doc = "Template mask planes to exclude when selecting sources for PSF matching." ,
274273 )
275274 badMaskPlanes = lsst .pex .config .ListField (
276275 dtype = str ,
@@ -279,7 +278,7 @@ class AlardLuptonSubtractBaseConfig(lsst.pex.config.Config):
279278 )
280279 preserveTemplateMask = lsst .pex .config .ListField (
281280 dtype = str ,
282- default = ("NO_DATA" , "BAD" ,),
281+ default = ("NO_DATA" , "BAD" , "HIGH_VARIANCE" ),
283282 doc = "Mask planes from the template to propagate to the image difference."
284283 )
285284 renameTemplateMask = lsst .pex .config .ListField (
@@ -443,7 +442,7 @@ def run(self, template, science, sources, visitSummary=None):
443442
444443 convolveTemplate = self .chooseConvolutionMethod (template , science )
445444
446- selectSources = self ._sourceSelector (sources , science .getBBox ())
445+ selectSources = self ._sourceSelector (sources , science .getBBox (), template . mask )
447446
448447 kernelResult = self .runMakeKernel (template , science , selectSources ,
449448 convolveTemplate = convolveTemplate )
@@ -627,7 +626,7 @@ def runKernelSourceDetection(self, template, science):
627626 scienceFwhmPix = self .sciencePsfSize )
628627
629628 # return sources
630- return self ._sourceSelector (sources , science .getBBox (), fallback = True )
629+ return self ._sourceSelector (sources , science .getBBox (), template . mask , fallback = True )
631630
632631 def runConvolveTemplate (self , template , science , psfMatchingKernel , backgroundModel = None ):
633632 """Convolve the template image with a PSF-matching kernel and subtract
@@ -908,7 +907,7 @@ def _convolveExposure(self, exposure, kernel, convolutionControl,
908907 else :
909908 return convolvedExposure [bbox ]
910909
911- def _sourceSelector (self , sources , bbox , fallback = False ):
910+ def _sourceSelector (self , sources , bbox , mask , fallback = False ):
912911 """Select sources from a catalog that meet the selection criteria.
913912 The selection criteria include any configured parameters of the
914913 `sourceSelector` subtask, as well as distance from the edge if
@@ -920,6 +919,13 @@ def _sourceSelector(self, sources, bbox, fallback=False):
920919 Input source catalog to select sources from.
921920 bbox : `lsst.geom.Box2I`
922921 Bounding box of the science image.
922+ mask : `lsst.afw.image.Mask`
923+ The mask plane of the template to use to reject kernel candidates.
924+ fallback : `bool`, optional
925+ Switch indicating the source selector is being called after
926+ running the fallback source detection subtask, which does not run a
927+ full set of measurement plugins and can't use the same settings for
928+ the source selector.
923929
924930 Returns
925931 -------
@@ -929,6 +935,9 @@ def _sourceSelector(self, sources, bbox, fallback=False):
929935
930936 Raises
931937 ------
938+ InsufficientKernelSourcesError
939+ An AlgorithmError that is raised if there are not enough PSF
940+ candidates to construct the PSF matching kernel.
932941 RuntimeError
933942 If there are too few sources to compute the PSF matching kernel
934943 remaining after source selection.
@@ -945,6 +954,9 @@ def _sourceSelector(self, sources, bbox, fallback=False):
945954 np .count_nonzero (~ bboxSelected ), rejectRadius )
946955 selected &= bboxSelected
947956 selectSources = sources [selected ].copy (deep = True )
957+ # Optionally remove sources that land on masked pixels
958+ maskSelected = checkMask (mask , selectSources , self .config .excludeMaskPlanes , checkAdjacent = True )
959+ selectSources = selectSources [maskSelected ].copy (deep = True )
948960 # Trim selectSources if they exceed ``maxKernelSources``.
949961 # Keep the highest signal-to-noise sources of those selected.
950962 if (len (selectSources ) > self .config .maxKernelSources ) & (self .config .maxKernelSources > 0 ):
@@ -1211,7 +1223,7 @@ def run(self, template, science, sources, visitSummary=None):
12111223 interpolateBadMaskPlanes = True )
12121224 self .metadata ["convolvedExposure" ] = "Preconvolution"
12131225 try :
1214- selectSources = self ._sourceSelector (sources , science .getBBox ())
1226+ selectSources = self ._sourceSelector (sources , science .getBBox (), template . mask )
12151227 subtractResults = self .runPreconvolve (template , science , matchedScience ,
12161228 selectSources , scienceKernel )
12171229
0 commit comments