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:
Create a
bundle_info.xml
containing information about the bundle,Create a Python package that interfaces with ChimeraX and implements the preset functionality, and
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 folderbundle_info.xml
- bundle information read by ChimeraXsrc
- source code to Python package for bundle__init__.py
- package initializer and interface to ChimeraXpresets.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¶
Bundle Example: Define a Chemical Subgroup Selector (previous topic)
Bundle Example: Define Presets (current topic)