LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
coaddBase.py
Go to the documentation of this file.
1 from __future__ import division, absolute_import
2 #
3 # LSST Data Management System
4 # Copyright 2008-2015 AURA/LSST.
5 #
6 # This product includes software developed by the
7 # LSST Project (http://www.lsst.org/).
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the LSST License Statement and
20 # the GNU General Public License along with this program. If not,
21 # see <http://www.lsstcorp.org/LegalNotices/>.
22 #
23 import lsst.pex.exceptions as pexExceptions
24 import lsst.pex.config as pexConfig
25 import lsst.afw.geom as afwGeom
26 import lsst.afw.image as afwImage
27 import lsst.pipe.base as pipeBase
28 import lsst.meas.algorithms as measAlg
29 
30 from lsst.afw.fits import FitsError
31 from lsst.coadd.utils import CoaddDataIdContainer
32 from .selectImages import WcsSelectImagesTask, SelectStruct
33 from .coaddInputRecorder import CoaddInputRecorderTask
34 
35 try:
36  from lsst.meas.mosaic import applyMosaicResults
37 except ImportError:
38  applyMosaicResults = None
39 
40 __all__ = ["CoaddBaseTask", "getSkyInfo"]
41 
42 class CoaddBaseConfig(pexConfig.Config):
43  """Config for CoaddBaseTask
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(dtype=bool, doc="Match to modelPsf?", default=False)
64  modelPsf = measAlg.GaussianPsfFactory.makeField(doc = "Model Psf factory")
65  doApplyUberCal = pexConfig.Field(
66  dtype = bool,
67  doc = "Apply meas_mosaic ubercal results to input calexps?",
68  default = False
69  )
70 
71 class CoaddTaskRunner(pipeBase.TaskRunner):
72  @staticmethod
73  def getTargetList(parsedCmd, **kwargs):
74  return pipeBase.TaskRunner.getTargetList(parsedCmd, selectDataList=parsedCmd.selectId.dataList,
75  **kwargs)
76 
77 class CoaddBaseTask(pipeBase.CmdLineTask):
78  """Base class for coaddition.
79 
80  Subclasses must specify _DefaultName
81  """
82  ConfigClass = CoaddBaseConfig
83  RunnerClass = CoaddTaskRunner
84 
85  def __init__(self, *args, **kwargs):
86  pipeBase.Task.__init__(self, *args, **kwargs)
87  self.makeSubtask("select")
88  self.makeSubtask("inputRecorder")
89 
90  def selectExposures(self, patchRef, skyInfo=None, selectDataList=[]):
91  """!Select exposures to coadd
92 
93  @param[in] patchRef data reference for sky map patch. Must include keys "tract", "patch",
94  plus the camera-specific filter key (e.g. "filter" or "band")
95  @param[in] skyInfo geometry for the patch; output from getSkyInfo
96  @return a list of science exposures to coadd, as butler data references
97  """
98  if skyInfo is None:
99  skyInfo = self.getSkyInfo(patchRef)
100  cornerPosList = afwGeom.Box2D(skyInfo.bbox).getCorners()
101  coordList = [skyInfo.wcs.pixelToSky(pos) for pos in cornerPosList]
102  return self.select.runDataRef(patchRef, coordList, selectDataList=selectDataList).dataRefList
103 
104  def getSkyInfo(self, patchRef):
105  """!Return SkyMap, tract and patch
106 
107  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
108 
109  @return pipe_base Struct containing:
110  - skyMap: sky map
111  - tractInfo: information for chosen tract of sky map
112  - patchInfo: information about chosen patch of tract
113  - wcs: WCS of tract
114  - bbox: outer bbox of patch, as an afwGeom Box2I
115  """
116  return getSkyInfo(coaddName=self.config.coaddName, patchRef=patchRef)
117 
118  def getCalExp(self, dataRef, bgSubtracted):
119  """!Return one "calexp" calibrated exposure
120 
121  @param[in] dataRef a sensor-level data reference
122  @param[in] bgSubtracted return calexp with background subtracted? If False get the
123  calexp's background background model and add it to the calexp.
124  @return calibrated exposure
125 
126  If config.doApplyUberCal, meas_mosaic calibrations will be applied to
127  the returned exposure using applyMosaicResults.
128  """
129  exposure = dataRef.get("calexp", immediate=True)
130  if not bgSubtracted:
131  background = dataRef.get("calexpBackground", immediate=True)
132  mi = exposure.getMaskedImage()
133  mi += background.getImage()
134  del mi
135  if not self.config.doApplyUberCal:
136  return exposure
137  if applyMosaicResults is None:
138  raise RuntimeError(
139  "Cannot use improved calibrations for %s because meas_mosaic could not be imported."
140  % dataRef.dataId
141  )
142  else:
143  applyMosaicResults(dataRef, calexp=exposure)
144  return exposure
145 
147  return self.config.coaddName + "Coadd"
148 
150  return self.config.coaddName + "Coadd_tempExp"
151 
152  @classmethod
154  """Create an argument parser
155  """
156  parser = pipeBase.ArgumentParser(name=cls._DefaultName)
157  parser.add_id_argument("--id", "deepCoadd", help="data ID, e.g. --id tract=12345 patch=1,2",
158  ContainerClass=CoaddDataIdContainer)
159  parser.add_id_argument("--selectId", "calexp", help="data ID, e.g. --selectId visit=6789 ccd=0..9",
160  ContainerClass=SelectDataIdContainer)
161  return parser
162 
163  def _getConfigName(self):
164  """Return the name of the config dataset
165  """
166  return "%s_%s_config" % (self.config.coaddName, self._DefaultName)
167 
168  def _getMetadataName(self):
169  """Return the name of the metadata dataset
170  """
171  return "%s_%s_metadata" % (self.config.coaddName, self._DefaultName)
172 
173  def getBadPixelMask(self):
174  """Convenience method to provide the bitmask from the mask plane names"""
175  return afwImage.MaskU.getPlaneBitMask(self.config.badMaskPlanes)
176 
177  def writeCoaddOutput(self, dataRef, obj, suffix=None):
178  """!Write a coadd product through the butler
179 
180  @param[in] dataRef data reference for coadd
181  @param[in,out] obj coadd product to write
182  @param[in] suffix suffix to apply to coadd dataset name
183  """
184  objName = self.getCoaddDatasetName()
185  if suffix is not None:
186  objName += "_" + suffix
187  self.log.info("Persisting %s" % objName)
188  dataRef.put(obj, objName)
189 
190 class SelectDataIdContainer(pipeBase.DataIdContainer):
191  """A dataId container for inputs to be selected.
192 
193  Read the header (including the size and Wcs) for all specified
194  inputs and pass those along, ultimately for the SelectImagesTask.
195  This is most useful when used with multiprocessing, as input headers are
196  only read once.
197  """
198  def makeDataRefList(self, namespace):
199  """Add a dataList containing useful information for selecting images"""
200  super(SelectDataIdContainer, self).makeDataRefList(namespace)
201  self.dataList = []
202  for ref in self.refList:
203  try:
204  md = ref.get("calexp_md", immediate=True)
205  wcs = afwImage.makeWcs(md)
206  data = SelectStruct(dataRef=ref, wcs=wcs, dims=(md.get("NAXIS1"), md.get("NAXIS2")))
207  except FitsError as e:
208  namespace.log.warn("Unable to construct Wcs from %s" % (ref.dataId))
209  continue
210  self.dataList.append(data)
211 
212 def getSkyInfo(coaddName, patchRef):
213  """!Return SkyMap, tract and patch
214 
215  @param[in] coaddName coadd name; typically one of deep or goodSeeing
216  @param[in] patchRef data reference for sky map. Must include keys "tract" and "patch"
217 
218  @return pipe_base Struct containing:
219  - skyMap: sky map
220  - tractInfo: information for chosen tract of sky map
221  - patchInfo: information about chosen patch of tract
222  - wcs: WCS of tract
223  - bbox: outer bbox of patch, as an afwGeom Box2I
224  """
225  skyMap = patchRef.get(coaddName + "Coadd_skyMap")
226  tractId = patchRef.dataId["tract"]
227  tractInfo = skyMap[tractId]
228 
229  # patch format is "xIndex,yIndex"
230  patchIndex = tuple(int(i) for i in patchRef.dataId["patch"].split(","))
231  patchInfo = tractInfo.getPatchInfo(patchIndex)
232 
233  return pipeBase.Struct(
234  skyMap = skyMap,
235  tractInfo = tractInfo,
236  patchInfo = patchInfo,
237  wcs = tractInfo.getWcs(),
238  bbox = patchInfo.getOuterBBox(),
239  )
def getCalExp
Return one &quot;calexp&quot; calibrated exposure.
Definition: coaddBase.py:118
def selectExposures
Select exposures to coadd.
Definition: coaddBase.py:90
Wcs::Ptr makeWcs(coord::Coord const &crval, geom::Point2D const &crpix, double CD11, double CD12, double CD21, double CD22)
Create a Wcs object from crval, crpix, CD, using CD elements (useful from python) ...
Definition: makeWcs.cc:141
def writeCoaddOutput
Write a coadd product through the butler.
Definition: coaddBase.py:177
def getSkyInfo
Return SkyMap, tract and patch.
Definition: coaddBase.py:104
def getSkyInfo
Return SkyMap, tract and patch.
Definition: coaddBase.py:212
A floating-point coordinate rectangle geometry.
Definition: Box.h:271