Ab-initio Pipeline Demonstration

This tutorial demonstrates some key components of an ab-initio reconstruction pipeline using synthetic data generated with ASPIRE’s Simulation class of objects.

Download an Example Volume

We begin by downloading a high resolution volume map of the 80S Ribosome, sourced from EMDB: https://www.ebi.ac.uk/emdb/EMD-2660. This is one of several volume maps that can be downloaded with ASPIRE’s data downloading utility by using the following import. sphinx_gallery_start_ignore flake8: noqa sphinx_gallery_end_ignore

from aspire.downloader import emdb_2660

# Load 80s Ribosome as a ``Volume`` object.
original_vol = emdb_2660()

# Downsample the volume
res = 41
vol = original_vol.downsample(res)

Note

A Volume can be saved using the Volume.save() method as follows:

fn = f"downsampled_80s_ribosome_size{res}.mrc"
vol.save(fn, overwrite=True)

Create a Simulation Source

ASPIRE’s Simulation class can be used to generate a synthetic dataset of projection images. A Simulation object produces random projections of a supplied Volume and applies noise and CTF filters. The resulting stack of 2D images is stored in an Image object.

CTF Filters

Let’s start by creating CTF filters. The operators package contains a collection of filter classes that can be supplied to a Simulation. We use RadialCTFFilter to generate a set of CTF filters with various defocus values.

# Create CTF filters
import numpy as np

from aspire.operators import RadialCTFFilter

# Radial CTF Filter
defocus_min = 15000  # unit is angstroms
defocus_max = 25000
defocus_ct = 7

ctf_filters = [
    RadialCTFFilter(pixel_size=vol.pixel_size, defocus=d)
    for d in np.linspace(defocus_min, defocus_max, defocus_ct)
]

Initialize Simulation Object

We feed our Volume and filters into Simulation to generate the dataset of images. When controlled white Gaussian noise is desired, WhiteNoiseAdder.from_snr() can be used to generate a simulation data set around a specific SNR.

Alternatively, users can bring their own images using an ArrayImageSource, or define their own custom noise functions via Simulation(..., noise_adder=CustomNoiseAdder(...)). Examples can be found in tutorials/class_averaging.py and experiments/simulated_abinitio_pipeline.py.

from aspire.noise import WhiteNoiseAdder
from aspire.source import Simulation

# set parameters
n_imgs = 2500

# SNR target for white gaussian noise.
snr = 0.5

Note

Note, the SNR value was chosen based on other parameters for this quick tutorial, and can be changed to adjust the power of the additive noise.

# For this ``Simulation`` we set all 2D offset vectors to zero,
# but by default offset vectors will be randomly distributed.
src = Simulation(
    n=n_imgs,  # number of projections
    vols=vol,  # volume source
    offsets=0,  # Default: images are randomly shifted
    unique_filters=ctf_filters,
    noise_adder=WhiteNoiseAdder.from_snr(snr=snr),  # desired SNR
)
  0%|          | 0/5 [00:00<?, ?it/s]
 20%|██        | 1/5 [00:00<00:00,  4.97it/s]
 40%|████      | 2/5 [00:00<00:00,  5.05it/s]
 60%|██████    | 3/5 [00:00<00:00,  5.06it/s]
 80%|████████  | 4/5 [00:00<00:00,  5.03it/s]
100%|██████████| 5/5 [00:00<00:00,  5.26it/s]
100%|██████████| 5/5 [00:00<00:00,  5.15it/s]

Several Views of the Projection Images

We can access several views of the projection images.

# with no corruption applied
src.projections[0:10].show()
pipeline demo
# with no noise corruption
src.clean_images[0:10].show()
pipeline demo
# with noise and CTF corruption
src.images[0:10].show()
pipeline demo

CTF Correction

We apply phase_flip() to correct for CTF effects.

src = src.phase_flip()

Cache

We apply cache to store the results of the ImageSource pipeline up to this point. This is optional, but can provide benefit when used intently on machines with adequate memory.

