1560 def findArtifacts(self, templateCoadd, tempExpRefList, imageScalerList):
1561 """Find artifacts.
1562
1563 Loop through warps twice. The first loop builds a map with the count
1564 of how many epochs each pixel deviates from the templateCoadd by more
1565 than ``config.chiThreshold`` sigma. The second loop takes each
1566 difference image and filters the artifacts detected in each using
1567 count map to filter out variable sources and sources that are
1568 difficult to subtract cleanly.
1569
1570 Parameters
1571 ----------
1573 Exposure to serve as model of static sky.
1574 tempExpRefList : `list`
1575 List of data references to warps.
1576 imageScalerList : `list`
1577 List of image scalers.
1578
1579 Returns
1580 -------
1581 altMasks : `list` of `dict`
1582 List of dicts containing information about CLIPPED
1583 (i.e., artifacts), NO_DATA, and EDGE pixels.
1584 """
1585 self.log.debug("Generating Count Image, and mask lists.")
1586 coaddBBox = templateCoadd.getBBox()
1587 slateIm = afwImage.ImageU(coaddBBox)
1588 epochCountImage = afwImage.ImageU(coaddBBox)
1589 nImage = afwImage.ImageU(coaddBBox)
1590 spanSetArtifactList = []
1591 spanSetNoDataMaskList = []
1592 spanSetEdgeList = []
1593 spanSetBadMorphoList = []
1594 badPixelMask = self.getBadPixelMask()
1595
1596
1597 templateCoadd.mask.clearAllMaskPlanes()
1598
1599 if self.config.doPreserveContainedBySource:
1600 templateFootprints = self.detectTemplate.detectFootprints(templateCoadd)
1601 else:
1602 templateFootprints = None
1603
1604 for warpRef, imageScaler in zip(tempExpRefList, imageScalerList):
1605 warpDiffExp = self._readAndComputeWarpDiff(warpRef, imageScaler, templateCoadd)
1606 if warpDiffExp is not None:
1607
1608 nImage.array += (numpy.isfinite(warpDiffExp.image.array)
1609 * ((warpDiffExp.mask.array & badPixelMask) == 0)).astype(numpy.uint16)
1610 fpSet = self.detect.detectFootprints(warpDiffExp, doSmooth=False, clearMask=True)
1611 fpSet.positive.merge(fpSet.negative)
1612 footprints = fpSet.positive
1613 slateIm.set(0)
1614 spanSetList = [footprint.spans for footprint in footprints.getFootprints()]
1615
1616
1617 if self.config.doPrefilterArtifacts:
1618 spanSetList = self.prefilterArtifacts(spanSetList, warpDiffExp)
1619
1620
1621 self.detect.clearMask(warpDiffExp.mask)
1622 for spans in spanSetList:
1623 spans.setImage(slateIm, 1, doClip=True)
1624 spans.setMask(warpDiffExp.mask, warpDiffExp.mask.getPlaneBitMask("DETECTED"))
1625 epochCountImage += slateIm
1626
1627 if self.config.doFilterMorphological:
1628 maskName = self.config.streakMaskName
1629 _ = self.maskStreaks.run(warpDiffExp)
1630 streakMask = warpDiffExp.mask
1631 spanSetStreak = afwGeom.SpanSet.fromMask(streakMask,
1632 streakMask.getPlaneBitMask(maskName)).split()
1633
1634 psf = warpDiffExp.getPsf()
1635 for s, sset in enumerate(spanSetStreak):
1636 psfShape = psf.computeShape(sset.computeCentroid())
1637 dilation = self.config.growStreakFp * psfShape.getDeterminantRadius()
1638 sset_dilated = sset.dilated(int(dilation))
1639 spanSetStreak[s] = sset_dilated
1640
1641
1642
1643
1644
1645 nans = numpy.where(numpy.isnan(warpDiffExp.maskedImage.image.array), 1, 0)
1647 nansMask.setXY0(warpDiffExp.getXY0())
1648 edgeMask = warpDiffExp.mask
1649 spanSetEdgeMask = afwGeom.SpanSet.fromMask(edgeMask,
1650 edgeMask.getPlaneBitMask("EDGE")).split()
1651 else:
1652
1653
1654 nansMask = afwImage.MaskX(coaddBBox, 1)
1655 spanSetList = []
1656 spanSetEdgeMask = []
1657 spanSetStreak = []
1658
1659 spanSetNoDataMask = afwGeom.SpanSet.fromMask(nansMask).split()
1660
1661 spanSetNoDataMaskList.append(spanSetNoDataMask)
1662 spanSetArtifactList.append(spanSetList)
1663 spanSetEdgeList.append(spanSetEdgeMask)
1664 if self.config.doFilterMorphological:
1665 spanSetBadMorphoList.append(spanSetStreak)
1666
1668 path = self._dataRef2DebugPath("epochCountIm", tempExpRefList[0], coaddLevel=True)
1669 epochCountImage.writeFits(path)
1670
1671 for i, spanSetList in enumerate(spanSetArtifactList):
1672 if spanSetList:
1673 filteredSpanSetList = self.filterArtifacts(spanSetList, epochCountImage, nImage,
1674 templateFootprints)
1675 spanSetArtifactList[i] = filteredSpanSetList
1676 if self.config.doFilterMorphological:
1677 spanSetArtifactList[i] += spanSetBadMorphoList[i]
1678
1679 altMasks = []
1680 for artifacts, noData, edge in zip(spanSetArtifactList, spanSetNoDataMaskList, spanSetEdgeList):
1681 altMasks.append({'CLIPPED': artifacts,
1682 'NO_DATA': noData,
1683 'EDGE': edge})
1684 return altMasks
1685