22"""Base measurement task, which subclassed by the single frame and forced
29from .pluginRegistry
import PluginMap
30from .exceptions
import FatalAlgorithmError, MeasurementError
31from .pluginsBase
import BasePluginConfig, BasePlugin
32from .noiseReplacer
import NoiseReplacerConfig
34__all__ = (
"BaseMeasurementPluginConfig",
"BaseMeasurementPlugin",
35 "BaseMeasurementConfig",
"BaseMeasurementTask")
39FATAL_EXCEPTIONS = (MemoryError, FatalAlgorithmError)
43 """Base config class for all measurement plugins.
47 Most derived classes will want to override `setDefaults` in order to
48 customize the default `executionOrder`.
50 A derived
class whose corresponding Plugin class implements
a do `measureN`
51 method should additionally add a bool `doMeasureN` field to replace the
52 bool
class attribute
defined here.
56 doc=
"whether to run this plugin in single-object mode")
62 """Base class for all measurement plugins.
66 This is class is
a placeholder
for future behavior which will be shared
67 only between measurement plugins
and is implemented
for symmetry
with the
68 measurement base plugin configuration
class
75 """Assign named plugins to measurement slots.
77 Slot configuration which assigns a particular named plugin to each of a set
78 of slots. Each slot allows a type of measurement to be fetched from the
84 The default algorithm
for each slot must be registered, even
if the default
89 centroid = Field(dtype=str, default="base_SdssCentroid", optional=
True,
90 doc=
"the name of the centroiding algorithm used to set source x,y")
91 shape =
Field(dtype=str, default=
"base_SdssShape", optional=
True,
92 doc=
"the name of the algorithm used to set source moments parameters")
93 psfShape =
Field(dtype=str, default=
"base_SdssShape_psf", optional=
True,
94 doc=
"the name of the algorithm used to set PSF moments parameters")
95 apFlux =
Field(dtype=str, default=
"base_CircularApertureFlux_12_0", optional=
True,
96 doc=
"the name of the algorithm used to set the source aperture instFlux slot")
97 modelFlux =
Field(dtype=str, default=
"base_GaussianFlux", optional=
True,
98 doc=
"the name of the algorithm used to set the source model instFlux slot")
99 psfFlux =
Field(dtype=str, default=
"base_PsfFlux", optional=
True,
100 doc=
"the name of the algorithm used to set the source psf instFlux slot")
101 gaussianFlux =
Field(dtype=str, default=
"base_GaussianFlux", optional=
True,
102 doc=
"the name of the algorithm used to set the source Gaussian instFlux slot")
103 calibFlux =
Field(dtype=str, default=
"base_CircularApertureFlux_12_0", optional=
True,
104 doc=
"the name of the instFlux measurement algorithm used for calibration")
107 """Set up a slots in a schema following configuration directives.
112 The schema in which slots will be set up.
116 This
is defined
in this configuration
class to support use in unit
117 tests without needing to construct an `lsst.pipe.base.Task` object.
119 aliases = schema.getAliasMap()
120 if self.
centroidcentroid
is not None:
121 aliases.set(
"slot_Centroid", self.
centroidcentroid)
122 if self.
shapeshape
is not None:
123 aliases.set(
"slot_Shape", self.
shapeshape)
124 if self.
psfShapepsfShape
is not None:
125 aliases.set(
"slot_PsfShape", self.
psfShapepsfShape)
126 if self.
apFluxapFlux
is not None:
127 aliases.set(
"slot_ApFlux", self.
apFluxapFlux)
129 aliases.set(
"slot_ModelFlux", self.
modelFluxmodelFlux)
130 if self.
psfFluxpsfFlux
is not None:
131 aliases.set(
"slot_PsfFlux", self.
psfFluxpsfFlux)
133 aliases.set(
"slot_GaussianFlux", self.
gaussianFluxgaussianFlux)
135 aliases.set(
"slot_CalibFlux", self.
calibFluxcalibFlux)
139 """Base configuration for all measurement driver tasks.
143 Subclasses should define the 'plugins' and 'undeblended' registries, e.g.
147 plugins = PluginBaseClass.registry.makeField(
150 doc=
"Plugins to be run and their configuration"
152 undeblended = PluginBaseClass.registry.makeField(
155 doc=
"Plugins to run on undeblended image"
158 where ``PluginBaseClass``
is the appropriate base
class of the plugin
159 (e.g., `SingleFramePlugin`
or `ForcedPlugin`).
163 dtype=SourceSlotConfig,
164 doc="Mapping from algorithms to special aliases in Source."
168 dtype=bool, default=
True, optional=
False,
169 doc=
'When measuring, replace other detected footprints with noise?')
172 dtype=NoiseReplacerConfig,
173 doc=
"configuration that sets how to replace neighboring sources with noise"
176 dtype=str, default=
"undeblended_",
177 doc=
"Prefix to give undeblended plugins"
181 lsst.pex.config.Config.validate(self)
182 if self.
slotsslots.centroid
is not None and self.
slotsslots.centroid
not in self.plugins.names:
183 raise ValueError(
"source centroid slot algorithm is not being run.")
184 if self.
slotsslots.shape
is not None and self.
slotsslots.shape
not in self.plugins.names:
185 raise ValueError(
"source shape slot algorithm '%s' is not being run." % self.
slotsslots.shape)
186 for slot
in (self.
slotsslots.psfFlux, self.
slotsslots.apFlux, self.
slotsslots.modelFlux,
187 self.
slotsslots.gaussianFlux, self.
slotsslots.calibFlux):
189 for name
in self.plugins.names:
190 if len(name) <= len(slot)
and name == slot[:len(name)]:
193 raise ValueError(
"source instFlux slot algorithm '%s' is not being run." % slot)
197 """Ultimate base class for all measurement tasks.
202 Will be modified
in-place to contain metadata about the plugins being
206 Additional arguments passed to `lsst.pipe.base.Task.__init__`.
210 This base
class for `SingleFrameMeasurementTask`
and
211 `ForcedMeasurementTask` mostly exists to share code between the two,
and
212 generally should
not be used directly.
215 ConfigClass = BaseMeasurementConfig
216 _DefaultName = "measurement"
219 """Plugins to be invoked (`PluginMap`).
221 Initially empty, this will be populated as plugins are initialized. It
222 should be considered read-only.
226 """Metadata about active plugins (`lsst.daf.base.PropertyList`).
228 Contains additional information about active plugins to be saved with
229 the output catalog. Will be filled by subclasses.
233 super(BaseMeasurementTask, self).
__init__(**kwds)
236 if algMetadata
is None:
241 """Initialize plugins (and slots) according to configuration.
246 Keyword arguments forwarded directly to plugin constructors.
250 Derived class constructors should call this method
to fill the
251 `plugins` attribute
and add corresponding output fields
and slot
252 aliases to the output schema.
254 In addition to the attributes added by `BaseMeasurementTask.__init__`,
255 a ``schema``` attribute holding the output schema must be present
256 before this method
is called.
258 Keyword arguments are forwarded directly to plugin constructors,
259 allowing derived classes to use plugins
with different signatures.
265 if self.config.slots.centroid
is not None:
266 self.
pluginsplugins[self.config.slots.centroid] =
None
269 for executionOrder, name, config, PluginClass
in sorted(self.config.plugins.apply()):
272 if getattr(PluginClass,
"hasLogName",
False):
273 self.
pluginsplugins[name] = PluginClass(config, name, metadata=self.
algMetadataalgMetadata,
274 logName=self.log.getChild(name).name, **kwds)
276 self.
pluginsplugins[name] = PluginClass(config, name, metadata=self.
algMetadataalgMetadata, **kwds)
281 if self.config.slots.centroid
is not None and self.
pluginsplugins[self.config.slots.centroid]
is None:
282 del self.
pluginsplugins[self.config.slots.centroid]
284 for executionOrder, name, config, PluginClass
in sorted(self.config.undeblended.apply()):
285 undeblendedName = self.config.undeblendedPrefix + name
286 if getattr(PluginClass,
"hasLogName",
False):
287 self.
undeblendedPluginsundeblendedPlugins[name] = PluginClass(config, undeblendedName,
289 logName=self.log.getChild(undeblendedName).name,
292 self.
undeblendedPluginsundeblendedPlugins[name] = PluginClass(config, undeblendedName,
296 """Call ``measure`` on all plugins and consistently handle exceptions.
301 The record corresponding to the object being measured. Will be
302 updated in-place
with the results of measurement.
304 Positional arguments forwarded to ``plugin.measure``
306 Keyword arguments. Two are handled locally:
309 Beginning execution order (inclusive). Measurements
with
310 ``executionOrder`` < ``beginOrder`` are
not executed. `
None`
314 Ending execution order (exclusive). Measurements
with
315 ``executionOrder`` >= ``endOrder`` are
not executed. `
None`
318 Others are forwarded to ``plugin.measure()``.
322 This method can be used
with plugins that have different signatures;
323 the only requirement
is that ``measRecord`` be the first argument.
324 Subsequent positional arguments
and keyword arguments are forwarded
325 directly to the plugin.
327 This method should be considered
"protected": it
is intended
for use by
328 derived classes,
not users.
330 beginOrder = kwds.pop("beginOrder",
None)
331 endOrder = kwds.pop(
"endOrder",
None)
333 if beginOrder
is not None and plugin.getExecutionOrder() < beginOrder:
335 if endOrder
is not None and plugin.getExecutionOrder() >= endOrder:
337 self.
doMeasurementdoMeasurement(plugin, measRecord, *args, **kwds)
340 """Call ``measure`` on the specified plugin.
342 Exceptions are handled in a consistent way.
346 plugin : subclass of `BasePlugin`
347 Plugin that will be executed.
349 The record corresponding to the object being measured. Will be
350 updated
in-place
with the results of measurement.
352 Positional arguments forwarded to ``plugin.measure()``.
354 Keyword arguments forwarded to ``plugin.measure()``.
358 This method can be used
with plugins that have different signatures;
359 the only requirement
is that ``plugin``
and ``measRecord`` be the first
360 two arguments. Subsequent positional arguments
and keyword arguments
361 are forwarded directly to the plugin.
363 This method should be considered
"protected": it
is intended
for use by
364 derived classes,
not users.
367 plugin.measure(measRecord, *args, **kwds)
368 except FATAL_EXCEPTIONS:
370 except MeasurementError
as error:
371 self.log.getChild(plugin.name).
debug(
372 "MeasurementError in %s.measure on record %s: %s",
373 plugin.name, measRecord.getId(), error)
374 plugin.fail(measRecord, error)
375 except Exception
as error:
376 self.log.getChild(plugin.name).
debug(
377 "Exception in %s.measure on record %s: %s",
378 plugin.name, measRecord.getId(), error)
379 plugin.fail(measRecord)
382 """Call ``measureN`` on all plugins and consistently handle exceptions.
387 Catalog containing only the records for the source family to be
388 measured,
and where outputs should be written.
390 Positional arguments forwarded to ``plugin.measure()``
392 Keyword arguments. Two are handled locally:
395 Beginning execution order (inclusive): Measurements
with
396 ``executionOrder`` < ``beginOrder`` are
not executed. `
None`
399 Ending execution order (exclusive): measurements
with
400 ``executionOrder`` >= ``endOrder`` are
not executed. `
None`
for
403 Others are are forwarded to ``plugin.measure()``.
407 This method can be used
with plugins that have different signatures;
408 the only requirement
is that ``measRecord`` be the first argument.
409 Subsequent positional arguments
and keyword arguments are forwarded
410 directly to the plugin.
412 This method should be considered
"protected": it
is intended
for use by
413 derived classes,
not users.
415 beginOrder = kwds.pop("beginOrder",
None)
416 endOrder = kwds.pop(
"endOrder",
None)
417 for plugin
in self.
pluginsplugins.iterN():
418 if beginOrder
is not None and plugin.getExecutionOrder() < beginOrder:
420 if endOrder
is not None and plugin.getExecutionOrder() >= endOrder:
425 """Call ``measureN`` on the specified plugin.
427 Exceptions are handled in a consistent way.
431 plugin : subclass of `BasePlugin`
432 Plugin that will be executed.
434 Catalog containing only the records
for the source family to be
435 measured,
and where outputs should be written.
437 Positional arguments forwarded to ``plugin.measureN()``.
439 Keyword arguments forwarded to ``plugin.measureN()``.
443 This method can be used
with plugins that have different signatures;
444 the only requirement
is that the ``plugin``
and ``measCat`` be the
445 first two arguments. Subsequent positional arguments
and keyword
446 arguments are forwarded directly to the plugin.
448 This method should be considered
"protected": it
is intended
for use by
449 derived classes,
not users.
452 plugin.measureN(measCat, *args, **kwds)
453 except FATAL_EXCEPTIONS:
456 except MeasurementError
as error:
457 for measRecord
in measCat:
458 self.log.getChild(plugin.name).
debug(
459 "MeasurementError in %s.measureN on records %s-%s: %s",
460 plugin.name, measCat[0].getId(), measCat[-1].getId(), error)
461 plugin.fail(measRecord, error)
462 except Exception
as error:
463 for measRecord
in measCat:
464 plugin.fail(measRecord)
465 self.log.getChild(plugin.name).
debug(
466 "Exception in %s.measureN on records %s-%s: %s",
467 plugin.name, measCat[0].getId(), measCat[-1].getId(), error)
Defines the fields and offsets for a table.
Record class that contains measurements made on a single exposure.
Table class that contains measurements made on a single exposure.
Class for storing ordered metadata with comments.
def doMeasurement(self, plugin, measRecord, *args, **kwds)
def initializePlugins(self, **kwds)
def doMeasurementN(self, plugin, measCat, *args, **kwds)
def callMeasure(self, measRecord, *args, **kwds)
def __init__(self, algMetadata=None, **kwds)
def callMeasureN(self, measCat, *args, **kwds)
def setupSchema(self, schema)