You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python读取.hdr和.dat文件绘制ECG波形异常求助

问题描述

我尝试读取并绘制存储在.dat文件中的ECG数据,该文件配有对应的.hdr头文件,头文件内容如下:

File Name: tam_racap.dat
Frontend Gain: 1000.0000
Scan Rate: 1000.0000
Channels Used:
Output Filtered Gain: 2.4400
ECG Gain: 2.4400
D/A Output Gain: 2.4400
Digital Output 4 Gain: 2.4400
Digital Output 6 Gain: 2.4400

Notes:

我计划读取第2通道(ECG通道)的数据,编写了wave_plot函数来利用头文件信息读取二进制数据,代码如下:

def wave_plot(profile_name):
    header_file_path = os.path.join(os.getcwd(), f'PROF_{profile_name}', 'header.hdr')

    # Check if the header file exists
    if os.path.exists(header_file_path):
        with open(header_file_path, 'r') as header_file:
            header_lines = header_file.readlines()

        frontend_gain = float(header_lines[1].split(':')[1].strip())
        scan_rate = float(header_lines[2].split(':')[1].strip())
        channels_used = [line.split(':')[0].strip() for line in header_lines[4:]]

        # Read binary data file
        data_file_path = os.path.join(os.getcwd(), f'PROF_{profile_name}', 'data.dat')
        if os.path.exists(data_file_path):
            with open(data_file_path, 'rb') as data_file:
                # Skip to the start of channel one data
                data_file.seek(2)  # Assuming data format starts at the beginning of the file
                # Read the data from channel one
                ecg_data = np.fromfile(data_file, dtype=np.float64)  # Assuming data type is float64

            # Apply gain to the data
            ecg_data = ecg_data * frontend_gain

            # Create time axis
            time = np.arange(0, len(ecg_data) / scan_rate, 1 / scan_rate)

            # Plot first 50 points of ECG waveform
            plt.figure(figsize=(10, 6))
            plt.plot(time[:50], ecg_data[:50], color='blue', linestyle='-', linewidth=0.5)  # Adjust line style and color
            plt.xlabel('Time (s)')
            plt.ylabel('Voltage (mV)')
            plt.title('ECG Waveform')
            plt.grid(True)
            plt.show()
        
    else:
        print(f"Header file not found for profile '{profile_name}'.")

运行程序后绘制的波形完全不正确,调整绘制点数、切换读取通道都没解决问题,求排查原因。

排查与修复方案

以下是几个核心问题及对应解决办法:

1. 二进制数据类型与读取偏移错误

  • 多数生理信号设备用16位整数(np.int16)存储原始数据,而非代码中假设的np.float64;无依据的seek(2)会导致数据读取错位。
  • 修复:
    # 先尝试用16位整数读取,去掉无意义的seek操作
    with open(data_file_path, 'rb') as data_file:
        ecg_data = np.fromfile(data_file, dtype=np.int16)
    
    若数据仍异常,再测试np.int32或np.float32类型。

2. 多通道数据存储顺序未处理

  • ECG是第2通道,但代码直接读取所有数据,未考虑多通道的存储格式(常见交错存储:通道1点1→通道2点1→…→通道N点1→通道1点2…;或连续存储:通道1全量数据→通道2全量数据…)。
  • 修复:
    • 交错存储提取ECG通道(索引1):
      num_channels = len(channels_used)
      ecg_data = ecg_data[1::num_channels]  # 每隔num_channels取一个值,对应第2通道
      
    • 连续存储提取ECG通道:
      total_points_per_channel = len(ecg_data) // num_channels
      ecg_data = ecg_data[total_points_per_channel : total_points_per_channel*2]
      

3. 增益计算逻辑错误

  • 头文件中每个通道有独立增益(ECG通道为2.4400),代码仅使用了Frontend Gain,忽略通道自身增益,导致电压缩放错误。
  • 修复:
    # 先从头文件提取ECG通道的增益
    channel_gains = {}
    for line in header_lines[4:]:
        if ':' in line:
            parts = line.split(':')
            ch_name = parts[0].strip()
            ch_gain = float(parts[1].strip())
            channel_gains[ch_name] = ch_gain
    ecg_gain = channel_gains.get('ECG', 1.0)
    
    # 若为16位整数原始数据,结合参考电压计算实际电压(以±2.5V为例)
    ecg_voltage = (ecg_data / 32767) * 2.5 * frontend_gain * ecg_gain
    

4. 字节序不匹配

  • 部分设备用大端字节序存储数据,而np.fromfile默认使用系统字节序,会导致数据完全错乱。
  • 修复:读取时指定字节序
    # 大端16位整数
    ecg_data = np.fromfile(data_file, dtype='>i16')
    # 小端16位整数用 '<i16'
    

5. 验证步骤

  • 先打印前100个原始数据,确认是否在合理范围(16位整数应在-32768~32767之间);
  • 计算电压后,检查是否符合ECG信号典型范围(0.5~4mV);
  • 先绘制全量数据波形,避免因局部数据异常误判。

内容的提问来源于stack exchange,提问作者Isaac Simmons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:04:53