Skip to content

Commit 853612b

Browse files
authored
Merge pull request #733 from mrava87/feat-mri
Feat: mri module
2 parents 3c2ff49 + 4dd8860 commit 853612b

11 files changed

Lines changed: 781 additions & 18 deletions

File tree

docs/source/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ Medical imaging
171171
:toctree: generated/
172172

173173
CT2D
174+
MRI2D
174175

175176

176177
Solvers

docs/source/faq.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ working with linear operators is indeed that you don't really need to access the
1414
of an operator.
1515

1616

17-
**2. Can I have an older version of** ``cupy`` **installed in my system (** ``cupy-cudaXX<10.6.0``)?**
17+
**2. Can I have an older version of** ``cupy`` **installed in my system (** ``cupy-cudaXX<10.6.0``**)?**
1818
1919
Yes. Nevertheless you need to tell PyLops that you don't want to use its ``cupy``
2020
backend by setting the environment variable ``CUPY_PYLOPS=0``.

docs/source/gpu.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,10 @@ Medical:
602602
- |:white_check_mark:|
603603
- |:white_check_mark:|
604604
- |:white_check_mark:|
605+
* - :class:`pylops.medical.mri.MRI2D`
606+
- |:white_check_mark:|
607+
- |:red_circle:|
608+
- |:white_check_mark:|
605609

606610
.. warning::
607611

examples/plot_avo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
r"""
22
AVO modelling
3-
===================
3+
=============
44
This example shows how to create pre-stack angle gathers using
55
the :py:class:`pylops.avo.avo.AVOLinearModelling` operator.
66
"""

examples/plot_mri.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
r"""
2+
MRI modelling
3+
=============
4+
This example shows how to use the :py:class:`pylops.medical.mri.MRI2D` operator
5+
to create K-space undersampled MRI data.
6+
"""
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
10+
import pylops
11+
12+
plt.close("all")
13+
np.random.seed(0)
14+
15+
###############################################################################
16+
# Let"s start by loading the Shepp-Logan phantom model.
17+
x = np.load("../testdata/optimization/shepp_logan_phantom.npy")
18+
x = x / x.max()
19+
nx, ny = x.shape
20+
21+
###############################################################################
22+
# Next, we create a mask to simulate undersampling in K-space and apply it to
23+
# the phantom model.
24+
25+
# Passing mask as array
26+
mask = np.zeros((nx, ny))
27+
mask[:, np.random.randint(0, ny, 2 * ny // 3)] = 1
28+
mask[:, ny // 2 - 20 : ny // 2 + 10] = 1
29+
30+
Mop = pylops.medical.MRI2D(dims=(nx, ny), mask=mask)
31+
32+
d = Mop @ x
33+
x_adj = Mop.H @ d
34+
35+
fig, axs = plt.subplots(1, 3, figsize=(12, 5))
36+
axs[0].imshow(x, cmap="gray", vmin=0, vmax=1)
37+
axs[0].set_title("Original Image")
38+
axs[1].imshow(np.abs(d), cmap="jet", vmin=0, vmax=1)
39+
axs[1].set_title("K-space Data")
40+
axs[2].imshow(x_adj.real, cmap="gray", vmin=0, vmax=1)
41+
axs[2].set_title("Adjoint Reconstruction")
42+
fig.tight_layout()
43+
44+
###############################################################################
45+
# Alternatively, we can create the same mask by specifying a sampling pattern
46+
# using the ``mask`` keyword argument. Here, we create a ``vertical-reg`` mask
47+
# that samples K-space lines in the vertical direction with a regular pattern.
48+
49+
# Vertical uniform with center
50+
Mop = pylops.medical.MRI2D(
51+
dims=(nx, ny), mask="vertical-reg", nlines=ny // 2, perc_center=0.0
52+
)
53+
54+
d = Mop @ x
55+
x_adj = (Mop.H @ d).reshape(nx, ny)
56+
57+
fig, axs = plt.subplots(1, 3, figsize=(12, 5))
58+
axs[0].imshow(x, cmap="gray", vmin=0, vmax=1)
59+
axs[0].set_title("Original Image")
60+
axs[1].imshow(np.abs(Mop.ROp.H @ d).reshape(nx, ny), cmap="jet", vmin=0, vmax=1)
61+
axs[1].set_title("K-space Data")
62+
axs[2].imshow(x_adj.real, cmap="gray", vmin=0, vmax=1)
63+
axs[2].set_title("Adjoint Reconstruction")
64+
fig.tight_layout()
65+
66+
###############################################################################
67+
# Similarly, we can create a ``vertical-uni`` mask that randomly samples
68+
# K-space lines in the vertical direction.
69+
70+
# Vertical uniform with center
71+
Mop = pylops.medical.MRI2D(
72+
dims=(nx, ny), mask="vertical-uni", nlines=40, perc_center=0.1
73+
)
74+
75+
d = Mop @ x
76+
x_adj = (Mop.H @ d).reshape(nx, ny)
77+
78+
fig, axs = plt.subplots(1, 3, figsize=(12, 5))
79+
axs[0].imshow(x, cmap="gray", vmin=0, vmax=1)
80+
axs[0].set_title("Original Image")
81+
axs[1].imshow(np.abs(Mop.ROp.H @ d).reshape(nx, ny), cmap="jet", vmin=0, vmax=1)
82+
axs[1].set_title("K-space Data")
83+
axs[2].imshow(x_adj.real, cmap="gray", vmin=0, vmax=1)
84+
axs[2].set_title("Adjoint Reconstruction")
85+
fig.tight_layout()
86+
87+
###############################################################################
88+
# Finally, we can create a sampling pattern with radial lines using the
89+
# ``radial-uni`` (or ``radial-reg``) option.
90+
91+
# Radial uniform
92+
Mop = pylops.medical.MRI2D(dims=(nx, ny), mask="radial-uni", nlines=40)
93+
94+
d = Mop @ x
95+
x_adj = (Mop.H @ d).reshape(nx, ny)
96+
97+
fig, axs = plt.subplots(1, 3, figsize=(12, 5))
98+
axs[0].imshow(x, cmap="gray", vmin=0, vmax=1)
99+
axs[0].set_title("Original Image")
100+
axs[1].imshow(np.abs(Mop.ROp.H @ d).reshape(nx, ny), cmap="jet", vmin=0, vmax=1)
101+
axs[1].set_title("K-space Data")
102+
axs[2].imshow(x_adj.real, cmap="gray", vmin=0, vmax=1)
103+
axs[2].set_title("Adjoint Reconstruction")
104+
fig.tight_layout()

pylops/medical/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
A list of operators present in pylops.medical:
99
1010
CT2D 2D Computerized Tomography.
11+
MRI2D 2D Magnetic Resonance Imaging.
1112
1213
"""
1314

1415
from .ct import *
16+
from .mri import *
1517

16-
__all__ = [
17-
"CT2D",
18-
]
18+
19+
__all__ = ["CT2D", "MRI2D"]

pylops/medical/ct.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ class CT2D(LinearOperator):
6363
6464
Attributes
6565
----------
66+
dims : :obj:`tuple`
67+
Shape of the array after the adjoint, but before flattening.
68+
69+
For example, ``x_reshaped = (Op.H * y.ravel()).reshape(Op.dims)``.
70+
dimsd : :obj:`tuple`
71+
Shape of the array after the forward, but before flattening.
72+
73+
For example, ``y_reshaped = (Op * x.ravel()).reshape(Op.dimsd)``.
6674
shape : :obj:`tuple`
6775
Operator shape
6876
explicit : :obj:`bool`

0 commit comments

Comments
 (0)