src = src.cache()
src.images[0:10].show()
pipeline demo
  0%|          | 0/5 [00:00<?, ?it/s]
 20%|██        | 1/5 [00:01<00:04,  1.20s/it]
 40%|████      | 2/5 [00:02<00:03,  1.20s/it]
 60%|██████    | 3/5 [00:03<00:02,  1.22s/it]
 80%|████████  | 4/5 [00:04<00:01,  1.21s/it]
100%|██████████| 5/5 [00:05<00:00,  1.16s/it]
100%|██████████| 5/5 [00:05<00:00,  1.18s/it]

Class Averaging

We use RIRClass2D object to classify the images via the rotationally invariant representation (RIR) algorithm. Class selection is customizable. The classification module also includes a set of protocols for selecting a set of images to be used after classification. Here we’re using the simplest DebugClassAvgSource which internally uses the TopClassSelector to select the first n_classes images from the source. In practice, the selection is done by sorting class averages based on some configurable notion of quality (contrast, neighbor distance etc).

from aspire.classification import RIRClass2D

# set parameters
n_classes = 200
n_nbor = 6

# We will customize our class averaging source. Note that the
# ``fspca_components`` and ``bispectrum_components`` were selected for
# this small tutorial.
rir = RIRClass2D(
    src,
    fspca_components=40,
    bispectrum_components=30,
    n_nbor=n_nbor,
)

from aspire.denoising import DebugClassAvgSource

avgs = DebugClassAvgSource(
    src=src,
    classifier=rir,
)

# We'll continue our pipeline using only the first ``n_classes`` from
# ``avgs``.  The ``cache()`` call is used here to precompute results
# for the ``:n_classes`` slice.  This avoids recomputing the same
# images twice when peeking in the next cell then requesting them in
# the following ``CLSyncVoting`` algorithm.  Outside of demonstration
# purposes, where we are repeatedly peeking at various stage results,
# such caching can be dropped allowing for more lazy evaluation.
avgs = avgs[:n_classes].cache()
  0%|          | 0/1 [00:00<?, ?it/s]

  0%|          | 0/5 [00:00<?, ?it/s]
100%|██████████| 5/5 [00:00<00:00, 820.77it/s]


  0%|          | 0/5 [00:00<?, ?it/s]

 20%|██        | 1/5 [00:00<00:01,  3.55it/s]

 40%|████      | 2/5 [00:00<00:00,  3.64it/s]

 60%|██████    | 3/5 [00:00<00:00,  3.69it/s]

 80%|████████  | 4/5 [00:01<00:00,  3.69it/s]

