Skip to content

Commit b2a7d0c

Browse files
Merge remote-tracking branch 'origin/develop' into refactor_image_src_519
2 parents a9a10a5 + ce200cc commit b2a7d0c

File tree

8 files changed

+45
-25
lines changed

8 files changed

+45
-25
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.8.1
2+
current_version = 0.9.0
33
commit = True
44
tag = True
55

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![codecov](https://codecov.io/gh/ComputationalCryoEM/ASPIRE-Python/branch/master/graph/badge.svg?token=3XFC4VONX0)](https://codecov.io/gh/ComputationalCryoEM/ASPIRE-Python)
66
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5657281.svg)](https://doi.org/10.5281/zenodo.5657281)
77

8-
# ASPIRE - Algorithms for Single Particle Reconstruction - v0.8.1
8+
# ASPIRE - Algorithms for Single Particle Reconstruction - v0.9.0
99

1010
This is the Python version to supersede the [Matlab ASPIRE](https://github.com/PrincetonUniversity/aspire).
1111

@@ -20,7 +20,7 @@ For more information about the project, algorithms, and related publications ple
2020
Please cite using the following DOI. This DOI represents all versions, and will always resolve to the latest one.
2121

2222
```
23-
ComputationalCryoEM/ASPIRE-Python: v0.8.1 https://doi.org/10.5281/zenodo.5657281
23+
ComputationalCryoEM/ASPIRE-Python: v0.9.0 https://doi.org/10.5281/zenodo.5657281
2424
2525
```
2626

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
# built documents.
7575
#
7676
# The full version, including alpha/beta/rc tags.
77-
release = version = "0.8.1"
77+
release = version = "0.9.0"
7878

7979
# The language for content autogenerated by Sphinx. Refer to documentation
8080
# for a list of supported languages.

docs/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Aspire v0.8.1
1+
Aspire v0.9.0
22
==============
33

44
Algorithms for Single Particle Reconstruction

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def read(fname):
99

1010
setup(
1111
name="aspire",
12-
version="0.8.1",
12+
version="0.9.0",
1313
data_files=[
1414
("", ["src/aspire/config.ini"]),
1515
("", ["src/aspire/logging.conf"]),

src/aspire/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from aspire.exceptions import handle_exception
1010

1111
# version in maj.min.bld format
12-
__version__ = "0.8.1"
12+
__version__ = "0.9.0"
1313

1414
# Implements some code that writes out exceptions to 'aspire.err.log'.
1515
config = Config(read_text(aspire, "config.ini"))

src/aspire/source/image.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def states(self, values):
107107

108108
@property
109109
def filter_indices(self):
110-
return self.get_metadata("__filter_indices")
110+
return np.atleast_1d(self.get_metadata("__filter_indices"))
111111

112112
@filter_indices.setter
113113
def filter_indices(self, indices):
@@ -279,17 +279,18 @@ def _images(self, start=0, num=np.inf, indices=None):
279279
"Subclasses should implement this and return an Image object"
280280
)
281281

282-
def _apply_filters(self, im_orig, start=0, num=np.inf, indices=None):
282+
def _apply_filters(
283+
self,
284+
im_orig,
285+
filters,
286+
indices,
287+
):
283288
"""
284-
For each image in `im_orig` specified by start, num, or indices,
285-
the unique_filters associated with the corresponding index in the
286-
`ImageSource` are applied. The images are then returned as an `Image`
287-
stack.
289+
For images in `im_orig`, `filters` associated with the corresponding
290+
index in the supplied `indices` are applied. The images are then returned as an `Image` stack.
288291
:param im_orig: An `Image` object
289-
:param start: Starting index of images in `im_orig`.
290-
:param num: Number of images to work on, starting at `start`.
291-
:param indices: A numpy array of image indices. If specified,`start` and `num` are ignored.
292-
:return: An `Image` instance with the unique filters of the source applied at the given indices.
292+
:param filters: A list of `Filter` objects
293+
:param indices: A list of indices indicating the corresponding filter in `filters`
293294
"""
294295
if not isinstance(im_orig, Image):
295296
logger.warning(
@@ -300,16 +301,20 @@ def _apply_filters(self, im_orig, start=0, num=np.inf, indices=None):
300301

301302
im = im_orig.copy()
302303

303-
if indices is None:
304-
indices = np.arange(start, min(start + num, self.n))
305-
306-
for i, filt in enumerate(self.unique_filters):
307-
idx_k = np.where(self.filter_indices[indices] == i)[0]
304+
for i, filt in enumerate(filters):
305+
idx_k = np.where(indices == i)[0]
308306
if len(idx_k) > 0:
309307
im[idx_k] = Image(im[idx_k]).filter(filt).asnumpy()
310308

311309
return im
312310

311+
def _apply_source_filters(self, im_orig, indices):
312+
return self._apply_filters(
313+
im_orig,
314+
self.unique_filters,
315+
self.filter_indices[indices],
316+
)
317+
313318
def cache(self):
314319
logger.info("Caching source images")
315320
self._cached_im = self.images(start=0, num=np.inf)
@@ -465,7 +470,7 @@ def im_backward(self, im, start):
465470
all_idx = np.arange(start, min(start + num, self.n))
466471
im *= self.amplitudes[all_idx, np.newaxis, np.newaxis]
467472
im = im.shift(-self.offsets[all_idx, :])
468-
im = self._apply_filters(im, start=start, num=num)
473+
im = self._apply_source_filters(im, all_idx)
469474

470475
vol = im.backproject(self.rots[start : start + num, :, :])[0]
471476

@@ -487,7 +492,7 @@ def vol_forward(self, vol, start, num):
487492
logger.warning(f"Volume.dtype {vol.dtype} inconsistent with {self.dtype}")
488493

489494
im = vol.project(0, self.rots[all_idx, :, :])
490-
im = self._apply_filters(im, start, num)
495+
im = self._apply_source_filters(im, all_idx)
491496
im = im.shift(self.offsets[all_idx, :])
492497
im *= self.amplitudes[all_idx, np.newaxis, np.newaxis]
493498
return im

src/aspire/source/simulation.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import copy
12
import logging
23

34
import numpy as np
@@ -84,13 +85,18 @@ def __init__(
8485
if unique_filters is None:
8586
unique_filters = []
8687
self.unique_filters = unique_filters
88+
# sim_filters must be a deep copy so that it is not changed
89+
# when unique_filters is changed
90+
self.sim_filters = copy.deepcopy(unique_filters)
8791

8892
# Create filter indices and fill the metadata based on unique filters
8993
if unique_filters:
9094
if filter_indices is None:
9195
filter_indices = randi(len(unique_filters), n, seed=seed) - 1
9296
self._populate_ctf_metadata(filter_indices)
9397
self.filter_indices = filter_indices
98+
else:
99+
self.filter_indices = np.zeros(n)
94100

95101
self.offsets = offsets
96102
self.amplitudes = amplitudes
@@ -170,7 +176,9 @@ def _images(self, start=0, num=np.inf, indices=None, enable_noise=True):
170176

171177
im = self.projections(start=start, num=num, indices=indices)
172178

173-
im = self._apply_filters(im, start=start, num=num, indices=indices)
179+
# apply original CTF distortion to image
180+
im = self._apply_sim_filters(im, indices)
181+
174182
im = im.shift(self.offsets[indices, :])
175183

176184
im *= self.amplitudes[indices].reshape(len(indices), 1, 1).astype(self.dtype)
@@ -180,6 +188,13 @@ def _images(self, start=0, num=np.inf, indices=None, enable_noise=True):
180188

181189
return im
182190

191+
def _apply_sim_filters(self, im, indices):
192+
return self._apply_filters(
193+
im,
194+
self.sim_filters,
195+
self.filter_indices[indices],
196+
)
197+
183198
def vol_coords(self, mean_vol=None, eig_vols=None):
184199
"""
185200
Coordinates of simulation volumes in a given basis

0 commit comments

Comments
 (0)