LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
wrappers.py
Go to the documentation of this file.
2 
3 from .pluginRegistry import generateAlgorithmName
4 from .apCorrRegistry import addApCorrName
5 from .sfm import SingleFramePlugin
6 from .forcedMeasurement import ForcedPlugin
7 
8 __all__ = ("wrapSingleFrameAlgorithm", "wrapForcedAlgorithm", "wrapSimpleAlgorithm")
9 
10 
11 class WrappedSingleFramePlugin(SingleFramePlugin):
12 
13  def __init__(self, config, name, schema, metadata):
14  SingleFramePlugin.__init__(self, config, name, schema, metadata)
15  self.cpp = self.factory(config, name, schema, metadata)
16 
17  def measure(self, measRecord, exposure):
18  self.cpp.measure(measRecord, exposure)
19 
20  def measureN(self, measCat, exposure):
21  self.cpp.measureN(measCat, exposure)
22 
23  def fail(self, measRecord, error=None):
24  self.cpp.fail(measRecord, error.cpp if error is not None else None)
25 
26 
27 class WrappedForcedPlugin(ForcedPlugin):
28 
29  def __init__(self, config, name, schemaMapper, metadata):
30  ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
31  self.cpp = self.factory(config, name, schemaMapper, metadata)
32 
33  def measure(self, measRecord, exposure, refRecord, refWcs):
34  self.cpp.measureForced(measRecord, exposure, refRecord, refWcs)
35 
36  def measureN(self, measCat, exposure, refCat, refWcs):
37  self.cpp.measureNForced(measCat, exposure, refCat, refWcs)
38 
39  def fail(self, measRecord, error=None):
40  self.cpp.fail(measRecord, error.cpp if error is not None else None)
41 
42 
43 def wrapAlgorithmControl(Base, Control, hasMeasureN=False):
44  """!
45  Wrap a C++ algorithm's control class into a Python Config class.
46 
47  @param[in] Base Base class for the returned ConfigClass; one of SingleFramePluginConfig or
48  ForcedPluginConfig
49  @param[in] Control Control class to be wrapped (a Swigged C++ class)
50  @param[in] hasMeasureN Whether the plugin supports fitting multiple objects at once (if so, a
51  config option to enable/disable this will be added).
52 
53  @return a new subclass of lsst.pex.config.Config
54 
55  This function is generally only called by wrapAlgorithm; it is unlikely users will have to call it
56  directly.
57  """
58  if hasMeasureN:
59  # We need to add a Config field to enable multi-object measurement, to replace
60  # the simple bool class attribute that's on the base class. To do that, we
61  # create the Config class dynamically here, then call makeControlClass to finish
62  # it off by adding fields from the control object.
63  cls = type(
64  Control.__name__.replace("Control", "Config"),
65  (Base,),
66  {"doMeasureN": lsst.pex.config.Field(dtype=bool, default=True,
67  doc="whether to run this plugin in multi-object mode")}
68  )
69  ConfigClass = lsst.pex.config.makeConfigClass(Control, module=Control.__module__, cls=cls)
70  else:
71  # If we don't have to add that Config field, we can delegate all of the work to
72  # pex_config's makeControlClass
73  ConfigClass = lsst.pex.config.makeConfigClass(Control, module=Control.__module__, base=Base)
74  return ConfigClass
75 
76 
77 def wrapAlgorithm(Base, AlgClass, factory, executionOrder, name=None, Control=None,
78  ConfigClass=None, TransformClass=None, doRegister=True, shouldApCorr=False,
79  apCorrList=(), **kwds):
80  """!
81  Wrap a C++ Algorithm class into a Python Plugin class.
82 
83  @param[in] Base Base class for the returned Plugin; one of SingleFramePlugin or
84  ForcedPlugin
85  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
86  SingleFrameAlgorithm or ForcedAlgorithm (matching the Base argument), or
87  an unrelated class with the same measure() and measureN() signatures as
88  those base classes.
89  @param[in] factory A callable that is used to construct an instance of AlgClass. It must take
90  four arguments, either (config, name, schema, metadata) or
91  (config, name, schemaMapper, metadata), depending on whether the algorithm is
92  single-frame or forced.
93  @param[in] executionOrder The order this plugin should be run, relative to others
94  (see BasePlugin.getExecutionOrder()).
95  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
96  set to generateAlgorithmName(AlgClass) if None.
97  @param[in] Control Swigged C++ Control class for the algorithm; AlgClass.Control is used if None.
98  Ignored if ConfigClass is not None.
99  @param[in] ConfigClass Python Config class that wraps the C++ Algorithm's swigged Control class. If
100  None, wrapAlgorithmControl is called to generate a Config class using the
101  Control argument.
102  @param[in] TransformClass Transformation which may be used to post-process the results of measurement.
103  If None, the default (defined by BasePlugin) is used.
104  @param[in] doRegister If True (the default), register the plugin with Base's registry, allowing it
105  to be used by measurement Tasks.
106  @param[in] shouldApCorr Does this algorithm measure a flux that can be aperture corrected? This is
107  shorthand for apCorrList=[name] and is ignored if apCorrList is specified.
108  @param[in] apCorrList List of field name prefixes for flux fields that should be aperture corrected.
109  If an algorithm produces a single flux that should be
110  aperture corrected then it is simpler to set shouldApCorr=True. But if an
111  algorithm produces multiple such fields then it must specify apCorrList,
112  instead. For example modelfit_CModel produces 3 such fields: apCorrList=
113  ("modelfit_CModel_exp", "modelfit_CModel_exp", "modelfit_CModel_def")
114  If apCorrList is non-empty then shouldApCorr is ignored.
115  If non-empty and doRegister is True then the names are added to the set
116  retrieved by getApCorrNameSet
117 
118 
119  @param[in] **kwds Additional keyword arguments passed to generateAlgorithmControl, including:
120  - hasMeasureN: Whether the plugin supports fitting multiple objects at once
121  (if so, a config option to enable/disable this will be added).
122  - executionOrder: If not None, an override for the default executionOrder for
123  this plugin (the default is 2.0, which is usually appropriate for fluxes).
124 
125  @return the new Plugin class, a subclass of Base
126 
127  This function is generally only called by the public wrapSingleFrameAlgorithm, wrapForcedAlgorithm, and
128  wrapSimpleAlgorithm functions; it is unlikely users will have to call it directly.
129  """
130  if ConfigClass is None:
131  if Control is None:
132  Control = AlgClass.Control
133  ConfigClass = wrapAlgorithmControl(Base.ConfigClass, Control, **kwds)
134  def getExecutionOrder():
135  return executionOrder
136  typeDict = dict(AlgClass=AlgClass, ConfigClass=ConfigClass, factory=staticmethod(factory),
137  getExecutionOrder=staticmethod(getExecutionOrder))
138  if TransformClass:
139  typeDict['getTransformClass'] = staticmethod(lambda: TransformClass)
140  PluginClass = type(AlgClass.__name__ + Base.__name__, (Base,), typeDict)
141  if doRegister:
142  if name is None:
143  name = generateAlgorithmName(AlgClass)
144  Base.registry.register(name, PluginClass)
145  if shouldApCorr:
146  addApCorrName(name)
147  return PluginClass
148 
149 
150 def wrapSingleFrameAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False,
151  **kwds):
152  """!
153  Wrap a C++ SingleFrameAlgorithm class into a Python SingleFramePlugin class.
154 
155  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
156  SingleFrameAlgorithm, or an unrelated class with the same measure(),
157  measureN(), and fail() signatures.
158  @param[in] executionOrder The order this plugin should be run, relative to others
159  (see BasePlugin.getExecutionOrder()).
160  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
161  set to generateAlgorithmName(AlgClass) if None.
162  @param[in] needsMetadata Sets whether the AlgClass's constructor should be passed a PropertySet
163  metadata argument.
164  @param[in] hasMeasureN Whether the algorithm supports simultaneous measurement of multiple sources.
165  If True, a bool doMeasureN field will be added to the generated Config class,
166  and its value will be passed as the last argument when calling the AlgClass
167  constructor.
168  @param[in] **kwds Additional keyword arguments passed to the lower-level wrapAlgorithm and
169  wrapAlgorithmControl classes. These include:
170  - Control: Swigged C++ Control class for the algorithm; AlgClass.Control
171  is used if None. Ignored if ConfigClass is not None.
172  - ConfigClass: Python Config class that wraps the C++ Algorithm's swigged
173  Control class. If None, wrapAlgorithmControl is called to generate a
174  Config class using the Control argument.
175  - doRegister: If True (the default), register the plugin with
176  SingleFramePlugin.registry, allowing it to be used by
177  SingleFrameMeasurementTask.
178  - shouldApCorr: does this algorithm measure a flux that can be aperture
179  corrected? This is shorthand for apCorrList=[name] and is ignored if
180  apCorrList is specified.
181  - apCorrList: list of field name prefixes for flux fields that should be
182  aperture corrected. If an algorithm produces a single flux that should be
183  aperture corrected then it is simpler to set shouldApCorr=True. But if an
184  algorithm produces multiple such fields then it must specify apCorrList,
185  instead. For example modelfit_CModel produces 3 such fields: apCorrList=
186  ("modelfit_CModel_exp", "modelfit_CModel_exp", "modelfit_CModel_def")
187  If apCorrList is non-empty then shouldApCorr is ignored.
188  If non-empty and doRegister is True then the names are added to the set
189  retrieved by getApCorrNameSet
190  - executionOrder: If not None, an override for the default executionOrder for
191  this plugin (the default is 2.0, which is usually appropriate for fluxes).
192 
193  @return the new SingleFramePlugin subclass
194 
195  The needsMetadata and hasMeasureN arguments combine to determine the expected constructor signature;
196  we always expect the first three arguments to be:
197  @verbatim
198  Control const & ctrl, std::string const & name, Schema & schema
199  @endverbatim
200  If needsMetadata, we also append:
201  @verbatim
202  PropertySet & metadata
203  @endverbatim
204  If hasMeasureN, we also append:
205  @verbatim
206  bool doMeasureN
207  @endverbatim
208  If both are True, the metadata PropertySet precedes the doMeasureN bool.
209  """
210  if hasMeasureN:
211  if needsMetadata:
212  def factory(config, name, schema, metadata):
213  return AlgClass(config.makeControl(), name, schema, metadata, config.doMeasureN)
214  else:
215  def factory(config, name, schema, metadata):
216  return AlgClass(config.makeControl(), name, schema, config.doMeasureN)
217  else:
218  if needsMetadata:
219  def factory(config, name, schema, metadata):
220  return AlgClass(config.makeControl(), name, schema, metadata)
221  else:
222  def factory(config, name, schema, metadata):
223  return AlgClass(config.makeControl(), name, schema)
224  return wrapAlgorithm(WrappedSingleFramePlugin, AlgClass, executionOrder=executionOrder, name=name,
225  factory=factory, hasMeasureN=hasMeasureN, **kwds)
226 
227 
228 def wrapForcedAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False,
229  hasMeasureN=False, needsSchemaOnly=False, **kwds):
230  """!
231  Wrap a C++ ForcedAlgorithm class into a Python ForcedPlugin class.
232 
233  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
234  ForcedAlgorithm, or an unrelated class with the same measure(), measureN(),
235  and fail() signatures.
236  @param[in] executionOrder The order this plugin should be run, relative to others
237  (see BasePlugin.getExecutionOrder()).
238  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
239  set to generateAlgorithmName(AlgClass) if None.
240  @param[in] needsMetadata Sets whether the AlgClass's constructor should be passed a PropertySet
241  metadata argument.
242  @param[in] hasMeasureN Whether the algorithm supports simultaneous measurement of multiple sources.
243  If True, a bool doMeasureN field will be added to the generated Config class,
244  and its value will be passed as the last argument when calling the AlgClass
245  constructor.
246  @param[in] needsSchemaOnly Whether the algorithm constructor expects a Schema argument (representing the
247  output Schema) rather than the full SchemaMapper (which provides access to
248  both the reference Schema and the output Schema).
249  @param[in] **kwds Additional keyword arguments passed to the lower-level wrapAlgorithm and
250  wrapAlgorithmControl classes. These include:
251  - Control: Swigged C++ Control class for the algorithm; AlgClass.Control
252  is used if None. Ignored if ConfigClass is not None.
253  - ConfigClass: Python Config class that wraps the C++ Algorithm's swigged
254  Control class. If None, wrapAlgorithmControl is called to generate a
255  Config class using the Control argument.
256  - doRegister: If True (the default), register the plugin with
257  ForcedPlugin.registry, allowing it to be used by ForcedMeasurementTask.
258  - shouldApCorr: does this algorithm measure a flux that can be aperture
259  corrected? This is shorthand for apCorrList=[name] and is ignored if
260  apCorrList is specified.
261  - apCorrList: list of field name prefixes for flux fields that should be
262  aperture corrected. If an algorithm produces a single flux that should be
263  aperture corrected then it is simpler to set shouldApCorr=True. But if an
264  algorithm produces multiple such fields then it must specify apCorrList,
265  instead. For example modelfit_CModel produces 3 such fields: apCorrList=
266  ("modelfit_CModel_exp", "modelfit_CModel_exp", "modelfit_CModel_def")
267  If apCorrList is non-empty then shouldApCorr is ignored.
268  If non-empty and doRegister is True then the names are added to the set
269  retrieved by getApCorrNameSet
270  - executionOrder: If not None, an override for the default executionOrder for
271  this plugin (the default is 2.0, which is usually appropriate for fluxes).
272 
273  @return the new ForcedPlugin subclass
274 
275  The needsMetadata, hasMeasureN, and needsSchemaOnly arguments combine to determine the expected
276  constructor signature; we always expect the first two arguments to be:
277  @verbatim
278  Control const & ctrl, std::string const & name
279  @endverbatim
280  If needsSchemaOnly is True, then the third argument will be
281  @verbatim
282  Schema & schema
283  @endverbatim
284  otherwise, it will be:
285  @verbatim
286  SchemaMapper & schemaMapper
287  @endverbatim
288  If needsMetadata, we also append:
289  @verbatim
290  PropertySet & metadata
291  @endverbatim
292  If hasMeasureN, we also append:
293  @verbatim
294  bool doMeasureN
295  @endverbatim
296  If both are True, the metadata PropertySet precedes the doMeasureN bool.
297  """
298  if needsSchemaOnly:
299  extractSchemaArg = lambda m: m.editOutputSchema()
300  else:
301  extractSchemaArg = lambda m: m
302  if hasMeasureN:
303  if needsMetadata:
304  def factory(config, name, schemaMapper, metadata):
305  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
306  metadata, config.doMeasureN)
307  else:
308  def factory(config, name, schemaMapper, metadata):
309  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
310  config.doMeasureN)
311  else:
312  if needsMetadata:
313  def factory(config, name, schemaMapper, metadata):
314  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
315  metadata)
316  else:
317  def factory(config, name, schemaMapper, metadata):
318  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper))
319  return wrapAlgorithm(WrappedForcedPlugin, AlgClass, executionOrder=executionOrder, name=name,
320  factory=factory, **kwds)
321 
322 
323 def wrapSimpleAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False, **kwds):
324  """!
325  Wrap a C++ SimpleAlgorithm class into both a Python SingleFramePlugin and ForcedPlugin classes
326 
327  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
328  simpleAlgorithm, or an unrelated class with the same measure(), measureN(),
329  and fail() signatures.
330  @param[in] executionOrder The order this plugin should be run, relative to others
331  (see BasePlugin.getExecutionOrder()).
332  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
333  set to generateAlgorithmName(AlgClass) if None.
334  @param[in] needsMetadata Sets whether the AlgClass's constructor should be passed a PropertySet
335  metadata argument.
336  @param[in] hasMeasureN Whether the algorithm supports simultaneous measurement of multiple sources.
337  If True, a bool doMeasureN field will be added to the generated Config class,
338  and its value will be passed as the last argument when calling the AlgClass
339  constructor.
340  @param[in] **kwds Additional keyword arguments passed to the lower-level wrapAlgorithm and
341  wrapAlgorithmControl classes. These include:
342  - Control: Swigged C++ Control class for the algorithm; AlgClass.Control
343  is used if None. Ignored if ConfigClass is not None.
344  - ConfigClass: Python Config class that wraps the C++ Algorithm's swigged
345  Control class. If None, wrapAlgorithmControl is called to generate a
346  Config class using the Control argument.
347  - doRegister: If True (the default), register the plugins with Base's
348  registry, allowing it to be used by measurement Tasks.
349  - shouldApCorr: does this algorithm measure a flux that can be aperture
350  corrected? This is shorthand for apCorrList=[name] and is ignored if
351  apCorrList is specified.
352  - apCorrList: list of field name prefixes for flux fields that should be
353  aperture corrected. If an algorithm produces a single flux that should be
354  aperture corrected then it is simpler to set shouldApCorr=True. But if an
355  algorithm produces multiple such fields then it must specify apCorrList,
356  instead. For example modelfit_CModel produces 3 such fields: apCorrList=
357  ("modelfit_CModel_exp", "modelfit_CModel_exp", "modelfit_CModel_def")
358  If apCorrList is non-empty then shouldApCorr is ignored.
359  If non-empty and doRegister is True then the names are added to the set
360  retrieved by getApCorrNameSet
361  - executionOrder: If not None, an override for the default executionOrder for
362  this plugin (the default is 2.0, which is usually appropriate for fluxes).
363 
364  @return a two-element tuple, containing the new SingleFramePlugin and ForcedPlugin subclasses
365 
366  The needsMetadata and hasMeasureN arguments combine to determine the expected constructor signature;
367  we always expect the first three arguments to be:
368  @verbatim
369  Control const & ctrl, std::string const & name, Schema & schema
370  @endverbatim
371  If needsMetadata, we also append:
372  @verbatim
373  PropertySet & metadata
374  @endverbatim
375  If hasMeasureN, we also append:
376  @verbatim
377  bool doMeasureN
378  @endverbatim
379  If both are True, the metadata PropertySet precedes the doMeasureN bool.
380  """
381  return (wrapSingleFrameAlgorithm(AlgClass, executionOrder=executionOrder, name=name,
382  needsMetadata=needsMetadata, **kwds),
383  wrapForcedAlgorithm(AlgClass, executionOrder=executionOrder, name=name,
384  needsMetadata=needsMetadata, needsSchemaOnly=True, **kwds))
def wrapSingleFrameAlgorithm
Wrap a C++ SingleFrameAlgorithm class into a Python SingleFramePlugin class.
Definition: wrappers.py:151
def wrapAlgorithm
Wrap a C++ Algorithm class into a Python Plugin class.
Definition: wrappers.py:79
def wrapAlgorithmControl
Wrap a C++ algorithm's control class into a Python Config class.
Definition: wrappers.py:43
def wrapForcedAlgorithm
Wrap a C++ ForcedAlgorithm class into a Python ForcedPlugin class.
Definition: wrappers.py:229
def wrapSimpleAlgorithm
Wrap a C++ SimpleAlgorithm class into both a Python SingleFramePlugin and ForcedPlugin classes...
Definition: wrappers.py:323
def addApCorrName
Add to the set of field name prefixes for fluxes that should be aperture corrected.