Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
FSL
win-pytreat
Commits
f275165a
Commit
f275165a
authored
Jan 15, 2021
by
Sean Fitzgibbon
Browse files
Formatting
parent
c216fda1
Changes
1
Hide whitespace changes
Inline
Side-by-side
applications/matlab_vs_python/bloch/bloch.ipynb
View file @
f275165a
...
...
@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Imports"
"
#
Imports"
]
},
{
...
...
@@ -216,7 +216,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.
3
"
"version": "3.7.
6
"
}
},
"nbformat": 4,
...
...
%% Cell type:markdown id: tags:
Imports
#
Imports
%% Cell type:code id: tags:
```
python
import
numpy
as
np
from
scipy.integrate
import
ode
,
solve_ivp
import
matplotlib.pyplot
as
plt
```
%% Cell type:markdown id: tags:
# Define the Bloch equation
$$
\f
rac{d
\v
ec{M}}{dt} =
\v
ec{M}
\t
imes
\v
ec{B} -
\f
rac{M_x + M_y}{T2} -
\f
rac{M_z - M_0}{T1}$$
In this section:
-
define a function
-
numpy functions like np.cross
%% Cell type:code id: tags:
```
python
# define bloch equation
def
bloch
(
t
,
M
,
T1
,
T2
):
# get effective B-field at time t
B
=
B_eff
(
t
)
# cross product of M and B, add T1 and T2 relaxation terms
return
np
.
array
([
M
[
1
]
*
B
[
2
]
-
M
[
2
]
*
B
[
1
]
-
M
[
0
]
/
T2
,
M
[
2
]
*
B
[
0
]
-
M
[
0
]
*
B
[
2
]
-
M
[
1
]
/
T2
,
M
[
0
]
*
B
[
1
]
-
M
[
1
]
*
B
[
0
]
-
(
M
[
2
]
-
1
)
/
T1
])
# alternatively
#return np.cross(M,B) - np.array([M[0]/T2, M[1]/T2, (M[2]-1)/T1])
```
%% Cell type:markdown id: tags:
# Define the pulse sequence
We work in the rotating frame, so we only need the amplitude envelope of the RF pulse
Typically, B1 excitation fields point in the x- and/or y-directions
Gradient fields point in the z-direction
In this simple example, a simple sinc-pulse excitation pulse is applied for 1 ms along the x-axis
then a gradient is turned on for 1.5 ms after that.
In this section:
-
constants such as np.pi
-
functions like np.sinc
%% Cell type:code id: tags:
```
python
# define effective B-field
def
B_eff
(
t
):
# Do nothing for 0.25 ms
if
t
<
0.25
:
return
np
.
array
([
0
,
0
,
0
])
# Sinc RF along x-axis and slice-select gradient on for 1.00 ms
elif
t
<
1.25
:
return
np
.
array
([
np
.
pi
*
np
.
sinc
((
t
-
0.75
)
*
4
),
0
,
np
.
pi
])
# Do nothing for 0.25 ms
elif
t
<
1.50
:
return
np
.
array
([
0
,
0
,
0
])
# Slice refocusing gradient on for 1.50 ms
# Half the area of the slice-select gradient lobe
elif
t
<
3.00
:
return
np
.
array
([
0
,
0
,
-
(
1
/
3
)
*
np
.
pi
])
# Pulse sequence finished
else
:
return
np
.
array
([
0
,
0
,
0
])
```
%% Cell type:markdown id: tags:
# Plot the pulse sequence
In this section:
-
unpacking return values
-
unwanted return values
-
list comprehension
-
basic plotting
%% Cell type:code id: tags:
```
python
# Create 2 vertical subplots
_
,
ax
=
plt
.
subplots
(
2
,
1
,
figsize
=
(
12
,
12
))
# Get pulse sequence B-fields from 0 - 5 ms
pulseq
=
[
B_eff
(
t
)
for
t
in
np
.
linspace
(
0
,
5
,
1000
)]
pulseq
=
np
.
array
(
pulseq
)
# Plot RF
ax
[
0
].
plot
(
pulseq
[:,
0
])
ax
[
0
].
set_ylabel
(
'B1'
)
# Plot gradient
ax
[
1
].
plot
(
pulseq
[:,
2
])
ax
[
1
].
set_ylabel
(
'Gradient'
)
```
%% Cell type:markdown id: tags:
# Integrate ODE
This uses a Runge-Kutta variant called the "Dormand-Prince method" by default. Other ode integration methods are available.
In this section:
-
ode solvers
-
lambdas (anonymous functions)
%% Cell type:code id: tags:
```
python
# Set the initial conditions
# equilibrium magnetization (M) = (0, 0, 1)
M
=
[
0
,
0
,
1
]
# Set time interval for integration
t
=
[
0
,
5
]
# Set max step size
dt
=
0.005
# Set T1 and T2
T1
,
T2
=
1500
,
50
# Integrate ODE
# In Scipy 1.2.0, the first argument to solve_ivp must be a function that takes exactly 2 arguments
sol
=
solve_ivp
(
lambda
t
,
M
:
bloch
(
t
,
M
,
T1
,
T2
),
t
,
M
,
max_step
=
dt
)
# Grab output
t
=
sol
.
t
M
=
sol
.
y
```
%% Cell type:markdown id: tags:
# Plot Results
In this section:
-
more plotting
%% Cell type:code id: tags:
```
python
# Create single axis
_
,
ax
=
plt
.
subplots
(
figsize
=
(
12
,
12
))
# Plot x, y and z components of Magnetisation
ax
.
plot
(
t
,
M
[
0
,:],
label
=
'Mx'
)
ax
.
plot
(
t
,
M
[
1
,:],
label
=
'My'
)
ax
.
plot
(
t
,
M
[
2
,:],
label
=
'Mz'
)
# Add legend and grid
ax
.
legend
()
ax
.
grid
()
```
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment