22 """Base command-line driver task for forced measurement. 24 Must be inherited to specialize for a specific dataset to be used (see 25 `ForcedPhotCcdTask`, `ForcedPhotCoaddTask`). 29 import lsst.pex.config
32 import lsst.pex.config
34 from lsst.pipe.base
import PipelineTaskConnections, PipelineTaskConfig
35 import lsst.pipe.base.connectionTypes
as cT
37 from .references
import MultiBandReferencesTask
38 from .forcedMeasurement
import ForcedMeasurementTask
39 from .applyApCorr
import ApplyApCorrTask
40 from .catalogCalculation
import CatalogCalculationTask
42 __all__ = (
"ForcedPhotImageConfig",
"ForcedPhotImageTask",
"ForcedPhotImageConnections")
46 dimensions=(
"abstract_filter",
"skymap",
"tract",
"patch"),
47 defaultTemplates={
"inputCoaddName":
"deep",
48 "outputCoaddName":
"deep"}):
49 inputSchema = cT.InitInput(
50 doc=
"Schema for the input measurement catalogs.",
51 name=
"{inputCoaddName}Coadd_ref_schema",
52 storageClass=
"SourceCatalog",
54 outputSchema = cT.InitOutput(
55 doc=
"Schema for the output forced measurement catalogs.",
56 name=
"{outputCoaddName}Coadd_forced_src_schema",
57 storageClass=
"SourceCatalog",
60 doc=
"Input exposure to perform photometry on.",
61 name=
"{inputCoaddName}Coadd",
62 storageClass=
"ExposureF",
63 dimensions=[
"abstract_filter",
"skymap",
"tract",
"patch"],
66 doc=
"Catalog of shapes and positions at which to force photometry.",
67 name=
"{inputCoaddName}Coadd_ref",
68 storageClass=
"SourceCatalog",
69 dimensions=[
"skymap",
"tract",
"patch"],
72 doc=
"Reference world coordinate system.",
73 name=
"{inputCoaddName}Coadd.wcs",
75 dimensions=[
"abstract_filter",
"skymap",
"tract",
"patch"],
78 doc=
"Output forced photometry catalog.",
79 name=
"{outputCoaddName}Coadd_forced_src",
80 storageClass=
"SourceCatalog",
81 dimensions=[
"abstract_filter",
"skymap",
"tract",
"patch"],
85 class ForcedPhotImageConfig(PipelineTaskConfig, pipelineConnections=ForcedPhotImageConnections):
86 """Config class for forced measurement driver task.""" 88 references = lsst.pex.config.ConfigurableField(
89 target=MultiBandReferencesTask,
90 doc=
"subtask to retrieve reference source catalog" 92 measurement = lsst.pex.config.ConfigurableField(
93 target=ForcedMeasurementTask,
94 doc=
"subtask to do forced measurement" 96 coaddName = lsst.pex.config.Field(
97 doc=
"coadd name: typically one of deep or goodSeeing",
101 doApCorr = lsst.pex.config.Field(
104 doc=
"Run subtask to apply aperture corrections" 106 applyApCorr = lsst.pex.config.ConfigurableField(
107 target=ApplyApCorrTask,
108 doc=
"Subtask to apply aperture corrections" 110 catalogCalculation = lsst.pex.config.ConfigurableField(
111 target=CatalogCalculationTask,
112 doc=
"Subtask to run catalogCalculation plugins on catalog" 115 def setDefaults(self):
119 super().setDefaults()
121 self.catalogCalculation.plugins.names = []
124 class ForcedPhotImageTask(lsst.pipe.base.PipelineTask, lsst.pipe.base.CmdLineTask):
125 """A base class for command-line forced measurement drivers. 129 butler : `lsst.daf.persistence.butler.Butler`, optional 130 A Butler which will be passed to the references subtask to allow it to 131 load its schema from disk. Optional, but must be specified if 132 ``refSchema`` is not; if both are specified, ``refSchema`` takes 134 refSchema : `lsst.afw.table.Schema`, optional 135 The schema of the reference catalog, passed to the constructor of the 136 references subtask. Optional, but must be specified if ``butler`` is 137 not; if both are specified, ``refSchema`` takes precedence. 139 Keyword arguments are passed to the supertask constructor. 143 This is a an abstract class, which is the common ancestor for 144 `ForcedPhotCcdTask` and `ForcedPhotCoaddTask`. It provides the 145 `runDataRef` method that does most of the work, while delegating a few 146 customization tasks to other methods that are overridden by subclasses. 148 This task is not directly usable as a command line task. Subclasses must: 150 - Set the `_DefaultName` class attribute; 151 - Implement `makeIdFactory`; 152 - Implement `fetchReferences`; 153 - Optionally, implement `attachFootprints`. 156 ConfigClass = ForcedPhotImageConfig
157 _DefaultName =
"processImageForcedTask" 159 def __init__(self, butler=None, refSchema=None, initInputs=None, **kwds):
160 super().__init__(**kwds)
162 if initInputs
is not None:
163 refSchema = initInputs[
'inputSchema'].schema
165 self.makeSubtask(
"references", butler=butler, schema=refSchema)
166 if refSchema
is None:
167 refSchema = self.references.schema
168 self.makeSubtask(
"measurement", refSchema=refSchema)
171 if self.config.doApCorr:
172 self.makeSubtask(
"applyApCorr", schema=self.measurement.schema)
173 self.makeSubtask(
'catalogCalculation', schema=self.measurement.schema)
177 inputs = butlerQC.get(inputRefs)
180 inputs[
'refCat'], inputs[
'refWcs'],
181 "tract_patch", butlerQC.registry)
182 outputs = self.
run(**inputs)
183 butlerQC.put(outputs, outputRefs)
185 def generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName, registry):
186 """Generate a measurement catalog for Gen3. 190 exposureDataId : `DataId` 191 Butler dataId for this exposure. 192 exposure : `lsst.afw.image.exposure.Exposure` 193 Exposure to generate the catalog for. 194 refCat : `lsst.afw.table.SourceCatalog` 195 Catalog of shapes and positions at which to force photometry. 196 refWcs : `lsst.afw.image.SkyWcs` 197 Reference world coordinate system. 199 Type of ID packer to construct from the registry. 200 registry : `lsst.daf.persistence.butler.Registry` 201 Registry to use to construct id packer. 205 measCat : `lsst.afw.table.SourceCatalog` 206 Catalog of forced sources to measure. 208 packer = registry.makeDataIdPacker(idPackerName, exposureDataId)
209 expId = packer.pack(exposureDataId)
210 expBits = packer.maxBits
218 """Perform forced measurement on a single exposure. 222 dataRef : `lsst.daf.persistence.ButlerDataRef` 223 Passed to the ``references`` subtask to obtain the reference WCS, 224 the ``getExposure`` method (implemented by derived classes) to 225 read the measurment image, and the ``fetchReferences`` method to 226 get the exposure and load the reference catalog (see 227 :lsst-task`lsst.meas.base.references.CoaddSrcReferencesTask`). 228 Refer to derived class documentation for details of the datasets 229 and data ID keys which are used. 230 psfCache : `int`, optional 231 Size of PSF cache, or `None`. The size of the PSF cache can have 232 a significant effect upon the runtime for complicated PSF models. 236 Sources are generated with ``generateMeasCat`` in the ``measurement`` 237 subtask. These are passed to ``measurement``'s ``run`` method, which 238 fills the source catalog with the forced measurement results. The 239 sources are then passed to the ``writeOutputs`` method (implemented by 240 derived classes) which writes the outputs. 242 refWcs = self.references.getWcs(dataRef)
244 if psfCache
is not None:
245 exposure.getPsf().setCacheSize(psfCache)
250 self.log.info(
"Performing forced measurement on %s" % (dataRef.dataId,))
255 forcedPhotResult = self.
run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
257 self.
writeOutput(dataRef, forcedPhotResult.measCat)
259 def run(self, measCat, exposure, refCat, refWcs, exposureId=None):
260 """Perform forced measurement on a single exposure. 264 measCat : `lsst.afw.table.SourceCatalog` 265 The measurement catalog, based on the sources listed in the 267 exposure : `lsst.afw.image.Exposure` 268 The measurement image upon which to perform forced detection. 269 refCat : `lsst.afw.table.SourceCatalog` 270 The reference catalog of sources to measure. 271 refWcs : `lsst.afw.image.SkyWcs` 272 The WCS for the references. 274 Optional unique exposureId used for random seed in measurement 279 result : `lsst.pipe.base.Struct` 280 Structure with fields: 283 Catalog of forced measurement results 284 (`lsst.afw.table.SourceCatalog`). 286 self.measurement.
run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
287 if self.config.doApCorr:
288 self.applyApCorr.
run(
290 apCorrMap=exposure.getInfo().getApCorrMap()
292 self.catalogCalculation.
run(measCat)
294 return lsst.pipe.base.Struct(measCat=measCat)
297 """Hook for derived classes to make an ID factory for forced sources. 301 That this applies to forced *source* IDs, not object IDs, which are 302 usually handled by the ``measurement.copyColumns`` config option. 305 raise NotImplementedError()
308 raise NotImplementedError()
311 """Hook for derived classes to define how to get reference objects. 315 Derived classes should call one of the ``fetch*`` methods on the 316 ``references`` subtask, but which one they call depends on whether the 317 region to get references for is a easy to describe in patches (as it 318 would be when doing forced measurements on a coadd), or is just an 319 arbitrary box (as it would be for CCD forced measurements). 321 raise NotImplementedError()
324 r"""Attach footprints to blank sources prior to measurements. 328 `~lsst.afw.detection.Footprint`\ s for forced photometry must be in the 329 pixel coordinate system of the image being measured, while the actual 330 detections may start out in a different coordinate system. 332 Subclasses of this class must implement this method to define how 333 those `~lsst.afw.detection.Footprint`\ s should be generated. 335 This default implementation transforms the 336 `~lsst.afw.detection.Footprint`\ s from the reference catalog from the 337 reference WCS to the exposure's WcS, which downgrades 338 `lsst.afw.detection.heavyFootprint.HeavyFootprint`\ s into regular 339 `~lsst.afw.detection.Footprint`\ s, destroying deblend information. 341 return self.measurement.attachTransformedFootprints(sources, refCat, exposure, refWcs)
344 """Read input exposure on which measurement will be performed. 348 dataRef : `lsst.daf.persistence.ButlerDataRef` 349 Butler data reference. 351 return dataRef.get(self.dataPrefix +
"calexp", immediate=
True)
354 """Write forced source table 358 dataRef : `lsst.daf.persistence.ButlerDataRef` 359 Butler data reference. The forced_src dataset (with 360 self.dataPrefix prepended) is all that will be modified. 361 sources : `lsst.afw.table.SourceCatalog` 362 Catalog of sources to save. 364 dataRef.put(sources, self.dataPrefix +
"forced_src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
367 """The schema catalogs that will be used by this task. 371 schemaCatalogs : `dict` 372 Dictionary mapping dataset type to schema catalog. 376 There is only one schema for each type of forced measurement. The 377 dataset type for this measurement is defined in the mapper. 380 catalog.getTable().setMetadata(self.measurement.algMetadata)
381 datasetType = self.dataPrefix +
"forced_src" 382 return {datasetType: catalog}
384 def _getConfigName(self):
386 return self.dataPrefix +
"forced_config" 388 def _getMetadataName(self):
390 return self.dataPrefix +
"forced_metadata" def attachFootprints(self, sources, refCat, exposure, refWcs, dataRef)
def getExposureId(self, dataRef)
def runDataRef(self, dataRef, psfCache=None)
def writeOutput(self, dataRef, sources)
def runQuantum(self, butlerQC, inputRefs, outputRefs)
def makeIdFactory(self, dataRef)
static std::shared_ptr< IdFactory > makeSource(RecordId expId, int reserved)
def generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName, registry)
def getExposure(self, dataRef)
def run(self, measCat, exposure, refCat, refWcs, exposureId=None)
def getSchemaCatalogs(self)
def fetchReferences(self, dataRef, exposure)