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
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" 121 self.catalogCalculation.plugins.names = []
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'],
182 outputs = self.
run(**inputs)
183 butlerQC.put(outputs, outputRefs)
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 Name of DimensionPacker to use to generate the packed version 200 of the data ID to mangle into source IDs. 204 measCat : `lsst.afw.table.SourceCatalog` 205 Catalog of forced sources to measure. 207 expId, expBits = exposureDataId.pack(idPackerName, returnMaxBits=
True)
215 """Perform forced measurement on a single exposure. 219 dataRef : `lsst.daf.persistence.ButlerDataRef` 220 Passed to the ``references`` subtask to obtain the reference WCS, 221 the ``getExposure`` method (implemented by derived classes) to 222 read the measurment image, and the ``fetchReferences`` method to 223 get the exposure and load the reference catalog (see 224 :lsst-task`lsst.meas.base.references.CoaddSrcReferencesTask`). 225 Refer to derived class documentation for details of the datasets 226 and data ID keys which are used. 227 psfCache : `int`, optional 228 Size of PSF cache, or `None`. The size of the PSF cache can have 229 a significant effect upon the runtime for complicated PSF models. 233 Sources are generated with ``generateMeasCat`` in the ``measurement`` 234 subtask. These are passed to ``measurement``'s ``run`` method, which 235 fills the source catalog with the forced measurement results. The 236 sources are then passed to the ``writeOutputs`` method (implemented by 237 derived classes) which writes the outputs. 239 refWcs = self.references.getWcs(dataRef)
241 if psfCache
is not None:
242 exposure.getPsf().setCacheSize(psfCache)
247 self.log.
info(
"Performing forced measurement on %s" % (dataRef.dataId,))
252 forcedPhotResult = self.
run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
254 self.
writeOutput(dataRef, forcedPhotResult.measCat)
256 def run(self, measCat, exposure, refCat, refWcs, exposureId=None):
257 """Perform forced measurement on a single exposure. 261 measCat : `lsst.afw.table.SourceCatalog` 262 The measurement catalog, based on the sources listed in the 264 exposure : `lsst.afw.image.Exposure` 265 The measurement image upon which to perform forced detection. 266 refCat : `lsst.afw.table.SourceCatalog` 267 The reference catalog of sources to measure. 268 refWcs : `lsst.afw.image.SkyWcs` 269 The WCS for the references. 271 Optional unique exposureId used for random seed in measurement 276 result : `lsst.pipe.base.Struct` 277 Structure with fields: 280 Catalog of forced measurement results 281 (`lsst.afw.table.SourceCatalog`). 283 self.measurement.
run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
284 if self.config.doApCorr:
285 self.applyApCorr.
run(
287 apCorrMap=exposure.getInfo().getApCorrMap()
289 self.catalogCalculation.
run(measCat)
294 """Hook for derived classes to make an ID factory for forced sources. 298 That this applies to forced *source* IDs, not object IDs, which are 299 usually handled by the ``measurement.copyColumns`` config option. 302 raise NotImplementedError()
305 raise NotImplementedError()
308 """Hook for derived classes to define how to get reference objects. 312 Derived classes should call one of the ``fetch*`` methods on the 313 ``references`` subtask, but which one they call depends on whether the 314 region to get references for is a easy to describe in patches (as it 315 would be when doing forced measurements on a coadd), or is just an 316 arbitrary box (as it would be for CCD forced measurements). 318 raise NotImplementedError()
321 r"""Attach footprints to blank sources prior to measurements. 325 `~lsst.afw.detection.Footprint`\ s for forced photometry must be in the 326 pixel coordinate system of the image being measured, while the actual 327 detections may start out in a different coordinate system. 329 Subclasses of this class must implement this method to define how 330 those `~lsst.afw.detection.Footprint`\ s should be generated. 332 This default implementation transforms the 333 `~lsst.afw.detection.Footprint`\ s from the reference catalog from the 334 reference WCS to the exposure's WcS, which downgrades 335 `lsst.afw.detection.heavyFootprint.HeavyFootprint`\ s into regular 336 `~lsst.afw.detection.Footprint`\ s, destroying deblend information. 338 return self.measurement.attachTransformedFootprints(sources, refCat, exposure, refWcs)
341 """Read input exposure on which measurement will be performed. 345 dataRef : `lsst.daf.persistence.ButlerDataRef` 346 Butler data reference. 348 return dataRef.get(self.dataPrefix +
"calexp", immediate=
True)
351 """Write forced source table 355 dataRef : `lsst.daf.persistence.ButlerDataRef` 356 Butler data reference. The forced_src dataset (with 357 self.dataPrefix prepended) is all that will be modified. 358 sources : `lsst.afw.table.SourceCatalog` 359 Catalog of sources to save. 361 dataRef.put(sources, self.dataPrefix +
"forced_src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
364 """The schema catalogs that will be used by this task. 368 schemaCatalogs : `dict` 369 Dictionary mapping dataset type to schema catalog. 373 There is only one schema for each type of forced measurement. The 374 dataset type for this measurement is defined in the mapper. 377 catalog.getTable().setMetadata(self.measurement.algMetadata)
378 datasetType = self.dataPrefix +
"forced_src" 379 return {datasetType: catalog}
381 def _getConfigName(self):
383 return self.dataPrefix +
"forced_config" 385 def _getMetadataName(self):
387 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)
Return an IdFactory that includes another, fixed ID in the higher-order bits.
def getExposure(self, dataRef)
def run(self, measCat, exposure, refCat, refWcs, exposureId=None)
def getSchemaCatalogs(self)
def generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName)
def fetchReferences(self, dataRef, exposure)