最近学习关于ECG信号处理,在使用rdmat函数时遇到的一点小问题,记录下来;
rdmat函数源代码链接:
archive.physionet.org/physiotools/matlab/wfdb-app-matlab/html/rdmat.m
代码原文:
function varargout=rdmat(varargin)
%
% [tm,signal,Fs,siginfo]=rdmat(recordName)
%
% Import a signal in physical units from a *.mat file generated by WFDB2MAT.
% Required Parameters:
%
% recorName
% String specifying the name of the *.mat file.
%
% Outputs are:
%
% tm
% A Nx1 array of doubles specifying the time in seconds.
% signal
% A NxM matrix of doubles contain the signals in physical units.
% Fs
% A 1x1 integer specifying the sampling frequency in Hz for the entire record.
%siginfo
% A LxN cell array specifying the signal siginfo. Currently it is a
% structure with the following fields:
%
% siginfo.Units
% siginfo.Baseline
% siginfo.Gain
% siginfo.Description
%
% NOTE:
% You can use the WFDB2MAT command in order to convert the record data into a *.mat file,
% which can then be loaded into MATLAB/Octave's workspace using the LOAD command.
% This sequence of procedures is quicker (by several orders of magnitude) than calling RDSAMP.
% The LOAD command will load the signal data in raw units, use RDMAT to load the signal in physical units.
%
% KNOWN LIMITATIONS:
% This function currently does support several of the features described
% in the WFDB record format (such as multiresolution signals) :
% http://www.physionet.org/physiotools/wag/header-5.htm
% If you are not sure that the record (or database format) you are reading is
% supported, you can do an integrity check by comparing the output with RDSAMP:
%
% [tm,signal,Fs,siginfo]=rdmat('200m');
% [tm2,signal2]=rdsamp('200m');
% if(sum(abs(signal-signal2)) !=0);
% error('Record not compatible with RDMAT');
% end
%
%
% Written by Ikaro Silva, 2014
% Last Modified: November 26, 2014
% Version 1.2
%
% Since 0.9.7
%
% %Example:
% wfdb2mat('mitdb/200')
%tic;[tm,signal,Fs,siginfo]=rdmat('200m');toc
%tic;[signal2]=rdsamp('200m');toc
% sum(abs(signal-signal2))
%
%
% See also RDSAMP, WFDB2MAT
%endOfHelp
%Set default pararameter values
inputs={'recordName'};
defGain=200; %Default value for missing gains
for n=1:nargin
if(~isempty(varargin{n}))
eval([inputs{n} '=varargin{n};'])
end
end
outputs={'tm','val','Fs','siginfo'};
fid = fopen([recordName, '.hea'], 'rt');
if(fid==-1)
error(['Could not open file: ' recordName '.hea !'])
end
%Following the documentation described in :
%http://www.physionet.org/physiotools/wag/header-5.htm
%to parse the header file
%Skip any comment lines
str=fgetl(fid);
while(strcmp(str(1),'#'))
str=fgetl(fid);
end
%Process Record Line Info
info=textscan(str,'%s %d %f %d %s %s');
M=info{2}; %Number of signals present
Fs=info{3};
%Process Signal Specification lines. Assumes no comments between lines.
siginfo(M)=struct();
for m = 1:M
str=fgetl(fid);
info=textscan(str,'%s %s %s %d %d %f %d %d %s');
fmt=info{2}{:};
gain=info{3}{:};
%Get Signal Units if present
ind=strfind(gain,'/');
if(~isempty(ind))
siginfo(m).Units=gain(ind+1:end);
gain=gain(1:ind-1);
end
%Get Signal Baseline if present
ind=strfind(gain,'(');
if(~isempty(ind))
ind2=strfind(gain,')');
siginfo(m).Baseline=str2num(gain(ind+1:ind2-1));
gain=gain(1:ind-1);
else
%If Baseline is missing, set it equal to ADC Zero
adc_zero=info{5};
if(~isempty(adc_zero))
siginfo(m).Baseline=double(adc_zero);
else
error('Could not obtain signal baseline');
end
end
%Get Signal Gain
gain=str2num(gain);
if(gain==0)
%Set gain to default value in this case
gain=defGain;
end
siginfo(m).Gain=double(gain);
%Get Signal Descriptor
siginfo(m).Description=info{9}{:};
% Store format for later
siginfo(m).fmt=fmt(1:strfind(fmt,'+')-1);
end
fclose(fid);
load([recordName '.mat']);
for m = 1:M
% Interpreting digital values of byte offset format 80
if strcmp(siginfo(m).fmt, '80')
val(m,:)=val(m,:)-128;
wfdbNaN=-128;
elseif strcmp(siginfo(m).fmt, '16')
wfdbNaN=-32768;
else
wfdbNaN=-2147483648;
end
% Fill in NaNs before subtracting and dividing.
val(m, val(m,:)==wfdbNaN)=nan;
%Convert from digital units to physical units.
% Mapping should be similar to that of rdsamp.c:
% http://www.physionet.org/physiotools/wfdb/app/rdsamp.c
val(m, :) = (val(m, :) - siginfo(m).Baseline ) / siginfo(m).Gain;
end
%Reshape to the Toolbox's standard format
val=val';
%Generate time vector
N=size(val,1);
tm =linspace(0,(N-1)/Fs,N);
for n=1:nargout
eval(['varargout{n}=' outputs{n} ';'])
end
end
在matlab中创建一个.m文件,将代码复制保存(文件名要和函数名一致rdmat.m);
之后在同目录下创建主程序代码;参考基于MATLAB实现ECG心电信号处理_利用matlab生成心电信号_Coppa的博客-CSDN博客
调用rdmat:
%rdmat函数中给出的调用格式
[tm,signal,Fs,siginfo]=rdmat(recordName)
%上文链接中调用的格式
[TIME,M,Fs,siginfo]=rdmat('数据文件名称,要mat文件类型') %引号要保留
此外,在MIT网站中,我发现官方提供了直接读取MIT数据的工具包
链接:
WFDB Toolbox for MATLAB and Octave (physionet.org)
根据官方提示,可以直接在Matlab中安装;
关键部分翻译:
需要复制的命令:
%在MATLAB的命令窗口键入以下命令:
[old_path]=which('rdsamp'); if(~isempty(old_path)) rmpath(old_path(1:end-8)); end
wfdb_url='https://physionet.org/physiotools/matlab/wfdb-app-matlab/wfdb-app-toolbox-0-10-0.zip';
[filestr,status] = urlwrite(wfdb_url,'wfdb-app-toolbox-0-10-0.zip');
unzip('wfdb-app-toolbox-0-10-0.zip');
cd mcode
addpath(pwd)
savepath
自动在当前目录安装并解压压缩包
测试部分:
%都是直接在命令窗口直接输入指令
%要演示工具箱,请运行
wfdbdemo
%要从 PhysioBank 的数据收集之一中读取和绘制心电图信号, 请尝试以下命令:
[sig, Fs, tm] = rdsamp('mitdb/100', 1);
plot(tm, sig);
以上是我在学习rdmat的一些步骤,很浅;希望能给大家提供微弱的帮助。