This example shows how to measure atomic-level (rather than volumetric) quantities such and angles, RMSDs, surface areas, and so forth.

The first concept to understand is that when models are moved in Chimera,
the atomic coordinates are not changed. Instead, a "transformation"
matrix is updated that transforms the model's original coordinates into
"world" coordinates (*i.e.* into the overall coordinate system).
Consequently, there are two methods for obtaining a coordinate from a chimera.Atom
object: `coord()`

, which returns the Atom's original coordinate, and
`xformCoord()`

, which returns the transformed coordinate. Note that
some structure-editing activities in Chimera *will* change the original
coordinates (*e.g.* changing a torsion angle).

Therefore, if you are measuring quantities that might involve multiple models,
you should use the `xformCoord()`

method. If your measurements are
completely intra-model you can instead use the very slightly faster `coord()`

method.

The "Chimera's Object Model" example discusses how to access various Chimera objects in detail, but here's an executive summary for the tl;dr crowd:

from chimera import OpenModels, Molecule mols = OpenModels.list(modelTypes=[Molecule])

`atoms`

/`bonds`

/`residues`

attributes, respectively.
`runCommand()`

function), use the
`currentAtoms`

/`currentBonds`

/`currentResidues`

functions
in the chimera.selection module, from chimera.selection import currentAtoms sel_atoms = currentAtoms()

*Atom*`.neighbors`

*Atom*`.primaryNeighbors()`

- Returns a list of the Atoms bonded to the given Atom.
Some high-resolution structures can have multiple positions for a single atom,
and in those cases
`primaryNeighbors()`

will only return one Atom among those positions whereas`neighbors`

will return all of them. *Atom*`.bonds`

*Atom*`.primaryBonds()`

- Returns a list of the Bonds the Atom is involved in.
`primaryBonds()`

is analogous to*Atom*`.primaryNeighbors()`

. *Atom*`.bondsMap`

- Returns a dictionary whose keys are Atoms the given Atom is bonded to, and the values are the corresponding Bonds.
*Atom*`.residue`

- Returns the Residue the Atom is in.
*Atom*`.molecule`

- Returns the Molecule model the Atom is in.
*Bond*`.atoms`

- Returns a list of the two Atoms forming the Bond.
*Residue*`.atoms`

- Returns a list of the Atoms in the Residue.
*Residue*`.atomsMap`

- Returns a dictionary whose keys are atom names.
The values are
*lists*of Atoms with the corresponding name. The values are lists because in some structure formats (*e.g.*Mol2, XYZ) small molecules atoms are not given unique names (for example, all carbons are named "C"). Also, PDB files where an atom has alternate locations will produce multiple Atoms with the same name in a Residue. *Residue*`.molecule`

- Returns the Molecule model the Residue is in.

Both the *Atom*`.coord()`

and *Atom*`.xformCoord()`

methods return
chimera.Point objects. Point objects have the following built-in measurement methods:

*Point*`.distance(`

*Point*`)`

- Returns the distance in angstroms between the two Points.
*Point*`.sqdistance(`

*Point*`)`

- Returns the square of the distance in angstroms between the two Points.
Taking square roots is slow, so this method is faster than the
`distance()`

method. Therefore in code where speed is important, when possible you should work with squares of distances rather than the distances themselves (*e.g.*when comparing a distance to a cutoff value, compare the squares instead [and make sure to only compute the square of the cutoff once!]).

`chimera.distance(`

*Point*`,`

*Point*`)`

`chimera.sqdistance(`

*Point*`,`

*Point*`)`

- Returns the distance (or distance squared) in angstroms between the two Points.
Functionally identical to
*Point*.distance(*Point*) and*Point*.sqdistance(*Point*) methods respectively. `chimera.angle(`

*Point*`,`

*Point*`,`

*Point*`)`

- Returns the angle in degrees formed by the points. The angle value ranges from 0 to 180.
`chimera.dihedral(`

*Point*`,`

*Point*`,`

*Point*`,`

*Point*`)`

