concept-collection / seqlab
seqlab / src / examples / pulseq / UTE.m
106 lines · 4.3 KBBlameHistoryRaw
1% a very basic UTE-like sequence, without ramp-sampling, ramp-RF and other
2% tricks yet. Achieves TE in the range of 300-400 us
3
4% set system limits
5sys = mr.opts('MaxGrad', 28, 'GradUnit', 'mT/m', ...
6 'MaxSlew', 100, 'SlewUnit', 'T/m/s', 'rfRingdownTime', 20e-6, ...
7 'rfDeadTime', 100e-6, 'adcDeadTime', 10e-6);
8
9seq=mr.Sequence(sys); % Create a new sequence object
10fov=250e-3; Nx=256; % Define FOV and resolution
11alpha=10; % flip angle
12sliceThickness=3e-3; % slice
13TR=10e-3; % TR
14Nr=128; % number of radial spokes
15delta= 2* pi / Nr; % angular increment; try golden angle pi*(3-5^0.5) or 0.5 of it
16ro_duration=2.56e-3; % read-out time: controls RO bandwidth and T2-blurring
17ro_os=2; % oversampling
18ro_asymmetry=1; % 0: fully symmetric 1: half-echo
19minRF_to_ADC_time=50e-6; % the parameter wich defines TE (together with the RO asymmetyry)
21% more in-depth parameters
22% RF spoiling increment = 84° for smoother transient decay, https://doi.org/10.1002/mrm.1910350216, 169° for diffusion independent rf spoiling in steady-state https://doi.org/10.1371/journal.pone.0324455
23rfSpoilingInc=84; % RF spoiling increment
25% Create alpha-degree slice selection pulse and gradient
26[rf, gz, gzReph] = mr.makeSincPulse(alpha*pi/180,'Duration',1e-3,...
27 'SliceThickness',sliceThickness,'apodization',0.5,'timeBwProduct',2,...
28 'centerpos',1,'system',sys, 'use','excitation');
30% Align RO assymmetry to ADC samples
31Nxo=round(ro_os*Nx);
32ro_asymmetry = round(ro_asymmetry*Nxo/2)/Nxo*2; % check whether we need to use 2Nx or so...
33% Define other gradients and ADC events
34deltak=1/fov/(1+ro_asymmetry);
35ro_area=Nx*deltak;
36gx = mr.makeTrapezoid('x','FlatArea',ro_area,'FlatTime',ro_duration,'system',sys);
37adc = mr.makeAdc(Nxo,'Duration',gx.flatTime,'Delay',gx.riseTime,'system',sys);
38gxPre = mr.makeTrapezoid('x','Area',-(gx.area-ro_area)/2 -gx.amplitude*adc.dwell/2 - ro_area/2*(1-ro_asymmetry),'system',sys);
40% gradient spoiling
41gxSpoil=mr.makeTrapezoid('x','Area',0.2*Nx*deltak,'system',sys);
43% Calculate timing
44%ceil((TE - mr.calcDuration(gxPre) - gz.fallTime - gz.flatTime/2 ...
45% - mr.calcDuration(gx)/2)/seq.gradRasterTime)*seq.gradRasterTime;
46% calculate actual achieved TE
47TE = gz.fallTime + mr.calcDuration(gxPre,gzReph)+gx.riseTime + adc.dwell*Nxo/2*(1-ro_asymmetry);
48delayTR=ceil((TR - mr.calcDuration(gxPre,gzReph) - mr.calcDuration(gz) ...
49 - mr.calcDuration(gx))/seq.gradRasterTime)*seq.gradRasterTime;
50assert(all(delayTR>=mr.calcDuration(gxSpoil)));
52fprintf('TE= %d us\n', round(TE*1e6));
54if mr.calcDuration(gzReph) > mr.calcDuration(gxPre)
55 gxPre.delay=mr.calcDuration(gzReph) - mr.calcDuration(gxPre);
56end
58rf_phase=0;
59rf_inc=0;
61for i=1:Nr
62 for c=1:2
63 rf.phaseOffset=rf_phase/180*pi;
64 adc.phaseOffset=rf_phase/180*pi;
65 rf_inc=mod(rf_inc+rfSpoilingInc, 360.0);
66 rf_phase=mod(rf_phase+rf_inc, 360.0);
67 % UTE: alternate GZ
68 gz.amplitude=-gz.amplitude;
69 gzReph.amplitude=-gzReph.amplitude;
70 %
71 seq.addBlock(rf,gz);
72 phi=delta*(i-1);
73 gpc=gxPre; gps=gxPre; gpc.amplitude=gxPre.amplitude*cos(phi); gps.amplitude=gxPre.amplitude*sin(phi); gps.channel='y';
74 grc=gx; grs=gx; grc.amplitude=gx.amplitude*cos(phi); grs.amplitude=gx.amplitude*sin(phi); grs.channel='y';
75 gsc=gxSpoil; gss=gxSpoil; gsc.amplitude=gxSpoil.amplitude*cos(phi); gss.amplitude=gxSpoil.amplitude*sin(phi); gss.channel='y';
76 seq.addBlock(gpc,gps,gzReph);
77 seq.addBlock(grc,grs,adc);
78 seq.addBlock(gsc,gss,mr.makeDelay(delayTR));
79 end
80end
82%% check whether the timing of the sequence is correct
83[ok, error_report]=seq.checkTiming;
85if (ok)
86 fprintf('Timing check passed successfully\n');
87else
88 fprintf('Timing check failed! Error listing follows:\n');
89 fprintf([error_report{:}]);
90 fprintf('\n');
91end
93%%
95%% plot gradients to check for gaps and optimality of the timing
96gw=seq.waveforms_and_times();
98%% k-space trajectory calculation
100% plot k-spaces
102%
103seq.setDefinition('FOV', [fov fov sliceThickness]);
104seq.setDefinition('Name', 'ute');
106seq.write('ute.seq'); % Write to pulseq file