EDF存储说明

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波形数据

Edf文件对字段长度要求非常严格,错一点都不行

最后给出一个基于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());        //记录头的字节数 总长度=256+256*通道数量

    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();

}

水平有限,如有疏漏、错误,还望海涵。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要打开EDF文件(European Data Format,欧洲数据格式)需要使用Java编程语言。首先,你需要了解EDF文件的结构和格式。 EDF文件是一种常用的医学生物信号文件格式,用于记录生理信号数据,如心电图(ECG)、脑电图(EEG)等。这些文件通常包含头部信息和信号数据记录。 要打开EDF文件,可以使用Java的文件输入流(FileInputStream)或者缓冲输入流(BufferedInputStream)。首先,你需要创建一个文件输入流并将EDF文件路径传递给它。然后,你可以使用缓冲输入流来提高读取文件的效率。 接下来,你需要解析EDF文件的头部信息。头部信息包含了文件的描述、信号通道数、采样频率等重要信息。你可以使用Java的字节流和字符流来读取和解析头部信息,根据EDF文件的规范进行解析。 一旦你解析了头部信息,你就可以读取EDF文件中的信号数据了。EDF文件中的信号数据以二进制形式存储,通常需要进行解码。不同的信号通道可能会有不同的存储格式,如整型、浮点型等。你可以根据信号通道的类型使用Java的数据输入流(DataInputStream)来读取并解码信号数据。 读取信号数据时,你可以按照指定的采样频率和数据长度来读取一定时间范围内的信号数据,或者按照指定的时间戳来读取特定时间点的信号数据。 当你读取完EDF文件中的所有信号数据后,记得关闭打开的流,释放资源。 总结一下,要打开EDF文件,你需要使用Java的文件输入流或者缓冲输入流来读取文件,然后解析头部信息,最后读取信号数据。这个过程需要根据EDF文件的规范进行解析和处理。希望这些信息能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值