23 """Base measurement task, which subclassed by the single frame and forced measurement tasks.
28 from .pluginRegistry
import PluginMap
29 from .baseLib
import FatalAlgorithmError, MeasurementError
30 from .pluginsBase
import BasePluginConfig, BasePlugin
31 from .noiseReplacer
import NoiseReplacerConfig
33 __all__ = (
"BaseMeasurementPluginConfig",
"BaseMeasurementPlugin",
34 "BaseMeasurementConfig",
"BaseMeasurementTask")
37 FATAL_EXCEPTIONS = (MemoryError, FatalAlgorithmError)
42 Base config class for all measurement plugins
44 Most derived classes will want to override setDefaults() in order to customize
45 the default exceutionOrder.
47 A derived class whose corresponding Plugin class implements measureN() should
48 additionally add a bool doMeasureN field to replace the bool class attribute
52 doMeasure = lsst.pex.config.Field(dtype=bool, default=
True,
53 doc=
"whether to run this plugin in single-object mode")
60 Base class for all measurement plugins
62 This is class is a placeholder for future behavior which will be shared only between
63 measurement plugins and is implemented for symmetry with the measurement base plugin
69 class SourceSlotConfig(lsst.pex.config.Config):
71 Slot configuration which assigns a particular named plugin to each of a set of
72 slots. Each slot allows a type of measurement to be fetched from the SourceTable
73 without knowing which algorithm was used to produced the data.
75 NOTE: the default algorithm for each slot must be registered, even if the default is not used.
78 centroid = lsst.pex.config.Field(dtype=str, default=
"base_SdssCentroid", optional=
True,
79 doc=
"the name of the centroiding algorithm used to set source x,y")
80 shape = lsst.pex.config.Field(dtype=str, default=
"base_SdssShape", optional=
True,
81 doc=
"the name of the algorithm used to set source moments parameters")
82 apFlux = lsst.pex.config.Field(dtype=str, default=
"base_CircularApertureFlux_12_0", optional=
True,
83 doc=
"the name of the algorithm used to set the source aperture flux slot")
84 modelFlux = lsst.pex.config.Field(dtype=str, default=
"base_GaussianFlux", optional=
True,
85 doc=
"the name of the algorithm used to set the source model flux slot")
86 psfFlux = lsst.pex.config.Field(dtype=str, default=
"base_PsfFlux", optional=
True,
87 doc=
"the name of the algorithm used to set the source psf flux slot")
88 instFlux = lsst.pex.config.Field(dtype=str, default=
"base_GaussianFlux", optional=
True,
89 doc=
"the name of the algorithm used to set the source inst flux slot")
90 calibFlux = lsst.pex.config.Field(dtype=str, default=
"base_CircularApertureFlux_12_0", optional=
True,
91 doc=
"the name of the flux measurement algorithm used for calibration")
94 """Convenience method to setup a Schema's slots according to the config definition.
96 This is defined in the Config class to support use in unit tests without needing
97 to construct a Task object.
99 aliases = schema.getAliasMap()
101 aliases.set(
"slot_Centroid", self.
centroid)
102 if self.
shape is not None:
103 aliases.set(
"slot_Shape", self.
shape)
104 if self.
apFlux is not None:
105 aliases.set(
"slot_ApFlux", self.
apFlux)
107 aliases.set(
"slot_ModelFlux", self.
modelFlux)
109 aliases.set(
"slot_PsfFlux", self.
psfFlux)
111 aliases.set(
"slot_InstFlux", self.
instFlux)
113 aliases.set(
"slot_CalibFlux", self.
calibFlux)
118 Base config class for all measurement driver tasks.
120 Subclasses should define the 'plugins' and 'undeblended' registries, e.g.:
122 plugins = PluginBaseClass.registry.makeField(
125 doc="Plugins to be run and their configuration"
127 undeblended = PluginBaseClass.registry.makeField(
130 doc="Plugins to run on undeblended image"
133 where PluginBaseClass is the appropriate base class of the plugin
134 (e.g., SingleFramePlugin or ForcedPlugin).
137 slots = lsst.pex.config.ConfigField(
138 dtype=SourceSlotConfig,
139 doc=
"Mapping from algorithms to special aliases in Source."
142 doReplaceWithNoise = lsst.pex.config.Field(
143 dtype=bool, default=
True, optional=
False,
144 doc=
'When measuring, replace other detected footprints with noise?')
146 noiseReplacer = lsst.pex.config.ConfigField(
147 dtype=NoiseReplacerConfig,
148 doc=
"configuration that sets how to replace neighboring sources with noise"
150 undeblendedPrefix = lsst.pex.config.Field(
151 dtype=str, default=
"undeblended_",
152 doc=
"Prefix to give undeblended plugins"
156 lsst.pex.config.Config.validate(self)
157 if self.slots.centroid
is not None and self.slots.centroid
not in self.plugins.names:
158 raise ValueError(
"source centroid slot algorithm is not being run.")
159 if self.slots.shape
is not None and self.slots.shape
not in self.plugins.names:
160 raise ValueError(
"source shape slot algorithm '%s' is not being run." % self.slots.shape)
161 for slot
in (self.slots.psfFlux, self.slots.apFlux, self.slots.modelFlux,
162 self.slots.instFlux, self.slots.calibFlux):
164 for name
in self.plugins.names:
165 if len(name) <= len(slot)
and name == slot[:len(name)]:
168 raise ValueError(
"source flux slot algorithm '%s' is not being run." % slot)
179 Ultimate base class for all measurement tasks.
181 This base class for SingleFrameMeasurementTask and ForcedMeasurementTask mostly exists to share
182 code between the two, and generally should not be used directly.
185 ConfigClass = BaseMeasurementConfig
186 _DefaultName =
"measurement"
190 Constructor; only called by derived classes.
192 @param[in] algMetadata An lsst.daf.base.PropertyList that will be filled with metadata
193 about the plugins being run. If None, an empty PropertyList will
195 @param[in] **kwds Additional arguments passed to lsst.pipe.base.Task.__init__.
197 This attaches two public attributes to the class for use by derived classes and parent tasks:
198 - plugins: an empty PluginMap, which will eventually contain all active plugins that will by
199 invoked by the run() method (to be filled by subclasses). This should be considered read-only.
200 - algMetadata: a lsst.daf.base.PropertyList that will contain additional information about the
201 active plugins to be saved with the output catalog (to be filled by subclasses).
203 super(BaseMeasurementTask, self).
__init__(**kwds)
206 if algMetadata
is None:
211 """Initialize the plugins (and slots) according to the configuration.
213 Derived class constructors should call this method to fill the self.plugins
214 attribute and add correspond output fields and slot aliases to the output schema.
216 In addition to the attributes added by BaseMeasurementTask.__init__, a self.schema
217 attribute holding the output schema must also be present before this method is called, .
219 Keyword arguments are forwarded directly to plugin constructors, allowing derived
220 classes to use plugins with different signatures.
225 if self.config.slots.centroid
is not None:
226 self.
plugins[self.config.slots.centroid] =
None
228 for executionOrder, name, config, PluginClass
in sorted(self.config.plugins.apply()):
233 if self.config.slots.centroid
is not None and self.
plugins[self.config.slots.centroid]
is None:
234 del self.
plugins[self.config.slots.centroid]
236 for executionOrder, name, config, PluginClass
in sorted(self.config.undeblended.apply()):
237 undeblendedName = self.config.undeblendedPrefix + name
243 Call the measure() method on all plugins, handling exceptions in a consistent way.
245 @param[in,out] measRecord lsst.afw.table.SourceRecord that corresponds to the object being
246 measured, and where outputs should be written.
247 @param[in] *args Positional arguments forwarded to Plugin.measure()
248 @param[in] **kwds Keyword arguments. Two are handled locally:
249 - beginOrder: beginning execution order (inclusive): measurements with
250 executionOrder < beginOrder are not executed. None for no limit.
251 - endOrder: ending execution order (exclusive): measurements with
252 executionOrder >= endOrder are not executed. None for no limit.
253 the rest are forwarded to Plugin.measure()
255 This method can be used with plugins that have different signatures; the only requirement is that
256 'measRecord' be the first argument. Subsequent positional arguments and keyword arguments are
257 forwarded directly to the plugin.
259 This method should be considered "protected"; it is intended for use by derived classes, not users.
261 beginOrder = kwds.pop(
"beginOrder",
None)
262 endOrder = kwds.pop(
"endOrder",
None)
263 for plugin
in self.plugins.iter():
264 if beginOrder
is not None and plugin.getExecutionOrder() < beginOrder:
266 if endOrder
is not None and plugin.getExecutionOrder() >= endOrder:
272 Call the measure() method on the nominated plugin, handling exceptions in a consistent way.
274 @param[in] plugin Plugin that will measure
275 @param[in,out] measRecord lsst.afw.table.SourceRecord that corresponds to the object being
276 measured, and where outputs should be written.
277 @param[in] *args Positional arguments forwarded to plugin.measure()
278 @param[in] **kwds Keyword arguments forwarded to plugin.measure()
280 This method can be used with plugins that have different signatures; the only requirement is that
281 the 'plugin' and 'measRecord' be the first two arguments. Subsequent positional arguments and
282 keyword arguments are forwarded directly to the plugin.
284 This method should be considered "protected"; it is intended for use by derived classes, not users.
287 plugin.measure(measRecord, *args, **kwds)
288 except FATAL_EXCEPTIONS:
290 except MeasurementError
as error:
291 plugin.fail(measRecord, error)
292 except Exception
as error:
293 self.log.warn(
"Error in %s.measure on record %s: %s"
294 % (plugin.name, measRecord.getId(), error))
295 plugin.fail(measRecord)
299 Call the measureN() method on all plugins, handling exceptions in a consistent way.
301 @param[in,out] measCat lsst.afw.table.SourceCatalog containing records for just
302 the source family to be measured, and where outputs should
304 @param[in] beginOrder beginning execution order (inclusive): measurements with
305 executionOrder < beginOrder are not executed. None for no limit.
306 @param[in] endOrder ending execution order (exclusive): measurements with
307 executionOrder >= endOrder are not executed. None for no limit.
308 @param[in] *args Positional arguments forwarded to Plugin.measure()
309 @param[in] **kwds Keyword arguments. Two are handled locally:
310 - beginOrder: beginning execution order (inclusive): measurements with
311 executionOrder < beginOrder are not executed. None for no limit.
312 - endOrder: ending execution order (exclusive): measurements with
313 executionOrder >= endOrder are not executed. None for no limit.
314 the rest are forwarded to Plugin.measure()
316 This method can be used with plugins that have different signatures; the only requirement is that
317 'measRecord' be the first argument. Subsequent positional arguments and keyword arguments are
318 forwarded directly to the plugin.
320 This method should be considered "protected"; it is intended for use by derived classes, not users.
322 beginOrder = kwds.pop(
"beginOrder",
None)
323 endOrder = kwds.pop(
"endOrder",
None)
324 for plugin
in self.plugins.iterN():
325 if beginOrder
is not None and plugin.getExecutionOrder() < beginOrder:
327 if endOrder
is not None and plugin.getExecutionOrder() >= endOrder:
333 Call the measureN() method on the nominated plugin, handling exceptions in a consistent way.
335 @param[in] plugin Plugin that will measure
336 @param[in,out] measCat lsst.afw.table.SourceCatalog containing records for just
337 the source family to be measured, and where outputs should
339 @param[in] *args Positional arguments forwarded to plugin.measureN()
340 @param[in] **kwds Keyword arguments forwarded to plugin.measureN()
342 This method can be used with plugins that have different signatures; the only requirement is that
343 the 'plugin' and 'measCat' be the first two arguments. Subsequent positional arguments and
344 keyword arguments are forwarded directly to the plugin.
346 This method should be considered "protected"; it is intended for use by derived classes, not users.
349 plugin.measureN(measCat, *args, **kwds)
350 except FATAL_EXCEPTIONS:
352 except MeasurementError
as error:
353 for measRecord
in measCat:
354 plugin.fail(measRecord, error)
355 except Exception
as error:
356 for measRecord
in measCat:
357 plugin.fail(measRecord)
358 self.log.warn(
"Error in %s.measureN on records %s-%s: %s"
359 % (plugin.name, measCat[0].getId(), measCat[-1].getId(), error))
Base config class for all measurement plugins.
def __init__
Constructor; only called by derived classes.
Class for storing ordered metadata with comments.
def callMeasure
Call the measure() method on all plugins, handling exceptions in a consistent way.
def doMeasurement
Call the measure() method on the nominated plugin, handling exceptions in a consistent way...
def doMeasurementN
Call the measureN() method on the nominated plugin, handling exceptions in a consistent way...
Ultimate base class for all measurement tasks.
Base config class for all measurement driver tasks.
def callMeasureN
Call the measureN() method on all plugins, handling exceptions in a consistent way.