78d04f1seqlab: write and view pulseq MRI sequences in the browserJeremy Magland 1function [varargout] = align(varargin)
2%align set alignment of the objects in the block
3%
4% align(align_spec, obj <, obj> <, align_spec, obj> ...);
5%
6% sets delays of the objects within the block to achieve the desired
7% alignment.
8% All previously configured delays within objects are taken into account
9% during calculating of the block duration but then reset according to
10% the selected alignment.
11% Possible values for align_spec are 'left', 'center', 'right'
12% WARNING: 'center' may break gradient raster alignment
13% When a numerical parameter is passed amongst the events it is
14% interpreted as the required duration of the block. If the duration of
15% any of the events exceeds this required duration an error will be thrown.
16% The required block duration is optionally returned as the last
17% parameter in the output list. If used within seq.addBlock() required
18% duration is always passed at the end of the list of the block events.
19%
20% See also Sequence.addBlock
21%
22% Maxim Zaitsev <maxim.zaitsev@uniklinik-freiburg.de>
24alignment_options={'left', 'center', 'right'};
25% parse parameters
26if ~ischar(varargin{1})
27 error('first parameter must be a string');
28end
29curr_align=find(strcmp(varargin{1},alignment_options));
30if isempty(curr_align)
31 error('invalid alignment spec');
32end
33iobjects=[];
34alignments=[];
35required_duration=[];
37for i=2:length(varargin)
38 if ischar(varargin{i})
39 curr_align=find(strcmp(varargin{i},alignment_options));
40 if isempty(curr_align)
41 error('invalid alignment spec');
42 end
43 continue;
44 end
45 if isnumeric(varargin{i})
46 if ~isempty(required_duration)
47 error('More than one numeric parameter given to align()');
48 end
49 required_duration=varargin{i};
50 continue;
51 end
52 iobjects(end+1)=i;
53 alignments=[alignments curr_align];
54end
56objects={varargin{iobjects}};
58dur=mr.calcDuration(objects);
59if ~isempty(required_duration)
60 if dur-required_duration>eps
61 error('Required block duration is %g s but actual block duration is %g s', required_duration, dur);
62 end
63 dur=required_duration;
64end
66% set new delays
67for i=1:length(objects)
68 if isfield(objects{i},'id')
69 error('attempting to align() readily registered object! please register objects after calling this function or deregister the argument(s) by calling rmfield(...,''id'')');
70 end
71 switch alignments(i)
72 case 1
73 objects{i}.delay=0;
74 case 2
75 objects{i}.delay=(dur - mr.calcDuration(objects{i}) + objects{i}.delay)/2;
76 case 3
77 ev=objects{i};
78 ev_dur=mr.calcDuration(ev);
79 %if isfield(ev,'ringdownTime')
80 % ev_dur=ev_dur+ev.ringdownTime;
81 %end
82 objects{i}.delay=dur - ev_dur + objects{i}.delay;
83 if objects{i}.delay < 0
84 error('align() attempts to set a negative delay, probably some RF pulses ignore rfRingdownTime');
85 end
86 end
87end
89if nargout==length(objects)
90 varargout=objects;
91elseif ~isempty(required_duration) && nargout==length(objects)+1
92 varargout=objects;
93 varargout{end+1}=required_duration;
94elseif nargout==1
95 if isempty(required_duration)
96 varargout={objects};
97 else
98 varargout={[objects {required_duration}]};
99 end
100elseif nargout<length(objects)
101 warning('not all objects can be assigned to the output arguments; we recommend using ~ to discard output arguments explicitly.');
102 nout=min(nargout,length(objects));
103 varargout=objects(1:nout);
104else
105 error(['the number of output arguments (' num2str(nargout) ') exceeds the number of sequence objects (' num2str(length(objects)) ') passed to the function.']);
106end
108end