23 from __future__
import absolute_import, division, print_function
26 import lsst.pex.config
as pexConfig
27 import lsst.afw.image
as afwImage
28 import lsst.coadd.utils
as coaddUtils
29 import lsst.pipe.base
as pipeBase
30 from lsst.meas.algorithms
import CoaddPsf
31 from .coaddBase
import CoaddBaseTask
32 from .warpAndPsfMatch
import WarpAndPsfMatchTask
33 from .coaddHelpers
import groupPatchExposures, getGroupDataRef
35 __all__ = [
"MakeCoaddTempExpTask"]
39 """Config for MakeCoaddTempExpTask
41 warpAndPsfMatch = pexConfig.ConfigurableField(
42 target=WarpAndPsfMatchTask,
43 doc=
"Task to warp and PSF-match calexp",
45 doWrite = pexConfig.Field(
46 doc=
"persist <coaddName>Coadd_tempExp",
50 doOverwrite = pexConfig.Field(
51 doc=
"overwrite <coaddName>Coadd_tempExp; If False, continue if the file exists on disk",
55 bgSubtracted = pexConfig.Field(
56 doc=
"Work with a background subtracted calexp?",
63 """Task to produce <coaddName>Coadd_tempExp images
65 ConfigClass = MakeCoaddTempExpConfig
66 _DefaultName =
"makeCoaddTempExp"
69 CoaddBaseTask.__init__(self, *args, **kwargs)
70 self.makeSubtask(
"warpAndPsfMatch")
73 def run(self, patchRef, selectDataList=[]):
74 """Produce <coaddName>Coadd_tempExp images
76 <coaddName>Coadd_tempExp are produced by PSF-matching (optional) and warping.
78 @param[in] patchRef: data reference for sky map patch. Must include keys "tract", "patch",
79 plus the camera-specific filter key (e.g. "filter" or "band")
80 @return: dataRefList: a list of data references for the new <coaddName>Coadd_tempExp
82 @warning: this task assumes that all exposures in a coaddTempExp have the same filter.
84 @warning: this task sets the Calib of the coaddTempExp to the Calib of the first calexp
85 with any good pixels in the patch. For a mosaic camera the resulting Calib should be ignored
86 (assembleCoadd should determine zeropoint scaling without referring to it).
88 skyInfo = self.getSkyInfo(patchRef)
90 calExpRefList = self.selectExposures(patchRef, skyInfo, selectDataList=selectDataList)
91 if len(calExpRefList) == 0:
92 self.log.warn(
"No exposures to coadd for patch %s", patchRef.dataId)
94 self.log.info(
"Selected %d calexps for patch %s", len(calExpRefList), patchRef.dataId)
95 calExpRefList = [calExpRef
for calExpRef
in calExpRefList
if calExpRef.datasetExists(
"calexp")]
96 self.log.info(
"Processing %d existing calexps for patch %s", len(calExpRefList), patchRef.dataId)
99 self.getTempExpDatasetName())
100 self.log.info(
"Processing %d tempExps for patch %s", len(groupData.groups), patchRef.dataId)
103 for i, (tempExpTuple, calexpRefList)
in enumerate(groupData.groups.items()):
104 tempExpRef =
getGroupDataRef(patchRef.getButler(), self.getTempExpDatasetName(),
105 tempExpTuple, groupData.keys)
106 if not self.config.doOverwrite
and tempExpRef.datasetExists(datasetType=self.getTempExpDatasetName()):
107 self.log.info(
"tempCoaddExp %s exists; skipping", tempExpRef.dataId)
108 dataRefList.append(tempExpRef)
110 self.log.info(
"Processing tempExp %d/%d: id=%s", i, len(groupData.groups), tempExpRef.dataId)
116 visitId = int(tempExpRef.dataId[
"visit"])
117 except (KeyError, ValueError):
122 dataRefList.append(tempExpRef)
123 if self.config.doWrite:
124 self.writeCoaddOutput(tempExpRef, exp,
"tempExp")
126 self.log.warn(
"tempExp %s could not be created", tempExpRef.dataId)
130 """Create a tempExp from inputs
132 We iterate over the multiple calexps in a single exposure to construct
133 the warp ("tempExp") of that exposure to the supplied tract/patch.
135 Pixels that receive no pixels are set to NAN; this is not correct
136 (violates LSST algorithms group policy), but will be fixed up by
137 interpolating after the coaddition.
139 @param calexpRefList: List of data references for calexps that (may)
140 overlap the patch of interest
141 @param skyInfo: Struct from CoaddBaseTask.getSkyInfo() with geometric
142 information about the patch
143 @param visitId: integer identifier for visit, for the table that will
145 @return warped exposure, or None if no pixels overlap
147 inputRecorder = self.inputRecorder.makeCoaddTempExpRecorder(visitId, len(calexpRefList))
148 coaddTempExp = afwImage.ExposureF(skyInfo.bbox, skyInfo.wcs)
149 coaddTempExp.getMaskedImage().set(numpy.nan, afwImage.MaskU.getPlaneBitMask(
"NO_DATA"), numpy.inf)
151 didSetMetadata =
False
152 modelPsf = self.config.modelPsf.apply()
if self.config.doPsfMatch
else None
153 for calExpInd, calExpRef
in enumerate(calexpRefList):
154 self.log.info(
"Processing calexp %d of %d for this tempExp: id=%s",
155 calExpInd+1, len(calexpRefList), calExpRef.dataId)
157 ccdId = calExpRef.get(
"ccdExposureId", immediate=
True)
165 calExpRef = calExpRef.butlerSubset.butler.dataRef(
"calexp", dataId=calExpRef.dataId,
166 tract=skyInfo.tractInfo.getId())
167 calExp = self.getCalExp(calExpRef, bgSubtracted=self.config.bgSubtracted)
168 exposure = self.warpAndPsfMatch.run(calExp, modelPsf=modelPsf, wcs=skyInfo.wcs,
169 maxBBox=skyInfo.bbox).exposure
171 mimg = exposure.getMaskedImage()
172 mimg *= (coaddTempExp.getCalib().getFluxMag0()[0] / exposure.getCalib().getFluxMag0()[0])
174 numGoodPix = coaddUtils.copyGoodPixels(
175 coaddTempExp.getMaskedImage(), exposure.getMaskedImage(), self.getBadPixelMask())
176 totGoodPix += numGoodPix
177 self.log.debug(
"Calexp %s has %d good pixels in this patch (%.1f%%)",
178 calExpRef.dataId, numGoodPix, 100.0*numGoodPix/skyInfo.bbox.getArea())
179 if numGoodPix > 0
and not didSetMetadata:
180 coaddTempExp.setCalib(exposure.getCalib())
181 coaddTempExp.setFilter(exposure.getFilter())
183 coaddTempExp.setPsf(exposure.getPsf())
184 didSetMetadata =
True
185 except Exception
as e:
186 self.log.warn(
"Error processing calexp %s; skipping it: %s", calExpRef.dataId, e)
188 inputRecorder.addCalExp(calExp, ccdId, numGoodPix)
190 inputRecorder.finish(coaddTempExp, totGoodPix)
191 if totGoodPix > 0
and didSetMetadata
and not self.config.doPsfMatch:
192 coaddTempExp.setPsf(CoaddPsf(inputRecorder.coaddInputs.ccds, skyInfo.wcs))
194 self.log.info(
"coaddTempExp has %d good pixels (%.1f%%)",
195 totGoodPix, 100.0*totGoodPix/skyInfo.bbox.getArea())
196 return coaddTempExp
if totGoodPix > 0
and didSetMetadata
else None