Skip to content

Commit 0671e54

Browse files
authored
Package refactor, update to v1.0.0 (#15)
* Forward interp working * New interp fn, sparse matrices * Add old data * Rename NUFFT folder * NUFFT test working * SENSE-NUFFT data * Add description * SENSE-NUFFT tests * Last task: toeplitz * File renaming * Torchscript fft ops * Removal of complex flow control * Remove more complex flow control * view to reshape * Toeplitz working * Remove extra fn * Update init, toep test * Remove unnecessarsy function file * Formatting * Add back CPU interp fn * Update dev requirements * Update readme * Update dcomp * Don't distribute docs * Update setup * Add dcomp test * Update toep kernel api * Update README * Update repr * Rename module * Add documentation * New basic notebook * Update notebooks * Update project name * Updated documentation * Template updates * Update class docs * Finished docs * Finalize docs, push branch * Update readme * Update docs link * Fix requires * Update credti * Fix Toeplitz link * Notebook link * Update readme * Update README * Update README * Update math * kbinterp docstring * Update kbinterp doc * Add nufft examples * Update fftshift doc * Typos * Lower-case x * DOI links * Add oversampling * Doc updates * Shorten stubs * Add a caption * Update all refs * Fix links * More doc fixes * Move toc location * Fix fn signature * Doc updates * Much faster CPU adjoint * Small fixes for GPU * Remove commented code * Fix format * Update compute times * Update comment * README tweaks * Remove Sedona * Update readme * Remove trailing space * Add GPU interp test * Fix workflow description * Fix notation * Fix grammar * Update doc * Fix threading * Doc updates * Restrict thread management to OMP * Fix numpy reference * mypy fixes * Comment update * Add contributing, update README * Update contributing * Typo * Add 3D option * Better way of doing forward * Final update * Fix 8 threads
1 parent 7b094a0 commit 0671e54

File tree

96 files changed

+5241
-6346
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+5241
-6346
lines changed

.flake8

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[flake8]
2+
max-line-length=88
3+
per-file-ignores=__init__.py:F401
4+
extend-exclude = *brain_challenge*,*2020-08*
5+
extend-ignore = E203, E266, E501

.github/workflows/python-app.yml

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@ on: [push, pull_request]
77

88
jobs:
99
build-and-test:
10-
1110
runs-on: ubuntu-latest
1211

1312
steps:
14-
- uses: actions/checkout@v2
15-
- name: Set up Python 3.9
16-
uses: actions/setup-python@v2
17-
with:
18-
python-version: 3.8
19-
- name: Install dependencies
20-
run: |
21-
python -m pip install --upgrade pip
22-
pip install -r dev-requirements.txt
23-
pip install -e .
24-
- name: Format and lint
25-
run: |
26-
black --check .
27-
- name: Test with pytest
28-
run: |
29-
pytest tests
13+
- uses: actions/checkout@v2
14+
- name: Set up Python 3.8
15+
uses: actions/setup-python@v2
16+
with:
17+
python-version: 3.8
18+
- name: Install dependencies
19+
run: |
20+
python -m pip install --upgrade pip
21+
pip install -r dev-requirements.txt
22+
pip install -e .
23+
- name: Format and lint
24+
run: |
25+
black --check .
26+
flake8 torchkbnufft
27+
mypy torchkbnufft
28+
- name: Test with pytest
29+
run: |
30+
pytest tests

CONTRIBUTING.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Contributing Guide
2+
3+
`torchkbnufft` welcomes contributions!
4+
5+
## Submitting Code
6+
7+
To submit code, take the following steps:
8+
9+
1. Fork the repository and make your changes.
10+
2. Add unit tests for any new functions or modules.
11+
3. Ensure your test suite passes.
12+
4. Make sure your code lints - we use [`black`](https://black.readthedocs.io/en/stable/),
13+
[`flake8`](https://flake8.pycqa.org/en/latest/), and
14+
[`mypy`](https://mypy.readthedocs.io/en/stable/).
15+
5. Add documentation. If you've added new functions that are exposed under
16+
`torchkbnufft`, ensure that they're properly linked in the `docs/` folder.
17+
6. Submit a [Pull Request](https://github.com/mmuckley/torchkbnufft/pulls) to
18+
bring your code into master!
19+
20+
We continuously check linting and unit tests using GitHub integrations for all
21+
Pull Requests. If your code fails any of the tests, make the appropriate
22+
changes and the tool will automatically retest your code.
23+
24+
## Issues
25+
26+
If you identify a bug or have a question, please fill out a GitHub issue and I
27+
will address it as soon as I can.
28+
29+
## License
30+
31+
By submitting your code to the repository, you agree to have your submission
32+
licensed under the terms in the LICENSE file at the root directory of this
33+
source tree.

README.md

Lines changed: 98 additions & 79 deletions
Large diffs are not rendered by default.

dev-requirements.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
-r requirements.txt
2-
black
3-
pytest
4-
flake8
5-
mypy
2+
black==20.8b1
3+
pytest==6.1.1
4+
flake8==3.8.4
5+
mypy==0.790
6+
pillow==8.0.1

docs/requirements.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
sphinx
2-
sphinx-autoapi
3-
sphinx-rtd-theme
2+
sphinx-rtd-theme
3+
sphinxcontrib-katex
4+
sphinx-autodoc-typehints
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.. role:: hidden
2+
:class: hidden-section
3+
.. currentmodule:: {{ module }}
4+
5+
6+
{{ name | underline}}
7+
8+
.. autoclass:: {{ name }}
9+
:inherited-members:
10+
:members:
11+
12+
.. autogenerated from source/_templates/autosummary/class.rst
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.. role:: hidden
2+
:class: hidden-section
3+
.. currentmodule:: {{ module }}
4+
5+
6+
{{ name | underline}}
7+
8+
.. autoclass:: {{ name }}
9+
:members:
10+
11+
12+
..
13+
autogenerated from source/_templates/classtemplate.rst
14+
note it does not have :inherited-members:
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.. role:: hidden
2+
:class: hidden-section
3+
.. currentmodule:: {{ module }}
4+
5+
6+
{{ name | underline}}
7+
8+
.. autofunction:: {{ name }}
9+
10+
11+
..
12+
autogenerated from source/_templates/classtemplate.rst
13+
note it does not have :inherited-members:

docs/source/_templates/module.rst_t

Lines changed: 0 additions & 9 deletions
This file was deleted.

docs/source/_templates/package.rst_t

Lines changed: 0 additions & 46 deletions
This file was deleted.

docs/source/_templates/toc.rst_t

Lines changed: 0 additions & 8 deletions
This file was deleted.

docs/source/basic.rst

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
Basic Usage
2+
=============
3+
4+
:py:mod:`torchkbnufft` works primarily via PyTorch modules. You create a module with
5+
the properties of your imaging setup. The module will calculate a Kaiser-Bessel
6+
kernel and some interpolation parameters based on your inputs. Then, you apply
7+
the module to your data stored as PyTorch tensors. NUFFT operations are wrapped in
8+
:py:class:`torch.autograd.Function` classes for backpropagation and training
9+
neural networks.
10+
11+
The following code loads a Shepp-Logan phantom and computes a single
12+
radial spoke of k-space data:
13+
14+
.. code-block:: python
15+
16+
import torch
17+
import torchkbnufft as tkbn
18+
import numpy as np
19+
from skimage.data import shepp_logan_phantom
20+
21+
x = shepp_logan_phantom().astype(np.complex)
22+
im_size = x.shape
23+
# convert to tensor, unsqueeze batch and coil dimension
24+
# output size: (1, 1, ny, nx)
25+
x = torch.tensor(x).unsqueeze(0).unsqueeze(0).to(torch.complex64)
26+
27+
klength = 64
28+
ktraj = np.stack(
29+
(np.zeros(64), np.linspace(-np.pi, np.pi, klength))
30+
)
31+
# convert to tensor, unsqueeze batch dimension
32+
# output size: (2, klength)
33+
ktraj = torch.tensor(ktraj).to(torch.float)
34+
35+
nufft_ob = tkbn.KbNufft(im_size=im_size)
36+
# outputs a (1, 1, klength) vector of k-space data
37+
kdata = nufft_ob(x, ktraj)
38+
39+
The package also includes utilities for working with SENSE-NUFFT operators. The
40+
above code can be modified to include sensitivity maps.
41+
42+
.. code-block:: python
43+
44+
smaps = torch.rand(1, 8, 400, 400) + 1j * torch.rand(1, 8, 400, 400)
45+
sense_data = nufft_ob(x, ktraj, smaps=smaps.to(x))
46+
47+
This code first multiplies by the sensitivity coils in ``smaps``, then
48+
computes a 64-length radial spoke for each coil. All operations are broadcast
49+
across coils, which minimizes interaction with the Python interpreter, helping
50+
computation speed.
51+
52+
Sparse matrices are an alternative to table interpolation. Their speed can
53+
vary, but they are a bit more accurate than standard table mode. The following
54+
code calculates sparse interpolation matrices and uses them to compute a single
55+
radial spoke of k-space data:
56+
57+
.. code-block:: python
58+
59+
adjnufft_ob = tkbn.KbNufftAdjoint(im_size=im_size)
60+
61+
# precompute the sparse interpolation matrices
62+
interp_mats = tkbn.calc_tensor_spmatrix(
63+
ktraj,
64+
im_size=im_size
65+
)
66+
67+
# use sparse matrices in adjoint
68+
image = adjnufft_ob(kdata, ktraj, interp_mats)
69+
70+
Sparse matrix multiplication is only implemented for real numbers in PyTorch,
71+
which can limit their speed.
72+
73+
The package includes routines for calculating
74+
`embedded Toeplitz kernels <https://doi.org/10.1007/s002110050101>`_ and
75+
using them as FFT filters for the forward/backward NUFFT operations. This is very useful
76+
for gradient descent algorithms that must use the forward/backward ops in calculating
77+
the gradient. The following code shows an example:
78+
79+
.. code-block:: python
80+
81+
adjnufft_ob = tkbn.KbNufftAdjoint(im_size=im_size)
82+
toep_ob = tkbn.ToepNufft()
83+
84+
# precompute the embedded Toeplitz FFT kernel
85+
kernel = tkbn.calc_toeplitz_kernel(ktraj, im_size)
86+
87+
# use FFT kernel from embedded Toeplitz matrix
88+
image = toep_ob(image, kernel)
89+
90+
All of the examples included in this repository can be run on the GPU by
91+
sending the NUFFT object and data to the GPU prior to the function call, e.g.,
92+
93+
.. code-block:: python
94+
95+
adjnufft_ob = adjnufft_ob.to(torch.device('cuda'))
96+
kdata = kdata.to(torch.device('cuda'))
97+
ktraj = ktraj.to(torch.device('cuda'))
98+
99+
image = adjnufft_ob(kdata, ktraj)
100+
101+
Similar to programming low-level code, PyTorch will throw errors if the
102+
underlying ``dtype`` and ``device`` of all objects are not matching. Be
103+
sure to make sure your data and NUFFT objects are on the right device and in
104+
the right format to avoid these errors.
105+
106+
For more details, please examine the API in :doc:`torchkbnufft` or the `notebooks
107+
<https://github.com/mmuckley/torchkbnufft/tree/master/notebooks>`_
108+
in the GitHub repository.

0 commit comments

Comments
 (0)