Magic angle effects (MAE) are well recognized in musculoskeletal (MSK) magnetic resonance (MR) imaging. With pulse sequences with TE $\leq$ 30 msec, the signal intensity of tendons, ligaments, and menisci depends on their orientation to the constant magnetic induction field ($B_{0}$) (Chappell et al, Li et al, Fullerton et al).
These tissues are rich in collagen, which is bound to water. These water protons undergo dipolar interactions whose strength depends on the orientation of the collagen fibers to $B_{0}$. These interactions result in a very short T2. These collagen-rich tissues therefore exhibit little or no signal intensity, and appear dark on many clinical MR sequences. The signal intensity, $S(\theta)$, of these tissues can be expressed by the following equation from Chappell et al:
$$S(\theta) = S_{1} + S_{0} \cdot e^{-TE[\frac{1}{T_{2base}} + \frac{1}{\alpha(3cos^{2}\theta - 1)^{2}}]}$$
However, this equation does not account for the exponential drop-off in MAE signal intensity seen with increasing TE in experimental data from other authors (Li and Mirowitz. To account for this phenomenon, we added an additional exponential term, resulting in the following equation:
$$S(\theta) = S_{1} + S_{0} \cdot e^{-TE[\frac{1}{T_{2base}} + \frac{1}{\alpha(3cos^{2}\theta - 1)^{2}}]} \cdot e^{- \beta (TE - t_{0})}$$
where $\beta$ is a decay constant and $t_{0}$ is the TE time at which maximum signal is observed experimentally.
To account for the effects of the noise floor, Prah et al suggest addeing an additional term:
$$S(\theta) = S_{1} + S_{0} \cdot e^{-TE[\frac{1}{T_{2base}} + \frac{1}{\alpha(3cos^{2}\theta - 1)^{2}}]} \cdot e^{- \beta (TE - t_{0})} + Noise_{floor}$$
The following code uses parameters derived from a non-linear least-squares fit of the experimental data from Li and Mirowitz. This function calculates the signal intensity for a given value of T2 and TE.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Wedge
from ipywidgets import interactive, interact, Label, widgets, Layout, Button, Box
from ipywidgets import FloatSlider, IntSlider
from IPython.display import display
def X_magic(TE, T2base, Noise):
# set up a nice wide figure to contain both plots
fig = plt.figure(figsize=(10,5))
# set up parameters for plot of signal intensity vs angle
rad2deg = 2 * np.pi /360
# parameters from fit to Li & Mirowitz FSE data
alpha = 0.125
S1 = 89.5
S0 = 427
t0 = 9
beta = 0.0504464
theta1 = np.arange(0,90, 2)
T2_magic_angle = (1/T2base) + (1/(alpha*(3*np.cos(rad2deg*theta1)* np.cos(rad2deg*theta1) - 1)**2))
S_magic_angle = S1 + S0 * np.exp(-(TE / T2_magic_angle)) * np.exp(-(TE-t0)*beta) + Noise
# plot signal intensity vs theta in first subplot area
ax = fig.add_subplot(121)
plt.axis([0,90,0,800])
plt.plot(theta1, S_magic_angle)
plt.ylabel("Signal Intensity (arbitrary units)")
plt.xlabel("Angle to $B_{0}$ field")
plt.title("Signal Intensity vs angle to $B_{0}$")
# create tendon gray scale map scaled on min and max signal intensity
# max signal is mapped to 1.0 (white); minimum signal is mapped to 0.0 (black)
tendon_map = np.round((S_magic_angle - np.ndarray.min(S_magic_angle))/(np.ndarray.max(S_magic_angle) - np.ndarray.min(S_magic_angle)), 2)
#print(np.array_str(tendon_map))
#print(range(len(theta)-1))
# create second subplot area for the simulated tendon
ax2 = fig.add_subplot(122, frameon=False)
theta2 = np.linspace(180, 270, 45)
for i in range(len(theta2)-1):
# print(np.array_str(tendon_map[i]))
ax2.add_artist(
Wedge((0, 0), 1, theta2[i], theta2[i+1], width=0.2, color=np.array_str(tendon_map[i]))
)
ax2.set_xlim((-1.25,.25))
ax2.set_ylim((-1.25,.25))
ax2.axes.get_xaxis().set_visible(False)
ax2.axes.get_yaxis().set_visible(False)
ax2.annotate("$B_{0}$",
xy=(-.3, 0.1), xycoords='data',
xytext=(-.37, -0.12), textcoords='data',fontsize=19,
arrowprops=dict(arrowstyle="simple",
connectionstyle="arc3"),
)
plt.show()
The following Python code creates an interactive widget, allowing one to explore variations in the signal intensity as one varies the T2, TE and noise floor. This signal is shown as a plot of signal vs angle to $B_{0}$ and also as the signal intensity within a simulated ankle tendon.
magic_angle_plot = interactive(X_magic,
TE = IntSlider(value=10, description='TE', max=120, min=1),
T2base = IntSlider(value=1.5, description='Tissue T2', max=200, min=1),
Noise = IntSlider(value=1.5, description='Noise floor', max=300, min=0),
Bzero=FloatSlider(value=1.5, description='Magnetic Field Strength', max=7.0, min=0.1, step=0.1)
)
display(magic_angle_plot)