CPMG condition for a simple spin-echo sequence
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/nullDefaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: torchkbnufft in /home/runner/.local/lib/python3.12/site-packages (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)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 367.8/367.8 kB 19.5 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
Downloading 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 17.3 MB/s eta 0:00:00
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
Downloading 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)
Downloading 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)
Downloading 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)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ 5.1/5.1 MB 152.6 MB/s eta 0:00:01 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.1/5.1 MB 116.0 MB/s eta 0:00:00
Downloading xsdata-25.7-py3-none-any.whl (234 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 234.5/234.5 kB 66.8 MB/s eta 0:00:00
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
plt.rcParams['figure.figsize'] = [10, 5]
plt.rcParams['figure.dpi'] = 100 # 200 e.g. is really fine, but slower
experiment_id = 'CPMG'
# %% 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=50*10e-6
)#@title CMPG in a brain phantom - sequence
# %% DEFINE the sequence, FOV and resolution
seq = pp.Sequence(system)
fov = 200e-3
Nread = 31 #@param {type:"slider", min:0, max:512, step:1}
Nphase = 1
slice_thickness = 8e-3 # slice
refocusing_angle=180 #@param {type:"slider", min:0, max:360, step:1}
# Define rf events
ETL=12 #@param {type:"slider", min:1, max:32, step:1}
TE_ms=1 #@param {type:"slider", min:1, max:32, step:1}
TE_ms*=1e-3
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)
rf2, _, _ = pp.make_sinc_pulse(
flip_angle=refocusing_angle * np.pi / 180, duration=1e-3, phase_offset=90 * np.pi / 180,
slice_thickness=slice_thickness, apodization=0.5, time_bw_product=4,
system=system, return_gz=True
)
sym_rf_block_delay=pp.calc_duration(rf1)-rf1.ringdown_time+rf1.delay
# Define other gradients and ADC events
dwell_time=1e-4
adc = pp.make_adc(num_samples=Nread, duration=Nread*dwell_time, phase_offset=0 * np.pi / 180, system=system)
minTE = pp.calc_duration(adc)+sym_rf_block_delay
print("Set TE to minTE ",minTE)
TEdelay=(TE_ms-minTE)/2
if TEdelay<0: TEdelay=0
# ======
# CONSTRUCT SEQUENCE
# ======
seq.add_block(rf1,sym_rf_block_delay)
seq.add_block(pp.make_delay(TEdelay+minTE/2 - sym_rf_block_delay))
for i in range(0, ETL):
seq.add_block(rf2,sym_rf_block_delay)
seq.add_block(pp.make_delay(TEdelay))
seq.add_block(adc)
seq.add_block(pp.make_delay(TEdelay))
# %% SIMULATE the external.seq file and add acquired signal to ADC plot
#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_2278/3227797924.py:14: 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_2278/3227797924.py:20: UserWarning: Specified RF delay 0.00 us is less than the dead time 100 us. Delay was increased to the dead time.
rf2, _, _ = pp.make_sinc_pulse(
/tmp/ipykernel_2278/3227797924.py:30: 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=Nread*dwell_time, phase_offset=0 * np.pi / 180, system=system)
Set TE to minTE 0.0051400000000000005
DEPRECATED: util.simulate_2d will be removed in the future.
Use util.simulate() instead (together with util.load_phantom() if necessary
---------------------------------------------------------------------------
ParseError Traceback (most recent call last)
Cell In[3], line 49
45 seq.add_block(pp.make_delay(TEdelay))
47 # %% SIMULATE the external.seq file and add acquired signal to ADC plot
48 #quick 2D brain phantom sim and plot
---> 49 signal = mr0.util.simulate_2d(seq)
50 # seq.plot(plot_now=False)
51 # mr0.util.insert_signal_plot(seq=seq, signal =signal.numpy())
52 # plt.show()
File ~/work/MRzero-Docs/MRzero-Docs/.venv/lib/python3.11/site-packages/MRzeroCore/util.py:870, in simulate_2d(seq, sim_size, noise_level, dB0, B0_scale, B0_polynomial)
867 obj_p = obj_p.build()
869 # MR zero simulation
--> 870 seq0 = mr0.Sequence.import_file(seq_filename)
872 # Remove temporary sequence file
873 if not isinstance(seq, str):
File ~/work/MRzero-Docs/MRzero-Docs/.venv/lib/python3.11/site-packages/MRzeroCore/sequence.py:457, in Sequence.import_file(cls, file_name, exact_trajectories, print_stats, default_shim, ref_voltage, resolution)
455 start = time()
456 if file_name.endswith(".seq"):
--> 457 parser = pydisseqt.load_pulseq(file_name)
458 else:
459 parser = pydisseqt.load_dsv(file_name, ref_voltage, resolution)
ParseError: No such file or directory (os error 2)seq.plot(plot_now=False)
mr0.util.insert_signal_plot(seq=seq, signal =signal.numpy())
plt.close(plt.figure(2))
plt.show()# Check whether the timing of the sequence is correct
ok, error_report = seq.check_timing()
if ok:
print('Timing check passed successfully')
else:
print('Timing check failed. Error listing follows:')
[print(e) for e in error_report]
# Prepare the sequence output for the scanner
seq.set_definition('FOV', [fov, fov, slice_thickness])
seq.set_definition('Name', 'CPMG')
seq.write(experiment_id + ".seq")