a b/DS_test.m
1
%% 参考rddata.m,用于QRS波一次性全数据库评估;
2
%-------------------------------------------------------------------------
3
clc; clear all;tic,
4
Name_whole=[100,101,102,103,104,105,106,107,108,109,111,112,113,114,115,...
5
    116,117,118,119,121,122,123,124,200,201,202,203,205,207,208,209,...
6
    210,212,213,214,215,217,219,220,221,222,223,228,230,231,232,233,234];
7
INFO=[];fs=360;
8
for na=1:48
9
    
10
%------ SPECIFY DATA ------------------------------------------------------
11
%------ 指定数据文件 -------------------------------------------------------
12
13
Name=num2str(Name_whole(na));
14
PATH= 'F:\MATLAB\MIT-BIH'; % 指定数据的储存路径  
15
HEADERFILE=strcat(Name, '.hea');% .hea 格式,头文件,可用记事本打开        
16
ATRFILE=strcat(Name, '.atr'); % .atr 格式,属性文件,数据格式为二进制数    
17
DATAFILE=strcat(Name, '.dat');% .dat ¸ñʽ£¬ECG Êý¾Ý
18
SAMPLES2READ=650000;          % 指定需要读入的样本数
19
                            % 若.dat文件中存储有两个通道的信号:
20
                            % 则读入 2*SAMPLES2READ 个数据 
21
22
%------ LOAD HEADER DATA --------------------------------------------------
23
%------ 读入头文件数据 -----------------------------------------------------
24
%
25
% 示例:用记事本打开的117.hea 文件的数据
26
%
27
%      117 2 360 650000
28
%      117.dat 212 200 11 1024 839 31170 0 MLII
29
%      117.dat 212 200 11 1024 930 28083 0 V2
30
%      # 69 M 950 654 x2
31
%      # None
32
%
33
%-------------------------------------------------------------------------
34
fprintf(1,'\\n$> WORKING ON %s ...\n', HEADERFILE); % 在Matlab命令行窗口提示当前工作状态
35
% 
36
% 【注】函数 fprintf 的功能将格式化的数据写入到指定文件中。
37
% ±í´ïʽ£ºcount = fprintf(fid,format,A,...)
38
% 在字符串'format'的控制下,将矩阵A的实数数据进行格式化,并写入到文件对象fid中。该函数返回所写入数据的字节数 count。
39
% fid 是通过函数 fopen 获得的整型文件标识符。fid=1,表示标准输出(即输出到屏幕显示);fid=2,表示标准偏差。
40
%
41
signalh= fullfile(PATH, HEADERFILE);    % 通过函数 fullfile 获得头文件的完整路径
42
fid1=fopen(signalh,'r');    % 打开头文件,其标识符为 fid1 ,属性为'r'--“只读”
43
z= fgetl(fid1);             % 读取头文件的第一行数据,字符串格式
44
A= sscanf(z, '%*s %d %d %d',[1,3]); % 按照格式 '%*s %d %d %d' 转换数据并存入矩阵 A 中
45
nosig= A(1);    % 信号通道数目
46
sfreq=A(2);     % 数据采样频率
47
clear A;        % 清空矩阵 A ,准备获取下一行数据
48
for k=1:nosig           % 读取每个通道信号的数据信息
49
    z= fgetl(fid1);
50
    A= sscanf(z, '%*s %d %d %d %d %d',[1,5]);
51
    dformat(k)= A(1);           % 信号格式; 这里只允许为 212 格式
52
    gain(k)= A(2);              % 每 mV 包含的整数个数
53
    bitres(k)= A(3);            % 采样精度(位分辨率)
54
    zerovalue(k)= A(4);         % ECG 信号零点相应的整数值
55
    firstvalue(k)= A(5);        % 信号的第一个整数值 (用于偏差测试)
56
end;
57
fclose(fid1);
58
clear A;
59
60
%------ LOAD BINARY DATA --------------------------------------------------
61
%------ 读取 ECG 信号二值数据 ----------------------------------------------
62
%
63
if dformat~= [212,212], error('this script does not apply binary formats different to 212.'); end;
64
signald= fullfile(PATH, DATAFILE);            % 读入 212 格式的 ECG 信号数据
65
fid2=fopen(signald,'r');
66
A= fread(fid2, [3, SAMPLES2READ], 'uint8')';  % matrix with 3 rows, each 8 bits long, = 2*12bit
67
fclose(fid2);
68
% 通过一系列的移位(bitshift)、位与(bitand)运算,将信号由二值数据转换为十进制数
69
M2H= bitshift(A(:,2), -4);        %字节向右移四位,即取字节的高四位
70
M1H= bitand(A(:,2), 15);          %取字节的低四位
71
PRL=bitshift(bitand(A(:,2),8),9);     % sign-bit   取出字节低四位中最高位,向右移九位
72
PRR=bitshift(bitand(A(:,2),128),5);   % sign-bit   取出字节高四位中最高位,向右移五位
73
M( : , 1)= bitshift(M1H,8)+ A(:,1)-PRL;
74
M( : , 2)= bitshift(M2H,8)+ A(:,3)-PRR;
75
if M(1,:) ~= firstvalue, error('inconsistency in the first bit values'); end;
76
switch nosig
77
case 2
78
    M( : , 1)= (M( : , 1)- zerovalue(1))/gain(1);
79
    M( : , 2)= (M( : , 2)- zerovalue(2))/gain(2);
80
    TIME=(0:(SAMPLES2READ-1))/sfreq;
81
case 1
82
    M( : , 1)= (M( : , 1)- zerovalue(1));
83
    M( : , 2)= (M( : , 2)- zerovalue(1));
84
    M=M';
85
    M(1)=[];
86
    sM=size(M);
87
    sM=sM(2)+1;
88
    M(sM)=0;
89
    M=M';
90
    M=M/gain(1);
91
    TIME=(0:2*(SAMPLES2READ)-1)/sfreq;
92
otherwise  % this case did not appear up to now!
93
    % here M has to be sorted!!!
94
    disp('Sorting algorithm for more than 2 signals not programmed yet!');
95
end;
96
clear A M1H M2H PRR PRL;
97
fprintf(1,'\\n$> LOADING DATA FINISHED \n');
98
99
%------ LOAD ATTRIBUTES DATA ----------------------------------------------
100
atrd= fullfile(PATH, ATRFILE);      % attribute file with annotation data
101
fid3=fopen(atrd,'r');
102
A= fread(fid3, [2, inf], 'uint8')';
103
fclose(fid3);
104
ATRTIME=[];
105
ANNOT=[];
106
sa=size(A);
107
saa=sa(1);
108
i=1;
109
while i<=saa
110
    annoth=bitshift(A(i,2),-2);
111
    if annoth==59
112
        ANNOT=[ANNOT;bitshift(A(i+3,2),-2)];
113
        ATRTIME=[ATRTIME;A(i+2,1)+bitshift(A(i+2,2),8)+...
114
                bitshift(A(i+1,1),16)+bitshift(A(i+1,2),24)];
115
        i=i+3;
116
    elseif annoth==60
117
        % nothing to do!
118
    elseif annoth==61
119
        % nothing to do!
120
    elseif annoth==62
121
        % nothing to do!
122
    elseif annoth==63
123
        hilfe=bitshift(bitand(A(i,2),3),8)+A(i,1);
124
        hilfe=hilfe+mod(hilfe,2);
125
        i=i+hilfe/2;
126
    else
127
        ATRTIME=[ATRTIME;bitshift(bitand(A(i,2),3),8)+A(i,1)];
128
        ANNOT=[ANNOT;bitshift(A(i,2),-2)];
129
   end;
130
   i=i+1;
