Bundle Example: Define Presets

This example describes how to create a ChimeraX bundle that defines presets that will appear in the ChimeraX Presets menu and be usable in the preset command.

The steps in implementing the bundle are:

  1. Create a bundle_info.xml containing information about the bundle,

  2. Create a Python package that interfaces with ChimeraX and implements the preset functionality, and

  3. Install and test the bundle in ChimeraX.

The final step builds a Python wheel that ChimeraX uses to install the bundle. So if the bundle passes testing, it is immediately available for sharing with other users.

Source Code Organization

The source code for this example may be downloaded as a zip-format file containing a folder named tut_preset. Alternatively, one can start with an empty folder and create source files based on the samples below. The source folder may be arbitrarily named, as it is only used during installation; however, avoiding whitespace characters in the folder name bypasses the need to type quote characters in some steps.

Sample Files

The files in the tut_preset folder are:

  • tut_preset - bundle folder
    • bundle_info.xml - bundle information read by ChimeraX

    • src - source code to Python package for bundle
      • __init__.py - package initializer and interface to ChimeraX

      • presets.py - source code to define/execute presets

The file contents are shown below.

bundle_info.xml

bundle_info.xml is an eXtensible Markup Language format file whose tags are listed in Bundle Information XML Tags. While there are many tags defined, only a few are needed for bundles written completely in Python. The bundle_info.xml in this example is similar to the one from the Bundle Example: Add a Tool example with changes highlighted. For explanations of the unhighlighted sections, please see Bundle Example: Hello World, Bundle Example: Add a Command and Bundle Example: Add a Tool.

 1<!--
 2ChimeraX bundle names must start with "ChimeraX-"
 3to avoid clashes with package names in pypi.python.org.
 4When uploaded to the ChimeraX toolshed, the bundle
 5will be displayed without the ChimeraX- prefix.
 6-->
 7
 8<BundleInfo name="ChimeraX-TutorialPresets"
 9	    version="0.1" package="chimerax.tut_preset"
10  	    minSessionVersion="1" maxSessionVersion="1">
11
12  <!-- Additional information about bundle source -->
13  <Author>UCSF RBVI</Author>
14  <Email>chimerax@cgl.ucsf.edu</Email>
15  <URL>https://www.rbvi.ucsf.edu/chimerax/</URL>
16
17  <!-- Synopsis is a one-line description
18       Description is a full multi-line description -->
19  <Synopsis>Example for adding presets</Synopsis>
20  <Description>Example code for implementing ChimeraX bundle.
21
22Implements new preset "thin sticks", possibly useful for depicting small molecules.
23  </Description>
24
25  <!-- Categories is a list where this bundle should appear -->
26  <Categories>
27    <Category name="Depiction"/>
28  </Categories>
29
30  <!-- Dependencies on other ChimeraX/Python packages -->
31  <Dependencies>
32    <Dependency name="ChimeraX-Core" version="~=1.3"/>
33    <Dependency name="ChimeraX-PresetMgr" version="~=1.1"/>
34  </Dependencies>
35
36  <Providers manager="presets">
37    <Provider category="small molecule" name="thin sticks" />
38    <Provider category="small molecule" name="ball and stick" />
39  </Providers>
40
41  <Classifiers>
42    <!-- Development Status should be compatible with bundle version number -->
43    <PythonClassifier>Development Status :: 3 - Alpha</PythonClassifier>
44    <PythonClassifier>License :: Freeware</PythonClassifier>
45  </Classifiers>
46
47</BundleInfo>

The BundleInfo, Synopsis, Description and Category tags are changed to reflect the new bundle name and documentation (lines 8-10, 19-23, and 26-28).

Since the presets use functionality from the PresetMgr bundle, the Dependencies section has been changed to reflect that (lines 31-34).

The Providers section on lines 36-39 informs ChimeraX that this bundle defines two presets, named “thin sticks” and “ball and stick”, and that their category is “small molcule” for organizing them in the Presets menu and for the category argument of the preset command. More details about the Providers section for presets can be found in Defining Presets.

There are also deletions relative to previous examples. For instance, there are no DataFiles or ChimeraXClassifier tags since this bundle does not provide a help page nor does it implement a tool.

src

src is the folder containing the source code for the Python package that implements the bundle functionality. The ChimeraX devel command, used for building and installing bundles, automatically includes all .py files in src as part of the bundle. (Additional files may also be included using bundle information tags such as DataFiles as shown in Bundle Example: Add a Tool.) The only required file in src is __init__.py. Other .py files are typically arranged to implement different types of functionality. For example, cmd.py is used for command-line commands; tool.py or gui.py for graphical interfaces; io.py for reading and saving files, etc.

src/__init__.py

As described in Bundle Example: Hello World, __init__.py contains the initialization code that defines the bundle_api object that ChimeraX needs in order to invoke bundle functionality. ChimeraX expects bundle_api class to be derived from chimerax.core.toolshed.BundleAPI with methods overridden for registering commands, tools, etc.

 1# vim: set expandtab shiftwidth=4 softtabstop=4:
 2
 3from chimerax.core.toolshed import BundleAPI
 4
 5
 6# Subclass from chimerax.core.toolshed.BundleAPI and
 7# override the method for defining presets
 8# inheriting all other methods from the base class.
 9class _MyAPI(BundleAPI):
10
11    # Override method for defining presets
12    @staticmethod
13    def run_provider(session, name, mgr, **kw):
14        # 'session' is the current chimerax.core.session.Session object
15        # 'name' is the name of the preset to execute
16        # 'mgr' is the preset manager (a.k.a. session.presets)
17        # 'kw', the keyword dictionary, is empty
18        #
19        # Note that this method is called by all managers that your
20        # bundle declares providers for, so if your bundle has providers
21        # for multiple different managers the the 'mgr' argument will
22        # not always be the session.presets instance, and some managers
23        # may provide non-empty keyword dictionaries to providers.
24
25        from .presets import run_preset
26        run_preset(session, name, mgr)
27
28
29# Create the ``bundle_api`` object that ChimeraX expects.
30bundle_api = _MyAPI()

The run_provider() method is called by the presets manager (session.presets) whenever one of the presets your bundle provides is requested, typically via the Presets menu or the preset command.

The arguments to run_provider() are session, the current chimerax.core.session.Session instance, name, the name of the preset to execute, mgr, a PresetsManager instance (a.k.a. session.presets), and kw, a keyword dictionary which is always empty in the case of presets. Since all managers that your bundle offers Providers for call this method, other calls to this method may have different mgr and kw argument values (and the run_provider code would have to be more complex). Since this example bundle only provides presets, it simply calls its run_preset function to execute the requested preset, which is discussed below.

src/presets.py

presets.py defines the function run_preset() that is invoked (from run_provider(), above) when either of our presets are requested.

 1# vim: set expandtab shiftwidth=4 softtabstop=4:
 2
 3def run_preset(session, name, mgr):
 4    """Run requested preset."""
 5
 6    # A preset needs to call mgr.execute(preset_info) to
 7    # execute the preset, so that information about the
 8    # preset's contents can be properly logged.  The
 9    # 'preset_info' argument can either be an executable
10    # Python function (that takes no arguments) or a
11    # string containing one or more ChimeraX commands.
12    # If there are multiple commands, the commands are typically
13    # separated with '; ', though in unusual cases (perhaps
14    # a very long series of commands) the commands could be
15    # newline separated -- in the latter case the newline-
16    # separated command string will be executed in individual
17    # calls to chimerax.core.commands.run() whereas '; '-
18    # separated commands will use only one call.
19    #
20    # Here we form a command string and use it with mgr.execute()
21    base_cmd = "size stickRadius 0.07 ballScale 0.18"
22    if name == "thin sticks":
23        style_cmd = "style stick"
24    elif name == "ball and stick":
25        style_cmd = "style ball"
26    else:
27        raise ValueError("No preset named '%s'" % name)
28    mgr.execute(base_cmd + '; ' + style_cmd)
29

The run_preset() function needs to in turn call the preset manager’s execute() method to actually execute the preset, so that the proper information about the preset can be logged. The single argument to execute() is either a Python function taking no arguments, or a string containing a ChimeraX command. The string is typically not just a single command, but multiple commands separated by semi-colon (‘;’) characters, which is the approach our run_presets() function uses to execute both a size command (to make the sticks/balls thin/small) and a style command to switch to stick or ball-and-stick style.

Building and Testing Bundles

To build a bundle, start ChimeraX and execute the command:

devel build PATH_TO_SOURCE_CODE_FOLDER

Python source code and other resource files are copied into a build sub-folder below the source code folder. C/C++ source files, if any, are compiled and also copied into the build folder. The files in build are then assembled into a Python wheel in the dist sub-folder. The file with the .whl extension in the dist folder is the ChimeraX bundle.

To test the bundle, execute the ChimeraX command:

devel install PATH_TO_SOURCE_CODE_FOLDER

This will build the bundle, if necessary, and install the bundle in ChimeraX. Bundle functionality should be available immediately.

To remove temporary files created while building the bundle, execute the ChimeraX command:

devel clean PATH_TO_SOURCE_CODE_FOLDER

Some files, such as the bundle itself, may still remain and need to be removed manually.

Building bundles as part of a batch process is straightforward, as these ChimeraX commands may be invoked directly by using commands such as:

ChimeraX --nogui --exit --cmd 'devel install PATH_TO_SOURCE_CODE_FOLDER exit true'

This example executes the devel install command without displaying a graphics window (--nogui) and exits immediately after installation (exit true). The initial --exit flag guarantees that ChimeraX will exit even if installation fails for some reason.

Distributing Bundles

With ChimeraX bundles being packaged as standard Python wheel-format files, they can be distributed as plain files and installed using the ChimeraX toolshed install command. Thus, electronic mail, web sites and file sharing services can all be used to distribute ChimeraX bundles.

Private distributions are most useful during bundle development, when circulation may be limited to testers. When bundles are ready for public release, they can be published on the ChimeraX Toolshed, which is designed to help developers by eliminating the need for custom distribution channels, and to aid users by providing a central repository where bundles with a variety of different functionality may be found.

Customizable information for each bundle on the toolshed includes its description, screen captures, authors, citation instructions and license terms. Automatically maintained information includes release history and download statistics.

To submit a bundle for publication on the toolshed, you must first sign in. Currently, only Google sign in is supported. Once signed in, use the Submit a Bundle link at the top of the page to initiate submission, and follow the instructions. The first time a bundle is submitted to the toolshed, it is held for inspection by the ChimeraX team, which may contact the authors for more information. Once approved, all subsequent submissions of new versions of the bundle are posted immediately on the site.

What’s Next