官方下载地址
https://www.physionet.org/content/mitdb/1.0.0/
由头文件[.hea],数据文件[.dat],注释文件[.atr]组成。
Kaggle数据集下载
https://www.kaggle.com/mondejar/mitbih-database
由数据文件[.csv]和注释文件[.txt]组成。
PhysioBank ATM
输入参数
输出
展示所选择的心电图片段。
MLⅡ+V5 二导联,灰度间距0.2s,0.5mV
代码出处
####################读取头文件######################
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()
注释
将源文件按行读取并记录下各参数含义,存入变量。
nosig 信号数量;sfreq 采样率
dformat 数据存储格式;gain 信号增益;bitres 位分辨率……
####################读取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!")
注释
A 三个字节存储两个信号数据;
SAMPLES2READ 3列矩阵;
M 由3列矩阵转的2列矩阵;
M[:,0] 第一个信号幅度;
M[:,1] 第二个信号幅度;
如果信号量nosig=2,信号幅度减去零点再除以信号增益,TIME为1/360s;
如果信号量nosig=1,……
####################读取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]
注释:
A 表示拿两个字节,然后转2列矩阵;
ANNOTD 注释文本内容;
ATRTIME 注释对应Time。
#####################显示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()
注释:
TIME 表示1/360s(采样率360Hz);M[:,0] 矩阵第一列(信号1的值),红线绘制。
如果信号数 nosig 为2,蓝线绘制信号2。
plt.text 注释内容 ANNOTD,注释横坐标 ATRTIMED,纵坐标 0
ECG
红线表示信号1,蓝线表示信号2,横坐标是采样率的时间间隔,一个单位为1/360s,纵坐标是信号相对零点的幅度。