示例#1
0
system = pp.Opts(max_grad=32, grad_unit='mT/m', max_slew=130, slew_unit='T/m/s', rf_ringdown_time=30e-6,
                 rf_dead_time=100e-6, adc_dead_time=20e-6)

# ======
# CREATE EVENTS
# ======
# Create 90 degree slice selection pulse and gradient
rf, gz, _ = pp.make_sinc_pulse(flip_angle=np.pi / 2, system=system, duration=3e-3, slice_thickness=3e-3,
                               apodization=0.5, time_bw_product=4, return_gz=True)

# Define other gradients and ADC events
delta_k = 1 / fov
k_width = Nx * delta_k
readout_time = 3.2e-4
gx = pp.make_trapezoid(channel='x', system=system, flat_area=k_width, flat_time=readout_time)
adc = pp.make_adc(num_samples=Nx, system=system, duration=gx.flat_time, delay=gx.rise_time)

# Pre-phasing gradients
pre_time = 8e-4
gz_reph = pp.make_trapezoid(channel='z', system=system, area=-gz.area / 2, duration=pre_time)
# Do not need minus for in-plane prephasers because of the spin-echo (position reflection in k-space)
gx_pre = pp.make_trapezoid(channel='x', system=system, area=gx.area / 2 - delta_k / 2, duration=pre_time)
gy_pre = pp.make_trapezoid(channel='y', system=system, area=Ny / 2 * delta_k, duration=pre_time)

# Phase blip in shortest possible time
dur = math.ceil(2 * math.sqrt(delta_k / system.max_slew) / 10e-6) * 10e-6
gy = pp.make_trapezoid(channel='y', system=system, area=delta_k, duration=dur)

# Refocusing pulse with spoiling gradients
rf180 = pp.make_block_pulse(flip_angle=np.pi, system=system, duration=500e-6, use='refocusing')
gz_spoil = pp.make_trapezoid(channel='z', system=system, area=gz.area * 2, duration=3 * pre_time)
示例#2
0
flip_ref = rf_flip[0] * np.pi / 180
rf_ref, gz, _ = pp.make_sinc_pulse(flip_angle=flip_ref, system=system, duration=t_ref, slice_thickness=slice_thickness,
                                   apodization=0.5, time_bw_product=4, phase_offset=rf_ref_phase, use='refocusing',
                                   return_gz=True)
gs_ref = pp.make_trapezoid(channel='z', system=system, amplitude=gs_ex.amplitude, flat_time=t_refwd, rise_time=dG)

ags_ex = gs_ex.area / 2
gs_spr = pp.make_trapezoid(channel='z', system=system, area=ags_ex * (1 + fsp_s), duration=t_sp, rise_time=dG)
gs_spex = pp.make_trapezoid(channel='z', system=system, area=ags_ex * fsp_s, duration=t_spex, rise_time=dG)

delta_k = 1 / fov
k_width = Nx * delta_k

gr_acq = pp.make_trapezoid(channel='x', system=system, flat_area=k_width, flat_time=readout_time, rise_time=dG)
adc = pp.make_adc(num_samples=Nx, duration=gr_acq.flat_time - 40e-6, delay=20e-6)
gr_spr = pp.make_trapezoid(channel='x', system=system, area=gr_acq.area * fsp_r, duration=t_sp, rise_time=dG)
gr_spex = pp.make_trapezoid(channel='x', system=system, area=gr_acq.area * (1 + fsp_r), duration=t_spex, rise_time=dG)

agr_spr = gr_spr.area
agr_preph = gr_acq.area / 2 + agr_spr
gr_preph = pp.make_trapezoid(channel='x', system=system, area=agr_preph, duration=t_spex, rise_time=dG)

# Phase-encoding
n_ex = math.floor(Ny / n_echo)
pe_steps = np.arange(1, n_echo * n_ex + 1) - 0.5 * n_echo * n_ex - 1
if divmod(n_echo, 2)[1] == 0:
    pe_steps = np.roll(pe_steps, -round(n_ex / 2))
pe_order = pe_steps.reshape((n_ex, n_echo), order='F').T
phase_areas = pe_order * delta_k
示例#3
0
extra_area = blip_duration / 2 * blip_duration / 2 * system.max_slew
gx = pp.make_trapezoid(channel='x', system=system, area=k_width + extra_area, duration=readout_time + blip_duration)
actual_area = gx.area - gx.amplitude / gx.rise_time * blip_duration / 2 * blip_duration / 2 / 2
actual_area -= gx.amplitude / gx.fall_time * blip_duration / 2 * blip_duration / 2 / 2
gx.amplitude = gx.amplitude / actual_area * k_width
gx.area = gx.amplitude * (gx.flat_time + gx.rise_time / 2 + gx.fall_time / 2)
gx.flat_area = gx.amplitude * gx.flat_time

# Calculate ADC
# We use ramp sampling, so we have to calculate the dwell time and the number of samples, which will be quite different
# from Nx and readout_time/Nx, respectively.
adc_dwell_nyquist = delta_k / gx.amplitude / ro_os
# Round-down dwell time to 100 ns
adc_dwell = math.floor(adc_dwell_nyquist * 1e7) * 1e-7
adc_samples = math.floor(readout_time / adc_dwell / 4) * 4  # Number of samples on Siemens needs to be divisible by 4
adc = pp.make_adc(num_samples=adc_samples, dwell=adc_dwell, delay=blip_duration / 2)
# Realign the ADC with respect to the gradient
time_to_center = adc_dwell * ((adc_samples - 1) / 2 + 0.5)  # Supposedly Siemens samples at center of dwell period
# Adjust delay to align the trajectory with the gradient. We have to align the delay to 1us
adc.delay = round((gx.rise_time + gx.flat_time / 2 - time_to_center) * 1e6) * 1e-6
# This rounding actually makes the sampling points on odd and even readouts to appear misaligned. However, on the real
# hardware this misalignment is much stronger anyways due to the gradient delays

# Split the blip into two halves and produnce a combined synthetic gradient
gy_parts = pp.split_gradient_at(grad=gy, time_point=blip_duration / 2, system=system)
gy_blipup, gy_blipdown, _ = pp.align(right=gy_parts[0], left=[gy_parts[1], gx])
gy_blipdownup = pp.add_gradients((gy_blipdown, gy_blipup), system=system)

# pe_enable support
gy_blipup.waveform = gy_blipup.waveform * pe_enable
gy_blipdown.waveform = gy_blipdown.waveform * pe_enable