Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gallery/tutorials/tutorials/image_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

file_path = os.path.join(os.path.dirname(os.getcwd()), "data", "monuments.npy")
img_data = np.load(file_path)
img_data.shape, img_data.dtype
print(img_data.shape, img_data.dtype)

# %%
# Create an Image Instance
Expand Down
5 changes: 4 additions & 1 deletion src/aspire/image/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ def show(self, columns=5, figsize=(20, 10), colorbar=True):

plt.show()

def frc(self, other, cutoff, pixel_size=None, method="fft", plot=False):
def frc(self, other, cutoff=None, pixel_size=None, method="fft", plot=False):
r"""
Compute the Fourier ring correlation between two images.

Expand All @@ -586,6 +586,9 @@ def frc(self, other, cutoff, pixel_size=None, method="fft", plot=False):

:param other: `Image` instance to compare.
:param cutoff: Cutoff value, traditionally `.143`.
Default `None` implies `cutoff=1` and excludes
plotting cutoff line.

:param pixel_size: Pixel size in angstrom. Default `None`
implies unit in pixels, equivalent to pixel_size=1.
:param method: Selects either 'fft' (on cartesian grid),
Expand Down
48 changes: 34 additions & 14 deletions src/aspire/utils/resolution_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module contains code for estimating resolution achieved by reconstructions.
"""
import logging
import warnings

import matplotlib.pyplot as plt
import numpy as np
Expand Down Expand Up @@ -44,7 +45,7 @@ def __init__(self, a, b, pixel_size=None, method="fft"):
Default `None` implies "pixel" units.
:param method: Selects either 'fft' (on Cartesian grid),
or 'nufft' (on polar grid). Defaults to 'fft'.
7"""
"""

# Sanity checks
if not hasattr(self, "dim"):
Expand Down Expand Up @@ -250,7 +251,11 @@ def analyze_correlations(self, cutoff):
Convert from the Fourier correlations to frequencies and resolution.

:param cutoff: Cutoff value, traditionally `.143`.
Note `cutoff=None` evaluates as `cutoff=1`.
"""
# Handle optional cutoff plotting.
if cutoff is None:
cutoff = 1
Comment on lines +257 to +258
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a divide by zero RuntimeWarning when computing the resolution below. I'm sure that's nothing new, but this is the default mode now. Do we want to prevent the warning in this case?


cutoff = float(cutoff)
if not (0 <= cutoff <= 1):
Expand All @@ -271,8 +276,12 @@ def analyze_correlations(self, cutoff):
# Convert indices to frequency (as 1/angstrom)
frequencies = self._freq(c_ind)

# Convert to resolution in angstrom, smaller is higher frequency.
self._resolutions = 1 / frequencies
with warnings.catch_warnings():
# When using high cutoff (eg. 1) it is possible `frequencies`
# contains 0; capture and ignore that division warning.
warnings.filterwarnings("ignore", r".*divide by zero.*")
# Convert to resolution in angstrom, smaller is higher frequency.
self._resolutions = 1 / frequencies

return self._resolutions

Expand All @@ -289,17 +298,25 @@ def _freq(self, k):
# Similar to wavenumbers. Larger is higher frequency.
return k / (self.L * self.pixel_size)

def plot(self, cutoff, save_to_file=False, labels=None):
def plot(self, cutoff=None, save_to_file=False, labels=None):
"""
Generates a Fourier correlation plot.

