134 def run(self, inputExp, sourceExps=[]):
135 """Measure pixel ratios between amplifiers in inputExp.
137 Extract crosstalk ratios between different amplifiers.
139 For pixels above ``config.threshold``, we calculate the ratio
140 between each background-subtracted target amp and the source
141 amp. We return a list of ratios for each pixel for each
142 target/source combination, as nested dictionary containing the
147 inputExp : `lsst.afw.image.Exposure`
148 Input exposure to measure pixel ratios on.
149 sourceExp : `list` [`lsst.afw.image.Exposure`], optional
150 List of chips to use as sources to measure inter-chip
155 results : `lsst.pipe.base.Struct`
156 The results struct containing:
158 ``outputRatios`` : `dict` [`dict` [`dict` [`dict` [`list`]]]]
159 A catalog of ratio lists. The dictionaries are
161 outputRatios[targetChip][sourceChip][targetAmp][sourceAmp]
162 contains the ratio list for that combination.
163 ``outputFluxes`` : `dict` [`dict` [`list`]]
164 A catalog of flux lists. The dictionaries are
166 outputFluxes[sourceChip][sourceAmp]
167 contains the flux list used in the outputRatios.
171 The lsstDebug.Info() method can be rewritten for __name__ =
172 `lsst.cp.pipe.measureCrosstalk`, and supports the parameters:
174 debug.display['extract'] : `bool`
175 Display the exposure under consideration, with the pixels used
176 for crosstalk measurement indicated by the DETECTED mask plane.
177 debug.display['pixels'] : `bool`
178 Display a plot of the ratio calculated for each pixel used in this
179 exposure, split by amplifier pairs. The median value is listed
182 outputRatios = defaultdict(
lambda: defaultdict(dict))
183 outputFluxes = defaultdict(
lambda: defaultdict(dict))
185 threshold = self.config.threshold
186 badPixels =
list(self.config.badMask)
188 targetDetector = inputExp.getDetector()
189 targetChip = targetDetector.getName()
192 sourceExtractExps = [inputExp]
193 sourceExtractExps.extend(sourceExps)
195 self.log.
info(
"Measuring full detector background for target: %s", targetChip)
196 targetIm = inputExp.getMaskedImage()
197 FootprintSet(targetIm, Threshold(threshold),
"DETECTED")
198 detected = targetIm.getMask().getPlaneBitMask(
"DETECTED")
199 bg = CrosstalkCalib.calculateBackground(targetIm, badPixels + [
"DETECTED"])
201 self.debugView(
'extract', inputExp)
203 for sourceExp
in sourceExtractExps:
204 sourceDetector = sourceExp.getDetector()
205 sourceChip = sourceDetector.getName()
206 sourceIm = sourceExp.getMaskedImage()
207 bad = sourceIm.getMask().getPlaneBitMask(badPixels)
208 self.log.
info(
"Measuring crosstalk from source: %s", sourceChip)
210 if sourceExp != inputExp:
211 FootprintSet(sourceIm, Threshold(threshold),
"DETECTED")
212 detected = sourceIm.getMask().getPlaneBitMask(
"DETECTED")
215 ratioDict = defaultdict(
lambda: defaultdict(list))
218 for sourceAmp
in sourceDetector:
219 sourceAmpName = sourceAmp.getName()
220 sourceAmpBBox = sourceAmp.getBBox()
if self.config.isTrimmed
else sourceAmp.getRawDataBBox()
221 sourceAmpImage = sourceIm[sourceAmpBBox]
222 sourceMask = sourceAmpImage.mask.array
223 select = ((sourceMask & detected > 0)
224 & (sourceMask & bad == 0)
225 & np.isfinite(sourceAmpImage.image.array))
226 count = np.sum(select)
227 self.log.
debug(
" Source amplifier: %s", sourceAmpName)
229 outputFluxes[sourceChip][sourceAmpName] = sourceAmpImage.image.array[select].tolist()
231 for targetAmp
in targetDetector:
233 targetAmpName = targetAmp.getName()
234 if sourceAmpName == targetAmpName
and sourceChip == targetChip:
235 ratioDict[sourceAmpName][targetAmpName] = []
237 self.log.
debug(
" Target amplifier: %s", targetAmpName)
239 targetAmpImage = CrosstalkCalib.extractAmp(targetIm.image,
240 targetAmp, sourceAmp,
241 isTrimmed=self.config.isTrimmed)
242 ratios = (targetAmpImage.array[select] - bg)/sourceAmpImage.image.array[select]
243 ratioDict[targetAmpName][sourceAmpName] = ratios.tolist()
244 extractedCount += count
246 self.debugPixels(
'pixels',
247 sourceAmpImage.image.array[select],
248 targetAmpImage.array[select] - bg,
249 sourceAmpName, targetAmpName)
251 self.log.
info(
"Extracted %d pixels from %s -> %s (targetBG: %f)",
252 extractedCount, sourceChip, targetChip, bg)
253 outputRatios[targetChip][sourceChip] = ratioDict
255 return pipeBase.Struct(
daf::base::PropertyList * list
def run(self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)