22 from __future__
import absolute_import, division, print_function
25 import lsst.pex.config
as pexConfig
26 import lsst.afw.geom
as afwGeom
27 import lsst.afw.image
as afwImage
28 import lsst.pipe.base
as pipeBase
29 import lsst.meas.algorithms
as measAlg
31 from lsst.afw.fits
import FitsError
32 from lsst.coadd.utils
import CoaddDataIdContainer
33 from .selectImages
import WcsSelectImagesTask, SelectStruct
34 from .coaddInputRecorder
import CoaddInputRecorderTask
37 from lsst.meas.mosaic
import applyMosaicResults
39 applyMosaicResults =
None
41 __all__ = [
"CoaddBaseTask",
"getSkyInfo"]
45 """Config for CoaddBaseTask
47 coaddName = pexConfig.Field(
48 doc=
"Coadd name: typically one of deep or goodSeeing.",
52 select = pexConfig.ConfigurableField(
53 doc=
"Image selection subtask.",
54 target=WcsSelectImagesTask,
56 badMaskPlanes = pexConfig.ListField(
58 doc=
"Mask planes that, if set, the associated pixel should not be included in the coaddTempExp.",
61 inputRecorder = pexConfig.ConfigurableField(
62 doc=
"Subtask that helps fill CoaddInputs catalogs added to the final Exposure",
63 target=CoaddInputRecorderTask
65 doPsfMatch = pexConfig.Field(dtype=bool, doc=
"Match to modelPsf?", default=
False)
66 modelPsf = measAlg.GaussianPsfFactory.makeField(doc=
"Model Psf factory")
67 doApplyUberCal = pexConfig.Field(
69 doc=
"Apply meas_mosaic ubercal results to input calexps?",
78 return pipeBase.TaskRunner.getTargetList(parsedCmd, selectDataList=parsedCmd.selectId.dataList,
83 """Base class for coaddition.
85 Subclasses must specify _DefaultName
87 ConfigClass = CoaddBaseConfig
88 RunnerClass = CoaddTaskRunner
91 pipeBase.Task.__init__(self, *args, **kwargs)
92 self.makeSubtask(
"select")
93 self.makeSubtask(
"inputRecorder")
97 \brief Select exposures to coadd
99 Get the corners of the bbox supplied in skyInfo using \ref afwGeom.Box2D and convert the pixel
100 positions of the bbox corners to sky coordinates using \ref skyInfo.wcs.pixelToSky. Use the
101 \ref WcsSelectImagesTask_ "WcsSelectImagesTask" to select exposures that lie inside the patch
102 indicated by the dataRef.
104 \param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch",
105 plus the camera-specific filter key (e.g. "filter" or "band")
106 \param[in] skyInfo geometry for the patch; output from getSkyInfo
107 \return a list of science exposures to coadd, as butler data references
111 cornerPosList = afwGeom.Box2D(skyInfo.bbox).getCorners()
112 coordList = [skyInfo.wcs.pixelToSky(pos)
for pos
in cornerPosList]
113 return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
117 \brief Use \ref getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox
120 \param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
122 \return pipe_base Struct containing:
124 - tractInfo: information for chosen tract of sky map
125 - patchInfo: information about chosen patch of tract
127 - bbox: outer bbox of patch, as an afwGeom Box2I
129 return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
132 """!Return one "calexp" calibrated exposure
134 @param[in] dataRef a sensor-level data reference
135 @param[in] bgSubtracted return calexp with background subtracted? If False get the
136 calexp's background background model and add it to the calexp.
137 @return calibrated exposure
139 If config.doApplyUberCal, meas_mosaic calibrations will be applied to
140 the returned exposure using applyMosaicResults.
142 exposure = dataRef.get(
"calexp", immediate=
True)
144 background = dataRef.get(
"calexpBackground", immediate=
True)
145 mi = exposure.getMaskedImage()
146 mi += background.getImage()
148 if not self.config.doApplyUberCal:
150 if applyMosaicResults
is None:
152 "Cannot use improved calibrations for %s because meas_mosaic could not be imported."
160 return self.config.coaddName +
"Coadd"
163 return self.config.coaddName +
"Coadd_tempExp"
166 def _makeArgumentParser(cls):
167 """Create an argument parser
169 parser = pipeBase.ArgumentParser(name=cls._DefaultName)
170 parser.add_id_argument(
"--id",
"deepCoadd", help=
"data ID, e.g. --id tract=12345 patch=1,2",
171 ContainerClass=CoaddDataIdContainer)
172 parser.add_id_argument(
"--selectId",
"calexp", help=
"data ID, e.g. --selectId visit=6789 ccd=0..9",
173 ContainerClass=SelectDataIdContainer)
176 def _getConfigName(self):
177 """Return the name of the config dataset
179 return "%s_%s_config" % (self.config.coaddName, self._DefaultName)
181 def _getMetadataName(self):
182 """Return the name of the metadata dataset
184 return "%s_%s_metadata" % (self.config.coaddName, self._DefaultName)
188 \brief Convenience method to provide the bitmask from the mask plane names
190 return afwImage.MaskU.getPlaneBitMask(self.config.badMaskPlanes)
194 \brief Write a coadd product through the butler
196 \param[in] dataRef data reference for coadd
197 \param[in,out] obj coadd product to write
198 \param[in] suffix suffix to apply to coadd dataset name
201 if suffix
is not None:
202 objName +=
"_" + suffix
203 self.log.info(
"Persisting %s" % objName)
204 dataRef.put(obj, objName)
209 \brief A dataId container for inputs to be selected.
211 Read the header (including the size and Wcs) for all specified
212 inputs and pass those along, ultimately for the SelectImagesTask.
213 This is most useful when used with multiprocessing, as input headers are
218 """Add a dataList containing useful information for selecting images"""
221 for ref
in self.refList:
223 md = ref.get(
"calexp_md", immediate=
True)
224 wcs = afwImage.makeWcs(md)
225 data = SelectStruct(dataRef=ref, wcs=wcs, dims=(md.get(
"NAXIS1"), md.get(
"NAXIS2")))
226 except FitsError
as e:
227 namespace.log.warn(
"Unable to construct Wcs from %s" % (ref.dataId))
229 self.dataList.append(data)
234 \brief Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded.
236 \param[in] coaddName coadd name; typically one of deep or goodSeeing
237 \param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
239 \return pipe_base Struct containing:
241 - tractInfo: information for chosen tract of sky map
242 - patchInfo: information about chosen patch of tract
244 - bbox: outer bbox of patch, as an afwGeom Box2I
246 skyMap = patchRef.get(coaddName +
"Coadd_skyMap")
247 tractId = patchRef.dataId[
"tract"]
248 tractInfo = skyMap[tractId]
251 patchIndex = tuple(int(i)
for i
in patchRef.dataId[
"patch"].split(
","))
252 patchInfo = tractInfo.getPatchInfo(patchIndex)
254 return pipeBase.Struct(
258 wcs=tractInfo.getWcs(),
259 bbox=patchInfo.getOuterBBox(),
265 \brief Scale the variance in a maskedImage
267 The variance plane in a convolved or warped image (or a coadd derived
268 from warped images) does not accurately reflect the noise properties of
269 the image because variance has been lost to covariance. This function
270 attempts to correct for this by scaling the variance plane to match
271 the observed variance in the image. This is not perfect (because we're
272 not tracking the covariance) but it's simple and is often good enough.
274 @param maskedImage MaskedImage to operate on; variance will be scaled
275 @param maskPlanes List of mask planes for pixels to reject
276 @param log Log for reporting the renormalization factor; or None
277 @return renormalisation factor
279 variance = maskedImage.getVariance()
280 sigNoise = maskedImage.getImage().getArray()/numpy.sqrt(variance.getArray())
281 maskVal = maskedImage.getMask().getPlaneBitMask(maskPlanes)
282 good = (maskedImage.getMask().getArray() & maskVal) == 0
284 q1, q3 = numpy.percentile(sigNoise[good], (25, 75))
285 stdev = 0.74*(q3 - q1)
288 log.info(
"Renormalizing variance by %f" % (ratio,))
def getTempExpDatasetName
def getBadPixelMask
Convenience method to provide the bitmask from the mask plane names.
A dataId container for inputs to be selected.
def getCalExp
Return one "calexp" calibrated exposure.
def scaleVariance
Scale the variance in a maskedImage.
def selectExposures
Select exposures to coadd.
def writeCoaddOutput
Write a coadd product through the butler.
def getSkyInfo
Use getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox of the patch...
def getSkyInfo
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded...