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