278 badPixels=["BAD"], minPixelToMask=45000,
279 crosstalkStr="CROSSTALK", isTrimmed=False,
280 backgroundMethod="None"):
281 """Subtract the intra-detector crosstalk from an exposure
283 We set the mask plane indicated by ``crosstalkStr`` in a target amplifier
284 for pixels in a source amplifier that exceed `minPixelToMask`. Note that
285 the correction is applied to all pixels in the amplifier, but only those
286 that have a substantial crosstalk are masked with ``crosstalkStr``.
288 The uncorrected image is used as a template for correction. This is good
289 enough if the crosstalk is small (e.g., coefficients < ~ 1e-3), but if it's
290 larger you may want to iterate.
292 This method needs unittests (DM-18876), but such testing requires
293 DM-18610 to allow the test detector to have the crosstalk
298 exposure : `lsst.afw.image.Exposure`
299 Exposure for which to subtract crosstalk.
300 crosstalkCoeffs : `numpy.ndarray`
301 Coefficients to use to correct crosstalk.
302 badPixels : `list` of `str`
303 Mask planes to ignore.
304 minPixelToMask : `float`
305 Minimum pixel value (relative to the background level) in
306 source amplifier for which to set ``crosstalkStr`` mask plane
309 Mask plane name for pixels greatly modified by crosstalk.
311 The image is already trimmed.
312 This should no longer be needed once DM-15409 is resolved.
313 backgroundMethod : `str`
314 Method used to subtract the background. "AMP" uses
315 amplifier-by-amplifier background levels, "DETECTOR" uses full
316 exposure/maskedImage levels. Any other value results in no
317 background subtraction.
319 mi = exposure.getMaskedImage()
322 ccd = exposure.getDetector()
324 if crosstalkCoeffs
is None:
325 coeffs = ccd.getCrosstalk()
327 coeffs = crosstalkCoeffs
328 assert coeffs.shape == (numAmps, numAmps)
336 backgrounds = [0.0
for amp
in ccd]
337 if backgroundMethod
is None:
339 elif backgroundMethod ==
"AMP":
341 elif backgroundMethod ==
"DETECTOR":
345 crosstalkPlane = mask.addMaskPlane(crosstalkStr)
347 thresholdBackground))
348 footprints.setMask(mask, crosstalkStr)
349 crosstalk = mask.getPlaneBitMask(crosstalkStr)
352 subtrahend = mi.Factory(mi.getBBox())
353 subtrahend.set((0, 0, 0))
354 for ii, iAmp
in enumerate(ccd):
355 iImage = subtrahend[iAmp.getBBox()
if isTrimmed
else iAmp.getRawDataBBox()]
356 for jj, jAmp
in enumerate(ccd):
358 assert coeffs[ii, jj] == 0.0
359 if coeffs[ii, jj] == 0.0:
362 jImage =
extractAmp(mi, jAmp, iAmp.getReadoutCorner(), isTrimmed)
363 jImage.getMask().getArray()[:] &= crosstalk
364 jImage -= backgrounds[jj]
366 iImage.scaledPlus(coeffs[ii, jj], jImage)
370 mask.clearMaskPlane(crosstalkPlane)