:param cutoff: Cutoff value, traditionally `.143`.
Default `None` implies `cutoff=1` and excludes
plotting cutoff line.
:param save_to_file: Optionally, save plot to file.
Defaults False, enabled by providing a string filename.
User is responsible for providing reasonable filename.
See `https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html`.
"""
cutoff = float(cutoff)

# Handle optional cutoff plotting.
_plot_cutoff = True
if cutoff is None:
cutoff = 1
_plot_cutoff = False

if not (0 <= cutoff <= 1):
raise ValueError("Supplied correlation `cutoff` not in [0,1], {cutoff}")

Expand Down Expand Up @@ -344,17 +361,20 @@ def plot(self, cutoff, save_to_file=False, labels=None):
_label = labels[i]
plt.plot(freqs_units, line, label=_label)

# Display cutoff
plt.axhline(y=cutoff, color="r", linestyle="--", label=f"cutoff={cutoff}")
estimated_resolution = self.analyze_correlations(cutoff)[0]

# Display resolution
plt.axvline(
x=estimated_resolution,
color="b",
linestyle=":",
label=f"Resolution={estimated_resolution:.3f}",
)
# Display cutoff
if _plot_cutoff:
plt.axhline(y=cutoff, color="r", linestyle="--", label=f"cutoff={cutoff}")

# Display resolution
plt.axvline(
x=estimated_resolution,
color="b",
linestyle=":",
label=f"Resolution={estimated_resolution:.3f}",
)

# x-axis decreasing
plt.gca().invert_xaxis()
plt.legend(title=f"Method: {self.method}")
Expand Down
4 changes: 3 additions & 1 deletion src/aspire/volume/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ def load(cls, filename, permissive=True, dtype=None, symmetry_group=None):

return cls(loaded_data, symmetry_group=symmetry_group, dtype=dtype)

def fsc(self, other, cutoff, pixel_size=None, method="fft", plot=False):
def fsc(self, other, cutoff=None, pixel_size=None, method="fft", plot=False):
r"""
Compute the Fourier shell correlation between two volumes.

Expand All @@ -564,6 +564,8 @@ def fsc(self, other, cutoff, pixel_size=None, method="fft", plot=False):

:param other: `Volume` instance to compare.
:param cutoff: Cutoff value, traditionally `.143`.
Default `None` implies `cutoff=1` and excludes
plotting cutoff line.
:param pixel_size: Pixel size in angstrom. Default `None`
implies unit in pixels, equivalent to pixel_size=1.
:param method: Selects either 'fft' (on cartesian grid),
Expand Down
8 changes: 5 additions & 3 deletions tests/test_fourier_correlation.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,10 @@ def test_frc_img_plot(image_fixture):
_ = img_a.frc(img_n, pixel_size=1, cutoff=0.143, plot=True)

# Plot to file
# Also tests `cutoff=None`
with tempfile.TemporaryDirectory() as tmp_input_dir:
file_path = os.path.join(tmp_input_dir, "img_frc_curve.png")
img_a.frc(img_n, pixel_size=1, cutoff=0.143, plot=file_path)
img_a.frc(img_n, pixel_size=1, cutoff=None, plot=file_path)
assert os.path.exists(file_path)


Expand Down Expand Up @@ -204,9 +205,10 @@ def test_fsc_vol_plot(volume_fixture):
_ = vol_a.fsc(vol_b, pixel_size=1, cutoff=0.5, plot=True)

# Plot to file
# Also tests `cutoff=None`
with tempfile.TemporaryDirectory() as tmp_input_dir:
file_path = os.path.join(tmp_input_dir, "img_fsc_curve.png")
vol_a.fsc(vol_b, pixel_size=1, cutoff=0.143, plot=file_path)
file_path = os.path.join(tmp_input_dir, "vol_fsc_curve.png")
vol_a.fsc(vol_b, pixel_size=1, cutoff=None, plot=file_path)
assert os.path.exists(file_path)


Expand Down
2 changes: 1 addition & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ def matplotlib_no_gui():

# Save and restore current warnings list.
with warnings.catch_warnings():
warnings.filterwarnings("ignore", "Matplotlib is currently using agg")
warnings.filterwarnings("ignore", r"Matplotlib is currently using agg.*")

yield

Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ per-file-ignores =
gallery/tutorials/pipeline_demo.py: T201
gallery/tutorials/turorials/data_downloader.py: E402
gallery/tutorials/tutorials/ctf.py: T201, E402
gallery/tutorials/tutorials/image_class.py: T201
gallery/tutorials/tutorials/micrograph_source.py: T201, E402
gallery/tutorials/tutorials/weighted_volume_estimation.py: T201, E402
# Ignore Sphinx gallery builds
Expand Down