100%|██████████| 5/5 [00:01<00:00,  3.87it/s]
100%|██████████| 5/5 [00:01<00:00,  3.77it/s]


  0%|          | 0/200 [00:00<?, ?it/s]

  1%|          | 2/200 [00:00<00:15, 12.67it/s]

  2%|▏         | 4/200 [00:00<00:15, 12.67it/s]

  3%|▎         | 6/200 [00:00<00:15, 12.68it/s]

  4%|▍         | 8/200 [00:00<00:15, 12.71it/s]

  5%|▌         | 10/200 [00:00<00:15, 12.66it/s]

  6%|▌         | 12/200 [00:00<00:14, 12.64it/s]

  7%|▋         | 14/200 [00:01<00:14, 12.64it/s]

  8%|▊         | 16/200 [00:01<00:14, 12.65it/s]

  9%|▉         | 18/200 [00:01<00:14, 12.64it/s]

 10%|█         | 20/200 [00:01<00:14, 12.56it/s]

 11%|█         | 22/200 [00:01<00:14, 12.59it/s]

 12%|█▏        | 24/200 [00:01<00:13, 12.63it/s]

 13%|█▎        | 26/200 [00:02<00:13, 12.62it/s]

 14%|█▍        | 28/200 [00:02<00:13, 12.61it/s]

 15%|█▌        | 30/200 [00:02<00:13, 12.64it/s]

 16%|█▌        | 32/200 [00:02<00:13, 12.60it/s]

 17%|█▋        | 34/200 [00:02<00:13, 12.59it/s]

 18%|█▊        | 36/200 [00:02<00:13, 12.60it/s]

 19%|█▉        | 38/200 [00:03<00:12, 12.58it/s]

 20%|██        | 40/200 [00:03<00:13, 12.26it/s]

 21%|██        | 42/200 [00:03<00:12, 12.36it/s]

 22%|██▏       | 44/200 [00:03<00:12, 12.39it/s]

 23%|██▎       | 46/200 [00:03<00:12, 12.46it/s]

 24%|██▍       | 48/200 [00:03<00:12, 12.54it/s]

 25%|██▌       | 50/200 [00:03<00:11, 12.61it/s]

 26%|██▌       | 52/200 [00:04<00:11, 12.63it/s]

 27%|██▋       | 54/200 [00:04<00:11, 12.65it/s]

 28%|██▊       | 56/200 [00:04<00:11, 12.62it/s]

 29%|██▉       | 58/200 [00:04<00:11, 12.58it/s]

 30%|███       | 60/200 [00:04<00:11, 12.22it/s]

 31%|███       | 62/200 [00:04<00:11, 12.33it/s]

 32%|███▏      | 64/200 [00:05<00:10, 12.36it/s]

 33%|███▎      | 66/200 [00:05<00:10, 12.40it/s]

 34%|███▍      | 68/200 [00:05<00:10, 12.42it/s]

 35%|███▌      | 70/200 [00:05<00:10, 12.42it/s]

 36%|███▌      | 72/200 [00:05<00:10, 12.35it/s]

 37%|███▋      | 74/200 [00:05<00:10, 11.99it/s]

 38%|███▊      | 76/200 [00:06<00:10, 12.13it/s]

 39%|███▉      | 78/200 [00:06<00:10, 12.16it/s]

 40%|████      | 80/200 [00:06<00:09, 12.26it/s]

 41%|████      | 82/200 [00:06<00:09, 12.18it/s]

 42%|████▏     | 84/200 [00:06<00:09, 12.34it/s]

 43%|████▎     | 86/200 [00:06<00:09, 12.28it/s]

 44%|████▍     | 88/200 [00:07<00:09, 12.41it/s]

 45%|████▌     | 90/200 [00:07<00:08, 12.47it/s]

 46%|████▌     | 92/200 [00:07<00:08, 12.50it/s]

 47%|████▋     | 94/200 [00:07<00:08, 12.56it/s]

 48%|████▊     | 96/200 [00:07<00:08, 12.56it/s]

 49%|████▉     | 98/200 [00:07<00:08, 12.59it/s]

 50%|█████     | 100/200 [00:08<00:07, 12.59it/s]

 51%|█████     | 102/200 [00:08<00:07, 12.61it/s]

 52%|█████▏    | 104/200 [00:08<00:07, 12.64it/s]

 53%|█████▎    | 106/200 [00:08<00:07, 12.63it/s]

 54%|█████▍    | 108/200 [00:08<00:07, 12.63it/s]

 55%|█████▌    | 110/200 [00:08<00:07, 12.68it/s]

 56%|█████▌    | 112/200 [00:08<00:06, 12.65it/s]

 57%|█████▋    | 114/200 [00:09<00:06, 12.58it/s]

 58%|█████▊    | 116/200 [00:09<00:06, 12.50it/s]

 59%|█████▉    | 118/200 [00:09<00:06, 12.44it/s]

 60%|██████    | 120/200 [00:09<00:06, 12.44it/s]

 61%|██████    | 122/200 [00:09<00:06, 12.49it/s]

 62%|██████▏   | 124/200 [00:09<00:06, 12.44it/s]

 63%|██████▎   | 126/200 [00:10<00:05, 12.48it/s]

 64%|██████▍   | 128/200 [00:10<00:05, 12.50it/s]

 65%|██████▌   | 130/200 [00:10<00:05, 12.51it/s]

 66%|██████▌   | 132/200 [00:10<00:05, 12.52it/s]

 67%|██████▋   | 134/200 [00:10<00:05, 12.53it/s]

 68%|██████▊   | 136/200 [00:10<00:05, 12.41it/s]

 69%|██████▉   | 138/200 [00:11<00:04, 12.47it/s]

 70%|███████   | 140/200 [00:11<00:04, 12.51it/s]

 71%|███████   | 142/200 [00:11<00:04, 12.52it/s]

 72%|███████▏  | 144/200 [00:11<00:04, 12.53it/s]

 73%|███████▎  | 146/200 [00:11<00:04, 12.52it/s]

 74%|███████▍  | 148/200 [00:11<00:04, 12.51it/s]

 75%|███████▌  | 150/200 [00:12<00:03, 12.52it/s]

 76%|███████▌  | 152/200 [00:12<00:03, 12.53it/s]

 77%|███████▋  | 154/200 [00:12<00:03, 12.56it/s]

 78%|███████▊  | 156/200 [00:12<00:03, 12.57it/s]

 79%|███████▉  | 158/200 [00:12<00:03, 12.56it/s]

 80%|████████  | 160/200 [00:12<00:03, 12.37it/s]

 81%|████████  | 162/200 [00:12<00:03, 12.41it/s]

 82%|████████▏ | 164/200 [00:13<00:02, 12.42it/s]

 83%|████████▎ | 166/200 [00:13<00:02, 12.44it/s]

 84%|████████▍ | 168/200 [00:13<00:02, 12.49it/s]

 85%|████████▌ | 170/200 [00:13<00:02, 12.49it/s]

 86%|████████▌ | 172/200 [00:13<00:02, 12.47it/s]

 87%|████████▋ | 174/200 [00:13<00:02, 12.47it/s]

 88%|████████▊ | 176/200 [00:14<00:01, 12.41it/s]

 89%|████████▉ | 178/200 [00:14<00:01, 12.44it/s]

 90%|█████████ | 180/200 [00:14<00:01, 12.48it/s]

 91%|█████████ | 182/200 [00:14<00:01, 12.51it/s]

 92%|█████████▏| 184/200 [00:14<00:01, 12.55it/s]

 93%|█████████▎| 186/200 [00:14<00:01, 12.40it/s]

 94%|█████████▍| 188/200 [00:15<00:00, 12.42it/s]

 95%|█████████▌| 190/200 [00:15<00:00, 12.45it/s]

 96%|█████████▌| 192/200 [00:15<00:00, 12.50it/s]

 97%|█████████▋| 194/200 [00:15<00:00, 12.49it/s]

 98%|█████████▊| 196/200 [00:15<00:00, 12.48it/s]

 99%|█████████▉| 198/200 [00:15<00:00, 12.44it/s]

