LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
forcedPhotCoadd.py
Go to the documentation of this file.
1 from builtins import zip
2 #!/usr/bin/env python
3 #
4 # LSST Data Management System
5 # Copyright 2008-2015 AURA/LSST.
6 #
7 # This product includes software developed by the
8 # LSST Project (http://www.lsst.org/).
9 #
10 # This program is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the LSST License Statement and
21 # the GNU General Public License along with this program. If not,
22 # see <https://www.lsstcorp.org/LegalNotices/>.
23 #
24 import lsst.pex.config
25 import lsst.pipe.base
26 import lsst.coadd.utils
27 import lsst.afw.table
28 
29 from .forcedPhotImage import ForcedPhotImageConfig, ForcedPhotImageTask
30 
31 __all__ = ("ForcedPhotCoaddConfig", "ForcedPhotCoaddTask")
32 
33 
34 class ForcedPhotCoaddConfig(ForcedPhotImageConfig):
35  footprintDatasetName = lsst.pex.config.Field(
36  doc="Dataset (without coadd prefix) that should be used to obtain (Heavy)Footprints for sources. "
37  "Must have IDs that match those of the reference catalog."
38  "If None, Footprints will be generated by transforming the reference Footprints.",
39  dtype=str,
40  default="meas",
41  optional=True
42  )
43 
44  def setDefaults(self):
45  ForcedPhotImageTask.ConfigClass.setDefaults(self)
46  # Copy 'id' and 'parent' columns without renaming them; since these are
47  # the only IDs we have in coadd processing, there's no need to qualify
48  # them with 'object'.
49  self.measurement.copyColumns["id"] = "id"
50  self.measurement.copyColumns["parent"] = "parent"
51  self.references.removePatchOverlaps = False # see validate() for why
52 
53  def validate(self):
54  ForcedPhotImageTask.ConfigClass.validate(self)
55  if (self.measurement.doReplaceWithNoise and self.footprintDatasetName is not None
56  and self.references.removePatchOverlaps):
57  raise ValueError("Cannot use removePatchOverlaps=True with deblended footprints, as parent "
58  "sources may be rejected while their children are not.")
59 
60 ## @addtogroup LSST_task_documentation
61 ## @{
62 ## @page processForcedCoaddTask
63 ## ForcedPhotCoaddTask
64 ## @copybrief ForcedPhotCoaddTask
65 ## @}
66 
67 
68 class ForcedPhotCoaddTask(ForcedPhotImageTask):
69  """!
70  A command-line driver for performing forced measurement on coadd images
71 
72  This task is a subclass of ForcedPhotImageTask which is specifically for doing forced
73  measurement on a coadd, using as a reference catalog detections which were made on overlapping
74  coadds (i.e. in other bands).
75 
76  The run method (inherited from ForcedPhotImageTask) takes a lsst.daf.persistence.ButlerDataRef
77  argument that corresponds to a coadd image. This is used to provide all the inputs and outputs
78  for the task:
79  - A "*Coadd_src" (e.g. "deepCoadd_src") dataset is used as the reference catalog. This not loaded
80  directly from the passed dataRef, however; only the patch and tract are used, while the filter
81  is set by the configuration for the references subtask (see CoaddSrcReferencesTask).
82  - A "*Coadd_calexp" (e.g. "deepCoadd_calexp") dataset is used as the measurement image. Note that
83  this means that ProcessCoaddTask must be run on an image before ForcedPhotCoaddTask, in order
84  to generate the "*Coadd_calexp" dataset.
85  - A "*Coadd_forced_src" (e.g. "deepCoadd_forced_src") dataset will be written with the output
86  measurement catalog.
87 
88  In addition to the run method, ForcedPhotCcdTask overrides several methods of ForcedPhotImageTask
89  to specialize it for coadd processing, including makeIdFactory() and fetchReferences(). None of these
90  should be called directly by the user, though it may be useful to override them further in subclasses.
91  """
92 
93  ConfigClass = ForcedPhotCoaddConfig
94  RunnerClass = lsst.pipe.base.ButlerInitializedTaskRunner
95  _DefaultName = "forcedPhotCoadd"
96  dataPrefix = "deepCoadd_"
97 
98  def getExposure(self, dataRef):
99  name = self.config.coaddName + "Coadd_calexp"
100  return dataRef.get(name) if dataRef.datasetExists(name) else None
101 
102  def makeIdFactory(self, dataRef):
103  """Create an object that generates globally unique source IDs from per-CCD IDs and the CCD ID.
104 
105  @param dataRef Data reference from butler. The "CoaddId_bits" and "CoaddId"
106  datasets are accessed. The data ID must have tract and patch keys.
107  """
108  # With the default configuration, this IdFactory doesn't do anything, because
109  # the IDs it generates are immediately overwritten by the ID from the reference
110  # catalog (since that's in config.measurement.copyColumns). But we create one here anyway, to
111  # allow us to revert back to the old behavior of generating new forced source IDs,
112  # just by renaming the ID in config.copyColumns to "object_id".
113  expBits = dataRef.get(self.config.coaddName + "CoaddId_bits")
114  expId = int(dataRef.get(self.config.coaddName + "CoaddId"))
115  return lsst.afw.table.IdFactory.makeSource(expId, 64 - expBits)
116 
117  def getExposureId(self, dataRef):
118  return int(dataRef.get(self.config.coaddName + "CoaddId"))
119 
120  def fetchReferences(self, dataRef, exposure):
121  """Return an iterable of reference sources which overlap the exposure
122 
123  @param dataRef Data reference from butler corresponding to the image to be measured;
124  should have tract, patch, and filter keys.
125  @param exposure lsst.afw.image.Exposure to be measured (not used by this implementation)
126 
127  All work is delegated to the references subtask; see CoaddSrcReferencesTask for information
128  about the default behavior.
129  """
130  skyMap = dataRef.get(self.dataPrefix + "skyMap", immediate=True)
131  tractInfo = skyMap[dataRef.dataId["tract"]]
132  patch = tuple(int(v) for v in dataRef.dataId["patch"].split(","))
133  patchInfo = tractInfo.getPatchInfo(patch)
134  references = lsst.afw.table.SourceCatalog(self.references.schema)
135  references.extend(self.references.fetchInPatches(dataRef, patchList=[patchInfo]))
136  return references
137 
138  def attachFootprints(self, sources, refCat, exposure, refWcs, dataRef):
139  """For coadd forced photometry, we use the deblended HeavyFootprints from the single-band
140  measurements of the same band - because we've guaranteed that the peaks (and hence child sources)
141  will be consistent across all bands before we get to measurement, this should yield reasonable
142  deblending for most sources. It's most likely limitation is that it will not provide good flux
143  upper limits for sources that were not detected in this band but were blended with sources that
144  were.
145  """
146  if self.config.footprintDatasetName is None:
147  return ForcedPhotImageTask.attachFootprints(self, sources, refCat, exposure, refWcs, dataRef)
148  self.log.info("Loading deblended footprints for sources from %s, %s" %
149  (self.config.footprintDatasetName, dataRef.dataId))
150  fpCat = dataRef.get("%sCoadd_%s" % (self.config.coaddName, self.config.footprintDatasetName),
151  immediate=True)
152  for refRecord, srcRecord in zip(refCat, sources):
153  fpRecord = fpCat.find(refRecord.getId())
154  if fpRecord is None:
155  raise LookupError("Cannot find Footprint for source %s; please check that %sCoadd_%s "
156  "IDs are compatible with reference source IDs" %
157  (srcRecord.getId(), self.config.coaddName,
158  self.config.footprintDatasetName))
159  srcRecord.setFootprint(fpRecord.getFootprint())
160 
161  @classmethod
163  parser = lsst.pipe.base.ArgumentParser(name=cls._DefaultName)
164  parser.add_id_argument("--id", "deepCoadd_forced_src", help="data ID, with raw CCD keys + tract",
165  ContainerClass=lsst.coadd.utils.CoaddDataIdContainer)
166  return parser
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
A command-line driver for performing forced measurement on coadd images.
static boost::shared_ptr< IdFactory > makeSource(RecordId expId, int reserved)
Return an IdFactory that includes another, fixed ID in the higher-order bits.