#include "headfile.h" #include #include #include std::vector heart_rate; // 辅助函数:获取数据类型名称 std::string get_data_type_name(DataType data_type) { switch (data_type) { case DataType::EEG: return "EEG (脑电)"; case DataType::ECG_2LEAD: return "ECG_2LEAD (胸腹设备)"; case DataType::SNORE: return "SNORE (鼾声)"; case DataType::RESPIRATION: return "RESPIRATION (呼吸/姿态/环境光)"; case DataType::ECG_12LEAD: return "ECG_12LEAD (12导联心电)"; case DataType::PPG: return "PPG (血氧)"; case DataType::STETHOSCOPE: return "STETHOSCOPE (听诊器)"; default: return "未知类型"; } } // 新增:完整的信号数据处理流程 - 整合所有步骤 void complete_signal_processing_pipeline() { try { std::cout << "=== 开始完整的信号数据处理流程 ===" << std::endl; // 1. 读取原始二进制文件 std::cout << "步骤1: 读取原始数据..." << std::endl; std::vector file_content = FileManager::readBinaryFile("raw_data/ecg_data_raw.dat"); std::cout << "原始文件大小: " << file_content.size() << " 字节" << std::endl; // 2. 解析设备数据包 std::cout << "步骤2: 解析设备数据包..." << std::endl; std::vector all_data = parse_device_data(file_content); std::cout << "数据解析完成,共解析出 " << all_data.size() << " 个数据对象" << std::endl; // 3. 通道映射 (MAPPER) std::cout << "步骤3: 执行通道映射..." << std::endl; Mapper mapper; for(size_t i = 0; i < all_data.size(); ++i) { try { std::cout << "映射数据对象 " << i + 1 << "/" << all_data.size() << "..."; all_data[i] = mapper.DataMapper(all_data[i]); std::cout << " 完成" << std::endl; } catch (const std::exception& e) { std::cerr << " 失败: " << e.what() << std::endl; continue; } } // 保存映射后的数据 save_to_csv(all_data, "data_generated/channel_data_mapped_.csv"); std::cout << "通道映射完成,结果已保存到 data_generated/channel_data_mapped_.csv" << std::endl; // 4. 信号预处理 (滤波等) std::cout << "步骤4: 执行信号预处理..." << std::endl; SignalProcessor processor; std::vector processed_data; try { processed_data = processor.process_channel_based_filtering_simple(all_data); std::cout << "信号预处理完成,处理了 " << processed_data.size() << " 个数据对象" << std::endl; } catch (const std::exception& e) { std::cerr << "信号预处理失败: " << e.what() << std::endl; std::cout << "使用映射后的数据继续处理..." << std::endl; processed_data = all_data; } // 保存预处理后的数据 save_to_csv(processed_data, "data_generated/channel_data_processed_.csv"); std::cout << "预处理后的数据已保存到 data_generated/channel_data_processed_.csv" << std::endl; // 5. 指标计算 std::cout << "步骤5: 计算生理指标..." << std::endl; MetricsCalculator calculator; const float sample_rate = 250.0f; // 创建详细指标文件 std::ofstream metrics_file("data_generated/calculated_metrics_detailed.csv"); if (!metrics_file.is_open()) { std::cerr << "无法创建指标保存文件" << std::endl; return; } // 写入CSV表头 metrics_file << "数据对象,数据类型,包序号,时间戳,信号质量指数,"; metrics_file << "心率(bpm),T波振幅(mV),QRS宽度(ms),ST偏移(mV),"; metrics_file << "血氧饱和度(%),灌注指数(%),脉搏波宽度,红光红外光比值,"; metrics_file << "SDNN(ms),RMSSD(ms),pNN50(%),三角指数,"; metrics_file << "均值,标准差,最小值,最大值,峰峰值,信号质量评分(%)\n"; // 计算每个数据对象的指标 for (size_t i = 0; i < processed_data.size(); ++i) { const auto& data = processed_data[i]; std::cout << "计算数据对象 " << i + 1 << "/" << processed_data.size() << " (" << get_data_type_name(data.data_type) << ") 的指标..." << std::endl; // 写入基本信息 metrics_file << i << "," << get_data_type_name(data.data_type) << "," << data.packet_sn << "," << data.timestamp << "," << data.sqi << ","; // 根据数据类型计算指标 if (data.data_type == DataType::ECG_12LEAD || data.data_type == DataType::ECG_2LEAD) { // ECG指标 auto ecg_metrics = calculator.calculate_all_ecg_metrics(data, sample_rate); metrics_file << ecg_metrics["heart_rate"] << "," << ecg_metrics["t_wave_amplitude"] << "," << ecg_metrics["qrs_width"] << "," << ecg_metrics["st_offset"] << "," << "0,0,0,0," // PPG指标填充0 << ecg_metrics["sdnn"] << "," << ecg_metrics["rmssd"] << "," << ecg_metrics["pnn50"] << "," << ecg_metrics["triangular_index"] << "," << ecg_metrics["mean"] << "," << ecg_metrics["std_dev"] << "," << ecg_metrics["min_value"] << "," << ecg_metrics["max_value"] << "," << ecg_metrics["peak_to_peak"] << "," << ecg_metrics["signal_quality"]; } else if (data.data_type == DataType::PPG) { // PPG指标 auto ppg_metrics = calculator.calculate_all_ppg_metrics(data, sample_rate); metrics_file << "0,0,0,0," // ECG指标填充0 << ppg_metrics["spo2"] << "," << ppg_metrics["perfusion_index"] << "," << ppg_metrics["pulse_width"] << "," << ppg_metrics["amplitude_ratio"] << "," << "0,0,0,0," // HRV指标填充0 << ppg_metrics["mean"] << "," << ppg_metrics["std_dev"] << "," << ppg_metrics["min_value"] << "," << ppg_metrics["max_value"] << "," << ppg_metrics["peak_to_peak"] << "," << ppg_metrics["signal_quality"]; } else { // 其他数据类型 metrics_file << "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"; } metrics_file << "\n"; } metrics_file.close(); std::cout << "指标计算完成,结果已保存到 calculated_metrics_detailed.csv" << std::endl; // 6. 创建指标汇总文件 std::cout << "步骤6: 生成指标汇总..." << std::endl; std::ofstream summary_file("data_generated/metrics_summary.csv"); if (summary_file.is_open()) { summary_file << "数据类型,数据对象数量,平均心率(bpm),平均信号质量(%),平均QRS宽度(ms),平均ST偏移(mV)\n"; // 按数据类型分组统计 std::map> type_groups; for (size_t i = 0; i < processed_data.size(); ++i) { type_groups[processed_data[i].data_type].push_back(i); } for (const auto& [data_type, indices] : type_groups) { if (indices.empty()) continue; std::string type_name = get_data_type_name(data_type); int count = static_cast(indices.size()); // 计算该类型的平均指标 float total_hr = 0.0f, total_quality = 0.0f, total_qrs = 0.0f, total_st = 0.0f; int valid_hr = 0, valid_quality = 0, valid_qrs = 0, valid_st = 0; for (size_t idx : indices) { const auto& data = processed_data[idx]; if (data.data_type == DataType::ECG_12LEAD || data.data_type == DataType::ECG_2LEAD) { auto ecg_metrics = calculator.calculate_all_ecg_metrics(data, sample_rate); if (ecg_metrics["heart_rate"] > 0) { total_hr += ecg_metrics["heart_rate"]; valid_hr++; } if (ecg_metrics["signal_quality"] > 0) { total_quality += ecg_metrics["signal_quality"]; valid_quality++; } if (ecg_metrics["qrs_width"] > 0) { total_qrs += ecg_metrics["qrs_width"]; valid_qrs++; } if (ecg_metrics["st_offset"] != 0) { total_st += ecg_metrics["st_offset"]; valid_st++; } } } // 计算平均值 float avg_hr = valid_hr > 0 ? total_hr / valid_hr : 0.0f; float avg_quality = valid_quality > 0 ? total_quality / valid_quality : 0.0f; float avg_qrs = valid_qrs > 0 ? total_qrs / valid_qrs : 0.0f; float avg_st = valid_st > 0 ? total_st / valid_st : 0.0f; summary_file << type_name << "," << count << "," << std::fixed << std::setprecision(2) << avg_hr << "," << avg_quality << "," << avg_qrs << "," << avg_st << "\n"; } std::cin.get(); summary_file.close(); std::cout << "指标汇总已保存到 metrics_summary.csv" << std::endl; } std::cin.get(); // 7. 流程完成总结 std::cout << "\n=== 完整信号数据处理流程完成 ===" << std::endl; std::cout << "生成的文件:" << std::endl; std::cout << "1. data_generated/channel_data_mapped_.csv - 通道映射后的数据" << std::endl; std::cout << "2. data_generated/channel_data_processed_.csv - 预处理后的数据" << std::endl; std::cout << "3. data_generated/calculated_metrics_detailed.csv - 详细指标数据" << std::endl; std::cout << "4. data_generated/metrics_summary.csv - 指标汇总统计" << std::endl; std::cin.get(); } catch (const std::exception& e) { std::cerr << "完整流程执行错误: " << e.what() << std::endl; } } // PPG数据处理函数 - 专门处理A50伤后6h-1.txt文件 void process_ppg_a50_data() { try { std::cout << "=== 开始处理PPG数据 (A50伤后6h-1.txt) ===" << std::endl; std::cin.get(); // 1. 读取PPG数据文件 std::cout << "步骤1: 读取PPG数据文件..." << std::endl; std::string ppg_file_path = "raw_data/A50_6h_1.txt"; std::cin.get(); std::ifstream ppg_file(ppg_file_path); if (!ppg_file.is_open()) { std::cerr << "错误: 无法打开PPG数据文件: " << ppg_file_path << std::endl; std::cout << "请确保文件存在于 raw_data/ 文件夹中" << std::endl; std::cin.get(); return; } // 2. 解析PPG数据 std::cout << "步骤2: 解析PPG数据..." << std::endl; std::vector red_channel, ir_channel; std::string line; int line_count = 0; while (std::getline(ppg_file, line)) { line_count++; if (line.empty()) continue; // 解析每行的两个数值 (红光,红外光) std::istringstream iss(line); std::string red_str, ir_str; if (std::getline(iss, red_str, ',') && std::getline(iss, ir_str)) { try { float red_val = std::stof(red_str); float ir_val = std::stof(ir_str); red_channel.push_back(red_val*0.879); ir_channel.push_back(ir_val*0.879); } catch (const std::exception& e) { std::cerr << "警告: 第 " << line_count << " 行数据解析失败: " << line << std::endl; continue; } } else { std::cerr << "警告: 第 " << line_count << " 行格式不正确: " << line << std::endl; continue; } } ppg_file.close(); std::cout << "PPG数据解析完成,共读取 " << red_channel.size() << " 个数据点" << std::endl; std::cout << "红光通道范围: [" << *std::min_element(red_channel.begin(), red_channel.end()) << ", " << *std::max_element(red_channel.begin(), red_channel.end()) << "]" << std::endl; std::cout << "红外光通道范围: [" << *std::min_element(ir_channel.begin(), ir_channel.end()) << ", " << *std::max_element(ir_channel.begin(), ir_channel.end()) << "]" << std::endl; // 3. 创建SensorData对象 std::cout << "步骤3: 创建PPG数据对象..." << std::endl; SensorData ppg_data; ppg_data.data_type = DataType::PPG; ppg_data.packet_sn = 1; ppg_data.timestamp = std::time(nullptr); ppg_data.sqi = 0.8f; // 默认信号质量指数 // 将单通道数据转换为多通道格式 std::vector> channels = {red_channel, ir_channel}; ppg_data.channel_data = channels; // 4. 信号预处理 std::cout << "步骤4: 执行PPG信号预处理..." << std::endl; SignalProcessor processor; std::vector ppg_data_vector = {ppg_data}; std::vector processed_ppg_data; try { processed_ppg_data = processor.process_channel_based_filtering_simple(ppg_data_vector); std::cout << "PPG信号预处理完成" << std::endl; } catch (const std::exception& e) { std::cerr << "PPG信号预处理失败: " << e.what() << std::endl; std::cout << "使用原始数据继续处理..." << std::endl; processed_ppg_data = ppg_data_vector; } // 5. 保存预处理后的数据 std::cout << "步骤5: 保存预处理后的PPG数据..." << std::endl; save_to_csv(processed_ppg_data, "data_generated/ppg_a50_processed.csv"); std::cout << "预处理后的PPG数据已保存到 data_generated/ppg_a50_processed.csv" << std::endl; // 6. 计算PPG生理指标 std::cout << "步骤6: 计算PPG生理指标..." << std::endl; MetricsCalculator calculator; const float sample_rate = 50.0f; // PPG采样率,请根据实际情况调整 auto ppg_metrics = calculator.calculate_all_ppg_metrics(processed_ppg_data[0], sample_rate); // 7. 保存指标计算结果 std::cout << "步骤7: 保存PPG指标计算结果..." << std::endl; std::ofstream metrics_file("data_generated/ppg_a50_metrics.csv"); if (metrics_file.is_open()) { metrics_file << "指标名称,数值,单位\n"; metrics_file << "心率," << ppg_metrics["heart_rate"] << ",bpm\n"; metrics_file << "血氧饱和度," << ppg_metrics["spo2"] << ",%\n"; metrics_file << "灌注指数," << ppg_metrics["perfusion_index"] << ",%\n"; metrics_file << "脉搏波宽度," << ppg_metrics["pulse_width"] << ",ms\n"; metrics_file << "红光红外光比值," << ppg_metrics["amplitude_ratio"] << ",无单位\n"; metrics_file << "信号质量评分," << ppg_metrics["signal_quality"] << ",%\n"; metrics_file << "均值," << ppg_metrics["mean"] << ",mV\n"; metrics_file << "标准差," << ppg_metrics["std_dev"] << ",mV\n"; metrics_file << "最小值," << ppg_metrics["min_value"] << ",mV\n"; metrics_file << "最大值," << ppg_metrics["max_value"] << ",mV\n"; metrics_file << "峰峰值," << ppg_metrics["peak_to_peak"] << ",mV\n"; metrics_file.close(); std::cout << "PPG指标已保存到 data_generated/ppg_a50_metrics.csv" << std::endl; } // 8. 显示关键指标 std::cout << "\n=== PPG数据处理完成 ===" << std::endl; std::cout << "关键指标:" << std::endl; std::cout << "- 心率: " << ppg_metrics["heart_rate"] << " bpm" << std::endl; std::cout << "- 血氧饱和度: " << ppg_metrics["spo2"] << " %" << std::endl; std::cout << "- 灌注指数: " << ppg_metrics["perfusion_index"] << " %" << std::endl; std::cout << "- 信号质量: " << ppg_metrics["signal_quality"] << " %" << std::endl; std::cout << "\n生成的文件:" << std::endl; std::cout << "1. data_generated/ppg_a50_processed.csv - 预处理后的PPG数据" << std::endl; std::cout << "2. data_generated/ppg_a50_metrics.csv - PPG生理指标" << std::endl; std::cout << "\n按Enter键退出..." << std::endl; std::cin.get(); } catch (const std::exception& e) { std::cerr << "PPG数据处理错误: " << e.what() << std::endl; } } int main() { // 选择要运行的测试 std::cout << "请选择测试模式:" << std::endl; std::cout << "1. 测试MIT-BIH数据处理" << std::endl; std::cout << "2. 运行完整信号数据处理流程 (推荐)" << std::endl; std::cout << "3. 处理PPG数据 (A50伤后6h-1.txt)" << std::endl; std::cout << "请输入选择 (1, 2 或 3): "; int choice; std::cin >> choice; if (choice == 1) { } else if (choice == 2) { complete_signal_processing_pipeline(); // 运行完整信号数据处理流程 } else if (choice == 3) { process_ppg_a50_data(); // 处理PPG数据 } else { std::cout << "无效选择,运行默认测试..." << std::endl; } return 0; }