信息速览
心脏会动,但心电图只记录电。一次心跳里,心室壁先在几十毫秒内完成等容收缩,压力陡升而容积不变,随后主动脉瓣被推开,血液以每秒数百毫升的流量冲出;舒张末期主动脉瓣关闭,压力回落。这一串机械事件的时刻,临床上是靠导管、超声或心音图间接推断的,体表心电图给不出答案。把一枚加速度计直接贴到心肌上,测的就是这串事件本身。
这个库来自挪威奥斯陆大学医院干预中心。他们的研究对象不是诊断,而是一条技术路线:把微型加速度计做进临时起搏导线,在开胸心脏手术中缝到心外膜上,术后几天里连续监测心功能。为了验证这条路走得通,团队做了多年的动物实验,又在 2022 年把其中一部分数据整理合并,交给 PhysioNet 托管。合并后的产物就是这里要说的 289 段记录。
它的价值与它的局限是同一件事的两面:信号源极干净,因为传感器就贴在心肌上,中间没有胸壁、没有肺、没有脂肪;但代价是全部数据来自麻醉开胸的动物,46 只,每段只有几秒到几十秒。它适合回答「这个信号里有没有这个信息」,不适合回答「这个模型在病人身上准不准」。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | Epicardially attached cardiac accelerometer data from canines and porcines |
| 发布方 | PhysioNet(数据由挪威奥斯陆大学医院干预中心提供) |
| 首版 | 2023 年 1 月 5 日,版本 1.0.0 |
| DOI | 10.13026/5xmr-zd88 |
| 动物规模 | 19 只犬、27 只猪,合计 46 只 |
| 记录数 | 289 段 |
| 单段时长 | 5 至 30 秒,平均 15 秒 |
| 采样率 | 统一 500 Hz(原始为 250、500、650、1000 Hz) |
| 通道 | 三轴加速度、左心室压力、部分记录含三导联心电 |
| 传感器 | MPU9250 三轴加速度计,缝于左室心尖前壁心外膜 |
| 压力测量 | Millar MPC-500 导管尖端微压计 |
| 文件格式 | 每段一个 JSON,五个数组加五个元数据字段 |
| 目录结构 | 5 个实验系列 / 46 个动物目录 / 17 类干预文件夹 |
| 体积 | 解压后 358 MB,官方压缩包 148 MB |
| 许可 | ODC-BY 1.0,免注册 |
| 标签 | 库内无瓣膜事件标签,标注在配套 GitHub 仓库 |
§1 它要解决的具体麻烦
1.1 有一个信号只能贴着心肌取
临床上想知道「左心室这一刻收缩得有多强」,可选的手段其实很有限。超声能看形态和容积,但需要探头贴在胸壁上,连续监测要有人守着;导管能测压力,是做心衰血流动力学监测的金标准,但要把导管送进心脏,属于有创操作;体表心音图便宜,可它听到的是瓣膜关闭的振动,经过胸壁、肺和脂肪之后,高频成分几乎被削平了。
心外膜加速度信号绕开了这一整条衰减链。传感器缝合在左心室心尖前壁,随心肌一起运动,测到的就是心室壁的加速度。收缩期开始时,室壁向内运动加速;主动脉瓣打开与关闭的瞬间,血流冲击与瓣膜止动会产生短促的高频振动,这两个时刻在加速度波形上表现为可检测的冲击。如果能从这一个信号里稳定地找出这两个时刻,就能进一步推算收缩间期、等容收缩时间这类功能指标,而传感器可以随起搏导线一起放进胸腔,术后几天连续工作。
这就是这个库存在的理由。它不是为了让模型认识更多病人,而是为了证明「一个贴在心肌上的加速度计,能不能独立地把机械事件定出来」。数据里的左室压不是配菜,它是这句话的裁判:有了高保真的压力曲线,才能用压力微分极值定义主动脉瓣开闭的真值,再去检验加速度信号单独能还原到什么程度。
理解这一点,后面的所有取舍才顺理成章。为什么只有几十秒?因为实验方案本来只关心若干个心动周期里的波形对齐。为什么是开胸?因为传感器要缝合,闭胸状态下做不到。为什么是犬和猪?因为这两种动物的心脏尺寸、胸廓结构与起搏实验习惯最接近临床前的需求。
还有一层现实约束来自导线本身。临时起搏导线要从胸壁引出体外,导体能容纳的芯数有限,每增加一个电极就多一分折断与感染的风险。加速度计不需要额外的电极界面,它占的是芯片的位置,信号沿既有导线引出。这就是为什么团队走的是「单点、三轴」而不是「多点、阵列」:不是没想过铺一片传感器,而是临床场景只允许一颗。这个约束反过来定义了数据的形状——每一个位置只有三个通道,想让模型看到更多空间信息,只能靠多个心动周期的时间上下文,或者靠多个动物之间的迁移。
1.2 三条常见的错误期待
第一条,期待它是「心震图的大规模替代」。 心震图(seismocardiography)测的是胸骨表面的振动,属于体表信号,可以用贴片或手持设备采集,因此天然适合穿戴场景。这个库测的是心外膜,属于植入场景。两者在物理链路上差着胸壁这一层,频率响应、干扰结构、可采集的人群都不同。拿它去训练一个胸骨贴片模型,等于让模型先学会一个它永远见不到的信号。
第二条,期待它是「可以泛化的心功能数据集」。 46 只动物、5 个实验系列、单一机构、统一的麻醉与开胸方案。这个规模足以支撑方法学验证,也就是「在受控条件下这个方法能不能成立」,但不足以支撑泛化 claim。任何以「跨物种」「跨个体」为卖点的结论,都需要额外的外部数据。
第三条,期待它开箱即用地带标签。 数据包里只有信号、物种、实验系列、动物编号、干预类型五个元数据字段。主动脉瓣开闭的参考标签在配套的 GitHub 仓库里,是按左室压微分的极大值与极小值定义的,需要另外下载、另外对齐。把数据包当完整监督数据集用,第一步就会卡住。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 验证加速度信号能否定位瓣膜事件 | 三轴加速度与左室压严格同步,参考标签可按官方定义重建 | 够,这正是它被建出来的用途 |
| 训练一个心音/心振事件检测模型 | 289 段带参考标签的短记录 | 可做原型,规模不足以训练大模型 |
| 研究加速度与压力的耦合关系 | 两路信号逐点同步,采样率一致 | 够,且是它最干净的用法 |
| 做人体可穿戴算法的外部验证 | 无人体记录,无体表信号 | 不够,链路完全不同 |
| 评估跨物种差异 | 犬与猪各自的干预谱,可分层比较 | 可以做探索,样本量偏小 |
| 长时程趋势或昼夜节律 | 单段最长 30 秒 | 不够,连一分钟的连续段都没有 |
| 心衰分型、预后预测 | 无随访、无结局、无临床分期 | 不够,这是纯信号库 |
| 传感器融合与姿态解算 | 三轴加速度,但重力已滤除 | 做不了姿态,重力分量已被减去 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你在做植入式心功能监测,需要一个公开的基准来证明算法有效 | 提供与导管压力同步的心外膜加速度,参考标签可复现 | 先按 §4.4 的标签链重建真值,再固定动物级划分跑基线 |
| 你在做心音或心振的事件检测,苦于没有干净的源信号 | 心外膜信号几乎不含胸壁低通与呼吸干扰,适合当「上限参考」 | 把它当上界,再在体表数据上看掉多少,差距就是胸壁的代价 |
| 你在验证一条从加速度反推压力波形的思路 | 三轴加速度与左室压逐点对齐,是最直接的一对一映射 | 注意压力单位未在字段名中声明,需从原始文献确认标定 |
| 你要做跨物种的生理信号迁移 | 犬与猪在同一套流程下采集,干预谱部分重叠 | 用重叠的基线、缺血、多巴酚丁胺三组做配对,其余组不可比 |
| 你在教生物医学信号处理,需要一个多通道同步的小数据 | 289 个 JSON,单个约 1.5 MB,读进来就是数组 | 用 §5.4 的代码,一节课就能跑通读取、滤波与分段 |
| 你想评估麻醉与开胸对心功能指标的影响 | 库内有开胸与闭胸两组猪的记录,可做粗略对照 | 注意闭胸组只有三类干预,且动物不配对 |
1.5 一句话判断
它不是「更小的心电库」,而是一台校准过的显微镜:把传感器放到信号源头上,看清机械事件在这一个通道里到底长什么样;至于这个长相能不能搬到胸壁上、搬到人身上,是下一个问题。
1.6 不适合谁:四条边界
不适合拿它做人体算法的训练集。 库内零人体记录。任何声称「在 cardiac-accel 上训练、在人体上测试」的工作,测试集一定来自别处,训练集与测试集之间隔着物种、麻醉、开胸状态三重差异。这个差距不是靠数据增强能填平的。
不适合拿它做长时程或趋势分析。 单段 5 到 30 秒,平均 15 秒。这个长度够看清十几个心动周期,不够看清一次呼吸周期引起的基线漂移,更不够看清术后几天的心功能演变。库的设计目标就是短片段对齐,不是连续监护。
不适合拿它做无监督预训练的主料。 289 段、46 只动物、总体积几百兆。这个体量在今天的自监督学习里连一个像样的预训练集都算不上,模型两三轮就会把这几十只动物记熟。
不适合把它当「原始数据」做信号处理研究。 官方明确说数据已经重采样到 500 Hz,不再是原始格式;重力分量也用三秒窗的滑动平均减掉了。想研究原始噪声特性、想做到 500 Hz 以上的频谱分析、想做姿态解算,都得回到原始采集,而这个库不提供。
§2 数据构成与规格
2.1 从一只动物到一个 JSON 文件
目录是四层。第一层 accelerometer_data,第二层是实验系列代号,第三层是动物编号,第四层是干预名,最里面是文件。系列代号有五个:AP、MP、MKCMS 是猪的三个系列,MK、MV 是犬的两个系列。动物编号带系列前缀,比如 AP106、MKCMS04、MV13。干预名用小写英文,比如 baseline、crt、lbbb、ischemia。
文件名把三层信息压进一个字符串:AP106_baseline_b_000.json 拆开是动物 AP106、干预 baseline、一个未在官方页面解释的字母 b、序号 000。同一只动物同一干预下的第二段就是 _001。这个 b 的含义官方没有说明,从命名习惯看可能是批次的标记,但库内没有对应字段,不要据此做推断。
有一个例外值得记住:MV 系列里有 9 个文件没有干预子目录,直接躺在动物目录下,比如 MV13/MV1302_baseline_b_000.json。写遍历脚本时如果假设路径深度固定为五段,这 9 个文件会被静默跳过(§5.6)。
2.2 字段/记录的完整字典
每个 JSON 只有十个键,五个是标量,五个是等长数组。
| 字段 | 类型 | 含义 | 取值示例 | 备注 |
|---|---|---|---|---|
experiment_name |
字符串 | 实验系列代号 | AP |
五个取值,对应五个系列 |
animal_species |
字符串 | 物种 | pig / dog |
英文小写 |
sample_rate |
浮点 | 采样率 | 500.0 |
全部为 500,浮点写法 |
intervention |
字符串 | 干预类型 | baseline |
与目录名一致,闭胸子集带后缀 |
identifier |
字符串 | 动物编号 | AP106 |
同一动物的多条记录共用 |
acc_x |
浮点数组 | 纵向加速度 | 0.7012… |
单位 g,已去重力 |
acc_y |
浮点数组 | 环向加速度 | 0.1782… |
单位 g,已去重力 |
acc_z |
浮点数组 | 径向加速度 | -0.0471… |
单位 g,已去重力 |
lvp |
浮点数组 | 左心室压力 | 连续压力曲线 | 单位在字段名中未声明 |
ecg |
浮点数组 | 心电 | 三导联之一 | 部分记录缺失或为空 |
只有这十个键,没有时间戳数组,也没有通道名列表。时间轴要自己按 sample_rate 生成,三轴顺序要自己按 x、y、z 记住。这是它与 WFDB 格式最大的差别:没有头文件声明单位、增益、导联名,一切隐含在官方文档的散文里。
2.3 一条记录的完整解剖
读一个文件,看它的键、长度与派生量。
import json
import urllib.request
URL = ("https://physionet.org/files/cardiac-accel-canine-porcine/1.0.0/"
"accelerometer_data/AP/AP106/baseline/AP106_baseline_b_000.json")
with urllib.request.urlopen(URL, timeout=60) as f:
rec = json.load(f)
for k, v in rec.items():
if isinstance(v, list):
print(f"{k:>15} 数组 长度 {len(v)}")
else:
print(f"{k:>15} 标量 {v}")
fs = float(rec["sample_rate"])
print("时长(秒)", len(rec["acc_x"]) / fs)
输出会告诉你五件事。第一,五个数组等长,都是 14932 个点;第二,按 500 Hz 折算,这一段是 29.86 秒,落在官方所说的 5 到 30 秒区间的上沿;第三,加速度数值的量级在正负一之间,符合 g 单位;第四,压力数组的量级是几十到一百多,符合毫米汞柱的常见范围,但字段名没有写单位;第五,identifier 是 AP106 而不是文件名全串。
这一段就是 §4.3 的案例里要展开的那条记录。它之所以适合当解剖样本,是因为它处在系列里最普通的组合上:猪、基线、开胸、单文件、五通道齐全。
2.4 干预谱与记录数的两个口径
官方把干预按物种分成两张清单,每项给出动物数(A)与记录数(S)。犬侧九类:
| 干预 | 动物数 A | 记录数 S | 做法 |
|---|---|---|---|
| 基线 baseline | 19 | 34 | 不做额外干预,记录稳态 |
| 右室起搏 rvp | 10 | 11 | 起搏右室,改变激动顺序 |
| 多巴酚丁胺 dobutamine | 4 | 8 | 药物增强收缩力 |
| 缺血 ischemia | 3 | 4 | 临时夹闭左前降支近段 |
| 左束支阻滞 lbbb | 17 | 25 | 射频消融左束支 |
| 双室起搏 crt | 11 | 38 | 心脏再同步治疗 |
| 左束支阻滞加多巴酚丁胺 lbbbdob | 2 | 2 | 两种干预叠加 |
| 左束支阻滞加缺血 lbbbisc | 3 | 3 | 两种干预叠加 |
| 左束支阻滞加补液 lbbbloading | 2 | 5 | 两种干预叠加 |
猪侧十一类:
| 干预 | 动物数 A | 记录数 S | 做法 |
|---|---|---|---|
| 基线 baseline | 25 | 25 | 不做额外干预 |
| 肾上腺素 adrenaline | 14 | 14 | 静注肾上腺素 10 mg |
| 艾司洛尔 esmolol | 13 | 13 | 静注β受体阻滞剂 100 mg |
| 硝普钠 niprid | 13 | 13 | 静注血管扩张剂 0.1 mg |
| 缺血 ischemia | 3 | 3 | 夹闭左前降支近段 |
| 补液 loading | 12 | 12 | 容量负荷 |
| 闭胸补液 loading-closed-chest | 9 | 25 | 闭胸状态下补液 |
| 闭胸放血 unloading-closed-chest | 9 | 18 | 闭胸状态下减少容量 |
| 闭胸基线 baseline-closed-chest | 7 | 8 | 闭胸状态下记录稳态 |
| 多巴酚丁胺 dobutamine | 3 | 3 | 药物增强收缩力 |
| 缺血加多巴酚丁胺 ischemiadob | 3 | 3 | 两种干预叠加 |
把两张表逐项相加,犬侧得 130,猪侧得 137,合计 267。但官方摘要与论文摘要都写 289 段,其中犬 130 段、猪 159 段。犬侧两者完全吻合,差额 22 段全部落在猪侧。
再看官方文件清单:SHA256SUMS.txt 里共 289 个 JSON,按系列拆是 MV 111、MKCMS 75、AP 58、MP 26、MK 19;按物种拆正好是犬 130、猪 159。继续往下拆到干预目录,猪侧的 ischemia 目录有 25 个文件,而上表写的是 3。
于是存在两个口径。口径 A 是官方干预表:猪缺血 3 段,合计 267。口径 B 是官方文件清单:猪缺血目录 25 个文件,合计 289。差额 22 段,官方没有说明哪一边需要修正,也没有说明多出来的缺血记录属于哪批动物。写论文时如果要报「猪缺血有多少段」,必须注明取的是哪个口径。
| 口径 | 来源 | 犬 | 猪 | 合计 |
|---|---|---|---|---|
| A:干预表逐项相加 | 官方页面 Data Description | 130 | 137 | 267 |
| B:文件清单逐目录计数 | 官方 SHA256SUMS.txt | 130 | 159 | 289 |
| 差额 | 官方未说明 | 0 | 22 | 22 |
2.5 与同类资源的字段差异
| 资源 | 传感器位置 | 对象 | 采样率 | 每条时长 | 标签 |
|---|---|---|---|---|---|
| 本库 | 心外膜(缝合) | 犬、猪 | 500 Hz | 5–30 秒 | 库外,瓣膜事件 |
| CEBSDB | 胸骨表面 | 人 | 5 kHz | 数十秒 | 无事件标签 |
| 常规心电库 | 体表电极 | 人 | 250–1000 Hz | 10 秒至数小时 | 心搏、节律 |
| 心音库 | 胸壁听诊区 | 人 | 数千赫兹 | 数秒 | 心音成分 |
| 大鼠血压库 | 动脉插管 | 鼠 | 100 Hz | 120 秒 | 无 |
这张表想说明的是:本库在「传感器离信号源的距离」这个维度上几乎站在极端,换来的代价是对象只能是动物。任何跨库拼接都要先想清楚,你拼的是同一类物理量,还是同一类问题。
2.6 五个实验系列的分工
| 系列 | 物种 | 动物数 | 记录数 | 主要干预 |
|---|---|---|---|---|
| AP | 猪 | 10 | 58 | 基线、肾上腺素、艾司洛尔、硝普钠、缺血、补液 |
| MP | 猪 | 6 | 26 | 基线、缺血、补液为主的方案 |
| MKCMS | 猪 | 11 | 75 | 闭胸补液、闭胸放血、闭胸基线 |
| MK | 犬 | 3 | 19 | 基线、起搏、缺血等 |
| MV | 犬 | 16 | 111 | 基线、左束支阻滞、双室起搏、多巴酚丁胺 |
系列代号不是缩写的组合,而是五个独立课题的代号。官方只说明 AP、MP、MKCMS 是猪,MK、MV 是犬,没有展开每个字母的含义。使用时的实际意义只有一个:系列是天然的分组单位,同一系列内的动物共享手术方案、设备批次与操作团队,跨系列比较会同时引入这些差异。
系列之间的体量很不均衡。MV 一个系列贡献了 111 段,占全库近四成;MK 只有 19 段,不到百分之七。如果直接按记录求平均,任何指标都会被 MV 主导,而 MV 恰好是干预种类最多的犬系列,基线记录只占其中一小部分。稳妥的做法是先按动物求平均,再按动物等权汇总,这样每只动物的权重相同,系列规模不会变成隐形的调味勺。这一点在做「犬与猪对比」时尤其重要,因为两边的记录数相差近三十段,不校正就会把「哪种干预更多」误读成「哪个物种更怎样」。
§3 它是谁的数据:一条起搏导线带出来的实验
3.1 贡献者与机构
| 角色 | 姓名 | 单位 |
|---|---|---|
| 第一作者 | Ali Wajdan | 奥斯陆大学医院干预中心、奥斯陆大学信息系 |
| 共同作者 | Tollef Jahren | 奥斯陆大学信息系 |
| 共同作者 | Manuel Villegas-Martinez | 奥斯陆大学医院干预中心、奥斯陆大学临床医学研究所 |
| 共同作者 | Magnus Krogh | 奥斯陆大学医院干预中心、奥斯陆大学信息系 |
| 共同作者 | Faraz Hameed Khan | 奥斯陆大学医院外科研究所 |
| 共同作者 | Andreas Espinoza | 奥斯陆大学医院干预中心 |
| 共同作者 | Per Steinar Halvorsen | 奥斯陆大学医院干预中心、临床医学研究所 |
| 共同作者 | Hans Henrik Odland | 奥斯陆大学医院心内科与小儿心内科 |
| 通讯级作者 | Ole Jakob Elle | 奥斯陆大学医院干预中心、奥斯陆大学信息系 |
| 通讯级作者 | Espen W. Remme | 奥斯陆大学医院外科研究所与干预中心 |
十位作者,三个单位:干预中心、信息系、外科研究所。这是一个典型的「工程加生理」组合,不是临床流行病学团队。这个构成决定了数据的形状:通道少而精,同步严格,样本量小,干预条件控制得比真实世界严得多。
3.2 时间线
| 时间 | 事件 |
|---|---|
| 2019 年 | 团队发表左束支阻滞室间隔运动的影像学研究,建立动物模型基础 |
| 2020 年 | 用同一批心外膜加速度数据做前负荷估计,发表于 IEEE TBME |
| 2020 年 | 提出用瓣膜事件重建左室压力曲线与压力-位移环,发表于 Scientific Reports |
| 2022 年 | 用深度网络检测主动脉瓣开闭,发表于 IEEE JBHI |
| 2022 年 9 月 | 数据目录在 PhysioNet 上建立 |
| 2022 年 12 月 | 许可与校验文件定稿 |
| 2023 年 1 月 5 日 | 1.0.0 版正式发布 |
从时间线能看出一个关键点:这个库不是为发布而采的,是为四篇论文采的,发布是副产品。这解释了为什么干预谱这么杂、为什么没有统一的动物元数据、为什么部分记录缺心电——它继承的是多个课题各自的采集习惯,只在最后统一了采样率与目录结构。
3.3 传感器与导管的物理配置
| 项目 | 内容 |
|---|---|
| 加速度计型号 | MPU9250(InvenSense,圣何塞) |
| 贴附方式 | 缝合于左心室心尖前壁心外膜 |
| x 轴 | 纵向,正向指向心尖 |
| y 轴 | 环向,正向指向左室侧壁 |
| z 轴 | 径向,正向向外 |
| 压力导管 | MPC-500 导管尖端微压计(Millar Instruments,休斯敦) |
| 压力标定 | 官方写明为已校准 |
| 心电 | 三个胸前导联 |
| 原始采样率(犬) | 650 Hz 或 1000 Hz |
| 原始采样率(猪) | 250 Hz 或 500 Hz |
| 入库采样率 | 统一 500 Hz |
| 重力处理 | 三秒 Tukey 窗滑动平均,余弦比例 0.5 |
| 幅值标定 | 标定为 g 单位并归一化 |
三个轴的正方向定义不是随便写的,它决定了同一段波形在不同动物之间能不能比较。纵向轴对着心尖,意味着心室长轴缩短时该轴读数为正;环向轴对着侧壁,意味着心室扭转时该轴有响应;径向轴朝外,意味着室壁增厚时该轴有响应。做特征工程时按这三个物理含义分组,比按 x、y、z 三个字母分组更有解释力。
3.4 伦理许可与利益冲突
三类实验方案分别获得挪威食品安全局的批准,批准号 17644(犬)、8628(猪)、9303(猪)。官方写明全部实验遵循挪威关于动物实验的法规。
利益冲突段落值得单独读一遍。两位作者是「用于评估心功能的加速度计技术」的专利持有人,四位作者是一家商业化该技术的公司 Cardiaccs A/S 的股东。这不影响数据本身的可用性,但影响你引用它时的措辞:把它当作「该技术路线的可行性证据」是合适的,把它当作「独立第三方验证」就不合适。数据集页面把这段写在显著位置,引用时照抄即可。
§4 它最独特的东西:贴着心肌的三轴
4.1 为什么贴壁信号不可替代
从心脏到体表,振动要穿过心包、肺、胸膜、胸壁肌肉、皮下脂肪和皮肤。每一层都是一次低通滤波:肺是含气组织,对高频振动几乎全反射;脂肪与肌肉的吸收随频率上升;皮肤与电极之间的接触阻抗又把最后的动态范围压了一道。等信号到达胸骨表面,几百赫兹以上的成分已经所剩无几。
这不仅是幅度问题,更是信息结构的问题。在体表心音图里,主动脉瓣关闭产生第二心音,它的分裂、强度、时限都受呼吸与体位影响;而同一个事件在心外膜加速度上,表现为一个几毫秒宽的冲击,前后文干净。用体表信号做事件检测,模型学到的一部分是生理,一部分是耦合条件;用心外膜信号做同样的事,模型学到的更接近事件本身。
这就是为什么这个库值得存在,即使它只有 46 只动物。它提供的不是更多样本,而是一个更少干扰的观测点。任何在体表数据上做事件检测的研究,都可以用它来估计「如果传感器足够近,性能上限在哪里」。这个上限不是终点,但它能把「信号不够好」和「方法不够好」这两类失败分开。
反过来也要防止把「贴壁」直接等同于「更真」。缝合本身改变了局部的力学边界:传感器的封装质量会加载在室壁上,缝线的松紧决定了耦合刚度,心包打开之后心脏周围从液体与心包的包裹变成与空气、纱布和牵引器接触。这些变化对低频段的影响可能比对高频段更大。所以贴壁信号的「干净」是有条件的——它干净在传导路径短,不干净在边界条件被手术改变过。做跨动物比较时,缝合位置与松紧的差异会以增益差异的形式出现,这一点在官方文档里没有量化,只能靠数据自己显形。
4.2 三个轴的解剖含义
| 轴 | 方向 | 主要响应 | 典型干扰 |
|---|---|---|---|
| acc_x | 纵向,向心尖为正 | 心室长轴缩短、房室平面位移 | 呼吸引起的整体位移 |
| acc_y | 环向,向侧壁为正 | 心室扭转、周向缩短 | 传感器缝合角度偏差 |
| acc_z | 径向,向外为正 | 室壁增厚、径向运动 | 心包液与周围组织碰撞 |
三个轴的用法不是平均也不是拼接。多数研究会把三轴当作三个独立通道送进模型,让网络自己学权重;也有研究只取径向轴,理由是径向运动与容积变化关系最直接。两种做法都合理,但比较结果时必须说明用的是哪一种,因为只取一轴的性能通常明显低于三轴。
还有一个容易被忽略的点:传感器的缝合角度在不同动物之间不可能完全一致。x 轴「指向心尖」是一个大致约定,实际偏差可能有一二十度。这会稀释轴向特征的可比性,也让「跨动物迁移」比「同一动物内跨时间迁移」难得多。
4.3 案例:AP106 的基线记录
拿 AP106 这条基线记录走一遍完整链路,能看清这个库的结构。它的路径是 accelerometer_data/AP/AP106/baseline/AP106_baseline_b_000.json,属于 AP 系列、猪、开胸、基线,是该动物该干预下的第 0 段。
文件里五个数组都是 14932 点,采样率 500 Hz,折合 29.86 秒。窗口覆盖的是一段稳定节律下的连续记录,没有起搏、没有给药、没有夹闭,正好适合当「干净参考」。三轴幅值都在正负一 g 的量级,径向轴的峰峰值通常大于另外两轴,这与径向运动直接对应室壁增厚相符。
这条记录能说明三件事。第一,官方说的「平均 15 秒、最长 30 秒」不是均匀分布,接近上限的段确实存在。第二,五个通道严格等长,说明采集是同一时钟下的同步采样,不需要做重采样对齐。第三,identifier 只到动物级,所以一条记录的身份要靠「动物编号 + 干预 + 文件名」三者共同确定,任何单独一个都不唯一。
后面 §5.4 会用它演示读数组,§7.2 会用它说明标签链的误差来源。一条普通记录被反复引用,比抽象地讲结构更清楚。
4.4 标注在库外:瓣膜事件的标签链
库内没有标签。官方页面指向配套 GitHub 仓库,那里存放论文所用的标注与复现脚本。标签的定义链条是这样的:
| 环节 | 做法 | 得到什么 |
|---|---|---|
| 压力测量 | 导管尖端微压计记录左室压 | 连续压力曲线 |
| 微分 | 对压力求时间导数 | dP/dt 曲线 |
| 取极值 | 收缩期最大值、舒张期最小值 | 两个时刻 |
| 赋义 | 最大值对应主动脉瓣打开,最小值对应关闭 | AVO 与 AVC |
| 逐搏对齐 | 用心电 R 峰定位心搏,再把事件挂到搏上 | 逐搏标签 |
| 训练 | 只用加速度信号,压力标签当监督 | 事件检测模型 |
这条链有三处会引入误差。压力导管本身的零点漂移是第一处;微分对噪声敏感是第二处,所以实际实现要先平滑;「dP/dt 极大值等于主动脉瓣打开」是一个生理近似,不是直接观测,它假设等容收缩期末压力上升最快的那一刻就是瓣膜开启的那一刻,而这个假设在缺血或心律失常时会松动。
理解这条链,才能理解论文里那些数字的含义。论文报告在 40 毫秒容差下,犬的 AVO 与 AVC 正确检出率是 98.9% 与 97.1%,猪是 98.2% 与 96.7%;正确检出的平均绝对误差在 7 到 10 毫秒之间。这些数字衡量的是「加速度信号能否复现压力微分定义的时刻」,不是「能否复现超声看到的瓣膜运动」。
4.5 边界条件:什么情况下它不再适用
当研究对象是人体时。 数据里没有一帧人体信号。跨物种的形态差异不只是尺寸缩放,还包括心率、心肌厚度、胸腔压力与自主神经张力。任何直接迁移都要重新验证。
当研究对象是闭胸状态时。 绝大多数记录是开胸的,心包被打开,胸腔与大气相通。这会改变心脏的外部约束,也会改变振动向外传播的路径。库内只有三类闭胸子协议(闭胸基线、闭胸补液、闭胸放血),共 51 段,覆盖不全。
当研究对象是长期演变时。 单段最长 30 秒,没有连续记录,没有随访。术后一周内的心功能变化,这个库完全看不到。
当研究对象是原始波形细节时。 数据已被重采样并去重力,原始的高频成分与直流分量都不在了。想做传感器层面的噪声建模,只能用别的数据。
§5 怎么拿到:从目录树到可训练数组
5.1 目录结构与下载面
| 层级 | 示例 | 数量 |
|---|---|---|
| 根 | accelerometer_data/ |
1 |
| 系列 | AP/ MP/ MKCMS/ MK/ MV/ |
5 |
| 动物 | AP106/ MV13/ |
46 |
| 干预 | baseline/ crt/ lbbb/ |
17 类 |
| 文件 | AP106_baseline_b_000.json |
289 |
根目录下另有两个文件:LICENSE.txt(ODC-BY 1.0 全文,约 20 KB)与 SHA256SUMS.txt(289 个 JSON 加许可文件的校验和)。没有 README,没有数据字典,所有说明都在项目主页上。
5.2 批量下载
官方给了两种方式,一种是递归抓取目录,一种是从公开的对象存储同步。
#-- 方式一:递归抓取(官方给出的 wget 命令)
wget -r -N -c -np https://physionet.org/files/cardiac-accel-canine-porcine/1.0.0/
#-- 方式二:从公开存储桶同步,速度通常更快
aws s3 sync --no-sign-request \
s3://physionet-open/cardiac-accel-canine-porcine/1.0.0/ ./cardiac-accel
#-- 下载完先校验,任何一条对不上就说明传输有问题
cd cardiac-accel && sha256sum -c SHA256SUMS.txt --quiet && echo CHECKSUM_OK
#-- 数一下记录数
find accelerometer_data -name '*.json' | wc -l
最后一行应该输出 289。如果不是,先别急着跑模型,先看是不是有目录被 -np 参数挡掉了。
5.3 用校验清单生成文件表
SHA256SUMS.txt 不只是校验用的,它本身就是最可靠的文件清单。拿它建表,比解析 HTML 目录页稳。
import urllib.request
from pathlib import Path
BASE = "https://physionet.org/files/cardiac-accel-canine-porcine/1.0.0/"
raw = urllib.request.urlopen(BASE + "SHA256SUMS.txt", timeout=60).read().decode()
rows = [ln.split(None, 1) for ln in raw.splitlines() if ln.strip()]
files = [(h, p) for h, p in rows if p.endswith(".json")]
Path("manifest.tsv").write_text("\n".join(f"{h}\t{p}" for h, p in files))
print(len(files), "个 JSON")
拿到 manifest.tsv 之后,物种可以从路径第二段推出来,动物编号从第三段取,干预则要判断路径深度:五段的取第四段,四段的从文件名里切。
5.4 读进数组
import json
import urllib.request
import numpy as np
BASE = "https://physionet.org/files/cardiac-accel-canine-porcine/1.0.0/"
def load(rel):
with urllib.request.urlopen(BASE + rel, timeout=60) as f:
d = json.load(f)
acc = np.stack([d["acc_x"], d["acc_y"], d["acc_z"]], axis=1)
lvp = np.asarray(d["lvp"], dtype="float32")
ecg = np.asarray(d.get("ecg", []), dtype="float32")
return acc, lvp, ecg, float(d["sample_rate"]), d["identifier"], d["intervention"]
acc, lvp, ecg, fs, aid, iv = load(
"accelerometer_data/AP/AP106/baseline/AP106_baseline_b_000.json")
print(aid, iv, fs, acc.shape, lvp.shape, ecg.shape)
t = np.arange(acc.shape[0]) / fs
print("首尾时间", t[0], t[-1])
注意 d.get("ecg", []) 这一句。部分记录没有心电键,直接取 d["ecg"] 会抛异常。这不是防御性编程的洁癖,是必须处理的真实情况——官方原话是「ECG was not available for all the recordings」。
5.5 重力分量与单位
官方说重力分量已经用三秒窗的滑动平均减掉,加速度标定为 g 并归一化。这意味着两件事:低于约三分之一赫兹的成分基本不在了,所以看不到呼吸基线与体位漂移;幅值以 g 为单位,1 g 约等于 9.8 米每二次方秒。
验证一下残余直流的量级,是读数据后的第一件例行检查。
import numpy as np
from scipy.signal import welch
f, pxx = welch(acc[:, 2], fs=fs, nperseg=2048)
band = (f >= 0.5) & (f <= 40)
peak = f[band][np.argmax(pxx[band])]
print(f"主频 {peak:.2f} Hz")
print(f"均值 {acc[:, 2].mean():.4f} g 标准差 {acc[:, 2].std():.4f} g")
如果某个轴的均值明显偏离零,说明那段记录的滑动平均窗与心动周期发生了共振,或者缝合后传感器有恒定偏置。这类记录在做幅值类特征前应当先剔除或单独校正。
滤波的副作用也值得算一遍。三秒窗的滑动平均近似一个截止频率在三分之一赫兹上下的高通,心率的一到三赫兹基频正好在通带里,所以心跳本身不会被削掉;但呼吸相关的基线调制落在零点二到零点五赫兹之间,正好压在过渡带上,会被部分削弱。这意味着想研究呼吸与心率耦合、或者想从基线漂移里提取呼吸相位,这个库已经不是合适的入口。要那类信息,得回到未滤波的原始记录,而官方明确说原始格式不再提供。所有预处理都有这种代价:它让 289 段能放在一起比,同时拿走了比较之外的那些东西。
5.6 六个最容易踩的坑
| 坑 | 表现 | 后果 | 处理 |
|---|---|---|---|
| 假设目录深度固定 | MV13 下 9 个文件少一层 | 静默丢 9 段 | 按路径段数分支处理 |
| 按文件随机划分 | 同一动物多段分散到两侧 | 指标虚高 | 按 identifier 分组 |
| 把 500 Hz 当原始采样率 | 对猪的记录做 250 Hz 以上分析 | 分析不存在的频段 | 先查系列对应的原始率 |
直接取 ecg 键 |
部分记录报 KeyError | 流程中断 | 用 get 并标记缺失 |
| 把三轴当同一物理量平均 | 三轴直接求均值 | 抵消掉主要成分 | 分轴处理或送进网络学权重 |
| 混用开胸与闭胸 | 闭胸子集混入训练 | 分布漂移 | 按干预名后缀分层 |
九段扁平文件这件事值得再说一句。它的存在说明目录结构不是机器生成的,而是人工整理的产物,整理时对 MV13 这一只动物采用了不同的层级。写健壮的遍历代码,比相信目录规整更省事。
§6 与库内词条的关系
6.1 关系图谱
库内最容易被混淆的是 CEBSDB,它是胸骨表面的心震图加心电同步记录,20 名健康志愿者各录三段,共 60 条,四通道 5 kHz 采样。名字里都有「加速度」,采集的物理量也确实是同一类,但两者在三个维度上完全不同。
| 维度 | 本库 | CEBSDB | 能否互换 |
|---|---|---|---|
| 传感器位置 | 心外膜,缝合于心肌 | 胸骨表面,贴附于皮肤 | 不能 |
| 对象 | 犬与猪,麻醉开胸 | 人,健康志愿者 | 不能 |
| 采样率 | 500 Hz | 5 kHz | 不能 |
| 单条时长 | 5 至 30 秒 | 数十秒 | 大致可比 |
| 通道 | 三轴加速度、左室压、部分心电 | 双导联心电、呼吸带、心震图 | 部分重叠 |
| 主要干扰 | 心包与周围组织、缝合角度 | 胸壁低通、呼吸、体位 | 不同 |
| 标签 | 瓣膜事件(库外) | 无事件标签 | 不同 |
两者的关系不是替代,而是同一条链路的两端。CEBSDB 回答「体表能测到什么」,本库回答「源头长什么样」。中间缺的一环是「人体心外膜」,而这一环在公开数据里基本不存在,因为需要植入手术。任何试图用其中一个去补另一个的研究,都要先把这一环的缺口说清楚。
心电类的库(INCART、MIT-BIH 系列)与本库的关系更远,只是共享「心血管生理信号」这个大类。大鼠血压库 bpssrat 在「动物模型 + 有创测量」这个维度上与本库同类,但测的是压力不是加速度,量纲都不同。
6.2 检索路径
| 你要找的东西 | 检索词 | 会落到哪里 |
|---|---|---|
| 同类的体表心振数据 | seismocardiography、SCG、CEBSDB |
§6.1 的关系表 |
| 心外膜加速度的其它来源 | epicardial accelerometer、cardiac motion |
本库与配套论文 |
| 动物有创血压 | bpssrat、rat blood pressure |
同属动物模型,量纲不同 |
| 无创血压估计的波形库 | PulseDB、cuffless blood pressure |
同为压力相关,但为人体的 PPG/ABP |
| 心脏超声的功能评估 | EchoNet、LVEF、echocardiography |
同为心功能,但为影像模态 |
| 起搏与再同步治疗 | CRT、LBBB、biventricular pacing |
本库的干预谱 |
6.3 与其他库的分工判据
| 任务 | 主力该用什么 | 本库的位置 | 原因 |
|---|---|---|---|
| 心音/心振事件检测的原型验证 | 体表心音库 | 上限参考 | 信号干净,可估性能天花板 |
| 可穿戴心功能监测 | 人体可穿戴数据 | 不适用 | 无人体、无体表 |
| 植入式传感器算法 | 本库 | 主力 | 公开数据里几乎没有同类 |
| 左室压无创估计 | 有创压力金标准库 | 可做方法验证 | 压力与加速度同步,但样本少 |
| 心衰分型与预后 | 电子病历加随访库 | 不适用 | 无临床结局 |
| 跨物种生理信号迁移 | 多物种库 | 辅助 | 只有犬与猪两个物种 |
| 传感器融合与姿态 | IMU 姿态库 | 不适用 | 重力已滤除 |
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
评价这个库时最常见的误判,是拿「数据量」当第一把尺子,然后得出「太小、不值得用」的结论。这把尺子在这里是错位的。它不是为训练大模型准备的语料,而是一次受控实验的原始记录:46 只动物、289 段、每一段都有导管压力的逐点对照。在这个用途上,289 段的价值不在于「多」,而在于「每段都有金标准」。
第二层误判是把「动物实验」当成「质量打折」。麻醉与开胸确实改变了生理状态,但它们同时消除了人体数据里最难控制的一堆变量:体位、活动、电极接触、依从性。这让它对「信号里有没有这个信息」这个问题给出了比人体数据更干净的答案。它的边界在推广,不在采集。
第三层误判是把重采样当成无损。500 Hz 的统一采样率是为了让 289 段能放在一起比较,代价是原始 1000 Hz 的犬记录被降了采样,原始 250 Hz 的猪记录被升了采样。前者丢了高频,后者没长出新信息。这两件事在 §7.3 会分开列。
7.1 五维评分
按 DAIMS 的常用维度打分,每项 1 到 5 分,评分针对「作为心外膜加速度算法研究数据」这个用途。
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 2 | 46 只动物、289 段,训练不足,验证够用 |
| 标注质量 | 3 | 有导管压力金标准,但标签在库外且依赖生理近似 |
| 任务适配 | 4 | 心外膜加速度的公开数据极少,替代品难找 |
| 文档完整 | 4 | 页面把传感器、采样、滤波、干预、伦理写得很细 |
| 可获取性 | 5 | 免注册、ODC-BY、体积小、有校验清单 |
合计 18 分(满分 25)。结构上它和许多小体量专业库一样:规模与标注拖后腿,适配与可获取性拉满。这个分布决定了它最合适的角色是「方法验证集」而不是「训练集」。
7.2 标签链的三段误差
标签不是观测出来的,是推出来的。三段误差要分开看。
| 环节 | 误差来源 | 量级 | 对下游的影响 |
|---|---|---|---|
| 压力测量 | 导管零点漂移、标定误差 | 官方未公布 | 整体平移,影响 dP/dt 的绝对值 |
| 微分 | 数值微分放大高频噪声 | 取决于平滑窗 | 极值时刻抖动,直接影响标签时刻 |
| 生理近似 | 假设 dP/dt 极值等于瓣膜开闭 | 数十毫秒 | 事件定义本身的系统偏差 |
第三段最容易被忽略。主动脉瓣的开启是一个过程,不是一个瞬间;压力上升最快的那一刻与瓣叶真正分离的那一刻之间,存在几毫秒到十几毫秒的差距。论文用 40 毫秒作为「正确检出」的容差,这个数值本身就说明事件时刻存在不确定性。§4.3 的案例里那条 29.86 秒的记录,如果按全局极值取点,只能得到一个 AVO 与一个 AVC;实际必须按心电 R 峰切成逐搏窗口,每一搏各取一次极值。
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 物种偏差 | 只有犬与猪 | 不能外推到人,也不能外推到其它实验动物 |
| 麻醉偏差 | 全部在麻醉状态下采集 | 自主神经张力被抑制,心率与收缩力不同于清醒状态 |
| 开胸偏差 | 绝大多数为开胸、心包打开 | 胸腔力学改变,振动传播路径改变 |
| 中心偏差 | 单一机构、五个课题 | 设备批次、缝合手法、操作团队都单一 |
| 传感器位置偏差 | 固定在左室心尖前壁 | 看不到其它室壁区域的事件 |
| 时长偏差 | 5 至 30 秒 | 无法做趋势、无法做长时程统计 |
| 通道缺失 | 部分记录无 ECG | 逐搏对齐前要先筛 |
| 重采样偏差 | 统一到 500 Hz | 原始 1000 Hz 的犬记录丢高频,原始 250 Hz 的猪记录无新增带宽 |
| 样本量偏差 | 46 只动物 | 一只动物的差异就能改变整体指标 |
| 产业关联 | 作者持有专利与股权 | 引用时需说明证据的独立性边界 |
7.4 外部验证矩阵
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 跨物种验证 | 在犬上训练,在猪上测试 | 两个物种在同一套流程下采集 | 心脏尺寸与心率差异会混进结果 |
| 跨干预验证 | 在基线上训练,在缺血上测试 | 检验模型对波形改变的鲁棒性 | 缺血本身改变了事件时刻的定义 |
| 跨手术状态验证 | 开胸训练,闭胸测试 | 检验胸腔力学变化的影响 | 闭胸样本只有 51 段,统计力弱 |
| 跨采样率验证 | 降采样到 250 Hz 再测试 | 模拟低功耗设备的带宽限制 | 只能单向做,升采样无意义 |
| 跨传感器验证 | 与体表心音或心震图对照 | 量化胸壁衰减的代价 | 需要额外的配对数据,本库没有 |
最后一行是这个库最难补的短板。它没有任何与体表信号同步采集的记录,所以「心外膜到胸骨之间衰减了多少」这个问题,只能靠间接比较两个不同研究的结果,而不能在同一次实验里直接量。
这也决定了引用方式。论文里的检出率是「方法在自家数据上的读数」,不是「这个库的官方基准线」。官方没有给出划分文件,没有固定训练测试集,也没有公布每一折的动物名单,所以任何两个人跑出来的数字都不必相同。复现时如果差得很多,先查三件事:标签是不是用同一套压力微分定义重建的,容差是不是 40 毫秒,划分是不是按动物而不是按文件。这三件事对结果的影响,通常比换一个网络结构更大。
7.5 它为何能持续:稀缺的是位置,不是数量
它不会更新,也没有扩版计划,但它会一直被引用,原因是它占着一个几乎没人能复现的位置:传感器直接缝在心肌上,同时有导管压力做金标准。要再造一份,需要一家愿意做动物实验、愿意把数据公开、并且有导管测压条件的机构,这个门槛比「再公开一批体表数据」高得多。只要植入式心功能监测这条路线还在推进,它作为「源头参照」的位置就不会被新库替代。
§8 生态位与历史
8.1 历史沿革
这个库的源头是一条专利路线。团队提出把微型加速度计做进临时起搏导线,在开胸手术中缝到心外膜,术后几天连续监测心功能。为了验证,他们从 2019 年起做了一系列动物实验:先用影像学确认左束支阻滞模型的室间隔运动异常,再用加速度信号估计前负荷变化,接着尝试用瓣膜事件重建压力曲线,最后用深度网络直接从加速度检测瓣膜开闭。
2022 年,团队把这些课题的数据抽取出来,统一重采样、统一去重力、统一目录结构,做成一个可供他人复用的集合。PhysioNet 在 2023 年 1 月 5 日发布了 1.0.0 版。整个过程没有基金驱动的采集计划,是一次「把已有实验数据整理公开」的典型操作。
8.2 与心震图、可穿戴心音的分野
心震图这条路走的是体表。传感器贴在胸骨,靠 MEMS 加速度计捕捉心脏冲击胸壁产生的微小振动,优点是无需植入、可用贴片或手机,缺点是被胸壁低通、被呼吸调制、被体位改变。过去十年这条路的进展主要集中在信号质量与姿态鲁棒性上。
本库走的是另一条:植入。它不追求可穿戴,追求的是信号源处的保真度。两者在临床落点上也不一样:心震图面向筛查与家庭监测,心外膜加速度面向术中与术后重症监护。
把两条路放在一起看,会发现它们其实是同一个问题的两端:一端问「能不能在体表把它测出来」,另一端问「它在源头到底是什么样」。中间那一环——人体心外膜——因为需要植入,公开数据几乎空白。本库用动物补上了这一环的一半。
落地场景也很具体。开胸心脏手术结束时,外科医生本来就要在心肌上缝临时起搏导线,术后如果心率不够或有传导阻滞,就靠这条导线起搏。导线在出院前从皮肤拔出,不需要二次手术。把加速度计做进这条导线,等于在不增加任何一次植入的前提下,拿到术后几天的心功能曲线。这条路径的吸引力不在于精度能超过导管,而在于它几乎零边际成本——导线已经在位,芯片只是多一颗。本库的实验设计正是照这个场景搭的:开胸、缝在心外膜、记录多个干预下的反应,而不是在体表做长期佩戴。
8.3 生态位
| 角色 | 主力粮仓 | 源头参照 |
|---|---|---|
| 典型用法 | 大规模训练、预训练 | 上限估计、机制验证、标签定义 |
| 需要的前提 | 数据量大、标签多 | 信号干净、有金标准、可解释 |
| 代表资源 | 体表心音与心电大库 | 本库、少量导管同步数据集 |
| 失败模式 | 标签噪声、域偏移 | 样本太少导致结论不稳 |
它坐在右边这一列。把它当粮仓用,会立刻遇到 46 只动物的天花板;把它当参照用,它的价值反而随使用者的模型变强而上升——模型越好,越需要一把精确的尺子来量它还差多少。
8.4 谁在用它
从公开文献看,使用者主要集中在三类:做植入式心功能监测的工程团队,把它当唯一可用的公开基准;做心音与心振事件检测的研究组,把它当干净信号的参照;做生理信号教学的单位,把它当多通道同步的小样本案例。第三类的用量不大,但它是这个库最稳定的使用群体,因为它不需要大样本,只需要结构清楚。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 算法研究者 | 跑通 §2.3 的读取,确认五个数组等长 | 按 §4.4 的链条重建标签,做动物级划分的基线 | 先定事件定义,再谈性能 |
| 器械工程师 | 看 §3.3 的轴向定义,核对三轴的物理含义 | 做降采样与带宽受限实验,估计低功耗设备的损失 | 不要用 500 Hz 以上的频段做结论 |
| 教学人员 | 用 §4.3 的案例讲一次完整链路 | 让学生自己做 R 峰切分与事件标注 | 讲清「开胸」与「动物」这两个前提 |
9.2 一条最短的可用流程
#-- 1. 同步全量数据(约 358 MB 解压后)
aws s3 sync --no-sign-request \
s3://physionet-open/cardiac-accel-canine-porcine/1.0.0/ ./cardiac-accel
#-- 2. 校验完整性
cd cardiac-accel && sha256sum -c SHA256SUMS.txt --quiet && echo CHECKSUM_OK
#-- 3. 确认记录数
find accelerometer_data -name '*.json' | wc -l
#-- 4. 生成文件清单,交给后面的 Python
awk '{print $2}' SHA256SUMS.txt | grep '\.json$' > manifest.txt
wc -l manifest.txt
import json
from pathlib import Path
paths = [p.strip() for p in Path("manifest.txt").read_text().splitlines() if p.strip()]
animals = sorted({p.split("/")[2] for p in paths})
print("动物数", len(animals), "记录数", len(paths))
#-- 按动物分组,避免同一颗心脏跨集合
cut = int(len(animals) * 0.7)
train_ids, test_ids = set(animals[:cut]), set(animals[cut:])
train = [p for p in paths if p.split("/")[2] in train_ids]
test = [p for p in paths if p.split("/")[2] in test_ids]
print("训练", len(train), "测试", len(test))
这段流程不读信号,只处理清单,几秒钟就能跑完。它的作用是先把「有哪些动物、怎么分」定下来,再去碰数组。顺序反过来,很容易在读完几百兆之后才发现划分泄漏。
9.3 引用方式
| 引用对象 | 内容 |
|---|---|
| 数据集 | Wajdan A, Jahren T, Villegas-Martinez M, et al. Epicardially attached cardiac accelerometer data from canines and porcines (version 1.0.0). PhysioNet. 2023. doi:10.13026/5xmr-zd88 |
| 原始论文 | Wajdan A, Jahren TS, Villegas-Martinez M, et al. Automatic Detection of Aortic Valve Events Using Deep Neural Networks on Cardiac Signals From Epicardially Placed Accelerometer. IEEE J Biomed Health Inform. 2022. doi:10.1109/jbhi.2022.3181148 |
| 平台 | PhysioNet 平台综述(2026,Nature Health),按官方页面 Cite 按钮生成 |
| 许可 | ODC-BY 1.0,署名即可,含商业使用 |
写论文时建议注明三件事:使用的版本号(1.0.0)、是否用了配套仓库的标签、划分是否按动物。第三点尤其重要,因为 289 段里同一只动物最多贡献 14 段,按文件随机划分的泄漏会非常严重。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,结构与事实由编辑核对 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面与官方文件清单 |
| 文件核验 | SHA256SUMS.txt、LICENSE.txt 与三个 JSON 样本经直接访问确认 |
| 记录数口径 | 官方干预表合计 267 与文件清单 289 的差异已在 §2.4 说明 |
| 论文信息 | 仅参考 Europe PMC 返回的摘要,未读全文 |
| 未核验内容 | 各干预的实际动物分配、缺失心电的记录数、原始采样率与系列的对应 |
| 图像 | 无配图;封面为生成式提示词,不含真实信号波形 |
| 免责 | 本文不构成临床或兽医建议;数据使用须遵守 ODC-BY 1.0 署名要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「这是人体的心震图数据」 | 犬与猪,传感器缝在心外膜上 | 官方标题写明 canines and porcines |
| 「它和 CEBSDB 可以互相替代」 | 一个体表一个心外膜,链路完全不同 | §6.1 的三维对比表 |
| 「500 Hz 是原始采样率」 | 原始为 250、500、650、1000 Hz,入库统一重采样 | 官方 Methods 段 |
| 「289 段等于干预表逐项相加」 | 表加得 267,文件清单 289,差 22 全在猪缺血 | §2.4 的两个口径 |
| 「每段都是 15 秒」 | 15 秒是平均值,范围 5 到 30 秒 | 官方 Abstract |
| 「数据包自带瓣膜事件标签」 | 标签在配套 GitHub 仓库,库内只有信号 | 官方 Data Description |
| 「三轴可以平均成一个通道」 | 三个轴对应三种不同的运动方向 | §4.2 的轴向表 |
| 「部分记录没有心电,是数据损坏」 | 官方明说采集时就没有,属设计内缺失 | Usage Notes 段 |
| 「开胸与闭胸的记录可以直接混用」 | 胸腔力学不同,须按干预后缀分层 | §5.6 的坑点表 |
| 「可以用它训练通用的心功能大模型」 | 46 只动物,两三轮就会记熟 | 文件清单的动物目录数 |
FAQ
Q1:这是人体数据还是动物数据?
动物。19 只犬与 27 只猪,共 46 只,全部在挪威奥斯陆大学医院的麻醉手术条件下采集。库内没有任何人类记录,也没有可用于人体部署验证的样本。
Q2:它和心震图数据库是一回事吗?
不是。心震图的传感器在胸骨或胸壁表面,测的是经过胸壁衰减的体表振动;这个库的传感器缝在心外膜上,测的是心肌壁本身的运动。信号源、频带、干扰结构都不同。
Q3:500 Hz 是原始采样率吗?
不是。犬的原始采样率是 650 或 1000 Hz,猪的是 250 或 500 Hz,入库时统一重采样到 500 Hz。原始 250 Hz 的猪记录在 500 Hz 文件里没有多出信息,原始 1000 Hz 的犬记录则损失了 500 Hz 以上频段。
Q4:主动脉瓣开闭的标签在哪里?
不在数据包里。官方页面指向配套 GitHub 仓库,那里有论文所用的左室压微分极值标注与复现脚本。数据包只给信号与干预类型,标签要另外取。
Q5:为什么官方干预表加起来不是 289 段?
逐项相加得 267,其中犬侧 130 与文件清单一致,差异全在猪侧:表里猪缺血写 3 段,清单里猪的缺血目录有 25 个文件。差额 22 段,官方没有解释哪一边需要修正。
Q6:训练集和测试集该怎么分?
按动物编号分。同一只动物往往贡献多段不同干预的记录,最多的单只贡献 14 段,按文件随机切分会把同一颗心脏放到两侧。46 只动物的量级下,建议用按动物的留一法或嵌套交叉验证。
Q7:能用它做压力波形的无创估计吗?
可以探索。三轴加速度与左室压逐点同步,是最直接的一对一映射。但压力单位没有写在字段名里,标注也依赖导管标定,做定量回归前要先确认单位与零点。
Q8:闭胸的那部分记录有多少?
三类闭胸子协议,分别是闭胸基线 8 段、闭胸补液 25 段、闭胸放血 18 段,合计 51 段,全部来自猪。官方把这三类称为开胸的例外,并在数据描述里显式标注 with closed chest。
Q9:数据量够训练深度学习模型吗?
做原型够,做训练不够。论文自己用的是嵌套交叉验证,原因写在摘要里:数据有限。289 段、46 只动物的规模,适合验证方法可行性,不适合从零训练大模型。
Q10:它支持商业使用吗?
支持。ODC-BY 1.0 允许商业使用,条件是署名。引用时写清数据集名称、版本、DOI 与来源,具体条款以 LICENSE.txt 全文为准。
Q11:为什么没有动物体重、年龄、性别?
官方没有公布这些字段,数据包里也没有对应键。46 只动物的个体信息只到编号一级,做跨动物归一化时只能靠信号本身。
术语表
| 术语 | 解释 |
|---|---|
| 心外膜 | 心脏最外层的膜,紧贴心肌,开胸手术中可直接缝合 |
| 心震图 | 记录心脏搏动引起体表微小振动的技术,传感器多在胸骨 |
| 三轴加速度 | 同时测量三个正交方向加速度的传感器输出 |
| g | 重力加速度单位,1 g 约 9.8 米每二次方秒 |
| 左心室压力 LVP | 左心室腔内的压力曲线,心功能评估的核心量 |
| dP/dt | 左室压对时间的导数,收缩期极大值反映收缩力 |
| AVO | 主动脉瓣打开,对应 dP/dt 极大值 |
| AVC | 主动脉瓣关闭,对应 dP/dt 极小值 |
| 等容收缩期 | 房室瓣已闭、主动脉瓣未开的阶段,压力快速上升 |
| MEMS | 微机电系统,微型传感器的主流工艺 |
| MPU9250 | 本库使用的三轴加速度计型号 |
| MPC-500 | 本库使用的导管尖端微压计型号 |
| Tukey 窗 | 两端平滑过渡的窗函数,用于抑制滤波边缘效应 |
| 滑动平均 | 用邻域均值估计慢变成分,本库用它估计重力 |
| 重采样 | 改变采样率,升采样不增加信息,降采样损失高频 |
| 奈奎斯特频率 | 可表示的最高频率,为采样率的一半 |
| 开胸 | 切开胸壁使胸腔与外界相通的手术状态 |
| 闭胸 | 胸壁完整的采集状态,本库仅三类猪的子协议 |
| LBBB | 左束支传导阻滞,本库用射频消融诱导 |
| CRT | 心脏再同步治疗,本库用双室起搏实现 |
| 缺血 | 本库通过临时夹闭左前降支近段诱导 |
| 多巴酚丁胺 | 增强心肌收缩力的药物 |
| 艾司洛尔 | 短效β受体阻滞剂,降低心率与收缩力 |
| 嵌套交叉验证 | 外层评估、内层调参的交叉验证方案,小样本常用 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 记录数 | 289 | 官方页面;SHA256SUMS 计数 | 官方页面与文件 |
| 动物数 | 46 | 官方页面;目录计数 | 官方页面与文件 |
| 犬 | 19 只 / 130 段 | 官方页面;目录计数 | 官方页面与文件 |
| 猪 | 27 只 / 159 段 | 官方页面;目录计数 | 官方页面与文件 |
| 单段时长 | 5–30 秒,均值 15 秒 | 官方 Abstract | 官方页面 |
| 采样率 | 500 Hz(统一后) | 官方 Methods;JSON 字段 | 官方页面与文件 |
| 原始采样率 | 犬 650/1000 Hz,猪 250/500 Hz | 官方 Methods | 官方页面 |
| 通道 | 三轴加速度、左心室压力、部分心电 | 官方 Abstract | 官方页面 |
| 传感器 | MPU9250 | 官方 Methods | 官方页面 |
| 压力导管 | MPC-500 | 官方 Methods | 官方页面 |
| 目录系列 | AP、MP、MKCMS、MK、MV | 官方 Data Description | 官方页面 |
| 干预类别 | 17 类目录名 | SHA256SUMS 路径 | 官方文件 |
| 体积 | 解压 358 MB,压缩 148 MB | 官方页面 Files 区 | 官方页面 |
| 单文件体积 | 约 1.5 MB | AP106 基线文件响应 | 官方文件 |
| 许可 | ODC-BY 1.0 | 官方页面;LICENSE.txt | 官方页面与文件 |
| 伦理批准号 | 17644(犬)、8628、9303(猪) | 官方 Ethics 段 | 官方页面 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 记录数、动物数、时长范围、采样率、传感器型号、压力导管型号、干预清单、伦理批准号、许可、体积,全部来自项目主页的 Abstract、Methods、Data Description、Ethics 与 Files 区,以及 SHA256SUMS.txt 与 LICENSE.txt。目录计数(系列、动物、干预、扁平文件)来自校验清单的路径解析。
第二层:论文摘要。 130 与 159 的分物种记录数、嵌套交叉验证、40 毫秒容差下的检出率与平均绝对误差,来自 Europe PMC 返回的 IEEE JBHI 论文摘要。摘要能支撑「官方这样报告」,不能支撑「换个数据集也成立」。
第三层:未核实。 每只动物的体重、年龄、性别,每条记录的原始采样率,缺心电的记录有多少条,闭胸与开胸动物是否配对,单段记录覆盖多少个心动周期。这些需要逐文件读取统计,超出本篇范围,凡涉及处只做定性表述。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | Epicardially attached cardiac accelerometer data from canines and porcines v1.0.0 | https://physionet.org/content/cardiac-accel-canine-porcine/1.0.0/ | 全部规模、结构、边界数据 |
| 2 | 该库的文件目录与校验清单 | https://physionet.org/files/cardiac-accel-canine-porcine/1.0.0/ | 目录计数与文件核对 |
| 3 | Wajdan 等,主动脉瓣事件自动检测,IEEE JBHI 2022 | https://doi.org/10.1109/jbhi.2022.3181148 | 分物种记录数与性能指标 |
| 4 | 配套代码与标签仓库 | https://github.com/TheInterventionCentre/aortic-valve-event-detection | 标签链与复现脚本 |
| 5 | Krogh 等,心外膜加速度估计前负荷,IEEE TBME 2020 | https://doi.org/10.1109/TBME.2020.2973279 | 历史沿革与用途背景 |
| 6 | Wajdan 等,瓣膜事件重建压力曲线,Scientific Reports 2020 | https://doi.org/10.1038/s41598-020-70814-4 | 方法学背景 |
| 7 | PhysioNet 平台综述,Nature Health 2026 | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 8 | CEBSDB 心震图数据库(库内对照) | https://physionet.org/content/cebsdb/ | §6.1 的体表对照 |
| 9 | 挪威食品安全局动物实验许可说明 | https://www.mattilsynet.no/ | 伦理框架背景 |
附录 D:任务代码
任务一:从压力微分重建瓣膜事件时刻
import numpy as np
def avo_avc(lvp, fs, win_s=0.01):
d = np.gradient(np.asarray(lvp, dtype="float64")) * fs
k = max(3, int(win_s * fs))
kernel = np.ones(k) / k
d = np.convolve(d, kernel, mode="same")
return int(np.argmax(d)), int(np.argmin(d)), d
avo, avc, dpdt = avo_avc(lvp, fs)
print("AVO 采样点", avo, "对应秒", avo / fs)
print("AVC 采样点", avc, "对应秒", avc / fs)
注意这段代码在整段上取全局极值,只适用于单个心动周期。§4.3 的案例那条记录接近 30 秒,包含十来个周期,必须先按心电 R 峰切窗,再在每窗内取极值。
任务二:按 R 峰切出逐搏窗口
import numpy as np
def r_peaks(ecg, fs):
ecg = np.asarray(ecg, dtype="float64")
thr = 0.5 * np.max(ecg)
above = (ecg > thr).astype(int)
rising = np.flatnonzero(np.diff(above) == 1)
peaks = []
for i in rising:
lo = max(0, i - int(0.05 * fs))
hi = min(len(ecg), i + int(0.05 * fs))
peaks.append(lo + int(np.argmax(ecg[lo:hi])))
return np.array(sorted(set(peaks)))
def beats(sig, peaks, fs, pre=0.3, post=0.5):
a, b = int(pre * fs), int(post * fs)
out = []
for p in peaks:
if p - a >= 0 and p + b <= len(sig):
out.append(sig[p - a:p + b])
return np.stack(out)
rp = r_peaks(ecg, fs)
x = beats(acc[:, 2], rp, fs)
print("心搏数", len(rp), "窗口形状", x.shape)
这段代码假设心电存在。对缺心电的记录,要么用加速度自身的周期性做峰值检测,要么直接跳过——这也解释了为什么 §5.6 把「直接取 ecg 键」列成一个坑。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 46 只动物,289 段,5 到 30 秒,500 Hz | 这四个数定义了一切用法与限制 |
| 2 | 传感器缝在心外膜上,不是贴在胸骨上 | 决定它与所有体表心振数据的区别 |
| 3 | 标签在库外,按左室压微分定义 | 不重建标签就没有监督信号 |
| 4 | 按动物划分,不按文件划分 | 同一颗心脏的多段记录会造成泄漏 |
| 5 | 官方干预表合计 267,文件清单 289 | 报数时必须说明取的是哪个口径 |
编辑说明
本文核验时间为 2026 年 10 月 28 日。核对方式为直接访问 PhysioNet 项目页与文件目录,确认 SHA256SUMS.txt、LICENSE.txt 可访问,并抽查了三个 JSON 文件的字段与数组长度;目录计数(五个系列、46 个动物、17 类干预、9 个扁平文件、289 个 JSON)由校验清单逐行解析得到。论文侧只检索了 Europe PMC 的摘要,未读全文。记录数存在两个口径:官方干预表逐项相加为 267,文件清单为 289,差额 22 全部落在猪缺血一项,官方未说明原因,本文按「并列两个口径、不下判断」处理,并在 §2.4、附录 A 与常见误读中各说明一次。未覆盖的内容包括:每只动物的体重年龄性别、每条记录的原始采样率、缺心电记录的确切条数、闭胸与开胸动物的配对关系,以及单段记录覆盖的心动周期数。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- cebsdb — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- tollet — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- icentia11k — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- cinc-2011 — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- butppg — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- cardiowave-portable — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- auricle-wearable-cv — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
- butqdb — 共享标签:生理信号 / 心电信号 / 可穿戴传感
- drivedb — 共享标签:生理信号 / 心电信号 / 可穿戴传感
- physionet-cinc-2017 — 共享标签:生理信号 / 心电信号 / 心血管疾病 / 可穿戴传感
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

