We hope your visit was informative.
We have provided this link to a non-NIST site because it has information that may be of interest to our users. NIST does not necessarily endorse the views expressed or the facts presented on this site. Further, NIST does not endorse any commercial products that may be advertised or available on this site.
', + preLinkMessage: "You will now be directed to:
{URL}
Cancel or press the ESC key.
'; + } else { + msgContent+='Click the link above to continue or Cancel
'; + } + + //Append the HTML to the message box + $('#'+options.messageBoxId).append(msgContent); + + //If the timer is enabled, set the timer to follow link after desired time. + if (options.timeOut>0) { + leaveIn=setTimeout(function(){ + $('#ln-cancelMessage').html('Loading...'); + window.location.href=url; + },options.timeOut); + } else { + leaveIn=false; + } + + //if newWindow is turned on, add target and click behavior + if (options.newWindow) { + $('a#'+options.linkId).attr('target', '_blank').click(function(){ + closeDialog(options, leaveIn); + }) + } + + //Apply event handler to pressing the close link + $('#ln-cancelLink').click(function(){ + closeDialog(options, leaveIn); + return false; + }); + + //Set up event handler for the ESC key + $(document).bind('keyup', function(e){ + if (e.which==27) { + closeDialog(options, leaveIn); + } + }); + + // Clears the display when leaving the page to prevent it from showing upon returning. + $(window).on('unload', function(){ + closeDialog(options, leaveIn); + }); + + return false; + }); + }); + }; + + // private function to close the dialog. This may be public in future + // releases, but for now it has to be private. + function closeDialog(options, timer) { + if (options.timeOut>0) { + clearTimeout(timer); + } + $('#'+options.overlayId+', #'+options.messageHolderId).fadeOut('fast',function(){ + $('#'+options.overlayId+', #'+options.messageHolderId).remove(); + }); + $(document).unbind('keyup'); + } + + // end and return jQuery object +})( jQuery ); \ No newline at end of file diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 0000000..e20e896 --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,38 @@ +{# Import the theme's layout. #} +{% extends "!layout.html" %} + +{% block extrahead %} + + + + + + + + +{% endblock %} + +{# Add some extra stuff before and use existing with 'super()' call. #} +{% block footer %} + {{ super() }} +{% endblock %} diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..d3e54da --- /dev/null +++ b/docs/api.md @@ -0,0 +1,136 @@ +# General Information + +The recommended way to use the ETSpy library is by importing the +`api` module: + +``` +import etspy.api as etspy +``` + +Running this command is approximately equivalent to running: + +``` +from etspy import align, io, utils # (1)! +from etspy.base import TomoStack +from etspy.io import create_stack, load +``` + +```{eval-rst} +.. code-annotations:: + 1. .. note:: + + If you wish to import things directly from ``etspy``, this + approach is perfectly valid. The ``etspy.api`` is just a helper + module to expose a more limited set of commonly used features. +``` + +The `etspy.api` module exposes the most commonly used features of ETSpy in a +convenient interface. In particular, it provides access tothe [`align`](alignment), +[`io`](io), and [`utils`](utilities) sub-modules. It also directly exposes +the [`create_stack`](#etspy.io.create_stack) and [`load`](#etspy.io.load) methods, +which allow for creation of [`TomoStack`](#etspy.base.TomoStack) objects either directly +from NumPy arrays, or by loading data from `.mrc`, `.dm3`, or `.dm4` files. One +can also use the [`TomoStack`](#etspy.base.TomoStack) constructor for more +detailed control over how the resulting signal is created. + +:::{tip} +For more examples, please consult the example notebook on the +[Example Usage](examples/etspy_demo) page. +::: + +(signals)= + +# Signals + +ETSpy provides two dedicated signal types that are extensions of the regular +[HyperSpy `Signal2D`](inv:hyperspy#hyperspy.api.signals.Signal2D) class. +[`TomoStack`](#etspy.base.TomoStack) objects provide the majority of the +functionality of ETSpy, and represent a tomographic tilt series data set. +[`RecStack`](#etspy.base.RecStack) objects provide a (currently limited) +set of additional operations useful for visualizing and processing the +results of a tomography reconstruction. For more details on these classes, +please consult the following pages: + +```{eval-rst} +.. python-apigen-group:: signals +``` + +(io)= + +# File I/O + +Experimental data files can be easily loaded into ETSpy using the +[`load`](#etspy.io.load) function. If your data is already held +in memory as a NumPy array, a [`TomoStack`](#etspy.base.TomoStack) +signal can be created using the [`create_stack`](#etspy.io.create_stack) +method. Additionally, the [`io`](io) module provides a number of +other helper functions: + +```{eval-rst} +.. python-apigen-group:: io + +``` + +(alignment)= + +# Alignment Methods + +The [`align`](alignment) module provides a range of tools to correct +for misalignments of tilt image series that are common during an experimental +data collection: + +```{eval-rst} +.. python-apigen-group:: align +``` + +(reconstruction)= + +# Reconstruction + +The [`recon`](reconstruction) module contains a number of lower-level helper +methods that run directly on NumPy arrays. These functions make extensive use +of the [ASTRA Toolbox](https://astra-toolbox.com) and are primarily designed to +be used internally by other parts of the code, but can be used directly, if desired. + +:::{tip} +For an easier way to reconstruct a {py:class}`~etspy.base.TomoStack` signal, use the +{py:meth}`etspy.base.TomoStack.reconstruct` function instead. +::: + +```{eval-rst} +.. python-apigen-group:: recon +``` + +(simulation)= + +# Data Simulation + +The [`simulation`](simulation) module provides tools to create model data, which can +be used to test various reconstruction routines: + +```{eval-rst} +.. python-apigen-group:: simulation +``` + +(datasets)= + +# Example Datasets + +The [`datasets`](datasets) module provides two experimental datasets distributed +along with the ETSpy code that can be used in examples or for testing reconstruction +and alignment routines: + +```{eval-rst} +.. python-apigen-group:: datasets +``` + +(utilities)= + +# Utilities + +The [`utils`](utilities) module provides a few miscellaneous functions that perform +assorted tasks related to tomographic reconstruction: + +```{eval-rst} +.. python-apigen-group:: utilities +``` diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..ca1f70f --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,324 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import inspect +import os +import sys +from pathlib import Path +from typing import cast + +import etspy + +sys.path.insert(0, os.path.abspath("..")) + +# PACKAGE_PATH used to exclude autodoc members not from ETSpy +PACKAGE_PATH = Path(__file__).parent.parent + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = "ETSpy" +# copyright = '2024, Andrew Herzing, Joshua Taillon' +author = "Andrew Herzing, Joshua Taillon" +release = etspy.__version__ + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx.ext.mathjax", + "sphinx.ext.intersphinx", + "sphinx.ext.viewcode", + "sphinx_immaterial", + "sphinx_immaterial.apidoc.python.apigen", + "sphinx.ext.duration", + "sphinx.ext.doctest", + "myst_nb" +] + +myst_enable_extensions = [ + "amsmath", + "attrs_inline", + "colon_fence", + "deflist", + "dollarmath", + "fieldlist", + "html_admonition", + "html_image", + # "linkify", + "replacements", + "smartquotes", + "strikethrough", + "substitution", + "tasklist", +] + +nitpicky = True +today_fmt = '%B %-d, %Y at %I:%M %p' +master_doc = "index" +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"] +source_suffix = [".rst", ".md", '.ipynb'] +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "hyperspy": ("https://hyperspy.org/hyperspy-doc/current", None), + "rsciio": ("https://hyperspy.org/rosettasciio", None), + "scipy": ("https://docs.scipy.org/doc/scipy", None), + "numpy": ("https://numpy.org/doc/stable", None), + "matplotlib": ("https://matplotlib.org/stable", None), + "astra": ("https://astra-toolbox.com", None) +} + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "sphinx_immaterial" +html_static_path = ["_static"] +html_logo = "_static/ETSpy_logo_trans.png" +html_css_files = [ + "custom_css.css", +] +html_favicon = "_static/favicon-64x64.png" + + +html_theme_options = { + "icon": { + "repo": "fontawesome/brands/github", + "edit": "material/file-edit-outline", + }, + "site_url": "https://pages.nist.gov/etspy/", + "repo_url": "https://github.com/usnistgov/etspy/", + "repo_name": "ETSpy", + "edit_uri": "blob/master/docs", + "globaltoc_collapse": True, + "toc_title_is_page_title": True, + "features": [ + "navigation.expand", + # "navigation.tabs", + # "toc.integrate", + # "navigation.sections", + "navigation.instant", + # "header.autohide", + "navigation.top", + "navigation.tracking", + "search.highlight", + "search.share", + "toc.follow", + "toc.sticky", + "content.tabs.link", + "content.code.annotate", + "announce.dismiss", + ], + "palette": [ + { + "media": "(prefers-color-scheme: light)", + "scheme": "default", + "primary": "blue", + "accent": "indigo", + "toggle": { + "icon": "material/lightbulb-outline", + "name": "Switch to dark mode", + }, + }, + { + "media": "(prefers-color-scheme: dark)", + "scheme": "slate", + "primary": "blue", + "accent": "indigo", + "toggle": { + "icon": "material/lightbulb", + "name": "Switch to light mode", + }, + }, + ], + "social": [ + { + "icon": "fontawesome/brands/github", + "link": "https://github.com/usnistgov/etspy", + "name": "Source on github.com", + }, + { + "icon": "fontawesome/brands/python", + "link": "https://pypi.org/project/etspy/", + }, + ], +} + + +favicons = [ + "favicon-16x16.png", + "favicon-32x32.png", + "favicon-64x64.png", + "favicon-128x128.png", + "favicon-256x256.png", + "favicon-512x512.png", + "icon.svg", +] + +autodoc_default_options = { + "imported-members": True, + "members": True, + # "special-members": True, + # "inherited-members": "ndarray", + # "member-order": "groupwise", +} +autodoc_typehints = "signature" +autodoc_typehints_description_target = "documented" +autodoc_typehints_format = "short" + +# make sure "Examples", "Notes", etc. rubrics are included in right-side ToC +object_description_options = [ + ("py:.*", dict( + include_object_type_in_xref_tooltip=False, + include_rubrics_in_toc=True, + )), +] + +# -- Sphinx Immaterial configs ------------------------------------------------- + +# Python apigen configuration +python_apigen_modules = { + "etspy": "api/etspy.", + "etspy.align": "api/etspy.align.", + "etspy.api": "api/etspy.api.", + "etspy.base": "api/etspy.base.", + "etspy.datasets": "api/etspy.datasets.", + "etspy.io": "api/etspy.io.", + "etspy.recon": "api/etspy.recon.", + "etspy.simulation": "api/etspy.simulation.", + "etspy.utils": "api/etspy.utils.", +} +python_apigen_show_base_classes = True + +# hide long base module names from display +# (see https://sphinx-immaterial.readthedocs.io/en/latest/apidoc/python/index.html#python-domain-customization) +python_module_names_to_strip_from_xrefs = [ + "hyperspy._signals.signal2d", + "etspy.base" +] + +# set up "automatic" groupings for members +python_apigen_default_groups = [ + ("class:.*", "Classes"), + ("data:.*", "Variables"), + ("function:.*", "Functions"), + ("classmethod:.*", "Class methods"), + ("method:.*", "Methods"), + (r"method:.*\.[A-Z][A-Za-z,_]*", "Constructors"), + (r"method:.*\.__[A-Za-z,_]*__", "Special methods"), + (r"method:.*\.__(init|new)__", "Constructors"), + (r"method:.*\.__(str|repr)__", "String representation"), + ("property:.*", "Properties"), + (r"etspy\.AlignmentMethod.*", "align"), + # (r".*:.*\.is_[a-z,_]*", "Attributes"), + (r"attribute:.*etspy\.AlignmentMethod.*", "Enum Values"), + # (".*etspy\\.api.*", "api"), + # (".*etspy\\.align.*", "align"), + # (".*etspy\\.utils.*", "utilities"), + # (".*etspy\\.io.*", "io"), + # (".*etspy\\.simulation.*", "simulation"), + # (".*etspy\\.recon.*", "recon"), + # (".*etspy\\.datasets.*", "datasets"), + # (".*etspy\\.base.*", "signals"), +] +python_apigen_default_order = [ + (".*etspy\\.api.*", 20), + (".*etspy\\.align.*", 21), + (".*etspy\\.utils.*", 22), + (".*etspy\\.io.*", 23), + (".*etspy\\.simulation.*", 24), + (".*etspy\\.recon.*", 25), + (".*etspy\\.datasets.*", 26), + (".*etspy\\.base.*", 27), + ("class:.*", 30), + ("data:.*", 31), + ("function:.*", 32), + ("classmethod:.*", 40), + ("method:.*", 50), + (r"method:.*\.[A-Z][A-Za-z,_]*", 20), + (r"method:.*\.__[A-Za-z,_]*__", 28), + (r"method:.*\.__(init|new)__", 20), + (r"method:.*\.__(str|repr)__", 30), + ("property:.*", 60), + (r".*:.*\.is_[a-z,_]*", 70), +] +python_apigen_order_tiebreaker = "definition_order" +python_apigen_case_insensitive_filesystem = False + + +def autodoc_skip_member(app, what, name, obj, skip, options): + """ + Instruct autodoc to skip members that not directly from ETSpy. + """ + if skip: + # Continue skipping things Sphinx already wants to skip + return skip + + if name == "__init__": + return False + + try: + # get source file for property via fget + if isinstance(obj, property): + p = Path(inspect.getfile(obj.fget)) # pyright: ignore[reportArgumentType] + else: + p = Path(inspect.getfile(obj)) + if PACKAGE_PATH not in p.parents: + # skip if member does not come from ETSpy + return True + except TypeError as e: + if 'AlignmentMethod' in str(obj): + return False + return 'etspy' not in str(obj) + + return skip + +def autodoc_process_signature(app, what, name, obj, options, signature, return_annotation): + if return_annotation == "~typing.Self": + print(f"SIGNATURE: {what}, {name}, {obj}, {options}, {signature}, {return_annotation}") + + # replace "Self" annotations with current class name + if return_annotation == "~typing.Self" and name[:11] == "etspy.base.TomoStack": + replaced_annotation = "~" + '.'.join(name.split('.')[:-1]) + return signature, replaced_annotation + +def autodoc_process_docstring(app, what, name, obj, options, lines): + if 'TomoStack' in name: + print(f"DOCSTRING: {what}, {name}, {obj}, {options}, {lines}") + pass + +def autodoc_process_bases(app, name, obj, options, bases): + # remove abc.ABC from displayed base class for CommonStack + from abc import ABC + if name == "etspy.base.CommonStack": + for cls in bases[:]: + if cls == ABC: + bases.remove(cls) + +def setup(app): + app.connect("autodoc-skip-member", autodoc_skip_member) + app.connect("autodoc-process-bases", autodoc_process_bases) + # app.connect("autodoc-process-docstring", autodoc_process_docstring) + # app.connect("autodoc-process-signature", autodoc_process_signature) + + +# -- Link checking configs ------------------------------------------------- + +linkcheck_ignore = [ + "https://doi.org/10.1103/PhysRevB.72.052103", # 403 Client Error: Forbidden for url: https://journals.aps.org/prb/abstract/10.1103/PhysRevB.72.052103 + "https://pages.nist.gov/etspy", # temporarily not published + "https://pypi.org/project/etspy", # temporarily not published + "https://github.com/usnistgov/etspy/tree/master/docs/examples/etspy_demo.ipynb" # temporarily not published +] + +linkcheck_exclude_documents = [] + +# Specify a standard user agent, as Sphinx default is blocked on some sites +user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54" + +# prevent documentation from executing notebook: +nb_execution_excludepatterns = ['etspy_demo.ipynb'] diff --git a/docs/examples/etspy_demo.ipynb b/docs/examples/etspy_demo.ipynb new file mode 100644 index 0000000..521e581 --- /dev/null +++ b/docs/examples/etspy_demo.ipynb @@ -0,0 +1,4332 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ETSpy Demo" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook demonstrates the basic use and functionality of the ETSpy package.\n", + "\n", + "It covers:\n", + "* Loading simulated data\n", + "* Basic plotting of tilt series data\n", + "* Reconstruction of single slices of simulated data\n", + "* Reconstruction of the full simluated dataset\n", + "* Saving reconstructed data\n", + "\n", + "If you are viewing this demo on the ETSpy documentation website, it will not be interactive. We recommend downloading the latest version of the demo from [Github](https://github.com/usnistgov/etspy/tree/master/docs/examples/etspy_demo.ipynb) and running it on your local machine." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports\n", + "For interactive plotting, we set the Matplotlib backend to `widget`.\n", + "\n", + "In addition to the `etspy` package itself we also need to import:\n", + "* `pyplot` from `matplotlib`\n", + "* `hyperspy`\n", + "\n", + "Finally, we also need to import the `datasets` module of `etspy` in order to load the simluated data we will be working with.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# %matplotlib inline\n", + "\n", + "## Set to widget for interactive plots\n", + "%matplotlib widget\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import hyperspy.api as hs\n", + "\n", + "import etspy.api as tomo\n", + "from etspy import datasets as ds" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulated Catalyst Tilt Series\n", + "\n", + "### Load Data\n", + "* Read simulated catalyst tilt series as a TomoStack object\n", + "* Each image is shifted randomly to simulate specimen motion during tilt series acquisition" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "stack = ds.get_catalyst_data(misalign=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "This notebook demonstrates the basic use and functionality of the ETSpy package.
-It covers:
-For interactive plotting, we set the Matplotlib backend to widget
.
In addition to the etspy
package itself we also need to import:
Finally, we also need to import the datasets
module of etspyng with.
%matplotlib inline
-
-## Set to widget for interactive plots
-# %matplotlibl widget
-
-import matplotlib.pyplot as plt
-import hyperspy.api as hs
-
-import etspy.api as tomo
-from etspyimport datasets as ds
-
stack = ds.get_catalyst_tilt_series(misalign=True)
-
stack.metadata.Tomography
-
Signal2D
classrebin = stack.rebin(scale=[1, 2, 2])
-rebin
-
<TomoStack, title: , dimensions: (90|300, 300)>-
rebin.plot(cmap='inferno')
-
VBox(children=(HBox(children=(Label(value='Tilt', layout=Layout(width='15%')), IntSlider(value=0, description=…-
rebin.max().plot(cmap='inferno')
-
reg = rebin.stack_register('StackReg')
-
INFO:etspyerforming stack registration using PyStackReg -INFO:etspy.align:Stack registration complete --
reg.max().plot(cmap='inferno')
-
sino = reg.isig[150,:].as_signal2D((1,0))
-
-ax = hs.plot.plot_images([sino, reg.inav[45]], cmap='inferno',per_row=2, label=['Sinogram','FBP Reconstruction'])
-ax[1].axhline(300, linestyle='--', color='red')
-plt.gcf().set_size_inches((8,4))
-plt.tight_layout()
-
recFBP = reg.isig[150:151, :].reconstruct('FBP', cuda=False)
-
INFO:etspy -INFO:etspy.recon:Reconstruction using 64 cores -INFO:etspy.recon:Reconstruction complete --
ax = hs.plot.plot_images([sino, recFBP], cmap='inferno',per_row=2, label=['Sinogram','FBP Reconstruction'])
-plt.gcf().set_size_inches((8,4))
-plt.tight_layout()
-
SIRTStack, SIRTerror = reg.isig[150:151, :].recon_error(iterations = 500)
-SIRTStack.axes_manager[2].name = 'z'
-
INFO:etspy.base:CUDA detected with Astra --
SIRTStack.plot(navigator=SIRTerror, cmap='inferno')
-
ax = hs.plot.plot_images([SIRTStack.inav[0],SIRTStack.inav[19],SIRTStack.inav[49],
- SIRTStack.inav[99], SIRTStack.inav[249], SIRTStack.inav[499]], cmap='inferno',
- axes_decor='off',
- label=['Iterations: 1','Iterations: 20','Iterations: 50',
- 'Iterations: 100','Iterations: 250','Iterations: 500'])
-plt.gcf().set_size_inches(12,6)
-plt.tight_layout()
-
recFBP = reg.reconstruct('FBP', cuda=True)
-recSIRT = reg.reconstruct('SIRT', iterations=100, constrain=True, cuda=True)
-
INFO:etspy -INFO:etspy.recon:Reconstruction complete -INFO:etspy.recon:Reconstructing volume using SIRT w/ minimum constraint. Minimum value: 0 -INFO:etspy.recon:Reconstruction complete --
recFBP.plot(vmax=2000, cmap='inferno')
-
VBox(children=(HBox(children=(Label(value='y', layout=Layout(width='15%')), IntSlider(value=0, description='in…-
recSIRT.plot(vmax=2000, cmap='inferno')
-
VBox(children=(HBox(children=(Label(value='y', layout=Layout(width='15%')), IntSlider(value=0, description='in…-
recSIRT.swap_axes(0,2).plot(vmax=2000, cmap='inferno')
-
VBox(children=(HBox(children=(Label(value='z', layout=Layout(width='15%')), IntSlider(value=0, description='in…-
recFBP.save('FBP_Reconstruction.hdf5', overwrite=True)
-recSIRT.save('SIRT_Reconstruction_100.hdf5', overwrite=True)
-
WARNING:hyperspy.misc.utils:The package {package} does not set its version in {package}.__version__. Please report this issue to the etspy developers. --
WARNING:hyperspy.misc.utils:The package {package} does not set its version in {package}.__version__. Please report this issue to the etspy developers. --
stack = ds.get_needle_data()
-
INFO:etspy.io:Tilts found in MRC file header --
stack.plot(navigator='slider')
-
VBox(children=(HBox(children=(Label(value='Tilt', layout=Layout(width='15%')), IntSlider(value=0, description=…-
reg = stack.stack_register('StackReg')
-
INFO:etspy.align:Performing stack registration using PyStackReg -INFO:etspy.align:Stack registration complete --
reg.plot(navigator='slider')
-
VBox(children=(HBox(children=(Label(value='Tilt', layout=Layout(width='15%')), IntSlider(value=0, description=…-
reg.swap_axes(1,2).test_align(slices=[10,100,140])
-
INFO:etspy.base:CUDA detected with Astra -INFO:etspy.recon:Reconstruction volume using FBP_CUDA -INFO:etspy.recon:Reconstruction complete --
<TomoStack, title: , dimensions: (3|256, 256)>-
ali = reg.tilt_align('CoM')
-
INFO:etspy.align:Performing alignments using slices: [84, 128, 171] -INFO:etspy.align:Calculated tilt-axis shift 2.62 -INFO:etspy.align:Calculated tilt-axis rotation -1.99 --
ali.test_align(slices=[10,100,140])
-
INFO:etspy.base:CUDA detected with Astra -INFO:etspy.recon:Reconstruction volume using FBP_CUDA -INFO:etspy.recon:Reconstruction complete --
<TomoStack, title: , dimensions: (3|256, 256)>-
ali.plot()
-
VBox(children=(HBox(children=(Label(value='Tilt', layout=Layout(width='15%')), IntSlider(value=0, description=…-
rec = ali.reconstruct('SIRT', 500, constrain=True)
-
INFO:etspy.base:CUDA detected with Astra -INFO:etspy.recon:Reconstructing volume using SIRT w/ minimum constraint. Minimum value: 0 -INFO:etspy.recon:Reconstruction complete --
rec.inav[10:205].plot(cmap='inferno', vmin=50, vmax=1200)
-
VBox(children=(HBox(children=(Label(value='y', layout=Layout(width='15%')), IntSlider(value=0, description='in…-
rec.isig[:,90:165].swap_axes(2,0).plot(cmap='inferno', vmin=50)
-
VBox(children=(HBox(children=(Label(value='z', layout=Layout(width='15%')), IntSlider(value=0, description='in…-
-
-