166 def run(self, snap0, snap1, defects=None):
167 """Combine two snaps.
175 defects : `list` or `None`, optional
176 Defect list (for repair task).
180 result : `lsst.pipe.base.Struct`
181 Results as a struct with attributes:
184 Snap-combined exposure.
186 Detected sources, or `None` if detection not performed.
191 if self.config.doRepair:
192 self.log.info(
"snapCombine repair")
193 psf = self.
makeInitialPsf(snap0, fwhmPix=self.config.repairPsfFwhm)
196 self.repair.run(snap0, defects=defects, keepCRs=
False)
197 self.repair.run(snap1, defects=defects, keepCRs=
False)
199 repair0frame = getDebugFrame(self._display,
"repair0")
201 getDisplay(repair0frame).mtv(snap0)
202 repair1frame = getDebugFrame(self._display,
"repair1")
204 getDisplay(repair1frame).mtv(snap1)
206 if self.config.doDiffIm:
207 if self.config.doPsfMatch:
208 raise NotImplementedError(
"PSF-matching of snaps is not yet supported.")
211 diffExp = afwImage.ExposureF(snap0,
True)
212 diffMi = diffExp.getMaskedImage()
213 diffMi -= snap1.getMaskedImage()
217 table = afwTable.SourceTable.make(self.
schema)
219 detRet = self.detection.run(table, diffExp)
220 sources = detRet.sources
221 if self.config.doMeasurement:
222 self.measurement.measure(diffExp, sources)
224 mask0 = snap0.getMaskedImage().getMask()
225 mask1 = snap1.getMaskedImage().getMask()
226 detRet.positive.setMask(mask0,
"DETECTED")
227 detRet.negative.setMask(mask1,
"DETECTED")
229 maskD = diffExp.getMaskedImage().getMask()
230 detRet.positive.setMask(maskD,
"DETECTED")
231 detRet.negative.setMask(maskD,
"DETECTED_NEGATIVE")
233 combinedExp = self.
addSnaps(snap0, snap1)
235 return pipeBase.Struct(
236 exposure=combinedExp,
241 """Add two snap exposures together, returning a new exposure.
252 combinedExp : `Unknown`
255 self.log.info(
"snapCombine addSnaps")
257 combinedExp = snap0.Factory(snap0,
True)
258 combinedMi = combinedExp.getMaskedImage()
261 weightMap = combinedMi.getImage().Factory(combinedMi.getBBox())
263 badPixelMask = afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
264 addToCoadd(combinedMi, weightMap, snap0.getMaskedImage(), badPixelMask, weight)
265 addToCoadd(combinedMi, weightMap, snap1.getMaskedImage(), badPixelMask, weight)
270 combinedMi /= weightMap
271 setCoaddEdgeBits(combinedMi.getMask(), weightMap)
276 combinedMetadata = combinedExp.getMetadata()
277 metadata0 = snap0.getMetadata()
278 metadata1 = snap1.getMetadata()
279 self.
fixMetadata(combinedMetadata, metadata0, metadata1)
284 """Fix the metadata of the combined exposure (in place).
286 This implementation handles items specified by config.averageKeys and config.sumKeys,
287 which have data type restrictions. To handle other data types (such as sexagesimal
288 positions and ISO dates) you must supplement this method with your own code.
292 combinedMetadata : `lsst.daf.base.PropertySet`
293 Metadata of combined exposure;
294 on input this is a deep copy of metadata0 (a PropertySet).
295 metadata0 : `lsst.daf.base.PropertySet`
296 Metadata of snap0 (a PropertySet).
297 metadata1 : `lsst.daf.base.PropertySet`
298 Metadata of snap1 (a PropertySet).
302 The inputs are presently PropertySets due to ticket #2542. However, in some sense
303 they are just PropertyLists that are missing some methods. In particular: comments and order
304 are preserved if you alter an existing value with set(key, value).
307 if self.config.averageKeys:
308 keyDoAvgList += [(key, 1)
for key
in self.config.averageKeys]
309 if self.config.sumKeys:
310 keyDoAvgList += [(key, 0)
for key
in self.config.sumKeys]
311 for key, doAvg
in keyDoAvgList:
312 opStr =
"average" if doAvg
else "sum"
314 val0 = metadata0.getScalar(key)
315 val1 = metadata1.getScalar(key)
317 self.log.warning(
"Could not %s metadata %r: missing from one or both exposures", opStr, key)
321 combinedVal = val0 + val1
325 self.log.warning(
"Could not %s metadata %r: value %r and/or %r not numeric",
326 opStr, key, val0, val1)
329 combinedMetadata.set(key, combinedVal)
332 """Initialise the detection procedure by setting the PSF and WCS.
334 exposure : `lsst.afw.image.Exposure`
343 Raised if any of the following occur:
344 - No exposure provided.
345 - No wcs in exposure.
347 assert exposure,
"No exposure provided"
348 wcs = exposure.getWcs()
349 assert wcs,
"No wcs in exposure"
352 fwhmPix = self.config.initialPsf.fwhm / wcs.getPixelScale().asArcseconds()
354 size = self.config.initialPsf.size
355 model = self.config.initialPsf.model
356 self.log.info(
"installInitialPsf fwhm=%s pixels; size=%s pixels", fwhmPix, size)
357 psfCls = getattr(measAlg, model +
"Psf")
358 psf = psfCls(size, size, fwhmPix/(2.0*num.sqrt(2*num.log(2.0))))