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`). 34 from .references
import MultiBandReferencesTask
35 from .forcedMeasurement
import ForcedMeasurementTask
36 from .applyApCorr
import ApplyApCorrTask
37 from .catalogCalculation
import CatalogCalculationTask
39 __all__ = (
"ForcedPhotImageConfig",
"ForcedPhotImageTask")
43 """Config class for forced measurement driver task.""" 45 inputSchema = lsst.pipe.base.InitInputDatasetField(
46 doc=
"Schema for the input measurement catalogs.",
47 nameTemplate=
"{inputCoaddName}Coadd_ref_schema",
48 storageClass=
"SourceCatalog",
50 outputSchema = lsst.pipe.base.InitOutputDatasetField(
51 doc=
"Schema for the output forced measurement catalogs.",
52 nameTemplate=
"{outputCoaddName}Coadd_forced_src_schema",
53 storageClass=
"SourceCatalog",
55 exposure = lsst.pipe.base.InputDatasetField(
56 doc=
"Input exposure to perform photometry on.",
57 nameTemplate=
"{inputCoaddName}Coadd",
59 storageClass=
"ExposureF",
60 dimensions=[
"AbstractFilter",
"SkyMap",
"Tract",
"Patch"],
62 refCat = lsst.pipe.base.InputDatasetField(
63 doc=
"Catalog of shapes and positions at which to force photometry.",
64 nameTemplate=
"{inputCoaddName}Coadd_ref",
66 storageClass=
"SourceCatalog",
67 dimensions=[
"SkyMap",
"Tract",
"Patch"],
69 refWcs = lsst.pipe.base.InputDatasetField(
70 doc=
"Reference world coordinate system.",
71 nameTemplate=
"{inputCoaddName}Coadd",
74 storageClass=
"ExposureF",
75 dimensions=[
"AbstractFilter",
"SkyMap",
"Tract",
"Patch"],
77 measCat = lsst.pipe.base.OutputDatasetField(
78 doc=
"Output forced photometry catalog.",
79 nameTemplate=
"{outputCoaddName}Coadd_forced_src",
81 storageClass=
"SourceCatalog",
82 dimensions=[
"AbstractFilter",
"SkyMap",
"Tract",
"Patch"],
87 target=MultiBandReferencesTask,
88 doc=
"subtask to retrieve reference source catalog" 91 target=ForcedMeasurementTask,
92 doc=
"subtask to do forced measurement" 95 doc=
"coadd name: typically one of deep or goodSeeing",
102 doc=
"Run subtask to apply aperture corrections" 105 target=ApplyApCorrTask,
106 doc=
"Subtask to apply aperture corrections" 109 target=CatalogCalculationTask,
110 doc=
"Subtask to run catalogCalculation plugins on catalog" 121 "outputCoaddName":
"deep",
123 self.
quantum.dimensions = (
"AbstractFilter",
"SkyMap",
"Tract",
"Patch")
127 """A base class for command-line forced measurement drivers. 131 butler : `lsst.daf.persistence.butler.Butler`, optional 132 A Butler which will be passed to the references subtask to allow it to 133 load its schema from disk. Optional, but must be specified if 134 ``refSchema`` is not; if both are specified, ``refSchema`` takes 136 refSchema : `lsst.afw.table.Schema`, optional 137 The schema of the reference catalog, passed to the constructor of the 138 references subtask. Optional, but must be specified if ``butler`` is 139 not; if both are specified, ``refSchema`` takes precedence. 141 Keyword arguments are passed to the supertask constructor. 145 This is a an abstract class, which is the common ancestor for 146 `ForcedPhotCcdTask` and `ForcedPhotCoaddTask`. It provides the 147 `runDataRef` method that does most of the work, while delegating a few 148 customization tasks to other methods that are overridden by subclasses. 150 This task is not directly usable as a command line task. Subclasses must: 152 - Set the `_DefaultName` class attribute; 153 - Implement `makeIdFactory`; 154 - Implement `fetchReferences`; 155 - Optionally, implement `attachFootprints`. 158 ConfigClass = ForcedPhotImageConfig
159 _DefaultName =
"processImageForcedTask" 161 def __init__(self, butler=None, refSchema=None, initInputs=None, **kwds):
164 if initInputs
is not None:
165 refSchema = initInputs[
'inputSchema'].schema
167 self.
makeSubtask(
"references", butler=butler, schema=refSchema)
168 if refSchema
is None:
169 refSchema = self.references.schema
170 self.
makeSubtask(
"measurement", refSchema=refSchema)
174 self.
makeSubtask(
"applyApCorr", schema=self.measurement.schema)
175 self.
makeSubtask(
'catalogCalculation', schema=self.measurement.schema)
181 inputData[
'refWcs'] = butler.get(f
"{self.config.refWcs.name}.wcs", inputDataIds[
"refWcs"])
183 inputData[
'exposure'],
184 inputData[
'refCat'], inputData[
'refWcs'],
185 "TractPatch", butler)
187 return self.
run(**inputData)
189 def generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName, butler):
190 """Generate a measurement catalog for Gen3. 194 exposureDataId : `DataId` 195 Butler dataId for this exposure. 196 exposure : `lsst.afw.image.exposure.Exposure` 197 Exposure to generate the catalog for. 198 refCat : `lsst.afw.table.SourceCatalog` 199 Catalog of shapes and positions at which to force photometry. 200 refWcs : `lsst.afw.image.SkyWcs` 201 Reference world coordinate system. 203 Type of ID packer to construct from the registry. 204 butler : `lsst.daf.persistence.butler.Butler` 205 Butler to use to construct id packer. 209 measCat : `lsst.afw.table.SourceCatalog` 210 Catalog of forced sources to measure. 212 packer = butler.registry.makeDataIdPacker(idPackerName, exposureDataId)
213 expId = packer.pack(exposureDataId)
214 expBits = packer.maxBits
222 """Perform forced measurement on a single exposure. 226 dataRef : `lsst.daf.persistence.ButlerDataRef` 227 Passed to the ``references`` subtask to obtain the reference WCS, 228 the ``getExposure`` method (implemented by derived classes) to 229 read the measurment image, and the ``fetchReferences`` method to 230 get the exposure and load the reference catalog (see 231 :lsst-task`lsst.meas.base.references.CoaddSrcReferencesTask`). 232 Refer to derived class documentation for details of the datasets 233 and data ID keys which are used. 234 psfCache : `int`, optional 235 Size of PSF cache, or `None`. The size of the PSF cache can have 236 a significant effect upon the runtime for complicated PSF models. 240 Sources are generated with ``generateMeasCat`` in the ``measurement`` 241 subtask. These are passed to ``measurement``'s ``run`` method, which 242 fills the source catalog with the forced measurement results. The 243 sources are then passed to the ``writeOutputs`` method (implemented by 244 derived classes) which writes the outputs. 246 refWcs = self.references.getWcs(dataRef)
248 if psfCache
is not None:
249 exposure.getPsf().setCacheSize(psfCache)
254 self.
log.
info(
"Performing forced measurement on %s" % (dataRef.dataId,))
259 forcedPhotResult = self.
run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
261 self.
writeOutput(dataRef, forcedPhotResult.measCat)
263 def run(self, measCat, exposure, refCat, refWcs, exposureId=None):
264 """Perform forced measurement on a single exposure. 268 measCat : `lsst.afw.table.SourceCatalog` 269 The measurement catalog, based on the sources listed in the 271 exposure : `lsst.afw.image.Exposure` 272 The measurement image upon which to perform forced detection. 273 refCat : `lsst.afw.table.SourceCatalog` 274 The reference catalog of sources to measure. 275 refWcs : `lsst.afw.image.SkyWcs` 276 The WCS for the references. 278 Optional unique exposureId used for random seed in measurement 283 result : `lsst.pipe.base.Struct` 284 Structure with fields: 287 Catalog of forced measurement results 288 (`lsst.afw.table.SourceCatalog`). 290 self.measurement.
run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
292 self.applyApCorr.
run(
294 apCorrMap=exposure.getInfo().getApCorrMap()
296 self.catalogCalculation.
run(measCat)
301 """Hook for derived classes to make an ID factory for forced sources. 305 That this applies to forced *source* IDs, not object IDs, which are 306 usually handled by the ``measurement.copyColumns`` config option. 309 raise NotImplementedError()
312 raise NotImplementedError()
315 """Hook for derived classes to define how to get reference objects. 319 Derived classes should call one of the ``fetch*`` methods on the 320 ``references`` subtask, but which one they call depends on whether the 321 region to get references for is a easy to describe in patches (as it 322 would be when doing forced measurements on a coadd), or is just an 323 arbitrary box (as it would be for CCD forced measurements). 325 raise NotImplementedError()
328 r"""Attach footprints to blank sources prior to measurements. 332 `~lsst.afw.detection.Footprint`\ s for forced photometry must be in the 333 pixel coordinate system of the image being measured, while the actual 334 detections may start out in a different coordinate system. 336 Subclasses of this class must implement this method to define how 337 those `~lsst.afw.detection.Footprint`\ s should be generated. 339 This default implementation transforms the 340 `~lsst.afw.detection.Footprint`\ s from the reference catalog from the 341 reference WCS to the exposure's WcS, which downgrades 342 `lsst.afw.detection.heavyFootprint.HeavyFootprint`\ s into regular 343 `~lsst.afw.detection.Footprint`\ s, destroying deblend information. 345 return self.measurement.attachTransformedFootprints(sources, refCat, exposure, refWcs)
348 """Read input exposure on which measurement will be performed. 352 dataRef : `lsst.daf.persistence.ButlerDataRef` 353 Butler data reference. 355 return dataRef.get(self.dataPrefix +
"calexp", immediate=
True)
358 """Write forced source table 362 dataRef : `lsst.daf.persistence.ButlerDataRef` 363 Butler data reference. The forced_src dataset (with 364 self.dataPrefix prepended) is all that will be modified. 365 sources : `lsst.afw.table.SourceCatalog` 366 Catalog of sources to save. 368 dataRef.put(sources, self.dataPrefix +
"forced_src", flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
371 """The schema catalogs that will be used by this task. 375 schemaCatalogs : `dict` 376 Dictionary mapping dataset type to schema catalog. 380 There is only one schema for each type of forced measurement. The 381 dataset type for this measurement is defined in the mapper. 384 catalog.getTable().setMetadata(self.measurement.algMetadata)
385 datasetType = self.dataPrefix +
"forced_src" 386 return {datasetType: catalog}
388 def _getConfigName(self):
390 return self.dataPrefix +
"forced_config" 392 def _getMetadataName(self):
394 return self.dataPrefix +
"forced_metadata"
def makeSubtask(self, name, keyArgs)
def getExposure(self, dataRef)
def runDataRef(self, dataRef, psfCache=None)
def adaptArgsAndRun(self, inputData, inputDataIds, outputDataIds, butler)
def fetchReferences(self, dataRef, exposure)
def formatTemplateNames(self, templateParamsDict)
def run(self, measCat, exposure, refCat, refWcs, exposureId=None)
def makeIdFactory(self, dataRef)
def getExposureId(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 generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName, butler)
def getSchemaCatalogs(self)
def writeOutput(self, dataRef, sources)
def __init__(self, butler=None, refSchema=None, initInputs=None, kwds)
def getInitOutputDatasets(self)
def attachFootprints(self, sources, refCat, exposure, refWcs, dataRef)