Skip to content

Commit 11c3dca

Browse files
authored
Merge pull request #538 from ComputationalCryoEM/cls_avg_align_refactor_Reddy
Align2D refactor/updates
2 parents 36cc4ec + d51b0ec commit 11c3dca

File tree

19 files changed

+1653
-412
lines changed

19 files changed

+1653
-412
lines changed

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
'gallery_dirs': ['auto_tutorials', 'auto_experiments'], # path to where to save gallery generated output
5050
'download_all_examples': False,
5151
'within_subsection_order': ExampleTitleSortKey,
52-
'filename_pattern': '/*.py',
52+
'filename_pattern': r'/tutorials/.*\.py', # Parse all gallery python files, but only execute tutorials.
5353
}
5454

5555
# Add any paths that contain templates here, relative to this directory.

gallery/experiments/README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Experiments - **COMING SOON**
1+
Experiments
22
=============================
33

44
This gallery will be for demonstrating the functionality of ASPIRE tools using experimental data.
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
"""
2+
Abinitio Pipeline - Experimental Data
3+
=====================================
4+
5+
This notebook introduces a selection of
6+
components corresponding to loading real Relion picked
7+
particle Cryo-EM data and running key ASPIRE-Python
8+
Abinitio model components as a pipeline.
9+
10+
Specifically this pipeline uses the
11+
EMPIAR 10028 picked particles data, available here:
12+
13+
https://www.ebi.ac.uk/empiar/EMPIAR-10028
14+
15+
https://www.ebi.ac.uk/emdb/EMD-10028
16+
"""
17+
18+
# %%
19+
# Imports
20+
# -------
21+
# First import some of the usual suspects.
22+
# In addition, import some classes from
23+
# the ASPIRE package that will be used throughout this experiment.
24+
25+
import logging
26+
27+
import matplotlib.pyplot as plt
28+
import numpy as np
29+
30+
from aspire.abinitio import CLSyncVoting
31+
from aspire.basis import FFBBasis2D, FFBBasis3D
32+
from aspire.classification import BFSReddyChatterjiAverager2D, RIRClass2D
33+
from aspire.denoising import DenoiserCov2D
34+
from aspire.noise import AnisotropicNoiseEstimator
35+
from aspire.reconstruction import MeanEstimator
36+
from aspire.source import RelionSource
37+
38+
logger = logging.getLogger(__name__)
39+
40+
41+
# %%
42+
# Parameters
43+
# ---------------
44+
# Example simulation configuration.
45+
46+
interactive = False # Draw blocking interactive plots?
47+
do_cov2d = True # Use CWF coefficients
48+
n_imgs = 20000 # Set to None for all images in starfile, can set smaller for tests.
49+
img_size = 32 # Downsample the images/reconstruction to a desired resolution
50+
n_classes = 1000 # How many class averages to compute.
51+
n_nbor = 50 # How many neighbors to stack
52+
starfile_in = "10028/data/shiny_2sets.star"
53+
volume_filename_prefix_out = f"10028_recon_c{n_classes}_m{n_nbor}_{img_size}.mrc"
54+
pixel_size = 1.34
55+
56+
# %%
57+
# Source data and Preprocessing
58+
# -----------------------------
59+
#
60+
# `RelionSource` is used to access the experimental data via a `starfile`.
61+
# Begin by downsampling to our chosen resolution, then preprocess
62+
# to correct for CTF and noise.
63+
64+
# Create a source object for the experimental images
65+
src = RelionSource(starfile_in, pixel_size=pixel_size, max_rows=n_imgs)
66+
67+
# Downsample the images
68+
logger.info(f"Set the resolution to {img_size} X {img_size}")
69+
src.downsample(img_size)
70+
71+
# Peek
72+
if interactive:
73+
src.images(0, 10).show()
74+
75+
# Use phase_flip to attempt correcting for CTF.
76+
logger.info("Perform phase flip to input images.")
77+
src.phase_flip()
78+
79+
# Estimate the noise and `Whiten` based on the estimated noise
80+
aiso_noise_estimator = AnisotropicNoiseEstimator(src)
81+
src.whiten(aiso_noise_estimator.filter)
82+
83+
# Plot the noise profile for inspection
84+
if interactive:
85+
plt.imshow(aiso_noise_estimator.filter.evaluate_grid(img_size))
86+
plt.show()
87+
88+
# Peek, what do the whitened images look like...
89+
if interactive:
90+
src.images(0, 10).show()
91+
92+
# # Optionally invert image contrast, depends on data convention.
93+
# # This is not needed for 10028, but included anyway.
94+
# logger.info("Invert the global density contrast")
95+
# src.invert_contrast()
96+
97+
# %%
98+
# Optional: CWF Denoising
99+
# -----------------------
100+
#
101+
# Optionally generate an alternative source that is denoised with `cov2d`,
102+
# then configure a customized averager. This allows the use of CWF denoised
103+
# images for classification, but stacks the original images for averages
104+
# used in the remainder of the reconstruction pipeline.
105+
#
106+
# In this example, this behavior is controlled by the `do_cov2d` boolean variable.
107+
# When disabled, the original src and default averager is used.
108+
# If you will not be using cov2d,
109+
# you may remove this code block and associated variables.
110+
111+
classification_src = src
112+
custom_averager = None
113+
if do_cov2d:
114+
# Use CWF denoising
115+
cwf_denoiser = DenoiserCov2D(src)
116+
# Use denoised src for classification
117+
classification_src = cwf_denoiser.denoise()
118+
# Peek, what do the denoised images look like...
119+
if interactive:
120+
classification_src.images(0, 10).show()
121+
122+
# Use regular `src` for the alignment and composition (averaging).
123+
composite_basis = FFBBasis2D((src.L,) * 2, dtype=src.dtype)
124+
custom_averager = BFSReddyChatterjiAverager2D(composite_basis, src, dtype=src.dtype)
125+
126+
127+
# %%
128+
# Class Averaging
129+
# ----------------------
130+
#
131+
# Now perform classification and averaging for each class.
132+
133+
logger.info("Begin Class Averaging")
134+
135+
rir = RIRClass2D(
136+
classification_src, # Source used for classification
137+
fspca_components=400,
138+
bispectrum_components=300, # Compressed Features after last PCA stage.
139+
n_nbor=n_nbor,
140+
n_classes=n_classes,
141+
large_pca_implementation="legacy",
142+
nn_implementation="sklearn",
143+
bispectrum_implementation="legacy",
144+
averager=custom_averager,
145+
)
146+
147+
classes, reflections, distances = rir.classify()
148+
avgs = rir.averages(classes, reflections, distances)
149+
if interactive:
150+
avgs.images(0, 10).show()
151+
152+
# %%
153+
# Common Line Estimation
154+
# ----------------------
155+
#
156+
# Next create a CL instance for estimating orientation of projections
157+
# using the Common Line with Synchronization Voting method.
158+
159+
logger.info("Begin Orientation Estimation")
160+
161+
orient_est = CLSyncVoting(avgs, n_theta=36)
162+
# Get the estimated rotations
163+
orient_est.estimate_rotations()
164+
rots_est = orient_est.rotations
165+
166+
# %%
167+
# Volume Reconstruction
168+
# ----------------------
169+
#
170+
# Using the estimated rotations, attempt to reconstruct a volume.
171+
172+
logger.info("Begin Volume reconstruction")
173+
174+
# Assign the estimated rotations to the class averages
175+
avgs.rots = rots_est
176+
177+
# Create a reasonable Basis for the 3d Volume
178+
basis = FFBBasis3D((img_size,) * 3, dtype=src.dtype)
179+
180+
# Setup an estimator to perform the back projection.
181+
estimator = MeanEstimator(avgs, basis)
182+
183+
# Perform the estimation and save the volume.
184+
estimated_volume = estimator.estimate()
185+
estimated_volume.save(volume_filename_prefix_out, overwrite=True)
186+
187+
# Peek at result
188+
if interactive:
189+
plt.imshow(np.sum(estimated_volume[0], axis=-1))
190+
plt.show()

0 commit comments

Comments
 (0)