- Returns the dihedral angle in degrees formed by the points.
The angle value ranges from -180 to 180.
Note that Residues have
*phi*,*psi*, and*chi1*through*chi4*attributes that can be queried for the corresponding values (value will be*None*if the Residue lacks that kind of angle). In fact, those attributes can be set and the structure will be adjusted appropriately!

`xformCoord()`

method used to fetch their coordinates):
import chimera angle = chimera.angle(a1.xformCoord(), a2.xformCoord(), a3.xformCoord())Alternatively, if the three atoms are in a list (

import chimera angle = chimera.angle(*[a.xformCoord() for a in atoms])

The `centroid`

,
`axis`

,
and `plane`

functions described below utilize chimera.Point, chimera.Vector,
and chimera.Plane objects for some of their return values.
A chimera.Point object, described previously, abstracts a point in Cartesian
3-space. A chimera.Vector objects abstracts a direction vector in 3-space
with finite length (*i.e.* it is not infinite and has an associated length).
A chimera.Plane object abstracts an infinite plane in 3-space.
Each of these objects has useful member functions that you can
learn about by using the *help* Python function in the IDLE tool
(*e.g.* `help(chimera.Plane)`

).
For instance, if *p* is a Plane and *pt* is a Point, then
*p*`.distance(`

*pt*`)`

is the distance from the Point *pt* to the Plane *p*.

The `axis`

and `plane`

functions take an
*n*-by-3 numpy array as one of their input arguments.
The easiest way to generate such an array from Atom coordinates is
to use the `numpyArrayFromAtoms`

function from the *chimera* module
(*i.e.*
`chimera.numpyArrayFromAtoms(`

*Atoms*`)`

or, if transformed coordinates are required,
`chimera.numpyArrayFromAtoms(`

*Atoms*`, `

).
`xformed=True`

)

The *StructMeasure* module has three convenient functions for finding the
best-fitting axis, centroid, or plane through a set of points. They are:

`StructMeasure.centroid(`

*points*,`weights=None)`

- Returns a chimera.Point object.
*points*is a sequence of chimera.Point objects.`weights`

is an optional sequence of corresponding numeric weights to give those Points when computing the centroid.`weights`

is most frequently used when mass weighting is desired. To that end, it is useful to know that the mass of atom*a*is given by*a*`.element.mass`

. `StructMeasure.axis(`

*xyzs*,`findBounds=False`

,`findRadius=False`

,`iterate=True`

,`weights=None)`

- Returns a chimera.Point and chimera.Vector.
The Point is the center of the axis, and the Vector indicates the direction
of the axis (and is of unit length).
As discussed in
**Preliminaries**,*xyzs*is an*n*-by-3 numpy array. If`findBounds`

is`True`

, two floating point numbers are appended to the return values, indicating the scaling values needed for the Vector to reach the approximate end of the axis given the input coordinates. One of the scaling values will be negative. If`findRadius`

is`True`

, a floating point number, indicating the approximate radius of the axis given the input coordinates, will be appended to the return values. If`iterate`

is`True`

, the best-fitting axis as determined by principal-component analysis will be iteratively tweaked to try to get the axis as equidistant as possible from the points determining the axis. For helical sets of atoms, the principal-component axis will tend to tilt towards the final atoms of the helix. The tilt is more pronounced the shorter the helix, and`iterate`

attempts to correct the tilt.`weights`

is the same as in the`centroid`

function. `StructMeasure.plane(`

*xyzs*,`findBounds=False)`

- Returns a chimera.Plane whose origin is the centroid of
*xyzs*. As discussed in**Preliminaries**,*xyzs*is an*n*-by-3 numpy array. If`findBounds`

is`True`

, a Point, which represents the furthest*xyz*from the origin when projected onto the Plane, is appended to the return value.

Once a surface has been computed for a model,
all Atoms and Residues of that model will have an
`areaSAS`

attribute (solvent accessible surface area)
and an
`areaSES`

attribute (solvent excluded surface area).
One possible way to get a surface computed for a model is to
call the *surface* command via the
`runCommand()`

function.