25 __all__ = [
"DiaSourceAnalystConfig",
"DiaSourceAnalyst"]
30 import lsst.pex.config
as pexConfig
36 srcBadMaskPlanes = pexConfig.ListField(
38 doc=
"""Mask planes that lead to an invalid detection.
39 Options: NO_DATA EDGE SAT BAD CR INTRP
40 E.g. : NO_DATA SAT BAD allows CR-masked and interpolated pixels""",
41 default=(
"NO_DATA",
"EDGE",
"SAT",
"BAD")
43 fBadPixels = pexConfig.Field(
45 doc=
"Fraction of bad pixels allowed in footprint",
48 fluxPolarityRatio = pexConfig.Field(
50 doc=
"Minimum fraction of flux in correct-polarity pixels",
53 nPolarityRatio = pexConfig.Field(
55 doc=
"Minimum fraction of correct-polarity pixels in unmasked subset",
58 nMaskedRatio = pexConfig.Field(
60 doc=
"Minimum fraction of correct-polarity unmasked to masked pixels",
63 nGoodRatio = pexConfig.Field(
65 doc=
"Minimum fraction of correct-polarity unmasked to all pixels",
74 self.
log = Log.getLogger(
"ip.diffim.DiaSourceAnalysis")
77 srcBadMaskPlanes = self.
config.srcBadMaskPlanes
78 for maskPlane
in srcBadMaskPlanes:
79 self.
bitMask |= afwImage.Mask.getPlaneBitMask(maskPlane)
82 idxP = num.where(mask & afwImage.Mask.getPlaneBitMask(
"DETECTED"))
83 idxN = num.where(mask & afwImage.Mask.getPlaneBitMask(
"DETECTED_NEGATIVE"))
84 return len(idxP[0]), len(idxN[0])
87 idxM = num.where(mask & self.
bitMask)
91 unmasked = ((mask & self.
bitMask) == 0)
92 idxP = num.where((pixels >= 0) & unmasked)
93 idxN = num.where((pixels < 0) & unmasked)
94 fluxP = num.sum(pixels[idxP])
95 fluxN = num.sum(pixels[idxN])
96 return len(idxP[0]), len(idxN[0]), fluxP, fluxN
99 imArr, maArr, varArr = subMi.getArrays()
100 flux = source.getApFlux()
102 nPixels = subMi.getWidth() * subMi.getHeight()
106 assert(nPixels == (nMasked + nPos + nNeg))
109 fMasked = (nMasked / nPixels)
110 fMaskedTol = self.
config.fBadPixels
111 if fMasked > fMaskedTol:
112 self.
log.
debug(
"Candidate %d : BAD fBadPixels %.2f > %.2f", source.getId(), fMasked, fMaskedTol)
117 fluxRatio = fPos / (fPos +
abs(fNeg))
118 ngoodRatio = nPos / nPixels
119 maskRatio = nPos / (nPos + nMasked)
120 npolRatio = nPos / (nPos + nNeg)
123 fluxRatio =
abs(fNeg) / (fPos +
abs(fNeg))
124 ngoodRatio = nNeg / nPixels
125 maskRatio = nNeg / (nNeg + nMasked)
126 npolRatio = nNeg / (nNeg + nPos)
129 fluxRatioTolerance = self.
config.fluxPolarityRatio
130 if fluxRatio < fluxRatioTolerance:
131 self.
log.
debug(
"Candidate %d : BAD flux polarity %.2f < %.2f (pos=%.2f neg=%.2f)",
132 source.getId(), fluxRatio, fluxRatioTolerance, fPos, fNeg)
136 polarityTolerance = self.
config.nPolarityRatio
137 if npolRatio < polarityTolerance:
138 self.
log.
debug(
"Candidate %d : BAD polarity count %.2f < %.2f (pos=%d neg=%d)",
139 source.getId(), npolRatio, polarityTolerance, nPos, nNeg)
143 maskedTolerance = self.
config.nMaskedRatio
144 if maskRatio < maskedTolerance:
145 self.
log.
debug(
"Candidate %d : BAD unmasked count %.2f < %.2f (pos=%d neg=%d mask=%d)",
146 source.getId(), maskRatio, maskedTolerance, nPos, nNeg, nMasked)
150 ngoodTolerance = self.
config.nGoodRatio
151 if ngoodRatio < ngoodTolerance:
152 self.
log.
debug(
"Candidate %d : BAD good pixel count %.2f < %.2f (pos=%d neg=%d tot=%d)",
153 source.getId(), ngoodRatio, ngoodTolerance, nPos, nNeg, nPixels)
156 self.
log.
debug(
"Candidate %d : OK flux=%.2f nPos=%d nNeg=%d nTot=%d nDetPos=%d nDetNeg=%d "
157 "fPos=%.2f fNeg=%2f",
158 source.getId(), flux, nPos, nNeg, nPixels, nDetPos, nDetNeg, fPos, fNeg)