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.
121 slots = lsst.pex.config.ConfigField(
122 dtype=SourceSlotConfig,
123 doc=
"Mapping from algorithms to special aliases in Source."
126 doReplaceWithNoise = lsst.pex.config.Field(
127 dtype=bool, default=
True, optional=
False,
128 doc=
'When measuring, replace other detected footprints with noise?')
130 noiseReplacer = lsst.pex.config.ConfigField(
131 dtype=NoiseReplacerConfig,
132 doc=
"configuration that sets how to replace neighboring sources with noise"
136 lsst.pex.config.Config.validate(self)
137 if self.slots.centroid
is not None and self.slots.centroid
not in self.plugins.names:
138 raise ValueError(
"source centroid slot algorithm is not being run.")
139 if self.slots.shape
is not None and self.slots.shape
not in self.plugins.names:
140 raise ValueError(
"source shape slot algorithm '%s' is not being run." % self.slots.shape)
141 for slot
in (self.slots.psfFlux, self.slots.apFlux, self.slots.modelFlux,
142 self.slots.instFlux, self.slots.calibFlux):
144 for name
in self.plugins.names:
145 if len(name) <= len(slot)
and name == slot[:len(name)]:
148 raise ValueError(
"source flux slot algorithm '%s' is not being run." % slot)
159 Ultimate base class for all measurement tasks.
161 This base class for SingleFrameMeasurementTask and ForcedMeasurementTask mostly exists to share
162 code between the two, and generally should not be used directly.
165 ConfigClass = BaseMeasurementConfig
166 _DefaultName =
"measurement"
170 Constructor; only called by derived classes.
172 @param[in] algMetadata An lsst.daf.base.PropertyList that will be filled with metadata
173 about the plugins being run. If None, an empty PropertyList will
175 @param[in] **kwds Additional arguments passed to lsst.pipe.base.Task.__init__.
177 This attaches two public attributes to the class for use by derived classes and parent tasks:
178 - plugins: an empty PluginMap, which will eventually contain all active plugins that will by
179 invoked by the run() method (to be filled by subclasses). This should be considered read-only.
180 - algMetadata: a lsst.daf.base.PropertyList that will contain additional information about the
181 active plugins to be saved with the output catalog (to be filled by subclasses).
183 super(BaseMeasurementTask, self).
__init__(**kwds)
185 if algMetadata
is None:
190 """Initialize the plugins (and slots) according to the configuration.
192 Derived class constructors should call this method to fill the self.plugins
193 attribute and add correspond output fields and slot aliases to the output schema.
195 In addition to the attributes added by BaseMeasurementTask.__init__, a self.schema
196 attribute holding the output schema must also be present before this method is called, .
198 Keyword arguments are forwarded directly to plugin constructors, allowing derived
199 classes to use plugins with different signatures.
204 if self.config.slots.centroid
is not None:
205 self.
plugins[self.config.slots.centroid] =
None
207 for executionOrder, name, config, PluginClass
in sorted(self.config.plugins.apply()):
212 if self.config.slots.centroid
is not None and self.
plugins[self.config.slots.centroid]
is None:
213 del self.
plugins[self.config.slots.centroid]
217 Call the measure() method on all plugins, handling exceptions in a consistent way.
219 @param[in,out] measRecord lsst.afw.table.SourceRecord that corresponds to the object being
220 measured, and where outputs should be written.
221 @param[in] *args Positional arguments forwarded to Plugin.measure()
222 @param[in] **kwds Keyword arguments. Two are handled locally:
223 - beginOrder: beginning execution order (inclusive): measurements with
224 executionOrder < beginOrder are not executed. None for no limit.
225 - endOrder: ending execution order (exclusive): measurements with
226 executionOrder >= endOrder are not executed. None for no limit.
227 the rest are forwarded to Plugin.measure()
229 This method can be used with plugins that have different signatures; the only requirement is that
230 'measRecord' be the first argument. Subsequent positional arguments and keyword arguments are
231 forwarded directly to the plugin.
233 This method should be considered "protected"; it is intended for use by derived classes, not users.
235 beginOrder = kwds.pop(
"beginOrder",
None)
236 endOrder = kwds.pop(
"endOrder",
None)
237 for plugin
in self.plugins.iter():
238 if beginOrder
is not None and plugin.getExecutionOrder() < beginOrder:
240 if endOrder
is not None and plugin.getExecutionOrder() >= endOrder:
243 plugin.measure(measRecord, *args, **kwds)
244 except FATAL_EXCEPTIONS:
246 except MeasurementError
as error:
247 plugin.fail(measRecord, error)
248 except Exception
as error:
249 self.log.warn(
"Error in %s.measure on record %s: %s"
250 % (plugin.name, measRecord.getId(), error))
251 plugin.fail(measRecord)
255 Call the measureN() method on all plugins, handling exceptions in a consistent way.
257 @param[in,out] measCat lsst.afw.table.SourceCatalog containing records for just
258 the source family to be measured, and where outputs should
260 @param[in] beginOrder beginning execution order (inclusive): measurements with
261 executionOrder < beginOrder are not executed. None for no limit.
262 @param[in] endOrder ending execution order (exclusive): measurements with
263 executionOrder >= endOrder are not executed. None for no limit.
264 @param[in] *args Positional arguments forwarded to Plugin.measure()
265 @param[in] **kwds Keyword arguments. Two are handled locally:
266 - beginOrder: beginning execution order (inclusive): measurements with
267 executionOrder < beginOrder are not executed. None for no limit.
268 - endOrder: ending execution order (exclusive): measurements with
269 executionOrder >= endOrder are not executed. None for no limit.
270 the rest are forwarded to Plugin.measure()
272 This method can be used with plugins that have different signatures; the only requirement is that
273 'measRecord' be the first argument. Subsequent positional arguments and keyword arguments are
274 forwarded directly to the plugin.
276 This method should be considered "protected"; it is intended for use by derived classes, not users.
278 beginOrder = kwds.pop(
"beginOrder",
None)
279 endOrder = kwds.pop(
"endOrder",
None)
280 for plugin
in self.plugins.iterN():
281 if beginOrder
is not None and plugin.getExecutionOrder() < beginOrder:
283 if endOrder
is not None and plugin.getExecutionOrder() >= endOrder:
286 plugin.measureN(measCat, *args, **kwds)
287 except FATAL_EXCEPTIONS:
289 except MeasurementError
as error:
290 for measRecord
in measCat:
291 plugin.fail(measRecord, error)
292 except Exception
as error:
293 for measRecord
in measCat:
294 plugin.fail(measRecord)
295 self.log.warn(
"Error in %s.measureN on records %s-%s: %s"
296 % (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.
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.