concept-collection / seqlab
seqlab / src / examples / gre.m
90 lines · 3.5 KBBlameHistoryRaw
1% 2D RF-spoiled gradient echo (GRE), 128x128, single slice.
2% The classic pulseq demo: slice-selective sinc excitation, phase encoding,
3% RF spoiling, and reconstruction labels via seq.autoLabel.
4% Adapted from pulseq's demoSeq/writeGradientEcho.m.
6% set system limits
7sys = mr.opts('MaxGrad', 22, 'GradUnit', 'mT/m', ...
8 'MaxSlew', 120, 'SlewUnit', 'T/m/s', ...
9 'rfRingdownTime', 20e-6, 'rfDeadTime', 100e-6, 'adcDeadTime', 10e-6);
11seq = mr.Sequence(sys); % Create a new sequence object
12fov = 256e-3; Nx = 128; Ny = Nx; % Define FOV and resolution
13alpha = 10; % flip angle
14sliceThickness = 3e-3; % slice
15TR = 12e-3; % repetition time TR
16TE = 5e-3; % echo time TE
18rfSpoilingInc = 84; % RF spoiling increment
19roDuration = 3.2e-3; % ADC duration
21% autoLabel adds on-scanner reconstruction labels (LIN/PAR) by recomputing
22% the full k-space trajectory. It is NOT needed to generate or view the
23% sequence and dominates the runtime (~25 s here vs ~2 s without), so it is
24% off by default. Set to true to include the labels.
25doAutoLabel = false;
27% Create alpha-degree slice selection pulse and gradient
28[rf, gz] = mr.makeSincPulse(alpha*pi/180, sys, 'Duration', 3e-3, ...
29 'SliceThickness', sliceThickness, 'apodization', 0.42, 'timeBwProduct', 4, ...
30 'use', 'excitation');
32% Define other gradients and ADC events
33deltak = 1/fov;
34gx = mr.makeTrapezoid('x', sys, 'FlatArea', Nx*deltak, 'FlatTime', roDuration);
35adc = mr.makeAdc(Nx, sys, 'Duration', gx.flatTime, 'Delay', gx.riseTime);
36gxPre = mr.makeTrapezoid('x', sys, 'Area', -gx.area/2, 'Duration', 1e-3);
37gzReph = mr.makeTrapezoid('z', sys, 'Area', -gz.area/2, 'Duration', 1e-3);
38phaseAreas = ((0:Ny-1)-Ny/2)*deltak;
39gyPre = mr.makeTrapezoid('y', sys, 'Area', max(abs(phaseAreas)), 'Duration', mr.calcDuration(gxPre));
40peScales = phaseAreas/gyPre.area;
42% gradient spoiling
43gxSpoil = mr.makeTrapezoid('x', sys, 'Area', 2*Nx*deltak);
44gzSpoil = mr.makeTrapezoid('z', sys, 'Area', 4/sliceThickness);
46% Calculate timing
47delayTE = ceil((TE - mr.calcDuration(gxPre) - gz.fallTime - gz.flatTime/2 ...
48 - mr.calcDuration(gx)/2)/seq.gradRasterTime)*seq.gradRasterTime;
49delayTR = ceil((TR - mr.calcDuration(gz) - mr.calcDuration(gxPre) ...
50 - mr.calcDuration(gx) - delayTE)/seq.gradRasterTime)*seq.gradRasterTime;
51assert(all(delayTE >= 0));
52assert(all(delayTR >= mr.calcDuration(gxSpoil, gzSpoil)));
54rf_phase = 0;
55rf_inc = 0;
57% Loop over phase encodes and define sequence blocks
58for i = 1:Ny
59 rf.phaseOffset = rf_phase/180*pi;
60 adc.phaseOffset = rf_phase/180*pi;
61 rf_inc = mod(rf_inc + rfSpoilingInc, 360.0);
62 rf_phase = mod(rf_phase + rf_inc, 360.0);
63 %
64 seq.addBlock(rf, gz);
65 seq.addBlock(gxPre, mr.scaleGrad(gyPre, peScales(i)), gzReph);
66 seq.addBlock(mr.makeDelay(delayTE));
67 seq.addBlock(gx, adc);
68 seq.addBlock(mr.makeDelay(delayTR), gxSpoil, mr.scaleGrad(gyPre, -peScales(i)), gzSpoil)
69end
71% check whether the timing of the sequence is correct
72[ok, error_report] = seq.checkTiming;
73if ok
74 fprintf('Timing check passed successfully\n');
75else
76 fprintf('Timing check failed! Error listing follows:\n');
77 fprintf([error_report{:}]);
78 fprintf('\n');
79end
81% add data labels to make image reconstruction on the scanner possible
82if doAutoLabel
83 seq.autoLabel('mirrorFourier', true, 'sortSlices', 'descending');
84end
86% prepare sequence export
87seq.setDefinition('FOV', [fov fov sliceThickness]);
88seq.setDefinition('Name', 'gre');
90seq.write('gre.seq') % Write to pulseq file