Chimera Programming Frequently Asked Questions

Last updated February 4, 2004. The most recent copy of the FAQ is at

  1. Where is the programming documentation?
  2. How to emulate command-line functionality.
  3. How to rotate/translate the camera.
  4. How to rotate/translate individual models.
  5. How to save the current view as an image.
  6. Some attributes return a copy of an object.
  7. Explanation of transparency for Surface_Model, MSMSModel and VRMLModel.
  8. Transparency displayed incorrectly when 2 or more models are transparent.
  9. Explanation of openState attribute.
  10. Memory leaks in scripts.
  11. Getting the size of a volume data set.
  12. How to write out a PDB file containing the crystal unit cell.

1) Where is the programming documentation?

The Chimera Programmer's Reference manual is automatically generated from comments in the code and is not of much use. The Programming Examples are a good source of information. The C++ header files for the Chimera objects are useful but are not currently distributed. You can request the header files from The archived Chimera development mailing list is at

2) How to emulate command-line functionality.

Commands available at the type-in command line are almost all implemented in the Midas module's file. You can use the commands for convenience in implementing the same functionality in your extension. For example, to color iron atoms red:

import Midas
Midas.color('red', '@/element=Fe')

A few commands related to processing command text (e.g. handling files of commands) are in Midas.midas_text. One in particular, makeCommand(), allows you to use command-line syntax directly instead of determining the proper arguments to a Midas module function. So the above example of coloring atoms red would look like this using makeCommand():

import Midas
from Midas.midas_text import makeCommand
makeCommand("color red @/element=Fe")

Note that if the command text may contain errors (e.g. it is based on user input), makeCommand() can raise IOError (yes, it probably should be SyntaxError, but oh well) so in such cases you may want to embed the makeCommand() in a try/except block.

3) How to rotate/translate the camera.

Camera always points in -z direction. There is no way to rotate it.

>>> v = chimera.viewer
>>> c =
>>> print
(5.9539999961853027, -2.186500072479248, 10.296500205993652)
>>> = (3, 2.5, 10)	# to translate camera
>>> v.scaleFactor = 1.5		# to zoom camera

4) How to rotate/translate individual models.

The Xform object model.openState.xform gives the rotation and translation for a model.

>>> om = chimera.openModels
>>> mlist = om.list()
>>> m = mlist[0]
>>> xf = chimera.Xform()
>>> axis = chimera.Vector(1, 0, 0)
>>> angle = 90			# degrees
>>> xf.rotate(axis, angle)
>>> print m.openState.xform	# 3x3 rotation matrix
				# last column is translation
0.982695 0.121524 0.139793 -1.07064
0.0250348 0.660639 -0.750287 6.83425
-0.183531 0.740803 0.646164 6.35578
>>> m.openState.globalXform(xf)

Another method to change the transform

>>> xf.premultiply(m.openState.xform)	# changes xf
>>> m.openState.xform = xf

To rotate relative to data axes use

>>> m.openState.localXform(xf)


>>> xf.multiply(m.openState.xform)	# changes xf
>>> m.openState.xform = xf

5) How to save the current view as an image.

import Midas
Midas.copy(file='/home/goddard/hoohoo.png', format='PNG')
# format can be 'PNG', 'BMP', 'EPS','GIF', 'JPEG', 'PDF', 'PPM', 'TIFF'

6) Some attributes return a copy of an object.

>>> xf = model.openState.xform	# xf is a copy of the model's Xform matrix.
>>> xf.zRotate(45)		# This will not rotate the model.
>>> c = model.atoms[0].color	# c is the MaterialColor object for the atom
>>> c.ambientDiffuse = (1,0,0)	# The Atom color changes immediately to red.

Some Chimera objects returned as attributes are always copies, some are always references to the uncopied object. Objects that are always copied include Xform, Vector, Point, Sphere, Element, MolResId, Coord, .... Objects that are never copied include Atom, Bond, PseudoBond, CoordSet, Molecule, Residue, RibbonStyle, .... These objects that are not copied do not have any any method for copying them. In order to know if an object type is passed by value is to look at the Chimera C++ header files. Classes without a WrapPy base class are copied. Those with a WrapPy base class are not copied. This base class is part of the C++ to Python interface generation.

7) Explanation of transparency for Surface_Model, MSMSModel and VRMLModel.

Volume viewer isosurfaces are Surface_Model objects defined by the C++ module. The Surface_Model interface is given in the surfmodel.h source code file. By default these surfaces use OpenGL (1,1-alpha) blending. This means the color for a triangle is added to an image plus the transparency (= 1-alpha) times the color from triangles in back of this one. As the transparency becomes greater, the brightness of the triangle does not diminish. In fact, more shows through from behind the triangle so it appears brighter. The specular highlights stay bright even if the triangle is black and fully tranparent. In Chimera 1730 a Surface_Model attribute transparency_blend_mode was added to allow the more common (alpha,1-alpha) blend mode. This is like the above mode but the triangle color is multiplied by alpha before being added to the image. For highly transparent triangles alpha is close to zero, and the triangle and specular highlights become dim.

