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