22r"""Base classes for single-frame measurement plugins and the associated task.
24In single-frame measurement, we assume that detection and probably deblending
25have already been run on the same frame, so a `~lsst.afw.table.SourceCatalog`
26has already been created with `lsst.afw.detection.Footprint`\ s (which may be
27"heavy" — that is, include pixel data). Measurements are generally recorded in
28the coordinate system of the image being measured (and all slot-eligible
29fields must be), but non-slot fields may be recorded in other coordinate
30systems if necessary to avoid information loss (this should, of course, be
31indicated in the field documentation).
34from lsst.utils.logging
import PeriodicLogger
35from lsst.utils.timer
import timeMethod
37from .pluginRegistry
import PluginRegistry
38from .baseMeasurement
import (BaseMeasurementPluginConfig, BaseMeasurementPlugin,
39 BaseMeasurementConfig, BaseMeasurementTask)
41__all__ = (
"SingleFramePluginConfig",
"SingleFramePlugin",
42 "SingleFrameMeasurementConfig",
"SingleFrameMeasurementTask")
46 """Base class for single-frame plugin configuration classes.
52 """Base class for single-frame measurement plugin.
56 config : `SingleFramePlugin.ConfigClass`
57 Configuration for this plugin.
59 The string with which the plugin was registered.
60 schema : `lsst.afw.table.Schema`
61 The schema for the source table . New fields are added here to
62 hold measurements produced by this plugin.
63 metadata : `lsst.daf.base.PropertySet`
64 Plugin metadata that will be attached to the output catalog
65 logName : `str`, optional
66 Name to use when logging errors.
70 New plugins can be created in Python by inheriting directly from this
71 class and implementing the `measure`, `fail` (from `BasePlugin`), and
72 optionally `__init__` and `measureN` methods. Plugins can also be defined
73 in C++ via the `WrappedSingleFramePlugin` class.
77 """Registry of subclasses of `SingleFramePlugin` (`PluginRegistry`).
80 ConfigClass = SingleFramePluginConfig
82 def __init__(self, config, name, schema, metadata, logName=None, **kwds):
83 BaseMeasurementPlugin.__init__(self, config, name, logName=logName)
86 """Measure the properties of a source on a single image.
88 The image may be from a single epoch, or it may be a coadd.
92 measRecord : `lsst.afw.table.SourceRecord`
93 Record describing the object being measured. Previously-measured
94 quantities may be retrieved from here, and it will be updated
95 in-place tih the outputs of this plugin.
96 exposure : `lsst.afw.image.ExposureF`
97 The pixel data to be measured, together with the associated PSF,
98 WCS, etc. All other sources in the image should have been replaced
99 by noise according to deblender outputs.
101 raise NotImplementedError()
105 """Config class for single frame measurement driver task.
108 plugins = SingleFramePlugin.registry.makeField(
110 default=[
"base_PixelFlags",
115 "base_CircularApertureFlux",
119 "base_LocalBackground",
120 "base_CompensatedTophatFlux",
121 "base_ClassificationSizeExtendedness",
123 doc=
"Plugins to be run and their configuration"
125 algorithms = property(
lambda self: self.
plugins, doc=
"backwards-compatibility alias for plugins")
126 undeblended = SingleFramePlugin.registry.makeField(
129 doc=
"Plugins to run on undeblended image"
134 """A subtask for measuring the properties of sources on a single exposure.
138 schema : `lsst.afw.table.Schema`
139 Schema of the output resultant catalog. Will be updated to provide
140 fields to accept the outputs of plugins which will be executed by this
142 algMetadata : `lsst.daf.base.PropertyList`, optional
143 Used to record metadaa about algorithm execution. An empty
144 `lsst.daf.base.PropertyList` will be created if `None`.
146 Keyword arguments forwarded to `BaseMeasurementTask`.
149 ConfigClass = SingleFrameMeasurementConfig
151 def __init__(self, schema, algMetadata=None, **kwds):
152 super(SingleFrameMeasurementTask, self).
__init__(algMetadata=algMetadata, **kwds)
154 self.config.slots.setupSchema(self.
schema)
176 r"""Run single frame measurement over an exposure and source catalog.
180 measCat : `lsst.afw.table.SourceCatalog`
181 Catalog to be filled with the results of measurement. Must contain
182 all the `lsst.afw.table.SourceRecord`\ s to be measured (with
183 `lsst.afw.detection.Footprint`\ s attached), and have a schema
184 that is a superset of ``self.schema``.
185 exposure : `lsst.afw.image.ExposureF`
186 Image containing the pixel data to be measured together with
187 associated PSF, WCS, etc.
188 noiseImage : `lsst.afw.image.ImageF`, optional
189 Can be used to specify the a predictable noise replacement field
190 for testing purposes.
191 exposureId : `int`, optional
192 Unique exposure identifier used to calculate the random number
193 generator seed during noise replacement.
194 beginOrder : `float`, optional
195 Start execution order (inclusive): measurements with
196 ``executionOrder < beginOrder`` are not executed. `None` for no
198 endOrder : `float`, optional
199 Final execution order (exclusive): measurements with
200 ``executionOrder >= endOrder`` are not executed. `None` for no
202 footprints : `dict` {`int`: `lsst.afw.detection.Footprint`}, optional
203 List of footprints to use for noise replacement. If this is not
204 supplied then the footprints from the measCat are used.
206 assert measCat.getSchema().contains(self.
schema)
207 if footprints
is None:
217 noiseReplacer = self.
initNoiseReplacer(exposure, measCat, footprints, exposureId, noiseImage)
219 self.
runPlugins(noiseReplacer, measCat, exposure, beginOrder, endOrder)
229 r"""Call the configured measument plugins on an image.
233 noiseReplacer : `NoiseReplacer`
234 Used to fill sources not being measured with noise.
235 measCat : `lsst.afw.table.SourceCatalog`
236 Catalog to be filled with the results of measurement. Must contain
237 all the `lsst.afw.table.SourceRecord`\ s to be measured (with
238 `lsst.afw.detection.Footprint`\ s attached), and have a schema
239 that is a superset of ``self.schema``.
240 exposure : `lsst.afw.image.ExposureF`
241 Image containing the pixel data to be measured together with
242 associated PSF, WCS, etc.
243 beginOrder : `float`, optional
244 Start execution order (inclusive): measurements with
245 ``executionOrder < beginOrder`` are not executed. `None` for no
247 endOrder : `float`, optional
248 Final execution order (exclusive): measurements with
249 ``executionOrder >= endOrder`` are not executed. `None` for no
252 nMeasCat = len(measCat)
253 self.log.info(
"Measuring %d source%s", nMeasCat, (
"" if nMeasCat == 1
else "s"))
256 periodicLog = PeriodicLogger(self.log)
258 for recordIndex, measRecord
in enumerate(measCat):
259 noiseReplacer.insertSource(measRecord.getId())
260 self.
callMeasure(measRecord, exposure, beginOrder=beginOrder, endOrder=endOrder)
263 self.
blendPlugin.cpp.measureChildPixels(exposure.getMaskedImage(), measRecord)
265 noiseReplacer.removeSource(measRecord.getId())
267 periodicLog.log(
"Measurement complete for %d sources out of %d", recordIndex + 1, nMeasCat)
274 for sourceIndex, source
in enumerate(measCat):
278 periodicLog.log(
"Undeblended measurement complete for %d sources out of %d",
279 sourceIndex + 1, nMeasCat)
284 for source
in measCat:
285 self.
blendPlugin.cpp.measureParentPixels(exposure.getMaskedImage(), source)
288 """Backwards-compatibility alias for `run`.
290 self.
run(measCat, exposure)
getFootprintsFromCatalog(catalog)
initNoiseReplacer(self, exposure, measCat, footprints, exposureId=None, noiseImage=None)
doMeasurement(self, plugin, measRecord, *args, **kwds)
addInvalidPsfFlag(self, schema)
initializePlugins(self, **kwds)
callMeasure(self, measRecord, *args, **kwds)
__init__(self, schema, algMetadata=None, **kwds)
runPlugins(self, noiseReplacer, measCat, exposure, beginOrder=None, endOrder=None)
run(self, measCat, exposure, noiseImage=None, exposureId=None, beginOrder=None, endOrder=None, footprints=None)
measure(self, measCat, exposure)
measure(self, measRecord, exposure)
__init__(self, config, name, schema, metadata, logName=None, **kwds)