读取EDF文件
此示例演示了以EDF(欧洲数据格式)格式(一种用于存储生物医学信号的标准格式)下载、分析和可视化记录数据的过程。
关于EDF格式
EDF(欧洲数据格式)是多通道生物信号存储和交换的开放标准,广泛用于医学和科学研究。 用于记录脑电图、心电图、肌电图、呼吸信号、眼动、血氧饱和度等生理数据。
EDF旨在确保来自不同制造商和不同软件的设备之间的兼容性。 由于其固定的结构,这种格式很容易被许多数据分析工具处理。
使用EDF格式
功能 engee.clear() 清理工作区:
engee.clear()
我们将使用函数进行连接 include 文件"edfread。jl"用于读取EDF文件:
include("$(@__DIR__)/edfread.jl")
功能 edfread 它用于读取EDF格式的数据。 结构 hdr 此函数返回的信息包含有关记录的完整元信息:
一般记录参数:
-
ver-EDF格式版本 -
patientID-病人ID -
recordID-记录ID -
startdate和starttime-开始录制的日期和时间 -
bytes-以字节为单位的标头大小 -
records-文件中的数据块数 -
duration-以秒为单位的一个区块的持续时间 -
ns-记录中的通道数
每个通道的参数:
-
labels-频道名称 -
transducers-传感器类型 -
physicalDims-物理测量单位 -
physicalMins和physicalMaxs-最小和最大物理值 -
digitalMins和digitalMaxs-最小和最大数字值 -
prefilters-在录制过程中应用的过滤器 -
samples-每个通道的一个块中的样本数
检查测试数据
来自[EDF/BDF测试文件]资源的标准化测试数据用于验证读取和处理EDF文件的算法的正确性(https://teuniz.net/edf_bdf_testfiles /)。
文件用于演示如何使用EDF格式。 test_generator.edf. 该文件包含用于测试和验证读取算法的多通道数据。
要使用EDF格式的数据,请使用以下函数 edfread,这将执行文件读取,元数据提取和信号加载。 由于她的工作,我们将得到两个对象。:
*标题结构 hdr 带记录参数;
*阵列 record,包含来自所有通道的数据。
hdr, record = edfread("$(@__DIR__)/test_generator.edf")
为了便于审查和验证从标题结构上传的数据 hdr 记录的关键参数进行提取显示。
println("格式版本: ", hdr.ver)
println("病人ID: ", strip(hdr.patientID))
println("记录的描述: ", strip(hdr.recordID))
println("开始日期/时间: ", hdr.startdate, " ", hdr.starttime)
println("频道数目: ", hdr.ns)
println("参赛作品数目: ", hdr.records)
println("总工期: ", hdr.records * hdr.duration, " sec")
让我们创建一个具有每个通道特征的表:其名称,值的物理范围,测量单位和采样率。
println(" 非也。. /通道/范围(最小/最大)/单位/频率,Hz")
println("----------------------------------------------------------")
for ch in 1:hdr.ns
label = hdr.labels[ch]
# 我们取矩阵的一行并删除NaN(填充)
row = record[ch, :]
row = row[.!isnan.(row)]
dataMin = round(minimum(row); digits = 2)
dataMax = round(maximum(row); digits = 2)
units = hdr.physicalDims[ch]
units = units == "" ? "-" : units
fs = round(hdr.samples[ch] / hdr.duration; digits = 2)
println(
lpad(ch, 2), " | ",
rpad(label, 8), " | ",
lpad(string(dataMin), 8), " / ",
rpad(string(dataMax), 8), " | ",
rpad(units, 6), " | ",
fs
)
end
为了验证读取和解释数据的正确性,我们会将上传的元数据与[EDF/BDF测试文件]页面上提供的参考信息进行比较(https://teuniz.net/edf_bdf_testfiles /)。
signal label waveform physical range f sf
--------------------------------------------------------------------
1 F4 block +800uV/-800uV 1Hz 200Hz
2 F3 triangle +800uV/-800uV 3Hz 100Hz
3 X10 impulse +0.8mV/-0.8mV 5Hz 200Hz
4 FP2 noise +3200uV/-3200uV -Hz 200Hz
5 P4 sine +800uV/-800uV 1Hz 50Hz
6 C4 sine +800uV/-800uV 2Hz 100Hz
7 P3 sine +800uV/-800uV 3Hz 200Hz
8 C3 sine +800uV/-800uV 4Hz 200Hz
9 X9 sine +800uV/-800uV 8Hz 200Hz
10 FP1 sine +800uV/-800uV 16Hz 200Hz
11 F8 sine +800uV/-800uV 32Hz 200Hz
12 F7 triangle +4mV/-4mV 5Hz 200Hz
13 DC01 sine square +6V/-0V 5Hz 200Hz
14 DC04 DC +100% -Hz 25Hz
15 DC03 DC +60BPM -Hz 25Hz
16 DC02 DC +16384 -Hz 25Hz
因此,上传的数据对应于测试文件的描述,这证实了功能正常工作。 edfread.
让我们建立多通道记录的前5秒的波形,以比较所得到的图形与测试图像。
t_max = 5.0 # 时间限制,与
nchan = size(record, 1) # 频道数目
plt = plot(
layout = (nchan, 1),
size = (1000, 200*nchan),
margin = 20*Plots.px
)
for ch in 1:nchan
# 信道采样率
fs = hdr.samples[ch] / hdr.duration
# 每个通道的最大采样数
n_time = min(Int(round(t_max * fs)), hdr.samples[ch] * hdr.records)
# 时间和信号
t = (0:n_time-1) ./ fs
y = record[ch, 1:n_time]
# 测量单位
units = hdr.physicalDims[ch]
units = units == "" ? "-" : units
plot!(
plt[ch],
t, y,
label = "$(hdr.labels[ch])",
xlabel = "时间,从",
ylabel = units,
legend = :topright
)
end
display(plt)
测试功能操作 edfread 使用扩展的EDF+格式,我们将上传文件 test_generator_2.edf.
hdr, record = edfread("$(@__DIR__)/test_generator_2.edf")
与之前的文件类似,我们提取并分析记录的关键参数。
println("格式版本: ", hdr.ver)
println("病人ID: ", strip(hdr.patientID))
println("记录的描述: ", strip(hdr.recordID))
println("开始日期/时间: ", hdr.startdate, " ", hdr.starttime)
println("频道数目: ", hdr.ns)
println("参赛作品数目: ", hdr.records)
println("总工期: ", hdr.records * hdr.duration, " 证券交易委员会")
让我们创建一个具有每个通道特征的表:其名称,值的物理范围,测量单位和采样率。
println(" 非也。. /通道/范围(最小/最大)/单位/频率,Hz")
println("------------------------------------------------------------")
for ch in 1:hdr.ns-1
label = hdr.labels[ch]
# 我们取矩阵的一行并删除NaN(填充)
row = record[ch, :]
row = row[.!isnan.(row)]
dataMin = round(minimum(row); digits = 2)
dataMax = round(maximum(row); digits = 2)
units = hdr.physicalDims[ch]
units = units == "" ? "-" : units
fs = round(hdr.samples[ch] / hdr.duration; digits = 2)
println(
lpad(ch, 2), " | ",
rpad(label, 10), " | ",
lpad(string(dataMin), 8), " / ",
rpad(string(dataMax), 8), " | ",
rpad(units, 6), " | ",
fs
)
end
为了验证读取和解释数据的正确性,我们会将上传的元数据与[EDF/BDF测试文件]页面上提供的参考信息进行比较(https://teuniz.net/edf_bdf_testfiles /)。
signal label/waveform amplitude f sf
---------------------------------------------------
1 squarewave 100 uV 0.1Hz 200 Hz
2 ramp 100 uV 1 Hz 200 Hz
3 pulse 100 uV 1 Hz 200 Hz
4 ECG 100 uV 1 Hz 200 Hz
5 noise 100 uV - Hz 200 Hz
6 sine 1 Hz 100 uV 1 Hz 200 Hz
7 sine 8 Hz 100 uV 8 Hz 200 Hz
8 sine 8.5 Hz 100 uV 8.5Hz 200 Hz
9 sine 15 Hz 100 uV 15 Hz 200 Hz
10 sine 17 Hz 100 uV 17 Hz 200 Hz
11 sine 50 Hz 100 uV 50 Hz 200 Hz
因此,上传的数据对应于测试文件的描述,这证实了功能正常工作。 edfread.
为了检查EDF+数据的下载和解释的正确功能,我们将绘制记录的前10秒的图形。
t_max = 10.0 # 时间限制,与
nchan = size(record, 1)-1
plt = plot(
layout = (nchan, 1),
size = (1000, 200*nchan),
margin = 30*Plots.px
)
for ch in 1:(nchan)
# 信道采样率
fs = hdr.samples[ch] / hdr.duration
# 每个通道的最大采样数
n_time = min(Int(round(t_max * fs)), hdr.samples[ch] * hdr.records)
# 时间和信号
t = (0:n_time-1) ./ fs
y = record[ch, 1:n_time]
# 测量单位
units = hdr.physicalDims[ch]
units = units == "" ? "-" : units
plot!(
plt[ch],
t, y,
label = "$(hdr.labels[ch])",
xlabel = "时间,从",
ylabel = units,
legend = :topright
)
end
display(plt)
结论
在此示例中,考虑了使用EDF和**EDF+**格式的数据的原则。 使用测试文件的示例(test_generator.edf 和 test_generator_2.edf),取自[EDF/BDF测试文件](https://teuniz.net/edf_bdf_testfiles /)。