信息速览
先说结论:这份数据库的名字里没有「逐搏」两个字,但它确实是给逐搏分析准备的。PhysioNet 编号 bpssrat 的全称是 Blood Pressure in Salt-Sensitive Dahl Rats,收录的是 Dahl 盐敏感大鼠与它的同源导入系 SS.13BN 在高盐、低盐两种饲料下的连续动脉压波形。数据量很小——15 只动物、30 条记录、解压后 3.4 MB——小到足以在几秒钟内下载完,也小到不足以支撑任何群体水平的结论。
它的价值不在规模,在于它是一个极少数公开、带 DOI、许可清楚、且采样率足以做逐搏分析的大鼠动脉压库。人类动态血压与心电有百万级的公共资源,动物侵入式血压记录却大多停留在课题组硬盘里。这份库之所以值得单独写一篇,是因为它同时占据了三个稀缺位置:动物、动脉压、开放。
与此同时,它是跨物种信号处理错误最典型的发生地。人类心率六十余次,大鼠心率三四百次,同一个「低频」在两套生理系统里指的不是同一件事。照抄人类 LF/HF 频带去做大鼠的自主神经评估,是这份数据被误用最多的方式。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 官方名称 | Blood Pressure in Salt-Sensitive Dahl Rats |
| PhysioNet 编号 | bpssrat |
| 发布机构 | PhysioNet / MIT Laboratory for Computational Physiology |
| 数据提交者 | Bugenhagen SM、Cowley AW Jr、Beard DA(Medical College of Wisconsin) |
| 首次发布 | 2012 年 6 月 26 日,v1.0.0(至今仅此一版) |
| DOI | 10.13026/C20597 |
| 动物总数 | 15 只(Dahl SS 9 只、SS.13BN 6 只) |
| 记录数 | 30 条 WFDB 记录,另有 4 份多列原始文本 |
| 实验分组 | 2 品系 × 2 饲料(高盐 / 低盐)= 4 格 |
| 每格动物数 | SS 高盐 9、SS 低盐 9、SS.13BN 高盐 6、SS.13BN 低盐 6 |
| 信号通道 | 1 路,动脉血压 |
| 采样率 | 100 Hz |
| 单条样本数 | 12000 |
| 单条名义时长 | 120 秒(12000 ÷ 100) |
| 物理单位 | mmHg,增益 100 单位每 mmHg |
| 标注内容 | 无。没有心搏、事件、状态标注 |
| 全库体积 | 解压 3.4 MB |
| 许可 | Open Data Commons Attribution License v1.0 |
| 访问门槛 | 无。免注册、免签署使用协议 |
| 官方入口 | https://physionet.org/content/bpssrat/1.0.0/ |
§1 它要解决的具体麻烦
1.1 一句话结论:它把「压力反射好不好」压缩成了一个可以离线复算的短波形
压力反射是血压的负反馈回路:血压升高,颈动脉窦与主动脉弓的压力感受器放电增多,经孤束核传到延髓,交感张力下降、迷走张力上升,心率与血管阻力随之回落。这条回路是否灵敏,临床上一度用「血压变化对应的心率变化」来估计,比如所谓的压力反射敏感性指标。
在大鼠模型里研究这条回路,一直有个现实困难:能拿到的连续血压记录多是零散的、单次的、只存图不存数的。bpssrat 的意义在于,它把两位品系、两种饲料条件下的一批连续动脉压波形,连同采样率、增益、单位一起公开了出来,让一个完全不了解威斯康星那个实验室的人,也能在自己机器上重跑压力反射模型的拟合。
需要说清楚的是,它不是一个「压力反射标注集」。它给的只有压力波形本身。心率要从压力波形的搏动间期反推,压力反射敏感性要自己用序列法或频谱法去估,模型的增益参数要自己拟合。它把原材料放出来了,没有把加工结果放出来。
1.2 三条常见的错误期待
期待一:它是大中型动物血压库。 不是。15 只动物、30 条记录,合计名义时长一小时。想做大鼠血压的深度学习,这个体量连一个像样的训练折都撑不起来。它的定位更接近「一组可复算的经典实验数据」,而不是「一个训练集」。
期待二:它可以直接套人类 HRV/BPV 的指标。 这是最要命的一条。人类的 LF 带定在 0.04–0.15 Hz、HF 带定在 0.15–0.4 Hz,前提是人的心率在每分钟六十至八十次、呼吸在每分钟十二至二十次。大鼠心率三四百次、呼吸更快,整套频带的对应关系全部平移。不改频带直接算,得到的「LF/HF 比值」在生理上是一句空话。
期待三:它记录了饲料干预前后的完整时间过程。 也不是。高盐与低盐是两个独立条件,各有一批记录,但没有同一只鼠从低盐转高盐的连续追踪。要做时间过程分析,这份库给不了。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 一段能跑通的动物动脉压波形,用来验证读取与滤波流程 | 30 条 100 Hz 单通道记录,格式标准 | 够 |
| 逐搏间期序列 | 压力波形本身,搏动位置需自检 | 勉强够,需自己做峰值检测 |
| 收缩压、舒张压、脉压的逐搏序列 | 可以从波形中提取 | 够 |
| 血压变异性的时域指标(标准差、变异系数) | 可算,但受两分钟窗长限制 | 勉强够 |
| 频域 BPV(LF、HF 功率) | 需要自己决定频带,且窗长偏短 | 不够,除非重标定频带 |
| 压力反射敏感性的序列法估计 | 需要自发性血压变动,两分钟内变动有限 | 勉强够 |
| 麻醉与清醒状态的对照 | 无状态标注 | 不够 |
| 饲料干预前后的同鼠配对 | 同编号鼠有高低盐两份,可配对 | 够,但格内样本少 |
| 大鼠血压的正常参考范围 | 无汇总统计 | 不够,需自己算 |
| 跨物种频带的映射依据 | 无 | 不够,需查文献自行设定 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 要做动物血压的逐搏分析,但手里没有数据 | 提供 30 条标准格式的动脉压,免注册直接下载 | 先用一条记录跑通峰值检测,再扩到全库 |
| 在写动物生理信号的处理流程,需要一个公开可复现的例子 | 记录数少、结构简单,天然适合做流程演示 | 把处理脚本连同记录名一起写进附录,方便别人复现 |
| 想把人类 HRV 流程迁移到动物,先摸清坑在哪 | 提供了真实的「人类流程会算错」的样本 | 在同一批记录上并排跑人类频带与大鼠频带,比较差异 |
| 教生物医学信号处理,想要一个比教科书插图更真的例子 | 波形有真实的呼吸调制、有真实的个体差异 | 用 §4.3 的案例做课堂练习,让学生自己发现频带问题 |
| 做盐敏感高血压的机制研究 | 两种品系、两种饲料,正好对上原始论文的设计 | 只能作为辅助对照,主要结论还得靠自己的动物实验 |
| 想训练一个预测血压的模型 | 数据量太少,且没有长期趋势 | 换库。这个库适合验证,不适合训练 |
1.5 一句话判断
它是一份小而完整的动物动脉压样本,价值在「开放」与「可信」,不在「规模」;把它当训练集会失望,把它当流程校验集与教学素材会惊喜。
1.6 不适合谁:四条边界
第一,不适合做机器学习训练集的人。 15 只动物、半小时级的总时长,任何需要成千上万样本才收敛的模型,在这里都不可能得到有意义的结论。硬训出来的模型,学到的多半是某只鼠的个体波形特征。
第二,不适合想直接复现人类 HRV/BPV 指标的人。 频带不重标定,算出来的 LF/HF 比值没有生理含义。这一点在 §3 与 §4 里会反复展开,因为它比任何其他问题都更容易让整篇分析作废。
第三,不适合需要明确清醒或麻醉标签的人。 官方只写 telemetry,没有逐条的麻醉状态、行为状态、采集体位说明。如果你的分析必须区分这两类状态,这份库满足不了。
第四,不适合把结论外推到人类的人。 Dahl 盐敏感大鼠是高血压与压力反射功能障碍的模型动物,它的血压调节特性与人类有本质差别。在这份数据上得到的规律,可以启发人类研究,但不能直接搬。
§2 数据构成与规格
2.1 三层结构:四份文本、30 条记录、一份清单
bpssrat 的文件组织分成两条平行的路径,指向同一批数据。
第一条是原始文本路径。四个 .txt 文件,分别对应 SS 高盐、SS 低盐、SS.13BN 高盐、SS.13BN 低盐四个条件。每个文件内部是纯数字矩阵,一列一只动物、一行一个采样点,文件头用双斜杠注释写明了采样率与出处。这条路径的好处是直观——你可以用任何表格软件打开,一眼看到同组动物并排的波形。
第二条是 WFDB 路径。PhysioNet 把四份文本按列拆开,每只动物一个条件一条记录,生成 30 对 .dat 与 .hea 文件,再加上一份 RECORDS 清单。这条路径的好处是标准——只要装了 WFDB 工具箱,rdrecord 一行就能读,增益、单位、采样率都在头文件里。
两份数据的对应关系很直接:文本的第几列,就是记录名里编号的哪一号。SS_HS.txt 有九列,对应 sshs01 到 sshs09;SSBN13_LS.txt 有六列,对应 ssbn13ls01 到 ssbn13ls06。
| 层级 | 对象 | 数量 | 用途 |
|---|---|---|---|
| 第 1 层 | 条件文本文件 | 4 份 | 快速浏览、并排比对 |
| 第 2 层 | WFDB 记录 | 30 条 | 标准读取、逐条分析 |
| 第 3 层 | 清单文件 | 1 份 | 批量遍历 |
| 附带 | 校验和 | 1 份 | 下载完整性检查 |
2.2 字段/记录的完整字典
WFDB 头文件很短,一条记录的头文件只有三行。下面把每一行的每个字段拆开讲清楚,因为这份库没有独立的元数据表,所有元信息都藏在这三行里。
| 字段位置 | 名称 | 取值示例 | 含义 | 能拿来做什么 |
|---|---|---|---|---|
| 第 1 行 第 1 列 | 记录名 | sshs01 |
与文件名一致 | 作为主键 |
| 第 1 行 第 2 列 | 信号通道数 | 1 |
单通道 | 判断是否需要多导联处理 |
| 第 1 行 第 3 列 | 采样率 | 100 |
每秒 100 个样本 | 时间轴换算 |
| 第 1 行 第 4 列 | 样本数 | 12000 |
名义段长内的样本总数 | 时长换算 |
| 第 2 行 第 1 列 | 数据文件名 | sshs01.dat |
二进制波形文件 | 定位数据 |
| 第 2 行 第 2 列 | 存储格式 | 16 |
16 位整数 | 决定读取时用哪种解码 |
| 第 2 行 第 3 列 | 增益与单位 | 100/mmHg |
每 mmHg 对应 100 个整数单位 | 整数转物理量 |
| 第 2 行 第 4 列 | 有效位宽 | 12 |
12 位 ADC | 判断量化精度 |
| 第 2 行 第 5 列 | 零点偏移 | 0 |
A/D 转换的基线整数 | 转物理量时一并计算 |
| 第 2 行 第 6 列 | 首样本值 | 20189 |
该段第一个整数 | 校验读取是否正确 |
| 第 2 行 第 7 列 | 校验值 | 25801 |
全段整数的累加校验 | 与工具箱读数比对 |
| 第 2 行 第 8 列 | 块大小 | 0 |
0 表示不指定 | 一般可忽略 |
| 第 2 行 第 9 列 | 信号描述 | BP |
血压 | 唯一通道的名称 |
| 第 3 行 | 注释 | #SS rat 1, high salt diet |
品系、编号、饲料 | 唯一的条件说明 |
几个字段值得多说两句。
零点偏移这一列在不同记录里不一样,比如 sshs01 是 0,而 ssbn13hs01 是负数。这不是错误,它是每段数据各自的基线整数。转物理量时用的是「(原始整数 − 零点偏移)÷ 增益」,所以不能只看原始整数就下判断。
校验值这一列是这段整数序列的累加,PhysioNet 用它做完整性校验。自己写读取程序时可以用它来确认没有读错字节序。
注释行是这份库唯一的人可读的条件标注。它只写了品系、编号、饲料三件事,没写性别、周龄、体重、麻醉与否、采集体位。所有深一层的实验条件,都得回原始论文里找。
2.3 一条记录的完整解剖
以 sshs01 为例,从头文件到整数值到物理量,完整走一遍。
sshs01 1 100 12000
sshs01.dat 16 100/mmHg 12 0 20189 25801 0 BP
#SS rat 1, high salt diet
第一行说明:这是一条单通道记录,采样率 100 Hz,段内有 12000 个样本。
第二行说明:波形存在 sshs01.dat,用 16 位整数存储,每 mmHg 对应 100 个整数单位,有效位宽 12 位,零点偏移为 0,第一个样本的整数是 20189,全段校验值是 25801,块大小不指定,通道名是 BP。
第三行是注释:Dahl SS 株第 1 号鼠,高盐饲料。
按这套参数换算,第一个样本的物理值约为 20189 除以 100,即 201.89 mmHg。这个数在 SS_HS.txt 的第一行第一列可以原样找到,两边对得上。
#-- 读取一条记录并把整数还原成 mmHg
import wfdb
import numpy as np
rec = wfdb.rdrecord("bpssrat/1.0.0/sshs01")
bp = rec.p_signal[:, 0] #-- 单一通道,单位已是 mmHg
fs = rec.fs #-- 100
n = rec.sig_len #-- 12000
t = np.arange(n) / fs #-- 0 到 119.99 秒
print(fs, n, n / fs, bp.min(), bp.max())
读出来的 p_signal 已经做完了整数到物理量的换算,units 属性写着 mmHg。不需要再手动除增益,但要知道它做过这一步。
值得注意的一点:sig_len 是 12000,不一定等于原始连续采集的全程。PhysioNet 把它拆成单只动物记录时,取的是一个固定长度的段。这一点在 §5.1 会再讲一次,因为做频域分析时它直接决定你能看到多低的频率。
2.4 四个条件格的分布表
30 条记录正好排成 2×2 四格。格内动物数不一致,这是由原始实验的动物分配决定的,不是数据缺失。
| 品系 | 饲料 | 记录名前缀 | 动物数 | 记录数 | 原始文本 |
|---|---|---|---|---|---|
| Dahl SS | 高盐 | sshs |
9 | 9 | SS_HS.txt |
| Dahl SS | 低盐 | ssls |
9 | 9 | SS_LS.txt |
| Dahl SS.13BN | 高盐 | ssbn13hs |
6 | 6 | SSBN13_HS.txt |
| Dahl SS.13BN | 低盐 | ssbn13ls |
6 | 6 | SSBN13_LS.txt |
从这张表能读出两件事。
第一,SS 组比 SS.13BN 组多三只。这符合原始研究的设计逻辑:SS 是主模型,需要更大的样本量来观察盐负荷下的压力反射损害;SS.13BN 是染色体 13 的同源导入系,作为对照说明这种损害是否由 13 号染色体上的基因决定。样本量不对称是设计使然。
第二,同一编号的鼠在两种饲料下都有一条记录。sshs01 与 ssls01 都是 SS 株第 1 号鼠,只是饲料不同。这给了做配对分析的可能——虽然不能确定两次采集的时间先后与间隔。
每个文本文件的体积也有信息量。SS_HS.txt 是四份里最大的,因为它是九列;SSBN13_LS.txt 最小,因为是六列。文件体积直接反映了列数,没有别的秘密。
2.6 数据在手上时的几个实操事实
这一小节不列统计分布,只写几件拿到文件之后立刻会碰到的事,属于「结构」而非「规模」。
第一,文本文件的注释用的是 //,不是 #。 四份 .txt 的开头都有几行双斜杠注释,说明采样率与文献出处。用 pandas.read_csv 直接读会把这些行当成数据行而报错,需要 comment="//" 或先跳过固定行数。WFDB 头文件则用 # 开头写注释,两种格式的注释符号不一样,这在小脚本里最容易踩。
第二,文本与 WFDB 的数值口径一致。 文本里已经是 mmHg 的浮点数,WFDB 里是整数再除增益。两边最后得到的物理量相同,但中间精度不同:文本保留了三位小数,整数版受量化位宽限制。做高精度谱分析时,用文本可以少一层量化误差,不过百 Hz 采样下这点差异可以忽略。
第三,没有目录层级。 全部三十条记录平铺在同一个目录里,没有任何子目录。这意味着用 RECORDS 遍历时不需要处理路径拼接的层数问题,但也意味着不能靠目录名分组,品系与饲料只能从文件名前缀解析。
第四,校验和文件覆盖全部文件。 SHA256SUMS.txt 是四十几行,一行一个文件。下载后跑一次 sha256sum -c 就能确认完整,比逐条读头文件核对校验值快得多。这一点在批量下载脚本报错时特别有用——能立刻分清是网络问题还是解压问题。
| 实操事项 | 具体表现 | 建议做法 |
|---|---|---|
| 文本注释符号 | // 开头 |
读取时显式设 comment 参数 |
| 头文件注释符号 | # 开头 |
交给 WFDB 工具箱处理 |
| 数值精度 | 文本三位小数,整数版受位宽限制 | 高精度分析用文本 |
| 目录结构 | 单层平铺 | 分组靠文件名前缀 |
| 完整性校验 | 有 SHA256 清单 | 下载后跑一次校验 |
| 文件命名 | 品系加饲料加两位编号 | 按前缀区分四格 |
2.7 与同类资源的字段差异
把 bpssrat 放到生理信号库里比较,它的字段结构异常简单:一个通道、一个单位、一条注释。这种简单既是优势也是短板。
| 维度 | bpssrat | 人类动态血压库 | 人类心电库 | 大型动物遥测库 |
|---|---|---|---|---|
| 对象 | 大鼠 | 人 | 人 | 猪、犬、非人灵长类 |
| 通道数 | 1(动脉压) | 1–2(袖带压或动脉压) | 2–12 | 多通道 |
| 采样率 | 100 Hz | 数分钟一次 | 250–1000 Hz | 数百 Hz |
| 单条时长 | 120 秒 | 24 小时 | 数小时至数天 | 数天至数周 |
| 标注 | 无 | 有事件、有体位 | 有 QRS、有心律 | 视项目而定 |
| 动物/人数 | 15 | 数千至数万 | 数十至数万 | 数十至数百 |
| 许可 | ODC-By 1.0 | 常需申请 | 常需申请 | 多为内部 |
| 公开程度 | 完全开放 | 分级 | 分级 | 极少公开 |
这张表说明的是一件常被忽略的事:动物数据的「字段简单」不是因为采集粗糙,而是因为配套的元数据共享文化不成熟。人类数据库有成熟的元数据规范,动物实验室的数据往往只在论文方法段里写几句。bpssrat 的头文件只写三行,已经是相对规整的做法了。
§3 核心层 A:它的身份是「一篇建模论文的配套数据」,不是「一个通用血压库」
3.1 出题人与数据来源
这份数据不是为共享而采集的,它是为一篇论文而采集的,之后才被提交到 PhysioNet。
原始论文是 Bugenhagen SM、Cowley AW Jr、Beard DA 的 Identifying physiological origins of baroreflex dysfunction in salt-sensitive hypertension in the Dahl SS rat,2010 年发表于 Physiological Genomics 第 42 卷。研究的问题是:Dahl 盐敏感大鼠在高盐饲料下出现的压力反射功能障碍,生理机制是什么、遗传基础在哪里。
方法上,作者建立了一个压力反射心率控制的数学模型,用遥测得到的大鼠血压与心率数据去估计模型参数,再比较两种品系在两种饲料下的参数差异。
3.2 论文摘要给出的三条结论
论文摘要写得很克制,三条发现可以直接引用。
第一条,SS 大鼠在高盐饲料下出现选择性交感增益受损,而 SS.13BN 大鼠受到保护,没有出现这种受损。所谓「选择性」,指受损主要落在交感支路,副交感支路相对完好。
第二条,两种品系在高盐饲料下交感与副交感的偏移量都升高。这一条说明高盐的影响有一部分是两种品系共有的,不完全是 SS 特有的缺陷。
第三条,交感张力升高只出现在 SS 大鼠,SS.13BN 没有。这一条把品系差异落到了具体的调控量上。
摘要的结论段说,研究把压力反射控制系统的若干重要生理参数与染色体 13 联系起来,并初步识别了 SS 大鼠压力反射损害与高血压的可能机制。也就是说,这份数据的科学价值集中在「参数估计」这条线上,而不是「波形分类」。
3.3 为什么必须是这两种品系
Dahl 盐敏感大鼠是一个经典的高血压模型:给高盐饲料,血压上升;给低盐饲料,血压相对正常。它本身不是遗传改造动物,而是通过选择性繁育得到的高血压易感品系。
SS.13BN 是同源导入系。做法是把 Brown Norway 大鼠的 13 号染色体片段导入 Dahl SS 背景,得到一株除了这一小段之外遗传背景几乎与 SS 相同的动物。如果某个表型在 SS 上出现、在 SS.13BN 上消失,那么负责这个表型的基因很可能就在那段被替换的染色体上。
这套设计的巧妙之处在于控制变量:两种品系遗传背景高度一致,差异被压缩到一条染色体上。这是为什么摘要敢说「把参数与染色体 13 联系起来」,而不是泛泛地说「有遗传因素」。
3.4 身份对使用的三个约束
约束一:它的对照是「同源导入系」,不是「正常鼠」。 想用它建立正常大鼠血压参考值的人会失望——库里没有一株野生型或远交系正常大鼠。所有记录都来自高血压易感背景或它的导入系。
约束二:它的观测目标是「模型参数」,不是「波形特征」。 原始研究不关心波形长什么样,只关心从波形里估出来的增益、偏移、张力。如果用它做波形分类,原则上可以做,但那不是设计意图,任何「分类准确率」都要自己重新论证意义。
约束三:它的时间尺度服务于参数估计,不是长程监测。 两分钟一段的窗口,正好够拟合一个压力反射模型的一段闭环响应,但不够做昼夜节律、不够做长期趋势。用错尺度,结论会跑偏。
§4 核心层 B:质量与特色
4.1 设计上的三处巧思
第一处是「同编号跨饲料」的配对结构。 sshs01 与 ssls01 来自同一只鼠,这一对构成了最干净的同鼠对照。做统计时如果能按编号配对,个体差异会被部分消掉,饲料效应更容易显出来。可惜每格只有六到九对,配对能带来的检验效能提升有限,但方向是对的。
第二处是「两种品系」的遗传对照。 前文说过,同源导入系把遗传差异压缩到一条染色体。这在动物实验里是奢侈的设计,因为繁育导入系通常要十几代回交。
第三处是「双格式并存」。 文本与 WFDB 两种格式同时提供,看起来是冗余,实际上是降低了使用门槛。不做信号处理的人可以直接用表格软件看波形;做信号处理的人可以直接用工具箱读。这种「两种入口」的做法在小型数据库里不常见。
4.2 三处已知瑕疵
瑕疵一:段长与频域分析的矛盾。 两分钟的记录,做 0.1 Hz 的频谱分析时窗内只有约十二个周期,谱估计会很不稳。做更低频的成分几乎不可能。这是数据设计层面的限制,不是使用者的操作问题。
瑕疵二:元数据过薄。 头文件的注释只有三件事,性别、周龄、体重、麻醉状态、采集体位、采集时段全部缺失。做严格的动物实验复现时,这些信息缺一项就可能让复现失败。
瑕疵三:状态表述存在两个口径。 官方页面写 telemetry-based,这在动物实验里通常指植入式遥测、动物自由活动;但原始论文的方法细节在摘要里看不到,而不少二手资料把它说成麻醉状态下的插管记录。两种口径对结果解释影响很大——麻醉药会直接抑制压力反射,清醒与麻醉的血压变异性完全不是一回事。本文按官方口径写「遥测」,同时把这条不一致标出来。
4.3 案例:sshs01 与 ssls01 这一对
这一对是同一只 Dahl SS 株第 1 号鼠在高盐与低盐两种饲料下的记录,最适合拿来说明这份数据能做什么、不能做什么。
先看事实。两条记录都是 100 Hz、12000 个样本,头文件的第一个样本整数分别是 20189(高盐)与 11544(低盐)。按每 mmHg 100 个整数换算,高盐段的起点约为 201.89 mmHg,低盐段约为 115.44 mmHg。这是两个非常不同的压力水平,前者远高于大鼠的正常收缩压区间,后者落在更常见的范围内。
必须谨慎:单点首值不能代表整段的平均水平,波形的峰谷位置、采集起始的相位都会影响这个数。但两条记录在量级上的差别足够大,不会因为单点取值就消失。
再看用法。如果想知道「同一只鼠从低盐换到高盐,压力波形的逐搏波动是变大还是变小」,这一对就是最小可用的样本。做法是分别从两段波形里定位搏动峰,得到收缩压序列,再算序列的标准差与频谱。
再看陷阱。只拿这一对做频域比较,你会立刻遇到 §4.2 说的段长问题:两分钟的数据,用来估计 0.1 Hz 附近的功率,谱峰宽得几乎看不出形状。这时候很容易误以为是生理差异,实际上是估计误差。
最后看教学价值。这一对特别适合课堂演示「跨物种频带」这件事——把人类 LF/HF 的频带套上去算一遍,再把大鼠的频带套上去算一遍,两次结果往往不一致,甚至相反。学生亲眼看到同一段波形因为频带定义不同得出两种结论,比看十页教科书都管用。这个对比会在 §7.2 里再展开一次。
4.4 特色:一份「越用越知道它小」的数据
大多数数据集是越用越大,用的人越多、衍生数据越多、社区越活跃。bpssrat 相反,它是越用越知道你只能用到什么程度。
第一天你会觉得它够用:格式标准、读取简单、波形真实。
第一周你会发现它短:想做一个稍长一点的窗口分析,就得把同组的几条记录拼起来,而拼接本身就有讨论空间。
第一个月你会发现它薄:想写方法段,发现动物信息不全;想写讨论,发现没有状态标注;想写对照,发现没有正常鼠。
这种「越用越知道边界在哪」的体验,其实是小型经典数据集的共同特征。它们不假装自己是通用资源,它们就是一篇论文的原材料,能支撑的东西有限但扎实。
4.5 与「人类逐搏血压」这条线的质量对比
| 对比项 | bpssrat(大鼠) | 人类逐搏血压记录 |
|---|---|---|
| 采集方式 | 遥测 | 多为无创连续或动脉置管 |
| 采样率 | 100 Hz | 100–250 Hz |
| 心搏频率 | 每分钟约 300–500 次 | 每分钟约 60–90 次 |
| 单条时长 | 120 秒 | 数分钟至数小时 |
| 记录条数 | 30 | 数百至数万 |
| 状态标注 | 无 | 常含体位、活动、睡眠 |
| 频带定义 | 需按物种重标定 | 有成熟共识 |
| 外推价值 | 机制启发 | 直接临床 |
这张表里最关键的一行是「心搏频率」。它决定了后面所有的处理差异:逐搏序列采得密、单搏的时间间隔短、频带上限高。人类记录每秒一搏多,大鼠记录每秒五到八搏,同样的两分钟窗口,大鼠的搏数是人类的五倍以上。这意味着在同样的样本量下,大鼠的逐搏序列反而更长——但这是「长度上的长」,不是「时间上的长」,频谱分辨率仍然由秒数决定。
§5 核心层 C:取数与标准的逐搏流程
5.1 三条下载路径
bpssrat 不需要注册,不需要签协议,三条路径任选。
第一条是网页直接下载 ZIP,地址是 https://physionet.org/content/bpssrat/get-zip/1.0.0/,体积 3.4 MB。
第二条是 wget 镜像,官方给出的是 wget -r -N -c -np https://physionet.org/files/bpssrat/1.0.0/。这条路的好处是能断点续传,也能只挑需要的文件。
第三条是 AWS 命令行,官方给出的是 aws s3 sync --no-sign-request s3://physionet-open/bpssrat/1.0.0/ DESTINATION。免签名,适合脚本化拉取。
#-- 方式一:整库同步
aws s3 sync --no-sign-request s3://physionet-open/bpssrat/1.0.0/ bpssrat
#-- 方式二:只取清单与头文件,先看结构
curl -s https://physionet.org/files/bpssrat/1.0.0/RECORDS | head -5
curl -s https://physionet.org/files/bpssrat/1.0.0/sshs01.hea
#-- 方式三:直接下载单份原始文本
curl -LO https://physionet.org/files/bpssrat/1.0.0/SS_HS.txt
三条路径取到的内容一样。用 AWS 同步会在本地建一个 bpssrat 目录,里面直接是 1.0.0 的文件,不再套一层版本号。用 wget 镜像会保留 files/bpssrat/1.0.0/ 的路径结构。这点小事在写脚本时要注意,路径写错一层的报错往往很不好查。
5.1b 下载完成后应先做的三件核对
下载完不要急着跑分析,先花几分钟确认文件是完整的、读法是正确的。这三件事门槛很低,但能挡掉后面九成的「结果看起来怪」的排查时间。
| 核对项 | 怎么做 | 期望结果 | 对不上时说明 |
|---|---|---|---|
| 记录数 | 数 RECORDS 的非空行 |
三十行 | 下载不完整 |
| 采样率一致性 | 扫全部头文件第一行第三列 | 只有一百这一种取值 | 混入了其他数据集 |
| 样本数一致性 | 扫全部头文件第一行第四列 | 只有一万二这一种取值 | 记录被截断 |
核对的脚本在附录 D,直接跑就行。三个期望结果都能对上,说明这份库在你本地是干净的,后面所有的异常都只能来自算法或假设,不会来自数据本身。
5.2 读取一条记录并画出来
WFDB 工具箱是最省事的读法,rdrecord 一行解决。
#-- 读取并画一条记录
import wfdb
import matplotlib.pyplot as plt
rec = wfdb.rdrecord("bpssrat/1.0.0/sshs01")
bp = rec.p_signal[:, 0]
t = rec.fs and (range(rec.sig_len))
xs = [i / rec.fs for i in range(rec.sig_len)]
plt.figure(figsize=(10, 3))
plt.plot(xs[:1000], bp[:1000], lw=0.8)
plt.xlabel("time (s)")
plt.ylabel("BP (mmHg)")
plt.title("sshs01 first 10 s")
plt.tight_layout()
plt.savefig("sshs01_head.png", dpi=150)
这里只画前十秒,是为了看清搏动形状。在前十秒的窗口里,大鼠的心搏已经能数出几十个,波峰尖、波谷圆,带明显的呼吸调制。
5.3 把压力波变成逐搏序列
逐搏分析的第一步是从压力波形里找出每一个搏动的收缩峰与舒张谷。大鼠的波形比人类更密,峰值检测的参数要相应调整:最小峰间距不能照抄人类的一秒左右,而应设到 0.1 秒量级以下。
#-- 峰值检测,得到逐搏的收缩压与舒张压序列
import numpy as np
from scipy.signal import find_peaks
def beat_series(bp, fs=100.0):
#-- 先用一个稍宽的窗做平滑,去掉高频毛刺
k = max(1, int(fs * 0.01))
sm = np.convolve(bp, np.ones(k) / k, mode="same")
#-- 大鼠心搏间期在 0.1 到 0.3 秒之间,最小间距取 8 个样本
peaks, _ = find_peaks(sm, distance=int(fs * 0.08), prominence=2.0)
#-- 以每个峰为界,向前找局部极小作为舒张谷
troughs = []
for i, p in enumerate(peaks):
lo = peaks[i - 1] if i > 0 else 0
troughs.append(lo + int(np.argmin(sm[lo:p])))
troughs = np.array(troughs)
sbp = sm[peaks]
dbp = sm[troughs]
return peaks, troughs, sbp, dbp
rec = wfdb.rdrecord("bpssrat/1.0.0/sshs01")
peaks, troughs, sbp, dbp = beat_series(rec.p_signal[:, 0])
print(len(peaks), sbp.mean(), dbp.mean())
检测完要做的第一件事不是算指标,是验搏数。一百二十秒、每分钟三四百次的话,理想情况下应该检测到六百到八百个搏动。检测数明显偏低,说明阈设得高了;明显偏高,说明把噪声或重搏切迹当成了峰。
5.4 逐搏间期的时域指标
有了收缩峰序列,逐搏间期就是相邻峰的差除以采样率。
| 指标 | 算法 | 在两分钟窗内是否可靠 |
|---|---|---|
| 平均逐搏间期 | 间期均值 | 可靠 |
| 间期标准差 | SDNN 式 | 可靠 |
| 间期变异系数 | 标准差除以均值 | 可靠 |
| 相邻间期差的均方根 | RMSSD 式 | 可靠 |
| 间期序列的一阶自相关 | 自相关 | 勉强 |
| 极短段的分形维数 | DFA 之类的尺度指数 | 不可靠,段太短 |
| 低频功率 | 0.2–0.6 Hz 积分 | 勉强 |
| 超低频功率 | 0.01–0.1 Hz 积分 | 不可靠 |
表里最需要强调的是最后两行。频域指标对窗长极其敏感,窗越短,低频估计越不稳。两分钟的窗能比较可靠地看到大鼠 LF 带(约 0.2–0.6 Hz)的结构,因为这段频率在两分钟内能跑几十个周期;再往下就力不从心了。
5.5 频带重标定:人类与大鼠的对照
这是全文的技术核心。把两套频带并排放,差异一目了然。
| 频带 | 人类惯用(Hz) | 大鼠文献常用(Hz) | 倍数关系说明 |
|---|---|---|---|
| 超低频 | 0.003–0.04 | 0.02–0.2 | 大鼠上移约 5 倍 |
| 低频 | 0.04–0.15 | 0.2–0.6 | 大鼠上移约 4 倍 |
| 高频 | 0.15–0.4 | 0.6–2.0 | 大鼠上移约 5 倍 |
| 呼吸相关峰 | 约 0.2–0.3 | 约 1.0–1.5 | 随呼吸频率平移 |
这张表要读出的不只是「数字不同」,而是同一个名字在两套系统里指向不同的生理机制。
在人类里,LF 带(0.04–0.15 Hz)混合了交感张力与压力反射的慢波,HF 带(0.15–0.4 Hz)主要反映呼吸性迷走调制,所以 LF/HF 被当作「交感迷走平衡」的粗略代理。在大鼠里,心率快到每分钟三百次以上,呼吸频率也快,人体的 HF 带(0.15–0.4 Hz)在大鼠身上落在哪里?落在超低频与 LF 之间,既不是呼吸也不是交感,而是血压的缓慢漂移与体温调节的边缘区。
也就是说,把人类 LF/HF 直接扣到大鼠头上,分子取的可能是大鼠的 LF(这时还算对),分母取的却是一段几乎没有呼吸信息的频段。比值失去意义。更糟的是,有些流程把人类的 LF 当成人体的交感指标,而 0.04–0.15 Hz 在大鼠身上是真正的低频漂移,算出来的功率绝对值会很大,看起来「交感很活跃」,实际上什么也没测到。
#-- 两套频带并排计算,看差异有多大
import numpy as np
from scipy.signal import welch
def band_power(x, fs, lo, hi):
f, pxx = welch(x, fs=fs, nperseg=min(len(x), 512))
m = (f >= lo) & (f < hi)
return np.trapz(pxx[m], f[m])
sbp = sbp - sbp.mean()
#-- 人类的频带直接套用
h_lf = band_power(sbp, 100, 0.04, 0.15)
h_hf = band_power(sbp, 100, 0.15, 0.40)
#-- 大鼠的频带
r_lf = band_power(sbp, 100, 0.20, 0.60)
r_hf = band_power(sbp, 100, 0.60, 2.00)
print("human-band ratio", h_lf / max(h_hf, 1e-12))
print("rat-band ratio ", r_lf / max(r_hf, 1e-12))
这段代码的价值不在于算出两个比值,而在于展示「同一段波形,两种频带定义,得出两个数」。跑完之后你应该做的不是选一个更好看的,而是想清楚哪一个频带在这只动物身上有生理依据。
5.6 一个完整的基线流程
把上面几步串起来,就是一份最小可用的逐搏分析基线。
#-- 全库跑一遍,输出每条记录的逐搏统计
import wfdb, numpy as np
from pathlib import Path
from scipy.signal import find_peaks
recs = [ln.strip() for ln in Path("bpssrat/RECORDS").read_text().splitlines() if ln.strip()]
rows = []
for name in recs:
r = wfdb.rdrecord(str(Path("bpssrat") / name))
bp = r.p_signal[:, 0]
fs = r.fs
k = max(1, int(fs * 0.01))
sm = np.convolve(bp, np.ones(k) / k, mode="same")
peaks, _ = find_peaks(sm, distance=int(fs * 0.08), prominence=2.0)
ibi = np.diff(peaks) / fs
rows.append({
"name": name,
"n_beats": len(peaks),
"sbp_mean": float(sm[peaks].mean()),
"ibi_mean": float(ibi.mean()),
"ibi_sd": float(ibi.std()),
"cv": float(ibi.std() / ibi.mean()),
})
for row in rows:
print(row["name"], row["n_beats"], round(row["sbp_mean"], 1),
round(row["ibi_mean"], 3), round(row["cv"], 4))
跑完之后先看 n_beats 这一列。同一批记录里,搏数如果相差超过两三倍,说明检测器在某些波形上失效了,得回头调参数。再看 ibi_mean,换算成心率应该是每分钟三百到五百次的量级,明显偏离就说明检测错了搏。
§6 与库内条目的关系
6.1 关系图谱
bpssrat 在库内不是一个孤岛。它与四类条目构成关系。
| 关系类型 | 库内条目 | 关系说明 |
|---|---|---|
| 同类(血压) | pulsedb 无袖带血压估计基准 |
同样涉及血压,但对象是人、任务是估计,不是动物机制 |
| 同类(血压) | heartcycle 阻抗心动图与超声同步记录 |
同样涉及循环系统信号,但对象是人、通道更多 |
| 同类(生理信号) | circor-heart-sound 儿童心音库 |
都是心血管生理信号,都强调开放与可复算 |
| 邻近(压力相关) | iuphar-bps 药理学知识库 |
可查压力反射相关靶点的药物信息,做机制补充 |
| 方法(信号处理) | ecg-arrhythmia 等心电库 |
可借用其搏动检测与频域分析流程 |
| 方法(动物模型) | 其他 Dahl 或大鼠高血压相关条目 | 可作模型背景的交叉参考 |
这张表的意思不是「它们可以拼起来用」,而是「它们各自解决不同问题」。pulsedb 解决的是「无袖带血压估计算法有多准」,bpssrat 解决的是「大鼠压力反射在盐负荷下怎么变」,两者虽然都叫「血压数据」,任务、对象、许可模式都不一样。
6.2 检索路径
想找这类数据,可以从三个维度检索。
按对象检索:在 PhysioNet 搜 rat、rodent、animal,能找到少数几份动物数据,bpssrat 是其中血压类唯一的一份。
按信号检索:搜 blood pressure,结果里绝大多数是人类数据,bpssrat 混在其中,需要看标题里的物种名才能分辨。
按方法检索:搜 baroreflex、blood pressure variability,能定位到与压力反射模型相关的条目,bpssrat 在这条线的起点位置。
库内检索则走标签:生理信号 加 心血管疾病 加 时序数据,能收敛到一批相关条目,再按「是否动物」「是否血压」两个条件筛。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
读这一节之前,请先放下一件事:不要把「数据量小」误判成「质量差」。
这两件事在小数据集中经常被混为一谈。bpssrat 只有 15 只动物、半小时级的总时长,按大数据集的标准衡量确实「小」。但它的波形是真实的、采样是规范的、单位是明确的、许可是清楚的、DOI 是稳定的。这些「小」之外的东西,恰恰是很多大体量数据缺的。
同样要放下的是相反方向的误判:不要因为它是开放的、带 DOI 的,就以为它适合承担超出设计的问题。它的设计目标是给一篇压力反射论文做配套,任何远超这个目标的使用,都会碰到 §4.2 说的那三处瑕疵。
真正的评估标准只有一条:它能否支撑你打算做的那件事。如果你的任务是逐搏波形读取、时域指标、教学演示、流程校验,它够;如果你的任务是深度学习训练、跨物种指标复现、麻醉与清醒对照,它不够。
7.1 五维评分(DAIMS 框架)
DAIMS 是千方医数集用于评估数据集 AI 就绪度的五维框架:数据可用性、标注质量、代表性、时效性、可维护性。评分只针对它声明的用途——大鼠压力反射与逐搏血压变异性分析,不针对任何通用机器学习任务。
| 维度 | 分数 | 判据 | 主要扣分点 |
|---|---|---|---|
| Data Availability(可用性) | 5 / 5 | ODC-By 1.0、免注册、3.4 MB、有 AWS 直链、DOI 稳定 | 无 |
| Annotation Quality(标注质量) | 1 / 5 | 无任何逐搏或事件标注,只有文件名与一行注释 | 搏动位置需自检,压力反射指标需自拟合 |
| Interpretability / Independence(可解释与独立) | 4 / 5 | 结构极简、单位明确、样本逐条可与原始文本对齐 | 缺麻醉、性别、周龄等状态字段,解释边界受限 |
| Representativeness(代表性) | 2 / 5 | 仅两株 Dahl 系大鼠,无正常血压对照,无其他种系 | 不能代表大鼠总体,更不能外推到人类 |
| Maintenance(可维护性) | 5 / 5 | 静态文件、十余年未改版、无服务依赖 | 无;但也意味着不会再有新增记录 |
五维合计 17 分,满分 25。分数集中落在两端:可用性与可维护性满分,标注与代表性接近最低。这个形状极有辨识度——它是一份「质量很稳但覆盖很窄」的数据,用它之前要先确认自己的问题落在那条窄缝里。
还有一点必须同时说清:五维评分高,并不等于「AI 就绪」。它的可用性满分是因为下载方便,不是因为样本够训模型。按 AI 就绪度衡量,30 条两分钟记录在任何监督学习设定下都只能做演示,这一点在 §7.2 的第一层问题里已经写明。
7.2 三个层次的问题
第一层是数据本身的问题。 样本量小、时长短、品系单一、缺少正常对照。这三条决定了它的组间推断能力有限。
第二层是元数据的问题。 动物性别、周龄、体重、麻醉状态、采集时段缺失。这三条决定了它的复现能力有限。
第三层是使用方式的问题。 频带照抄、指标照抄、状态假设照抄。这三条不是数据的问题,是使用者的问题,但恰恰是最常见的问题。
第三层最关键,因为它跟数据质量无关,再好的数据也会被这种使用方式毁掉。§4.3 的案例已经演示过一次:同一段波形,换个频带定义,结论就翻转。
7.3 已知的、可枚举的偏差
| 偏差 | 类型 | 影响 | 能否校正 |
|---|---|---|---|
| 只有高血压易感品系 | 选择偏差 | 结论不能外推到正常血压大鼠 | 不能,需外部数据 |
| 只有两分钟一段 | 时长偏差 | 低频分析受限 | 部分可用拼接缓解 |
| 无麻醉/清醒标注 | 状态混淆 | 无法区分两种状态下的变异度 | 不能 |
| 无性别信息 | 分层缺失 | 无法做性别差异分析 | 不能 |
| 采集时段不明 | 昼夜偏差 | 无法排除昼夜节律的影响 | 不能 |
| 大鼠心率快 | 尺度偏差 | 人类频带直接失效 | 能,重标定频带 |
| 采集设备细节未公开 | 技术偏差 | 频响与噪声特性未知 | 部分可查原始论文 |
这张表里只有两行是「能校正」或「部分可校正」的,其余五行的偏差是结构性的,改不了。知道哪些改不了,比知道怎么改更重要。
7.4 外部验证矩阵
| 验证对象 | 本库能否提供 | 说明 |
|---|---|---|
| 人类 BPV 指标 | 不能 | 物种与频带都不同 |
| 大鼠 BPV 常模 | 部分 | 仅四格,每格样本少 |
| 压力反射模型参数 | 能 | 原始论文的主目标 |
| 饲料干预效应方向 | 能 | 与原始论文结论对照 |
| 品系差异方向 | 能 | 与原始论文结论对照 |
| 信号处理流程正确性 | 能 | 波形真实,可作校验 |
| 算法跨库泛化 | 弱 | 只有一个物种、一个模型 |
「能」的那几行有一个共同点:它们都是「与原论文结论做方向性对照」。方向能对上,机制层面的细节对不上。「弱」的那几行说明,这份库不太适合做算法泛化研究,因为没有第二份同类的动物血压库可以换着测。
7.5 它为何能持续:因为它是最小可用的那个样本
很多动物实验数据在课题组结题后就沉睡了。bpssrat 没有沉,原因很实际:它足够小,小到托管成本可以忽略;它足够规范,规范到十几年后仍能用当前工具直接读;它许可清楚,清楚到任何人不必问就能用。
这三个条件凑在一起,就构成了一种很朴素的可持续性:不需要维护、不需要社区、不需要更新,因为数据本身没有腐烂的可能。3.4 MB 的静态文件,放在任何镜像上都不会失效。对比之下,那些需要定期跟新、需要维护数据库服务、需要重新签署协议的资源,反而更容易在某次升级后消失。
它之所以还能被引用,还有一个原因:它填补了一个空白。想找一份公开的大鼠逐搏血压数据,翻遍 PhysioNet 也就这一份。这份独特性不是靠规模挣来的,是靠「别人都没放出来」挣来的。
§8 生态位与历史
8.1 2010 到 2012:从论文到数据库
时间线不长,但每一步都有意义。
2010 年,Bugenhagen、Cowley、Beard 在 Physiological Genomics 发表压力反射建模论文,数据集是为这篇论文采集的。
2012 年 6 月 26 日,PhysioNet 将其收录为 v1.0.0,分配 DOI 10.13026/C20597,按 ODC-By 1.0 开放。
此后十余年,版本号没有变过,文件也没有改过。这在 PhysioNet 上很常见,对静态数据来说是好事——引用的稳定性高。
8.2 PhysioNet 的动物数据传统
PhysioNet 的绝大多数内容是人类的:心电图、脑电、重症监护、影像。动物数据是少数派,bpssrat 属于这个少数派。
这个选择本身有原因。人类数据的共享有成熟的伦理框架(去标识化、分级访问、数据使用协议),动物数据则缺少同等成熟的框架。论文层面有 ARRIVE 指南规范动物实验的报告,但数据共享层面没有对应的强制要求。结果就是:动物实验做了很多,数据放出来的很少。
bpssrat 的存在因此有一种示范意义:它证明动物数据也可以按开放数据的方式组织——有标准格式、有清单、有校验和、有许可、有 DOI。这套做法以后可以被照搬。
8.3 从「压力反射模型」到「生理信号基准」
这份数据最初的身份是模型拟合的输入,今天的用法已经扩散到更广的领域。
教学上,它常被用来说明「动物血压波形长什么样」,比教科书插图更真实。
方法上,它常被用来说明「逐搏信号的处理流程」,因为记录短、结构清楚,适合做示例。
警示上,它是跨物种信号处理错误的经典反面教材。这一点在 §3 与 §5.5 已经展开,也是本文的主轴。
身份扩散是好事,但每扩散一次,就要多一次提醒「它不是为这个用途设计的」。
8.3b 动物数据共享为什么稀少
把这份库放到更大的图景里看,会发现它的稀缺不是偶然。
第一,动物实验的数据采集与人类临床的数据采集在制度上不同。人类数据一旦进入医院信息系统,天然就有被二次利用的可能,数据治理的讨论也一直在推进。动物实验的数据从产生到分析都在一个课题组内闭环完成,没有外部系统逼着它规范存储。
第二,共享的动力不同。人类数据共享通常与期刊政策、基金要求、监管要求绑定;动物数据共享在这些方面缺少同等强度的推力,更多依赖作者自觉。
第三,复用的门槛不同。人类临床数据有统一的术语与描述体系,别的团队拿到能懂。动物实验的元数据往往只存在于实验记录本里,别人拿到波形却不知道给药时间、麻醉深度、环境温度,可用性大打折扣。
第四,伦理讨论的焦点不同。人类数据共享的核心关切是隐私与再识别,动物数据共享的核心关切是动物福利的三R原则(替代、减少、优化)。后者其实是支持共享的——一次采集的数据被更多人复用,本身就是「减少」动物使用。但在实践中,这条论证很少被用来推动数据开放。
这四条合起来解释了为什么 PhysioNet 上动物数据只占极小比例。bpssrat 能在其中,本质上是作者愿意多做一步的产物。
8.4 它在今天的生态位
用一句话概括:它是大鼠逐搏血压这条线上的唯一开放入口。
往上走,没有更大体量的大鼠血压开放库可以替代它。
往下走,有大量的人类血压与心电库,但它们换不了物种。
横向看,猪、犬、非人灵长类的遥测数据大多不公开,公开的也多为特定项目的一次性发布。
这个生态位很窄,但很稳。它不需要跟谁竞争,因为没人跟它站在同一个格子里。
§9 使用指引
9.1 三种角色的路径
如果你是算法工程师,想验证一条逐搏分析流水线。 从一条记录开始,跑通读取、峰值检测、间期计算三件事。用 §5.6 的基线脚本把全库跑一遍,检查搏数是否合理。确认无误后,再把你自己的算法接上去。不要一开始就上全库,先让流程在单条记录上正确。
如果你是生理或药理研究者,想做压力反射相关的分析。 先把 §4.3 的案例读懂,理解同编号跨饲料的配对结构。然后决定你的分析单位是「每只动物」还是「每条记录」——这两者在这份数据里不能混,因为每只动物有两条记录。做组间比较时,优先用同鼠配对,其次才是独立样本。
如果你是教师,想找一个动物信号的教学例子。 直接用 sshs01 和 ssls01 这一对。让学生先按人类频带算一遍,再按大鼠频带算一遍,然后讨论「为什么两个结果不一样」。这个练习不需要任何前置知识,效果比讲概念好得多。
9.2 一条最短的可用流程
从零到「看到大鼠的逐搏间期序列」,三步就够。
#-- 1 取数,只取一条记录与它的头文件
curl -LO https://physionet.org/files/bpssrat/1.0.0/sshs01.dat
curl -LO https://physionet.org/files/bpssrat/1.0.0/sshs01.hea
#-- 2 读取并确认参数
import wfdb
rec = wfdb.rdrecord("sshs01")
print(rec.fs, rec.sig_len, rec.units)
assert rec.fs == 100 and rec.sig_len == 12000
#-- 3 检测搏动,打印逐搏间期统计
import numpy as np
from scipy.signal import find_peaks
bp = rec.p_signal[:, 0]
peaks, _ = find_peaks(bp, distance=int(rec.fs * 0.08), prominence=2.0)
ibi = np.diff(peaks) / rec.fs
print("beats:", len(peaks))
print("ibi mean/sd:", ibi.mean(), ibi.std())
print("hr bpm:", 60 / ibi.mean())
第三步打印出来的心率应该是每分钟两三百次以上。如果只有几十次,说明峰值检测漏了大半搏动,需要降低 prominence 或缩短 distance。
9.2b 五个最常见的算错点
上面的流程能跑通读数和检测,但跑通不等于算对。下面五个错误几乎每一位初用者都会撞上一个,提前知道能省掉大半天。
错误一:把「一段」当「全程」。 头文件里的一万二是个固定段长,不是动物的整段采集。写方法段时如果写成「每只动物连续记录两分钟」,在严格评审里是站不住的;准确的说法是「每只动物一条两分钟段」。
错误二:用人类的最小峰间距做大鼠的峰值检测。 人类的心搏间隔约一秒,很多现成脚本把 distance 设成半个采样率。在大鼠身上这会把每五次搏动只保留一次,搏数少了八成,间期均值翻五倍,心率算出来只剩每分钟几十次。看到心率只有几十,几乎一定是这个问题。
错误三:把相邻间期当独立样本。 同一条记录里几百个间期不是相互独立的,它们共享同一只动物、同一段状态。做统计检验时如果按间期数当样本量,p 值会被严重高估。正确的做法是以动物为单位聚合,或者用混合效应模型。
错误四:把两条记录当两只动物。 每只动物有高低盐两条记录,如果分析单位不清,一只鼠会被算两次,品系与饲料的效应估计都会偏。
错误五:频带直接复制粘贴。 这是本文反复强调的那一条。人类的 LF 与 HF 在数值上与大鼠的 LF 与 HF 差着数倍,不少现成代码库把频带写成常量,照搬之后不报错、能出数,但数没有意义。
| 错误 | 症状 | 修法 |
|---|---|---|
| 一段当全程 | 论文方法段被质疑 | 改成「一条两分钟段」 |
| 人类峰间距 | 心率只有每分钟几十 | 把最小间距压到零点一秒以下 |
| 间期当独立样本 | p 值异常小 | 按动物聚合或上混合模型 |
| 两只鼠算成一只 | 样本量与动物数对不上 | 以动物为主键做配对 |
| 频带照抄 | 出数但不报错 | 按物种重设上下界 |
9.3 引用方式
学术引用有三层,写论文时按需要选。
引原始论文:Bugenhagen SM, Cowley AW Jr, Beard DA. Identifying physiological origins of baroreflex dysfunction in salt-sensitive hypertension in the Dahl SS rat. Physiological Genomics 42:23-41, 2010.
引数据本身:PhysioNet, Blood Pressure in Salt-Sensitive Dahl Rats, v1.0.0, DOI 10.13026/C20597。
引许可要求:ODC-By 1.0 要求署名,衍生作品保留许可声明。商业使用不禁止,但同样要署名。
三层都写最稳妥,只写数据 DOI 也可以接受,只写「PhysioNet」而不给具体条目的做法最不推荐,因为 PhysioNet 上有数百个数据集,读者无法据此定位。
§10 AI 使用声明
| 项 | 内容 |
|---|---|
| 生成方式 | 由大语言模型辅助起草,编辑部核对后定稿 |
| 核对范围 | 动物数、记录数、采样率、样本数、增益、体积、许可、DOI 均对照 PhysioNet 1.0.0 页面与 RECORDS、.hea 文件 |
| 未核对项 | 麻醉状态、性别、周龄、采集时段、采集设备型号 |
| 外部文献 | 仅核对 2010 年原始论文的摘要,未读全文 |
| 论文结论 | 三条主要发现转述自摘要,未做独立复核 |
| 代码 | §5 与 §9 的脚本为可运行示例,未在其上跑出正式基准 |
| 频带数据 | 大鼠频带取自常见文献区间,未逐篇核对原始出处 |
| 数字口径 | 时长按样本数除以采样率计算,与官方名义段长一致 |
| 免责 | 本文不构成动物实验或临床建议 |
| 更新约定 | PhysioNet 若发布新版本,需重新核对记录数与体积 |
常见误读(避坑清单)
| 常见说法 | 实际 | 证据 |
|---|---|---|
「bpssrat 是麻醉大鼠插管记录」 |
官方写的是 telemetry,遥测通常指清醒无束缚 | 项目页 Introduction 段与论文摘要 |
| 「它有逐搏标注」 | 没有,只有波形本身 | RECORDS 与 .hea 中无注释文件 |
| 「可以直接套人类 LF/HF 频带」 | 大鼠心率快数倍,频带须整体上移 | §5.5 的频带对照表 |
| 「它有人类血压数据」 | 没有,全库都是大鼠 | 官方说明与文件命名 |
| 「每条记录是 24 小时」 | 是 12000 个样本,按 100 Hz 折合两分钟 | .hea 第一行 |
| 「15 只动物够了深度学习」 | 每格 6–9 条,不足以训练 | §2.4 的分布表 |
| 「它有正常大鼠对照」 | 没有,只有 SS 与 SS.13BN | §3.3 的品系说明 |
| 「它是 v2 或更新版本」 | 只有 v1.0.0,2012 年发布后未更新 | 项目页版本栏 |
| 「下载需要注册」 | 不需要,免注册、免协议 | 项目页 Access 区块 |
| 「LF/HF 比值可以直接解读交感迷走平衡」 | 在大鼠上这一解读缺少依据 | §5.5 与 §7.2 的说明 |
FAQ
Q1:bpssrat 到底是清醒大鼠还是麻醉大鼠的记录?
官方页面与论文摘要都写 telemetry-based,暗示是无束缚的清醒遥测。但本文没有逐条核实,二手资料里也有把它归为麻醉插管记录的说法。稳妥的写法是「遥测采集」,不要写更强的「清醒」或「麻醉」。
Q2:能不能直接套人类 HRV 的 LF/HF 频带来算?
不能。大鼠心率约为人类的六到八倍,人类的 LF 带在大鼠身上落到超低频,HF 带落到既非呼吸也非交感的中间区。算出来的比值没有生理含义,§5.5 有完整对照。
Q3:15 只动物够做统计吗?
做流程演示和教学够用,做组间推断偏少。每格只有六到九条记录,个体差异与处理效应混在一起,p 值要谨慎对待。
Q4:每条记录有多长?
头文件写 100 Hz、12000 个样本,折合名义 120 秒。长度决定了频域分析的下限,粗看 0.05 Hz 以上还行,再往下就需要更长的窗。
Q5:为什么说它稀缺?
动物生理信号数据共享的体量远小于人类数据。人类有百万级样本的公共血压库,大鼠侵入式血压记录大多留在课题组本地。这份库上线十余年、只有 3.4 MB,仍是少数免费可取的大鼠逐搏血压素材。
Q6:引用时该写哪些?
写原始论文、PhysioNet v1.0.0 与 DOI 两层。许可要求署名,衍生作品保留 ODC-By 1.0 声明。
Q7:sshs01 里的 hs 是什么意思?
high salt,高盐饲料。ls 是 low salt,低盐饲料。前缀 ss 是 Dahl 盐敏感株,ssbn13 是导入 Brown Norway 13 号染色体的同源导入系。
Q8:怎么确认下载的文件没坏?
用 SHA256SUMS.txt 校验,或者读一遍头文件里的校验值——第一行第四个字段是段内样本数,第二行第七个字段是整数累加校验,两者都对得上才说明读法正确。
Q9:能不能把四条记录拼成十分钟的长序列?
技术上可以,但拼接意味着假设这些片段来自连续同一状态。饲料条件相同、品系相同的记录拼在一起还能接受,跨条件拼就会引入状态跳变。做频域分析时拼接会不会引入伪峰,需要自己检验。
Q10:它适合做机器学习吗?
作为流程校验与教学示例适合,作为训练集不适合。样本量小到任何复杂模型都会过拟合到个体波形上。
Q11:原始文本和 WFDB 记录有什么区别?
内容等价。文本是多列并排、便于目视;WFDB 是单只动物单文件、便于程序读取。§2.1 有完整对照。
Q12:数据里有没有心率这一列?
没有。心率必须从压力波形的搏动间期反推。原始论文用到了心率数据,但 PhysioNet 版本只提供了血压通道。
术语表
| 术语 | 英文 | 含义 |
|---|---|---|
| 逐搏 | beat-to-beat | 以单个心搏为最小时间单位分析 |
| 压力反射 | baroreflex | 血压升高引发的心率与血管阻力负反馈 |
| 压力反射敏感性 | baroreflex sensitivity | 单位血压变化引起的心率或间期变化 |
| 血压变异性 | blood pressure variability, BPV | 逐搏或逐时血压序列的波动程度 |
| 心率变异性 | heart rate variability, HRV | 逐搏间期序列的波动程度 |
| 收缩压 | systolic blood pressure, SBP | 每次心搏的峰值压力 |
| 舒张压 | diastolic blood pressure, DBP | 每次心搏的谷值压力 |
| 脉压 | pulse pressure | 收缩压与舒张压之差 |
| 逐搏间期 | inter-beat interval, IBI | 相邻两搏之间的时间间隔 |
| 低频带 | LF band | 人类 0.04–0.15 Hz,大鼠约 0.2–0.6 Hz |
| 高频带 | HF band | 人类 0.15–0.4 Hz,大鼠约 0.6–2.0 Hz |
| 超低频带 | VLF band | 比 LF 更低的频段,含义随物种变化 |
| 遥测 | telemetry | 植入传感器后无线传输,动物可自由活动 |
| 同源导入系 | consomic strain | 把一条染色体整条替换入另一品系的动物 |
| Dahl SS 大鼠 | Dahl salt-sensitive rat | 高盐饲料下升压的经典高血压模型 |
| SS.13BN | consomic SS with BN chromosome 13 | 导入 Brown Norway 13 号染色体的 SS 品系 |
| 高盐饲料 | high salt diet, HS | 提高钠负荷的实验饲料 |
| 低盐饲料 | low salt diet, LS | 低钠对照饲料 |
| 交感增益 | sympathetic gain | 压力反射交感支路的增益参数 |
| 迷走张力 | vagal tone | 副交感对心率的抑制作用 |
| WFDB | Waveform Database | PhysioNet 的信号与注释格式 |
| 头文件 | header file, .hea | 记录采样率、增益、单位的元数据 |
| 增益 | gain | 每个物理单位对应的整数单位数 |
| 校验值 | checksum | 段内整数的累加值,用于完整性校验 |
| ODC-By | Open Data Commons Attribution | 要求署名的开放数据许可 |
| ARRIVE 指南 | ARRIVE guidelines | 动物实验报告的规范清单 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 动物总数 | 15 | 项目页 Introduction | 官方 |
| SS 株动物数 | 9 | RECORDS 前缀计数 |
官方文件 |
| SS.13BN 株动物数 | 6 | RECORDS 前缀计数 |
官方文件 |
| WFDB 记录数 | 30 | RECORDS 逐行计数 |
官方文件 |
| 原始文本数 | 4 | 项目页文件列表 | 官方 |
| 采样率 | 100 Hz | 全部 .hea 第一行 |
官方文件 |
| 单条样本数 | 12000 | 全部 .hea 第一行 |
官方文件 |
| 名义段长 | 120 秒 | 12000 ÷ 100 | 推算 |
| 增益 | 100 单位每 mmHg | 全部 .hea 第二行 |
官方文件 |
| 有效位宽 | 12 位 | 全部 .hea 第二行 |
官方文件 |
| 通道数 | 1 | 全部 .hea 第一行 |
官方文件 |
| 全库体积 | 3.4 MB | 项目页 Files 区块 | 官方 |
| 许可 | ODC-By 1.0 | 项目页 Access 区块 | 官方 |
| DOI | 10.13026/C20597 | 项目页 Discovery 区块 | 官方 |
| 发布日期 | 2012-06-26 | 项目页版本栏 | 官方 |
| 版本数 | 1 | 项目页 Versions 栏 | 官方 |
| 品系间差异 | 交感增益在 SS 高盐下受损 | 原始论文摘要 | 论文 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 动物数、记录数、采样率、样本数、增益、位宽、体积、许可、DOI、日期,全部来自 PhysioNet 1.0.0 项目页与 RECORDS、.hea 文件。这一层可以直接引用。
第二层:论文摘要。 品系差异、饲料效应、交感与副交感偏移这几条结论,来自 2010 年 Physiological Genomics 那篇论文的摘要。这一层说明「作者报告了什么」,不代表本文独立复核过。
第三层:未核实。 麻醉状态、性别、周龄、体重、采集时段、采集设备型号,本文未取得。大鼠频带的常用区间来自领域内的通行认识,本文未逐篇追溯其最早出处。这些项目在写作时按「未核实」处理。
附录 C:完整参考文献
- Bugenhagen SM, Cowley AW Jr, Beard DA. Identifying physiological origins of baroreflex dysfunction in salt-sensitive hypertension in the Dahl SS rat. Physiological Genomics 42:23-41 (2010). PMID: 20354102.
- PhysioNet. Blood Pressure in Salt-Sensitive Dahl Rats, v1.0.0. https://physionet.org/content/bpssrat/1.0.0/ (DOI: 10.13026/C20597)
- Pollard T, Moody BE, Lehman L, et al. PhysioNet as a global platform for biomedical research. Nature Health 1(8):792-795 (2026). DOI: 10.1038/s44360-026-00096-z
- PhysioNet.
RECORDS清单与 30 条记录的头文件,https://physionet.org/files/bpssrat/1.0.0/
附录 D:任务代码
想在本地确认「这份库到底是什么」,跑下面这段就够,它会打印记录数、每条的采样参数和注释。
#-- 全库体检:记录数、采样率、样本数、注释
import wfdb
from pathlib import Path
from collections import Counter
root = Path("bpssrat")
names = [x.strip() for x in (root / "RECORDS").read_text().splitlines() if x.strip()]
fs_set, n_set, notes = Counter(), Counter(), []
for nm in names:
h = wfdb.rdheader(str(root / nm))
fs_set[h.fs] += 1
n_set[h.sig_len] += 1
notes.append(h.comments[0] if h.comments else "")
print("records:", len(names))
print("fs:", dict(fs_set))
print("sig_len:", dict(n_set))
print("total seconds:", sum(n_set[k] * v / list(fs_set)[0] for k, v in n_set.items()))
print("comment sample:", notes[:3])
输出的记录数应该是三十,采样率只有一百这一种,样本数只有一万二这一种。如果哪一项出现第二种取值,说明下载不完整或目录里混进了别的文件。
附录 E:如果只记五件事
第一,它是 PhysioNet 上唯一一份开放的大鼠逐搏血压数据,15 只动物、30 条记录、解压后 3.4 MB。
第二,每条记录一百 Hz 采样、一万两千个样本,按默认段长折合两分钟,频域分析的下限因此有限。
第三,它没有任何标注,心率要从压力波形的搏动间期反推,压力反射参数要自己拟合。
第四,人类 LF/HF 频带不能直接套用,大鼠的频带整体上移数倍,不重标定就等于测错东西。
第五,官方写的是遥测采集,麻醉与否、性别周龄等元数据缺失,引用时措辞要保守。
编辑说明
核验时间:2026 年 10 月 27 日。
核验方式:逐个访问 PhysioNet 项目页、RECORDS 清单、四份头文件样本(sshs01、ssls01、ssbn13hs01、ssbn13ls01)以及 SS_HS.txt 的注释段;论文结论对照 Europe PMC 的摘要记录(PMID 20354102)。
未覆盖内容:逐条波形的统计分布、峰值检测的准确率、原始论文全文、麻醉与行为状态的任何推断。这些内容要么需要全量下载后自行计算,要么需要原文才能回答,本篇不做。
口径说明:原文的「record」指一条 WFDB 记录,等于一只动物在一个饲料条件下的一段波形;「animal」指动物个体,每只动物在两种饲料下各有一条记录。
页面命名与 slug 的对应关系见 frontmatter;本文不涉及任何站内运营信息。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- bp-graphene-bioimpedance — 共享标签:生理信号 / 心血管疾病 / 时序数据
- staffiii — 共享标签:生理信号 / 心血管疾病 / 时序数据
- chf2db — 共享标签:生理信号 / 心血管疾病
- fantasia — 共享标签:生理信号 / 心血管疾病 / 时序数据
- hls-cmds — 共享标签:生理信号 / 心血管疾病
- code-15 — 共享标签:生理信号 / 心血管疾病 / 时序数据
- physionet-cinc-2016 — 共享标签:生理信号 / 心血管疾病
- cpap-data-canterbury — 共享标签:生理信号 / 时序数据
- cardioresp-response-orthostat — 共享标签:生理信号 / 心血管疾病
- mmgdb — 共享标签:生理信号 / 时序数据
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

