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.4400Notes:
我计划读取第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]
- 交错存储提取ECG通道(索引1):
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
相关产品推荐
相关产品推荐

