LSSTApplications  18.1.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.afw.geom as afwGeom
24 import lsst.afw.image as afwImage
25 import lsst.pipe.base as pipeBase
26 import lsst.meas.algorithms as measAlg
27 
28 from lsst.afw.fits import FitsError
29 from lsst.coadd.utils import CoaddDataIdContainer
30 from .selectImages import WcsSelectImagesTask, SelectStruct
31 from .coaddInputRecorder import CoaddInputRecorderTask
32 from .scaleVariance import ScaleVarianceTask
33 
34 __all__ = ["CoaddBaseTask", "getSkyInfo", "makeSkyInfo"]
35 
36 
37 class CoaddBaseConfig(pexConfig.Config):
38  """!Configuration parameters for CoaddBaseTask
39 
40  @anchor CoaddBaseConfig_
41 
42  @brief Configuration parameters shared between MakeCoaddTempExp and AssembleCoadd
43  """
44  coaddName = pexConfig.Field(
45  doc="Coadd name: typically one of deep or goodSeeing.",
46  dtype=str,
47  default="deep",
48  )
49  select = pexConfig.ConfigurableField(
50  doc="Image selection subtask.",
51  target=WcsSelectImagesTask,
52  )
53  badMaskPlanes = pexConfig.ListField(
54  dtype=str,
55  doc="Mask planes that, if set, the associated pixel should not be included in the coaddTempExp.",
56  default=("NO_DATA",),
57  )
58  inputRecorder = pexConfig.ConfigurableField(
59  doc="Subtask that helps fill CoaddInputs catalogs added to the final Exposure",
60  target=CoaddInputRecorderTask
61  )
62  doPsfMatch = pexConfig.Field(
63  dtype=bool,
64  doc="Match to modelPsf? Deprecated. Sets makePsfMatched=True, makeDirect=False",
65  default=False
66  )
67  modelPsf = measAlg.GaussianPsfFactory.makeField(doc="Model Psf factory")
68  doApplyUberCal = pexConfig.Field(
69  dtype=bool,
70  doc="Apply jointcal WCS and PhotoCalib results to input calexps?",
71  default=False
72  )
73  useMeasMosaic = pexConfig.Field(
74  dtype=bool,
75  doc="Use meas_mosaic's applyMosaicResultsExposure() to do the photometric "
76  "calibration/wcs update (deprecated).",
77  default=False
78  )
79  includeCalibVar = pexConfig.Field(
80  dtype=bool,
81  doc="Add photometric calibration variance to warp variance plane.",
82  default=False
83  )
84  matchingKernelSize = pexConfig.Field(
85  dtype=int,
86  doc="Size in pixels of matching kernel. Must be odd.",
87  default=21,
88  check=lambda x: x % 2 == 1
89  )
90 
91 
92 class CoaddTaskRunner(pipeBase.TaskRunner):
93 
94  @staticmethod
95  def getTargetList(parsedCmd, **kwargs):
96  return pipeBase.TaskRunner.getTargetList(parsedCmd, selectDataList=parsedCmd.selectId.dataList,
97  **kwargs)
98 
99 
100 class CoaddBaseTask(pipeBase.CmdLineTask):
101  """!Base class for coaddition.
102 
103  Subclasses must specify _DefaultName
104  """
105  ConfigClass = CoaddBaseConfig
106  RunnerClass = CoaddTaskRunner
107 
108  def __init__(self, **kwargs):
109  super().__init__(**kwargs)
110  self.makeSubtask("select")
111  self.makeSubtask("inputRecorder")
112 
113  def selectExposures(self, patchRef, skyInfo=None, selectDataList=[]):
114  """!
115  @brief Select exposures to coadd
116 
117  Get the corners of the bbox supplied in skyInfo using @ref afwGeom.Box2D and convert the pixel
118  positions of the bbox corners to sky coordinates using @ref skyInfo.wcs.pixelToSky. Use the
119  @ref WcsSelectImagesTask_ "WcsSelectImagesTask" to select exposures that lie inside the patch
120  indicated by the dataRef.
121 
122  @param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch",
123  plus the camera-specific filter key (e.g. "filter" or "band")
124  @param[in] skyInfo geometry for the patch; output from getSkyInfo
125  @return a list of science exposures to coadd, as butler data references
126  """
127  if skyInfo is None:
128  skyInfo = self.getSkyInfo(patchRef)
129  cornerPosList = afwGeom.Box2D(skyInfo.bbox).getCorners()
130  coordList = [skyInfo.wcs.pixelToSky(pos) for pos in cornerPosList]
131  return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
132 
133  def getSkyInfo(self, patchRef):
134  """!
135  @brief Use @ref getSkyinfo to return the skyMap, tract and patch information, wcs and the outer bbox
136  of the patch.
137 
138  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
139 
140  @return pipe_base Struct containing:
141  - skyMap: sky map
142  - tractInfo: information for chosen tract of sky map
143  - patchInfo: information about chosen patch of tract
144  - wcs: WCS of tract
145  - bbox: outer bbox of patch, as an afwGeom Box2I
146  """
147  return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
148 
149  def getCoaddDatasetName(self, warpType="direct"):
150  """Return coadd name for given warpType and task config
151 
152  Parameters
153  ----------
154  warpType : string
155  Either 'direct' or 'psfMatched'
156 
157  Returns
158  -------
159  CoaddDatasetName : `string`
160  """
161  suffix = "" if warpType == "direct" else warpType[0].upper() + warpType[1:]
162  return self.config.coaddName + "Coadd" + suffix
163 
164  def getTempExpDatasetName(self, warpType="direct"):
165  """Return warp name for given warpType and task config
166 
167  Parameters
168  ----------
169  warpType : string
170  Either 'direct' or 'psfMatched'
171 
172  Returns
173  -------
174  WarpDatasetName : `string`
175  """
176  return self.config.coaddName + "Coadd_" + warpType + "Warp"
177 
178  @classmethod
179  def _makeArgumentParser(cls):
180  """Create an argument parser
181  """
182  parser = pipeBase.ArgumentParser(name=cls._DefaultName)
183  parser.add_id_argument("--id", "deepCoadd", help="data ID, e.g. --id tract=12345 patch=1,2",
184  ContainerClass=CoaddDataIdContainer)
185  parser.add_id_argument("--selectId", "calexp", help="data ID, e.g. --selectId visit=6789 ccd=0..9",
186  ContainerClass=SelectDataIdContainer)
187  return parser
188 
189  def _getConfigName(self):
190  """Return the name of the config dataset
191  """
192  return "%s_%s_config" % (self.config.coaddName, self._DefaultName)
193 
194  def _getMetadataName(self):
195  """Return the name of the metadata dataset
196  """
197  return "%s_%s_metadata" % (self.config.coaddName, self._DefaultName)
198 
199  def getBadPixelMask(self):
200  """!
201  @brief Convenience method to provide the bitmask from the mask plane names
202  """
203  return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes)
204 
205 
206 class SelectDataIdContainer(pipeBase.DataIdContainer):
207  """!
208  @brief A dataId container for inputs to be selected.
209 
210  Read the header (including the size and Wcs) for all specified
211  inputs and pass those along, ultimately for the SelectImagesTask.
212  This is most useful when used with multiprocessing, as input headers are
213  only read once.
214  """
215 
216  def makeDataRefList(self, namespace):
217  """Add a dataList containing useful information for selecting images"""
218  super(SelectDataIdContainer, self).makeDataRefList(namespace)
219  self.dataList = []
220  for ref in self.refList:
221  try:
222  md = ref.get("calexp_md", immediate=True)
223  wcs = afwGeom.makeSkyWcs(md)
224  data = SelectStruct(dataRef=ref, wcs=wcs, bbox=afwImage.bboxFromMetadata(md))
225  except FitsError:
226  namespace.log.warn("Unable to construct Wcs from %s" % (ref.dataId))
227  continue
228  self.dataList.append(data)
229 
230 
231 def getSkyInfo(coaddName, patchRef):
232  """!
233  @brief Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded.
234 
235  @param[in] coaddName coadd name; typically one of deep or goodSeeing
236  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
237 
238  @return pipe_base Struct containing:
239  - skyMap: sky map
240  - tractInfo: information for chosen tract of sky map
241  - patchInfo: information about chosen patch of tract
242  - wcs: WCS of tract
243  - bbox: outer bbox of patch, as an afwGeom Box2I
244  """
245  skyMap = patchRef.get(coaddName + "Coadd_skyMap")
246  return makeSkyInfo(skyMap, patchRef.dataId["tract"], patchRef.dataId["patch"])
247 
248 
249 def makeSkyInfo(skyMap, tractId, patchId):
250  """Return SkyInfo Struct
251 
252  Constructs SkyInfo used by coaddition tasks for multiple
253  patchId formats.
254 
255  Parameters
256  ----------
257  skyMap : `lsst.skyMap.SkyMap`
258  tractId : int
259  patchId : str or int or tuple of int
260  Either Gen2-style comma delimited string (e.g. '4,5'),
261  tuple of integers (e.g (4, 5), Gen3-style integer.
262  """
263  tractInfo = skyMap[tractId]
264 
265  if isinstance(patchId, str) and ',' in patchId:
266  # patch format is "xIndex,yIndex"
267  patchIndex = tuple(int(i) for i in patchId.split(","))
268  else:
269  patchIndex = patchId
270 
271  patchInfo = tractInfo.getPatchInfo(patchIndex)
272 
273  return pipeBase.Struct(
274  skyMap=skyMap,
275  tractInfo=tractInfo,
276  patchInfo=patchInfo,
277  wcs=tractInfo.getWcs(),
278  bbox=patchInfo.getOuterBBox(),
279  )
280 
281 
282 def scaleVariance(maskedImage, maskPlanes, log=None):
283  """!
284  @brief Scale the variance in a maskedImage
285 
286  The variance plane in a convolved or warped image (or a coadd derived
287  from warped images) does not accurately reflect the noise properties of
288  the image because variance has been lost to covariance. This function
289  attempts to correct for this by scaling the variance plane to match
290  the observed variance in the image. This is not perfect (because we're
291  not tracking the covariance) but it's simple and is often good enough.
292 
293  @deprecated Use the ScaleVarianceTask instead.
294 
295  @param maskedImage MaskedImage to operate on; variance will be scaled
296  @param maskPlanes List of mask planes for pixels to reject
297  @param log Log for reporting the renormalization factor; or None
298  @return renormalisation factor
299  """
300  config = ScaleVarianceTask.ConfigClass()
301  config.maskPlanes = maskPlanes
302  task = ScaleVarianceTask(config=config, name="scaleVariance", log=log)
303  return task.run(maskedImage)
def getCoaddDatasetName(self, warpType="direct")
Definition: coaddBase.py:149
Base class for coaddition.
Definition: coaddBase.py:100
A floating-point coordinate rectangle geometry.
Definition: Box.h:305
Configuration parameters for CoaddBaseTask.
Definition: coaddBase.py:37
A dataId container for inputs to be selected.
Definition: coaddBase.py:206
def makeSkyInfo(skyMap, tractId, patchId)
Definition: coaddBase.py:249
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
Definition: functional.cc:33
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
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:133
def getTempExpDatasetName(self, warpType="direct")
Definition: coaddBase.py:164
def getBadPixelMask(self)
Convenience method to provide the bitmask from the mask plane names.
Definition: coaddBase.py:199
def getTargetList(parsedCmd, kwargs)
Definition: coaddBase.py:95
def selectExposures(self, patchRef, skyInfo=None, selectDataList=[])
Select exposures to coadd.
Definition: coaddBase.py:113
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:496
def scaleVariance(maskedImage, maskPlanes, log=None)
Scale the variance in a maskedImage.
Definition: coaddBase.py:282
def getSkyInfo(coaddName, patchRef)
Return the SkyMap, tract and patch information, wcs, and outer bbox of the patch to be coadded...
Definition: coaddBase.py:231
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
Definition: Image.cc:709