131
end;
132
ANNOT(length(ANNOT))=[];       % last line = EOF (=0)
133
ATRTIME(length(ATRTIME))=[];   % last line = EOF
134
clear A;
135
ATRTIME= (cumsum(ATRTIME))/sfreq;
136
ind= find(ATRTIME <= TIME(end));
137
ATRTIMED= ATRTIME(ind);
138
ANNOT=round(ANNOT);
139
ANNOTD= ANNOT(ind);
140
141
%------ DISPLAY DATA ------------------------------------------------------
142
%{
143
figure(1); clf, box on, hold on
144
plot(TIME, M(:,1),'r');
145
if nosig==2
146
    plot(TIME, M(:,2),'b');
147
end;
148
for k=1:length(ATRTIMED)
149
    text(ATRTIMED(k),0,num2str(ANNOTD(k)));
150
end;
151
xlim([TIME(1), TIME(end)]);
152
xlabel('Time / s'); ylabel('Voltage / mV');
153
string=['ECG signal ',DATAFILE];
154
title(string);
155
fprintf(1,'\\n$> DISPLAYING DATA FINISHED \n');
156
%}
157
% -------------------------------------------------------------------------
158
fprintf(1,'\\n$> ALL FINISHED \n');
159
160
%% ---------------------------------------------------------------
161
s=M(:,1);
162
ecg_i=s';
163
%%
164
[QRS_amp,QRS_ind] = DS_detect(ecg_i,0); % µ÷ÓÃQRS²¨¼ì²âËã·¨£»
165
%%
166
Nt=size(QRS_ind,2);
167
R_TIME=ATRTIMED(ANNOTD~=14 & ANNOTD~=16 & ANNOTD~=18 & ANNOTD~=19 & ANNOTD~=20 & ANNOTD~=21 & ANNOTD~=22 & ...
168
ANNOTD~=23 & ANNOTD~=24 & ANNOTD~=27  & ANNOTD~=28 & ANNOTD~=29 & ANNOTD~=30 & ...
169
ANNOTD~=32 & ANNOTD~=33 & ANNOTD~=37 & ANNOTD~=39 & ANNOTD~=40);
170
REF_ind=round(R_TIME'.*fs);
171
Nr=size(REF_ind,2);
172
if Nt>Nr
173
    typ=0;
174
else
175
    typ=1;
176
end
177
TP=0;FP=0;FN=0;
178
if typ==0
179
    QRS_ind_buf=[];
180
    for n=1:Nr
181
        ref=REF_ind(n);
182
        for m=1:Nt
183
            if abs(ref-QRS_ind(m))<=0.15*fs
184
               QRS_ind_buf=[QRS_ind_buf QRS_ind(m)];
185
               TP=TP+1;
186
               break; 
187
            end 
188
        end
189
        if m==Nt&&abs(ref-QRS_ind(Nt))>0.15*fs
190
            FN=FN+1;
191
        end
192
    end
193
    FP=Nt-size(QRS_ind_buf,2);
194
else
195
    REF_ind_buf=[];
196
    for n=1:Nt
197
        qrs=QRS_ind(n);
198
        for m=1:Nr
199
            if abs(qrs-REF_ind(m))<=0.15*fs
200
                REF_ind_buf=[REF_ind_buf REF_ind(m)];
201
                TP=TP+1;
202
                break;
203
            end
204
        end
205
        if m==Nr&&abs(qrs-REF_ind(Nr))>0.15*fs
206
            FP=FP+1;
207
        end
208
    end
209
    FN=Nr-size(REF_ind_buf,2);
210
end
211
Se=TP/(TP+FN);Pp=TP/(TP+FP);
212
info=[Name_whole(na),Nr,TP,FP,FN,Se,Pp];
213
INFO=[INFO;info];
214
end
215
final=[0,sum(INFO(:,2)),sum(INFO(:,3)),sum(INFO(:,4)),sum(INFO(:,5)),...
216
    0,0];
217
final(6)=final(3)/(final(3)+final(5));
218
final(7)=final(3)/(final(3)+final(4));
219
INFO=[INFO;final];
220
toc