📄 readpar.m
字号:
function par = readpar(filename)
% readpar - read a Philips PAR file
%
% FORMAT: par = readpar(filename)
%
% Input fields:
%
% filename PAR filename
%
% Output fields:
%
% par 1x1 struct with PAR contents
%
% See also transio
% Version: v0.6c
% Build: 7012311
% Date: Jan-23 2007, 11:05 AM CET
% Author: Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools
% enough arguments ?
if nargin < 1 || ...
~ischar(filename) || ...
isempty(filename) || ...
exist(filename(:)', 'file') ~= 2
error( ...
'BVQXtools:BadArguments',...
'Bad argument or file not found.' ...
);
end
filename = filename(:)';
% try read
try
parcont = asciiread(filename);
catch
error( ...
'BVQXtools:FileNotReadable', ...
'File not readable: ''%s''.', ...
filename ...
);
end
% preliminary parse content
parlines = splittocell(parcont, char([10, 13]), 1, 1);
if length(parlines) < 30
error( ...
'BVQXtools:BadFileContent', ...
'Too few lines in file.' ...
);
end
slline = grep(parlines, '-ixl', 'sl\s+ec\s+dyn');
if numel(slline) ~= 1 || ...
slline < 30
error( ...
'BVQXtools:BadFileContent', ...
'Line with ''#sl ec dyn ...'' tokens not found or too early.' ...
);
end
% prepare output
par = struct;
par.PARFile = filename;
% remove comment lines from first part
parset = parsesetlines(grep(parlines(1:slline - 1), '-vx', '^\#'), '^\.\s+');
par.Parameters = parset;
parnames = fieldnames(parset);
% find settings in par set
noslices = findfield(parnames, {'slice', 'number'});
nodynamics = findfield(parnames, {'dynamic', 'number'});
noechoes = findfield(parnames, {'echo', 'number'});
% check settings
if isempty(noslices) || ...
isempty(nodynamics)
error( ...
'BVQXtools:BadFileContent', ...
'Either number of slices or number of dynamics not found.' ...
);
end
noslices = parset.(noslices);
nodynamics = parset.(nodynamics);
if ~isempty(noechoes)
noechoes = parset.(noechoes);
else
noechoes = 1;
end
nodynsliech = prod([nodynamics, noslices, noechoes]);
% image definition
imglines = grep(parlines, '-ix', '^#\s+.*(float|integer|string)\)\s*$');
imgset = parsesetlines(imglines, '^#\s+');
par.ImageParameters = imgset;
imgnames = fieldnames(imgset);
imgnum = length(imgnames);
% build correct representation
imghead = {};
for cc = imgnum:-1:1
limgname = lower(imgnames{cc});
limgset = lower(imgset.(imgnames{cc}));
[li_t{1:3}] = regexp(limgset, '^\((\d+)\*[a-z]+\)$');
li_t = li_t{3};
if ~isempty(li_t) && ...
numel(li_t{1}) == 2
try
addnumber = str2double(limgset(li_t{1}(1):li_t{1}(2)));
imgnum = imgnum + addnumber - 1;
for ac = addnumber:-1:2
imghead = [{sprintf('%s_%d', limgname, ac)}; imghead(:)];
end
catch
% nothing
end
imghead = [{[limgname '_1']}; imghead(:)];
else
imghead = [{limgname}; imghead(:)];
end
end
imgnames = imghead;
imgnum = length(imgnames);
% find settings in img set
sliceno = findfield(imgnames, {'slice', 'number'});
dynamicno = findfield(imgnames, {'dynamic', 'number'});
pixres = findfield(imgnames, {'pixel', 'size'});
imgres = findfield(imgnames, {'resolution'});
imgidx = findfield(imgnames, {'index', 'rec'});
% check settings
if isempty(sliceno) || ...
isempty(dynamicno) || ...
isempty(pixres) || ...
isempty(imgres)
error( ...
'BVQXtools:BadFileContent', ...
'Required image header fields not found.' ...
);
end
sliceno = find(strcmp(imgnames, sliceno));
dynamicno = find(strcmp(imgnames, dynamicno));
pixres = find(strcmp(imgnames, pixres));
imgres = find(strcmp(imgnames, imgres));
% try conversion
vallines = grep(grep(parlines(slline + 1:end), '-vx', '^#'), '-vx', '^$');
valmatrix = zeros(length(vallines), imgnum);
eval(['valmatrix(:,:)=[' gluetostring(vallines, ';') '];'], 'valmatrix=[];');
if size(valmatrix, 1) ~= length(vallines)
error( ...
'BVQXtools:BadFileContent', ...
'Error converting value lines in PAR file.' ...
);
end
if size(valmatrix, 2) ~= imgnum
error( ...
'BVQXtools:BadFileContent', ...
'Value matrix header line inconsistent.' ...
);
end
par.MatrixHeaders = imghead;
par.MatrixValues = valmatrix;
% try to locate REC file
[fpath, fname] = fileparts(filename);
if numel(fpath) > 0 && ...
fpath(end) ~= filesep
fpath = [fpath filesep];
end
fpath = [fpath fname];
if exist([fpath '.REC'], 'file') == 2
rfile = [fpath '.REC'];
elseif exist([fpath '.rec'], 'file') == 2
rfile = [fpath '.rec'];
else
return;
end
par.RECFile = rfile;
% check pix/img res
if any(diff(valmatrix(:, pixres(1)))) || ...
any(diff(valmatrix(:, imgres(1)))) || ...
any(diff(valmatrix(:, imgres(1) + 1)))
warning( ...
'BVQXtools:FileContNoSupported', ...
'Unequal image resolutions over time!' ...
);
return;
end
% try to guess indexing order
useidx = false;
if ~isempty(imgidx)
imgidx = find(strcmp(imgnames, imgidx));
if ~isempty(imgidx)
[uimgidx, iuimgidx] = unique(valmatrix(:, imgidx(1)));
if length(uimgidx) == size(valmatrix, 1)
useidx = true;
end
end
end
par.UseIndex = useidx;
% check remaining line number
if size(valmatrix, 1) == (noslices * nodynamics * noechoes)
% get dynslc array
if useidx
dynslc = valmatrix(iuimgidx(:)', [dynamicno(1), sliceno(1)]);
par.RECDataType = 'Dyn.Slice';
else
dynslc = valmatrix(:, [dynamicno(1), sliceno(1)]);
par.RECDataType = 'Slice';
end
else
if useidx
dynslc = iuimgidx(:) - 1;
par.RECDataType = 'Slice';
else
dynslc = size(valmatrix, 1);
par.RECDataType = 'Chunk';
end
end
% calculate image size and class
pixres = valmatrix(1, pixres(1));
switch (pixres)
case {8}, dcls = 'uint8';
case {16}, dcls = 'int16';
case {32}, dcls = 'single';
case {64}, dcls = 'double';
otherwise
warning( ...
'BVQXtools:FileContNoSupported', ...
'Pixel bitsize of %d not supported.', ...
valmatrix(1, pixres(1)) ...
);
end
pixres = pixres / 8;
imgdims = valmatrix(1, imgres(1):imgres(1)+1);
imgsize = prod(imgdims) * pixres;
par.BytePerPixel = pixres;
par.SliceResolution = imgdims;
% try to create object
try
if useidx
if size(dynslc, 2) > 1
transio(rfile, 'ieee-le', 'uint8', 0, [nodynsliech, imgsize]);
for ic = 1:size(dynslc, 1)
par.RECData.Dyn(dynslc(ic, 1)).Slice(dynslc(ic, 2)).IO = ...
transio(rfile, 'ieee-le', dcls, (ic - 1) * imgsize, imgdims);
end
else
for ic = 1:length(dynslc)
par.RECData.Slice(ic).IO = ...
transio(rfile, 'ieee-le', dcls, dynslc(ic) * imgsize, imgdims);
end
end
else
if length(dynslc) > 1
for ic = 1:length(dynslc)
par.RECData.Slice(ic).IO = ...
transio(rfile, 'ieee-le', dcls, (ic - 1) * imgsize, imgdims);
end
else
par.RECData.Chunk.IO = ...
transio(rfile, 'ieee-le', dcls, 0, [dynslc, imgdims]);
end
end
catch
if isfield(par, 'RECData')
par = rmfield(par, 'RECData');
end
end
% %%% subfunctions
function setstr = parsesetlines(setlines, lineprefix)
setstr = struct;
for lc = 1:length(setlines)
setline = setlines{lc};
if ~isempty(setline) && ...
~isempty(regexpi(setline, lineprefix))
setline = mstrrep(setline, {lineprefix, '\s+'}, {'', ' '}, 1);
colonpos = find(setline == ':');
if numel(colonpos) == 1 && ...
colonpos > 1
labline = makelabel(deblank(regexprep(setline(1:colonpos - 1), ...
'[^a-zA-Z\s\.].*$', '')));
valline = mstrrep(setline(colonpos + 1:end), ...
{'^\s+', '\s+$'}, {'', ''}, 1);
else
setlinec = splittocell(setline, char([9, 32]), 1, 1);
if length(setlinec) < 2
continue;
end
labline = makelabel(deblank(regexprep(gluetostring( ...
setlinec(1:end-1), ' '), '[^a-zA-Z_\s\.].*$', '')));
valline = setlinec{end};
end
if length(labline) < 2 || ...
(any('vV' == labline(1)) && labline(2) == '_')
continue;
end
vallineok = regexp(valline, '^[0-9\+\-e\.\s]+$');
if ~isempty(vallineok) && ...
(isa(vallineok, 'double') || ...
(iscell(vallineok) && ~isempty(vallineok{1})))
try
valline = eval(['[' valline ']']);
catch
valline = 0;
end
end
setstr.(labline) = valline;
end
end
% end of function setstr = parsesetlines(setlines)
function fname = findfield(fnames, parts)
lfnames = lower(fnames);
if ~iscell(parts)
parts = {parts};
end
parts = lower(parts);
pnum = length(parts);
for fc = 1:length(fnames)
fmatch = true;
for pc = 1:pnum
if isempty(strfind(lfnames{fc}, parts{pc}))
fmatch = false;
break;
end
end
if fmatch
fname = fnames{fc};
return;
end
end
fname = '';
% end of function fname = findfield(fnames, parts)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -