22 from collections
import namedtuple
27 from lsst.utils.timer
import timeMethod
29 from .pluginsBase
import BasePlugin, BasePluginConfig
30 from .pluginRegistry
import PluginRegistry, PluginMap
31 from .
import FatalAlgorithmError, MeasurementError
35 FATAL_EXCEPTIONS = (MemoryError, FatalAlgorithmError)
37 __all__ = (
"CatalogCalculationPluginConfig",
"CatalogCalculationPlugin",
"CatalogCalculationConfig",
38 "CatalogCalculationTask")
42 """Default configuration class for catalog calcuation plugins.
48 """Base class for catalog calculation plugins.
52 config : `CatalogCalculationPlugin.ConfigClass`
55 The string the plugin was registered with.
56 schema : `lsst.afw.table.Schema`
57 The source schema, New fields should be added here to
58 hold output produced by this plugin.
59 metadata : `lsst.daf.base.PropertySet`
60 Plugin metadata that will be attached to the output catalog
63 ConfigClass = CatalogCalculationPluginConfig
66 """List of available plugins (`lsst.meas.base.PluginRegistry`).
70 """Does the plugin operate on a single source or the whole catalog (`str`)?
72 If the plugin operates on a single source at a time, this should be set to
73 ``"single"``; if it expects the whoe catalog, to ``"multi"``. If the
74 plugin is of type ``"multi"``, the `fail` method must be implemented to
75 accept the whole catalog. If the plugin is of type ``"single"``, `fail`
76 should accept a single source record.
79 def __init__(self, config, name, schema, metadata):
80 BasePlugin.__init__(self, config, name)
84 r"""Used to set the relative order of plugin execution.
86 The values returned by `getExecutionOrder` are compared across all
87 plugins, and smaller numbers run first.
91 `CatalogCalculationPlugin`\s must run with
92 `BasePlugin.DEFAULT_CATALOGCALCULATION` or higher.
94 All plugins must implement this method with an appropriate run level
96 raise NotImplementedError()
99 """Perform the calculation specified by this plugin.
101 This method can either be used to operate on a single catalog record
102 or a whole catalog, populating it with the output defined by this
105 Note that results may be added to catalog records as new columns, or
106 may result in changes to existing values.
110 cat : `lsst.afw.table.SourceCatalog` or `lsst.afw.table.SourceRecord`
111 May either be a `~lsst.afw.table.SourceCatalog` or a single
112 `~lsst.afw.table.SourceRecord`, depending on the plugin type. Will
113 be updated in place to contain the results of plugin execution.
115 Any additional keyword arguments that may be passed to the plugin.
117 raise NotImplementedError()
121 """Handle errors that are thrown by catalog calculation plugins.
123 This is a context manager.
127 plugin : `CatalogCalculationPlugin`
128 The plugin that is to be run.
129 cat : `lsst.afw.table.SourceCatalog` or `lsst.afw.table.SourceRecord`
130 May either be a `~lsst.afw.table.SourceCatalog` or a single
131 `~lsst.afw.table.SourceRecord`, depending on the plugin type.
132 log : `lsst.log.Log` or `logging.Logger`
133 A logger. Generally, this should be the logger of the object in which
134 the context manager is being used.
144 def __exit__(self, exc_type, exc_value, traceback):
147 if exc_type
in FATAL_EXCEPTIONS:
149 elif exc_type
is MeasurementError:
150 self.plugin.fail(self.cat, exc_value)
152 self.log.warning(
"Error in %s.calculate: %s", self.plugin.name, exc_value)
157 """Config class for the catalog calculation driver task.
159 Specifies which plugins will execute when the `CatalogCalculationTask`
160 associated with this configuration is run.
163 plugins = CatalogCalculationPlugin.registry.makeField(
165 default=[
"base_ClassificationExtendedness",
166 "base_FootprintArea"],
167 doc=
"Plugins to be run and their configuration")
171 """Run plugins which operate on a catalog of sources.
173 This task facilitates running plugins which will operate on a source
174 catalog. These plugins may do things such as classifying an object based
175 on source record entries inserted during a measurement task.
179 plugMetaData : `lsst.daf.base.PropertyList` or `None`
180 Will be modified in-place to contain metadata about the plugins being
181 run. If `None`, an empty `~lsst.daf.base.PropertyList` will be
184 Additional arguments passed to the superclass constructor.
188 Plugins may either take an entire catalog to work on at a time, or work on
191 ConfigClass = CatalogCalculationConfig
192 _DefaultName =
"catalogCalculation"
194 def __init__(self, schema, plugMetadata=None, **kwargs):
195 lsst.pipe.base.Task.__init__(self, **kwargs)
197 if plugMetadata
is None:
205 """Initialize the plugins according to the configuration.
208 pluginType = namedtuple(
'pluginType',
'single multi')
214 for executionOrder, name, config, PluginClass
in sorted(self.config.plugins.apply()):
216 self.
executionDictexecutionDict[executionOrder] = pluginType(single=[], multi=[])
217 if PluginClass.getExecutionOrder() >= BasePlugin.DEFAULT_CATALOGCALCULATION:
218 plug = PluginClass(config, name, self.
schemaschema, metadata=self.
plugMetadataplugMetadata)
219 self.
pluginsplugins[name] = plug
220 if plug.plugType ==
'single':
221 self.
executionDictexecutionDict[executionOrder].single.append(plug)
222 elif plug.plugType ==
'multi':
223 self.
executionDictexecutionDict[executionOrder].multi.append(plug)
225 errorTuple = (PluginClass, PluginClass.getExecutionOrder(),
226 BasePlugin.DEFAULT_CATALOGCALCULATION)
227 raise ValueError(
"{} has an execution order less than the minimum for an catalogCalculation "
228 "plugin. Value {} : Minimum {}".format(*errorTuple))
232 """The entry point for the catalog calculation task.
236 meascat : `lsst.afw.table.SourceCatalog`
237 Catalog for measurement.
242 """Run each of the plugins on the catalog.
246 catalog : `lsst.afw.table.SourceCatalog`
247 The catalog on which the plugins will operate.
253 plug.calculate(catalog)
255 for measRecord
in catalog:
256 for plug
in self.
executionDictexecutionDict[runlevel].single:
257 with CCContext(plug, measRecord, self.log):
258 plug.calculate(measRecord)
def __init__(self, plugin, cat, log)
def __exit__(self, exc_type, exc_value, traceback)
def calculate(self, cat, **kwargs)
def __init__(self, config, name, schema, metadata)
def getExecutionOrder(cls)
def __init__(self, schema, plugMetadata=None, **kwargs)
def callCompute(self, catalog)
def initializePlugins(self)