39def setDetectionMask(maskedImage, forceSlowBin=False, binning=None, detectedPlane="DETECTED",
40 badMaskPlanes=(
"NO_DATA",
"INTRP",
"BAD",
"SAT",
"EDGE"), detectionThreshold=5):
41 """Make detection mask and set the mask plane.
43 Creat a binary image from a masked image by setting all data with signal-to-
44 noise below some threshold to zero, and all data above the threshold to one.
45 If the binning parameter has been set, this procedure will be preceded by a
46 weighted binning of the data in order to smooth the result, after which the
47 result is scaled back to the original dimensions. Set the detection mask
48 plane with this binary image.
52 maskedImage : `lsst.afw.image.maskedImage`
53 Image to be (optionally) binned and converted.
54 forceSlowBin : `bool`, optional
55 Force usage of slower binning method to check that the two methods
57 binning : `int`, optional
58 Number of pixels by which to bin image.
59 detectedPlane : `str`, optional
60 Name of mask with pixels that were detected above threshold in image.
61 badMaskPlanes : `set`, optional
62 Names of masks with pixels that are rejected.
63 detectionThreshold : `float`, optional
64 Boundary in signal-to-noise between non-detections and detections for
65 making a binary image from the original input image.
67 data = maskedImage.image.array
68 weights = 1 / maskedImage.variance.array
69 mask = maskedImage.getMask()
71 detectionMask = ((mask.array & mask.getPlaneBitMask(detectedPlane)))
72 badPixelMask = mask.getPlaneBitMask(badMaskPlanes)
73 badMask = (mask.array & badPixelMask) > 0
74 fitMask = detectionMask.astype(bool) & ~badMask
76 fitData = np.copy(data)
78 fitWeights = np.copy(weights)
79 fitWeights[~fitMask] = 0
83 ymax, xmax = fitData.shape
84 if (ymax % binning == 0)
and (xmax % binning == 0)
and (
not forceSlowBin):
86 binNumeratorReshape = (fitData * fitWeights).reshape(ymax // binning, binning,
87 xmax // binning, binning)
88 binDenominatorReshape = fitWeights.reshape(binNumeratorReshape.shape)
89 binnedNumerator = binNumeratorReshape.sum(axis=3).sum(axis=1)
90 binnedDenominator = binDenominatorReshape.sum(axis=3).sum(axis=1)
93 warnings.warn(
'Using slow binning method--consider choosing a binsize that evenly divides '
94 f
'into the image size, so that {ymax} mod binning == 0 '
95 f
'and {xmax} mod binning == 0', stacklevel=2)
96 xarray = np.arange(xmax)
97 yarray = np.arange(ymax)
98 xmesh, ymesh = np.meshgrid(xarray, yarray)
99 xbins = np.arange(0, xmax + binning, binning)
100 ybins = np.arange(0, ymax + binning, binning)
101 numerator = fitWeights * fitData
102 binnedNumerator, *_ = scipy.stats.binned_statistic_2d(ymesh.ravel(), xmesh.ravel(),
103 numerator.ravel(), statistic=
'sum',
105 binnedDenominator, *_ = scipy.stats.binned_statistic_2d(ymesh.ravel(), xmesh.ravel(),
106 fitWeights.ravel(), statistic=
'sum',
108 binnedData = np.zeros(binnedNumerator.shape)
109 ind = binnedDenominator != 0
110 np.divide(binnedNumerator, binnedDenominator, out=binnedData, where=ind)
111 binnedWeight = binnedDenominator
112 binMask = (binnedData * binnedWeight**0.5) > detectionThreshold
113 tmpOutputMask = binMask.repeat(binning, axis=0)[:ymax]
114 outputMask = tmpOutputMask.repeat(binning, axis=1)[:, :xmax]
116 outputMask = (fitData * fitWeights**0.5) > detectionThreshold
119 maskedImage.mask.array &= ~maskedImage.mask.getPlaneBitMask(detectedPlane)
122 maskedImage.mask.array[outputMask] |= maskedImage.mask.getPlaneBitMask(detectedPlane)
431 """Configuration parameters for `MaskStreaksTask`.
434 minimumKernelHeight = pexConfig.Field(
435 doc=
"Minimum height of the streak-finding kernel relative to the tallest kernel",
439 absMinimumKernelHeight = pexConfig.Field(
440 doc=
"Minimum absolute height of the streak-finding kernel",
444 clusterMinimumSize = pexConfig.Field(
445 doc=
"Minimum size in pixels of detected clusters",
449 clusterMinimumDeviation = pexConfig.Field(
450 doc=
"Allowed deviation (in pixels) from a straight line for a detected "
455 delta = pexConfig.Field(
456 doc=
"Stepsize in angle-radius parameter space",
460 nSigma = pexConfig.Field(
461 doc=
"Number of sigmas from center of kernel to include in voting "
466 rhoBinSize = pexConfig.Field(
467 doc=
"Binsize in pixels for position parameter rho when finding "
468 "clusters of detected lines",
472 thetaBinSize = pexConfig.Field(
473 doc=
"Binsize in degrees for angle parameter theta when finding "
474 "clusters of detected lines",
478 invSigma = pexConfig.Field(
479 doc=
"Inverse of the Moffat sigma parameter (in units of pixels)"
480 "describing the profile of the streak",
484 footprintThreshold = pexConfig.Field(
485 doc=
"Threshold at which to determine edge of line, in units of "
490 dChi2Tolerance = pexConfig.Field(
491 doc=
"Absolute difference in Chi2 between iterations of line profile"
492 "fitting that is acceptable for convergence",
496 detectedMaskPlane = pexConfig.Field(
497 doc=
"Name of mask with pixels above detection threshold, used for first"
498 "estimate of streak locations",
502 streaksMaskPlane = pexConfig.Field(
503 doc=
"Name of mask plane holding detected streaks",
setDetectionMask(maskedImage, forceSlowBin=False, binning=None, detectedPlane="DETECTED", badMaskPlanes=("NO_DATA", "INTRP", "BAD", "SAT", "EDGE"), detectionThreshold=5)