# 项目背景文档(供 Agent 快速上手) ## 1. 文档目的 这份文档用于帮助新进入仓库的 agent 快速建立项目心智模型,重点回答下面几个问题: - 这个仓库在做什么 - 核心处理链路是什么 - 代码从哪里开始看 - 输入数据长什么样,输出产物长什么样 - 哪些模块已经可用,哪些模块还只是占位或半成品 --- ## 2. 一句话理解项目 `DataPrepare` 是一个睡眠呼吸暂停数据预处理仓库,主要用于把原始的 BCG / PSG 信号与呼吸暂停标签整理成可训练的数据集。 当前主线可以概括为两步: 1. 在 `event_mask_process/` 中把原始标注和规则检测结果整理成逐秒标签掩码。 2. 在 `dataset_builder/` 中根据这些掩码切出固定长度窗口,并将信号和窗口索引保存为 `npz` 数据集。 --- ## 3. 仓库总览 | 目录 | 作用 | 备注 | | --- | --- | --- | | `dataset_config/` | 各数据集的 YAML 配置 | 包含路径、采样率、阈值、切窗参数 | | `event_mask_process/` | 生成逐秒标签掩码 | 主入口之一 | | `dataset_builder/` | 将信号切成窗口并保存数据集 | 主入口之二 | | `signal_method/` | 信号预处理、规则检测、特征计算 | 规则逻辑核心 | | `utils/` | 读文件、标签转换、切窗、滤波、通用工具 | 底层支撑 | | `draw_tools/` | 全夜信号图、分段图、统计图 | 调试与可视化 | | `dataset_tools/` | 辅助脚本 | 包括配对拷贝、SHHS 标注检查 | | `output/` | 中间结果样例 | 仓库内已有若干处理结果示例 | --- ## 4. 项目主线流程 ### 4.1 HYS(BCG 主线) 对应文件: - `event_mask_process/HYS_process.py` - `dataset_builder/HYS_dataset.py` 处理过程: 1. 从 `root_path/OrgBCG_Aligned//OrgBCG_Sync_*.txt` 读取原始 BCG 同步信号。 2. 从 `root_path/Label//SA Label_corrected.csv` 读取人工修正后的呼吸暂停标签。 3. 对原始 BCG 进行 50Hz 陷波,再拆出: - 呼吸分量 `resp_data` - BCG 分量 `bcg_data` 4. 根据配置做规则检测,生成逐秒掩码: - `Resp_LowAmp_Label` - `Resp_Movement_Label` - `Resp_AmpChange_Label` - `BCG_LowAmp_Label` - `BCG_Movement_Label` - `BCG_AmpChange_Label` - `Disable_Label`(来自 `排除区间.xlsx`) - `SA_Label` / `SA_Score`(来自人工标签) 5. 将这些结果保存为 `output/HYS//_Processed_Labels.csv`。 6. 在数据集构建阶段读取上述逐秒标签,按 `window_sec` 和 `stride_sec` 切成窗口。 7. 保存处理后的信号 `Signals/*.npz`、窗口索引 `Segments_List/*.npz`、标签副本 `Labels/*.csv`。 ### 4.2 HYS_PSG(PSG 主线) 对应文件: - `event_mask_process/HYS_PSG_process.py` - `dataset_builder/HYS_PSG_dataset.py` 处理过程: 1. 从 `root_path/PSG_Aligned//` 读取 PSG 通道,包括: - `Rpeak` - `ECG_Sync` - `Effort Tho` - `Effort Abd` - `Flow P` - `Flow T` - `SpO2` - `5_class` 2. 从同目录读取 `SA Label_Sync.csv`。 3. 在 `HYS_PSG_process.py` 中生成较简化的逐秒标签: - `SA_Label` - `SA_Score` - `Disable_Label`(主要由睡眠分期里的清醒期生成) - 其余 `Resp_*` / `BCG_*` 掩码目前全部置零 4. 在 `HYS_PSG_dataset.py` 中对胸腹带、流量、SpO2、RRI 做统一重采样与长度对齐。 5. 对 SpO2 进行异常填补或置空,再切成窗口,保存为 PSG 数据集。 ### 4.3 设计上的共性 无论是 HYS 还是 HYS_PSG,核心设计都是: 1. 先把整夜记录整理成逐秒掩码。 2. 再根据掩码和切窗规则提取训练片段。 这意味着以后如果要改“可用性判断”或“切窗逻辑”,优先看: - `event_mask_process/` - `utils/split_method.py` --- ## 5. 数据与目录约定 ### 5.1 外部数据目录 这个仓库本身不包含原始数据,真正的数据目录由 YAML 中的绝对路径指定,例如: - `/mnt/disk_wd/marques_dataset/DataCombine2023/HYS` - `/mnt/disk_wd/marques_dataset/shhs/polysomnography/shhs1` 因此在新环境运行时,第一件事通常不是改代码,而是先改 `dataset_config/*.yaml` 里的绝对路径。 ### 5.2 HYS 数据目录约定 代码默认外部目录至少包含: - `OrgBCG_Aligned//OrgBCG_Sync_.txt` - `PSG_Aligned//...` - `Label//SA Label_corrected.csv` ### 5.3 HYS_PSG 数据目录约定 代码默认 `PSG_Aligned//` 内文件命名符合下面的模式: - `Rpeak*.txt` - `ECG_Sync*.txt` - `Effort Tho*.txt` - `Effort Abd*.txt` - `Flow P*.txt` - `Flow T*.txt` - `SpO2*.txt` - `5_class*.txt` - `SA Label_Sync.csv` ### 5.4 处理中间结果目录 仓库内 `output/` 保存的是“中间标签与图像结果”,不是最终训练数据集。 最终数据集通常会写到 YAML 中 `dataset_save_path` 指向的外部目录。 --- ## 6. 核心入口脚本 ### 6.1 主入口 | 场景 | 脚本 | | --- | --- | | HYS 逐秒标签生成 | `event_mask_process/HYS_process.py` | | HYS 数据集构建 | `dataset_builder/HYS_dataset.py` | | HYS_PSG 逐秒标签生成 | `event_mask_process/HYS_PSG_process.py` | | HYS_PSG 数据集构建 | `dataset_builder/HYS_PSG_dataset.py` | ### 6.2 辅助脚本 | 脚本 | 作用 | | --- | --- | | `dataset_tools/resp_pair_copy.py` | 将 HYS/ZD5Y 的 BCG 与 PSG 原始文件拷贝为配对数据集 | | `dataset_tools/shhs_annotations_check.py` | 统计 SHHS XML 标注中的事件类型组合 | | `event_mask_process/SHHS1_process.py` | SHHS1 处理入口占位,目前未实现 | ### 6.3 入口脚本的共同特点 - 大多数脚本没有命令行参数接口。 - 配置文件路径通常直接写在 `if __name__ == '__main__':` 中。 - 运行逻辑依赖 YAML 中的绝对路径。 所以如果 agent 要“跑脚本”,通常需要先确认: 1. 当前机器是否存在对应外部数据目录。 2. YAML 路径是否匹配当前环境。 --- ## 7. 关键模块说明 ### 7.1 `utils/` #### `utils/HYS_FileReader.py` 负责各种输入文件读取,是仓库最重要的底层模块之一: - `read_signal_txt`:读取单通道 txt,并根据文件名中的采样率推断 `fs` - `read_label_csv`:读取人工修正的 HYS 标签 - `read_raw_psg_label`:读取 PSG 原始同步标签 - `read_disable_excel`:读取 `排除区间.xlsx` - `read_mask_execl`:读取处理后的逐秒标签 CSV,并生成事件片段列表 - `read_psg_channel`:按通道名读取 PSG 文件夹里的多通道数据 #### `utils/operation_tools.py` 负责标签转换、片段提取和通用处理: - `load_dataset_conf`:读取 YAML - `generate_event_mask`:把事件表转换成逐秒 `SA_Label` - `generate_disable_mask`:把 Excel 中的排除区间转换成逐秒 `Disable_Label` - `event_mask_2_list`:把 0/1 掩码转为 `[start, end]` 列表 - `merge_short_gaps` / `remove_short_durations`:对逐秒掩码做时长后处理 - `fill_spo2_anomaly`:修补 SpO2 异常段 #### `utils/split_method.py` 真正的切窗规则在这里: - 默认按 `window_sec` / `stride_sec` 滑窗 - 只在 `EnableSegment` 内生成可用窗口 - 如果一个窗口中 `Resp_Movement_Label | Resp_LowAmp_Label` 超过窗口时长的 2/3,则该窗口转入 `disable_segment_list` #### `utils/filter_func.py` 提供滤波和采样率处理: - Butterworth / Bessel - 陷波 - 整数倍降采样 - 自动升降采样 - 移动平均去趋势 ### 7.2 `signal_method/` #### `signal_method/signal_process.py` 负责信号预处理: - `signal_filter_split`:把原始 OrgBCG 信号拆成呼吸分量和 BCG 分量 - `psg_effort_filter`:处理 PSG 努力带 / 流量信号 - `rpeak2hr` / `rpeak2rri_interpolation`:由 R 峰生成 HR / RRI #### `signal_method/rule_base_event.py` 规则检测主逻辑: - `detect_movement`:基于滑窗标准差和局部幅值比较检测体动 - `movement_revise`:对体动掩码做二次修正 - `detect_low_amplitude_signal`:检测低幅值 - `position_based_sleep_recognition_v2/v3`:根据体动前后幅值变化标记姿势/幅值变化段 #### `signal_method/normalize_method.py` `normalize_resp_signal_by_segment` 会按“可用片段”做分段 z-score 标准化。 HYS 中通常按 `Resp_AmpChange_Label` 的反向片段来归一化,目的是减少整夜幅值漂移带来的影响。 ### 7.3 `draw_tools/` 主要用于人工检查处理质量: - `draw_signal_with_mask`:画 HYS 全夜原始信号 + 规则掩码 - `draw_psg_signal`:画 HYS_PSG 全夜 PSG 信号 - `draw_psg_label` / `draw_psg_bcg_label`:按窗口导出分段图 ### 7.4 `dataset_builder/` 核心职责是把“整夜记录 + 逐秒掩码”转换成训练样本: - 保存处理后的多通道信号到 `npz` - 保存窗口起止列表到 `npz` - 把标签 CSV 一并拷贝到数据集目录 --- ## 8. 标签、通道和编码约定 ### 8.1 呼吸暂停事件编码 定义于 `utils/event_map.py`: | 事件 | 编码 | | --- | --- | | `Hypopnea` | 1 | | `Central apnea` | 2 | | `Obstructive apnea` | 3 | | `Mixed apnea` | 4 | ### 8.2 PSG 通道编号映射 同样定义于 `utils/event_map.py`: | 编号 | 通道名 | | --- | --- | | 1 | `Rpeak` | | 2 | `ECG_Sync` | | 3 | `Effort Tho` | | 4 | `Effort Abd` | | 5 | `Flow P` | | 6 | `Flow T` | | 7 | `SpO2` | | 8 | `5_class` | ### 8.3 睡眠分期编码 `5_class` 在读取时会转成整数: | 分期 | 编码 | | --- | --- | | `N3` | 1 | | `N2` | 2 | | `N1` | 3 | | `R` | 4 | | `W` | 5 | ### 8.4 逐秒标签 CSV 字段 `Processed_Labels.csv` 的核心字段为: - `Second` - `SA_Label` - `SA_Score` - `Disable_Label` - `Resp_LowAmp_Label` - `Resp_Movement_Label` - `Resp_AmpChange_Label` - `BCG_LowAmp_Label` - `BCG_Movement_Label` - `BCG_AmpChange_Label` 样例可见仓库内: - `output/HYS/220/220_Processed_Labels.csv` - `output/HYS_PSG/220/220_Processed_Labels.csv` --- ## 9. 主要配置文件 ### 9.1 HYS `dataset_config/HYS_config.yaml` 主要控制: - 样本 ID 列表 - 原始数据根目录 - 中间标签保存目录 - 呼吸 / BCG 的滤波和降采样参数 - 低幅值、体动、幅值变化检测阈值 - 数据集窗口长度和步长 ### 9.2 HYS_PSG `dataset_config/HYS_PSG_config.yaml` 主要控制: - 样本 ID 列表 - 目标统一采样率 `target_fs` - 努力带 / 流量滤波参数 - SpO2 异常填补参数 - 数据集输出路径 ### 9.3 其他配置 - `dataset_config/ZD5Y_config.yaml`:另一套 BCG 规则配置 - `dataset_config/SHHS1_config.yaml`:SHHS1 预留配置 - `dataset_config/RESP_PAIR_HYS_config.yaml`:HYS 配对原始数据拷贝 - `dataset_config/RESP_PAIR_ZD5Y_config.yaml`:ZD5Y 配对原始数据拷贝 --- ## 10. 输出产物说明 ### 10.1 中间输出 典型位置: - `output/HYS//_Processed_Labels.csv` - `output/HYS//_Signal_Plots.png` - `output/HYS_PSG//_Processed_Labels.csv` - `output/HYS_PSG//_Signal_Plots.png` - `output/HYS_PSG//_Signal_Plots_fill.png` ### 10.2 最终数据集输出 由 `dataset_builder/*` 保存到 YAML 指定的外部目录,结构通常是: - `Signals/` - `Segments_List/` - `Labels/` HYS 的 `Signals/*.npz` 里主要保存: - `bcg_signal_notch` - `bcg_signal` - `resp_signal` HYS_PSG 的 `Signals/*.npz` 里主要保存: - `Effort Tho` - `Effort Abd` - `Effort` - `Flow P` - `Flow T` - `SpO2` - `HR` - `RRI` - `5_class` `Segments_List/*.npz` 中主要保存: - `segment_list` - `disable_segment_list` --- ## 11. 推荐阅读顺序 如果 agent 是第一次接触这个仓库,建议按下面顺序阅读: 1. `dataset_config/HYS_config.yaml` 2. `event_mask_process/HYS_process.py` 3. `utils/operation_tools.py` 4. `utils/split_method.py` 5. `dataset_builder/HYS_dataset.py` 6. `signal_method/signal_process.py` 7. `signal_method/rule_base_event.py` 8. `utils/HYS_FileReader.py` 如果要看 PSG 主线,再继续读: 1. `dataset_config/HYS_PSG_config.yaml` 2. `event_mask_process/HYS_PSG_process.py` 3. `dataset_builder/HYS_PSG_dataset.py` 4. `draw_tools/draw_label.py` --- ## 12. 常见修改入口 如果你要改不同类型的问题,可以优先从这些文件入手: | 需求 | 优先看哪里 | | --- | --- | | 调整阈值、采样率、窗口长度 | `dataset_config/*.yaml` | | 修改逐秒标签生成逻辑 | `event_mask_process/*.py` | | 修改体动 / 低幅值 / 幅值变化规则 | `signal_method/rule_base_event.py` | | 修改滤波与重采样 | `signal_method/signal_process.py`、`utils/filter_func.py` | | 修改切窗规则 | `utils/split_method.py` | | 修改输入文件解析 | `utils/HYS_FileReader.py` | | 修改事件编码或通道映射 | `utils/event_map.py` | | 修改图像输出样式 | `draw_tools/*.py` | --- ## 13. 当前实现状态与注意事项 下面这些点对 agent 很重要: 1. 仓库没有依赖清单文件(如 `requirements.txt` / `pyproject.toml`),依赖需要从源码导入中反推,当前至少涉及 `numpy`、`pandas`、`scipy`、`matplotlib`、`seaborn`、`yaml`、`tqdm`、`rich`、`polars`、`lxml`、`mne`。 2. 大部分脚本依赖绝对路径,迁移环境时优先修改 YAML。 3. `event_mask_process/SHHS1_process.py` 目前基本为空,占位多于实现。 4. `event_mask_process/HYS_PSG_process.py` 当前是“简化版标签生成”,核心只用了 SA 标签和睡眠分期,`Resp_*` / `BCG_*` 掩码还没有真正实现。 5. `dataset_builder/HYS_dataset.py` 里虽然保留了分段可视化入口,但实际绘图调用被注释掉了,因此默认不会导出分段图。 6. `utils/signal_process.py` 和 `utils/filter_func.py` 有部分重复实现;当前实际被 `utils/__init__.py` 导出并广泛使用的是 `filter_func.py` 中的版本。 7. `README.md` 目前非常简略,真正的项目逻辑主要还是要靠源码理解。 --- ## 14. 对 Agent 最有价值的结论 如果只能记住几件事,请记住下面这些: 1. 这是一个“先做逐秒掩码,再做固定窗口切片”的数据准备仓库。 2. HYS 主线比 HYS_PSG 更完整,规则检测主要服务于 HYS。 3. 切窗逻辑集中在 `utils/split_method.py`,不是分散在各个 builder 里。 4. 原始数据不在仓库里,仓库只是代码和部分中间结果样例。 5. 大多数运行问题都不是代码逻辑错,而是路径、文件命名、采样率和外部数据结构不匹配。