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
30 import lsst.log
as log
32 from lsst.afw.fits
import FitsError
33 from lsst.coadd.utils
import CoaddDataIdContainer
34 from .selectImages
import WcsSelectImagesTask, SelectStruct
35 from .coaddInputRecorder
import CoaddInputRecorderTask
38 from lsst.meas.mosaic
import applyMosaicResults
40 applyMosaicResults =
None 42 __all__ = [
"CoaddBaseTask",
"getSkyInfo"]
46 """!Configuration parameters for CoaddBaseTask 48 \anchor CoaddBaseConfig_ 50 \brief Configuration parameters shared between MakeCoaddTempExp and AssembleCoadd 52 coaddName = pexConfig.Field(
53 doc=
"Coadd name: typically one of deep or goodSeeing.",
57 select = pexConfig.ConfigurableField(
58 doc=
"Image selection subtask.",
59 target=WcsSelectImagesTask,
61 badMaskPlanes = pexConfig.ListField(
63 doc=
"Mask planes that, if set, the associated pixel should not be included in the coaddTempExp.",
66 inputRecorder = pexConfig.ConfigurableField(
67 doc=
"Subtask that helps fill CoaddInputs catalogs added to the final Exposure",
68 target=CoaddInputRecorderTask
70 doPsfMatch = pexConfig.Field(
72 doc=
"Match to modelPsf? Deprecated. Sets makePsfMatched=True, makeDirect=False",
75 modelPsf = measAlg.GaussianPsfFactory.makeField(doc=
"Model Psf factory")
76 doApplyUberCal = pexConfig.Field(
78 doc=
"Apply meas_mosaic ubercal results to input calexps?",
81 makeDirect = pexConfig.Field(
82 doc=
"Make direct Warp/Coadds",
86 makePsfMatched = pexConfig.Field(
87 doc=
"Make Psf-Matched Warp/Coadd?",
93 pexConfig.Config.validate(self)
95 raise RuntimeError(
"At least one of config.makePsfMatched and config.makeDirect must be True")
99 log.warn(
"Config doPsfMatch deprecated. Setting makePsfMatched=True and makeDirect=False")
108 return pipeBase.TaskRunner.getTargetList(parsedCmd, selectDataList=parsedCmd.selectId.dataList,
113 """!Base class for coaddition. 115 Subclasses must specify _DefaultName 117 ConfigClass = CoaddBaseConfig
118 RunnerClass = CoaddTaskRunner
121 pipeBase.Task.__init__(self, *args, **kwargs)
122 self.makeSubtask(
"select")
123 self.makeSubtask(
"inputRecorder")
127 \brief Select exposures to coadd 129 Get the corners of the bbox supplied in skyInfo using \ref afwGeom.Box2D and convert the pixel 130 positions of the bbox corners to sky coordinates using \ref skyInfo.wcs.pixelToSky. Use the 131 \ref WcsSelectImagesTask_ "WcsSelectImagesTask" to select exposures that lie inside the patch 132 indicated by the dataRef. 134 \param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch", 135 plus the camera-specific filter key (e.g. "filter" or "band") 136 \param[in] skyInfo geometry for the patch; output from getSkyInfo 137 \return a list of science exposures to coadd, as butler data references 141 cornerPosList = afwGeom.Box2D(skyInfo.bbox).getCorners()
142 coordList = [skyInfo.wcs.pixelToSky(pos)
for pos
in cornerPosList]
143 return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
147 \brief Use \ref getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox 150 \param[in] patchRef data reference for sky map. Must include keys "tract" and "patch" 152 \return pipe_base Struct containing: 154 - tractInfo: information for chosen tract of sky map 155 - patchInfo: information about chosen patch of tract 157 - bbox: outer bbox of patch, as an afwGeom Box2I 159 return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
162 """!Return one "calexp" calibrated exposure 164 @param[in] dataRef a sensor-level data reference 165 @param[in] bgSubtracted return calexp with background subtracted? If False get the 166 calexp's background background model and add it to the calexp. 167 @return calibrated exposure 169 If config.doApplyUberCal, meas_mosaic calibrations will be applied to 170 the returned exposure using applyMosaicResults. 172 exposure = dataRef.get(
"calexp", immediate=
True)
174 background = dataRef.get(
"calexpBackground", immediate=
True)
175 mi = exposure.getMaskedImage()
176 mi += background.getImage()
178 if not self.config.doApplyUberCal:
180 if applyMosaicResults
is None:
182 "Cannot use improved calibrations for %s because meas_mosaic could not be imported." 190 """Return coadd name for given warpType and task config 195 Either 'direct' or 'psfMatched' 199 CoaddDatasetName : `string` 201 suffix =
"" if warpType ==
"direct" else warpType[0].upper() + warpType[1:]
202 return self.config.coaddName +
"Coadd" + suffix
205 """Return warp name for given warpType and task config 210 Either 'direct' or 'psfMatched' 214 WarpDatasetName : `string` 216 return self.config.coaddName +
"Coadd_" + warpType +
"Warp" 219 """Return list of requested warp types per the config. 222 if self.config.makeDirect:
223 warpTypeList.append(
"direct")
224 if self.config.makePsfMatched:
225 warpTypeList.append(
"psfMatched")
229 def _makeArgumentParser(cls):
230 """Create an argument parser 232 parser = pipeBase.ArgumentParser(name=cls._DefaultName)
233 parser.add_id_argument(
"--id",
"deepCoadd", help=
"data ID, e.g. --id tract=12345 patch=1,2",
234 ContainerClass=CoaddDataIdContainer)
235 parser.add_id_argument(
"--selectId",
"calexp", help=
"data ID, e.g. --selectId visit=6789 ccd=0..9",
236 ContainerClass=SelectDataIdContainer)
239 def _getConfigName(self):
240 """Return the name of the config dataset 242 return "%s_%s_config" % (self.config.coaddName, self._DefaultName)
244 def _getMetadataName(self):
245 """Return the name of the metadata dataset 247 return "%s_%s_metadata" % (self.config.coaddName, self._DefaultName)
251 \brief Convenience method to provide the bitmask from the mask plane names 253 return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
258 \brief A dataId container for inputs to be selected. 260 Read the header (including the size and Wcs) for all specified 261 inputs and pass those along, ultimately for the SelectImagesTask. 262 This is most useful when used with multiprocessing, as input headers are 267 """Add a dataList containing useful information for selecting images""" 270 for ref
in self.refList:
272 md = ref.get(
"calexp_md", immediate=
True)
273 wcs = afwImage.makeWcs(md)
274 data =
SelectStruct(dataRef=ref, wcs=wcs, dims=(md.get(
"NAXIS1"), md.get(
"NAXIS2")))
275 except FitsError
as e:
276 namespace.log.warn(
"Unable to construct Wcs from %s" % (ref.dataId))
283 \brief Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded. 285 \param[in] coaddName coadd name; typically one of deep or goodSeeing 286 \param[in] patchRef data reference for sky map. Must include keys "tract" and "patch" 288 \return pipe_base Struct containing: 290 - tractInfo: information for chosen tract of sky map 291 - patchInfo: information about chosen patch of tract 293 - bbox: outer bbox of patch, as an afwGeom Box2I 295 skyMap = patchRef.get(coaddName +
"Coadd_skyMap")
296 tractId = patchRef.dataId[
"tract"]
297 tractInfo = skyMap[tractId]
300 patchIndex = tuple(int(i)
for i
in patchRef.dataId[
"patch"].split(
","))
301 patchInfo = tractInfo.getPatchInfo(patchIndex)
303 return pipeBase.Struct(
307 wcs=tractInfo.getWcs(),
308 bbox=patchInfo.getOuterBBox(),
314 \brief Scale the variance in a maskedImage 316 The variance plane in a convolved or warped image (or a coadd derived 317 from warped images) does not accurately reflect the noise properties of 318 the image because variance has been lost to covariance. This function 319 attempts to correct for this by scaling the variance plane to match 320 the observed variance in the image. This is not perfect (because we're 321 not tracking the covariance) but it's simple and is often good enough. 323 @param maskedImage MaskedImage to operate on; variance will be scaled 324 @param maskPlanes List of mask planes for pixels to reject 325 @param log Log for reporting the renormalization factor; or None 326 @return renormalisation factor 328 variance = maskedImage.getVariance()
329 sigNoise = maskedImage.getImage().getArray()/numpy.sqrt(variance.getArray())
330 maskVal = maskedImage.getMask().getPlaneBitMask(maskPlanes)
331 good = (maskedImage.getMask().getArray() & maskVal) == 0
333 q1, q3 = numpy.percentile(sigNoise[good], (25, 75))
334 stdev = 0.74*(q3 - q1)
337 log.info(
"Renormalizing variance by %f" % (ratio,))
def getCoaddDatasetName(self, warpType="direct")
def makeDataRefList(self, namespace)
Base class for coaddition.
Configuration parameters for CoaddBaseTask.
A dataId container for inputs to be selected.
def __init__(self, args, kwargs)
def getSkyInfo(self, patchRef)
Use getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox of the patch...
def getTempExpDatasetName(self, warpType="direct")
def getBadPixelMask(self)
Convenience method to provide the bitmask from the mask plane names.
def getTargetList(parsedCmd, kwargs)
def selectExposures(self, patchRef, skyInfo=None, selectDataList=[])
Select exposures to coadd.
def getCalExp(self, dataRef, bgSubtracted)
Return one "calexp" calibrated exposure.
def scaleVariance(maskedImage, maskPlanes, log=None)
Scale the variance in a maskedImage.
def getWarpTypeList(self)
def getSkyInfo(coaddName, patchRef)
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded...