EDF文件的结构:
EDF文件包括【文件头信息】和【数据存储区域】,其中,【文件头信息】又分为两部分,【文件头前半部分】和【文件头后半部分】。EDF头文件信息全部使用ascll表示,头文件中每个功能参数描述均使用固定存储长度,相关信息在存储的时候需要左对齐,剩余未使用的空间使用‘ ’(字符空格)补齐;
【文件头前半部分】该部分共256字节,记录了采集行为的相关信息,主要包括通道数、采集时间、患者信息、数据总量等信息;
【文件头后半部分】它记录了各个通道的相关参数信息,每个通道的相关参数占用256字节
现在我们假设需要存储4个通道的数据,数据通道名称分别是PPG、EEG、ECG、HR,采样频率分别是100Hz、20Hz、3Hz、3Hz,记录时长100秒,存储软件1秒存一次数据。根据这个需求来解释EDF存储格式。
【文件头前半部分】:
8字节ASCII码:数据格式版本(0),目前我是用版本0做的实验,版本0存储的是int16类型,低字节在前。存储其他类型,例如float先修改格式版本。
80字节ASCII码:病人信息标识,这个根据实际需求填写,没有需求可以随便填。
80字节ASCII码:记录标识,这个没研究明白,暂时随便填吧。
8字节ASCII码:记录开始日期,顺序为日.月.年,用“.”隔开,例如2023年6月21日:21.03.2023
8字节ASCII码:记录开始时间,顺序为时.分.秒 ,格式要求与日期相同
8字节ASCII码:记录头的字节数 ,此部分记录了文件头数据的总长度,总长度=256+256*通道数量=256+256*4=1280(公式中第一个256是文件头前半部分,第二个256是各个通道的相关参数)
44字节ASCII码:保留
8字节ASCII码:文件中数据记录块数nr,该参数用于解析软件计算edf文件的完整性。
8字节ASCII码:一个数据记录块的记录时间
4字节ASCII码:数据记录的通道数(ns)
【文件头后半部分】:
16字节ASCII码:ns*标识(如 PPG)
16字节ASCII码:ns*标识(如 EEG)
16字节ASCII码:ns*标识(如 ECG)
16字节ASCII码:ns*标识(如 HR)
80 字节ASCII码:传感器类型,如对PPG传感器的一个描述,根据需求写
80 字节ASCII码:传感器类型,如对EEG传感器的一个描述,根据需求写
80 字节ASCII码:传感器类型,如对ECG传感器的一个描述,根据需求写
80 字节ASCII码:传感器类型,如对HR传感器的一个描述,根据需求写
8字节ASCII码:物理信号单位,如mV
8字节ASCII码:物理信号单位,如mV
8字节ASCII码:物理信号单位,如%
8字节ASCII码:物理信号单位,如BMP
8字节ASCII码:物理信号最小值
8字节ASCII码:物理信号最小值
8字节ASCII码:物理信号最小值
8字节ASCII码:物理信号最小值
8字节ASCII码:物理信号最大值
8字节ASCII码:物理信号最大值
8字节ASCII码:物理信号最大值
8字节ASCII码:物理信号最大值
8字节ASCII码:数字信号最小值,记录数据超过该值设置的大小,EDFbrowser将显示该值,超出部分被削平,其他通道类似
8字节ASCII码:数字信号最小值
8字节ASCII码:数字信号最小值
8字节ASCII码:数字信号最小值
8字节ASCII码:数字信号最大值,记录数据超过该值设置的大小,EDFbrowser将显示该值,超出部分被削平,其他通道类似
8字节ASCII码:数字信号最大值
8字节ASCII码:数字信号最大值
8字节ASCII码:数字信号最大值
80字节ASCII码:滤波器信息
80字节ASCII码:滤波器信息
80字节ASCII码:滤波器信息
80字节ASCII码:滤波器信息
8字节ASCII码:一个数据记录的采样点数,在一个存储块中本通道的数据个数
8字节ASCII码:一个数据记录的采样点数,在一个存储块中本通道的数据个数
8字节ASCII码:一个数据记录的采样点数,在一个存储块中本通道的数据个数
8字节ASCII码:一个数据记录的采样点数,在一个存储块中本通道的数据个数
32字节ASCII码:保留字节
32字节ASCII码:保留字节
32字节ASCII码:保留字节
32字节ASCII码:保留字节
数字信号最大最小值与物理信号最大最小值控制波形在EDFbrowser中Y轴的显示范围。我们自己做解析软件可能用不到。
【数据存储区域】:
第1块存储数据:PPG波形数据+ EEG波形数据+ECG波形数据+HR波形数据
第1块存储数据:PPG波形数据+ EEG波形数据+ECG波形数据+HR波形数据
.
.
.
第n块存储数据:PPG波形数据+ EEG波形数据+ECG波形数据+HR波形数据
最后给出一个基于QT的例程,无论什么语言,明白了存储原理,存储不是问题。
QString edf_appendData(QString data,int total_len) { QString edf_data; edf_data.append(data); qDebug()<<edf_data<<data.size(); for(int i=0;i<(total_len-data.size());i++) { edf_data.append(' '); } return edf_data; } void MainWindow::EDFwriteData(QDataStream &file_write,qint16 *PPG,qint16 *HuXi,qint16 *SPO2,qint16 *HR) { int i; for ( i = 0; i < 100; i++) //PPG每秒100个数,即100Hz { file_write << PPG[i]; // 写入信号采样值到文件 } for (i = 0; i <20; i++) //呼吸每秒20个数,即20Hz { file_write << *(HuXi+i); // 写入信号采样值到文件 qDebug()<<*(HuXi+i); } for (i = 0; i <3; i++) //血氧每秒3个数,即3Hz { file_write << *(SPO2+i); // 写入信号采样值到文件 } for (i = 0; i <3; i++) //脉率每秒3个数,即3Hz { file_write << *(HR+i); // 写入信号采样值到文件 } } void MainWindow::on_pushButton_clicked() { // 创建并打开EDF文件 QFile file("exampl.edf"); if (!file.open(QIODevice::WriteOnly)) { // 文件打开失败处理 return; } file.write(edf_appendData("0",8).toUtf8()); //数据格式版本 file.write(edf_appendData("test",80).toUtf8()); //病人信息标识 file.write(edf_appendData("112233",80).toUtf8()); //记录标识 file.write(edf_appendData("23.04.21",8).toUtf8()); //记录开始日期,用.分割,日、月、年 file.write(edf_appendData("08.30.00",8).toUtf8()); //记录开始时间,用.分割,时分秒 file.write(edf_appendData("1280",8).toUtf8()); //记录头的字节数 *********计算一下长度******** file.write(edf_appendData("",44).toUtf8()); //保留字段。 file.write(edf_appendData("100",8).toUtf8()); //记录块数 如果1秒为一个记录块,那记录块数就是记录总时间 file.write(edf_appendData("1",8).toUtf8()); //每个记录块的时间长度(以秒为单位)。 file.write(edf_appendData("4",4).toUtf8()); //指示EDF文件中的信号通道数量 file.write(edf_appendData("PPG",16).toUtf8()); //信号通道描述 file.write(edf_appendData("EEG",16).toUtf8()); //信号通道描述 file.write(edf_appendData("ECG",16).toUtf8()); //信号通道描述 file.write(edf_appendData("HR",16).toUtf8()); //信号通道描述 file.write(edf_appendData("Private Edition",80).toUtf8()); //传感器类型,即对传感器的描述 file.write(edf_appendData("+1Kpa~-1Kpa",80).toUtf8()); //传感器类型,即对传感器的描述 file.write(edf_appendData("XueYang",80).toUtf8()); //传感器类型,即对传感器的描述 file.write(edf_appendData("MaiLv",80).toUtf8()); //传感器类型,即对传感器的描述 file.write(edf_appendData("mV",8).toUtf8()); //信号通道单位 file.write(edf_appendData("Kpa",8).toUtf8()); //信号通道单位 file.write(edf_appendData("%",8).toUtf8()); //信号通道单位 file.write(edf_appendData("BPM",8).toUtf8()); //信号通道单位 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的物理最小值 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的物理最小值 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的物理最小值 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的物理最小值 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的物理最大值 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的物理最大值 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的物理最大值 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的物理最大值 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的数字最小值。 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的数字最小值。 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的数字最小值。 file.write(edf_appendData("0",8).toUtf8()); //每个信号通道的数字最小值。 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的数字最大值。 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的数字最大值。 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的数字最大值。 file.write(edf_appendData("1000",8).toUtf8()); //每个信号通道的数字最大值。 file.write(edf_appendData("LV BO QI 10Hz",80).toUtf8()); //滤波器信息 file.write(edf_appendData("LV BO QI 20Hz",80).toUtf8()); //滤波器信息 file.write(edf_appendData("LV BO QI 20Hz",80).toUtf8()); //滤波器信息 file.write(edf_appendData("LV BO QI 20Hz",80).toUtf8()); //滤波器信息 file.write(edf_appendData("100",8).toUtf8()); //一个数据记录块的采样点数 file.write(edf_appendData("20",8).toUtf8()); //一个数据记录块的采样点数 file.write(edf_appendData("3",8).toUtf8()); //一个数据记录块的采样点数 file.write(edf_appendData("3",8).toUtf8()); //一个数据记录块的采样点数 file.write(edf_appendData("",32).toUtf8()); //保留字段。 file.write(edf_appendData("",32).toUtf8()); //保留字段。 file.write(edf_appendData("",32).toUtf8()); //保留字段。 file.write(edf_appendData("",32).toUtf8()); //保留字段。 // 创建并写入EDF文件头部 QDataStream out(&file); out.setByteOrder(QDataStream::LittleEndian); // 根据EDF文件规范,设置字节顺序 设置大小端 qint16 PPG_Buf[100]={0},HuXi_Buf[20]={0},SPO2_Buf[3]={0},HR_Buf[3]={0}; HR_Buf[0]=1;HR_Buf[1]=20;HR_Buf[2]=30; for(int i=0;i<100;i++) PPG_Buf[i]=i; for(int i=0;i<20;i++) HuXi_Buf[i]=i; for(int i=0;i<3;i++) SPO2_Buf[i]=i; for(int i=0;i<3;i++) HR_Buf[i]=i*10; for (int i = 0;i<100;i++) { EDFwriteData(out,PPG_Buf,HuXi_Buf,SPO2_Buf,HR_Buf); } // 关闭文件 file.close(); }
Edf文件对字段长度要求非常严格,错一点都不行
水平有限,如有疏漏、错误,还望海涵。
标签:存储,EDF,字节,波形,数据,说明,80,ASCII From: https://www.cnblogs.com/xiaofakun/p/17496507.html