Atom selection language¶
The Python function vibeview.molecular_selection.select(structure, expression)
returns a set of zero-based atom indices. Surface and interaction selection
fields use this same parser. Expressions use one-based atom numbers.
expression = conjunction { "or" conjunction }
conjunction = negation { "and" negation }
negation = "not" negation | primary
primary = "(" expression ")" | "all" | "none"
| "index" index-list | "element" value | "chain" value
| "residue" value | "model" value | "group" value
| "within" radius "of" "(" expression ")"
index-list = positive-integer [ "-" positive-integer ]
{ "," positive-integer [ "-" positive-integer ] }
not binds before and, which binds before or. Keywords are case-sensitive;
element symbols are case-insensitive. Values containing spaces need quotes.
Indices and inclusive ranges must be in bounds, and reversed ranges are refused.
Residues use chain/sequence, for example residue A/24. Missing identifiers
match no atoms. Blank expressions select none. Invalid syntax raises ValueError;
expressions are never executed as Python.
Examples:
element O or element Nchain A and not element Hindex 1,3-8within 4 of (residue A/24) and not residue A/24(model protein and element C) or group "active site"
Distances are in angstroms, inclusive at the cutoff, and include seed atoms.
They use the supplied coordinates without periodic images. A single structure
has model ID 1. Callers representing several models supply model_ids, with
one string identifier per atom. Named groups are supplied with groups, a
mapping of names to sets of zero-based indices; invalid group indices are
refused. Neither context is modified. Unknown group names raise ValueError
to catch mistakes in scripts.
from vibeview import QVFReader
from vibeview.molecular_selection import select
with QVFReader("molecule.qvf") as reader:
structure = reader.read_structure()
# This example needs a structure with at least five atoms.
selected = select(structure, 'group "active site" and not element H',
groups={"active site": {0, 2, 4}})
The returned set has no atom ordering. Sort indices for a deterministic single-structure report, but supply an explicit chemical correspondence for paired measurements. An empty result is valid for an absent residue or element; check it before fitting a plane or computing a centroid.
These functions are submodule APIs rather than package-root exports. Pin the viewer version for scripts that depend on them; see the SDK contract. The grammar and context API are available independently of scene scripting. See working model scenes for browser command history, replayable models and scene measurements.
Measurements in Python¶
vibeview.selection_measurements accepts finite (N, 3) coordinate arrays in
angstroms (or consistently in another length unit). centroid is unweighted;
principal_axes returns the centroid, descending population variances and unit
axes as rows. Its unique flag is false when eigenvalues are repeated: directions
within that subspace are not physically determined. This is coordinate covariance,
not a mass-weighted moment-of-inertia tensor.
best_fit_plane returns a centroid, unit normal and RMS perpendicular residual
from orthogonal least squares. It refuses collinear selections and other cases
without a unique normal. point_plane_distance is unsigned; plane_angle
returns the unoriented acute angle in degrees (0–90). Empty or nonfinite selections
are errors. No periodic images or minimum-image distances are inferred.
selection_rmsd(first, second) uses the supplied row correspondence; pass
superpose=True to remove translation and proper rotation with Kabsch alignment.
It never guesses atom pairing or mirrors one structure onto another. Order paired
selections deliberately; independently sorting two index sets need not represent
the same chemical correspondence.
import numpy as np
from vibeview.molecular_selection import positions, select
from vibeview.selection_measurements import best_fit_plane, centroid
indices = sorted(select(structure, "residue A/24 and not element H"))
coordinates = positions(structure)[np.asarray(indices, dtype=int)]
centre = centroid(coordinates)
plane = best_fit_plane(coordinates)