100%|██████████| 200/200 [00:16<00:00, 12.47it/s]
100%|██████████| 200/200 [00:16<00:00, 12.49it/s]


  0%|          | 0/200 [00:00<?, ?it/s]

 10%|▉         | 19/200 [00:00<00:00, 185.98it/s]

 19%|█▉        | 38/200 [00:00<00:00, 185.44it/s]

 28%|██▊       | 57/200 [00:00<00:00, 186.73it/s]

 38%|███▊      | 76/200 [00:00<00:00, 186.06it/s]

 48%|████▊     | 95/200 [00:00<00:00, 185.74it/s]

 57%|█████▋    | 114/200 [00:00<00:00, 186.50it/s]

 66%|██████▋   | 133/200 [00:00<00:00, 186.93it/s]

 76%|███████▌  | 152/200 [00:00<00:00, 182.80it/s]

 86%|████████▌ | 172/200 [00:00<00:00, 185.15it/s]

 96%|█████████▌| 191/200 [00:01<00:00, 185.72it/s]
100%|██████████| 200/200 [00:01<00:00, 185.45it/s]

100%|██████████| 1/1 [00:24<00:00, 24.05s/it]
100%|██████████| 1/1 [00:24<00:00, 24.05s/it]

View the Class Averages

# Show class averages
avgs.images[0:10].show()
pipeline demo
# Show original images corresponding to those classes. This 1:1
# comparison is only expected to work because we used
# ``TopClassSelector`` to classify our images.
src.images[0:10].show()
pipeline demo

Orientation Estimation

We create an OrientedSource, which consumes an ImageSource object, an orientation estimator, and returns a new source which lazily estimates orientations. In this case we supply avgs for our source and a CLSyncVoting class instance for our orientation estimator. The CLSyncVoting algorithm employs a common-lines method with synchronization and voting.

