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
forcedPhotImage.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # LSST Data Management System
4 # Copyright 2008, 2009, 2010, 2014 LSST Corporation.
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 
24 """Base command-line driver task for forced measurement. Must be inherited to specialize for
25 a specific dataset to be used (see ForcedPhotCcdTask, ForcedPhotCoaddTask).
26 """
27 
28 import lsst.pex.config
29 import lsst.daf.base
30 import lsst.pipe.base
31 import lsst.pex.config
32 
33 from .references import MultiBandReferencesTask
34 from .forcedMeasurement import ForcedMeasurementTask
35 
36 __all__ = ("ProcessImageForcedConfig", "ProcessImageForcedTask")
37 
38 class ProcessImageForcedConfig(lsst.pex.config.Config):
39  """!Config class for forced measurement driver task."""
40 
41  references = lsst.pex.config.ConfigurableField(
42  target=MultiBandReferencesTask,
43  doc="subtask to retrieve reference source catalog"
44  )
45  measurement = lsst.pex.config.ConfigurableField(
46  target=ForcedMeasurementTask,
47  doc="subtask to do forced measurement"
48  )
49  coaddName = lsst.pex.config.Field(
50  doc = "coadd name: typically one of deep or goodSeeing",
51  dtype = str,
52  default = "deep",
53  )
54  copyColumns = lsst.pex.config.DictField(
55  keytype=str, itemtype=str, doc="Mapping of reference columns to source columns",
56  default={"id": "objectId", "parent": "parentObjectId", "deblend_nChild": "deblend_nChild"}
57  )
58 
59  def setDefaults(self):
60  # coadds do not yet include include aperture correction data,
61  # but that is planned, so might as well warn when it occurs
62  self.measurement.doApplyApCorr = "noButWarn"
63 
64 ## @addtogroup LSST_task_documentation
65 ## @{
66 ## @page ProcessImageForcedTask
67 ## ProcessImageForcedTask
68 ## @copybrief ProcessImageForcedTask
69 ## @}
70 
71 class ProcessImageForcedTask(lsst.pipe.base.CmdLineTask):
72  """!A base class for command-line forced measurement drivers.
73 
74  This is a an abstract class, which is the common ancestor for ForcedPhotCcdTask
75  and ForcedPhotCoaddTask. It provides the run() method that does most of the
76  work, while delegating a few customization tasks to other methods that are
77  overridden by subclasses.
78 
79  This task is not directly usable as a CmdLineTask; subclasses must:
80  - Set the _DefaultName class attribute
81  - Implement makeIdFactory
82  - Implement fetchReferences
83  - (optional) Implement attachFootprints
84  """
85  ConfigClass = ProcessImageForcedConfig
86  _DefaultName = "processImageForcedTask"
87 
88  def __init__(self, butler=None, refSchema=None, **kwds):
89  """Initialize the task.
90 
91  ForcedPhotImageTask takes two keyword arguments beyond the usual CmdLineTask arguments:
92  - refSchema: the Schema of the reference catalog, passed to the constructor of the references
93  subtask
94  - butler: a butler that will be passed to the references subtask to allow it to load its Schema
95  from disk
96  At least one of these arguments must be present; if both are, schema takes precedence.
97  """
98  super(lsst.pipe.base.CmdLineTask, self).__init__(**kwds)
99  self.makeSubtask("references", butler=butler, schema=refSchema)
100  if refSchema is None:
101  refSchema = self.references.schema
102  self.makeSubtask("measurement", refSchema=refSchema)
103 
104  def run(self, dataRef):
105  """!Measure a single exposure using forced detection for a reference catalog.
106 
107  @param[in] dataRef An lsst.daf.persistence.ButlerDataRef. It is passed to the
108  references subtask to obtain the reference WCS, the getExposure()
109  method (implemented by derived classes) to read the measurement
110  image, and the fetchReferences() method (implemented by derived
111  classes) to get the exposure and load the reference catalog (see
112  the CoaddSrcReferencesTask for more information). Sources are
113  generated with generateMeasCat() in the measurement subtask. These
114  are passed to measurement's run method which fills the source
115  catalog with the forced measurement results. The sources are then
116  passed to the writeOutputs() method (implemented by derived classes)
117  which writes the outputs. See derived class documentation for which
118  datasets and data ID keys are used.
119  """
120  refWcs = self.references.getWcs(dataRef)
121  exposure = self.getExposure(dataRef)
122  refCat = self.fetchReferences(dataRef, exposure)
123  measCat = self.measurement.generateMeasCat(exposure, refCat, refWcs,
124  idFactory=self.makeIdFactory(dataRef))
125  self.log.info("Performing forced measurement on %s" % dataRef.dataId)
126  self.attachFootprints(measCat, refCat, exposure, refWcs, dataRef)
127  self.measurement.run(measCat, exposure, refCat, refWcs)
128  self.writeOutput(dataRef, measCat)
129 
130  def makeIdFactory(self, dataRef):
131  """!Hook for derived classes to define how to make an IdFactory for forced sources.
132 
133  Note that this is for forced source IDs, not object IDs, which are usually handled by
134  the copyColumns config option.
135  """
136  raise NotImplementedError()
137 
138  def fetchReferences(self, dataRef, exposure):
139  """!Hook for derived classes to define how to get references objects.
140 
141  Derived classes should call one of the fetch* methods on the references subtask,
142  but which one they call depends on whether the region to get references for is a
143  easy to describe in patches (as it would be when doing forced measurements on a
144  coadd), or is just an arbitrary box (as it would be for CCD forced measurements).
145  """
146  raise NotImplementedError()
147 
148  def attachFootprints(self, sources, refCat, exposure, refWcs, dataRef):
149  """!Hook for derived classes to define how to attach Footprints to blank sources prior to measurement
150 
151  Footprints for forced photometry must be in the pixel coordinate system of the image being
152  measured, while the actual detections may start out in a different coordinate system.
153 
154  Subclasses for ForcedPhotImageTask must implement this method to define how those Footprints
155  should be generated.
156 
157  The default implementation (defined in forcedMeasurement.py) transforms the Footprints from
158  the reference catalog from the refWcs to the exposure's Wcs, which downgrades HeavyFootprints
159  into regular Footprints, destroying deblend information.
160  """
161  return self.measurement.attachTransformedFootprints(sources, refCat, exposure, refWcs)
162 
163  def getExposure(self, dataRef):
164  """!Read input exposure on which to perform the measurements
165 
166  @param dataRef Data reference from butler.
167  """
168  return dataRef.get(self.dataPrefix + "calexp", immediate=True)
169 
170  def writeOutput(self, dataRef, sources):
171  """!Write forced source table
172 
173  @param dataRef Data reference from butler; the forced_src dataset (with self.dataPrefix included)
174  is all that will be modified.
175  @param sources SourceCatalog to save
176  """
177  dataRef.put(sources, self.dataPrefix + "forced_src")
178 
179  def getSchemaCatalogs(self):
180  """!Get a dict of Schema catalogs that will be used by this Task.
181 
182  In the case of forced taks, there is only one schema for each type of forced measurement.
183  The dataset type for this measurement is defined in the mapper.
184  """
185  catalog = lsst.afw.table.SourceCatalog(self.measurement.mapper.getOutputSchema())
186  catalog.getTable().setMetadata(self.measurement.algMetadata)
187  datasetType = self.dataPrefix + "forced_src"
188  return {datasetType:catalog}
189 
190  def _getConfigName(self):
191  """!Return the name of the config dataset. Forces config comparison from run-to-run
192  """
193  return self.dataPrefix + "forced_config"
194 
195  def _getMetadataName(self):
196  """!Return the name of the metadata dataset. Forced metadata to be saved
197  """
198  return self.dataPrefix + "forced_metadata"
199 
Config class for forced measurement driver task.
def fetchReferences
Hook for derived classes to define how to get references objects.
def attachFootprints
Hook for derived classes to define how to attach Footprints to blank sources prior to measurement...
def run
Measure a single exposure using forced detection for a reference catalog.
def getExposure
Read input exposure on which to perform the measurements.
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
Definition: fwd.h:55
def _getConfigName
Return the name of the config dataset.
def makeIdFactory
Hook for derived classes to define how to make an IdFactory for forced sources.
def getSchemaCatalogs
Get a dict of Schema catalogs that will be used by this Task.
def _getMetadataName
Return the name of the metadata dataset.
A base class for command-line forced measurement drivers.