Chimera implements its graphical user interface (GUI) using a Python interface (Tkinter module) to the Tcl/Tk toolkit. Since Chimera extensions are also written in Python, they can extend the user interface using the same mechanism. Any extension that requires user input will need to present a GUI. This example assumes that the reader is familiar with Tkinter and does not describe the Tkinter-specific code in detail.
The code below demonstrates how to change the display mode of protein backbone
to a user-selected representation. The graphical window renders atoms and bonds
according to their drawMode
attribute. Thus, all that the example
code in the main package, __init__.py, does is to change the attribute
values of backbone atoms and bonds. The example code in the graphical user interface
submodule, gui.py, adds a button to the Chimera toolbar. When the user
clicks the toolbar button, the window below is displayed.
The user can select the desired display representation for atoms and bonds
using the option menus, and then set the backbone atom and bond representations
by clicking the Apply
button.
Import the standard modules used in this example.
Import the Chimera modules used in this example.
Define a regular expression for matching the names of protein backbone
atoms (we do not include the carbonyl oxygens because they tend to
clutter up the graphics display without adding much information).
Define
Import the standard modules used by this example.
Import the Chimera modules and classes used by this example.
Import the package for which the graphical user interface
is designed. In this case, the package is named
Define two module variables:
Define two dictionaries that map string names into Chimera
enumerated constant values. The two variables
Chimera offers two base classes to somewhat simplify the task of
creating user interfaces: ModalDialog and ModelessDialog. The
former is designed for situations when information or response
is required of the user immediately; the dialog stays in front
of other Chimera windows until dismissed and prevents input from
going to other Chimera windows. The latter dialog type is designed
for "ongoing" interfaces; it allows input focus to go to other
windows, and other windows can obscure it.
Here we declare a class that derives from ModelessDialog and
customize it for the specific needs of this extension.
Chimera dialogs can either be named or nameless. Named
dialogs are displayed using the
A nameless dialog is intended for use only in the extension that
defines the dialog. A nameless dialog is typically created and
displayed by calling its constructor. Once created, a nameless
dialog can be redisplayed (if it was withdrawn by clicking its
For demonstration purposes, we use a named dialog here. A
nameless dialog is used in the Color and Color Wells example.
The buttons displayed at the bottom of the dialog are given
in the class variable
Both dialog base classes provide appropriate methods for
A help file or URL can be specified with the
The title displayed in the dialog window's title bar is set
via the class variable
Both ModelessDialog and ModalDialog, in their __init__
functions, set up the standard parts of the dialog interface
(top-level window, bottom-row buttons, etc.) and then call
a function named
Declare that, in
Create and initialize
Create the label and option menu for selecting atom
display representation. First create the label
Create the menu button and the option menu that it brings up.
Add radio buttons for all possible choices to the menu.
The list of choices is obtained from the keys of the
string-to-enumeration dictionary, and the radio button
for each choice is programmed to update the
Assigns the option menu to the menu button.
The lines below do the same thing for bond representation
as the lines above do for atom representation.
Define the method that is invoked when the
Now we register the above dialog with Chimera, so that it may be
invoked via the
Create the Chimera toolbar button that displays the dialog when
pressed. Note that since the package is not normally searched for
icons, we have to prepend the path of this package to the icon's
file name. The example above requires the user to first select the desired representation,
then apply the selection to the protein backbone. An alternative interface style
is to apply user selections immediately. The appropriate choice of style depends
on the extension application. The reason for choosing the "Apply"
style for this example is that the user is expected to change both atom and
bond representations, and there is no need to edit and display intermediate
representations.
The ratio of 13 lines of functionality code to 34 lines of user interface code
is fairly typical. Doing things is easy; figuring out what a user wants to do,
that's hard.
For extensions based on the The example code files and toolbar icon must be saved in a directory named This should display a button on the Chimera toolbar. Clicking the button should
bring up a window similar to the one shown above.
import re
import chimera
MAINCHAIN = re.compile("^(N|CA|C)$", re.I)
mainchain
function for setting the display representation
of protein backbone atoms and bonds. See Molecular Editing for a
more detailed example on changing molecular attributes.
def mainchain(atomMode, bondMode):
for b in m.bonds:
if MAINCHAIN.match(ends[0].name) \
and MAINCHAIN.match(ends[1].name):
Example ExtensionUI/gui.py
import os
import Tkinter
import chimera
from chimera.baseDialog import ModelessDialog
ExtensionUI
.
import ExtensionUI
atomMode
and bondMode
are Tk variables that keep track of
the last selected display representations. These variables are
initialized to be None
, and are set to usable values when
the GUI is created.
atomMode = None
bondMode = None
atomMode
and
bondMode
keep track of the representations as strings because
they are displayed directly in the user interface. However,
the mainchain
function in the main package expects Chimera
constants as its arguments. The dictionaries atomModeMap
and
bondModeMap
provides the translation from string to enumerated
constants.
atomModeMap = {
}
'Sphere': chimera.Atom.Sphere,
'EndCap': chimera.Atom.EndCap,
'Ball': chimera.Atom.Ball
bondModeMap = {
}
'Stick': chimera.Bond.Stick
class MainchainDialog(ModelessDialog):
display(name)
function
of the chimera.dialogs module. The name that should be used
as an argument to the display
function is given by the class
variable name
. Using a named dialog is appropriate when
it might be desirable to invoke the dialog from other extensions
or from Chimera itself.Cancel
button for example) by calling its enter()
method.
name = "extension ui"
buttons
. For modeless dialogs, a
help button will automatically be added to the button list
(the help button will be grayed out if no help information
is provided). For buttons other than Help
, clicking on
them will invoke a class method of the same name.Close
, so we won't provide a Close
method in this
subclass. The ModelessDialog base class also provides a
stub method for Apply
, but we will override it with our
own Apply
method later in the class definition.
buttons = ("Apply", "Close")
help
class
variable. A URL would be specified as a string (typically
starting with "http://..."). A file would be specified as
a 2-tuple of file name followed by a package. The file
would then be looked for in the helpdir
subdirectory of
the package. A dialog of Chimera itself (rather than of an
imported package) might only give a filename as the class
help variable. That file would be looked for in
/usr/local/chimera/share/chimera/helpdir.
help = ("ExtensionUI.html", ExtensionUI)
title
.
title = "Set Backbone Representation"
fillInUI
so that the subclass can fill
in the parts of the interface specific to the dialog. As
an argument to the function, a Tkinter Frame is provided
that should be the parent to the subclass-provided interface
elements.
def fillInUI(self, parent):
fillInUI
, the names atomMode
and
bondMode
refer to the global variables defined above.
global atomMode, bondMode
atomMode
and bondMode
, the
two global Tk string variables that keep track of the
currently selected display representation.
atomMode = Tkinter.StringVar(parent)
atomMode.set('Dot')
bondMode = Tkinter.StringVar(parent)
bondMode.set('Wire')
Atom
Representation
and place it on the left-hand side of
the top row in the GUI window.
atomLabel = Tkinter.Label(parent, text='Atom Representation')
atomLabel.grid(column=0, row=0)
atomButton = Tkinter.Menubutton(parent, indicatoron=1,
atomButton.grid(column=1, row=0)
relief=Tkinter.RAISED, borderwidth=2)
atomMenu = Tkinter.Menu(atomButton, tearoff=0)
atomMode
variable when selected.
for mode in atomModeMap.keys():
atomButton['menu'] = atomMenu
bondLabel = Tkinter.Label(parent, text='Bond Representation')
bondLabel.grid(column=0, row=1)
bondButton = Tkinter.Menubutton(parent, indicatoron=1,
bondButton.grid(column=1, row=1)
relief=Tkinter.RAISED, borderwidth=2)
bondMenu = Tkinter.Menu(bondButton, tearoff=0)
for mode in bondModeMap.keys():
bondButton['menu'] = bondMenu
Apply
button
is clicked. The function simply converts the currently
selected representations from strings to enumerated constants,
using the atomModeMap
and bondModeMap
dictionaries, and
invokes the main package function mainchain
.
def Apply(self):
display(name)
method of the chimera.dialogs module.
Here the class itself is registered, but since it is a named dialog
deriving from ModalDialog/ModelessDialog, the instance will automatically
reregister itself when first created. This allows the dialogs.find()
function to return the instance instead of the class.
chimera.dialogs.register(MainchainDialog.name, MainchainDialog)
dir, file = os.path.split(__file__)
icon = os.path.join(dir, 'ExtensionUI.tiff')
chimera.tkgui.app.toolbar.add(icon, lambda d=chimera.dialogs.display, n=MainchainDialog.name: d(n), 'Set Main Chain Representation', None)
Code Notes
ModalDialog
class, a different
approach is typically used. The dialog is not registered (no call to
chimera.dialogs.register
). The function associated with the
toolbar icon (the second argument to
chimera.tkgui.app.toolbar.add
) creates the modal dialog, calls
the dialog's run()
method, and uses that method's return value
as appropriate (None
is returned by a user-initiated Cancel of
the dialog). When writing dialog methods, the return value is kept in the
self.returnValue
attribute of the dialog. The dialog is
destroyed when the toolbar function runs out of scope.
Running the Example
ExtensionUI
.
To run the example, start chimera in the directory above the package
directory and type the following command into the IDLE command line:
import ExtensionUI.gui