source: aedes_readbruker.m @ 193

Last change on this file since 193 was 193, checked in by tjniskan, 7 years ago
  • Added a warning about reconstructing Bruker raw data (FID-files)

M aedes_readbruker.m
M aedes_revision.m

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

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