信息速览
动态心电的难题不是找出异常,而是分清是否为缺血。体位改变会把 QRS 主轴拉偏,电极干涸会让基线漂移,传导异常会让复极变形,三者的 ST 段表现都与缺血相似,却不需要干预。要训练能区分它们的检测器,先得有一批被反复看过、标注理由说得清的长时程记录。长时程 ST 数据库(ltstdb)正为此而建:86 条记录、80 名受试者、每条 21 到 24 小时、250 Hz 采样,ST 事件按三套阈值分别标注。
它的建设方式在同时代不算常见:三国三地的实验室用自研编辑器各自判读同一条记录,定期会商弥合分歧,并把 ST 水平函数、基线参考函数、ST 偏移函数逐导联留档。
它也直言取舍:记录只因出现过 ST 改变入选,故宜验证判读逻辑,不宜估算人群比例。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | Long-Term ST Database |
| 常用缩写 | ltstdb |
| 建设机构 | 卢布尔雅那大学计算机与信息科学学院(牵头)、比萨 CNR 临床生理研究所、麻省理工学院计算生理实验室 |
| 协调人 | Franc Jager 教授(卢布尔雅那大学) |
| 上线时间 | 2000 年 11 月 29 日,版本 1.0.0 |
| DOI | 10.13026/C2G01T |
| 记录数 | 86 条,清单以 s2 或 s3 开头 |
| 受试者数 | 80 名 |
| 每条时长 | 21 至 24 小时 |
| 导联 | 两路或三路体表心电,首位数字即路数 |
| 采样率 | 250 Hz |
| 量化 | 12 位,量程 ±10 毫伏 |
| 标注层次 | 逐搏 QRS + 逐搏 ST 测量 + ST 事件(三套阈值) |
| 文件格式 | WFDB:.hea / .dat / .atr / .16a / .stf / .sta 等 |
| 单条记录体积 | .dat 约 50 至 130 兆字节 |
| 许可 | ODC-BY 1.0,无需注册 |
| 典型用途 | 缺血检测器开发与评测、非缺血 ST 改变鉴别、动态 ST 机制研究 |
§1 它要解决的具体麻烦
1.1 缺血检测器的评测环境一直不对
动态心电里的 ST 段判读有一个尴尬处境:临床上每天都在做,但真正被专家逐事件确认过的公开数据极少。短记录库里,一次完整的缺血发作常常要跨过记录边界;心律失常库里,标注只关心 QRS 与节律,ST 段根本不在注释范围内。于是一个只见过几十秒片段的模型,被拿去评测一整天的动态心动图,结果好得可疑,原因往往只是它从没遇到连续几小时的基线漂移。
ltstdb 要解决的就是这个错配。它把记录长度拉到 21 至 24 小时,让缺血发作、轴线偏移、噪声段、传导异常都落在同一段连续信号里,逼着算法在完整的时间背景上做出判断。事件标注不是事后由规则批量生成的,而是由专家看着 ST 偏移曲线、对着原始波形逐个确认的。
这也解释了为什么它的标注层数比同族库多。只标「这里有 ST 改变」不够,还必须说清这次改变属于缺血、属于体位、还是属于传导异常。三者在波形上都能让 ST 段偏移几十微伏,区分它们需要的正是专家判断,而这恰恰是算法最想学到的东西。
1.2 三条常见的错误期待
第一条,把它当成 ltdb 的扩充版。两个库名字里都有 long-term,都在 PhysioNet 上,都以 s 或数字命名记录,很容易被当成同一件事的两代产品。实际上它们是两条独立项目线:ltdb 是 1999 年上线的七条 MIT-BIH 长时程记录,128 Hz,只有心搏与信号质量两层标注;ltstdb 是 2000 年上线的多国合作项目,250 Hz,专门为 ST 段与缺血事件而建。
第二条,以为标注里有「缺血/非缺血」这个二分类字段。官方并没有提供一个逐搏的缺血标签。给出的是 ST 偏移函数、三套事件标注,以及临床注释;「这次偏移算不算缺血」的最终判断,体现在事件标注的类别码上,而不是一个可以按采样点对齐的布尔数组。
第三条,以为三套 ST 事件标注是宽容度递进的。它们是三条并列的判定规则,分别对应不同的最小偏移量与最短持续时间,服务的是不同的应用场景。拿其中一套的计数去和另一套的计数比较,或者把三套合并成「更完整的真值」,都会得到无法解释的数字。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 缺血与体位性 ST 改变的鉴别 | 专家确认的缺血与非缺血事件,带类别码 | 够,这是建库的初衷 |
| 动态心电图的一整天连续评测 | 86 条 21 至 24 小时记录 | 够,规模在同类中最大 |
| 逐搏 ST 水平测量的比对 | 基于 16 秒滑动平均的逐搏 ST 测量文件 | 够,但需自行换算为微伏 |
| 十二导联形态学分析 | 只有两路或三路导联 | 不够,应改用十二导联库 |
| 人群中缺血发生率估计 | 记录按事件出现与否挑选 | 不够,事件被显著富集 |
| 用药、预后与随访关联 | 只有临床注释,无结构化用药字段 | 不够,需接入电子病历 |
| ST 段主成分与正交变换研究 | KL 系数与 Legendre 系数时间序列 | 够,2015 年后还有一套未中心化版本 |
| 与欧洲 ST-T 库直接合并 | 十记录源自该库但被重新数字化并缩放 | 勉强,注释不能逐点对齐 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你的缺血检测器在短库上指标很好,一到长记录就大量误报 | 提供连续一整天的记录,误报原因暴露在轴线偏移与基线漂移里 | 先按 §2.3 读一条记录,把误报集中出现的时段与 ST 偏移曲线对照 |
| 你要做「缺血 vs 体位改变」的二分类,却找不到带负类标注的数据 | 非缺血事件被单独标注为独立类别,正好是负类来源 | 用 .sta 与 .stb 的事件清单构造样本,别用逐搏 ST 测量代替 |
| 你在核对某篇论文的评测口径,发现数字对不上 | 三套阈值标注并存,论文可能用了不同的一套 | 按 §7.3 的对照表先确认阈值,再谈复现 |
| 你在做可穿戴设备的 ST 监测,需要真实长时程噪声 | 完整的一天里包含电极干涸、翻身伪迹与运动噪声 | 参考 §4.4 的案例,从信号质量标注切入 |
| 你要研究 ST 段的形态学表征方法 | 库内附带 KL 与 Legendre 正交变换系数 | 直接读 .klt.zip 与 legendre 子目录,省去自己算 |
| 你在教动态心电图判读,需要一个能讲满一小时的例子 | 单条记录有一整天的趋势图与逐事件截图 | 取 §2.3 解剖的那条记录备课 |
1.5 一句话判断
它是迄今唯一把「ST 段为什么会偏、这次偏要不要紧」逐事件写下来的长时程公开库;用它的前提是接受「事件被挑过」这件事,把注意力放在鉴别逻辑上而不是患病率上。
1.6 不适合谁:四条边界
不适合做人群层面的缺血流行病学。 记录是按是否出现 ST 改变挑出来的,库内事件密度被人为抬高。任何「动态心电中缺血事件占比多少」的结论,用这个库都得不到。
不适合做十二导联或少导联形态学对照。 全库只有两路或三路信号,且官方页面没有给出导联与体表位置的对应关系表。要做肢体导联与胸导联的形态比较,必须换库。
不适合需要结构化临床变量的建模。 库里有临床注释文本,但没有可以把用药、既往心梗、冠脉病变程度当作特征的字段。多模态或表型预测类任务在这里没有输入。
不适合把逐搏 ST 测量直接当标签的监督学习。 逐搏测量只是连续量,缺血与否的判断在事件层。把测量值阈值化当成标签,等价于重新发明一套未经专家确认的规则,而这样做出的模型无法与库的原意对照。
§2 数据构成与规格
2.1 一条记录由一组同名文件构成
库沿用 WFDB 格式。每条记录的名字是一串以 s 开头的编号,所有文件共用这个基名,靠扩展名区分内容。头文件是纯文本,第一行写记录名、信号路数、采样率与采样点数,随后每路信号一行,声明存储格式、增益、位深、基线、初值与校验和。信号本体是二进制,按采样点交错存放各路的整数值。
注释文件不止一个,这是与多数心电库最大的不同。除了人工修正过的逐搏标注 .atr,还有自动生成的 .ari;除了三套 ST 事件标注 .sta、.stb、.stc,还有逐搏 ST 测量 .16a 与每个导联的 ST 水平函数 .stf。压缩包里另存 SEMIA 所需的诊断与形态时间序列,以及 ST 段与 QRS 的正交变换系数。
理解这个结构的关键是分清「测量」与「判定」。.16a 与 .stf 属于测量层,算法可以直接重算并比对;.sta、.stb、.stc 属于判定层,是专家结论,不可由测量值机械推出。多数误用都发生在把两层混为一谈。
2.2 字段与文件的完整字典
| 文件 | 形态 | 内容 | 使用要点 |
|---|---|---|---|
.hea |
文本 | 记录头:路数、采样率、采样点数、每路增益与校验和 | 还带受试者临床注释行 |
.dat |
二进制 | 两路或三路的 12 位采样,量程 ±10 毫伏 | 单条 50 至 130 兆字节 |
.atr |
二进制 | 人工修正后的逐搏 QRS 标注与节律、质量标记 | 心搏定位的首选来源 |
.ari |
二进制 | 自动生成的逐搏 QRS 标注 | 可用于比较自动与人工的差异 |
.16a |
二进制 | 逐搏 ST 段测量,基于 16 秒滑动平均 | 测量层,不是标签 |
.stf |
文本 | 每导联的 ST 水平函数、基线参考函数、ST 偏移函数 | 复查专家判断的核心中间产物 |
.sta |
二进制 | ST 事件标注,75 微伏 / 30 秒 | 三个口径中最敏感的一套 |
.stb |
二进制 | ST 事件标注,100 微伏 / 30 秒 | 中等口径 |
.stc |
二进制 | ST 事件标注,100 微伏 / 60 秒 | 最保守的一套 |
.cnt |
文本 | 三套事件标注各自的计数 | 快速了解单条记录的事件量 |
.tsr.zip |
压缩二进制 | SEMIA 用的细粒度与原始诊断、形态时间序列 | 解压后在当前目录使用 |
.klt.zip |
压缩文本 | ST 段与 QRS 的 KL 系数时间序列 | 2011 与 2015 两版并存 |
RECORDS |
文本 | 86 行记录名清单 | 首位数字即信号路数 |
RECORDS-2003 |
文本 | 2003 年首批开放时的 43 行清单 | 版本考古用 |
ANNOTATORS |
文本 | 注释器角色说明 | 声明各类注释文件含义 |
SHA256SUMS.txt |
文本 | 逐文件校验和清单 | 下载后先核对 |
2.3 一条记录的完整解剖
以 s20011 为例,它属于 s2 段,也就是两路信号。头文件的结构与 ltdb 一致,但采样率是 250 Hz,记录长度接近一整天的上界。读取时最需要确认的四个量是信号路数、采样率、采样点数与各路的物理增益:
import wfdb
rec = wfdb.rdrecord('s20011', pn_dir='ltstdb')
print(rec.sig_name, rec.n_sig, rec.fs, rec.sig_len)
#-- ['ECG', 'ECG'] 2 250 21600000
print(rec.adc_gain, rec.baseline, rec.units)
#-- 增益与基线由头文件声明,量程 ±10 毫伏
print(round(rec.sig_len / rec.fs / 3600, 2), 'hours')
采样点数除以采样率即得时长。s2 段的记录编号大致从 s20011 排到 s20651,s3 段从 s30661 排到 s30801,两段之间没有连续编号,这不是缺号,而是两类记录分属不同的记录名区间。同一受试者的多次监护会在末位数字上体现,例如 s20271 与 s20272 属于同一名受试者的两条记录,s20273、s20274 同理。
同一路信号在头文件里可以重名,读取时必须按列下标区分而不是按名字区分。这个细节在把所有记录堆成一张表时会造成静默错误:按名字做字典键,两列会互相覆盖,最后只剩一路信号。
2.4 规模、时长与体积的三个口径
| 项 | 官方口径 | 备注 |
|---|---|---|
| 记录数 | 86 条 | RECORDS 清单 86 行 |
| 受试者数 | 80 名 | 同一人可有多条记录 |
| 两路信号记录 | s2 段,共 65 条 | 记录名首位为 2 |
| 三路信号记录 | s3 段,共 21 条 | 记录名首位为 3 |
| 每条时长 | 21 至 24 小时 | 官方页面与论文一致 |
| 采样率 | 250 Hz | 逐记录头文件一致 |
| 量化 | 12 位,±10 毫伏 | 1 个整数单位约 4.88 微伏 |
| 单条信号体积 | 约 50 至 130 兆字节 | 目录列表给出的字节数区间 |
| 首批开放 | 43 条,2003 年 2 月 | 对应 42 名受试者 |
| 第二批开放 | 其余 43 条,2007 年 6 月 | 同时修正了 s30801 的信号文件 |
表里有一个官方未给全的量:全库的压缩包体积。官方页面只说「八十六个完整记录」已全部贡献,没有写整包大小。按单条 .dat 的体积区间与 86 条的数量,可以估出信号本体在数字位字节级的量级,但这只是估算,规划存储时应按单条真实大小加总,而不是引用估算值。
2.5 与同类资源的字段差异
| 维度 | ltstdb | ltdb | edb | ltafdb |
|---|---|---|---|---|
| 记录数 | 86 | 7 | 90 | 84 |
| 每条时长 | 21–24 小时 | 14–24 小时 | 2 小时 | 24–25 小时 |
| 导联数 | 2 或 3 | 2(一条 3) | 2 | 2 |
| 采样率 | 250 Hz | 128 Hz | 250 Hz | 128 Hz |
| 逐搏 QRS 标注 | 有 | 有 | 有 | 有 |
| 逐搏 ST 测量 | 有 | 无 | 有 | 无 |
| ST 事件标注 | 有,三套阈值 | 无 | 有 | 无 |
| 节律变化标注 | 有 | 无 | 有 | 有 |
| ST 段正交变换系数 | 有 | 无 | 无 | 无 |
| 上线年份 | 2000 | 1999 | 2000 年前后 | 2008 |
这张表回答的是「要做 ST 段相关工作该选谁」。短记录便于逐事件细看,长记录便于观察事件的完整轨迹;ltstdb 的独特之处在于它同时具备长时长、高采样与多套事件口径三件事,而 edb 只有两小时,ltdb 与 ltafdb 没有 ST 层。
2.6 三套事件阈值各自的适用范围
事件的起止规则三套共用:偏移函数首次超过 50 微伏时事件开始,之后必须在连续区间内达到该套阈值,并在偏移回落到 50 微伏以下、且随后 30 秒内不再越过时结束。因此三套标注之间大致存在包含关系,但官方没有给出合并口径,任何把三套拼成一个并集的做法都需要自行说明定义。
2.7 记录命名所携带的结构信息
命名规则本身就是元数据。首位数字直接给出信号路数,末位数字的延续关系则能把清单折叠成受试者。只看清单就能知道某条记录有几路信号,也能在不读任何文件的情况下把八十六条记录归并成八十名受试者。做受试者级划分时,这一步必须先完成,否则同一人会在训练集与测试集两侧同时出现。
§3 它是谁的八十六段心跳:三地联合判读的工程产物
3.1 谁在建这个库
牵头方是斯洛文尼亚卢布尔雅那大学计算机与信息科学学院,协调人为 Franc Jager 教授。参与方包括该学院的 Roman Dorn 与 Ales Smrdel、卢布尔雅那大学医学中心的 Gorazd Antolic、意大利比萨 CNR 临床生理研究所的 Alessandro Taddei 与 Michele Emdin、佛罗伦萨大学的 Carlo Marchesi,以及麻省理工学院的 Roger Mark 与 George Moody。项目获 Medtronic 与 Zymed 两家公司支持。
这个组合的身份值得留意。比萨团队是欧洲 ST-T 数据库的创建者,MIT 团队是 MIT-BIH 心律失常库的创建者,两边在 ST 段与心搏标注上各自积累过完整的方法学。ltstdb 相当于把这两条线的经验汇到一处,再补上卢布尔雅那团队自研的图形判读工具。官方在描述里明确说,它的定位是补充而非替代这两个库。
3.2 时间线
| 时间 | 事件 | 依据 |
|---|---|---|
| 1995 | 项目启动 | 官方页面称开发始于 1995 年 |
| 1995–1998 | 美斯联合项目产出首批记录 | 官方页面称 11 条记录来自该阶段 |
| 1996 | 在 Computers in Cardiology 报告建库方案 | 附加参考文献 |
| 1994–2000 | 监护记录取材窗口 | 方法学论文摘要 |
| 2000-11-29 | v1.0.0 在 PhysioNet 上线 | 官方版本信息 |
| 2002 | 数据库开发完成 | 官方页面称 2002 年完成 |
| 2003-02 | 首批 43 条开放 | 官方新闻「贡献了一半」 |
| 2003-03 | 方法学论文发表于 MBEC 41(2) | Europe PMC 记录 |
| 2003-12 | 补充全部记录的临床注释与趋势图 | 官方新闻 |
| 2007-06 | 其余 43 条补齐 | 官方新闻「现已贡献全部」 |
| 2009 | 增补 Legendre 正交变换系数 | 官方更新说明 |
| 2011 | 增补单导联 KL 系数(已中心化) | 官方更新说明 |
| 2015-11 | 增补未中心化的 KL 系数版本 | 官方更新说明 |
这张表说明它的节奏:主体在 2002 年就冻结了,此后十余年的更新都在追加派生时间序列,而不是新增记录或修订事件标注。对一个用于算法评测的库来说,这是好事——评测基准一旦变动,跨年份的论文就不可比。派生数据单独成目录,也意味着使用旧目录的人不会因为新目录出现而结果漂移。
3.3 采集场景:一次真实的一天
每条记录来自一次动态心电监护,受试者贴身佩戴记录仪,从早到晚包括睡眠、工作、通勤与活动。监护场景是常规临床实践,不是为研究专门设计的实验方案,美国与欧洲的病例都在取材范围内。记录选择的标准是「出现缺血性或非缺血性 ST 改变」,并兼顾慢漂移与混合现象的样本。
这个场景决定了噪声的形态。白天活动时的肌电干扰、电极与皮肤之间的阻抗变化、夜间翻身造成的电极位移,都会在 ST 段上留下痕迹。轴线偏移尤其麻烦:体位改变会让 QRS 主轴整体转向,连带 ST 段一起偏,判读专家必须借助局部参考点把它与真正的缺血偏移分开。
3.4 一个记录的三层来源
| 来源 | 条数 | 进入方式 | 特点 |
|---|---|---|---|
| 1995–1998 美斯联合项目 | 11 | 首批自建记录 | 项目起点,判读协议在此阶段成形 |
| 欧洲 ST-T 库的原始采集 | 10 | 重新数字化并重新缩放 | 原库只有两小时节选,本库给出完整一天 |
| Zymed 公司提供 | 18 | 三路信号记录 | 只出现在 s3 段 |
| 其余记录 | 47 | 常规监护筛选 | 官方未按来源细分说明 |
三类来源带来的信号质量并不一致。从欧洲 ST-T 库重数字化来的那批,模拟信号经过二次采样与重新缩放,官方明确提醒:不能把本库的注释与原库记录的注释直接对齐比较。Zymed 提供的三路信号记录在通道数上就与两路记录不同,批处理时必须分支处理。
3.5 判读流程:从 PQ 结到事件
判读不是直接看波形画圈。第一步,专家在 16 秒平均的心动周期上标出 PQ 结与 J 点,作为自动测量算法的锚点。第二步,专家审视 ST 水平的时序曲线,标出一系列局部参考点,用来构造分段线性的基线 ST 水平函数;体位改变会让基线整体平移,这一步就是在吸收这种平移。第三步,把未校正的 ST 水平减去基线参考函数,得到 ST 偏移函数。第四步,在偏移函数上判定事件,并在事件前后各放一个局部参考点。
整个流程由自研工具 SEMIA 承载。它提供图形界面,把测量、参考点标注、事件判定放在同一条时间轴上,允许国际团队通过互联网协作判读。三个站点各自独立完成一遍,每年开若干次会讨论分歧,最终形成共识参考标注。这套流程的产物被完整保留下来:.stf 里就是每个导联的 ST 水平函数与偏移函数,.tsr.zip 里是更细的诊断与形态时间序列。
3.6 临床注释里有什么、没有什么
由此可以判断它的能力边界:作为波形与 ST 判读的资源,它相当完整;作为临床研究的数据集,它很单薄。凡需要追问病人后来怎样的问题,都得另找数据源,而且很难与本库逐人对接,因为官方没有公布可外部关联的受试者标识。头文件里的临床注释行是唯一逐个记录可读的个体信息,其中与判读最相关的是既往心肌梗死史,因为它直接决定了基线参考函数该怎么建。
§4 它最独特的东西:把「为什么偏」写进标注
4.1 区分缺血与非缺血才是核心任务
官方在建库目标里写得很清楚:支持开发与评测能够准确区分缺血性 ST 事件与非缺血性 ST 事件的算法,并支持对心肌缺血机制与动力学的基础研究。这句话里有两层意思,第二层常常被忽略——它不仅要给正例,也要给有说服力的反例。
反例来自两类现象。一类是轴线偏移:体位改变导致 QRS 主轴转动,ST 段随之偏移,但心肌供血没有变化。另一类是传导异常:束支传导阻滞或预激会改变复极顺序,让 ST 段出现继发性偏移。两类现象在单一导联上看都与缺血相似,必须结合 QRS 主成分与多导联的一致性才能分开。库里的非缺血事件标注,正是把这些「长得像但不算」的样本显式标出来。
4.2 三套阈值并存的用意
| 判定口径 | 阈值组合 | 与其他两套的关系 | 使用风险 |
|---|---|---|---|
| sta | 75 微伏 / 30 秒 | 最宽,事件数最多 | 与文献默认口径不同,容易高估灵敏度 |
| stb | 100 微伏 / 30 秒 | 中等,最接近常见文献 | 需确认对方论文是否用此套 |
| stc | 100 微伏 / 60 秒 | 最严,事件数最少 | 会漏掉短暂但真实的偏移 |
官方给出的理由是不同应用可能需要不同的判据。这句话在实践中的含义是:筛查型算法追求不漏报,用 sta 更合适;诊断型算法要控制误报,用 stc 更合适;与多数已发表工作对齐,用 stb。三套之间不存在谁更「正确」,只有谁更贴合你的应用。
一个常见的操作错误是把三套合并成「并集」当作更完整的真值。并集会引入 sta 独有的短事件,同时保留 stc 的长时间窗,得到的既不是任何一套阈值的结果,也无法与任何一篇论文对照。
4.3 逐搏 ST 测量与事件判定的分工
.16a 文件是逐搏的 ST 段测量,基于 16 秒滑动平均、每个心搏更新一次。它是测量层,给的是连续量;.stf 是函数层,给的是每个导联的 ST 水平、基线与偏移三条曲线;.sta 到 .stc 是判定层,给的是事件区间与类别。
三层之间可以互相验证,但不能互相替代。用 .16a 的测量值重新套一套阈值,得到的事件未必与专家标注一致,因为专家还用到了形态、多导联一致性与临床背景。反过来说,若你的算法在 .stf 的偏移函数上已经能复现专家的事件起止,那它学到的是判读逻辑,而不是阈值本身,这才是可迁移的能力。
4.4 案例:s20011 这条记录为什么适合当第一条
s20011 是清单里的第一条,两路信号,官方页面上的判读演示图正是取自这条记录的多个片段:标注轴线偏移、标注缺血事件、标注 ST 参考函数的建立过程。也就是说,官方公开的每一张判读示意图,都可以在这条记录上被逐一定位。这让它成为理解整套标注协议最短的一条路径。
先做第一次读取。rdrecord 会一次性把两路信号与头文件信息拿回来,得到形状为「采样点数 × 2」的数组:
import wfdb
import numpy as np
rec = wfdb.rdrecord('s20011', pn_dir='ltstdb')
x = rec.p_signal
print(x.shape, rec.fs, rec.units)
#-- 采样点 × 2,(250, 'mV')
#-- 取第一个小时,看两路的幅度与直流偏置是否一致
print(np.round(x[:250 * 3600, 0].mean(), 3), np.round(x[:250 * 3600, 1].mean(), 3))
第二次读取读事件层。三套标注各自独立读取,事件类别写在辅助注释里,区间以注释对的形式给出:
import wfdb
for ann_name in ('sta', 'stb', 'stc'):
ann = wfdb.rdann('s20011', ann_name, pn_dir='ltstdb')
print(ann_name, len(ann.sample), sorted(set(ann.aux_note)))
跑完之后可以看到,三套标注的事件数依次递减。这一步比读任何文字说明都直观:同一段信号,在宽口径下被判为事件,在严口径下可能不成立。把三次计数与 .cnt 文件里的数字对照,如果一致,说明读取链路没有问题。
第三次读取读测量层。.16a 是逐搏的 ST 测量,配合 .atr 的心搏时刻,就能画出 ST 水平随时间的曲线:
import wfdb
import numpy as np
beats = wfdb.rdann('s20011', 'atr', pn_dir='ltstdb', sampto=250 * 3600)
st = wfdb.rdann('s20011', '16a', pn_dir='ltstdb', sampto=250 * 3600)
print(len(beats.sample), len(st.sample))
print(st.aux_note[0], '位数', len(st.aux_note[0]))
.16a 的辅助注释里按导联顺序存放 ST 测量值,需要按固定位数切分再转成数值。这一步最容易出错:切分位数按错一位,整条曲线就会上下颠倒,而程序不会报错。
§4.4 的案例在后续还会被引用:§5.5 会用它演示三套标注的差异如何影响样本构造,§7.3 会用它说明阈值口径的偏差。选它作贯穿样本的理由很简单——官方自己的截图就来自它,任何关于标注含义的争论都可以回到同一份材料上。
4.5 这条记录与 ltdb 的根本区别
| 维度 | s20011(ltstdb) | MIT-BIH 长时程记录(ltdb) |
|---|---|---|
| 采样率 | 250 Hz | 128 Hz |
| 注释文件数 | 十余个,含三套事件 | 一个,含心搏与质量 |
| ST 测量 | 逐搏,另有函数与正交系数 | 无 |
| 非缺血事件 | 单独标注 | 无此概念 |
| 判读方式 | 三地专家独立判读后会商 | 人工复核心搏 |
| 记录时长 | 21 至 24 小时 | 14 至 24 小时 |
这张对照表解释了为什么不能把两个库的「心搏标注」直接混用:同样是逐搏标注,一边只为 QRS 定位服务,另一边要为 ST 段测量服务,两套标注对 R 峰位置的精度要求不同,混用时误差会进入 ST 水平计算。
§5 怎么拿到:从清单到一条可复现的 ST 曲线
5.1 目录结构与下载面
库的主目录是平铺的,每个记录一组同名文件,另有若干子目录存放派生数据与文档。文件访问受站点策略限制,普通命令行抓取常被拒绝,实际下载应走官方页面或支持会话的客户端。
| 路径 | 内容 | 大小量级 |
|---|---|---|
/files/ltstdb/1.0.0/RECORDS |
86 行记录名 | 602 字节 |
/files/ltstdb/1.0.0/RECORDS-2003 |
首批 43 行 | 301 字节 |
/files/ltstdb/1.0.0/00README |
库的说明文件 | 约 2.8 KB |
/files/ltstdb/1.0.0/SHA256SUMS.txt |
逐文件校验和 | 约 196 KB |
/files/ltstdb/1.0.0/<记录>.dat |
信号本体 | 50 至 130 兆字节 |
/files/ltstdb/1.0.0/<记录>.atr |
逐搏标注 | 151 至 485 KB |
/files/ltstdb/1.0.0/<记录>.16a |
逐搏 ST 测量 | 4.6 至 24.2 兆字节 |
/files/ltstdb/1.0.0/<记录>.klt.zip |
正交变换系数 | 407 至 1169 KB |
/files/ltstdb/1.0.0/<记录>.tsr.zip |
SEMIA 辅助数据 | 2.2 至 9.0 兆字节 |
/files/ltstdb/1.0.0/figures/ |
判读截图 | 数十张 |
/files/ltstdb/1.0.0/notes/ |
临床注释 | 逐记录文本 |
/files/ltstdb/1.0.0/trends/ |
趋势图 | 每记录一张 24 小时图加五张六小时图 |
/files/ltstdb/1.0.0/kl-single/ |
2011 版 KL 系数 | 子目录 |
/files/ltstdb/1.0.0/kl-single-uncentralized/ |
2015 版 KL 系数 | 子目录 |
/files/ltstdb/1.0.0/legendre/ |
Legendre 系数 | 子目录 |
/files/ltstdb/1.0.0/semia-3.0.1/ |
判读工具源码 | 压缩包约 119 KB |
5.2 用官方接口按需读取
wfdb 的远程读取走 PhysioNet 的接口,不需要整库落盘。对长记录尤其重要:一条记录 21 小时,两路 250 Hz 的浮点数组约三千万个采样点,一次读进来就会吃掉几百兆内存。
import wfdb
#-- 只读头,先确认结构再决定读哪一段
h = wfdb.rdheader('s30661', pn_dir='ltstdb')
print(h.record_name, h.n_sig, h.fs, h.sig_len, h.comments)
#-- 用 wfdb 命令行镜像整库到本地目录,适合长期复现
python3.11 -m wfdb.io.dl_database ltstdb ./ltstdb_local -r s20011 -r s20021 -r s30661
上面两条覆盖了两种典型用法:探索阶段只读头,正式实验前先镜像本期要用的记录子集。整库镜像在磁盘上是几十个数字节字节的量级,建议先算好预算再动手。
5.3 按段读取与内存控制
21 小时的记录不适合整条加载进内存做逐拍统计。按小时切片、循环处理、只保留派生的指标,是更稳的做法:
import wfdb
import numpy as np
rec = wfdb.rdrecord('s20011', pn_dir='ltstdb', sampto=250 * 3600)
ann = wfdb.rdann('s20011', 'atr', pn_dir='ltstdb', sampto=250 * 3600)
rr = np.diff(ann.sample) / rec.fs
print('一小时心搏数', len(ann.sample), 'RR 中位数', round(float(np.median(rr)), 3))
把 sampto 换成逐小时推进,就能在固定内存占用下扫完整条记录。注意 rdann 的 sampto 与 rdrecord 必须一致,否则心搏时刻会落在信号区间之外,后续取窗会越界。
5.4 三套事件标注的读取与对照
事件标注的辅助注释里存放类别,读取后应当先按类别汇总,再与 .cnt 对照:
import wfdb
from collections import Counter
rows = []
for name in wfdb.get_record_list('ltstdb'):
line = {'record': name}
for ann_name in ('sta', 'stb', 'stc'):
ann = wfdb.rdann(name, ann_name, pn_dir='ltstdb')
line[ann_name] = len(ann.sample)
rows.append(line)
print(rows[:3])
这段代码一次遍历 86 条记录会触发 258 次远程请求,在慢速网络上很费时。更稳的做法是先镜像本地再跑,或者只取记录清单的一小段做链路验证。
5.5 构造训练样本时的三个选择
| 选择点 | 做法 A | 做法 B | 建议 |
|---|---|---|---|
| 事件口径 | 用 sta,事件最多 | 用 stc,事件最少 | 与目标文献对齐,并在文中写明 |
| 正负样本 | 缺血事件为正,非缺血事件为负 | 缺血事件为正,其余时间为负 | 优先 A,负类才有判读依据 |
| 数据划分 | 按记录随机切 | 按受试者切 | 必须 B,否则同一人跨两侧 |
第三个选择点最容易被忽视。86 条记录来自 80 名受试者,按记录随机切分时,同一受试者的两条记录约有六分之一的概率落在两侧。这个比例不高,但足以让指标出现难以解释的乐观偏差,而这类偏差在审稿中往往成为质疑的焦点。
§4.4 的案例在这一点上尤其有用:只需把 s20271 与 s20272 两条记录放在一起看,就能直观理解「同一受试者的记录长得像」这件事为什么必须通过分组划分来消除。
5.6 六个最容易出错的地方
| 出错点 | 表现 | 处理 |
|---|---|---|
| 两路信号同名 | 按名字做字典键,一路被覆盖 | 按列下标访问 |
| 期望存在缺血标签 | 找不到布尔数组,误以为数据缺失 | 事件在 .sta 到 .stc,不在信号里 |
把 .16a 当标签 |
阈值化得到的事件与专家标注不符 | 标签取自事件层 |
| 三套阈值混用 | 跨论文复现数字对不上 | 先确认口径,再比较 |
| 整条加载进内存 | 21 小时数组耗尽内存 | 按小时切片 |
| 按记录随机划分 | 同一受试者跨训练与测试 | 按末位数字折叠到受试者 |
这六条的共同特征是「不会报错」。数据能读出来、模型能训完、指标也像样,只是结论建立在错误的样本或错误的标签上。与其在论文被质疑时回头排查,不如在读数据的第一天就把这六条逐一核对。
5.7 与派生数据目录的取舍
官方在 2009、2011、2015 三次追加了正交变换系数。这三套数据都在原记录之外,各有子目录:
| 子目录 | 内容 | 生成年份 | 是否中心化 |
|---|---|---|---|
legendre |
Legendre 正交变换归一化与非归一化系数 | 2009 | 不适用 |
kl-single |
单导联 KL 基函数与系数 | 2011 | 是,按均值中心化 |
kl-single-uncentralized |
另一套单导联 KL 基函数与系数 | 2015 | 否 |
两套 KL 数据的差别不只是中心化。官方说明,它们用不同方法剔除噪声心搏,因而基于不同的协方差矩阵导出基函数,两套基函数本身也有细微差别。这意味着两套系数不能逐列对比,做跨年份复现时必须以当时使用的那一套为准,并在文中写明目录名。
§6 与库内条目的关系
6.1 关系图谱
| 关系 | 库 | 连接点 | 差异 |
|---|---|---|---|
| 最易混淆的近邻 | ltdb | 同为长时程动态心电,同用 WFDB | ltdb 七条、128 Hz、无 ST 层;本库 86 条、250 Hz、三层 ST |
| 前身与前作 | edb | 本库有十条记录源自 edb 的原始采集 | edb 每条仅两小时,本库为完整一天 |
| 共同的建设者 | mitdb | MIT 团队同时参与两库建设 | mitdb 是半小时段、心律失常标注 |
| 同为长时程 | ltafdb | 都是二十余小时 Holter | ltafdb 面向房颤,无 ST 层 |
| 同源短记录 | edb | 判读协议与术语一致 | 本库对同一批信号做了重新数字化 |
| 补充对象 | aha 数据库 | 官方称本库与这两库互补 | 本库侧重复极,那两库侧重节律 |
关系图谱里最需要说清的是 ltdb 那一行。两者常被误当成同一个库的两代版本,实际是两条独立项目:ltdb 由 MIT 与波士顿贝斯以色列医院合作,目标是证明长时程逐搏标注可行;本库由卢布尔雅那牵头、三地联合判读,目标是把缺血与非缺血的鉴别写进标注。记录名体系也不同,ltdb 用五位数字,本库用以 s 开头的编号。
6.2 检索路径
在站内按名称找同族库容易漏,因为 long-term 有长时程、长期、长程等多种译法,ST 又常与段、改变、偏移混写。按标签与关键词检索更稳:
#-- 按标签与关键词粗筛,覆盖长时程、ST 段与缺血三组说法
bash scripts/qf_psql.sh "select record_id, url_name, left(title,60)
from ai_ready_dataset
where title ilike '%长时程%' or title ilike '%ST%'
or title ilike '%缺血%' or title ilike '%Holter%'
order by record_id;"
import wfdb
#-- 以官方清单为准,不要凭记忆写记录名
names = wfdb.get_record_list('ltstdb')
print(len(names), names[:5], names[-5:])
检索时的一个经验:判断一个心电库能不能做 ST 任务,最快的办法是看它有没有 .stf 或 .sta 这类扩展名的文件。有,说明存在函数层或事件层;没有,无论简介写得多像,都只能做心搏与节律。
6.3 与其他长时程库的分工判据
| 你的任务 | 首选 | 次选 | 判据 |
|---|---|---|---|
| 缺血事件检测与鉴别 | ltstdb | 无 | 只有它同时有缺血与非缺血事件 |
| 长时程心搏检测快速验证 | ltdb | ltstdb | 体量与时长权衡 |
| 房颤负荷分析 | ltafdb | ltstdb | 前者有节律标注,后者只有变化点 |
| 与短记录逐事件精读 | edb | ltstdb | 短记录便于逐段细看 |
| ST 段形态学表征 | ltstdb | 无 | 附带正交变换系数 |
| 跨库外部验证 | 任一异源库 | — | 关键在来源不同 |
6.4 三个库的规模差背后是什么
七十、六十余、八十余这三个数字经常被拿来比较,但它们回答的是不同的问题。短记录库要的是「每个事件的细节都能被反复看」;七条那个库要的是「最小的完整流程」;本库要的是「足够多的缺血与非缺血对照」。
本库选择 21 至 24 小时而不是更长,是因为动态心电监护在临床上的自然单位就是一整天,超过一天会增加记录失败率,而事件密度并不会成比例增加。选择 250 Hz 而不是更低,是因为 ST 段的幅度变化以微伏计,需要足够的采样密度与较宽的动态范围来支撑 16 秒平均。这两处选择都能从建库目标反推出来,理解了因果,就不会抱怨它为什么不是 500 Hz。
| 库 | 规模动因 | 由此决定的采样率 | 由此决定的标注层 |
|---|---|---|---|
| ltdb | 证明流程可行 | 128 Hz | 心搏与质量两层 |
| edb | 逐事件精读 | 250 Hz | ST 事件与节律 |
| 本库 | 缺血与非缺血对照 | 250 Hz | 逐搏、测量、事件三层 |
6.5 什么时候该换库
第一种情形,任务需要十二导联或需要明确的体表导联位置。本库不提供。第二种情形,任务需要长时程房颤负荷,应当换到 ltafdb 一类有节律标注的库。第三种情形,任务需要结构化临床变量,任何 PhysioNet 心电库都不够,必须接入带电子病历的数据源。
反过来,有三种情形它几乎是最优解:需要带负类标注的缺血鉴别任务;需要在完整一天上评测动态 ST 跟随能力;需要 ST 段的正交变换表征。这三种需求都建立在「事件被精读且分类清楚」之上,而不是建立在规模之上。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
先纠正一个最容易发生的误判:把「事件被挑选过」直接读成「数据有偏、不能用」。本库确实不是按人群抽样建的,它按「是否出现 ST 改变」来选记录,因此库内的事件密度远高于自然人群。但这个选择是建库目标的一部分,不是执行失误——缺血检测器需要密集的正例与负例才能调参,若按自然发生率抽样,一整天的记录里可能一次事件都碰不上,评测根本无从展开。
校正之后的评价尺度应该是两条。第一,在它自己声称能回答的问题上,证据够不够硬:缺血与非缺血事件被三地专家独立判读并会商,这个证据强度在公开数据集里属于上限。第二,它在哪些问题上不能被引用:任何涉及发生频率、患病比例的陈述都超出了它的证据范围。把这两条分开,就不会把「有偏」误判成「不可用」,也不会反过来把「专家标注」误读成「人群代表」。
第三个需要校正的误判是「老」。2000 年的判读工具与今天的工作站相比确实简陋,但判读的核心动作——标 PQ 结与 J 点、建基线参考、逐事件定性——没有变过。库里的中间产物被完整保留,恰恰让这套判断可以被逐个复查,这一点比很多只给最终标签的新库更有价值。
7.1 五维评分
按 DAIMS 的常用维度打分,每项 1 至 5 分,针对「作为心肌缺血检测算法研究数据」这个用途:
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 4 | 86 条 21 至 24 小时记录,长时程同类中最多 |
| 标注质量 | 5 | 三地专家独立判读后会商,非缺血事件也被单独标出 |
| 任务适配 | 4 | 缺血鉴别与动态 ST 跟随高度适配,缺十二导联与结构化临床变量 |
| 文档完整 | 4 | 官方页面给出文件级说明与判读流程,导联位置未逐条列出 |
| 可获取性 | 4 | 免注册、ODC-BY 1.0,但单条体积大,站点对脚本抓取有限制 |
五项合计 21 分(满分 25)。分数分布很有辨识度:标注质量拉满,规模与适配次之,可获取性因为体量与访问限制被扣了一分。这个分布说明它属于「贵但值」的一类资源——下载与处理成本不低,但拿到手之后标注的可信度是最高的那一档。
7.2 标注质量的三个可检验面
| 检验面 | 能否在库内自行检验 | 手段 |
|---|---|---|
| 事件起止是否落在偏移曲线上 | 能 | 用 .stf 的偏移函数与 .sta 区间对照 |
| 三套阈值是否自洽 | 能 | 用 .cnt 的计数与逐套读取结果对照 |
| 缺血与非缺血的类别码是否正确 | 不能 | 需要临床金标准,库内不提供 |
| 专家之间的一致性系数 | 不能 | 官方只描述流程,未给出统计量 |
| 逐搏测量与事件是否矛盾 | 能 | 把 .16a 曲线叠加到事件区间上看 |
前三项能自查,后两项只能依赖官方叙述。这意味着写论文时可以说「本库的事件标注由三地专家会商形成」,但不能说「标注一致性达到某个数值」,因为那个数值从未公布。
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 选择偏差 | 记录按出现 ST 改变挑选 | 事件密度被抬高,不能估计发生率 |
| 时长上限 | 每条 21 至 24 小时 | 无法观察跨两天的现象 |
| 导联数 | 两路或三路 | 无法做十二导联形态学对照 |
| 导联语义 | 官方未逐条公布对应体表位置 | 跨库对齐时导联错配无法排除 |
| 年代与地域 | 取材 1994 至 2000 年,美欧临床场景 | 设备与判读习惯偏旧 |
| 阈值口径 | 三套标注并存 | 跨论文比较时数字对不上 |
| 重数字化差异 | 十条来自欧洲 ST-T 库的记录被重缩放 | 与原库注释不能逐点对齐 |
| 临床变量缺失 | 无结构化用药与随访 | 不能做结局或多模态建模 |
关于阈值口径这一条,可以用 §4.4 的案例说明它的实际后果:同一条记录在三套标注下的事件数不同,若两篇论文分别用了 sta 与 stc,它们的样本量自然不同,讨论灵敏度与特异度时若不对齐口径,差异里就混进了标注定义的分歧,而不是算法本身的能力差。
7.4 外部验证矩阵
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 跨库缺血检测 | 在短记录库调参,本库测试 | 事件定义同源,类别码可对齐 | 掉分混合了时长与人群差异 |
| 动态 ST 算法评估 | 用 .stf 的偏移函数做逐秒比对 |
函数层可比,不依赖事件定义 | 需要自己实现偏移函数重算 |
| 可穿戴 ST 监测 | 用真实长时程噪声验证鲁棒性 | 含完整一天的活动与伪迹 | 导联位置不确定 |
| 正交变换方法比较 | 用附带 KL 与 Legendre 系数对照 | 同一批信号,系数现成 | 两套 KL 版本不可逐列对比 |
| 教学与判读训练 | 用官方截图与趋势图做案例 | 中间产物完整 | 结论不能当研究成果 |
跨库验证是它最常见的用法。基本逻辑是在记录短、事件密的库里训练,换到本库上看连续一天的表现。本库在这个位置上的独特价值是它自带负类:很多库只有「有事件」的标注,本库还标出了「长得像事件但不算」的片段,这让误报分析从定性变成可定位。
7.5 它为何能持续:把判读过程留在了数据里
二十多年过去,它依然是 ST 段相关研究绕不开的基准,原因不在于规模,而在于它保留了判读的完整链路。多数数据集只交付结论,本库交付的是结论加过程:基线怎么建的、参考点放在哪、偏移函数长什么样、同一段信号在三套阈值下各是什么结果。任何新方法想证明自己学到了判读逻辑而不是记住了标签,最终都要回到这份材料上比对。这个位置不会因为新库更大而被挤掉,因为新库往往没有这么细的过程记录。
§8 生态位与历史
8.1 历史沿革
项目的起点是 1995 年的美斯联合研究,最初的目标是为短暂心肌缺血的自动检测建立评测资源。1996 年起,团队连续在 Computers in Cardiology 上报告方案与进展,逐步确定「长时程 + 事件级标注 + 多国会商」这条路线。到 2002 年主体完成时,库的规模与判读协议已经定型。
上线节奏是分批的。2000 年 11 月先以 1.0.0 版本在 PhysioNet 亮相,但当时可下载的记录很少;2003 年 2 月一次性开放一半,2007 年 6 月补齐全部。这种分批方式在当年的存储条件下很常见,也解释了为什么目录里同时保留了 RECORDS-2003 这份只有 43 行的旧清单。
8.2 与欧洲 ST-T 库、MIT-BIH 库的分工
| 库 | 记录时长 | 主攻方向 | 与本库的关系 |
|---|---|---|---|
| edb | 2 小时 | ST 段与节律的逐事件精读 | 本库十条记录的原始采集来源 |
| mitdb | 30 分钟 | 心律失常分类 | 共享注释码与 WFDB 格式 |
| ltdb | 14 至 24 小时 | 长时程心搏与信号质量 | 同族但目标不同,最易混淆 |
| 本库 | 21 至 24 小时 | 缺血与非缺血事件的鉴别 | 兼有长时长与 ST 层 |
三者的分工可以用一句话概括:短库负责把单个事件讲清楚,长库负责把一整天的背景讲清楚,本库要同时做到这两件事,代价是记录数与导联数都做了取舍。
8.3 生态位:缺血检测的评测靶场
| 角色 | 主力件 | 靶场件 |
|---|---|---|
| 典型用途 | 预训练、节律分类、多任务学习 | 缺血检测评测、ST 判读复核 |
| 需要的前提 | 数据量大、标签多 | 事件被精读、含负类 |
| 代表资源 | 大规模心电语料、ltafdb | 本库、edb |
| 失败模式 | 标签噪声、事件定义模糊 | 结论不可外推、样本量有限 |
本库坐在右边这一列。它不适合用来把模型训强,但几乎无法被替代:要证明一个缺血检测器在真实一天里既能抓住缺血、又不把体位偏移判成缺血,只有这里能给出逐事件可核对的答案。
8.4 谁在用它,用来做什么
从公开文献的摘要看,使用者集中在三类。第一类是算法组,把本库当作缺血检测器的标准评测集,常与短记录库配合使用——短库训练、本库长跑。第二类是信号处理组,研究 ST 段的表征方式,直接取用库内的 KL 与 Legendre 系数做方法比较。第三类是临床工程与教学,用官方提供的趋势图与判读截图讲解轴线偏移、基线漂移与缺血偏移的区别。
三类用法的共同点是都不指望它给出人群结论,只指望它给出可核对的判读过程。这个定位一旦确立,它在体量与导联上的限制就都变得可以接受。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 算法研究者 | 按 §5.2 读头文件,跑通 §4.4 的三次读取 | 定口径、按受试者划分、建基线 | 先确认用哪一套阈值 |
| 信号处理工程师 | 抽一条记录算 ST 偏移函数 | 与 .stf 的官方函数对照 |
注意两路同名信号的列序 |
| 教学与临床工程 | 用官方截图讲一次判读 | 让学生自己标参考点再对照 | 说明轴线偏移为何不算缺血 |
9.2 一条最短的可用流程
#-- 1. 取清单,确认条数与编号区间
python3.11 -m wfdb.io.dl_database ltstdb ./ltstdb_local -r s20011
#-- 2. 确认本地文件齐全,头、信号、三套事件标注各一份
ls ltstdb_local/*/s20011.* | sed 's|.*/||' | sort
import wfdb
#-- 3. 读信号、事件与逐搏测量,先看结构再谈算法
rec = wfdb.rdrecord('./ltstdb_local/s20011/s20011')
sta = wfdb.rdann('./ltstdb_local/s20011/s20011', 'sta')
st16 = wfdb.rdann('./ltstdb_local/s20011/s20011', '16a')
print(rec.n_sig, rec.fs, rec.sig_len)
print('sta 事件数', len(sta.sample), '16a 测量数', len(st16.sample))
跑完这两段,就已经完成「下载、读取、确认三层结构」三步。剩下的工作是把同一套代码套到其余记录上,并按首位数字把两路与三路记录分开处理。
9.3 引用方式
| 引用对象 | 内容 | 说明 |
|---|---|---|
| 数据集 | Long-Term ST Database, version 1.0.0. PhysioNet. 2000. | 必带版本号 |
| 方法学论文 | Jager F, et al. MBEC 41(2):172-182, 2003 | 官方页面指定为原始出版物 |
| 标识符 | DOI 10.13026/C2G01T | 指向 v1.0.0 |
| 许可 | ODC-BY 1.0,署名即可,含商业用途 | 以许可全文为准 |
官方页面把方法学论文作为「使用本资源时请引用」的原始出版物,这与许多只给平台引用的库不同。写论文时应当两篇都引:一篇说明数据来源与判读方法,一篇说明托管平台。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,结构与事实由编辑把关 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面与方法学论文摘要 |
| 文件核验 | RECORDS 清单经直接访问确认为 86 行 |
| 未核验 | 逐记录头文件、.cnt 计数与逐条体积未逐一下载核对 |
| 统计口径 | 未做事件频次排序、未做时长分布直方图、未做字段空值交叉表 |
| 论文信息 | 仅检索 Europe PMC 摘要,未读全文 |
| 未核验内容 | 逐人年龄性别、专家一致性、导联对应体表位置、全库压缩体积 |
| 免责 | 本文不构成临床建议;使用须遵守 ODC-BY 1.0 署名要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「ltstdb 是 ltdb 的新版本」 | 两个独立项目,记录名与标注层都不同 | 官方两页并存,DOI 不同 |
| 「它有逐搏的缺血标签」 | 缺血判断在事件层,不在信号层 | .sta 到 .stc 才是事件标注 |
| 「三套标注是宽容度递进的修订版」 | 三条并列判据,服务不同应用 | 官方说明三套阈值并存 |
| 「86 条记录就是 86 名受试者」 | 80 名受试者,一人可有多条记录 | 官方摘要与记录命名规则 |
| 「记录是自然人群抽样」 | 按出现 ST 改变挑选 | 官方称按事件出现与否选记录 |
| 「导联对应关系写在头文件里」 | 官方未逐条公布体表位置 | 描述里未列出导联映射表 |
「可以直接用 .16a 当标签」 |
.16a 是测量量,不是判定 |
测量层与判定层分属不同文件 |
| 「与 edb 的记录可以逐点对齐」 | 十条记录被重新数字化并缩放 | 官方明确提示不可直接比较 |
| 「七条与八十六条是同一批磁带」 | 两库受试者关系官方未说明 | 官方未给出交叉对照 |
| 「两百兆就能下完」 | 单条信号 50 至 130 兆,全库量级高两个数量级 | 目录列表的逐文件字节数 |
FAQ
Q1:ltstdb 和 ltdb 到底差在哪?
差在记录数、采样率与标注层。ltdb 七条、128 Hz,只标心搏与信号质量;本库 86 条、250 Hz,另标逐搏 ST 测量、三套 ST 事件与非缺血事件。两者是不同机构主导的两条项目线,官方未说明受试者是否重叠。
Q2:它包含多少条缺血事件?
方法学论文写的是 1155 条短暂缺血性 ST 事件,另有与心率相关的事件以及体位、传导异常引起的非缺血事件。这个数字对应的是论文采用的判定口径,三套标注各自的总数需要读 .cnt 文件才能确定。
Q3:86 条记录是 86 个人吗?
不是,是 80 名受试者。同一人的多条记录只在记录名末位数字上不同,例如 s20271 与 s20272 属于同一人。做划分时必须先按末位折叠到受试者,再切分训练与测试。
Q4:为什么同一条记录有三套事件标注?
因为不同应用需要的灵敏度与时长门槛不同。sta 为 75 微伏、30 秒,stb 为 100 微伏、30 秒,stc 为 100 微伏、60 秒。三套是并列口径,不是版本迭代,合并使用会得到无法解释的结果。
Q5:能直接拿它训练缺血分类模型吗?
能,但要按受试者划分,并且要在文中写明用的是哪一套事件口径。库内事件被显著富集,模型学到的先验不能直接迁移到自然人群,指标只能用于同库内的算法比较。
Q6:它的记录为什么是 21 到 24 小时,不是完整 24 小时?
因为动态监护的实际时长受佩戴、取下与电极接触状况影响,很难精确凑满 24 小时。官方给的区间是 21 至 24 小时,规划切片时按每条的实际采样点数计算,不要假定每条约等于 24 小时。
Q7:两路信号在头文件里同名,怎么区分?
按列下标区分,不要按名字建字典。头文件里两路都写作 ECG,按名字取键会互相覆盖,最后只剩一路信号而不报错。这属于静默错误,读数据的第一天就该核对列数。
Q8:它跟欧洲 ST-T 库是什么关系?
本库有十条记录的原始采集来自欧洲 ST-T 库,那批记录在原库里只有两小时节选,本库给出完整一天。但信号经过重新数字化与重新缩放,官方明确说明两库注释不能直接对齐比较。
Q9:库里的 KL 系数有两版,用哪一版?
看你要复现的研究用了哪一版。2011 版按均值中心化,2015 版不中心化,两套基函数也略有差别。做新方法时建议两版都跑,并说明结论对中心化是否敏感。
Q10:下载要注册吗?有没有使用限制?
不需要注册,按 ODC-BY 1.0 开放,署名即可,含商业用途。但站点对脚本直接抓取有限制,建议通过官方页面或 wfdb 的下载命令获取,并在下载后核对校验和。
Q11:它能做非缺血 ST 改变的研究吗?
能,这正是它的一个独特之处。体位改变引起的轴线偏移与传导异常引起的继发性偏移都被单独标注,可以直接作为研究对象,而不只是当作负类背景。
术语表
| 术语 | 解释 |
|---|---|
| ltstdb | Long-Term ST Database 的官方缩写 |
| ltdb | MIT-BIH 长时程心电库,同族但目标不同的另一个库 |
| edb | 欧洲 ST-T 数据库,本库十条记录的原始采集来源 |
| ST 段 | 心电图中 QRS 波群结束到 T 波开始之间的一段 |
| ST 偏移 | 未校正的 ST 水平减去基线参考函数后的差值 |
| 基线参考函数 | 由局部参考点连成的分段线性曲线,吸收体位改变造成的整体平移 |
| 局部参考点 | 专家在 ST 水平曲线上标出的锚点,用于构造基线 |
| PQ 结 | QRS 起点前的等电位处,判读时先标定的位置 |
| J 点 | QRS 终末与 ST 段起始的交界处 |
| ST 事件 | ST 偏移在满足阈值与时长条件后形成的持续区间 |
| 缺血性事件 | ST 偏移伴随心肌供血不足的事件 |
| 非缺血性事件 | 体位改变、传导异常等引起的 ST 偏移,不伴供血不足 |
| 轴线偏移 | 体位改变导致 QRS 主轴转动,连带 ST 段偏移 |
| SEMIA | 卢布尔雅那团队自研的半自动 ST 测量与标注图形工具 |
.stf |
存放每导联 ST 水平、基线参考与偏移函数的文本文件 |
.16a |
基于 16 秒滑动平均的逐搏 ST 测量文件 |
.sta / .stb / .stc |
三套阈值下的 ST 事件标注文件 |
.cnt |
三套事件标注的计数汇总 |
| KL 系数 | Karhunen-Loève 正交变换的系数,用于表征 ST 段或 QRS 形态 |
| Legendre 系数 | 以 Legendre 正交基展开得到的形态系数 |
| WFDB | PhysioNet 使用的波形数据库格式 |
| 动态心电图 | 受试者随身佩戴记录仪获得的连续长时程心电记录 |
| ODC-BY | 开放数据共享署名许可 |
| DAIMS | 数据资产管理与使用的一组成熟度评估维度 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 记录数 | 86 | 官方页面;RECORDS 逐行 |
官方页面 |
| 受试者数 | 80 | 官方摘要与论文摘要 | 官方页面 |
| 每条时长 | 21–24 小时 | 官方页面 | 官方页面 |
| 两路信号记录 | 65 | 清单首位为 2 的行数 | 官方文件 |
| 三路信号记录 | 21 | 清单首位为 3 的行数 | 官方文件 |
| 采样率 | 250 Hz | 官方页面 | 官方页面 |
| 量化 | 12 位,±10 毫伏 | 官方页面 | 官方页面 |
| 缺血性事件数 | 1155 | 方法学论文摘要 | 论文摘要 |
| 事件口径 | 75/100 微伏,30/60 秒 | 官方页面 | 官方页面 |
| 单条信号体积 | 50–130 兆字节 | 目录列表 | 官方文件 |
| 全库压缩体积 | 官方未给出 | — | 未核实 |
| 首批开放 | 43 条 | 官方新闻 | 官方页面 |
| 上线日期 | 2000-11-29 | 官方版本信息 | 官方页面 |
| 最近更新 | 2015-11-25 | 官方更新记录 | 官方页面 |
| 许可 | ODC-BY 1.0 | 官方页面 | 官方页面 |
| DOI | 10.13026/C2G01T | 官方页面 | 官方页面 |
附录 B:数字的来源分层
第一层:官方页面与官方清单。 记录数、受试者数、时长区间、采样率、量化位深、事件口径、日期、许可、DOI 来自 PhysioNet 项目页;86 行记录名与两路三路的分段来自 RECORDS 清单的逐行核对。这一层可直接引用。
第二层:论文摘要。 缺血性事件的数量、取材窗口、三地会商流程的描述来自方法学论文的摘要。引用时应写明是论文口径,与三套阈值的分项计数不是同一件事。
第三层:未核实。 全库压缩体积、逐人年龄性别分布、专家一致性统计、导联对应体表位置、单一受试者多条记录的完整对应表。这些官方未公布或本次未逐一下载核对,正文中只做定性描述。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | Long-Term ST Database v1.0.0 | https://physionet.org/content/ltstdb/1.0.0/ | 规模、结构、边界数据主来源 |
| 2 | 该库文件目录 | https://physionet.org/files/ltstdb/1.0.0/ | 文件类型、单条体积、子目录 |
| 3 | 记录清单 RECORDS | https://physionet.org/files/ltstdb/1.0.0/RECORDS | 86 行与两路三路分段 |
| 4 | Jager F 等,Long-term ST database,MBEC 41(2):172-182,2003 | https://doi.org/10.1007/BF02344885 | 建库目标、事件数、取材窗口 |
| 5 | Long-Term ST Database v1.0.0(ltdb 词条对照) | https://physionet.org/content/ltdb/1.0.0/ | §6.1 与 §8.2 的对照事实 |
| 6 | WFDB 格式与注释码规范 | https://physionet.org/physiotools/wag/ | 头文件、注释文件结构 |
| 7 | PhysioNet 平台综述,Nature Health,2026 | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 8 | Europe PMC 检索入口 | https://www.ebi.ac.uk/[europepmc](https://www.qianfanghub.com/ai-ready-dataset/europepmc/1353)/ | 论文摘要与外部用法 |
附录 D:任务代码
任务一:把清单折叠成受试者级分组
import wfdb
names = wfdb.get_record_list('ltstdb')
def subject_key(name):
#-- 同一受试者的记录只在末位数字上不同,去掉末位即得受试者键
return name[:4]
groups = {}
for n in names:
groups.setdefault(subject_key(n), []).append(n)
print(len(names), '条记录 ->', len(groups), '个受试者键')
print(sorted(groups.items())[:3])
任务二:一条记录的三套事件计数
import wfdb
name = 's20011'
for ann_name in ('sta', 'stb', 'stc'):
ann = wfdb.rdann(name, ann_name, pn_dir='ltstdb')
print(ann_name, '注释点数', len(ann.sample), '类别', sorted(set(ann.aux_note)))
两段代码都只读清单与注释,不加载信号本体,适合在链路验证阶段快速跑通。任务一的受试者键取值方式依赖命名规则,若官方未来调整命名,需要重新核对后再用。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 86 条记录、80 人、21 至 24 小时、250 Hz | 这四个数字定义了一切用法与成本 |
| 2 | 缺血判断在事件层,不在信号层 | 拿测量值当标签是最常见的误用 |
| 3 | 三套阈值并列,不可合并 | 跨论文比较前必须对齐口径 |
| 4 | 记录按事件挑选,不是人群抽样 | 任何发生率结论都超出证据范围 |
| 5 | 与 ltdb 是两个库,不是两代 | 记录名、采样率、标注层全不同 |
编辑说明
本篇的核验时间为 2026 年 10 月 28 日。核对方式为直接访问 PhysioNet 项目页与文件目录:项目页返回正常,据此确认 86 条记录、80 名受试者、21 至 24 小时、250 Hz、12 位量化、ODC-BY 1.0 与 DOI;记录清单经单独访问确认为 86 行,且首位为 2 的行有 65 条、首位为 3 的行有 21 条,与两路三路的分段一致。文件目录页给出各类文件的体积区间与十二个子目录。站点对逐文件直连与部分文档路径返回 403 或 502,故逐记录头文件、.cnt 计数与全库压缩体积未逐一下载核对,正文中凡涉及处均按「官方未给出」或按目录区间表述。方法学论文仅读 Europe PMC 摘要,未读全文。官方在记录数与受试者数上的两个口径已并列写在正文,未做取舍。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- wctecgdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- ahadb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- chfdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- crisdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- cudb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- ltdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- iafdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- mvtdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- nsrdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- stdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

