LSSTApplications  20.0.0
LSSTDataManagementBasePackage
coaddBase.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2015 AURA/LSST.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 import lsst.pex.config as pexConfig
23 import lsst.geom as geom
24 import lsst.afw.geom as afwGeom
25 import lsst.afw.image as afwImage
26 import lsst.pipe.base as pipeBase
27 import lsst.meas.algorithms as measAlg
28 
29 from lsst.afw.fits import FitsError
30 from lsst.coadd.utils import CoaddDataIdContainer
31 from .selectImages import WcsSelectImagesTask, SelectStruct
32 from .coaddInputRecorder import CoaddInputRecorderTask
33 from .scaleVariance import ScaleVarianceTask
34 
35 __all__ = ["CoaddBaseTask", "getSkyInfo", "makeSkyInfo", "makeCoaddSuffix"]
36 
37 
38 class CoaddBaseConfig(pexConfig.Config):
39  """!Configuration parameters for CoaddBaseTask
40 
41  @anchor CoaddBaseConfig_
42 
43  @brief Configuration parameters shared between MakeCoaddTempExp and AssembleCoadd
44  """
45  coaddName = pexConfig.Field(
46  doc="Coadd name: typically one of deep or goodSeeing.",
47  dtype=str,
48  default="deep",
49  )
50  select = pexConfig.ConfigurableField(
51  doc="Image selection subtask.",
52  target=WcsSelectImagesTask,
53  )
54  badMaskPlanes = pexConfig.ListField(
55  dtype=str,
56  doc="Mask planes that, if set, the associated pixel should not be included in the coaddTempExp.",
57  default=("NO_DATA",),
58  )
59  inputRecorder = pexConfig.ConfigurableField(
60  doc="Subtask that helps fill CoaddInputs catalogs added to the final Exposure",
61  target=CoaddInputRecorderTask
62  )
63  doPsfMatch = pexConfig.Field(
64  dtype=bool,
65  doc="Match to modelPsf? Deprecated. Sets makePsfMatched=True, makeDirect=False",
66  default=False
67  )
68  modelPsf = measAlg.GaussianPsfFactory.makeField(doc="Model Psf factory")
69  doApplyUberCal = pexConfig.Field(
70  dtype=bool,
71  doc=("Apply ubercalibrated WCS and PhotoCalib results to input calexps? "
72  "This field is no longer used, and has been deprecated by DM-21308. "
73  "It will be removed after v20. Use doApplyExternalPhotoCalib and "
74  "doApplyExternalSkyWcs instead."),
75  default=False
76  )
77  doApplyExternalPhotoCalib = pexConfig.Field(
78  dtype=bool,
79  default=False,
80  doc=("Whether to apply external photometric calibration via an "
81  "`lsst.afw.image.PhotoCalib` object. Uses the "
82  "`externalPhotoCalibName` field to determine which calibration "
83  "to load.")
84  )
85  externalPhotoCalibName = pexConfig.ChoiceField(
86  dtype=str,
87  doc="Type of external PhotoCalib if `doApplyExternalPhotoCalib` is True.",
88  default="jointcal",
89  allowed={
90  "jointcal": "Use jointcal_photoCalib",
91  "fgcm": "Use fgcm_photoCalib",
92  "fgcm_tract": "Use fgcm_tract_photoCalib"
93  }
94  )
95  doApplyExternalSkyWcs = pexConfig.Field(
96  dtype=bool,
97  default=False,
98  doc=("Whether to apply external astrometric calibration via an "
99  "`lsst.afw.geom.SkyWcs` object. Uses `externalSkyWcsName` "
100  "field to determine which calibration to load.")
101  )
102  externalSkyWcsName = pexConfig.ChoiceField(
103  dtype=str,
104  doc="Type of external SkyWcs if `doApplyExternalSkyWcs` is True.",
105  default="jointcal",
106  allowed={
107  "jointcal": "Use jointcal_wcs"
108  }
109  )
110  includeCalibVar = pexConfig.Field(
111  dtype=bool,
112  doc="Add photometric calibration variance to warp variance plane.",
113  default=False
114  )
115  matchingKernelSize = pexConfig.Field(
116  dtype=int,
117  doc="Size in pixels of matching kernel. Must be odd.",
118  default=21,
119  check=lambda x: x % 2 == 1
120  )
121 
122 
123 class CoaddTaskRunner(pipeBase.TaskRunner):
124 
125  @staticmethod
126  def getTargetList(parsedCmd, **kwargs):
127  return pipeBase.TaskRunner.getTargetList(parsedCmd, selectDataList=parsedCmd.selectId.dataList,
128  **kwargs)
129 
130 
131 class CoaddBaseTask(pipeBase.CmdLineTask):
132  """!Base class for coaddition.
133 
134  Subclasses must specify _DefaultName
135  """
136  ConfigClass = CoaddBaseConfig
137  RunnerClass = CoaddTaskRunner
138 
139  def __init__(self, **kwargs):
140  super().__init__(**kwargs)
141  self.makeSubtask("select")
142  self.makeSubtask("inputRecorder")
143 
144  def selectExposures(self, patchRef, skyInfo=None, selectDataList=[]):
145  """!
146  @brief Select exposures to coadd
147 
148  Get the corners of the bbox supplied in skyInfo using @ref geom.Box2D and convert the pixel
149  positions of the bbox corners to sky coordinates using @ref skyInfo.wcs.pixelToSky. Use the
150  @ref WcsSelectImagesTask_ "WcsSelectImagesTask" to select exposures that lie inside the patch
151  indicated by the dataRef.
152 
153  @param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch",
154  plus the camera-specific filter key (e.g. "filter" or "band")
155  @param[in] skyInfo geometry for the patch; output from getSkyInfo
156  @return a list of science exposures to coadd, as butler data references
157  """
158  if skyInfo is None:
159  skyInfo = self.getSkyInfo(patchRef)
160  cornerPosList = geom.Box2D(skyInfo.bbox).getCorners()
161  coordList = [skyInfo.wcs.pixelToSky(pos) for pos in cornerPosList]
162  return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
163 
164  def getSkyInfo(self, patchRef):
165  """!
166  @brief Use @ref getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox
167  of the patch.
168 
169  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
170 
171  @return pipe_base Struct containing:
172  - skyMap: sky map
173  - tractInfo: information for chosen tract of sky map
174  - patchInfo: information about chosen patch of tract
175  - wcs: WCS of tract
176  - bbox: outer bbox of patch, as an geom Box2I
177  """
178  return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
179 
180  def getCoaddDatasetName(self, warpType="direct"):
181  """Return coadd name for given warpType and task config
182 
183  Parameters
184  ----------
185  warpType : string
186  Either 'direct' or 'psfMatched'
187 
188  Returns
189  -------
190  CoaddDatasetName : `string`
191  """
192  return self.config.coaddName + "Coadd" + makeCoaddSuffix(warpType)
193 
194  def getTempExpDatasetName(self, warpType="direct"):
195  """Return warp name for given warpType and task config
196 
197  Parameters
198  ----------
199  warpType : string
200  Either 'direct' or 'psfMatched'
201 
202  Returns
203  -------
204  WarpDatasetName : `string`
205  """
206  return self.config.coaddName + "Coadd_" + warpType + "Warp"
207 
208  @classmethod
209  def _makeArgumentParser(cls):
210  """Create an argument parser
211  """
212  parser = pipeBase.ArgumentParser(name=cls._DefaultName)
213  parser.add_id_argument("--id", "deepCoadd", help="data ID, e.g. --id tract=12345 patch=1,2",
214  ContainerClass=CoaddDataIdContainer)
215  parser.add_id_argument("--selectId", "calexp", help="data ID, e.g. --selectId visit=6789 ccd=0..9",
216  ContainerClass=SelectDataIdContainer)
217  return parser
218 
219  def _getConfigName(self):
220  """Return the name of the config dataset
221  """
222  return "%s_%s_config" % (self.config.coaddName, self._DefaultName)
223 
224  def _getMetadataName(self):
225  """Return the name of the metadata dataset
226  """
227  return "%s_%s_metadata" % (self.config.coaddName, self._DefaultName)
228 
229  def getBadPixelMask(self):
230  """!
231  @brief Convenience method to provide the bitmask from the mask plane names
232  """
233  return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
234 
235 
236 class SelectDataIdContainer(pipeBase.DataIdContainer):
237  """!
238  @brief A dataId container for inputs to be selected.
239 
240  Read the header (including the size and Wcs) for all specified
241  inputs and pass those along, ultimately for the SelectImagesTask.
242  This is most useful when used with multiprocessing, as input headers are
243  only read once.
244  """
245 
246  def makeDataRefList(self, namespace):
247  """Add a dataList containing useful information for selecting images"""
248  super(SelectDataIdContainer, self).makeDataRefList(namespace)
249  self.dataList = []
250  for ref in self.refList:
251  try:
252  md = ref.get("calexp_md", immediate=True)
253  wcs = afwGeom.makeSkyWcs(md)
254  data = SelectStruct(dataRef=ref, wcs=wcs, bbox=afwImage.bboxFromMetadata(md))
255  except FitsError:
256  namespace.log.warn("Unable to construct Wcs from %s" % (ref.dataId))
257  continue
258  self.dataList.append(data)
259 
260 
261 def getSkyInfo(coaddName, patchRef):
262  """!
263  @brief Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded.
264 
265  @param[in] coaddName coadd name; typically one of deep or goodSeeing
266  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
267 
268  @return pipe_base Struct containing:
269  - skyMap: sky map
270  - tractInfo: information for chosen tract of sky map
271  - patchInfo: information about chosen patch of tract
272  - wcs: WCS of tract
273  - bbox: outer bbox of patch, as an geom Box2I
274  """
275  skyMap = patchRef.get(coaddName + "Coadd_skyMap")
276  return makeSkyInfo(skyMap, patchRef.dataId["tract"], patchRef.dataId["patch"])
277 
278 
279 def makeSkyInfo(skyMap, tractId, patchId):
280  """Return SkyInfo Struct
281 
282  Constructs SkyInfo used by coaddition tasks for multiple
283  patchId formats.
284 
285  Parameters
286  ----------
287  skyMap : `lsst.skyMap.SkyMap`
288  tractId : int
289  patchId : str or int or tuple of int
290  Either Gen2-style comma delimited string (e.g. '4,5'),
291  tuple of integers (e.g (4, 5), Gen3-style integer.
292  """
293  tractInfo = skyMap[tractId]
294 
295  if isinstance(patchId, str) and ',' in patchId:
296  # patch format is "xIndex,yIndex"
297  patchIndex = tuple(int(i) for i in patchId.split(","))
298  else:
299  patchIndex = patchId
300 
301  patchInfo = tractInfo.getPatchInfo(patchIndex)
302 
303  return pipeBase.Struct(
304  skyMap=skyMap,
305  tractInfo=tractInfo,
306  patchInfo=patchInfo,
307  wcs=tractInfo.getWcs(),
308  bbox=patchInfo.getOuterBBox(),
309  )
310 
311 
312 def scaleVariance(maskedImage, maskPlanes, log=None):
313  """!
314  @brief Scale the variance in a maskedImage
315 
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.
322 
323  @deprecated Use the ScaleVarianceTask instead.
324 
325  @param maskedImage MaskedImage to operate on; variance will be scaled
326  @param maskPlanes List of mask planes for pixels to reject
327  @param log Log for reporting the renormalization factor; or None
328  @return renormalisation factor
329  """
330  config = ScaleVarianceTask.ConfigClass()
331  config.maskPlanes = maskPlanes
332  task = ScaleVarianceTask(config=config, name="scaleVariance", log=log)
333  return task.run(maskedImage)
334 
335 
336 def makeCoaddSuffix(warpType="direct"):
337  """Return coadd suffix for warpType
338 
339  Parameters
340  ----------
341  warpType : string
342  Either 'direct' or 'psfMatched'
343 
344  Returns
345  -------
346  CoaddSuffix : `string`
347  """
348  suffix = "" if warpType == "direct" else warpType[0].upper() + warpType[1:]
349  return suffix
lsst.pipe.tasks.coaddBase.scaleVariance
def scaleVariance(maskedImage, maskPlanes, log=None)
Scale the variance in a maskedImage.
Definition: coaddBase.py:312
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
lsst.pipe.tasks.coaddBase.CoaddBaseTask.selectExposures
def selectExposures(self, patchRef, skyInfo=None, selectDataList=[])
Select exposures to coadd.
Definition: coaddBase.py:144
lsst.pipe.tasks.coaddBase.SelectDataIdContainer.makeDataRefList
def makeDataRefList(self, namespace)
Definition: coaddBase.py:246
lsst.pipe.tasks.coaddBase.getSkyInfo
def getSkyInfo(coaddName, patchRef)
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded.
Definition: coaddBase.py:261
lsst.pipe.tasks.coaddBase.CoaddBaseTask.getBadPixelMask
def getBadPixelMask(self)
Convenience method to provide the bitmask from the mask plane names.
Definition: coaddBase.py:229
ast::append
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
Definition: functional.cc:33
lsst.pipe.tasks.coaddBase.makeSkyInfo
def makeSkyInfo(skyMap, tractId, patchId)
Definition: coaddBase.py:279
lsst.pipe.tasks.scaleVariance.ScaleVarianceTask
Definition: scaleVariance.py:48
lsst.pipe.tasks.coaddBase.CoaddBaseTask.getCoaddDatasetName
def getCoaddDatasetName(self, warpType="direct")
Definition: coaddBase.py:180
lsst.pipe.tasks.coaddBase.CoaddTaskRunner
Definition: coaddBase.py:123
lsst.pipe.tasks.coaddBase.CoaddBaseConfig
Configuration parameters for CoaddBaseTask.
Definition: coaddBase.py:38
lsst.pipe.tasks.coaddBase.CoaddBaseTask.getSkyInfo
def getSkyInfo(self, patchRef)
Use getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox of the patch...
Definition: coaddBase.py:164
lsst.pipe.tasks.coaddBase.CoaddBaseTask.getTempExpDatasetName
def getTempExpDatasetName(self, warpType="direct")
Definition: coaddBase.py:194
lsst::afw::geom::makeSkyWcs
std::shared_ptr< SkyWcs > makeSkyWcs(TransformPoint2ToPoint2 const &pixelsToFieldAngle, lsst::geom::Angle const &orientation, bool flipX, lsst::geom::SpherePoint const &boresight, std::string const &projection="TAN")
Construct a FITS SkyWcs from camera geometry.
Definition: SkyWcs.cc:536
lsst.pipe.tasks.selectImages.SelectStruct
Definition: selectImages.py:163
lsst::geom
Definition: geomOperators.dox:4
lsst::afw::image::bboxFromMetadata
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
Definition: Image.cc:694
lsst::afw::fits
Definition: fits.h:31
lsst.pipe.tasks.coaddBase.makeCoaddSuffix
def makeCoaddSuffix(warpType="direct")
Definition: coaddBase.py:336
lsst.pipe.tasks.coaddBase.CoaddTaskRunner.getTargetList
def getTargetList(parsedCmd, **kwargs)
Definition: coaddBase.py:126
lsst.pipe.tasks.coaddBase.CoaddBaseTask
Base class for coaddition.
Definition: coaddBase.py:131
lsst.pipe.tasks.coaddBase.SelectDataIdContainer
A dataId container for inputs to be selected.
Definition: coaddBase.py:236
lsst.pipe.tasks.coaddBase.SelectDataIdContainer.dataList
dataList
Definition: coaddBase.py:249
lsst::geom::Box2D
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
lsst.pipe.base
Definition: __init__.py:1
lsst::meas::algorithms
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations.
Definition: CoaddBoundedField.h:34
lsst.pipe.tasks.coaddBase.CoaddBaseTask.__init__
def __init__(self, **kwargs)
Definition: coaddBase.py:139
lsst::coadd::utils
Definition: addToCoadd.h:37
lsst::afw::geom
Definition: frameSetUtils.h:40