diff --git a/.readthedocs.yml b/.readthedocs.yml index 990752cd..485d23e7 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,10 +5,6 @@ # Required version: 2 -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/source/conf.py - # Optionally build your docs in additional formats such as PDF formats: all # pdf, epub and htlmzip @@ -16,7 +12,11 @@ formats: all # pdf, epub and htlmzip build: os: ubuntu-22.04 tools: - python: "3.10" + python: "3.11" python: install: - requirements: requirements.txt + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py diff --git a/__init__.py b/__init__.py deleted file mode 100644 index 243eca73..00000000 --- a/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# from __future__ import division, print_function, absolute_import -# from distutils.version import LooseVersion -# -# -# from . import spyritest -# -# -# __all__ = [s for s in dir() if not s.startswith('_')] diff --git a/docs/source/_templates/spyrit-class-template.rst b/docs/source/_templates/spyrit-class-template.rst index b29757c5..2162996f 100644 --- a/docs/source/_templates/spyrit-class-template.rst +++ b/docs/source/_templates/spyrit-class-template.rst @@ -3,19 +3,19 @@ .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} - :members: :show-inheritance: - :inherited-members: {% block methods %} - .. automethod:: __init__ - {% if methods %} .. rubric:: {{ _('Methods') }} .. autosummary:: + :toctree: + :template: spyrit-method-template.rst {% for item in methods %} + {%- if item is in members %} ~{{ name }}.{{ item }} + {%- endif %} {%- endfor %} {% endif %} {% endblock %} @@ -25,8 +25,11 @@ .. rubric:: {{ _('Attributes') }} .. autosummary:: + :toctree: {% for item in attributes %} + {%- if item != "training" %} ~{{ name }}.{{ item }} + {%- endif %} {%- endfor %} {% endif %} {% endblock %} diff --git a/docs/source/_templates/spyrit-method-template.rst b/docs/source/_templates/spyrit-method-template.rst new file mode 100644 index 00000000..d6b50ff0 --- /dev/null +++ b/docs/source/_templates/spyrit-method-template.rst @@ -0,0 +1,5 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. automethod:: {{ objname }} diff --git a/docs/source/_templates/spyrit-module-template.rst b/docs/source/_templates/spyrit-module-template.rst index a33ad652..9f0f9c0b 100644 --- a/docs/source/_templates/spyrit-module-template.rst +++ b/docs/source/_templates/spyrit-module-template.rst @@ -1,6 +1,7 @@ {{ fullname | escape | underline}} .. automodule:: {{ fullname }} + :show-inheritance: {% block attributes %} {% if attributes %} diff --git a/docs/source/api.rst b/docs/source/api.rst deleted file mode 100644 index b547f4ff..00000000 --- a/docs/source/api.rst +++ /dev/null @@ -1,11 +0,0 @@ -============= -API reference -============= - -This section contains the API reference and usage information for spyrit. - -.. rubric:: **spyrit Modules:** - -.. toctree:: - - api/modules diff --git a/docs/source/conf.py b/docs/source/conf.py index bf35544b..7534d29b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -14,12 +14,10 @@ import sys from sphinx_gallery.sorting import ExampleTitleSortKey -sys.path.insert(0, os.path.abspath("../../spyrit")) -sys.path.insert(0, os.path.abspath("../../")) - +# paths relative to this file +sys.path.insert(0, os.path.abspath("../..")) # -- Project information ----------------------------------------------------- - project = "spyrit" copyright = "2021, Antonio Tomas Lorente Mur - Nicolas Ducros - Sebastien Crombez - Thomas Baudier" author = ( @@ -29,7 +27,6 @@ # The full version, including alpha/beta/rc tags release = "2.1.0" - # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -37,10 +34,10 @@ # ones. extensions = [ "sphinx.ext.intersphinx", - "sphinx.ext.autodoc", # + "sphinx.ext.autodoc", "sphinx.ext.mathjax", "sphinx.ext.todo", - "sphinx.ext.autosummary", # + "sphinx.ext.autosummary", "sphinx.ext.napoleon", "sphinx.ext.viewcode", "sphinx_gallery.gen_gallery", @@ -59,6 +56,8 @@ napoleon_use_param = False napoleon_use_rtype = False +autodoc_member_order = "bysource" +autosummary_generate = True todo_include_todos = True # Add any paths that contain templates here, relative to this directory. @@ -72,7 +71,7 @@ sphinx_gallery_conf = { # path to your examples scripts "examples_dirs": [ - "../../spyrit/tutorial", + "../../tutorial", ], # path where to save gallery generated examples "gallery_dirs": ["gallery"], @@ -113,5 +112,24 @@ } # http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_mock_imports -autodoc_mock_imports = "numpy matplotlib mpl_toolkits scipy torch torchvision Pillow opencv-python imutils PyWavelets pywt wget imageio".split() -autodoc_member_order = "bysource" +# autodoc_mock_imports incompatible with autosummary somehow +# autodoc_mock_imports = "numpy matplotlib mpl_toolkits scipy torch torchvision Pillow opencv-python imutils PyWavelets pywt wget imageio".split() + + +# exclude all torch.nn.Module members from the documentation +# except forward and __init__ methods +import torch + + +def skip_member_handler(app, what, name, obj, skip, options): + if name in [ + "forward", + ]: + return False + if name in dir(torch.nn.Module): + return True + return None + + +def setup(app): + app.connect("autodoc-skip-member", skip_member_handler) diff --git a/spyrit/images/tuto/dcnet.png b/docs/source/fig/dcnet.png similarity index 100% rename from spyrit/images/tuto/dcnet.png rename to docs/source/fig/dcnet.png diff --git a/spyrit/images/tuto/pinvnet.png b/docs/source/fig/pinvnet.png similarity index 100% rename from spyrit/images/tuto/pinvnet.png rename to docs/source/fig/pinvnet.png diff --git a/spyrit/images/tuto/pinvnet_cnn.png b/docs/source/fig/pinvnet_cnn.png similarity index 100% rename from spyrit/images/tuto/pinvnet_cnn.png rename to docs/source/fig/pinvnet_cnn.png diff --git a/docs/source/index.rst b/docs/source/index.rst index 6f9bdc3d..e771d8c2 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -98,7 +98,6 @@ The main functionalities of SPyRiT are implemented in the :class:`spyrit.core` s 6. **Training (train)** provide the functionalities for training reconstruction networks (see :mod:`spyrit.core.train`). - Subpackages ----------------------------------- @@ -117,8 +116,6 @@ Subpackages gallery/index - - .. Indices and tables ================== diff --git a/spyrit/images/tuto/noise_op.png b/spyrit/images/tuto/noise_op.png deleted file mode 100644 index 01b2024b..00000000 Binary files a/spyrit/images/tuto/noise_op.png and /dev/null differ diff --git a/spyrit/tutorial/README.txt b/tutorial/README.txt similarity index 100% rename from spyrit/tutorial/README.txt rename to tutorial/README.txt diff --git a/spyrit/images/test/ILSVRC2012_test_00000001.jpeg b/tutorial/images/test/ILSVRC2012_test_00000001.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000001.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000001.jpeg diff --git a/spyrit/images/test/ILSVRC2012_test_00000002.jpeg b/tutorial/images/test/ILSVRC2012_test_00000002.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000002.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000002.jpeg diff --git a/spyrit/images/test/ILSVRC2012_test_00000003.jpeg b/tutorial/images/test/ILSVRC2012_test_00000003.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000003.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000003.jpeg diff --git a/spyrit/images/test/ILSVRC2012_test_00000004.jpeg b/tutorial/images/test/ILSVRC2012_test_00000004.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000004.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000004.jpeg diff --git a/spyrit/images/test/ILSVRC2012_test_00000005.jpeg b/tutorial/images/test/ILSVRC2012_test_00000005.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000005.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000005.jpeg diff --git a/spyrit/images/test/ILSVRC2012_test_00000006.jpeg b/tutorial/images/test/ILSVRC2012_test_00000006.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000006.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000006.jpeg diff --git a/spyrit/images/test/ILSVRC2012_test_00000007.jpeg b/tutorial/images/test/ILSVRC2012_test_00000007.jpeg similarity index 100% rename from spyrit/images/test/ILSVRC2012_test_00000007.jpeg rename to tutorial/images/test/ILSVRC2012_test_00000007.jpeg diff --git a/spyrit/tutorial/tuto_01_acquisition_operators.py b/tutorial/tuto_01_acquisition_operators.py similarity index 93% rename from spyrit/tutorial/tuto_01_acquisition_operators.py rename to tutorial/tuto_01_acquisition_operators.py index 5f1ad49f..3c76fdd1 100644 --- a/spyrit/tutorial/tuto_01_acquisition_operators.py +++ b/tutorial/tuto_01_acquisition_operators.py @@ -2,6 +2,7 @@ 01. Acquisition operators ========================== .. _tuto_acquisition_operators: + This tutorial shows how to simulate measurements using the :class:`spyrit.core` submodule, which is based on three classes: @@ -14,15 +15,9 @@ 3. **Preprocessing operators** are typically used to process the noisy measurements prior to reconstruction (see :mod:`spyrit.core.prep`) -These tutorials must be runned from `spyrit/tutorial/` folder (they load image samples from `spyrit/images/`). +These tutorials load image samples from `/images/`. """ -import numpy as np -import os -from spyrit.misc.disp import imagesc -import matplotlib.pyplot as plt - - # %% # Load a batch of images # ----------------------------------------------------------------------------- @@ -31,16 +26,20 @@ # Images :math:`x` for training neural networks expect values in [-1,1]. The images are normalized # using the :func:`transform_gray_norm` function. -# sphinx_gallery_thumbnail_path = '../../spyrit/images/tuto/noise_op.png' +import os -from spyrit.misc.statistics import transform_gray_norm -import torchvision import torch +import torchvision +import numpy as np +import matplotlib.pyplot as plt + +from spyrit.misc.disp import imagesc +from spyrit.misc.statistics import transform_gray_norm h = 64 # image size hxh i = 1 # Image index (modify to change the image) spyritPath = os.getcwd() -imgs_path = os.path.join(spyritPath, "../images") +imgs_path = os.path.join(spyritPath, "images/") # Create a transform for natural images to normalized grayscale image tensors @@ -69,10 +68,13 @@ ############################################################################### # Noise operators are defined in the :mod:`~spyrit.core.noise` module. A noise # operator computes the following three steps sequentially: -# 1. Normalization of the image :math:`x` with values in [-1,1] to get an -# image :math:`\tilde{x}=\frac{x+1}{2}` in [0,1], as it is required for measurement simulation -# 2. Application of the measurement model, i.e., computation of :math:`H\tilde{x}` -# 3. Application of the noise model +# +# 1. Normalization of the image :math:`x` with values in [-1,1] to get an image +# :math:`\tilde{x}=\frac{x+1}{2}` in [0,1], as it is required for measurement simulation +# +# 2. Application of the measurement model, i.e., computation of :math:`H\tilde{x}` +# +# 3. Application of the noise model # # .. math:: # y \sim \texttt{Noise}(H\tilde{x}) = \texttt{Noise}\left(\frac{H(x+1)}{2}\right), @@ -215,9 +217,11 @@ ############################################################################### # We consider the :class:`spyrit.core.prep.DirectPoisson` class that intends -# to "undo" the :class:`spyrit.core.noise.Poisson` class by compensating for -# * the scaling that appears when computing Poisson-corrupted measurements -# * the affine transformation to get images in [0,1] from images in [-1,1] +# to "undo" the :class:`spyrit.core.noise.Poisson` class by compensating for: +# +# * the scaling that appears when computing Poisson-corrupted measurements +# +# * the affine transformation to get images in [0,1] from images in [-1,1] # # For this, it computes # @@ -281,4 +285,6 @@ # We show again one of the preprocessed measurement vectors (tutorial thumbnail purpose) # Plot +# Choose this plot to be the thumbnail +# sphinx_gallery_thumbnail_number = 5 imagesc(m2[0, :, :], "100 photons", title_fontsize=20) diff --git a/spyrit/tutorial/tuto_02_pseudoinverse_linear.py b/tutorial/tuto_02_pseudoinverse_linear.py similarity index 95% rename from spyrit/tutorial/tuto_02_pseudoinverse_linear.py rename to tutorial/tuto_02_pseudoinverse_linear.py index 6041c83e..1be54f8d 100644 --- a/spyrit/tutorial/tuto_02_pseudoinverse_linear.py +++ b/tutorial/tuto_02_pseudoinverse_linear.py @@ -2,11 +2,12 @@ 02. Pseudoinverse solution from linear measurements =================================================== .. _tuto_pseudoinverse_linear: + This tutorial shows how to simulate measurements and perform image reconstruction. The measurement operator is chosen as a Hadamard matrix with positive coefficients. Note that this matrix can be replaced by any desired matrix. -These tutorials must be runned from `spyrit/tutorial/` folder (they load image samples from `spyrit/images/`). +These tutorials load image samples from `/images/`. """ # %% @@ -17,18 +18,19 @@ # Images :math:`x` for training expect values in [-1,1]. The images are normalized # using the :func:`transform_gray_norm` function. -# sphinx_gallery_thumbnail_path = '../../spyrit/images/tuto/pinvnet.png' - import os -from spyrit.misc.statistics import transform_gray_norm -import torchvision + import torch +import torchvision +import numpy as np + from spyrit.misc.disp import imagesc +from spyrit.misc.statistics import transform_gray_norm h = 64 # image size hxh i = 1 # Image index (modify to change the image) spyritPath = os.getcwd() -imgs_path = os.path.join(spyritPath, "../images") +imgs_path = os.path.join(spyritPath, "images/") # Create a transform for natural images to normalized grayscale image tensors @@ -62,13 +64,13 @@ # image of size :attr:`h` and takes its positive part. from spyrit.misc.walsh_hadamard import walsh2_matrix -import numpy as np F = walsh2_matrix(h) F = np.where(F > 0, F, 0) ############################################################################### # .. _low_frequency: +# # Next, we subsample the rows of the measurement matrix to simulate an # accelerated acquisition. For this, we use the # :func:`spyrit.misc.sampling.Permutation_Matrix` function @@ -142,11 +144,11 @@ ############################################################################### # We now compute and plot the preprocessed measurements corresponding to an -# image in [-1,1]. For details in the preprocessing, see :ref:`tuto_acquisition_operators`. +# image in [-1,1]. For details in the preprocessing, see :ref:`Tutorial 1 `. # # .. note:: # -# Using :class:`spyrit.core.prep.DirectPoisson` with :math:`\alpha` = 1 +# Using :class:`spyrit.core.prep.DirectPoisson` with :math:`\alpha = 1` # allows to compensate for the image normalisation achieved by # :class:`spyrit.core.noise.NoNoise`. @@ -181,6 +183,8 @@ x_rec = recon_op(y, meas_op) # plot +# Choose this plot to be the thumbnail +# sphinx_gallery_thumbnail_number = 5 x_plot = x_rec.squeeze().view(h, h).cpu().numpy() imagesc(x_plot, "Pseudoinverse reconstruction (no noise)", title_fontsize=20) @@ -195,7 +199,7 @@ # can be set to the identity operator ############################################################################### -# .. image:: ../../../spyrit/images/tuto/pinvnet.png +# .. image:: /spyrit/docs/source/fig/pinvnet.png # :width: 400 # :align: center # :alt: Sketch of the PinvNet architecture @@ -248,7 +252,7 @@ ############################################################################### # Here, we consider the :class:`spyrit.core.noise.Poisson` class # together with a :class:`spyrit.core.prep.DirectPoisson` -# preprocessing operator (see :ref:`tuto_acquisition_operators`). +# preprocessing operator (see :ref:`Tutorial 1 `). alpha = 10 # maximum number of photons in the image diff --git a/spyrit/tutorial/tuto_03_pseudoinverse_cnn_linear.py b/tutorial/tuto_03_pseudoinverse_cnn_linear.py similarity index 97% rename from spyrit/tutorial/tuto_03_pseudoinverse_cnn_linear.py rename to tutorial/tuto_03_pseudoinverse_cnn_linear.py index e6fd690a..13456a49 100644 --- a/spyrit/tutorial/tuto_03_pseudoinverse_cnn_linear.py +++ b/tutorial/tuto_03_pseudoinverse_cnn_linear.py @@ -2,6 +2,7 @@ 03. Pseudoinverse solution + CNN denoising ========================================== .. _tuto_pseudoinverse_cnn_linear: + This tutorial shows how to simulate measurements and perform image reconstruction using PinvNet (pseudoinverse linear network) with CNN denoising as a last layer. This tutorial is a continuation of the :ref:`Pseudoinverse solution tutorial ` @@ -9,6 +10,8 @@ The measurement operator is chosen as a Hadamard matrix with positive coefficients, which can be replaced by any matrix. + +These tutorials load image samples from `/images/`. """ # %% @@ -19,18 +22,20 @@ # Images :math:`x` for training expect values in [-1,1]. The images are normalized # using the :func:`transform_gray_norm` function. -# sphinx_gallery_thumbnail_path = '../../spyrit/images/tuto/pinvnet_cnn.png' - import os -from spyrit.misc.statistics import transform_gray_norm -import torchvision + import torch +import torchvision +import numpy as np +import matplotlib.pyplot as plt + from spyrit.misc.disp import imagesc +from spyrit.misc.statistics import transform_gray_norm h = 64 # image size hxh i = 1 # Image index (modify to change the image) spyritPath = os.getcwd() -imgs_path = os.path.join(spyritPath, "../images") +imgs_path = os.path.join(spyritPath, "images/") # Create a transform for natural images to normalized grayscale image tensors transform = transform_gray_norm(img_size=h) @@ -62,7 +67,6 @@ # the first :attr:`M` low-frequency coefficients # (see :ref:`Positive Hadamard matrix ` for full explantion). -import numpy as np import math from spyrit.misc.sampling import Permutation_Matrix from spyrit.misc.walsh_hadamard import walsh2_matrix @@ -167,12 +171,11 @@ # neural network (eg. UNet from :class:`spyrit.core.nnet.Unet`). ############################################################################### -# .. image:: ../../../spyrit/images/tuto/pinvnet_cnn.png +# .. image:: /spyrit/docs/source/fig/pinvnet_cnn.png # :width: 400 # :align: center # :alt: Sketch of the PinvNet with CNN architecture -from spyrit.misc.disp import imagesc from spyrit.core.nnet import ConvNet, Unet from spyrit.core.train import load_net @@ -244,7 +247,6 @@ x_plot2 = x_rec.squeeze().cpu().numpy() x_plot3 = x_rec_cnn.squeeze().cpu().numpy() -import matplotlib.pyplot as plt from spyrit.misc.disp import add_colorbar, noaxis f, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5)) @@ -267,6 +269,8 @@ # We show the best result again (tutorial thumbnail purpose) # Plot +# We choose this plot for the thumbnail +# sphinx_gallery_thumbnail_number = 5 imagesc(x_plot3, f"Pinv + CNN (trained {num_epochs} epochs", title_fontsize=20) plt.show() diff --git a/spyrit/tutorial/tuto_04_train_pseudoinverse_cnn_linear.py b/tutorial/tuto_04_train_pseudoinverse_cnn_linear.py similarity index 99% rename from spyrit/tutorial/tuto_04_train_pseudoinverse_cnn_linear.py rename to tutorial/tuto_04_train_pseudoinverse_cnn_linear.py index 7f804b39..f4086aa5 100644 --- a/spyrit/tutorial/tuto_04_train_pseudoinverse_cnn_linear.py +++ b/tutorial/tuto_04_train_pseudoinverse_cnn_linear.py @@ -2,6 +2,7 @@ 04. Train pseudoinverse solution + CNN denoising ================================================ .. _tuto_train_pseudoinverse_cnn_linear: + This tutorial shows how to train PinvNet with a CNN denoiser for reconstruction of linear measurements (results shown in the :ref:`previous tutorial `). @@ -14,6 +15,8 @@ The linear measurement operator is chosen as the positive part of a Hadamard matrix, but this matrix can be replaced by any desired matrix. + +These tutorials load image samples from `/images/`. """ # %% @@ -24,15 +27,19 @@ # First, we load an image :math:`x` and normalized it to [-1,1], as in previous examples. import os -from spyrit.misc.statistics import transform_gray_norm -import torchvision + import torch +import torchvision +import numpy as np +import matplotlib.pyplot as plt + from spyrit.misc.disp import imagesc +from spyrit.misc.statistics import transform_gray_norm h = 64 # image size hxh i = 1 # Image index (modify to change the image) spyritPath = os.getcwd() -imgs_path = os.path.join(spyritPath, "../images") +imgs_path = os.path.join(spyritPath, "images/") # Create a transform for natural images to normalized grayscale image tensors @@ -97,10 +104,8 @@ # Then, we simulate an accelerated acquisition by keeping only the first # :attr:`M` low-frequency coefficients (see :ref:`low frequency sampling `). -from spyrit.misc.walsh_hadamard import walsh2_matrix -import numpy as np import math -from spyrit.misc.disp import imagesc +from spyrit.misc.walsh_hadamard import walsh2_matrix from spyrit.misc.sampling import Permutation_Matrix und = 4 # undersampling factor @@ -148,7 +153,6 @@ # Then, we define the PinvNet network by passing the noise and preprocessing operators # and the denoiser. -import torch from spyrit.core.nnet import ConvNet from spyrit.core.recon import PinvNet @@ -330,7 +334,6 @@ # Plot # sphinx_gallery_thumbnail_number = 2 -import matplotlib.pyplot as plt fig = plt.figure() plt.plot(train_info["train"], label="train") diff --git a/spyrit/tutorial/tuto_05_acquisition_split_measurements.py b/tutorial/tuto_05_acquisition_split_measurements.py similarity index 91% rename from spyrit/tutorial/tuto_05_acquisition_split_measurements.py rename to tutorial/tuto_05_acquisition_split_measurements.py index 713307b4..4fbe9f03 100644 --- a/spyrit/tutorial/tuto_05_acquisition_split_measurements.py +++ b/tutorial/tuto_05_acquisition_split_measurements.py @@ -1,21 +1,18 @@ r""" 05. Acquisition operators (advanced) - Split measurements and subsampling -================================================ +========================================================================= .. _tuto_acquisition_split_measurements: + This tutorial is a continuation of the :ref:`Acquisition operators tutorial ` for single-pixel imaging, which showed how to simulate linear measurements using the :class:`spyrit.core` submodule (based on three classes :class:`spyrit.core.meas`, :class:`spyrit.core.noise`, and :class:`spyrit.core.prep`). This tutorial extends the previous case: i) by introducing split measurements that can handle a Hadamard measurement matrix, and ii) by discussing the choice of the subsampling pattern for accelerated acquisitions. -""" - -import numpy as np -import os -from spyrit.misc.disp import imagesc -import matplotlib.pyplot as plt +These tutorials load image samples from `/images/`. +""" # %% # Load a batch of images @@ -25,14 +22,21 @@ # Images :math:`x` for training neural networks expect values in [-1,1]. The images are normalized # using the :func:`transform_gray_norm` function. -from spyrit.misc.statistics import transform_gray_norm -import torchvision +import os + import torch +import torchvision +import numpy as np +import matplotlib.pyplot as plt + +from spyrit.misc.disp import imagesc +from spyrit.misc.statistics import transform_gray_norm + h = 64 # image size hxh i = 1 # Image index (modify to change the image) spyritPath = os.getcwd() -imgs_path = os.path.join(spyritPath, "../images") +imgs_path = os.path.join(spyritPath, "images/") # Create a transform for natural images to normalized grayscale image tensors @@ -62,10 +66,13 @@ ############################################################################### # Noise operators are defined in the :mod:`~spyrit.core.noise` module. A noise # operator computes the following three steps sequentially: -# 1. Normalization of the image :math:`x` with values in [-1,1] to get an -# image :math:`\tilde{x}=\frac{x+1}{2}` in [0,1], as it is required for measurement simulation -# 2. Application of the measurement model, i.e., computation of :math:`P\tilde{x}` -# 3. Application of the noise model +# +# 1. Normalization of the image :math:`x` with values in [-1,1] to get an +# image :math:`\tilde{x}=\frac{x+1}{2}` in [0,1], as it is required for measurement simulation +# +# 2. Application of the measurement model, i.e., computation of :math:`P\tilde{x}` +# +# 3. Application of the noise model # # .. math:: # y \sim \texttt{Noise}(P\tilde{x}) = \texttt{Noise}\left(\frac{P(x+1)}{2}\right). @@ -99,26 +106,28 @@ ############################################################################### # We simulate an accelerated acquisition by subsampling the measurement matrix. # We consider two subsampling strategies: -# * "Naive subsampling" by retaining only the first :math:`M` rows of the measurement matrix. -# * "Variance subsampling" by retaining only the first :math:`M` rows of a permuted measurement matrix -# where the first rows corresponds to the coefficients with largest variance and the last ones to -# the coefficients that are close to constant. The motivation is that almost constant coefficients are less informative than the others. -# This can be supported by principal component analysis, which states that preserving the components -# with largest variance leads to the best linear predictor. +# +# * "Naive subsampling" by retaining only the first :math:`M` rows of the measurement matrix. +# +# * "Variance subsampling" by retaining only the first :math:`M` rows of a permuted measurement matrix +# where the first rows corresponds to the coefficients with largest variance and the last ones to +# the coefficients that are close to constant. The motivation is that almost constant coefficients are less informative than the others. +# This can be supported by principal component analysis, which states that preserving the components +# with largest variance leads to the best linear predictor. ############################################################################### # Subsampling is done by retaining only the first :math:`M` rows of # a permuted Hadamard matrix :math:`\textrm{Perm} H`, where :math:`\textrm{Perm}` is a # permutation matrix with shape with shape :math:`(M,N)` and :math:`H` is a # "full" Hadamard matrix with shape :math:`(N,N)` -# (see Hadamard matrix in :ref:`tutorial on pseudoinverse solution `). +# (see Hadamard matrix in :ref:`tutorial on pseudoinverse solution `). # The permutation matrix :math:`\textrm{Perm}` is obtained from the ordering matrix # :math:`\textrm{Ord}` with shape :math:`(h,h)`. This is all handled internally # by the :class:`spyrit.core.meas.HadamSplit` class. ############################################################################### # First, we download the covariance matrix from our warehouse and load it. The covariance matrix -# has been computed from :ref:`ImageNet 2012 dataset `. +# has been computed from `ImageNet 2012 dataset `_. import girder_client @@ -269,8 +278,10 @@ ############################################################################### # We consider the :class:`spyrit.core.prep.SplitPoisson` class that intends # to "undo" the :class:`spyrit.core.noise.Poisson` class, for split measurements, by compensating for -# * the scaling that appears when computing Poisson-corrupted measurements -# * the affine transformation to get images in [0,1] from images in [-1,1] +# +# * the scaling that appears when computing Poisson-corrupted measurements +# +# * the affine transformation to get images in [0,1] from images in [-1,1] # # For this, it computes # diff --git a/spyrit/tutorial/tuto_06_dcnet_split_measurements.py b/tutorial/tuto_06_dcnet_split_measurements.py similarity index 95% rename from spyrit/tutorial/tuto_06_dcnet_split_measurements.py rename to tutorial/tuto_06_dcnet_split_measurements.py index 1c009d6c..fa25846e 100644 --- a/spyrit/tutorial/tuto_06_dcnet_split_measurements.py +++ b/tutorial/tuto_06_dcnet_split_measurements.py @@ -2,20 +2,16 @@ 06. DCNet solution for split measurements ========================================= .. _tuto_dcnet_split_measurements: + This tutorial shows how to perform image reconstruction using DCNet (data completion network) with and without a trainable image denoiser. In the previous tutorial :ref:`Acquisition - split measurements ` we showed how to handle split measurements for a Hadamard operator and how to perform a pseudo-inverse reconstruction with PinvNet. +These tutorials load image samples from `/images/`. """ -import numpy as np -import os -from spyrit.misc.disp import imagesc -import matplotlib.pyplot as plt - - # %% # Load a batch of images # ----------------------------------------------------------------------------- @@ -24,16 +20,20 @@ # Images :math:`x` for training neural networks expect values in [-1,1]. The images are normalized # using the :func:`transform_gray_norm` function. -# sphinx_gallery_thumbnail_path = '../../spyrit/images/tuto/dcnet.png' +import os -from spyrit.misc.statistics import transform_gray_norm -import torchvision import torch +import torchvision +import numpy as np +import matplotlib.pyplot as plt + +from spyrit.misc.disp import imagesc +from spyrit.misc.statistics import transform_gray_norm h = 64 # image size hxh i = 1 # Image index (modify to change the image) spyritPath = os.getcwd() -imgs_path = os.path.join(spyritPath, "../images") +imgs_path = os.path.join(spyritPath, "images/") # Create a transform for natural images to normalized grayscale image tensors @@ -163,14 +163,19 @@ ############################################################################### # We can improve PinvNet results by using the *denoised* completion network DCNet with the # :class:`spyrit.core.recon.DCNet` class. It has four sequential steps: -# i) denoising of the acquired measurements, -# ii) estimation of the missing measurements from the denoised ones, -# iii) mapping them to the image domain, and -# iv) denoising in the image-domain. +# +# i) denoising of the acquired measurements, +# +# ii) estimation of the missing measurements from the denoised ones, +# +# iii) mapping them to the image domain, and +# +# iv) denoising in the image-domain. +# # Only the last step involves learnable parameters. ############################################################################### -# .. image:: ../../../spyrit/images/tuto/dcnet.png +# .. image:: /spyrit/docs/source/fig/dcnet.png # :width: 400 # :align: center # :alt: Sketch of the DCNet architecture @@ -247,6 +252,8 @@ ############################################################################### # We plot all results +# We choose this plot as thumbnail +# sphinx_gallery_thumbnail_number = 3 # plot reconstruction side by side x_plot = x.view(-1, h, h).cpu().numpy() x_plot2 = z_invnet.view(-1, h, h).cpu().numpy() diff --git a/spyrit/tutorial/tuto_bonus_advanced_methods_colab.py b/tutorial/tuto_bonus_advanced_methods_colab.py similarity index 94% rename from spyrit/tutorial/tuto_bonus_advanced_methods_colab.py rename to tutorial/tuto_bonus_advanced_methods_colab.py index 2223958b..e1b76dc9 100644 --- a/spyrit/tutorial/tuto_bonus_advanced_methods_colab.py +++ b/tutorial/tuto_bonus_advanced_methods_colab.py @@ -1,7 +1,8 @@ r""" Bonus. Advanced methods - Colab -============================ +=============================== .. _tuto_advanced_methods_colab: + We refer to `spyrit-examples/tutorial `_ for a list of tutorials that can be run directly in colab and present more advanced cases than the main spyrit tutorials, such as comparison of methods for split measurements, or comparison of different denoising networks.