LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
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.afw.table
29 import lsst.pex.config
30 import lsst.daf.base
31 import lsst.pipe.base
32 import lsst.pex.config
33 
34 from .references import MultiBandReferencesTask
35 from .forcedMeasurement import ForcedMeasurementTask
36 from .applyApCorr import ApplyApCorrTask
37 from .catalogCalculation import CatalogCalculationTask
38 
39 __all__ = ("ForcedPhotImageConfig", "ForcedPhotImageTask")
40 
41 
42 class ForcedPhotImageConfig(lsst.pex.config.Config):
43  """!Config class for forced measurement driver task."""
44 
45  references = lsst.pex.config.ConfigurableField(
46  target=MultiBandReferencesTask,
47  doc="subtask to retrieve reference source catalog"
48  )
49  measurement = lsst.pex.config.ConfigurableField(
50  target=ForcedMeasurementTask,
51  doc="subtask to do forced measurement"
52  )
53  coaddName = lsst.pex.config.Field(
54  doc="coadd name: typically one of deep or goodSeeing",
55  dtype=str,
56  default="deep",
57  )
58  doApCorr = lsst.pex.config.Field(
59  dtype=bool,
60  default=True,
61  doc="Run subtask to apply aperture corrections"
62  )
63  applyApCorr = lsst.pex.config.ConfigurableField(
64  target=ApplyApCorrTask,
65  doc="Subtask to apply aperture corrections"
66  )
67  catalogCalculation = lsst.pex.config.ConfigurableField(
68  target=CatalogCalculationTask,
69  doc="Subtask to run catalogCalculation plugins on catalog"
70  )
71  copyColumns = lsst.pex.config.DictField(
72  keytype=str, itemtype=str, doc="Mapping of reference columns to source columns",
73  default={"id": "objectId", "parent": "parentObjectId", "deblend_nChild": "deblend_nChild"}
74  )
75 
76  def setDefaults(self):
77  # Make catalogCalculation a no-op by default as no modelFlux is setup by default in
78  # ForcedMeasurementTask
79  self.catalogCalculation.plugins.names = []
80 
81 ## @addtogroup LSST_task_documentation
82 ## @{
83 ## @page ForcedPhotImageTask
84 ## ForcedPhotImageTask
85 ## @copybrief ForcedPhotImageTask
86 ## @}
87 
88 
89 class ForcedPhotImageTask(lsst.pipe.base.CmdLineTask):
90  """!A base class for command-line forced measurement drivers.
91 
92  This is a an abstract class, which is the common ancestor for ForcedPhotCcdTask
93  and ForcedPhotCoaddTask. It provides the run() method that does most of the
94  work, while delegating a few customization tasks to other methods that are
95  overridden by subclasses.
96 
97  This task is not directly usable as a CmdLineTask; subclasses must:
98  - Set the _DefaultName class attribute
99  - Implement makeIdFactory
100  - Implement fetchReferences
101  - (optional) Implement attachFootprints
102  """
103  ConfigClass = ForcedPhotImageConfig
104  _DefaultName = "processImageForcedTask"
105 
106  def __init__(self, butler=None, refSchema=None, **kwds):
107  """Initialize the task.
108 
109  ForcedPhotImageTask takes two keyword arguments beyond the usual CmdLineTask arguments:
110  - refSchema: the Schema of the reference catalog, passed to the constructor of the references
111  subtask
112  - butler: a butler that will be passed to the references subtask to allow it to load its Schema
113  from disk
114  At least one of these arguments must be present; if both are, schema takes precedence.
115  """
116  super(lsst.pipe.base.CmdLineTask, self).__init__(**kwds)
117  self.makeSubtask("references", butler=butler, schema=refSchema)
118  if refSchema is None:
119  refSchema = self.references.schema
120  self.makeSubtask("measurement", refSchema=refSchema)
121  # It is necessary to get the schema internal to the forced measurement task until such a time
122  # that the schema is not owned by the measurement task, but is passed in by an external caller
123  if self.config.doApCorr:
124  self.makeSubtask("applyApCorr", schema=self.measurement.schema)
125  self.makeSubtask('catalogCalculation', schema=self.measurement.schema)
126 
127  def run(self, dataRef):
128  """!Measure a single exposure using forced detection for a reference catalog.
129 
130  @param[in] dataRef An lsst.daf.persistence.ButlerDataRef. It is passed to the
131  references subtask to obtain the reference WCS, the getExposure()
132  method (implemented by derived classes) to read the measurement
133  image, and the fetchReferences() method (implemented by derived
134  classes) to get the exposure and load the reference catalog (see
135  the CoaddSrcReferencesTask for more information). Sources are
136  generated with generateMeasCat() in the measurement subtask. These
137  are passed to measurement's run method which fills the source
138  catalog with the forced measurement results. The sources are then
139  passed to the writeOutputs() method (implemented by derived classes)
140  which writes the outputs. See derived class documentation for which
141  datasets and data ID keys are used.
142  """
143  refWcs = self.references.getWcs(dataRef)
144  exposure = self.getExposure(dataRef)
145  refCat = self.fetchReferences(dataRef, exposure)
146  measCat = self.measurement.generateMeasCat(exposure, refCat, refWcs,
147  idFactory=self.makeIdFactory(dataRef))
148  self.log.info("Performing forced measurement on %s" % (dataRef.dataId,))
149  self.attachFootprints(measCat, refCat, exposure, refWcs, dataRef)
150 
151  self.measurement.run(measCat, exposure, refCat, refWcs, exposureId=self.getExposureId(dataRef))
152 
153  if self.config.doApCorr:
154  self.applyApCorr.run(
155  catalog=measCat,
156  apCorrMap=exposure.getInfo().getApCorrMap()
157  )
158  self.catalogCalculation.run(measCat)
159 
160  self.writeOutput(dataRef, measCat)
161 
162  def makeIdFactory(self, dataRef):
163  """!Hook for derived classes to define how to make an IdFactory for forced sources.
164 
165  Note that this is for forced source IDs, not object IDs, which are usually handled by
166  the copyColumns config option.
167  """
168  raise NotImplementedError()
169 
170  def getExposureId(self, dataRef):
171  raise NotImplementedError()
172 
173  def fetchReferences(self, dataRef, exposure):
174  """!Hook for derived classes to define how to get references objects.
175 
176  Derived classes should call one of the fetch* methods on the references subtask,
177  but which one they call depends on whether the region to get references for is a
178  easy to describe in patches (as it would be when doing forced measurements on a
179  coadd), or is just an arbitrary box (as it would be for CCD forced measurements).
180  """
181  raise NotImplementedError()
182 
183  def attachFootprints(self, sources, refCat, exposure, refWcs, dataRef):
184  """!Hook for derived classes to define how to attach Footprints to blank sources prior to measurement
185 
186  Footprints for forced photometry must be in the pixel coordinate system of the image being
187  measured, while the actual detections may start out in a different coordinate system.
188 
189  Subclasses for ForcedPhotImageTask must implement this method to define how those Footprints
190  should be generated.
191 
192  The default implementation (defined in forcedMeasurement.py) transforms the Footprints from
193  the reference catalog from the refWcs to the exposure's Wcs, which downgrades HeavyFootprints
194  into regular Footprints, destroying deblend information.
195  """
196  return self.measurement.attachTransformedFootprints(sources, refCat, exposure, refWcs)
197 
198  def getExposure(self, dataRef):
199  """!Read input exposure on which to perform the measurements
200 
201  @param dataRef Data reference from butler.
202  """
203  return dataRef.get(self.dataPrefix + "calexp", immediate=True)
204 
205  def writeOutput(self, dataRef, sources):
206  """!Write forced source table
207 
208  @param dataRef Data reference from butler; the forced_src dataset (with self.dataPrefix included)
209  is all that will be modified.
210  @param sources SourceCatalog to save
211  """
212  dataRef.put(sources, self.dataPrefix + "forced_src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
213 
214  def getSchemaCatalogs(self):
215  """!Get a dict of Schema catalogs that will be used by this Task.
216 
217  In the case of forced taks, there is only one schema for each type of forced measurement.
218  The dataset type for this measurement is defined in the mapper.
219  """
220  catalog = lsst.afw.table.SourceCatalog(self.measurement.mapper.getOutputSchema())
221  catalog.getTable().setMetadata(self.measurement.algMetadata)
222  datasetType = self.dataPrefix + "forced_src"
223  return {datasetType: catalog}
224 
225  def _getConfigName(self):
226  """!Return the name of the config dataset. Forces config comparison from run-to-run
227  """
228  return self.dataPrefix + "forced_config"
229 
230  def _getMetadataName(self):
231  """!Return the name of the metadata dataset. Forced metadata to be saved
232  """
233  return self.dataPrefix + "forced_metadata"
A base class for command-line forced measurement drivers.
def _getConfigName
Return the name of the config dataset.
def run
Measure a single exposure using forced detection for a reference catalog.
def makeIdFactory
Hook for derived classes to define how to make an IdFactory for forced sources.
def fetchReferences
Hook for derived classes to define how to get references objects.
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 attachFootprints
Hook for derived classes to define how to attach Footprints to blank sources prior to measurement...
def _getMetadataName
Return the name of the metadata dataset.
def getExposure
Read input exposure on which to perform the measurements.
def getSchemaCatalogs
Get a dict of Schema catalogs that will be used by this Task.
Config class for forced measurement driver task.