LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
LSSTDataManagementBasePackage
wrappers.py
Go to the documentation of this file.
2 
3 from .base import generateAlgorithmName
4 from .sfm import SingleFramePlugin, SingleFramePluginConfig
5 from .forcedMeasurement import ForcedPlugin, ForcedPluginConfig
6 
7 __all__ = ("wrapSingleFrameAlgorithm", "wrapForcedAlgorithm", "wrapSimpleAlgorithm")
8 
9 
10 class WrappedSingleFramePlugin(SingleFramePlugin):
11 
12  def __init__(self, config, name, schema, metadata):
13  SingleFramePlugin.__init__(self, config, name, schema, metadata)
14  self.cpp = self.factory(config, name, schema, metadata)
15 
16  def measure(self, measRecord, exposure):
17  self.cpp.measure(measRecord, exposure)
18 
19  def measureN(self, measCat, exposure):
20  self.cpp.measureN(measRecord, exposure)
21 
22  def fail(self, measRecord, error=None):
23  self.cpp.fail(measRecord, error.cpp if error is not None else None)
24 
25 
26 class WrappedForcedPlugin(ForcedPlugin):
27 
28  def __init__(self, config, name, schemaMapper, metadata):
29  ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
30  self.cpp = self.factory(config, name, schemaMapper, metadata)
31 
32  def measure(self, measRecord, exposure, refRecord, refWcs):
33  self.cpp.measure(measRecord, exposure, refRecord, refWcs)
34 
35  def measureN(self, measCat, exposure, refCat, refWcs):
36  self.cpp.measureN(measRecord, exposure, refCat, refWcs)
37 
38  def fail(self, measRecord, error=None):
39  self.cpp.fail(measRecord, error.cpp if error is not None else None)
40 
41 
42 def wrapAlgorithmControl(Base, Control, hasMeasureN=False, executionOrder=None):
43  """!
44  Wrap a C++ algorithm's control class into a Python Config class.
45 
46  @param[in] Base Base class for the returned ConfigClass; one of SingleFramePluginConfig or
47  ForcedPluginConfig
48  @param[in] Control Control class to be wrapped (a Swigged C++ class)
49  @param[in] hasMeasureN Whether the plugin supports fitting multiple objects at once (if so, a
50  config option to enable/disable this will be added).
51  @param[in] executionOrder If not None, an override for the default executionOrder for this plugin.
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  if executionOrder is not None:
75  ConfigClass.executionOrder.default = float(executionOrder)
76  return ConfigClass
77 
78 
79 def wrapAlgorithm(Base, AlgClass, factory, name=None, Control=None, ConfigClass=None, doRegister=True,
80  **kwds):
81  """!
82  Wrap a C++ Algorithm class into a Python Plugin class.
83 
84  @param[in] Base Base class for the returned Plugin; one of SingleFramePlugin or
85  ForcedPlugin
86  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
87  SingleFrameAlgorithm or ForcedAlgorithm (matching the Base argument), or
88  an unrelated class with the same measure() and measureN() signatures as
89  those base classes.
90  @param[in] factory A callable that is used to construct an instance of AlgClass. It must take
91  four arguments, either (config, name, schema, metadata) or
92  (config, name, schemaMapper, metadata), depending on whether the algorithm is
93  single-frame or forced.
94  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
95  set to generateAlgorithmName(AlgClass) if None.
96  @param[in] Control Swigged C++ Control class for the algorithm; AlgClass.Control is used if None.
97  Ignored if ConfigClass is not None.
98  @param[in] ConfigClass Python Config class that wraps the C++ Algorithm's swigged Control class. If
99  None, wrapAlgorithmControl is called to generate a Config class using the
100  Control argument.
101  @param[in] doRegister If True (the default), register the plugin with Base's registry, allowing it
102  to be used by measurement Tasks.
103  @param[in] **kwds Additional keyword arguments passed to generateAlgorithmControl, including:
104  - hasMeasureN: Whether the plugin supports fitting multiple objects at once
105  (if so, a config option to enable/disable this will be added).
106  - executionOrder: If not None, an override for the default executionOrder for
107  this plugin (the default is 2.0, which is usually appropriate for fluxes).
108 
109  @return the new Plugin class, a subclass of Base
110 
111  This function is generally only called by the public wrapSingleFrameAlgorithm, wrapForcedAlgorithm, and
112  wrapSimpleAlgorithm functions; it is unlikely users will have to call it directly.
113  """
114  if ConfigClass is None:
115  if Control is None:
116  Control = AlgClass.Control
117  ConfigClass = wrapAlgorithmControl(Base.ConfigClass, Control, **kwds)
118  PluginClass = type(AlgClass.__name__ + Base.__name__, (Base,),
119  dict(AlgClass=AlgClass, ConfigClass=ConfigClass, factory=staticmethod(factory)))
120  if doRegister:
121  if name is None:
122  name = generateAlgorithmName(AlgClass)
123  Base.registry.register(name, PluginClass)
124  return PluginClass
125 
126 
127 def wrapSingleFrameAlgorithm(AlgClass, name=None, needsMetadata=False, hasMeasureN=False, **kwds):
128  """!
129  Wrap a C++ SingleFrameAlgorithm class into a Python SingleFramePlugin class.
130 
131  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
132  SingleFrameAlgorithm, or an unrelated class with the same measure(),
133  measureN(), and fail() signatures.
134  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
135  set to generateAlgorithmName(AlgClass) if None.
136  @param[in] needsMetadata Sets whether the AlgClass's constructor should be passed a PropertySet
137  metadata argument.
138  @param[in] hasMeasureN Whether the algorithm supports simultaneous measurement of multiple sources.
139  If True, a bool doMeasureN field will be added to the generated Config class,
140  and its value will be passed as the last argument when calling the AlgClass
141  constructor.
142  @param[in] **kwds Additional keyword arguments passed to the lower-level wrapAlgorithm and
143  wrapAlgorithmControl classes. These include:
144  - Control: Swigged C++ Control class for the algorithm; AlgClass.Control
145  is used if None. Ignored if ConfigClass is not None.
146  - ConfigClass: Python Config class that wraps the C++ Algorithm's swigged
147  Control class. If None, wrapAlgorithmControl is called to generate a
148  Config class using the Control argument.
149  - doRegister: If True (the default), register the plugin with
150  SingleFramePlugin.registry, allowing it to be used by
151  SingleFrameMeasurementTask.
152  - executionOrder: If not None, an override for the default executionOrder for
153  this plugin (the default is 2.0, which is usually appropriate for fluxes).
154 
155  @return the new SingleFramePlugin subclass
156 
157  The needsMetadata and hasMeasureN arguments combine to determine the expected constructor signature;
158  we always expect the first three arguments to be:
159  @verbatim
160  Control const & ctrl, std::string const & name, Schema & schema
161  @endverbatim
162  If needsMetadata, we also append:
163  @verbatim
164  PropertySet & metadata
165  @endverbatim
166  If hasMeasureN, we also append:
167  @verbatim
168  bool doMeasureN
169  @endverbatim
170  If both are True, the metadata PropertySet precedes the doMeasureN bool.
171  """
172  if hasMeasureN:
173  if needsMetadata:
174  def factory(config, name, schema, metadata):
175  return AlgClass(config.makeControl(), name, schema, metadata, config.doMeasureN)
176  else:
177  def factory(config, name, schema, metadata):
178  return AlgClass(config.makeControl(), name, schema, config.doMeasureN)
179  else:
180  if needsMetadata:
181  def factory(config, name, schema, metadata):
182  return AlgClass(config.makeControl(), name, schema, metadata)
183  else:
184  def factory(config, name, schema, metadata):
185  return AlgClass(config.makeControl(), name, schema)
186  return wrapAlgorithm(WrappedSingleFramePlugin, AlgClass, factory=factory,
187  hasMeasureN=hasMeasureN, **kwds)
188 
189 
190 def wrapForcedAlgorithm(AlgClass, name=None, needsMetadata=False, hasMeasureN=False, needsSchemaOnly=False,
191  **kwds):
192  """!
193  Wrap a C++ ForcedAlgorithm class into a Python ForcedPlugin class.
194 
195  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
196  ForcedAlgorithm, or an unrelated class with the same measure(), measureN(),
197  and fail() signatures.
198  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
199  set to generateAlgorithmName(AlgClass) if None.
200  @param[in] needsMetadata Sets whether the AlgClass's constructor should be passed a PropertySet
201  metadata argument.
202  @param[in] hasMeasureN Whether the algorithm supports simultaneous measurement of multiple sources.
203  If True, a bool doMeasureN field will be added to the generated Config class,
204  and its value will be passed as the last argument when calling the AlgClass
205  constructor.
206  @param[in] needsSchemaOnly Whether the algorithm constructor expects a Schema argument (representing the
207  output Schema) rather than the full SchemaMapper (which provides access to
208  both the reference Schema and the output Schema).
209  @param[in] **kwds Additional keyword arguments passed to the lower-level wrapAlgorithm and
210  wrapAlgorithmControl classes. These include:
211  - Control: Swigged C++ Control class for the algorithm; AlgClass.Control
212  is used if None. Ignored if ConfigClass is not None.
213  - ConfigClass: Python Config class that wraps the C++ Algorithm's swigged
214  Control class. If None, wrapAlgorithmControl is called to generate a
215  Config class using the Control argument.
216  - doRegister: If True (the default), register the plugin with
217  ForcedPlugin.registry, allowing it to be used by ForcedMeasurementTask.
218  - executionOrder: If not None, an override for the default executionOrder for
219  this plugin (the default is 2.0, which is usually appropriate for fluxes).
220 
221  @return the new ForcedPlugin subclass
222 
223  The needsMetadata, hasMeasureN, and needsSchemaOnly arguments combine to determine the expected
224  constructor signature; we always expect the first two arguments to be:
225  @verbatim
226  Control const & ctrl, std::string const & name
227  @endverbatim
228  If needsSchemaOnly is True, then the third argument will be
229  @verbatim
230  Schema & schema
231  @endverbatim
232  otherwise, it will be:
233  @verbatim
234  SchemaMapper & schemaMapper
235  @endverbatim
236  If needsMetadata, we also append:
237  @verbatim
238  PropertySet & metadata
239  @endverbatim
240  If hasMeasureN, we also append:
241  @verbatim
242  bool doMeasureN
243  @endverbatim
244  If both are True, the metadata PropertySet precedes the doMeasureN bool.
245  """
246  if needsSchemaOnly:
247  extractSchemaArg = lambda m: m.editOutputSchema()
248  else:
249  extractSchemaArg = lambda m: m
250  if hasMeasureN:
251  if needsMetadata:
252  def factory(config, name, schemaMapper, metadata):
253  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
254  metadata, config.doMeasureN)
255  else:
256  def factory(config, name, schemaMapper, metadata):
257  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
258  config.doMeasureN)
259  else:
260  if needsMetadata:
261  def factory(config, name, schemaMapper, metadata):
262  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper),
263  metadata)
264  else:
265  def factory(config, name, schemaMapper, metadata):
266  return AlgClass(config.makeControl(), name, extractSchemaArg(schemaMapper))
267  return wrapAlgorithm(WrappedForcedPlugin, AlgClass, factory=factory, **kwds)
268 
269 
270 def wrapSimpleAlgorithm(AlgClass, name=None, needsMetadata=False, hasMeasureN=False, **kwds):
271  """!
272  Wrap a C++ SimpleAlgorithm class into both a Python SingleFramePlugin and ForcedPlugin classes
273 
274  @param[in] AlgClass Swigged C++ Algorithm class to convert; must be a subclass of
275  simpleAlgorithm, or an unrelated class with the same measure(), measureN(),
276  and fail() signatures.
277  @param[in] name String to use when registering the algorithm. Ignored if doRegistry=False,
278  set to generateAlgorithmName(AlgClass) if None.
279  @param[in] needsMetadata Sets whether the AlgClass's constructor should be passed a PropertySet
280  metadata argument.
281  @param[in] hasMeasureN Whether the algorithm supports simultaneous measurement of multiple sources.
282  If True, a bool doMeasureN field will be added to the generated Config class,
283  and its value will be passed as the last argument when calling the AlgClass
284  constructor.
285  @param[in] **kwds Additional keyword arguments passed to the lower-level wrapAlgorithm and
286  wrapAlgorithmControl classes. These include:
287  - Control: Swigged C++ Control class for the algorithm; AlgClass.Control
288  is used if None. Ignored if ConfigClass is not None.
289  - ConfigClass: Python Config class that wraps the C++ Algorithm's swigged
290  Control class. If None, wrapAlgorithmControl is called to generate a
291  Config class using the Control argument.
292  - doRegister: If True (the default), register the plugins with Base's
293  registry, allowing it to be used by measurement Tasks.
294  - executionOrder: If not None, an override for the default executionOrder for
295  this plugin (the default is 2.0, which is usually appropriate for fluxes).
296 
297  @return a two-element tuple, containing the new SingleFramePlugin and ForcedPlugin subclasses
298 
299  The needsMetadata and hasMeasureN arguments combine to determine the expected constructor signature;
300  we always expect the first three arguments to be:
301  @verbatim
302  Control const & ctrl, std::string const & name, Schema & schema
303  @endverbatim
304  If needsMetadata, we also append:
305  @verbatim
306  PropertySet & metadata
307  @endverbatim
308  If hasMeasureN, we also append:
309  @verbatim
310  bool doMeasureN
311  @endverbatim
312  If both are True, the metadata PropertySet precedes the doMeasureN bool.
313  """
314  return (wrapSingleFrameAlgorithm(AlgClass, name=name, needsMetadata=needsMetadata, **kwds),
315  wrapForcedAlgorithm(AlgClass, name=name, needsMetadata=needsMetadata,
316  needsSchemaOnly=True, **kwds))
def wrapSingleFrameAlgorithm
Wrap a C++ SingleFrameAlgorithm class into a Python SingleFramePlugin class.
Definition: wrappers.py:127
def generateAlgorithmName
Definition: base.py:40
def wrapAlgorithm
Wrap a C++ Algorithm class into a Python Plugin class.
Definition: wrappers.py:80
def wrapAlgorithmControl
Wrap a C++ algorithm's control class into a Python Config class.
Definition: wrappers.py:42
def wrapForcedAlgorithm
Wrap a C++ ForcedAlgorithm class into a Python ForcedPlugin class.
Definition: wrappers.py:191
def wrapSimpleAlgorithm
Wrap a C++ SimpleAlgorithm class into both a Python SingleFramePlugin and ForcedPlugin classes...
Definition: wrappers.py:270