MSMS molecular surface models use (alpha, 1-alpha) blending. They also use a 2 pass algorithm which is faster than sorting all the triangles by depth, but gives the strictly correct appearance only when the viewer looks through at most 2 surface layers.

VRML models use (alpha,1) blending. That is they multiply triangle color by alpha, but add in all of the color from triangles further back without reducing it by the transparency factor. This is like complete transparency, where the triangle colors are just scaled by the alpha value. This is horrible looking unless you want complete transparency.

8) Transparency displayed incorrectly when 2 or more models are transparent.

The Chimera architecture only correctly displays transparency when at most one transparent model is shown. Any number of opaque models can also be shown. If two transparent models are shown, one will be drawn after the other. This will make one appear as if it is drawn entirely on top of another even if they in actuality intersect. The rearmost model, may in fact appear to be in front. This is because Chimera sorts the triangles by depth within a single model as needed for rendering transparency, but is not able to sort triangles by depth across multiple models.

9) Explanation of openState attribute.

The openState attribute of a Model controls whether that model is active for motion ('.active'), and contains the model's transformation matrix ('.xform') and center of rotation ('.cofr'). Since some models must move in synchrony (e.g. a molecule and its surface), OpenState instances may shared among multiple models. If you create a model that needs a shared openState with another model, then when adding your model to the list of open models with chimera.openModels.add(), you should use the 'sameAs' keyword to specify that other model.

10) Memory leaks in scripts.

In the 1700 release, Chimera uses a substantial amount of memory to hold molecular data, but does not have any large memory leaks to the best of our knowledge (i.e. as structures are closed their memory usage will be reclaimed). However, the memory is reclaimed by a task that runs during idle times, so therefore scripts that loop through many structures, opening and closing them, will have their memory use grow continuously until the script finishes. This will often cause the script to fail as the Chimera process runs out of memory.

You can cause the memory-reclamation task to run during your script by calling:


You would want to call this after closing models in your script. Since the checkForChanges() routine also allows triggers to fire, you might want to also put it after any code that opens models. For example, the code that assigns surface categories to models runs from a trigger callback, so adding a molecular surface may not work as expected if checkForChanges() is not called after a molecule is opened.

In post-1700 releases and snapshots, checkForChanges() is called automatically when models are opened or closed, so you will not need to insert these calls into your code.

11) Getting the size of a volume data set.

Here's some code to find the size of a volume data set.

import VolumeViewer
d = VolumeViewer.volume_dialog()
d0 = d.data_sets[0]	# There may be more than one data set opened
			# You could look at each one's name (= file name)
			# to find the one you want.
data =		# This is a Grid_Data object defined in
			# VolumeData/
xsize, ysize, zsize = data.size

12) How to write out a PDB file containing the crystal unit cell.

Here's code that creates the copies of a PDB molecule needed to fill out a crystallographic unit cell, then writes all the copies to a new PDB file. This code uses the standard Chimera 1.1892 PDBmatrices module, which uses the PDB SMTRY remarks or CRYST1 record to determine the needed transformations.

You can run it without a graphical user interface as follows

	% chimera --nogui myfile.pdb

where the file contains the script given below.

# Get the Molecule that has already been opened
import chimera
m = chimera.openModels.list()[0]

# Get the symmetry matrices
import PDBmatrices
tflist = PDBmatrices.crystal_symmetry_matrices(m.pdbHeaders)

# Get center of bounding box
import UnitCell
center = UnitCell.molecule_center(m)

# Get CRYST1 line from PDB headers
cryst1 = m.pdbHeaders['CRYST1'][0]

# Getting crystal parameters
from PDBmatrices import crystal
cp = crystal.pdb_cryst1_parameters(cryst1)
a,b,c,alpha,beta,gamma = cp[:6]

# Adjust matrices to produce close packing.
cpm = PDBmatrices.close_packing_matrices(tflist, center, a, b, c, alpha, beta, gamma)

# Apply transformations to copies of Molecule
mlist = []
from PDBmatrices import matrices
path = m.openedAs[0]			# Path to original PDB file
for tf in cpm:
    xf = matrices.chimera_xform(tf)	# Chimera style transform matrix
    m =[0]	# Open another copy

# Write PDB file with transformed copies of molecule
import Midas
out_path = 'unitcell.pdb'
Midas.write(mlist, None, out_path)