source: aedes_readbruker.m @ 178

Last change on this file since 178 was 178, checked in by tjniskan, 8 years ago
  • Added some support for Bruker spectral data.
  • Fixed a small bug in aedes_readctdata.m.

M aedes_readbruker.m
M aedes_readctdata.m
M aedes_revision.m

File size: 17.4 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));
345kspace = reshape(kspace,hdr.acqp.ACQ_size(1)/2,[]);
346
347% Reconstruct k-space
348if Dat.return ~= 4
349        [kspace,pe1_table,msg] = l_ReconstructKspace(kspace,hdr,Dat);
350else
351        pe1_table = l_GetPeTable(hdr);
352end
353if isempty(kspace)
354        kspace = [];
355        return
356end
357
358% Fourier transform k-space
359if any(Dat.return==[1 3])
360        [data,msg] = l_doFFT(kspace,hdr,Dat);
361        if isempty(data)
362                kspace = [];
363                data = [];
364                return
365        end
366else
367        data = [];
368end
369
370
371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372% Read reconstructed Bruker data (2dseq files)
373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374function [data,kspace,msg] = l_ReadData2dseq(filename,hdr,Dat)
375
376data = [];
377kspace = [];
378msg = '';
379
380% Get word type
381if isfield(hdr,'reco')
382        if strcmpi(hdr.reco.RECO_wordtype,'_8BIT_UNSGN_INT')
383                precision = ['uint8=>',Dat.precision];
384        elseif strcmpi(hdr.reco.RECO_wordtype,'_16BIT_SGN_INT')
385                precision = ['int16=>',Dat.precision];
386        elseif strcmpi(hdr.reco.RECO_wordtype,'_32BIT_SGN_INT')
387                precision = ['int32=>',Dat.precision];
388        elseif strcmpi(hdr.reco.RECO_wordtype,'_32BIT_FLOAT')
389                precision = ['single=>',Dat.precision];
390        else
391                msg = sprintf('Unknown word type "%s".',hdr.reco.RECO_wordtype);
392                return
393        end
394else
395        % Try to guess the word type from file size if reco file was not found...
396        sz = [hdr.d3proc.IM_SIX,...
397                hdr.d3proc.IM_SIY,...
398                hdr.d3proc.IM_SIZ,...
399                hdr.d3proc.IM_SIT];
400        d=dir(filename);
401        nBytes = d.bytes;
402        bytesPerPixel = nBytes/prod(sz);
403        if bytesPerPixel == 1
404                precision = ['uint8=>',Dat.precision];
405        elseif bytesPerPixel == 2
406                precision = ['int16=>',Dat.precision];
407        else
408                precision = ['int32=>',Dat.precision];
409        end
410end
411
412% Get byteorder
413if isfield(hdr,'reco')
414        if strcmpi(hdr.reco.RECO_byte_order,'littleEndian')
415                byteorder = 'ieee-le';
416        else
417                byteorder = 'ieee-be';
418        end
419else
420        % Use little endian if no information is available
421        byteorder = 'ieee-le';
422end
423
424% Get image type
425if isfield(hdr,'reco')
426        if strcmpi(hdr.reco.RECO_image_type,'COMPLEX_IMAGE')
427                isDataComplex = true;
428        elseif strcmpi(hdr.reco.RECO_image_type,'MAGNITUDE_IMAGE')
429                isDataComplex = false;
430        else
431                msg = sprintf('Unknown image type "%s".',hdr.reco.RECO_image_type);
432                return
433        end
434else
435        % Assume magnitude image if information is not available
436        isDataComplex = false;
437end
438
439% Open 2dseq file for reading
440fid = fopen(filename,'r',byteorder);
441if fid < 0
442        msg = sprintf('Could not open 2dseq file "%s" for reading.');
443        return
444end
445
446% Show waitbar
447if Dat.showWbar
448        wbh = aedes_calc_wait('Reading data from Bruker 2dseq file.');
449end
450
451% Read data
452if ~isDataComplex
453        % - Read magnitude data ---------------------------------
454        [data,count] = fread(fid,inf,precision);
455        fclose(fid);
456       
457        % Reshape and permute to correct size and orientation
458        data = reshape(data,[hdr.d3proc.IM_SIX,...
459                hdr.d3proc.IM_SIY,...
460                hdr.d3proc.IM_SIZ,...
461                hdr.d3proc.IM_SIT]);
462        data = permute(data,[2 1 3 4]);
463       
464        % Map integer data to single or double values
465        if ~strcmpi(hdr.reco.RECO_wordtype,'_32BIT_FLOAT')
466                slope = hdr.reco.RECO_map_slope;
467                offset = hdr.reco.RECO_map_offset;
468                if length(hdr.reco.RECO_size) == 1
469                        nDim = 1;
470                elseif length(hdr.reco.RECO_size) == 2
471                        nDim = 2;
472                elseif length(hdr.reco.RECO_size) == 3
473                        nDim = 3;
474                end
475                for ii=1:length(slope)
476                        if any(nDim == [1 2])
477                                data(:,:,ii) = data(:,:,ii)/slope(ii)+offset(ii);
478                        else
479                                data(:,:,:,ii) = data(:,:,:,ii)/slope(ii)+offset(ii);
480                        end
481                end
482        end
483       
484        % The length of RECO_transposition should be same as NI.
485        NI = length(hdr.reco.RECO_transposition);
486        if NI~=hdr.d3proc.IM_SIZ
487                data = reshape(data,hdr.d3proc.IM_SIY,...
488                        hdr.d3proc.IM_SIX,NI,[]);
489        end
490       
491else
492        % - Read complex data -----------------------------------
493        [data,count] = fread(fid,inf,precision);
494        fclose(fid);
495       
496        % Reshape and permute to correct size and orientation
497        data = reshape(data,[hdr.d3proc.IM_SIX,...
498                hdr.d3proc.IM_SIY,...
499                hdr.d3proc.IM_SIZ,...
500                hdr.d3proc.IM_SIT]);
501        data = permute(data,[2 1 3 4]);
502       
503        % Map integer data to single or double values
504        if ~strcmpi(hdr.reco.RECO_wordtype,'_32BIT_FLOAT')
505                slope = hdr.reco.RECO_map_slope;
506                offset = hdr.reco.RECO_map_offset;
507                if length(hdr.reco.RECO_size) == 2
508                        nDim = 2;
509                elseif length(hdr.reco.RECO_size) == 3
510                        nDim = 3;
511                end
512                for ii=1:length(slope)
513                        if nDim == 2
514                                data(:,:,ii) = data(:,:,ii)/slope(ii)+offset(ii);
515                        else
516                                data(:,:,:,ii) = data(:,:,:,ii)/slope(ii)+offset(ii);
517                        end
518                end
519        end
520       
521        data = reshape(data,hdr.reco.RECO_size(1),...
522                hdr.reco.RECO_size(2),...
523                hdr.reco.RECO_size(3),[]);
524       
525        kspace = complex(data(:,:,:,1),data(:,:,:,2));
526        data = [];
527end
528
529% Close waitbar
530if Dat.showWbar
531        close(wbh);
532end
533
534%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535% Reconstruct k-space
536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537function [kspace,pe1_table,msg] = l_ReconstructKspace(kspace,hdr,Dat)
538
539msg = '';
540
541% Don't try to reconstruct 1D data
542nDims = hdr.acqp.ACQ_dim;
543if nDims == 1
544        pe1_table = l_GetPeTable(hdr);
545        return
546end
547NI = hdr.acqp.NI; % Number of objects
548NSLICES = hdr.acqp.NSLICES; % Number of slices
549NR = hdr.acqp.NR; % Number of repetitions
550phase_factor = hdr.acqp.ACQ_phase_factor; % scans belonging to a single image
551im_size = hdr.acqp.ACQ_size;im_size(1)=im_size(1)/2;
552order = hdr.acqp.ACQ_obj_order;
553
554% Get phase table
555usePeTable = true;
556pe1_table = l_GetPeTable(hdr);
557if isempty(pe1_table)
558        usePeTable = false;
559end
560
561% Reshape data so that all echoes are in correct planes
562kspace = reshape(kspace,im_size(1),...
563        phase_factor,NI,im_size(2)/phase_factor,NR);
564kspace = permute(kspace,[1 2 4 3 5]);
565kspace = reshape(kspace,im_size(1),im_size(2),NI,NR);
566
567% Handle EPI data
568if strncmpi(hdr.acqp.PULPROG,'EPI',3)
569        epi_matrix_size = hdr.method.PVM_Matrix;
570        kspace = reshape(kspace,epi_matrix_size(1),epi_matrix_size(2),NSLICES,NR);
571end
572
573% Sort echoes
574if usePeTable
575        kspace = kspace(:,pe1_table,:,:);
576end
577
578% Sort object order
579kspace(:,:,order+1,:) = kspace;
580
581% Permute to correct orientation
582kspace = flipdim(flipdim(kspace,1),2);
583
584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585% Check that the required reconstruction parameters are found in acqp
586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587function [ok,msg] = l_CheckAcqpParams(hdr)
588
589ok = false;
590msg = '';
591
592% Minimal list of ACQP parameters for data reconstruction
593minParamList = {...
594        'ACQ_dim',...
595        'ACQ_size',...
596        'NI',...
597        'NR',...
598        'BYTORDA',...
599        'ACQ_word_size',...
600        'ACQ_scan_size',...
601        'ACQ_scan_shift',...
602        'ACQ_phase_factor',...
603        'ACQ_rare_factor',...
604        'ACQ_phase_encoding_mode',...
605        'ACQ_phase_enc_start',...
606        'ACQ_spatial_size_1',...
607        'ACQ_spatial_size_2',...
608        'ACQ_spatial_phase_1',...
609        'ACQ_spatial_phase_2',...
610        'ACQ_obj_order',...
611        'ACQ_mod',...
612        'DSPFVS',...
613        'DSPFIRM',...
614        'DECIM'};
615
616param = fieldnames(hdr.acqp);
617
618
619
620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621% Fourier transform data
622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623function [data,msg] = l_doFFT(kspace,hdr,Dat)
624
625data = [];
626msg = '';
627
628% Check dimensions
629if hdr.acqp.ACQ_dim == 1
630  % 1D-image
631  AcqType = 1;
632elseif hdr.acqp.ACQ_dim == 2
633  % 2D-image
634  AcqType = 2;
635elseif hdr.acqp.ACQ_dim == 3
636  % 3D-image
637  AcqType = 3;
638else
639  AcqType = 4;
640end
641
642% Do Zero filling if requested
643if any(AcqType == [2 3])
644        switch Dat.zerofill
645                case 'auto'
646                       
647                case 'on'
648                       
649                case 'off'
650                       
651                otherwise
652                        warning('Unknown zerofill option "%s". Skipping zerofilling...',...
653                                Dat.zerofill);
654        end
655end
656
657if AcqType==1
658        %data = flipdim(abs(fftshift(fft(kspace,[],1),1)),1);
659        data = abs(fftshift(fft(flipdim(kspace,1),[],1),1));
660  %data = circshift(flipdim(abs(fftshift(fft(kspace,[],1),1)),1),[1 0 0]);
661elseif AcqType==2
662  data = abs(fftshift(fftshift(fft(fft(kspace,[],1),[],2),1),2));
663elseif AcqType==3
664  data = abs(fftshift(fftshift(fftshift(fft(fft(fft(kspace,[],1),[],2),[],3),1),2),3));
665end
666
667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668% Calculate phase table indexes
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670function pt = l_GetPeTable(hdr)
671
672if ~isfield(hdr,'acqp') || ~isfield(hdr,'method')
673        error('Cannot determine phase table, because ACQP and/or METHODS fields are missing.')
674end
675
676if isfield(hdr.acqp,'ACQ_spatial_phase_1')
677        [s,pt] = sort(hdr.acqp.ACQ_spatial_phase_1);
678elseif isfield(hdr.method,'PVM_EncSteps1')
679        pt = hdr.method.PVM_EncSteps1+(-min(hdr.method.PVM_EncSteps1(:))+1);
680else
681        pt = [];
682end
683
684
685
686
687
688
689
690
691
692
693
Note: See TracBrowser for help on using the repository browser.

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