LSST Applications g0265f82a02+0e5473021a,g02d81e74bb+bd2ed33bd6,g1470d8bcf6+de7501a2e0,g14a832a312+ff425fae3c,g2079a07aa2+86d27d4dc4,g2305ad1205+91a32aca49,g295015adf3+762506a1ad,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g3ddfee87b4+c34e8be1fa,g487adcacf7+5fae3daba8,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+ea1711114f,g5a732f18d5+53520f316c,g64a986408d+bd2ed33bd6,g858d7b2824+bd2ed33bd6,g8a8a8dda67+585e252eca,g99cad8db69+016a06b37a,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,ga8c6da7877+ef4e3a5875,gb0e22166c9+60f28cb32d,gb6a65358fc+0e5473021a,gba4ed39666+c2a2e4ac27,gbb8dafda3b+09e12c87ab,gc120e1dc64+bc2e06c061,gc28159a63d+0e5473021a,gcf0d15dbbd+c34e8be1fa,gdaeeff99f8+f9a426f77a,ge6526c86ff+508d0e0a30,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gf18bd8381d+8d59551888,gf1cff7945b+bd2ed33bd6,w.2024.16
LSST Data Management Base Package
Loading...
Searching...
No Matches
wrappers.py
Go to the documentation of this file.
1# This file is part of meas_base.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22import warnings
23
24import lsst.pex.config
25from .pluginsBase import BasePlugin
26from .pluginRegistry import generateAlgorithmName, register
27from .apCorrRegistry import addApCorrName
28from .sfm import SingleFramePlugin, SingleFramePluginConfig
29from .forcedMeasurement import ForcedPlugin, ForcedPluginConfig
30
31__all__ = ("wrapSingleFrameAlgorithm", "wrapForcedAlgorithm", "wrapSimpleAlgorithm",
32 "wrapAlgorithm", "wrapAlgorithmControl", "wrapTransform", "GenericPlugin")
33
34
36
37 def __init__(self, config, name, schema, metadata, logName=None):
38 SingleFramePlugin.__init__(self, config, name, schema, metadata, logName=logName)
39 if hasattr(self, "hasLogName") and self.hasLogName and logName is not None:
40 self.cpp = self.factory(config, name, schema, metadata, logName=logName)
41 else:
42 self.cpp = self.factory(config, name, schema, metadata)
43
44 def measure(self, measRecord, exposure):
45 self.cpp.measure(measRecord, exposure)
46
47 def measureN(self, measCat, exposure):
48 self.cpp.measureN(measCat, exposure)
49
50 def fail(self, measRecord, error=None):
51 self.cpp.fail(measRecord, error.cpp if error is not None else None)
52
53
55
56 def __init__(self, config, name, schemaMapper, metadata, logName=None):
57 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata, logName=logName)
58 if hasattr(self, "hasLogName") and self.hasLogName and logName is not None:
59 self.cpp = self.factory(config, name, schemaMapper, metadata, logName=logName)
60 else:
61 self.cpp = self.factory(config, name, schemaMapper, metadata)
62
63 def measure(self, measRecord, exposure, refRecord, refWcs):
64 self.cpp.measureForced(measRecord, exposure, refRecord, refWcs)
65
66 def measureN(self, measCat, exposure, refCat, refWcs):
67 self.cpp.measureNForced(measCat, exposure, refCat, refWcs)
68
69 def fail(self, measRecord, error=None):
70 self.cpp.fail(measRecord, error.cpp if error is not None else None)
71
72
73def wrapAlgorithmControl(Base, Control, module=None, hasMeasureN=False):
74 """Wrap a C++ algorithm's control class into a Python config class.
75
76 Parameters
77 ----------
78 Base : `SingleFramePluginConfig` or `ForcedPluginConfig`
79 Base class for the returned config.
80 Control : pybind11-wrapped version of a C++ class.
81 Control class to be wrapped.
82 module : module, `str`, `int`, or `None`; optional
83 Either a module object, a string specifying the name of the module, or
84 an integer specifying how far back in the stack to look for the module
85 to use: ``0`` is `lsst.pex.config.wrap`, ``1`` is
86 `lsst.meas.base.wrappers`, ``2`` is the immediate caller, etc. This
87 will be used to set ``__module__`` for the new config class, and the
88 class will also be added to the module. The default is none in which
89 case module will be looked up from Control.
90 hasMeasureN : `bool`, optional
91 Whether the plugin supports fitting multiple objects at once (if so, a
92 config option to enable/disable this will be added).
93
94 Returns
95 -------
96 ConfigClass : `lsst.pex.config.Config`
97 A new subclass of lsst.pex.config.Config.
98
99 Notes
100 -----
101 This function is generally only called by `wrapAlgorithm`; it is unlikely
102 users will have to call it directly.
103 """
104 if hasMeasureN:
105 # We need to add a Config field to enable multi-object measurement, to
106 # replace the simple bool class attribute that's on the base class.
107 # To do that, we create the Config class dynamically here, then call
108 # makeControlClass to finish it off by adding fields from the control
109 # object.
110 cls = type(
111 Control.__name__.replace("Control", "Config"),
112 (Base,),
113 {"doMeasureN": lsst.pex.config.Field(dtype=bool, default=True,
114 doc="whether to run this plugin in multi-object mode")}
115 )
116 ConfigClass = lsst.pex.config.makeConfigClass(Control, module=module, cls=cls)
117 else:
118 # If we don't have to add that Config field, we can delegate all of
119 # the work to pex_config's makeControlClass
120 ConfigClass = lsst.pex.config.makeConfigClass(Control, module=module, base=Base)
121 return ConfigClass
122
123
124def wrapAlgorithm(Base, AlgClass, factory, executionOrder, name=None, Control=None,
125 ConfigClass=None, TransformClass=None, doRegister=True, shouldApCorr=False,
126 apCorrList=(), hasLogName=False, **kwds):
127 """Wrap a C++ algorithm class to create a measurement plugin.
128
129 Parameters
130 ----------
131 Base : `SingleFramePlugin` or `ForcedPlugin`
132 Base class for the returned Plugin.
133 AlgClass : API compatible with `SingleFrameAlgorithm` or `ForcedAlgorithm`
134 C++ algorithm class to convert. May either derive directly from
135 `SingleFrameAlgorithm` or `ForcedAlgorithm`, or be an unrelated class
136 which has the same ``measure`` and ``measureN`` signatures.
137 factory : callable
138 A callable that is used to construct an instance of ``AlgClass``. It
139 must take four arguments, either ``(config, name, schema, metadata)``
140 or ``(config, name, schemaMapper, metadata)``, depending on whether
141 the algorithm is single-frame or forced.
142 executionOrder : `float`
143 The order this plugin should be run, relative to others
144 (see `BasePlugin.getExecutionOrder`).
145 name : `str`, optional
146 String to use when registering the algorithm. Ignored if
147 ``doRegistry=False``, set to ``generateAlgorithmName(AlgClass)`` if
148 `None`.
149 Control : Pybind11-wrapped version of a C++ class, optional
150 Pybind11-wrapped C++ Control class for the algorithm;
151 ``AlgClass.Control`` is used if `None`. Ignored if ``ConfigClass``
152 is not `None`.
153 ConfigClass : subclass of `BaseMeasurementPluginConfig`
154 Python config class that wraps the C++ algorithm's pybind11-wrapped
155 Control class. If `None`, `wrapAlgorithmControl` is called to
156 generate a Config class using the ``Control`` argument.
157 TransformClass : subclass of `MeasurementTransform`, optional
158 Transformation which may be used to post-process the results of
159 measurement. If `None`, the default defined by `BasePlugin` is
160 used.
161 doRegister : `bool`, optional
162 If `True` (the default), register the plugin with ``Base``'s
163 registry, allowing it to be used by measurement tasks.
164 shouldApCorr : `bool`, optional
165 Does this algorithm measure an instFlux that can be aperture
166 corrected? This is shorthand for ``apCorrList=[name]`` and is ignored
167 if ``apCorrList`` is specified.
168 apCorrList : iterable of `str`, optional
169 Field name prefixes for instFlux fields to be aperture corrected. If
170 an algorithm measures a single instFlux that should be aperture
171 corrected, then it is simpler to set ``shouldApCorr=True``. However,
172 if an algorithm produces multiple such fields, then specify
173 ``apCorrList`` instead. For example, ``modelfit_CModel`` produces
174 three such fields: ``apCorrList= ("modelfit_CModel_exp",
175 "modelfit_CModel_exp", "modelfit_CModel_def")`` If ``apCorrList`` is
176 not empty then ``shouldApCorr`` is ignored. If non-empty and
177 ``doRegister`` is `True` then the names are added to the set
178 retrieved by ``getApCorrNameSet``.
179 hasLogName : `bool`, optional
180 `True` if the C++ algorithm supports ``logName`` as a constructor
181 argument.
182 **kwds
183 Additional keyword arguments passed to generateAlgorithmControl, which
184 may include:
185
186 - ``hasMeasureN``: Whether the plugin supports fitting multiple
187 objects at once ;if so, a config option to enable/disable this will
188 be added (`bool`).
189 - ``executionOrder``: If not `None`, an override for the default
190 execution order for this plugin (the default is ``2.0``, which is
191 usually appropriate for fluxes; `bool`).
192
193 Returns
194 -------
195 PluginClass : subclass of ``Base``
196 The new plugin class.
197 """
198 if ConfigClass is None:
199 if Control is None:
200 Control = AlgClass.Control
201 ConfigClass = wrapAlgorithmControl(Base.ConfigClass, Control, **kwds)
202
203 def getExecutionOrder():
204 return executionOrder
205 typeDict = dict(AlgClass=AlgClass, ConfigClass=ConfigClass, factory=staticmethod(factory),
206 getExecutionOrder=staticmethod(getExecutionOrder))
207 if TransformClass:
208 typeDict['getTransformClass'] = staticmethod(lambda: TransformClass)
209 PluginClass = type(AlgClass.__name__ + Base.__name__, (Base,), typeDict)
210 if doRegister:
211 if name is None:
212 name = generateAlgorithmName(AlgClass)
213 Base.registry.register(name, PluginClass)
214 if shouldApCorr:
215 addApCorrName(name)
216 PluginClass.hasLogName = hasLogName
217 return PluginClass
218
219
220def wrapSingleFrameAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False,
221 hasLogName=False, deprecated=None, **kwds):
222 """Expose a C++ ``SingleFrameAlgorithm`` class as a measurement plugin.
223
224 Parameters
225 ----------
226 AlgClass : API compatible with `SingleFrameAlgorithm`
227 C++ algorithm class to convert. May either derive directly from
228 `SingleFrameAlgorithm` or be an unrelated class which has the same
229 ``measure``, ``measureN`` and ``fail`` signatures.
230 executionOrder : `float`
231 The order this plugin should be run, relative to others
232 (see `BasePlugin.getExecutionOrder`).
233 name : `str`, optional
234 Name to use when registering the algorithm. Ignored if
235 ``doRegistry=False``; set to ``generateAlgorithmName(AlgClass)`` if
236 `None`.
237 needsMetadata : `bool`, optional
238 Sets whether the ``AlgClass``'s constructor should be passed a
239 `~lsst.daf.base.PropertySet` metadata argument.
240 hasMeasureN : `bool`, optional
241 Does the algorithm support simultaneous measurement of multiple
242 sources? If `True`, a `bool` ``doMeasureN`` field will be added to
243 the generated config class, and its value will be passed as the last
244 argument when calling the ``AlgClass`` constructor.
245 hasLogName : `bool`, optional
246 `True` if the C++ algorithm supports ``logName`` as a constructor
247 argument.
248 deprecated : `str`, optional
249 If specified, emit as a deprecation warning when the plugin is
250 constructed.
251 **kwds
252 Additional keyword arguments are passed to the lower-level
253 `wrapAlgorithm` and `wrapAlgorithmControl` classes.
254
255 Returns
256 -------
257 singleFramePlugin : subclass of `SingleFramePlugin`
258 The new measurement plugin class.
259
260 Notes
261 -----
262 The first three arguments to the C++ constructor are expected to be
263 ``Control const & ctrl, std::string const & name, Schema & schema``.
264
265 If ``needsMetadata`` is `True`, we also append ``PropertySet & metadata``.
266
267 If ``hasMeasureN`` is `True`, we also append ``bool doMeasureN``.
268
269 If ``hasLogName`` is `True`, we also append ``std::string logName``.
270
271 If more than one of the above is `True`, the metadata ``PropertySet``
272 precedes the ``doMeasureN`` ``bool`` and the ``logName`` comes last of the
273 three.
274 """
275 if hasMeasureN:
276 if needsMetadata:
277 def factory(config, name, schema, metadata, **kwargs):
278 if deprecated:
279 warnings.warn(deprecated, category=FutureWarning)
280 return AlgClass(config.makeControl(), name, schema, metadata, config.doMeasureN, **kwargs)
281 else:
282 def factory(config, name, schema, metadata, **kwargs):
283 if deprecated:
284 warnings.warn(deprecated, category=FutureWarning)
285 return AlgClass(config.makeControl(), name, schema, config.doMeasureN, **kwargs)
286 else:
287 if needsMetadata:
288 def factory(config, name, schema, metadata, **kwargs):
289 if deprecated:
290 warnings.warn(deprecated, category=FutureWarning)
291 return AlgClass(config.makeControl(), name, schema, metadata, **kwargs)
292 else:
293 def factory(config, name, schema, metadata, **kwargs):
294 if deprecated:
295 warnings.warn(deprecated, category=FutureWarning)
296 return AlgClass(config.makeControl(), name, schema, **kwargs)
297
298 return wrapAlgorithm(WrappedSingleFramePlugin, AlgClass, executionOrder=executionOrder, name=name,
299 factory=factory, hasMeasureN=hasMeasureN, hasLogName=hasLogName, **kwds)
300
301
302def wrapForcedAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False,
303 hasMeasureN=False, needsSchemaOnly=False, hasLogName=False,
304 deprecated=None, **kwds):
305 """Expose a C++ ``ForcedAlgorithm`` class as a measurement plugin.
306
307 Parameters
308 ----------
309 AlgClass : API compatible with `ForcedAlgorithm`
310 C++ algorithm class to convert. May either derive directly from
311 `ForcedAlgorithm` or be an unrelated class which has the same
312 ``measure``, ``measureN`` and ``fail`` signatures.
313 executionOrder : `float`
314 The order this plugin should be run, relative to others
315 (see `BasePlugin.getExecutionOrder`).
316 name : `str`, optional
317 Name to use when registering the algorithm. Ignored if
318 ``doRegistry=False``; set to ``generateAlgorithmName(AlgClass)`` if
319 `None`.
320 needsMetadata : `bool`, optional
321 Sets whether the ``AlgClass``'s constructor should be passed a
322 `~lsst.daf.base.PropertySet` metadata argument.
323 hasMeasureN : `bool`, optional
324 Does the algorithm support simultaneous measurement of multiple
325 sources? If `True`, a `bool` ``doMeasureN`` field will be added to
326 the generated config class, and its value will be passed as the last
327 argument when calling the ``AlgClass`` constructor.
328 hasLogName : `bool`, optional
329 `True` if the C++ algorithm supports ``logName`` as a constructor
330 argument.
331 needsSchemaOnly : `bool`, optional
332 Whether the algorithm constructor expects a Schema argument
333 (representing the output `~lsst.afw.table.Schema`) rather than the
334 full `~lsst.afw.table.SchemaMapper` (which provides access to both the
335 reference schema and the output schema).
336 deprecated : `str`, optional
337 If specified, emit as a deprecation warning when the plugin is
338 constructed.
339 **kwds
340 Additional keyword arguments are passed to the lower-level
341 `wrapAlgorithm` and `wrapAlgorithmControl` classes.
342
343 Returns
344 -------
345 forcedPlugin : subclass of `ForcedPlugin`
346 The new measurement plugin class.
347
348 Notes
349 -----
350 The first two arguments to the C++ constructor are expected to be
351 ``Control const & ctrl, std::string const & name``
352
353 If ``needsSchemaOnly`` is `True`, then the third argument will be
354 ``Schema & schema``; otherwise, it will be ``SchemaMapper &
355 schemaMapper``.
356
357 If ``needsMetadata`` is `True`, we also append ``PropertySet &
358 metadata``.
359
360 If ``hasMeasureN`` is `True`, we also append ``bool doMeasureN``.
361
362 If ``hasLogName`` is `True`, we also append ``std::string logName``.
363
364 If more than one of the above is `True`, the metadata ``PropertySet``
365 precedes the ``doMeasureN`` ``bool`` and the ``logName`` comes last of the
366 three.
367 """
368 if needsSchemaOnly:
369 def extractSchemaArg(m):
370 return m.editOutputSchema()
371 else:
372 def extractSchemaArg(m):
373 return m
374 if hasMeasureN:
375 if needsMetadata:
376 def factory(config, name, schemaMapper, metadata, **kwargs):
377 if deprecated:
378 warnings.warn(deprecated, category=FutureWarning)
379 return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
380 metadata, config.doMeasureN, **kwargs)
381 else:
382 def factory(config, name, schemaMapper, metadata, **kwargs):
383 if deprecated:
384 warnings.warn(deprecated, category=FutureWarning)
385 return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
386 config.doMeasureN, **kwargs)
387 else:
388 if needsMetadata:
389 def factory(config, name, schemaMapper, metadata, **kwargs):
390 if deprecated:
391 warnings.warn(deprecated, category=FutureWarning)
392 return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
393 metadata, **kwargs)
394 else:
395 def factory(config, name, schemaMapper, metadata, **kwargs):
396 if deprecated:
397 warnings.warn(deprecated, category=FutureWarning)
398 return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper), **kwargs)
399
400 return wrapAlgorithm(WrappedForcedPlugin, AlgClass, executionOrder=executionOrder, name=name,
401 factory=factory, hasLogName=hasLogName, **kwds)
402
403
404def wrapSimpleAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False,
405 hasLogName=False, deprecated=None, **kwds):
406 r"""Expose a C++ ``SimpleAlgorithm`` class as a measurement plugin.
407
408 ``SimpleAlgorithm``\ s are made available as both `SingleFramePlugin`\ s
409 and `ForcedPlugin`\ s.
410
411 Parameters
412 ----------
413 AlgClass : Subclass of C++ ``SimpleAlgorithm``, or API compatible
414 Algorithm class to convert. The C++ class should be wrapped with
415 Pybind11, and must provide ``measure()``, ``measureN()`` and ``fail()`
416 signatures equivalent to ``SimpleAlgorithm``.
417 executionOrder : `float`
418 The order this plugin should be run, relative to others
419 (see `~BasePlugin.getExecutionOrder`).
420 name : `str`, optional
421 Name to use when registering the algorithm. Ignored if
422 ``doRegistry=False``; set to ``generateAlgorithmName(AlgClass)`` if
423 `None`.
424 needsMetadata : `bool`, optional
425 Sets whether the ``AlgClass``'s constructor should be passed a
426 `~lsst.daf.base.PropertySet` metadata argument.
427 hasMeasureN : `bool`, optional
428 Does the algorithm support simultaneous measurement of multiple
429 sources? If `True`, a `bool` ``doMeasureN`` field will be added to
430 the generated config class, and its value will be passed as the last
431 argument when calling the ``AlgClass`` constructor.
432 hasLogName : `bool`, optional
433 `True` if the C++ algorithm supports ``logName`` as a constructor
434 argument.
435 deprecated : `str`, optional
436 If specified, emit as a deprecation warning when the plugin is
437 constructed.
438 **kwds
439 Additional keyword arguments are passed to the lower-level
440 `wrapAlgorithm` and `wrapAlgorithmControl` classes.
441
442 Returns
443 -------
444 singleFramePlugin : subclass of `SingleFramePlugin`
445 The new single frame measurement plugin class.
446 forcedPlugin : subclass of `ForcedPlugin`
447 The new forced measurement plugin class.
448
449 Notes
450 -----
451 The first three arguments to the C++ constructor are expected to be
452 ``Control const & ctrl, std::string const & name, Schema & schema``.
453
454 If ``needsMetadata`` is `True`, we also append ``PropertySet &
455 metadata``.
456
457 If ``hasMeasureN`` is `True`, we also append ``bool doMeasureN``.
458
459 If ``hasLogName`` is `True`, we also append ``std::string logName``.
460
461 If more than one of the above is `True`, the metadata ``PropertySet``
462 precedes the ``doMeasureN`` ``bool`` and the ``logName`` comes last of the
463 three.
464 """
465 return (wrapSingleFrameAlgorithm(AlgClass, executionOrder=executionOrder, name=name,
466 needsMetadata=needsMetadata, hasLogName=hasLogName,
467 deprecated=deprecated, **kwds),
468 wrapForcedAlgorithm(AlgClass, executionOrder=executionOrder, name=name,
469 needsMetadata=needsMetadata, hasLogName=hasLogName,
470 needsSchemaOnly=True, **kwds))
471
472
473def wrapTransform(transformClass, hasLogName=False):
474 """Modify a C++ transform to accept either a ``Config`` or a ``Control``.
475
476 That is, the configuration may either be provided as a (C++) ``Control``
477 object or an instance of a Python class derived from
478 `~lsst.meas.base.BasePluginConfig`.
479
480 Parameters
481 ----------
482 transformClass : Subclass of C++ ``BaseTransform``
483 A C++ transform class, wrapped with pybind11. Its constructor must
484 take a ``Control`` object, a ``std::string``, and a
485 `~lsst.afw.table.SchemaMapper`, in that order.
486 hasLogName : `bool`, optional
487 Unused.
488 """
489 oldInit = transformClass.__init__
490
491 def _init(self, ctrl, name, mapper, logName=None):
492 if hasattr(ctrl, "makeControl"):
493 ctrl = ctrl.makeControl()
494 # logName signature needs to be on this Class __init__, but is not
495 # needed by the C++ plugin.
496 oldInit(self, ctrl, name, mapper)
497
498 transformClass.__init__ = _init
499
500
502 """Abstract base class for a generic plugin.
503
504 Parameters
505 ----------
506 config : `lsst.pex.config.Config`
507 An instance of this class' ``ConfigClass``.
508 name : `str`
509 Name of this measurement plguin, for registering.
510 schema : `lsst.afw.table.Schema`
511 The catalog schema. New fields should be added here to
512 hold measurements produced by this plugin.
513 metadata : `lsst.daf.base.PropertySet`
514 Metadata that will be attached to the output catalog.
515 logName : `str`, optional
516 Name of log component.
517
518 Notes
519 -----
520 A generic plugin can be used with the `singleFramePluginFromGeneric`
521 and/or `forcedPluginFromGeneric` wrappers to create classes that can be
522 used for single frame measurement and/or forced measurement (as
523 appropriate). The only real difference between `SingleFramePlugin` and
524 `ForcedPlugin` is the ``measure`` method; this class introduces a shared
525 signature for `measure` that, in combination with the aforementioned
526 wrappers, allows both plugin styles to share a single implementation.
527
528 This doesn't use `abc.ABCMeta` because I couldn't get it to work
529 with a superclass.
530
531 Sub-classes should set `ConfigClass` and implement the `measure` and
532 `measureN` methods. They may optionally provide alternative
533 implementations for the `__init__`, `fail` and `getExecutionOrder`
534 methods.
535
536 This default implementation simply adds a field for recording
537 a fatal failure of the measurement plugin.
538 """
539 ConfigClass = None
540
541 @classmethod
543 return 0
544
545 def __init__(self, config, name, schema, metadata, logName=None):
546 BasePlugin.__init__(self, config, name, logName=logName)
547 self._failKey = schema.addField(name + '_flag', type="Flag", doc="Set for any fatal failure")
548
549 def measure(self, measRecord, exposure, center):
550 """Measure a single source.
551
552 It is the responsibility of this method to perform the desired
553 measurement and record the result in the `measRecord`.
554
555 Parameters
556 ----------
557 measRecord : `lsst.afw.table.SourceRecord`
558 Catalog record for the source being measured.
559 exposure : `lsst.afw.image.Exposure`
560 Exposure on which the source is being measured.
561 center : `lsst.geom.Point2D`
562 Pixel coordinates of the object.
563
564 Raises
565 ------
566 MeasurementError
567 Raised if the measurement fails for a known/justifiable reason.
568 """
569 raise NotImplementedError()
570
571 def measureN(self, measCat, exposure, refCat, refWcs):
572 """Measure multiple sources.
573
574 It is the responsibility of this method to perform the desired
575 measurement and record the result in the `measCat`.
576
577 Parameters
578 ----------
579 measCat : `lsst.afw.table.SourceCatalog`
580 Catalog for the sources being measured.
581 exposure : `lsst.afw.image.Exposure`
582 Exposure on which the source is being measured.
583 refCat : `lsst.afw.table.SourceCatalog`
584 Reference catalog.
585 refWcs : `lsst.afw.image.Wcs`
586 Astrometric solution for the reference image.
587
588 Raises
589 ------
590 MeasurementError
591 Raised if the measurement fails for a known/justifiable reason.
592 """
593 raise NotImplementedError()
594
595 def fail(self, measRecord, error=None):
596 """Record a measurement failure.
597
598 This default implementation simply records the failure in the source
599 record.
600
601 Parameters
602 ----------
603 measRecord : `lsst.afw.table.SourceRecord`
604 Catalog record for the source being measured.
605 error : `Exception`
606 Error causing failure, or `None`.
607 """
608 measRecord.set(self._failKey, True)
609
610 @classmethod
611 def makeSingleFramePlugin(cls, name):
612 """Produce a SingleFramePlugin subclass from this GenericPlugin class.
613
614 The class is also registered.
615
616 Parameters
617 ----------
618 name : `str`
619 Name of plugin to register.
620 """
621 class SingleFrameFromGenericConfig(cls.ConfigClass, SingleFramePluginConfig):
622 pass
623
624 @register(name)
625 class SingleFrameFromGenericPlugin(SingleFramePlugin):
626 ConfigClass = SingleFrameFromGenericConfig
627
628 def __init__(self, config, name, schema, metadata, logName=None):
629 SingleFramePlugin.__init__(self, config, name, schema, metadata, logName=logName)
630 self._generic = cls(config, name, schema, metadata)
631
632 def measure(self, measRecord, exposure):
633 center = measRecord.getCentroid()
634 return self._generic.measure(measRecord, exposure, center)
635
636 def measureN(self, measCat, exposure, refCat, refWcs):
637 return self._generic.measureN(measCat, exposure, refCat, refWcs)
638
639 def fail(self, measRecord, error=None):
640 self._generic.fail(measRecord, error if error is not None else None)
641
642 @staticmethod
643 def getExecutionOrder():
645
646 def getTransformClass(self):
647 return self._generic.getTransformClass()
648
649 return SingleFrameFromGenericPlugin
650
651 @classmethod
652 def makeForcedPlugin(cls, name):
653 """Produce a ForcedPlugin subclass from this GenericPlugin class.
654
655 The class is also registered.
656
657 Parameters
658 ----------
659 name : `str`
660 Name of plugin to register.
661 """
662 class ForcedFromGenericConfig(cls.ConfigClass, ForcedPluginConfig):
663 pass
664
665 @register(name)
666 class ForcedFromGenericPlugin(ForcedPlugin):
667 ConfigClass = ForcedFromGenericConfig
668
669 def __init__(self, config, name, schemaMapper, metadata, logName=None):
670 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata, logName=logName)
671 schema = schemaMapper.editOutputSchema()
672 self._generic = cls(config, name, schema, metadata)
673
674 def measure(self, measRecord, exposure, refRecord, refWcs):
675 # Forced photometry tasks should almost be configured with a
676 # centroider (populating measRecord.getCentroid()) that
677 # transforms the reference centroid, but we respect their
678 # decision if they decided to re-centroid (or do something more
679 # unusual) on the image being measured.
680 center = measRecord.getCentroid()
681 return self._generic.measure(measRecord, exposure, center)
682
683 def measureN(self, measCat, exposure, refCat, refWcs):
684 return self._generic.measureN(measCat, exposure, refCat, refWcs)
685
686 def fail(self, measRecord, error=None):
687 self._generic.fail(measRecord, error if error is not None else None)
688
689 @staticmethod
690 def getExecutionOrder():
692
693 def getTransformClass(self):
694 return self._generic.getTransformClass()
695
696 return ForcedFromGenericPlugin
measure(self, measRecord, exposure, center)
Definition wrappers.py:549
__init__(self, config, name, schema, metadata, logName=None)
Definition wrappers.py:545
fail(self, measRecord, error=None)
Definition wrappers.py:595
measureN(self, measCat, exposure, refCat, refWcs)
Definition wrappers.py:571
fail(self, measRecord, error=None)
Definition wrappers.py:69
measureN(self, measCat, exposure, refCat, refWcs)
Definition wrappers.py:66
__init__(self, config, name, schemaMapper, metadata, logName=None)
Definition wrappers.py:56
measure(self, measRecord, exposure, refRecord, refWcs)
Definition wrappers.py:63
__init__(self, config, name, schema, metadata, logName=None)
Definition wrappers.py:37
wrapSingleFrameAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False, hasLogName=False, deprecated=None, **kwds)
Definition wrappers.py:221
wrapTransform(transformClass, hasLogName=False)
Definition wrappers.py:473
wrapAlgorithm(Base, AlgClass, factory, executionOrder, name=None, Control=None, ConfigClass=None, TransformClass=None, doRegister=True, shouldApCorr=False, apCorrList=(), hasLogName=False, **kwds)
Definition wrappers.py:126
wrapSimpleAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False, hasLogName=False, deprecated=None, **kwds)
Definition wrappers.py:405
wrapForcedAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False, needsSchemaOnly=False, hasLogName=False, deprecated=None, **kwds)
Definition wrappers.py:304
wrapAlgorithmControl(Base, Control, module=None, hasMeasureN=False)
Definition wrappers.py:73