Skip to article frontmatterSkip to article content

Free induction decay

This notebook showcases free induction decay:

  • exponential fall-off with TwT_w^*
  • oscillations depending on B0B_0 off-resonance
Notebook Cell
!pip install pypulseq &> /dev/null
!pip install  torchkbnufft --no-deps
!pip install MRzeroCore --no-deps
!pip install pydisseqt
!pip install ismrmrd

!wget https://github.com/MRsources/MRzero-Core/raw/main/documentation/playground_mr0/numerical_brain_cropped.mat &> /dev/null
Defaulting to user installation because normal site-packages is not writeable
Collecting torchkbnufft
  Downloading torchkbnufft-1.5.2-py3-none-any.whl.metadata (11 kB)
Downloading torchkbnufft-1.5.2-py3-none-any.whl (37 kB)
Installing collected packages: torchkbnufft
Successfully installed torchkbnufft-1.5.2
Defaulting to user installation because normal site-packages is not writeable
Collecting MRzeroCore
  Downloading MRzeroCore-0.4.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.9 kB)
Downloading MRzeroCore-0.4.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (367 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/367.8 kB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 367.8/367.8 kB 19.4 MB/s eta 0:00:00
Installing collected packages: MRzeroCore
Successfully installed MRzeroCore-0.4.1
Defaulting to user installation because normal site-packages is not writeable
Collecting pydisseqt
  Using cached pydisseqt-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (1.7 kB)
Downloading pydisseqt-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (471 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/471.2 kB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 471.2/471.2 kB 12.3 MB/s eta 0:00:00a 0:00:01
Installing collected packages: pydisseqt
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
mrzerocore 0.4.1 requires ismrmrd, which is not installed.
mrzerocore 0.4.1 requires scikit-image, which is not installed.
mrzerocore 0.4.1 requires torch>=1.12, which is not installed.
mrzerocore 0.4.1 requires tqdm, which is not installed.
Successfully installed pydisseqt-0.2.0
Defaulting to user installation because normal site-packages is not writeable
Collecting ismrmrd
  Using cached ismrmrd-1.14.2-py3-none-any.whl.metadata (927 bytes)
Collecting h5py>=2.3 (from ismrmrd)
  Downloading h5py-3.15.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (3.0 kB)
Requirement already satisfied: numpy>=1.22.0 in /home/runner/.local/lib/python3.12/site-packages (from ismrmrd) (2.3.4)
Collecting xsdata>=22.12 (from ismrmrd)
  Using cached xsdata-25.7-py3-none-any.whl.metadata (5.5 kB)
Requirement already satisfied: typing-extensions>=4.7.0 in /usr/lib/python3/dist-packages (from xsdata>=22.12->ismrmrd) (4.10.0)
Using cached ismrmrd-1.14.2-py3-none-any.whl (32 kB)
Downloading h5py-3.15.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (5.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/5.1 MB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.1/5.1 MB 69.4 MB/s eta 0:00:0000:0100:01
Using cached xsdata-25.7-py3-none-any.whl (234 kB)
Installing collected packages: xsdata, h5py, ismrmrd
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
mrzerocore 0.4.1 requires scikit-image, which is not installed.
mrzerocore 0.4.1 requires torch>=1.12, which is not installed.
mrzerocore 0.4.1 requires tqdm, which is not installed.
Successfully installed h5py-3.15.1 ismrmrd-1.14.2 xsdata-25.7
import numpy as np
import MRzeroCore as mr0
import pypulseq as pp
import matplotlib.pyplot as plt
#@title FID in a brain phantom - sequence
# %% S2. DEFINE the sequence, FOV and resolution
seq = pp.Sequence()
fov = 200e-3
Nread = 256
Nphase = 1
slice_thickness = 8e-3  # slice

experiment_id = 'FID'
# %% S1. SETUP sys
# choose the scanner limits
system = pp.Opts(
    max_grad=28, grad_unit='mT/m', max_slew=150, slew_unit='T/m/s',
    rf_ringdown_time=20e-6, rf_dead_time=100e-6,
    adc_dead_time=20e-6, grad_raster_time=10e-6
)


# Define rf events
rf1, _, _ = pp.make_sinc_pulse(
    flip_angle=90 * np.pi / 180, duration=1e-3,
    slice_thickness=slice_thickness, apodization=0.5, time_bw_product=4,
    delay=0, system=system, return_gz=True
)
# rf1 = pp.make_block_pulse(flip_angle=90 * np.pi / 180, duration=1e-3, system=system)

# Define other gradients and ADC events
adc = pp.make_adc(num_samples=Nread, duration=70e-3, phase_offset=0 * np.pi / 180, delay=0, system=system)

# ======
# CONSTRUCT SEQUENCE
# ======
seq.add_block(rf1)
seq.add_block(adc)

#quick 2D brain phantom sim and plot
signal = mr0.util.simulate_2d(seq,)
seq.plot(plot_now=False)
mr0.util.insert_signal_plot(seq=seq, signal =signal.numpy())
plt.show()
/tmp/ipykernel_2275/3263536545.py:20: UserWarning: Specified RF delay 0.00 us is less than the dead time 100 us. Delay was increased to the dead time.
  rf1, _, _ = pp.make_sinc_pulse(
/tmp/ipykernel_2275/3263536545.py:28: UserWarning: Specified ADC delay 0.00 us is less than the dead time 20 us. Delay was increased to the dead time.
  adc = pp.make_adc(num_samples=Nread, duration=70e-3, phase_offset=0 * np.pi / 180, delay=0, system=system)
/home/runner/work/MRzero-Docs/MRzero-Docs/.venv/lib/python3.11/site-packages/MRzeroCore/util.py:829: UserWarning: write(): 1 timing errors found in the sequence
  seq.write('tmp.seq')
DEPRECATED: util.simulate_2d will be removed in the future.
Use util.simulate() instead (together with util.load_phantom() if necessary
>>>> Rust - compute_graph(...) >>>
Converting Python -> Rust: 0.000180688 s
Compute Graph
Computing Graph: 0.00052436 s
Analyze Graph
Analyzing Graph: 0.000017893 s
Converting Rust -> Python: 0.000469187 s
<<<< Rust <<<<
Calculating repetition 6 / 13
Calculating repetition 12 / 13
Calculating repetition 13 / 13 - done
Can't insert signal into pulseq plot:
Signal and sequence have different amount of ADC samples.
<Figure size 640x480 with 3 Axes><Figure size 640x480 with 3 Axes>
#@title Detailed phantom definition and simulation ation


# Prepare the sequence output for the scanner
seq.set_definition('FOV', [fov, fov, slice_thickness])
seq.set_definition('Name', 'FID')
seq.write('FID.seq')
#@markdown  The B0 inhomogeneity brings you from the rotating frame FID at dB0=0, closer to the lab frame FID at dB0=B0.
#@markdown Try dB0=0 and dB0=500 for a test.
dB0 = 470 #@param {title:'dB0',type:"slider", min:0, max:500, step:10}
# %% S4: SETUP SPIN SYSTEM/object on which we can run the MR sequence external.seq from above
sz = [64, 64]
obj_p = mr0.VoxelGridPhantom.load_mat('numerical_brain_cropped.mat')
obj_p = obj_p.interpolate(sz[0], sz[1], 1)
# Manipulate loaded data
obj_p.B0 += dB0
obj_p.D *= 0
#obj_p.plot()
# Convert Phantom into simulation data
obj_p = obj_p.build()

# %% S5:. SIMULATE  the external.seq file and add acquired signal to ADC plot
# Read in the sequence
seq0 = mr0.Sequence.import_file("FID.seq")
# seq0.plot_kspace_trajectory()
# Simulate the sequence
graph = mr0.compute_graph(seq0, obj_p, 200, 1e-3)
signal = mr0.execute_graph(graph, seq0, obj_p, print_progress=False)
# PLOT sequence with SIGNAL

seq.plot(plot_now=False)
mr0.util.insert_signal_plot(seq=seq, signal =signal.numpy())
plt.show()

# plt.figure()
# plt.plot(signal.abs().numpy(),'.')
# plt.show()
/tmp/ipykernel_2275/2062822204.py:7: UserWarning: write(): 1 timing errors found in the sequence
  seq.write('FID.seq')
>>>> Rust - compute_graph(...) >>>
Converting Python -> Rust: 0.000383366 s
Compute Graph
Computing Graph: 0.000049252 s
Analyze Graph
Analyzing Graph: 0.000001142 s
Converting Rust -> Python: 0.00000548 s
<<<< Rust <<<<
<Figure size 640x480 with 3 Axes><Figure size 640x480 with 3 Axes>
seq.plot(plot_now=False)
mr0.util.insert_signal_plot(seq=seq, signal =signal.numpy())
plt.close(plt.figure(2))
plt.show()
<Figure size 640x480 with 3 Axes>