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, e.g.:
from chimera.selection import currentAtoms sel_atoms = currentAtoms()
.neighbors
.primaryNeighbors()
primaryNeighbors()
will only return one Atom among those positions whereas
neighbors
will return all of them.
.bonds
.primaryBonds()
primaryBonds()
is analogous to
Atom.primaryNeighbors()
.
.bondsMap
.residue
.molecule
.atoms
.atoms
.atomsMap
.molecule
Both the Atom.coord()
and Atom.xformCoord()
methods return
chimera.Point objects. Point objects have the following built-in measurement methods:
.distance(
Point)
.sqdistance(
Point)
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)
chimera.angle(
Point,
Point,
Point)
chimera.dihedral(
Point,
Point,
Point,
Point)
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 (atoms), you can use slightly fancier Python:
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)
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)
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)
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.