Introduction Part III - Gridding Sequences#

Imports#

[1]:
from copy import deepcopy

import numpy as np
from pint import Quantity
import matplotlib.pyplot as plt
%matplotlib inline

import sys
sys.path.insert(0, "../../..")
import cmrseq

Construct Sequence from Part I#

[2]:
system_specs = cmrseq.SystemSpec(gamma=Quantity(42.575, "MHz/T"),
                                 grad_raster_time=Quantity(5, "us"),
                                 max_grad=Quantity(40, "mT/m"),
                                 max_slew=Quantity(120, "mT/m/ms"),
                                 rf_raster_time=Quantity(5, "us"),
                                 adc_raster_time=Quantity(0.3, "us"))

rf_excitation = cmrseq.bausteine.SincRFPulse(system_specs=system_specs,
                                             flip_angle=Quantity(np.pi/2, "rad"),
                                             duration=Quantity(1., "ms"),
                                             time_bandwidth_product=4,
                                             name="fid_excitation")


fov_x = Quantity(30, "cm")
kx_max = 2 / fov_x
prephaser_area = kx_max / system_specs.gamma
ro_prephaser = cmrseq.bausteine.TrapezoidalGradient.from_area(system_specs=system_specs,
                                                              area=prephaser_area,
                                                              orientation=np.array([-1., 0., 0.]),
                                                              name="ro_prephaser")

adc_block = cmrseq.bausteine.SymmetricADC(system_specs=system_specs,
                                          num_samples=51,
                                          duration=Quantity(0.8, "ms"))

ro_gradient = cmrseq.bausteine.TrapezoidalGradient.from_fdur_area(system_specs=system_specs,
                                                                  orientation=np.array([1., 0., 0.]),
                                                                  flat_duration=adc_block.duration,
                                                                  area=prephaser_area*2,
                                                                  name="ro_gradient")
ro_prephaser.shift(rf_excitation.tmax)
ro_gradient.shift(ro_prephaser.tmax)
adc_block.shift(ro_gradient.tmin + ro_gradient.rise_time)
sequence_obj = cmrseq.Sequence(building_blocks=[rf_excitation, ro_prephaser, ro_gradient, adc_block], system_specs=system_specs)
[3]:
sequence_obj.adc_to_grid()
[3]:
(array([0.    , 0.005 , 0.01  , ..., 1.885 , 1.8851, 1.89  ]),
 array([0., 0., 0., ..., 0., 0., 0.]),
 array([0., 0., 0., ..., 0., 0., 0.]),
 array([[ 217, 3040]]))

Gridding#

Gradients#

[4]:
time_raster, waveform = sequence_obj.gradients_to_grid()
print("Gridded Gradient time-raster:", time_raster.shape)
print("Gridded Gradient waveform:", waveform.shape)

f, a = plt.subplots(1, 1, figsize=(12, 4))
_ = a.plot(time_raster, waveform.T)
_ = f.suptitle("Unformated Gridded Gradient Plot")
Gridded Gradient time-raster: (379,)
Gridded Gradient waveform: (3, 379)
../_images/getting_started_sequence_gridding_7_1.png

RF-pulses#

[5]:
time_raster, waveform = sequence_obj.rf_to_grid()
print("Gridded RF time-raster:", time_raster.shape)
print("Gridded RF waveform:", waveform.shape)

f, a = plt.subplots(1, 1, figsize=(12, 4))
_ = a.plot(time_raster, waveform.real)
_ = a.plot(time_raster, waveform.imag)
_= f.suptitle("Unformated Gridded RF Plot")
Gridded RF time-raster: (379,)
Gridded RF waveform: (379,)
../_images/getting_started_sequence_gridding_9_1.png

ADCs#

force_raster=False: ADC-points are inserted into gradient raster resulting in a non-uniform raster

[6]:
time_raster, adc_on, adc_phase, start_end = sequence_obj.adc_to_grid(force_raster=False)

print("Gridded ADC time-raster:", time_raster.shape)
print("Gridded ADC on events:", adc_on.shape)
print("Gridded ADC phase:", adc_phase.shape)
print("Start/End time of ADC-block:", start_end.shape)

f, a = plt.subplots(1, 1, figsize=(20, 4))
a.plot(time_raster, adc_on, "x")
a.plot(time_raster, adc_phase, "--")
a.vlines(time_raster[start_end[0]], -1, 1, colors="k")
a.set_xlim([1, 2])
_ = f.suptitle("Exact ADC-events with non-uniform raster")
Gridded ADC time-raster: (3042,)
Gridded ADC on events: (3042,)
Gridded ADC phase: (3042,)
Start/End time of ADC-block: (1, 2)
../_images/getting_started_sequence_gridding_11_1.png

force_raster=True: ADC-point that are not on gradient raster are not inserted, but the surrounding points are set to active

[7]:
time_raster, adc_on, adc_phase, start_end = sequence_obj.adc_to_grid(force_raster=True)

print("Gridded ADC time-raster:", time_raster.shape)
print("Gridded ADC on events:", adc_on.shape)
print("Gridded ADC phase:", adc_phase.shape)
print("Start/End time of ADC-block:", start_end.shape)

f, a = plt.subplots(1, 1, figsize=(20, 4))
a.plot(time_raster, adc_on, "x")
a.plot(time_raster, adc_phase, "--")
a.vlines(time_raster[start_end[0]], -1, 1, colors="k")
a.set_xlim([1, 2])
_ = f.suptitle("Exact ADC-events with uniform raster")
Gridded ADC time-raster: (2993,)
Gridded ADC on events: (2993,)
Gridded ADC phase: (2993,)
Start/End time of ADC-block: (1, 2)
../_images/getting_started_sequence_gridding_13_1.png

Utility: Gridding combined#

Gridding sequences with matching temporal raster:

[8]:
time_raster, rf_raster, gradient_raster, adc_raster = cmrseq.utils.grid_sequence_list([sequence_obj, ], force_uniform_grid=False)
time_raster, rf_raster, gradient_raster, adc_raster = [np.stack(v) for v in [time_raster, rf_raster, gradient_raster, adc_raster]]

print("Gridded time-raster:", time_raster.shape)
print("Gridded rf:", rf_raster.shape, rf_raster.dtype)
print("Gridded gradient:", gradient_raster.shape)
print("Gridded ADCs:", adc_raster.shape)
Gridded time-raster: (1, 3042)
Gridded rf: (1, 3042) complex128
Gridded gradient: (1, 3042, 3)
Gridded ADCs: (1, 3042, 2)

Calculate Moments & k-space#

[9]:
first_moment = sequence_obj.calculate_moment(moment=1)
print("First Moment of all gradient channels:", first_moment)
First Moment of all gradient channels: [0.3022117831278078 0.0 0.0] millisecond ** 2 * millitesla / meter
[10]:
kspace_on_raster, k_adc, t_adc = sequence_obj.calculate_kspace()
print("K-space position for all gradient raster points:", kspace_on_raster.shape)
print("K-space positions of all ADC-events:", k_adc.shape)
print("Time points of all ADC-events:", t_adc.shape)
K-space position for all gradient raster points: (3, 379)
K-space positions of all ADC-events: (3, 51)
Time points of all ADC-events: (51,)