Python overview

There are several python environments from which you can use SMTK

  • Interactively inside ParaView’s (or ModelBuilder’s) Python Shell. In this case, many plugins have already been loaded and you can obtain pre-existing managers from smtk.extension.paraview.appcomponents.pqSMTKBehavior.instance(). Also, python commands you run may have an effect on the user interface of the application. You are responsible for importing whatever SMTK modules you need.

  • Interactively from a python command prompt or by running a python script. In this case, plugins are not loaded unless you manually load them (discussed below). You are responsible for importing whatever SMTK modules you need. User interface components are not available.

  • From an SMTK operation written in python. In this case, you can assume the environment is prepared, either by the script or the user interface. However, operations should generally not attempt to perform user interaction or assume a user interface is present. You are responsible for importing whatever SMTK modules you need.

Regardless of the environment, SMTK provides python support via two mechanisms:

  • python modules (smtk, smtk.resource, smtk.operation, …) that you can import and

  • shared-library plugins (built when ParaView support is enabled) that you can load.

Python modules provide access to C++ classes. The modules are arranged to mirror the directory structure of SMTK’s source code (e.g., the smtk.resource module contains bindings for C++ classes in the smtk/resource directory). C++ classes are wrapped as needed and more effort has been put into wrapping classes that expose basic functionality than into subclasses that extend functionality. This is because most of SMTK’s functionality can be exercised via the methods on base classes such as smtk::resource::Component; frequently subclasses do not need wrapping.

Second, shared-library plugins can be loaded from python. These plugins are typically used to register resource types, operations, and view classes to managers. While it is possible to wrap the Registrar classes each subsystem of SMTK provides, this is not always done. In these cases, you should load the plugin and call the smtk.plugin.registerTo() method to populate your Manager instances with classes contained in the loaded plugins.

Consider the following python script:

1# We need to import SMTK's python modules that expose
2# python bindings to C++ objects:
3
4# After importing, we can create manager instances.
5rsrcMgr = smtk.resource.Manager.create()
6opMgr = smtk.operation.Manager.create()
7# The instances are initially empty:
8print('ops:', len(opMgr.availableOperations()))

While it imports the operation and resource modules and creates managers, these managers are not initialized with any resource types or operations because no registrars have been added to the plugin registry. We can load plugins like so:

 1# Use ParaView's plugin infrastructure to initialize C++ functionality
 2# that may not be python wrapped but that can be used from Python via
 3# the wrapped API (such as resource types and operations).
 4smtkLibDir = os.path.join(appDir, 'lib', 'smtk-' +
 5                          smtk.common.Version.number())
 6
 7# Load the plugins containing Registrars
 8LoadPlugin(os.path.join(smtkLibDir, 'smtkAttributePlugin/smtkAttributePlugin.so'))
 9LoadPlugin(os.path.join(smtkLibDir, 'smtkOperationPlugin/smtkOperationPlugin.so'))
10# Have the plugins populate the operation manager with their operations.
11smtk.plugin.registerPluginsTo(opMgr)
12smtk.plugin.registerPluginsTo(rsrcMgr)
13# Now we should see some operations. For my configuration, this prints "ops: 62".
14print('ops:', len(opMgr.availableOperations()))

With the plugins loaded, the registrars have been added and the managers can be registered to all the loaded plugins. Finally, we can then ask the resource manager to load a resource for us:

1# Read an attribute resource using the resource manager:
2fta = rsrcMgr.read('smtk::attribute::Resource',
3                   '/path/to/fileTestAttribute.smtk')
4allAttributes = fta.filter('*') if fta else []
5print('Read %d attributes from file.' % len(allAttributes))

As an alternative, we can create an operation and run it to load or import a file. The example below imports an SimBuilder Template (SBT) file.

 1# It is also possible to use operations, either directly
 2# or via an operation group such as the Reader group.
 3importOp = opMgr.createOperation('smtk::attribute::Import')
 4importOp.parameters().findFile('filename').setValue(
 5    '/path/to/fileTestAttribute.sbt')
 6result = importOp.operate()
 7outcome = smtk.operation.Operation.Outcome(res.findInt('outcome').value(0))
 8if outcome == smtk.operation.Operation.SUCCEEDED:
 9    print('Imported file')
10else:
11    print('Operation failed with status %s' % outcome)
12    print('Operation log:\n%s' % importOp.log().convertToString())