source: aedes_readbruker.m @ 179

Last change on this file since 179 was 179, checked in by tjniskan, 7 years ago
  • Fixed a bug in handling blick size in aedes_readbruker.m

M aedes_readbruker.m
M aedes_revision.m

File size: 17.6 KB
Line 
1function DATA = aedes_readbruker(filename,varargin)
2% AEDES_READBRUKER - Read Bruker file formats (raw FID-files and
3%                    reconstructed 2DSEQ files)
4%   
5%
6% Synopsis:
7%        DATA=aedes_readbruker(filename,'PropertyName1',value1,'PropertyName2',value2,...)
8%        DATA=aedes_readbruker(filename,'header')
9%
10% Description:
11%        The function reads Bruker FID- and 2DSEQ files and returns a structure
12%        DATA with fields DataFormat, HDR, FTDATA, KSPACE, PROCPAR, and
13%        PHASETABLE. The fields of the DATA structure are constructed as
14%        follows:
15%       
16%        DATA
17%          |-> DataFormat         (string identifier for data format 'bruker_raw'/'bruker_reco')
18%          |-> HDR
19%                |-> FileHeader   (data file header)
20%                |-> BlockHeaders (Varian FID file data block headers)
21%                |-> fname        (file name)
22%                |-> fpath        (file path)
23%                |-> Param        (parameter values used by AEDES_READBRUKER to read the data)
24%          |-> FTDATA             (real fourier transformed image data)
25%          |-> KSPACE             (complex k-space, empty by default)
26%          |-> PROCPAR            (parameters from procpar file, NOTE: Varian FID files only)
27%          |-> PHASETABLE         (phasetable)
28%
29%        The DATA structure is returned as empty (without the above described fields)
30%        if an error has occurred during reading.
31%       
32%        The first input argument is either a string containing full path to
33%        the FID/2DSEQ-file or an empty string. Only the data file headers
34%        can be read by giving a string 'header' as the second input
35%        argument.
36%
37%        By default the k-space is not returned, i.e. the field KSPACE is
38%        empty. The returned data can be adjusted by using the 'return'
39%        property and values 1, 2, or 3 (see below for more information).
40%        The return option is ignored for 2DSEQ files.
41%
42%        The supported property-value pairs in AEDES_READBRUKER (property strings
43%        are not case sensitive):
44%
45%        Property:        Value:                Description:
46%        *********        ******                ************
47%        'Return'      :  [ {1} | 2 | 3 | 4 ]   % 1=return only ftdata (default)
48%                                               % 2=return only k-space
49%                                               % 3=return both ftdata & kspace
50%                                               % 4=return raw kspace
51%
52%        'wbar'        : [ {'on'} | 'off' ]     % Show/hide waitbar
53%
54%        'Precision'   : [{'double'}|'single']  % The precision for the
55%                                               % reconstructed and scaled
56%                                               % data. (default='double')
57%
58%
59% Examples:
60%        DATA=aedes_readbruker(filename)   % Read image data from 'filename'
61%
62% See also:
63%        AEDES, AEDES_READVNMR
64
65% This function is a part of Aedes - A graphical tool for analyzing
66% medical images
67%
68% Copyright (C) 2011 Juha-Pekka Niskanen <Juha-Pekka.Niskanen@uef.fi>
69%
70% Department of Applied Physics, Department of Neurobiology
71% University of Eastern Finland, Kuopio, FINLAND
72%
73% This program may be used under the terms of the GNU General Public
74% License version 2.0 as published by the Free Software Foundation
75% and appearing in the file LICENSE.TXT included in the packaging of
76% this program.
77%
78% This program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
79% WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
80
81% Defaults
82DATA = [];
83isRawData = true;
84Dat.showWbar = true;
85Dat.precision = 'double';
86Dat.return = 1;
87Dat.zerofill = 'auto';
88
89if nargin == 0 || isempty(filename)
90        [fname,fpath,findex] = uigetfile({'fid;fid.*;2dseq','Bruker file formats (fid, 2dseq)';...
91                '*.*','All Files (*.*)'},'Select Bruker file formats');
92        if isequal(fname,0)
93                % Canceled
94                return
95        end
96        filename = [fpath,fname];
97end
98
99% Parse filename
100[fp,fn,fe] = fileparts(filename);
101if strcmpi(fn,'fid')
102        isRawData = true;
103        data_format = aedes_getdataformat(filename);
104        if strcmpi(data_format,'vnmr')
105                error('aedes_readbruker cannot read Varian FID-files. Use aedes_readvnmr instead.');
106        end
107elseif strcmpi(fn,'2dseq')
108        isRawData = false;
109else
110        error('Only Bruker FID and 2DSEQ files are supported.');
111end
112
113% Check varargin length
114if rem(length(varargin),2)==1
115        error('Input arguments may only include filename and param/value pairs.')
116end
117
118% Parse varargin
119for ii=1:2:length(varargin)
120        param = varargin{ii};
121        if ~ischar(param) || isempty(param)
122                error('Parameters must be strings.')
123        end
124        value = varargin{ii+1};
125        switch lower(param)
126                case 'wbar'
127                        Dat.wbar = value;
128                case 'precision'
129                        Dat.precision = value;
130                case 'return'
131                        if ~isnumeric(value) || ~isscalar(value) || isempty(value) || ...
132                                        isnan(value) || ~isreal(value) || (value-floor(value)) ~= 0 || ...
133                                        value < 1 || value > 4
134                                error('Invalid return value. Return value can be an integer in the range 1..4')
135                        end
136                        Dat.return = value;
137                otherwise
138                        error('Unknown parameter "%s".',param)
139        end
140end
141
142if isRawData
143        [hdr,msg] = l_ReadHeaderFid(filename);
144        if isempty(hdr)
145                error(msg);
146        end
147        [data,kspace,pe1_table,msg] = l_ReadDataFid(filename,hdr,Dat);
148        DATA.DataFormat = 'bruker_raw';
149else
150        [hdr,msg] = l_ReadHeader2dseq(filename);
151        if isempty(hdr)
152                error(msg);
153        end
154        [data,kspace,msg] = l_ReadData2dseq(filename,hdr,Dat);
155        DATA.DataFormat = 'bruker_reco';
156        pe1_table = [];
157end
158if isempty(data) && isempty(kspace)
159        DATA = [];
160        error(msg);
161end
162
163DATA.HDR.FileHeader = hdr;
164DATA.HDR.BlockHeader = [];
165DATA.HDR.fname = [fn,fe];
166DATA.HDR.fpath = [fp,filesep];
167DATA.FTDATA = data;
168if Dat.return == 1
169        DATA.KSPACE = [];
170        clear kspace;
171else
172        DATA.KSPACE = kspace;
173end
174DATA.PROCPAR = [];
175DATA.PHASETABLE = pe1_table;
176
177
178% - Subfunctions -
179
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181% Read header files for raw data
182%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183function [hdr,msg] = l_ReadHeaderFid(filename)
184
185hdr = [];
186msg = '';
187
188% Parse filename
189[fp,fn,fe] = fileparts(filename);
190
191% Read Header files -------------------------
192
193% Read ACQP file
194acqp_file = [fp,filesep,'acqp'];
195if exist(acqp_file,'file')~=2
196        msg = sprintf('Cannot find ACQP file in "%s".',fp);
197        return
198end
199try
200        hdr.acqp = aedes_readjcamp(acqp_file);
201catch
202        hdr = [];
203        msg = sprintf('Error while reading "%s". The error was "%s".',...
204                acqp_file,lasterr);
205        return
206end
207
208% Read Method file
209method_file = [fp,filesep,'method'];
210if exist(method_file,'file')~=2
211        msg = sprintf('Cannot find METHOD file in "%s".',fp);
212        return
213end
214try
215        hdr.method = aedes_readjcamp(method_file);
216catch
217        hdr = [];
218        msg = sprintf('Error while reading "%s". The error was "%s".',...
219                method_file,lasterr);
220        return
221end
222
223
224
225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226% Read header files for reconstructed 2dseq data
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228function [hdr,msg] = l_ReadHeader2dseq(filename)
229
230hdr = [];
231msg = '';
232
233% Parse filename
234[fp,fn,fe] = fileparts(filename);
235
236% Read Header files -------------------------
237
238% Read d3proc file
239d3proc_file = [fp,filesep,'d3proc'];
240if exist(d3proc_file,'file')~=2
241        hdr = [];
242        msg = sprintf('Cannot find D3PROC file in "%s".',fp);
243        return
244end
245try
246        hdr.d3proc = aedes_readjcamp(d3proc_file);
247catch
248        hdr = [];
249        msg = sprintf('Error while reading "%s". The error was "%s".',...
250                d3proc_file,lasterr);
251        return
252end
253
254% Read procs file
255procs_file = [fp,filesep,'procs'];
256if exist(procs_file,'file')~=2
257        hdr = [];
258        msg = sprintf('Cannot find PROCS file in "%s".',fp);
259        return
260end
261try
262        hdr.procs = aedes_readjcamp(procs_file);
263catch
264        hdr = [];
265        msg = sprintf('Error while reading "%s". The error was "%s".',...
266                procs_file,lasterr);
267        return
268end
269
270% Read reco file
271reco_file = [fp,filesep,'reco'];
272if exist(reco_file,'file')~=2
273        warning('Cannot find RECO file in "%s"',fp);
274else
275        try
276                hdr.reco = aedes_readjcamp(reco_file);
277        catch
278                hdr = [];
279                msg = sprintf('Error while reading "%s". The error was "%s".',...
280                        reco_file,lasterr);
281                return
282        end
283end
284
285% Check for Functional Imaging Tool files
286if exist([fp,filesep,'fun'],'dir') == 7
287       
288        % To be implemented...
289       
290end
291
292return
293
294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295% Read raw Bruker data (fid files)
296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297function [data,kspace,pe1_table,msg] = l_ReadDataFid(filename,hdr,Dat)
298
299data = [];
300kspace = [];
301msg = '';
302
303% Get word type
304if strcmpi(hdr.acqp.GO_raw_data_format,'GO_32BIT_SGN_INT')
305        precision = ['int32=>',Dat.precision];
306elseif strcmpi(hdr.acqp.GO_raw_data_format,'GO_16BIT_SGN_INT')
307        precision = ['int16=>',Dat.precision];
308elseif strcmpi(hdr.acqp.GO_raw_data_format,'GO_16BIT_FLOAT')
309        precision = ['single=>',Dat.precision];
310else
311        msg = sprintf('Unknown word type "%s".',hdr.acqp.GO_raw_data_format);
312        return
313end
314
315% Get byteorder
316if strcmpi(hdr.acqp.BYTORDA,'little')
317        byteorder = 'ieee-le';
318else
319        byteorder = 'ieee-be';
320end
321
322% Get block size
323if strcmpi(hdr.acqp.GO_block_size,'continuous')
324        fixed_blocksize = false;
325elseif strcmpi(hdr.acqp.GO_block_size,'Standard_KBlock_format')
326        fixed_blocksize = true;
327else
328        msg = sprintf('Unknown block size identifier "%s".',hdr.acqp.GO_block_size);
329        return
330end
331
332% Open fid file for reading
333fid = fopen(filename,'r',byteorder);
334if fid < 0
335        hdr.acqp = [];
336        hdr.method = [];
337        msg = sprintf('Could not open file "%s" for reading.',filename);
338        return
339end
340
341% Read fid file
342tmp = fread(fid,inf,precision);
343fclose(fid);
344kspace = complex(tmp(1:2:end),tmp(2:2:end));
345
346% Handle block size
347if strcmp(hdr.acqp.GO_block_size,'Standard_KBlock_Format')
348        blk_size = round(length(kspace)/1024)*1024;
349else
350        blk_size = hdr.acqp.ACQ_size(1)/2;
351end
352kspace = reshape(kspace,blk_size,[]);
353
354% Reconstruct k-space
355if Dat.return ~= 4
356        [kspace,pe1_table,msg] = l_ReconstructKspace(kspace,hdr,Dat);
357else
358        pe1_table = l_GetPeTable(hdr);
359end
360if isempty(kspace)
361        kspace = [];
362        return
363end
364
365% Fourier transform k-space
366if any(Dat.return==[1 3])
367        [data,msg] = l_doFFT(kspace,hdr,Dat);
368        if isempty(data)
369                kspace = [];
370                data = [];
371                return
372        end
373else
374        data = [];
375end
376
377
378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379% Read reconstructed Bruker data (2dseq files)
380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381function [data,kspace,msg] = l_ReadData2dseq(filename,hdr,Dat)
382
383data = [];
384kspace = [];
385msg = '';
386
387% Get word type
388if isfield(hdr,'reco')
389        if strcmpi(hdr.reco.RECO_wordtype,'_8BIT_UNSGN_INT')
390                precision = ['uint8=>',Dat.precision];
391        elseif strcmpi(hdr.reco.RECO_wordtype,'_16BIT_SGN_INT')
392                precision = ['int16=>',Dat.precision];
393        elseif strcmpi(hdr.reco.RECO_wordtype,'_32BIT_SGN_INT')
394                precision = ['int32=>',Dat.precision];
395        elseif strcmpi(hdr.reco.RECO_wordtype,'_32BIT_FLOAT')
396                precision = ['single=>',Dat.precision];
397        else
398                msg = sprintf('Unknown word type "%s".',hdr.reco.RECO_wordtype);
399                return
400        end
401else
402        % Try to guess the word type from file size if reco file was not found...
403        sz = [hdr.d3proc.IM_SIX,...
404                hdr.d3proc.IM_SIY,...
405                hdr.d3proc.IM_SIZ,...
406                hdr.d3proc.IM_SIT];
407        d=dir(filename);
408        nBytes = d.bytes;
409        bytesPerPixel = nBytes/prod(sz);
410        if bytesPerPixel == 1
411                precision = ['uint8=>',Dat.precision];
412        elseif bytesPerPixel == 2
413                precision = ['int16=>',Dat.precision];
414        else
415                precision = ['int32=>',Dat.precision];
416        end
417end
418
419% Get byteorder
420if isfield(hdr,'reco')
421        if strcmpi(hdr.reco.RECO_byte_order,'littleEndian')
422                byteorder = 'ieee-le';
423        else
424                byteorder = 'ieee-be';
425        end
426else
427        % Use little endian if no information is available
428        byteorder = 'ieee-le';
429end
430
431% Get image type
432if isfield(hdr,'reco')
433        if strcmpi(hdr.reco.RECO_image_type,'COMPLEX_IMAGE')
434                isDataComplex = true;
435        elseif strcmpi(hdr.reco.RECO_image_type,'MAGNITUDE_IMAGE')
436                isDataComplex = false;
437        else
438                msg = sprintf('Unknown image type "%s".',hdr.reco.RECO_image_type);
439                return
440        end
441else
442        % Assume magnitude image if information is not available
443        isDataComplex = false;
444end
445
446% Open 2dseq file for reading
447fid = fopen(filename,'r',byteorder);
448if fid < 0
449        msg = sprintf('Could not open 2dseq file "%s" for reading.');
450        return
451end
452
453% Show waitbar
454if Dat.showWbar
455        wbh = aedes_calc_wait('Reading data from Bruker 2dseq file.');
456end
457
458% Read data
459if ~isDataComplex
460        % - Read magnitude data ---------------------------------
461        [data,count] = fread(fid,inf,precision);
462        fclose(fid);
463       
464        % Reshape and permute to correct size and orientation
465        data = reshape(data,[hdr.d3proc.IM_SIX,...
466                hdr.d3proc.IM_SIY,...
467                hdr.d3proc.IM_SIZ,...
468                hdr.d3proc.IM_SIT]);
469        data = permute(data,[2 1 3 4]);
470       
471        % Map integer data to single or double values
472        if ~strcmpi(hdr.reco.RECO_wordtype,'_32BIT_FLOAT')
473                slope = hdr.reco.RECO_map_slope;
474                offset = hdr.reco.RECO_map_offset;
475                if length(hdr.reco.RECO_size) == 1
476                        nDim = 1;
477                elseif length(hdr.reco.RECO_size) == 2
478                        nDim = 2;
479                elseif length(hdr.reco.RECO_size) == 3
480                        nDim = 3;
481                end
482                for ii=1:length(slope)
483                        if any(nDim == [1 2])
484                                data(:,:,ii) = data(:,:,ii)/slope(ii)+offset(ii);
485                        else
486                                data(:,:,:,ii) = data(:,:,:,ii)/slope(ii)+offset(ii);
487                        end
488                end
489        end
490       
491        % The length of RECO_transposition should be same as NI.
492        NI = length(hdr.reco.RECO_transposition);
493        if NI~=hdr.d3proc.IM_SIZ
494                data = reshape(data,hdr.d3proc.IM_SIY,...
495                        hdr.d3proc.IM_SIX,NI,[]);
496        end
497       
498else
499        % - Read complex data -----------------------------------
500        [data,count] = fread(fid,inf,precision);
501        fclose(fid);
502       
503        % Reshape and permute to correct size and orientation
504        data = reshape(data,[hdr.d3proc.IM_SIX,...
505                hdr.d3proc.IM_SIY,...
506                hdr.d3proc.IM_SIZ,...
507                hdr.d3proc.IM_SIT]);
508        data = permute(data,[2 1 3 4]);
509       
510        % Map integer data to single or double values
511        if ~strcmpi(hdr.reco.RECO_wordtype,'_32BIT_FLOAT')
512                slope = hdr.reco.RECO_map_slope;
513                offset = hdr.reco.RECO_map_offset;
514                if length(hdr.reco.RECO_size) == 2
515                        nDim = 2;
516                elseif length(hdr.reco.RECO_size) == 3
517                        nDim = 3;
518                end
519                for ii=1:length(slope)
520                        if nDim == 2
521                                data(:,:,ii) = data(:,:,ii)/slope(ii)+offset(ii);
522                        else
523                                data(:,:,:,ii) = data(:,:,:,ii)/slope(ii)+offset(ii);
524                        end
525                end
526        end
527       
528        data = reshape(data,hdr.reco.RECO_size(1),...
529                hdr.reco.RECO_size(2),...
530                hdr.reco.RECO_size(3),[]);
531       
532        kspace = complex(data(:,:,:,1),data(:,:,:,2));
533        data = [];
534end
535
536% Close waitbar
537if Dat.showWbar
538        close(wbh);
539end
540
541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542% Reconstruct k-space
543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544function [kspace,pe1_table,msg] = l_ReconstructKspace(kspace,hdr,Dat)
545
546msg = '';
547
548% Don't try to reconstruct 1D data
549nDims = hdr.acqp.ACQ_dim;
550if nDims == 1
551        pe1_table = l_GetPeTable(hdr);
552        return
553end
554NI = hdr.acqp.NI; % Number of objects
555NSLICES = hdr.acqp.NSLICES; % Number of slices
556NR = hdr.acqp.NR; % Number of repetitions
557phase_factor = hdr.acqp.ACQ_phase_factor; % scans belonging to a single image
558im_size = hdr.acqp.ACQ_size;im_size(1)=im_size(1)/2;
559order = hdr.acqp.ACQ_obj_order;
560
561% Get phase table
562usePeTable = true;
563pe1_table = l_GetPeTable(hdr);
564if isempty(pe1_table)
565        usePeTable = false;
566end
567
568% Reshape data so that all echoes are in correct planes
569kspace = reshape(kspace,im_size(1),...
570        phase_factor,NI,im_size(2)/phase_factor,NR);
571kspace = permute(kspace,[1 2 4 3 5]);
572kspace = reshape(kspace,im_size(1),im_size(2),NI,NR);
573
574% Handle EPI data
575if strncmpi(hdr.acqp.PULPROG,'EPI',3)
576        epi_matrix_size = hdr.method.PVM_Matrix;
577        kspace = reshape(kspace,epi_matrix_size(1),epi_matrix_size(2),NSLICES,NR);
578end
579
580% Sort echoes
581if usePeTable
582        kspace = kspace(:,pe1_table,:,:);
583end
584
585% Sort object order
586kspace(:,:,order+1,:) = kspace;
587
588% Permute to correct orientation
589kspace = flipdim(flipdim(kspace,1),2);
590
591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592% Check that the required reconstruction parameters are found in acqp
593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594function [ok,msg] = l_CheckAcqpParams(hdr)
595
596ok = false;
597msg = '';
598
599% Minimal list of ACQP parameters for data reconstruction
600minParamList = {...
601        'ACQ_dim',...
602        'ACQ_size',...
603        'NI',...
604        'NR',...
605        'BYTORDA',...
606        'ACQ_word_size',...
607        'ACQ_scan_size',...
608        'ACQ_scan_shift',...
609        'ACQ_phase_factor',...
610        'ACQ_rare_factor',...
611        'ACQ_phase_encoding_mode',...
612        'ACQ_phase_enc_start',...
613        'ACQ_spatial_size_1',...
614        'ACQ_spatial_size_2',...
615        'ACQ_spatial_phase_1',...
616        'ACQ_spatial_phase_2',...
617        'ACQ_obj_order',...
618        'ACQ_mod',...
619        'DSPFVS',...
620        'DSPFIRM',...
621        'DECIM'};
622
623param = fieldnames(hdr.acqp);
624
625
626
627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628% Fourier transform data
629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630function [data,msg] = l_doFFT(kspace,hdr,Dat)
631
632data = [];
633msg = '';
634
635% Check dimensions
636if hdr.acqp.ACQ_dim == 1
637  % 1D-image
638  AcqType = 1;
639elseif hdr.acqp.ACQ_dim == 2
640  % 2D-image
641  AcqType = 2;
642elseif hdr.acqp.ACQ_dim == 3
643  % 3D-image
644  AcqType = 3;
645else
646  AcqType = 4;
647end
648
649% Do Zero filling if requested
650if any(AcqType == [2 3])
651        switch Dat.zerofill
652                case 'auto'
653                       
654                case 'on'
655                       
656                case 'off'
657                       
658                otherwise
659                        warning('Unknown zerofill option "%s". Skipping zerofilling...',...
660                                Dat.zerofill);
661        end
662end
663
664if AcqType==1
665        %data = flipdim(abs(fftshift(fft(kspace,[],1),1)),1);
666        data = abs(fftshift(fft(flipdim(kspace,1),[],1),1));
667  %data = circshift(flipdim(abs(fftshift(fft(kspace,[],1),1)),1),[1 0 0]);
668elseif AcqType==2
669  data = abs(fftshift(fftshift(fft(fft(kspace,[],1),[],2),1),2));
670elseif AcqType==3
671  data = abs(fftshift(fftshift(fftshift(fft(fft(fft(kspace,[],1),[],2),[],3),1),2),3));
672end
673
674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675% Calculate phase table indexes
676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677function pt = l_GetPeTable(hdr)
678
679if ~isfield(hdr,'acqp') || ~isfield(hdr,'method')
680        error('Cannot determine phase table, because ACQP and/or METHODS fields are missing.')
681end
682
683if isfield(hdr.acqp,'ACQ_spatial_phase_1')
684        [s,pt] = sort(hdr.acqp.ACQ_spatial_phase_1);
685elseif isfield(hdr.method,'PVM_EncSteps1')
686        pt = hdr.method.PVM_EncSteps1+(-min(hdr.method.PVM_EncSteps1(:))+1);
687else
688        pt = [];
689end
690
691
692
693
694
695
696
697
698
699
700
Note: See TracBrowser for help on using the repository browser.

Powered by Trac 1.0.9.Copyright © Juha-Pekka Niskanen 2008