from aspire.abinitio import CLSyncVoting
from aspire.source import OrientedSource

# Stash true rotations for later comparison
true_rotations = src.rotations[:n_classes]

# For this low resolution example we will customize the ``CLSyncVoting``
# instance to use fewer theta points ``n_theta`` then the default value of 360.
orient_est = CLSyncVoting(avgs, n_theta=72)

# Instantiate an ``OrientedSource``.
oriented_src = OrientedSource(avgs, orient_est)

Mean Error of Estimated Rotations

ASPIRE has the built-in utility function, mean_aligned_angular_distance, which globally aligns the estimated rotations to the true rotations and computes the mean angular distance (in degrees).

from aspire.utils import mean_aligned_angular_distance

# Compare with known true rotations
mean_ang_dist = mean_aligned_angular_distance(oriented_src.rotations, true_rotations)
print(f"Mean aligned angular distance: {mean_ang_dist} degrees")
Searching over common line pairs:   0%|          | 0/19900 [00:00<?, ?it/s]
Searching over common line pairs:   1%|▏         | 275/19900 [00:00<00:07, 2747.78it/s]
Searching over common line pairs:   3%|▎         | 568/19900 [00:00<00:06, 2853.69it/s]
Searching over common line pairs:   4%|▍         | 859/19900 [00:00<00:06, 2876.28it/s]
Searching over common line pairs:   6%|▌         | 1151/19900 [00:00<00:06, 2890.22it/s]
Searching over common line pairs:   7%|▋         | 1442/19900 [00:00<00:06, 2894.81it/s]
Searching over common line pairs:   9%|▊         | 1735/19900 [00:00<00:06, 2903.43it/s]
Searching over common line pairs:  10%|█         | 2027/19900 [00:00<00:06, 2908.66it/s]
Searching over common line pairs:  12%|█▏        | 2319/19900 [00:00<00:06, 2911.99it/s]
Searching over common line pairs:  13%|█▎        | 2611/19900 [00:00<00:05, 2912.90it/s]
Searching over common line pairs:  15%|█▍        | 2903/19900 [00:01<00:05, 2911.09it/s]
Searching over common line pairs:  16%|█▌        | 3195/19900 [00:01<00:05, 2911.27it/s]
Searching over common line pairs:  18%|█▊        | 3487/19900 [00:01<00:05, 2911.54it/s]
Searching over common line pairs:  19%|█▉        | 3779/19900 [00:01<00:05, 2913.67it/s]
Searching over common line pairs:  20%|██        | 4071/19900 [00:01<00:05, 2913.38it/s]
Searching over common line pairs:  22%|██▏       | 4363/19900 [00:01<00:05, 2910.55it/s]
Searching over common line pairs:  23%|██▎       | 4656/19900 [00:01<00:05, 2913.42it/s]
Searching over common line pairs:  25%|██▍       | 4948/19900 [00:01<00:05, 2907.12it/s]
Searching over common line pairs:  26%|██▋       | 5239/19900 [00:01<00:05, 2903.72it/s]
Searching over common line pairs:  28%|██▊       | 5530/19900 [00:01<00:04, 2902.09it/s]
Searching over common line pairs:  29%|██▉       | 5821/19900 [00:02<00:04, 2900.56it/s]
Searching over common line pairs:  31%|███       | 6112/19900 [00:02<00:04, 2889.52it/s]
Searching over common line pairs:  32%|███▏      | 6401/19900 [00:02<00:04, 2877.12it/s]
Searching over common line pairs:  34%|███▎      | 6692/19900 [00:02<00:04, 2886.62it/s]
Searching over common line pairs:  35%|███▌      | 6983/19900 [00:02<00:04, 2891.00it/s]
Searching over common line pairs:  37%|███▋      | 7273/19900 [00:02<00:04, 2891.71it/s]
Searching over common line pairs:  38%|███▊      | 7564/19900 [00:02<00:04, 2896.30it/s]
Searching over common line pairs:  39%|███▉      | 7856/19900 [00:02<00:04, 2901.97it/s]
Searching over common line pairs:  41%|████      | 8147/19900 [00:02<00:04, 2904.02it/s]
Searching over common line pairs:  42%|████▏     | 8439/19900 [00:02<00:03, 2908.08it/s]
Searching over common line pairs:  44%|████▍     | 8731/19900 [00:03<00:03, 2908.87it/s]
Searching over common line pairs:  45%|████▌     | 9023/19900 [00:03<00:03, 2910.33it/s]
Searching over common line pairs:  47%|████▋     | 9315/19900 [00:03<00:03, 2912.92it/s]
Searching over common line pairs:  48%|████▊     | 9607/19900 [00:03<00:03, 2912.84it/s]
Searching over common line pairs:  50%|████▉     | 9899/19900 [00:03<00:03, 2911.53it/s]
Searching over common line pairs:  51%|█████     | 10191/19900 [00:03<00:03, 2907.37it/s]
Searching over common line pairs:  53%|█████▎    | 10482/19900 [00:03<00:03, 2901.82it/s]
Searching over common line pairs:  54%|█████▍    | 10773/19900 [00:03<00:03, 2903.29it/s]
Searching over common line pairs:  56%|█████▌    | 11065/19900 [00:03<00:03, 2905.93it/s]
Searching over common line pairs:  57%|█████▋    | 11357/19900 [00:03<00:02, 2909.15it/s]
Searching over common line pairs:  59%|█████▊    | 11648/19900 [00:04<00:02, 2906.40it/s]
Searching over common line pairs:  60%|█████▉    | 11939/19900 [00:04<00:02, 2907.43it/s]
Searching over common line pairs:  61%|██████▏   | 12230/19900 [00:04<00:02, 2906.33it/s]
Searching over common line pairs:  63%|██████▎   | 12521/19900 [00:04<00:02, 2905.44it/s]
Searching over common line pairs:  64%|██████▍   | 12813/19900 [00:04<00:02, 2907.98it/s]
Searching over common line pairs:  66%|██████▌   | 13104/19900 [00:04<00:02, 2906.86it/s]
Searching over common line pairs:  67%|██████▋   | 13395/19900 [00:04<00:02, 2905.81it/s]
Searching over common line pairs:  69%|██████▉   | 13687/19900 [00:04<00:02, 2907.39it/s]
Searching over common line pairs:  70%|███████   | 13979/19900 [00:04<00:02, 2909.41it/s]
Searching over common line pairs:  72%|███████▏  | 14270/19900 [00:04<00:01, 2908.65it/s]
Searching over common line pairs:  73%|███████▎  | 14562/19900 [00:05<00:01, 2910.88it/s]
Searching over common line pairs:  75%|███████▍  | 14854/19900 [00:05<00:01, 2912.69it/s]
Searching over common line pairs:  76%|███████▌  | 15147/19900 [00:05<00:01, 2915.40it/s]
Searching over common line pairs:  78%|███████▊  | 15439/19900 [00:05<00:01, 2914.73it/s]
Searching over common line pairs:  79%|███████▉  | 15731/19900 [00:05<00:01, 2911.20it/s]
Searching over common line pairs:  81%|████████  | 16023/19900 [00:05<00:01, 2907.83it/s]
Searching over common line pairs:  82%|████████▏ | 16314/19900 [00:05<00:01, 2898.03it/s]
Searching over common line pairs:  83%|████████▎ | 16606/19900 [00:05<00:01, 2903.27it/s]
Searching over common line pairs:  85%|████████▍ | 16897/19900 [00:05<00:01, 2894.34it/s]
Searching over common line pairs:  86%|████████▋ | 17190/19900 [00:05<00:00, 2902.68it/s]
Searching over common line pairs:  88%|████████▊ | 17482/19900 [00:06<00:00, 2905.55it/s]
Searching over common line pairs:  89%|████████▉ | 17774/19900 [00:06<00:00, 2909.11it/s]
Searching over common line pairs:  91%|█████████ | 18066/19900 [00:06<00:00, 2911.10it/s]
Searching over common line pairs:  92%|█████████▏| 18358/19900 [00:06<00:00, 2911.26it/s]
Searching over common line pairs:  94%|█████████▎| 18650/19900 [00:06<00:00, 2910.51it/s]
Searching over common line pairs:  95%|█████████▌| 18942/19900 [00:06<00:00, 2908.43it/s]
Searching over common line pairs:  97%|█████████▋| 19234/19900 [00:06<00:00, 2909.88it/s]
Searching over common line pairs:  98%|█████████▊| 19525/19900 [00:06<00:00, 2908.74it/s]
Searching over common line pairs: 100%|█████████▉| 19816/19900 [00:06<00:00, 2907.44it/s]
Searching over common line pairs: 100%|██████████| 19900/19900 [00:06<00:00, 2904.21it/s]

