2D spin echo imaging (single slice)

(a) TR/TE=400ms/10ms (b) TR/TE=400ms/10ms (c) TR=4000ms/80ms
subvoxel = 1 x 1 x 4 subvoxel = 2 x 1 x 4 subvoxel = 2 x 1 x 4
Image matrix = 256 x 256, slice thickness = 5 mm, number of isochromats = 13,572,096 for (a) 27,335,680 for (b) and (c). Calculation time was 46.802, 92.431, and 92.431 s for (a), (b), and (c).
Python pulse sequence:
from psdk import *
import numpy as np
gamma = 42.57747892 # [MHz/T]
TR = 4000.0e+3 # [us]
TE = 80.0e+3 # [us]
NR = 256 # Number of readout points
NPE1 = 256 # Number of 1st phase encoding
fov = [256.0, 256.0, 256.0] # [mm]
dwell_time = 10.0 # [us]
slice_width = 5.0 # [mm]
gx_value = 1e+6 / (dwell_time * gamma * fov[0]) # [mT/m]
gy_value = 2e+6 / (dwell_time * gamma * fov[1]) * NPE1 / NR # [mT/m]
gz_value = 1.25 / (slice_width * 1.0e-3) / gamma # [mT/m]
gx_rt = 300.0 # [us] gx_rise_time
gy_rt = 300.0 # [us] gy_rise_time
gz_rt = 300.0 # [us] gz_rise_time
ex_pulse_width = 2400.0 # [us]
ex_pulse_flip_angle = 90.0 # [degree]
def sinc_with_hamming(flip_angle, pulse_width, points, *, min = -2.0 * np.pi, max = 2.0 * np.pi):
x0 = np.arange(min, max, (max - min) / points)
x1 = x0 + (max - min) / points
y = (np.sinc(x0 / np.pi) + np.sinc(x1 / np.pi)) * 0.5 * np.hamming(points)
return flip_angle * y * points / (y.sum() * pulse_width * 360.0e-6 * gamma)
with Sequence('2D SpinEcho'):
with Block('Excitation', ex_pulse_width + 2.0*gz_rt):
GZ(0.0, gz_value, gz_rt)
RF(gz_rt, sinc_with_hamming(ex_pulse_flip_angle, ex_pulse_width, 160), ex_pulse_width / 160, phase = 0.0)
GZ(ex_pulse_width + gz_rt, 0.0, gz_rt)
with Block('SR+RP', NR // 2 * dwell_time + gx_rt * 2.0 ):
GZ(0.0, -gz_value, gz_rt)
GZ(ex_pulse_width * 0.5 + gz_rt, 0.0, gz_rt)
GX(0.0, gx_value, gx_rt)
GX(NR // 2 * dwell_time + gx_rt, 0.0, gx_rt)
with Block('Refocus', ex_pulse_width + 2.0*gz_rt):
GZ(0.0, gz_value, gz_rt)
RF(gz_rt, 2.0 * sinc_with_hamming(ex_pulse_flip_angle, ex_pulse_width, 160), ex_pulse_width / 160, phase = np.pi * 0.5)
GZ(ex_pulse_width + gz_rt, 0.0, gz_rt)
with Block('PE+RD+RW', TE/2 + NR * dwell_time - ex_pulse_width * 0.5 - gz_rt + gy_rt):
GY(0.0, ([gy_value * (i - NPE1 // 2) / NPE1 for i in range(NPE1)], ['PE1']), gy_rt)
GY(NR // 2 * dwell_time, 0.0, gy_rt)
GX(TE/2 - ex_pulse_width * 0.5 - gz_rt - NR // 2 * dwell_time - gx_rt * 1.5, gx_value, gx_rt)
AD(TE/2 - ex_pulse_width * 0.5 - gz_rt - NR // 2 * dwell_time, NR, dwell_time)
GX(TE/2 - ex_pulse_width * 0.5 - gz_rt + NR // 2 * dwell_time + gx_rt * 0.5, 0, gx_rt)
GY(TE/2 - ex_pulse_width * 0.5 - gz_rt + NR // 2 * dwell_time, ([gy_value * (NPE1 // 2 - i) / NPE1 for i in range(NPE1)], ['PE1']), gy_rt)
GY(TE/2 - ex_pulse_width * 0.5 - gz_rt + NR * dwell_time, 0.0, gy_rt)
with Main():
with Loop('PE1', NPE1):
BlockRef('Excitation')
BlockRef('SR+RP')
WaitUntil(TE/2)
BlockRef('Refocus')
BlockRef('PE+RD+RW')
WaitUntil(TR)