diff --git a/gallery/tutorials/configuration.py b/gallery/tutorials/configuration.py index 89dde5ed97..819ff9b675 100644 --- a/gallery/tutorials/configuration.py +++ b/gallery/tutorials/configuration.py @@ -122,7 +122,7 @@ # %% # Logging preferences -# --------- +# ------------------- # The "Logging" section contains options for controlling the verbosity and destination of log messages generated by ASPIRE. # # By default, the ``log_dir`` is a directory called ``logs`` within the current working directory from which ASPIRE was invoked, but @@ -162,7 +162,7 @@ # %% # Advanced logging options -# --------- +# ------------------------ # Users with sophisticated knowledge of Python's ``logging`` library are able to directly work with the ``logging.conf`` file stored in # ``src/aspire`` in the source. # diff --git a/gallery/tutorials/pipeline_demo.py b/gallery/tutorials/pipeline_demo.py index 3f38ae8597..31146317bb 100644 --- a/gallery/tutorials/pipeline_demo.py +++ b/gallery/tutorials/pipeline_demo.py @@ -141,11 +141,13 @@ # 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 for -# classification. Here we're using ``TopClassSelector``, which -# selects 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. +# 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 @@ -250,15 +252,13 @@ # the z-axis. These estimated projections should align with the # original projection images. -from aspire.source import ArrayImageSource - -# Get projections from the estimated volume using the estimated -# orientations. We instantiate the projections as an -# ``ArrayImageSource`` to access the ``Image.show()`` method. -projections_est = ArrayImageSource(estimated_volume.project(oriented_src.rotations)) +# 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.images[0:10].show() +projections_est.show() # %% diff --git a/gallery/tutorials/tutorials/ctf.py b/gallery/tutorials/tutorials/ctf.py index b26bc637c2..a06ce51d87 100644 --- a/gallery/tutorials/tutorials/ctf.py +++ b/gallery/tutorials/tutorials/ctf.py @@ -206,7 +206,7 @@ def generate_example_image(L, noise_variance=0.1): # %% # Validating ``CTFFilter`` -# -------------------- +# ------------------------ # The forward modeling of CTF can be validated by passing a corrupted image # through CTF estimators and comparing the resulting defocus value(s). diff --git a/src/aspire/source/image.py b/src/aspire/source/image.py index dfed0825f7..4f4a499a0a 100644 --- a/src/aspire/source/image.py +++ b/src/aspire/source/image.py @@ -1,4 +1,5 @@ import copy +import functools import logging import os.path import types @@ -102,7 +103,7 @@ def __getitem__(self, indices): return self.fun(indices) -def as_copy(func): +def _as_copy(func): """ Method decorator that invokes the decorated method on a deepcopy of the object, and returns it on exit. The original object is unmodified. @@ -114,6 +115,7 @@ def as_copy(func): is best used on methods that mutate the object but don't return anything. """ + @functools.wraps(func) # Pass metadata (eg name and doctrings) from `func` def wrapper(self, *args, **kwargs): obj_copy = copy.deepcopy(self) func_copy = copy.deepcopy(func) @@ -757,7 +759,7 @@ def _apply_source_filters(self, im_orig, indices): self.filter_indices[indices], ) - @as_copy + @_as_copy def cache(self): """ Computes all queued pipeline transformations and stores the @@ -784,7 +786,7 @@ def _images(self, indices): Subclasses handle cached image check as well as applying transforms in the generation pipeline. """ - @as_copy + @_as_copy def downsample(self, L): if L > self.L: raise ValueError( @@ -800,7 +802,7 @@ def downsample(self, L): self.L = L - @as_copy + @_as_copy def whiten(self, noise_estimate=None): """ Modify the `ImageSource` in-place by appending a whitening filter to the generation pipeline. @@ -840,7 +842,7 @@ def whiten(self, noise_estimate=None): logger.info("Adding Whitening Filter Xform to end of generation pipeline") self.generation_pipeline.add_xform(FilterXform(whiten_filter)) - @as_copy + @_as_copy def phase_flip(self): """ Perform phase flip on images in the source object using CTF information. @@ -865,7 +867,7 @@ def phase_flip(self): " Confirm you have correctly populated CTFFilters." ) - @as_copy + @_as_copy def invert_contrast(self, batch_size=512): """ invert the global contrast of images @@ -915,7 +917,7 @@ def invert_contrast(self, batch_size=512): logger.info("Adding Scaling Xform to end of generation pipeline") self.generation_pipeline.add_xform(Multiply(scale_factor)) - @as_copy + @_as_copy def normalize_background(self, bg_radius=1.0, do_ramp=True): """ Normalize the images by the noise background