【ECG信号的储存及读取方式详解】数据集MIT-BIH,212格式存储

MIT-BIH公开数据集下载地址如下:

MIT-BIH Arrhythmia Database v1.0.0 (physionet.org)https://www.physionet.org/content/mitdb/1.0.0/可以知道,心电数据的储存通常通过三个类型的文件,详解参考:

(138条消息) MIT-BIH数据的读取,以及各文件的作用_LLLijiahao的博客-CSDN博客icon-default.png?t=M1L8https://blog.csdn.net/qq_40695191/article/details/110846845

matlab代码如下:

国外大神原创(具体叫啥得回来找找- -),可以读取三个类型文件

clc; clear all;
%------ SPECIFY DATA ------------------------------------------------------
%%选择文件名称
stringname='111';
%选择你要处理的信号点数
points=10000; 
PATH= 'F:\ECG\MIT-BIH database directory'; % path, where data are saved
HEADERFILE= strcat(stringname,'.hea');      % header-file in text format
ATRFILE= strcat(stringname,'.atr');        % attributes-file in binary format
DATAFILE=strcat(stringname,'.dat');        % data-file
SAMPLES2READ=points;         % number of samples to be read
                      % in case of more than one signal:
                            % 2*SAMPLES2READ samples are read
   
%------ LOAD HEADER DATA --------------------------------------------------
fprintf(1,'\\n$> WORKING ON %s ...\n', HEADERFILE);
signalh= fullfile(PATH, HEADERFILE);
fid1=fopen(signalh,'r');
z= fgetl(fid1);
A= sscanf(z, '%*s %d %d %d',[1,3]);
nosig= A(1);  % number of signals
sfreq=A(2);   % sample rate of data
clear A;
for k=1:nosig
    z= fgetl(fid1);
    A= sscanf(z, '%*s %d %d %d %d %d',[1,5]);
    dformat(k)= A(1);           % format; here only 212 is allowed
    gain(k)= A(2);              % number of integers per mV
    bitres(k)= A(3);            % bitresolution
    zerovalue(k)= A(4);         % integer value of ECG zero point
    firstvalue(k)= A(5);        % first integer value of signal (to test for errors)
end;
fclose(fid1);
clear A;
 
%------ LOAD BINARY DATA --------------------------------------------------
if dformat~= [212,212], error('this script does not apply binary formats different to 212.'); end;
signald= fullfile(PATH, DATAFILE);            % data in format 212
fid2=fopen(signald,'r');
A= fread(fid2, [3, SAMPLES2READ], 'uint8')';  % matrix with 3 rows, each 8 bits long, = 2*12bit
fclose(fid2);
M2H= bitshift(A(:,2), -4);
M1H= bitand(A(:,2), 15);
PRL=bitshift(bitand(A(:,2),8),9);     % sign-bit
PRR=bitshift(bitand(A(:,2),128),5);   % sign-bit
M( : , 1)= bitshift(M1H,8)+ A(:,1)-PRL;
M( : , 2)= bitshift(M2H,8)+ A(:,3)-PRR;
if M(1,:) ~= firstvalue, error('inconsistency in the first bit values'); end;
switch nosig
case 2
    M( : , 1)= (M( : , 1)- zerovalue(1))/gain(1);
    M( : , 2)= (M( : , 2)- zerovalue(2))/gain(2);
    TIME=(0:(SAMPLES2READ-1))/sfreq;
case 1
    M( : , 1)= (M( : , 1)- zerovalue(1));
    M( : , 2)= (M( : , 2)- zerovalue(1));
    M=M';
    M(1)=[];
    sM=size(M);
    sM=sM(2)+1;
    M(sM)=0;
    M=M';
    M=M/gain(1);
    TIME=(0:2*(SAMPLES2READ)-1)/sfreq;
otherwise  % this case did not appear up to now!
    % here M has to be sorted!!!
    disp('Sorting algorithm for more than 2 signals not programmed yet!');
end;
clear A M1H M2H PRR PRL;
fprintf(1,'\\n$> LOADING DATA FINISHED \n');
 
%------ LOAD ATTRIBUTES DATA ----------------------------------------------
atrd= fullfile(PATH, ATRFILE);      % attribute file with annotation data
fid3=fopen(atrd,'r');
A= fread(fid3, [2, inf], 'uint8')';
fclose(fid3);
ATRTIME=[];
ANNOT=[];
sa=size(A);
saa=sa(1);
i=1;
while i<=saa
    annoth=bitshift(A(i,2),-2);
    if annoth==59
        ANNOT=[ANNOT;bitshift(A(i+3,2),-2)];
        ATRTIME=[ATRTIME;A(i+2,1)+bitshift(A(i+2,2),8)+...
                bitshift(A(i+1,1),16)+bitshift(A(i+1,2),24)];
        i=i+3;
    elseif annoth==60
        % nothing to do!
    elseif annoth==61
        % nothing to do!
    elseif annoth==62
        % nothing to do!
    elseif annoth==63
        hilfe=bitshift(bitand(A(i,2),3),8)+A(i,1);
        hilfe=hilfe+mod(hilfe,2);
        i=i+hilfe/2;
    else
        ATRTIME=[ATRTIME;bitshift(bitand(A(i,2),3),8)+A(i,1)];
        ANNOT=[ANNOT;bitshift(A(i,2),-2)];
   end;
   i=i+1;
end;
ANNOT(length(ANNOT))=[];       % last line = EOF (=0)
ATRTIME(length(ATRTIME))=[];   % last line = EOF
clear A;
ATRTIME= (cumsum(ATRTIME))/sfreq;
ind= find(ATRTIME <= TIME(end));
ATRTIMED= ATRTIME(ind);
ANNOT=round(ANNOT);
ANNOTD= ANNOT(ind);
 
%------ DISPLAY DATA ------------------------------------------------------
figure(1); clf, box on, hold on ;grid on ;
plot(TIME, M(:,1),'r');
if nosig==2
    plot(TIME, M(:,2),'b');
end;
for k=1:length(ATRTIMED)
    text(ATRTIMED(k),0,num2str(ANNOTD(k)));
end;
xlim([TIME(1), TIME(end)]);
xlabel('Time / s'); ylabel('Voltage / mV');
string=['ECG signal ',DATAFILE];
title(string);
fprintf(1,'\\n$> DISPLAYING DATA FINISHED \n');
% -------------------------------------------------------------------------
fprintf(1,'\\n$> ALL FINISHED \n');

python代码如下:

##################################################

import numpy as np
import matplotlib.pyplot as plt

PATH="./MIT-BIH/"     #path, 这里就是写刚才你保存的数据地址  
HEADERFILE="105.hea"     #文件格式为文本格式 
ATRFILE="105.atr"     #attributes-file 文件以二进制格式 
DATAFILE="105.dat"     #data-file  
SAMPLES2READ=3000     #读取的数据样本点数
####################读取头文件######################
f=open(PATH+HEADERFILE,"r")
z=f.readline().split()
nosig,sfreq=int(z[1]),int(z[2])     #% number of signals,sample rate of data

dformat,gain,bitres,zerovalue,firstvalue=[],[],[],[],[]
for i in range(nosig):
    z=f.readline().split()
    dformat.append(int(z[1]))     #format; here only 212 is allowed
    gain.append(int(z[2]))     #number of integers per mV
    bitres.append(int(z[3]))     #bitresolution
    zerovalue.append(int(z[4]))     #integer value of ECG zero point
    firstvalue.append(int(z[5]))     #first integer value of signal (to test for errors)
f.close()
####################读取dat文件######################
f=open(PATH+DATAFILE,"rb")     #以二进制格式读入dat文件
b=f.read()   
f.close()

A_init=np.frombuffer(b,dtype=np.uint8)      #将读入的二进制文件转化为unit8格式
A_shape0=int(A_init.shape[0]/3)     
A=A_init.reshape(A_shape0,3)[:SAMPLES2READ]     #将A转为3列矩阵

M=np.zeros((SAMPLES2READ,2))     #创建矩阵M

M2H=A[:,1]>>4     #字节向右移四位,即取字节的高四位
M1H=A[:,1]&15     #取字节的低四位

PRL=(A[:,1]&8)*(2**9)     #sign-bit   取出字节低四位中最高位,向左移九位,等于乘2^9
PRR=A[:,1]&128<<5     #sign-bit   取出字节高四位中最高位,向左移五位

