Bundle Example: Define a Chemical Subgroup Selector¶
This example describes how to create a ChimeraX bundle that defines a chemical subgroup selector that can be used in command line target specifier for identifying atoms of interest.
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 atom-selection 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_sel. 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_sel
folder are:
tut_sel
- bundle folderbundle_info.xml
- bundle information read by ChimeraXsrc
- source code to Python package for bundle__init__.py
- package initializer and interface to ChimeraXselector.py
- source code to define target selector
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-TutorialSelector"
9 version="0.1" package="chimerax.tut_sel"
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 selector</Synopsis>
20 <Description>Example code for implementing ChimeraX bundle.
21
22Implements new specifier selector "endres" for selecting
23end residues of chains.
24 </Description>
25
26 <!-- Categories is a list where this bundle should appear -->
27 <Categories>
28 <Category name="General"/>
29 </Categories>
30
31 <!-- Dependencies on other ChimeraX/Python packages -->
32 <Dependencies>
33 <Dependency name="ChimeraX-Core" version="~=1.1"/>
34 </Dependencies>
35
36 <Classifiers>
37 <!-- Development Status should be compatible with bundle version number -->
38 <PythonClassifier>Development Status :: 3 - Alpha</PythonClassifier>
39 <PythonClassifier>License :: Freeware</PythonClassifier>
40 <!-- ChimeraX classifiers describe supplied functionality -->
41 <!-- Register "endres" selector for selecting resides at ends of chains -->
42 <ChimeraXClassifier>ChimeraX :: Selector :: endres :: residues at ends of chains</ChimeraXClassifier>
43 </Classifiers>
44
45</BundleInfo>
The BundleInfo
, Synopsis
and Description
tags are
changed to reflect the new bundle name and documentation
(lines 8-10 and 17-24).
The ChimeraXClassifier
tag on line 42 informs ChimeraX that
there is one chemical subgroup selector named endres
in
the bundle. The last field is a short description for
the selector. If endres
appears in the target specification
of a ChimeraX command, the bundle function associated with
endres
will be invoked to find the atoms of interest,
e.g. the command sel endres
will select the ending residues of chains.
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 registering selectors,
8# inheriting all other methods from the base class.
9class _MyAPI(BundleAPI):
10
11 api_version = 1
12
13 # Override method for registering selectors
14 @staticmethod
15 def register_selector(bi, si, logger):
16 # bi is an instance of chimerax.core.toolshed.BundleInfo
17 # si is an instance of chimerax.core.toolshed.SelectorInfo
18 # logger is an instance of chimerax.core.logger.Logger
19
20 # This method is called once for each selector listed
21 # in bundle_info.xml. Since we list only one selector,
22 # we expect a single call to this method.
23 from .selector import register
24 return register(si.name, logger)
25
26
27# Create the ``bundle_api`` object that ChimeraX expects.
28bundle_api = _MyAPI()
The register_selector()
method is called by ChimeraX,
once for each selector listed in bundle_info.xml
,
before the first time a command target specification is parsed.
In this example, the method is called a single time
with selector name endres
.
The arguments to register_selector()
, in bundle API version 1,
are bi
, a chimerax.core.toolshed.BundleInfo
instance,
si
, a chimerax.core.toolshed.SelectorInfo
instance, and
logger
, a chimerax.core.logger.Logger
instance.
The method is expected to call
chimerax.core.commands.register_selector()
to define
a selector whose name is given by si.name
.
Note that there is no session
argument because, like commands,
selectors are session-independent; that is, once registered, a selector
may be used in any session.
src/selector.py
¶
selector.py
defines both the callback function, _select_endres
,
that is invoked when endres
is encountered in a target specification,
as well as the function for registering select_endres
with ChimeraX.
1# vim: set expandtab shiftwidth=4 softtabstop=4:
2
3def register(selector_name, logger):
4 """Register selector with ChimeraX.
5 """
6 # Registration is simply telling ChimeraX which function
7 # to call when the selector is used. If an unexpected
8 # selector_name is given, the dictionary lookup will fail,
9 # and the resulting exception will be caught by ChimeraX.
10 from chimerax.core.commands import register_selector
11 register_selector(selector_name, _selector_func[selector_name], logger)
12
13
14def _select_endres(session, models, results):
15 # session is an instance of chimerax.core.session.Session
16 # models is a list of chimerax.atomic.Model instances
17 # results is an instance of chimerax.core.objects.Objects
18
19 # Iterate through the models and add atoms that are end
20 # residues in chains. If model does not have chains, just
21 # silently ignore it.
22 for m in models:
23 try:
24 chains = m.chains
25 except AttributeError:
26 continue
27 # chains is an instance of chimerax.atomic.Chains
28 # whose elements are chimerax.atomic.Chain instances
29 for c in chains:
30 residues = c.existing_residues
31 # residues is an instance of chimerax.atomic.Residues
32 # whose elements are chimerax.atomic.Residue
33 # instances.
34 # 'results' only holds models, atoms and bonds, not residues.
35 # We add atoms from the residues on the ends. Bonds between
36 # atoms in each residue are also added.
37 results.add_atoms(residues[0].atoms, bonds=True)
38 results.add_atoms(residues[-1].atoms, bonds=True)
39
40
41# Map selector name to corresponding callback function.
42# Only one selector for now, but more can be added
43_selector_func = {
44 "endres": _select_endres
45}
The code in selector.py
is designed to register multiple
selector callback functions using the same registration function.
When register()
is called from
__init__.bundle_api.register_selector()
,
it looks up the callback function associated
with the given selector name using the _selector_func
dictionary,
and registers it using
chimerax.core.commands.register_selector
.
A selector callback function is invoked with three arguments:
session
, a chimerax.core.session.Session
instance,
models
, a list of chimerax.core.models.Model
instances, and
results
, a chimerax.core.objects.Objects
instance.
The callback function is expected to process all the given models
and add items of interest to results
. Currently, the only items
that can be added are instances of chimerax.core.models.Model
,
chimerax.atomic.Atom
and
chimerax.atomic.Bond
.
Typically, Model
instances
are only added explicitly for non-atomic models.
More commonly, atoms (and bonds) are added
using the add_atoms()
method.
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: Fetch from Network Database (previous topic)
Bundle Example: Define a Chemical Subgroup Selector (current topic)
Bundle Example: Define Presets (next topic)