Modeling Cryo-EM using tomosipo
Jul 21, 2020

Cryo-EM is a technique where particles are frozen (“cryo”) in a solid and imaged using a electron microscope (EM). The particles are in random locations and in random orientation, both of which are unknown. In addition, it is not really known what the particle looks like. In contrast to other tomographic techniques, the sample is not rotated: a single picture is taken. Still, people have managed to determine the structure of viruses and other micro-particles using this technique, leading to a Nobel prize in 2017.

Here is how to model the geometry in tomosipo, given that you do know the locations and orientations of your particles:

import numpy as np
import tomosipo as ts
from tomosipo.qt import animate

N = 100
vg = ts.volume().to_vec()
# A detector (usually a parallel beam detector, but a cone-beam detector looks
# nicer in the animations)
flip180 = ts.rotate(pos=0, axis=(1, 0, 0), deg=180)
pg = flip180 * ts.cone(size=20, src_orig_dist=10, src_det_dist=20).to_vec()

# Rotate into a uniformly random orientation:
Rs = [
ts.rotate(pos=0, axis=np.random.normal(size=3), rad=np.random.uniform(0, 2 * np.pi))
for _ in range(N)
]

# Move to a random location:
Ts = [
ts.translate(np.random.uniform(-5, 5, size=3) * np.array([1, 0, 1]))
for _ in range(N)
]

# Scale geometries to fit in video:
visual_S = ts.scale(1 / 3)

# View geometry
animate(
*[visual_S * T * R * vg for (T, R) in zip(Ts, Rs)],
visual_S * pg
)


Each randomly oriented box is a particle. You could also look at them one by one:

T = ts.concatenate([T * R for (T, R) in zip(Ts, Rs)])
animate(
visual_S * T * vg,
visual_S * pg
)


Or, if you consider each particle to be the same, then you could view the same geometry from the perspective of the particle, yielding:

P = ts.from_perspective(box=T * vg)
animate(
visual_S * P * T * vg,
visual_S * P * pg
)


Apart from checking if you are prone to epileptic seizures, these animations might be useful for illustrating how a Cryo-EM reconstruction is obtained.

Thanks to Francien Bossema for feedback that clarified this post and to Dirk Schut for finding a typo!