M1H=M1H*(2**8)
M2H=M2H*(2**8)

M[:,0]=A[:,0]+M1H-PRL
M[:,1]=A[:,2]+M2H-PRR

if ((M[1,:]!=firstvalue).any()):
    print("inconsistency in the first bit values")

if nosig==2:
    M[:, 0] = (M[:, 0] - zerovalue[0]) / gain[0]
    M[:, 1] = (M[:, 1] - zerovalue[1]) / gain[1]
    TIME=np.linspace(0,SAMPLES2READ-1,SAMPLES2READ)/sfreq
elif nosig==1:
    M2=[]
    M[:, 0] = M[:, 0] - zerovalue[0]
    M[:, 1] = M[:, 1] - zerovalue[1]
    for i in range(M.shape[0]):
        M2.append(M[:,0][i])
        M2.append(M[:,1][i])
    M2.append(0)
    del M2[0]
    M2=np.array(M2)/gain[0]
    TIME=np.linspace(0,2*SAMPLES2READ-1,2*SAMPLES2READ)/sfreq
else:
    print("Sorting algorithm for more than 2 signals not programmed yet!")
####################读取atr文件######################
f=open(PATH+ATRFILE,"rb")     #主要是读取ATR文件中各周期数据并在之后打印在图中
b=f.read()
f.close()

A_init=np.frombuffer(b,dtype=np.uint8)
A_shape0=int(A_init.shape[0]/2)
A=A_init.reshape(A_shape0,2)

ANNOT,ATRTIME=[],[]
i=0
while i < A.shape[0]:
    annoth=A[i,1]>>2
    if annoth==59:
        ANNOT.append(A[i+3,1]>>2)
        ATRTIME.append(A[i+2,0]+A[i+2,1]*(2**8)+A[i+1,0]*(2**16)+A[i+1,1]*(2**24))
        i+=3
    elif annoth==60:pass
    elif annoth==61:pass
    elif annoth==62:pass
    elif annoth==63:
        hilfe=(A[i,1]&3)*(2**8)+A[i,0]
        hilfe=hilfe+hilfe%2
        i+=int(hilfe/2)
    else:
        ATRTIME.append((A[i,1]&3)*(2**8)+A[i,0])
        ANNOT.append(A[i,1]>>2)
    i+=1

del ANNOT[len(ANNOT)-1]
del ATRTIME[len(ATRTIME)-1]

ATRTIME=np.array(ATRTIME)
ATRTIME=np.cumsum(ATRTIME)/sfreq

ind=np.where(ATRTIME<=TIME[-1])[0]
ATRTIMED=ATRTIME[ind]

ANNOT=np.round(ANNOT)
ANNOTD=ANNOT[ind]
#####################显示ECG####################
plt.plot(TIME,M[:,0],linewidth="0.5",c="r")
if nosig==2:
    plt.plot(TIME, M[:, 1], linewidth="0.5", c="b")
for i in range(len(ATRTIMED)):
    plt.text(ATRTIMED[i],0,str(ANNOTD[i]))
plt.xlim(TIME[0],TIME[-1])
plt.xlabel("Time / s")
plt.ylabel("Votage / mV")
plt.title("ECG signal ")
plt.show()

python补充解释版参考:

(138条消息) MIT-BIH介绍(三)如何使用MIT-BIH?_Cou流氓也要有文化的博客-CSDN博客_mitbih采样频率icon-default.png?t=M1L8https://blog.csdn.net/sinat_34337520/article/details/111869530?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-4.pc_relevant_default&spm=1001.2101.3001.4242.3&utm_relevant_index=7 

然鹅,python有一个wfdb的包,可以专门用来读取心电信号233

好的没关系,我们弄懂一些ECG的原理也是好的。

下面开始介绍这个wfdb的包及用法,参考,继续整理:

(138条消息) Python中的WFDB库使用_卷福1995的博客-CSDN博客_python wfdbicon-default.png?t=M1L8https://blog.csdn.net/weixin_44191286/article/details/86305591

感谢参考:

(37 封私信 / 80 条消息) 如何利用python语言对MIT-BIH数据库里的dat、hea、atr数据进行读取画图? - 知乎 (zhihu.com)https://www.zhihu.com/question/273874101

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值