LSQR            Least-squares solution of  Ax = b
The matrix A has 19900 rows and 400 columns
damp = 0.00000000000000e+00   calc_var =        0
atol = 1.00e-06                 conlim = 1.00e+08
btol = 1.00e-06               iter_lim =      800

   Itn      x[0]       r1norm     r2norm   Compatible    LS      Norm A   Cond A
     0  0.00000e+00   7.900e+01  7.900e+01    1.0e+00  4.1e-02
     1 -9.09180e-02   7.372e+01  7.372e+01    9.3e-01  7.6e-02   9.1e+00  1.0e+00
     2 -6.20053e-02   7.347e+01  7.347e+01    9.3e-01  1.5e-02   1.3e+01  2.0e+00
     3 -7.09242e-02   7.345e+01  7.345e+01    9.3e-01  4.6e-03   1.5e+01  3.1e+00
     4 -6.65593e-02   7.345e+01  7.345e+01    9.3e-01  2.2e-03   1.7e+01  4.3e+00
     5 -6.65370e-02   7.345e+01  7.345e+01    9.3e-01  9.2e-04   1.9e+01  5.7e+00
     6 -6.57091e-02   7.345e+01  7.345e+01    9.3e-01  3.0e-04   2.1e+01  6.9e+00
     7 -6.61623e-02   7.345e+01  7.345e+01    9.3e-01  1.1e-04   2.2e+01  8.1e+00
     8 -6.59082e-02   7.345e+01  7.345e+01    9.3e-01  4.6e-05   2.3e+01  9.3e+00
     9 -6.60291e-02   7.345e+01  7.345e+01    9.3e-01  1.9e-05   2.5e+01  1.0e+01
    10 -6.59594e-02   7.345e+01  7.345e+01    9.3e-01  7.7e-06   2.6e+01  1.2e+01
    11 -6.59790e-02   7.345e+01  7.345e+01    9.3e-01  3.5e-06   2.7e+01  1.3e+01
    12 -6.59683e-02   7.345e+01  7.345e+01    9.3e-01  1.3e-06   2.8e+01  1.4e+01
    13 -6.59708e-02   7.345e+01  7.345e+01    9.3e-01  4.4e-07   3.0e+01  1.5e+01

