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