Geometry Conventions
This document describes the mathematical conventions used in copick for representing spatial data, including point positions, orientations, volumetric data, and meshes. Understanding these conventions is essential for correctly interpreting data, implementing new tools, and ensuring interoperability with other cryo-ET software packages.
Overview
Cryo-electron tomography (cryo-ET) data involves multiple coordinate systems and representations: physical coordinates in Angstroms, voxel indices in 3D arrays, and transformation matrices describing particle orientations. Different software packages in the cryo-ET ecosystem use varying conventions for these representations, which can lead to confusion and errors when exchanging data.
Copick adopts a set of conventions designed to be internally consistent and to facilitate conversion to and from other common formats (RELION, Dynamo, TOM/Artiatomi). This document provides a rigorous mathematical description of these conventions.
1. Coordinate System
1.1 Physical Coordinates
All spatial positions in copick are expressed in physical coordinates with the following properties:
| Property | Value |
|---|---|
| Units | Angstrom (Å) |
| Origin | Corner of the tomogram volume (0, 0, 0) |
| Indexing | 0-indexed |
| Handedness | Right-handed |
A point in physical space is represented as a 3-vector:
where \(x\), \(y\), and \(z\) are distances in Angstrom measured from the corner of the tomogram volume along each respective axis.
1.2 Voxel Coordinates
Voxel coordinates are integer indices into a 3D array. The relationship between voxel and physical coordinates is mediated by the voxel spacing \(s\) (in Å/voxel):
where the floor operation is used when converting continuous physical coordinates to discrete voxel indices.
2. Pick Geometry
Picks represent point annotations in a tomogram, typically marking the locations and orientations of particles or other structures of interest.
2.1 Position
Pick positions are stored as CopickLocation(x, y, z) objects containing physical coordinates in Angstrom. The position
represents the center of the picked object in tomogram space.
2.2 Orientation (Transformation Matrix)
Each pick has an associated 4×4 homogeneous affine transformation matrix \(\mathbf{T}\) that describes the orientation of the particle. This matrix transforms coordinates from object space to tomogram space:
where:
- \(\mathbf{R} = (r_{ij})_{i,j \in \{0,1,2\}}\) is a 3×3 rotation matrix in SO(3)
- \(\mathbf{t} = (t_x, t_y, t_z)^T\) is the translation component in Angstrom
Interpretation
The transformation matrix answers the question: "If I have a point defined in the particle's local coordinate frame, where does it appear in the tomogram?"
For a point \(\mathbf{p}_\text{obj}\) in object space, the corresponding point in tomogram space is:
In homogeneous coordinates:
Constraints
The transformation matrix must satisfy:
- The bottom row must be \((0, 0, 0, 1)\)
- The element \(\mathbf{T}_{3,3} = 1\)
- The rotation submatrix \(\mathbf{R}\) should be orthonormal (i.e., \(\mathbf{R}^T \mathbf{R} = \mathbf{I}\) and \(\det(\mathbf{R}) = 1\))
Default Value
For picks without orientation information, the identity matrix is used:
2.3 Relationship Between Position and Transform
The pick's location field stores the position of the particle center in tomogram coordinates. The transformation
matrix describes the particle's orientation and may contain an additional translation component (e.g., for refined
shifts during subtomogram averaging).
The full position of the particle center, including any refinement shifts, is:
where \(\mathbf{t}_\text{transform} = (t_x, t_y, t_z)^T\) is extracted from the transformation matrix.
CopickPicks.full_positions() returns these centres; use it, not the locations returned by CopickPicks.numpy(),
wherever a particle is placed, drawn or extracted.
2.4 Filament Frames
Objects declared as filaments (see Pickable Object) use the point fields with these conventions:
instance_idis the filament ID. IDs start at 1; 0 means the point is not assigned to a filament.- Points are grouped by filament and stored in order along it.
- The +Z axis of the transform's rotation, \(\mathbf{R}\,\hat{\mathbf{z}}\), is the local filament axis (the tangent), pointing in the direction of increasing point order. The rotation about the axis (roll) is arbitrary unless a tool documents otherwise.
- The transform's translation is 0; the position along the axis is the
location. - The point order follows the structure's polarity only where the producer states it (a filament's
polarity_known, see Filaments): minus to plus end for microtubules, pointed to barbed end for actin. Otherwise the direction along the filament is unknown.
3. Volume Geometry (Tomograms and Segmentations)
Volumetric data in copick includes tomograms (3D reconstructions) and segmentations (labeled volumes).
3.1 Array Axis Ordering
Volumes are stored in ZYX axis order, following the C-contiguous (row-major) convention standard in Python/NumPy:
For a volume with dimensions \((N_z, N_y, N_x)\):
- The first axis (index 0) corresponds to the Z dimension
- The second axis (index 1) corresponds to the Y dimension
- The third axis (index 2) corresponds to the X dimension
This ordering is reflected in the OME-Zarr metadata, which specifies axes as ["z", "y", "x"] with units in Angstrom.
3.2 Voxel-to-Physical Coordinate Mapping
For a voxel at array index \((i_z, i_y, i_x)\), the physical coordinates are:
where \(s\) is the isotropic voxel spacing in Å/voxel.
Axis Order Mismatch
Note the difference between array indexing order [z, y, x] and physical coordinate order (x, y, z). This is a
common source of bugs when converting between representations.
3.3 OME-Zarr Scale Transform
The OME-Zarr format stores coordinate transforms as part of the metadata. For copick volumes, the scale transform is:
This transform maps voxel indices to physical coordinates:
where the vectors follow the ZYX ordering convention.
3.4 Multiscale Pyramids
Tomograms and segmentations are stored as multiscale pyramids with successive 2× downsampling. The available resolution levels are typically:
| Level | Scale Factor | Voxel Spacing |
|---|---|---|
"0" |
1× | \(s\) |
"1" |
2× | \(2s\) |
"2" |
4× | \(4s\) |
For a voxel at index \(\mathbf{i}\) in level \(n\), the corresponding index in level \(0\) is approximately:
4. Mesh Geometry
Meshes in copick represent surface annotations, typically for structures like membranes, organelles, or sample boundaries.
4.1 Vertex Coordinates
Mesh vertices are stored in physical coordinates (Angstrom), consistent with pick positions:
The coordinate system matches that of picks and tomograms: corner-origin, 0-indexed, in Angstrom.
4.2 Storage Format
Meshes are stored in GLB format (binary glTF), which is a widely-supported 3D format that efficiently stores vertices, faces, and optional attributes like normals and colors.
4.3 Mesh-Volume Correspondence
To find the voxel containing a mesh vertex:
To sample the volume value at a vertex position (with interpolation), use the continuous voxel coordinates:
5. Euler Angle Conventions for Import/Export
When exchanging data with other cryo-ET software, coordinate and rotation conventions must be carefully converted. Copick stores rotations as 3×3 matrices, but other formats often use Euler angles.
5.1 Convention Summary
| Format | Euler Convention | Rotation Type | Notes |
|---|---|---|---|
| RELION | ZYZ | Extrinsic, inverted | Uses rlnAngleRot, rlnAngleTilt, rlnAnglePsi |
| Dynamo | ZXZ | Intrinsic, inverted | Uses tdrot, tilt, narot |
| TOM/Artiatomi | ZXZ | Intrinsic | Uses \(\phi\), \(\theta\), \(\psi\) (stored as \(\phi\), \(\psi\), \(\theta\) in file) |
| Copick (native) | Matrix | N/A | Full 4×4 transformation matrix |
5.2 Conversion Formulas
RELION to Copick
Given RELION Euler angles \((\phi, \theta, \psi)\) in ZYZ convention:
where \(R_z\) and \(R_y\) are elementary rotation matrices about the Z and Y axes, respectively.
RELION 4/5 tomography particles may also carry a subtomogram orientation (rlnTomoSubtomogramRot/Tilt/Psi) and
shifts (rlnOriginX/Y/ZAngst). As in RELION's ParticleSet, with \(\mathbf{A}_\text{sub}\) and
\(\mathbf{A}_\text{particle}\) the matrices of the two angle triples (each converted as above):
where \(\mathbf{o}\) is the origin shift in Angstrom. Copick stores the shifted position as the location and leaves the transform's translation at zero. On export, the location plus the translation is written, with no origin shift.
RELION filament particles
RELION's filament convention (get_particle_poses/filaments.py, relion_tomo_import_coordinates) stores the
filament frame in the subtomogram orientation, pre-rotated by \(R_y(90°)\), and fixes the particle angles at
(0, 90, 0) with priors rlnAngleTiltPrior = 90 and rlnAnglePsiPrior = 0:
where \(\mathbf{R}\) is copick's rotation, whose +Z axis is the filament axis (see 2.4 Filament Frames). Copick writes
this convention for picks of filament objects (copick export picks --filament-columns), together with
rlnHelicalTubeID (the instance ID), rlnHelicalTrackLengthAngst (Angstrom along the filament in point order) and
rlnAnglePsiFlipRatio: 0 (an ordinary psi prior) where the filament's polarity_known says the point order follows
its polarity, 0.5 (a bimodal prior, so that refinement may flip the direction) elsewhere. The column is always
written, because RELION reads a missing one as 0.5. On import, rlnHelicalTubeID becomes the instance ID and rows
are ordered by tube and track length.
Picks whose rotation is a registered pose rather than a filament frame (e.g. subunits registered to a lattice) can be
written with --filament-angles pose (filament_angles="pose"): each pick's rotation goes into
rlnAngleRot/Tilt/Psi exactly as for a particle without filament columns, and no subtomogram orientation and no angle
priors are written. rlnHelicalTubeID, rlnHelicalTrackLengthAngst and rlnAnglePsiFlipRatio are written as above.
Without filament columns, pose changes nothing.
Neighboring particles of one filament overlap, so a refinement that splits its half sets per particle puts the same
density in both halves and overestimates the resolution. RELION keeps the half sets particles already carry in
rlnRandomSubset, and --half-sets filament (half_sets="filament") writes them by whole filament. A filament is a
(rlnTomoName, rlnHelicalTubeID) pair, so one file may hold many tomograms. The halves are balanced greedily:
filaments are taken by descending particle count (then by tomogram name and tube ID), and each goes to the half with
fewer particles so far, half 1 on a tie. A combined export balances over all its runs; a per-run export balances each
file on its own. Half sets by filament need filament columns.
Dynamo to Copick
Given Dynamo Euler angles \((t_\text{drot}, t_\text{ilt}, n_\text{arot})\) in ZXZ convention:
Note: Lowercase convention letters (e.g., zxz) indicate intrinsic rotations in scipy.
TOM/Artiatomi to Copick
Given TOM Euler angles \((\phi, \theta, \psi)\) in ZXZ convention:
No inversion is applied for the TOM format.
5.3 Position Convention Summary
| Format | Position Units | Origin | Indexing |
|---|---|---|---|
| Copick (native) | Angstrom | Corner | 0-indexed |
| Dynamo | Pixels | Corner | 0-indexed |
| TOM/Artiatomi | Pixels | Corner | 1-indexed (converted on read) |
| RELION | Pixels or Angstrom | Centered or Corner | 0-indexed |
| CSV | Angstrom | Corner | 0-indexed |
RELION coordinates
RELION 4/5 tomography files give a particle's position as rlnCenteredCoordinateX/Y/ZAngst (Angstrom from the
tomogram centre) and/or rlnCoordinateX/Y/Z (pixels of the unbinned tilt series, from the corner). The tomogram
centre is rlnTomoSizeX/Y/Z / 2 * rlnTomoTiltSeriesPixelSize from tomograms.star; the reconstruction binning
does not enter it. On import copick uses, in order:
- centred coordinates, when the tomogram's centre is known (from a
tomograms.star, or the copick tomogram); rlnCoordinateX/Y/Ztimes the tilt-series pixel size (given explicitly, from the file's optics tablerlnTomoTiltSeriesPixelSize, or fromtomograms.star);rlnCoordinateX/Y/Ztimes the given voxel size, for files whose coordinates are tomogram pixels (older tools, earlier copick versions), with a warning.
On export copick writes rlnTomoName, centred coordinates whenever the tomogram centre is known and, when the
tilt-series pixel size is known, rlnCoordinateX/Y/Z in tilt-series pixels together with the optics table
(rlnTomoTiltSeriesPixelSize) that RELION requires, one optics group per run. Without a tilt-series pixel size no
optics table is written, and RELION builds one from tomograms.star. The center comes from tomograms.star, from the
caller (tomogram_centers), or from the shape of the copick tomogram (of --tomo-type, if given), in that order.
With --coordinates centered, only centered coordinates are written, and a run without a center is an error rather
than a fallback to pixel coordinates. --star-layout import (copick.ops.export.export_relion_particles(layout="import")) writes
the input of RELION's tomography Import Coordinates job instead of one particle file: an index
(data_coordinate_files with rlnTomoName and rlnTomoImportParticleFile) naming one coordinate file per run,
each with the same columns and no optics table.
Shifts in EM and Dynamo files
Dynamo table shifts (dx, dy, dz) and TOM motivelist shifts (rows 11-13) in pixels become the transform's
translation in Angstrom, so the particle centre is the location plus the shift; export writes the translation back as
shifts.
6. Summary and Quick Reference
Key Points
-
All spatial data uses Angstrom units - Positions, mesh vertices, and transformation translations are all in Angstrom.
-
Corner-origin, 0-indexed - The coordinate origin is at the corner of the tomogram, and indices start at 0.
-
Volumes use ZYX ordering - Array indexing is
[z, y, x], but physical coordinates are(x, y, z). -
Transformations go from object to tomogram space - The transformation matrix \(\mathbf{T}\) maps points in the particle's local frame to the tomogram coordinate system.
-
Voxel spacing is isotropic - Copick assumes equal spacing in all three dimensions.
Common Conversions
| From | To | Formula |
|---|---|---|
| Physical (Å) | Voxel | \(\mathbf{p}_\text{voxel} = \lfloor \mathbf{p}_\text{Å} / s \rfloor\) |
| Voxel | Physical (Å) | \(\mathbf{p}_\text{Å} = \mathbf{p}_\text{voxel} \cdot s\) |
| Object space | Tomogram space | \(\mathbf{p}_\text{tomo} = \mathbf{T} \cdot \mathbf{p}_\text{obj}\) |
Array index [z,y,x] |
Physical (x,y,z) |
\((x, y, z) = (i_x \cdot s, i_y \cdot s, i_z \cdot s)\) |