Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster DCF based on pipe #629

Draft
wants to merge 57 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
38f33fb
tests added
ckolbPTB Oct 22, 2024
74e6250
doc strings
ckolbPTB Oct 22, 2024
60fca9e
Update src/mrpro/operators/NonUniformFastFourierOp.py
fzimmermann89 Oct 22, 2024
fed8954
merge main
ckolbPTB Oct 23, 2024
2659402
review
ckolbPTB Oct 23, 2024
cc1472d
input pars and doc string adapted
ckolbPTB Oct 23, 2024
0c29b01
Merge branch 'main' into separate_nufft_op
ckolbPTB Oct 23, 2024
393c5a9
Merge branch 'main' into separate_nufft_op
ckolbPTB Oct 23, 2024
276873e
test for nufft output added
ckolbPTB Oct 23, 2024
89e36bc
Merge branch 'main' into separate_nufft_op
ckolbPTB Oct 24, 2024
3c6d873
empty dim
ckolbPTB Oct 24, 2024
d2fb391
Update tests/operators/test_non_uniform_fast_fourier_op.py
ckolbPTB Dec 5, 2024
a4b8a64
merge main
ckolbPTB Dec 5, 2024
2a90533
fix merge problems
ckolbPTB Dec 5, 2024
b67bef6
fix more merge problems
ckolbPTB Dec 5, 2024
9b60be2
gram and cart_samp fixed
ckolbPTB Dec 5, 2024
281e5bc
spatial dims and test for unsupported direction added
ckolbPTB Dec 5, 2024
4b8d8fb
nufft dim automatically detected
ckolbPTB Dec 6, 2024
aba850d
fix for single shot traj and further tests added
ckolbPTB Dec 11, 2024
6ba3fb4
remove superfluous tests
ckolbPTB Dec 11, 2024
b7c83e6
first try
ckolbPTB Dec 11, 2024
8270de5
forward adapted
ckolbPTB Dec 11, 2024
e73ace5
adjoint adapted
ckolbPTB Dec 11, 2024
e586360
add _nufft_type1 and _nufft_type2
ckolbPTB Dec 12, 2024
9977205
clean up
ckolbPTB Dec 12, 2024
4b70389
sep dims and joint dims for forward and adjoint
ckolbPTB Dec 12, 2024
01ca1dc
gram started
ckolbPTB Dec 12, 2024
87f51c2
gram finished for nufft
ckolbPTB Dec 12, 2024
6585ab9
tests adapted and bug fix
ckolbPTB Dec 13, 2024
2330e3d
add rpe to conftest
ckolbPTB Dec 13, 2024
739d76c
conftest update
ckolbPTB Dec 13, 2024
d8217e8
use given kshape
ckolbPTB Dec 14, 2024
1bccb41
conftest error fixed
ckolbPTB Dec 14, 2024
b11acf0
misalignment k210 and kzyx still a problem
ckolbPTB Dec 14, 2024
b2d58fa
tidy up
ckolbPTB Dec 14, 2024
d027e4a
Merge branch 'main' into separate_nufft_op
ckolbPTB Dec 14, 2024
302782c
joint dims zyx
ckolbPTB Dec 16, 2024
4382d68
nufft gram separated out
ckolbPTB Dec 16, 2024
f364526
Merge branch 'main' into separate_nufft_op
ckolbPTB Dec 16, 2024
2d9c51a
merge main
ckolbPTB Jan 10, 2025
3cd6c8e
gram adj_nufft separate, test fix and speed up
ckolbPTB Jan 10, 2025
9e229da
fix cart traj calc
ckolbPTB Jan 10, 2025
8ae651c
Merge branch 'main' into separate_nufft_op
ckolbPTB Jan 20, 2025
06a7d91
Merge branch 'main' into separate_nufft_op
ckolbPTB Jan 22, 2025
32317f9
docs formatting
ckolbPTB Jan 22, 2025
5386333
Merge branch 'main' into separate_nufft_op
fzimmermann89 Jan 30, 2025
bfc6b28
[pre-commit] auto fixes from pre-commit hooks
pre-commit-ci[bot] Jan 30, 2025
d5279d3
Merge branch 'main' into separate_nufft_op
ckolbPTB Jan 30, 2025
19056e3
small changes
fzimmermann89 Jan 31, 2025
e8d3c40
docstring
fzimmermann89 Jan 31, 2025
f894e78
test
fzimmermann89 Jan 31, 2025
d53c4a2
partially adress oversamping in tests
fzimmermann89 Jan 31, 2025
ffb3b9b
scaling
fzimmermann89 Jan 31, 2025
63c36cb
lint
fzimmermann89 Jan 31, 2025
611b6ba
Merge branch 'main' into separate_nufft_op
fzimmermann89 Jan 31, 2025
0ba382c
proof of concept: dcf
fzimmermann89 Feb 1, 2025
690f214
Merge branch 'main' into estimatedcf
fzimmermann89 Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 96 additions & 1 deletion examples/notebooks/direct_reconstruction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -391,13 +391,108 @@
"cell_type": "code",
"execution_count": null,
"id": "32",
"metadata": {},
"metadata": {
"lines_to_next_cell": 2
},
"outputs": [],
"source": [
"# If the assert statement did not raise an exception, the results are equal.\n",
"torch.testing.assert_close(img.data, img_manual.data)\n",
"torch.testing.assert_close(img.data, img_more_manual.data, atol=1e-4, rtol=1e-4)"
]
},
{
"cell_type": "markdown",
"id": "33",
"metadata": {
"lines_to_next_cell": 0
},
"source": [
"Faster DCF"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34",
"metadata": {},
"outputs": [],
"source": [
"from mrpro.data import KTrajectory\n",
"from mrpro.operators import FourierOp\n",
"\n",
"\n",
"def estimate_dcf(trajectory: KTrajectory, fourier_op: FourierOp, max_iter: int = 0) -> torch.Tensor:\n",
" \"\"\"Estimate the density compensation factors for a given trajectory.\n",
"\n",
" Uses the Jackson or Pipe method to estimate the density of an arbitrary set of points.\n",
" If max_iter is set to 0, the Jackson method is used. Otherwise, the Pipe method is used.\n",
"\n",
" Parameters\n",
" ----------\n",
" trajectory\n",
" Shap `(*other, 2 or 3, k2, k1, k0)`\n",
" fourier_op\n",
" The Fourier operator\n",
" max_iter\n",
" The number of iterations to use for the Pipe method. If set to 0, the Jackson method is used.\n",
"\n",
" Returns\n",
" -------\n",
" density estimate\n",
"\n",
" References\n",
" ----------\n",
" .. [1] Jackson, J.I., Meyer, C.H., Nishimura, D.G. and Macovski, A. (1991),\n",
" Selection of a convolution function for Fourier inversion using gridding\n",
" (computerized tomography application). IEEE Transactions on Medical\n",
" Imaging, 10(3): 473-478. https://doi.org/10.1109/42.97598\n",
" .. [2] Pipe, J.G. and Menon, P. (1999), Sampling density compensation in\n",
" MRI: Rationale and an iterative numerical solution. Magn. Reson. Med.,\n",
" 41: 179-186. https://doi.org/10.1002/(SICI)1522-2594(199901)41:1<179::AID-MRM25>3.0.CO;2-V\n",
" \"\"\"\n",
" ones = torch.ones(trajectory.broadcasted_shape, dtype=torch.complex64).unsqueeze(-4)\n",
" if fourier_op._non_uniform_fast_fourier_op is None:\n",
" # cartesian\n",
" return ones\n",
" op = fourier_op._non_uniform_fast_fourier_op @ fourier_op._non_uniform_fast_fourier_op.H\n",
" weight = op(ones)[0].reciprocal().nan_to_num()\n",
" for _ in range(max_iter):\n",
" weight *= op(weight)[0].reciprocal().nan_to_num()\n",
" return weight.abs().squeeze(-4)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "35",
"metadata": {
"lines_to_next_cell": 0
},
"outputs": [],
"source": [
"fourier_operator = mrpro.operators.FourierOp.from_kdata(kdata)\n",
"dcf_operator2 = mrpro.data.DcfData(estimate_dcf(kdata.traj, fourier_operator)).as_operator()\n",
"adjoint1 = (dcf_operator @ fourier_operator @ csm_operator).H\n",
"adjoint2 = (dcf_operator2 @ fourier_operator @ csm_operator).H\n",
"(img1,) = adjoint1(kdata.data)\n",
"(img2,) = adjoint2(kdata.data)\n",
"\n",
"plt.matshow(img1.abs()[0, 0, 0], cmap='gray')\n",
"plt.title('DCFs from Voronoi')\n",
"plt.colorbar()\n",
"plt.matshow(img2.abs()[0, 0, 0], cmap='gray')\n",
"plt.title('DCFs from estimate_dcf')\n",
"plt.colorbar()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "36",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
64 changes: 64 additions & 0 deletions examples/scripts/direct_reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,67 @@
# If the assert statement did not raise an exception, the results are equal.
torch.testing.assert_close(img.data, img_manual.data)
torch.testing.assert_close(img.data, img_more_manual.data, atol=1e-4, rtol=1e-4)


# %% [markdown]
# Faster DCF
# %%
from mrpro.data import KTrajectory
from mrpro.operators import FourierOp


def estimate_dcf(trajectory: KTrajectory, fourier_op: FourierOp, max_iter: int = 0) -> torch.Tensor:
"""Estimate the density compensation factors for a given trajectory.

Uses the Jackson or Pipe method to estimate the density of an arbitrary set of points.
If max_iter is set to 0, the Jackson method is used. Otherwise, the Pipe method is used.

Parameters
----------
trajectory
Shap `(*other, 2 or 3, k2, k1, k0)`
fourier_op
The Fourier operator
max_iter
The number of iterations to use for the Pipe method. If set to 0, the Jackson method is used.

Returns
-------
density estimate

References
----------
.. [1] Jackson, J.I., Meyer, C.H., Nishimura, D.G. and Macovski, A. (1991),
Selection of a convolution function for Fourier inversion using gridding
(computerized tomography application). IEEE Transactions on Medical
Imaging, 10(3): 473-478. https://doi.org/10.1109/42.97598
.. [2] Pipe, J.G. and Menon, P. (1999), Sampling density compensation in
MRI: Rationale and an iterative numerical solution. Magn. Reson. Med.,
41: 179-186. https://doi.org/10.1002/(SICI)1522-2594(199901)41:1<179::AID-MRM25>3.0.CO;2-V
"""
ones = torch.ones(trajectory.broadcasted_shape, dtype=torch.complex64).unsqueeze(-4)
if fourier_op._non_uniform_fast_fourier_op is None:
# cartesian
return ones
op = fourier_op._non_uniform_fast_fourier_op @ fourier_op._non_uniform_fast_fourier_op.H
weight = op(ones)[0].reciprocal().nan_to_num()
for _ in range(max_iter):
weight *= op(weight)[0].reciprocal().nan_to_num()
return weight.abs().squeeze(-4)


# %%
fourier_operator = mrpro.operators.FourierOp.from_kdata(kdata)
dcf_operator2 = mrpro.data.DcfData(estimate_dcf(kdata.traj, fourier_operator)).as_operator()
adjoint1 = (dcf_operator @ fourier_operator @ csm_operator).H
adjoint2 = (dcf_operator2 @ fourier_operator @ csm_operator).H
(img1,) = adjoint1(kdata.data)
(img2,) = adjoint2(kdata.data)

plt.matshow(img1.abs()[0, 0, 0], cmap='gray')
plt.title('DCFs from Voronoi')
plt.colorbar()
plt.matshow(img2.abs()[0, 0, 0], cmap='gray')
plt.title('DCFs from estimate_dcf')
plt.colorbar()
# %%
Loading