LSQR finished
The least-squares solution is good enough, given atol

istop =       2   r1norm = 7.3e+01   anorm = 3.0e+01   arnorm = 9.6e-04
itn   =      13   r2norm = 7.3e+01   acond = 1.5e+01   xnorm  = 3.4e+00

Mean aligned angular distance: 13.057314471222043 degrees

Volume Reconstruction

Now that we have our class averages and rotation estimates, we can estimate the mean volume by supplying the class averages and basis for back projection.

from aspire.reconstruction import MeanEstimator

# Setup an estimator to perform the back projection.
estimator = MeanEstimator(oriented_src)

# Perform the estimation and save the volume.
estimated_volume = estimator.estimate()

Comparison of Estimated Volume with Source Volume

To get a visual confirmation that our results are sane, we rotate the estimated volume by the estimated rotations and project along the z-axis. These estimated projections should align with the original projection images.

# Get the first 10 projections from the estimated volume using the
# estimated orientations.  Recall that ``project`` returns an
# ``Image`` instance, which we can peek at with ``show``.
projections_est = estimated_volume.project(oriented_src.rotations[0:10])

# We view the first 10 projections of the estimated volume.
projections_est.show()
pipeline demo
# For comparison, we view the first 10 source projections.
src.projections[0:10].show()
pipeline demo

Total running time of the script: (1 minutes 6.861 seconds)

Gallery generated by Sphinx-Gallery