Scientific Agent Skills:IDC 数字病理数据查询实战指南(SM / ANN / SEG 索引表与 SQL 模式)
【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills
本篇围绕 NCI 影像数据共同体(Imaging Data Commons,IDC)中的数字病理数据,讲解如何用idc-index客户端的本地 DuckDB 索引表,对全切片显微图像(Slide Microscopy,SM)、显微批量简单标注(Microscopy Bulk Simple Annotations,ANN)与病理分割(SEG)做元数据发现、肿瘤/正常组织区分和预计算分析结果的检索。读完后,你将能够脱离 BigQuery,直接对 IDC v24 数据版本执行病理相关的 SQL 查询,并掌握从索引发现到下载、测量提取的完整工作流。
以下内容继承自技能包中的数字病理参考文档 skills/imaging-data-commons/references/digital_pathology_guide.md,并结合本仓库 skills/imaging-data-commons/SKILL.md 的索引表总览与 scripts/check_version.py 的版本校验逻辑进行了扩充说明。
版本基线:idc-index 0.12.5 与 IDC 数据版本 v24
原指南在开头明确标注:Tested with: idc-index 0.12.5(IDC 数据 version v24)。这是一个必须重视的前提——所有查询列名(如min_PixelSpacing_2sf、primaryAnatomicStructureModifier_CodeMeaning)和示例结果(如 TCGA-BRCA 的幻灯片计数)都以该版本为准,版本升级后列结构可能变化。
仓库中这一版本约束有双重佐证:
- skills/imaging-data-commons/SKILL.md 的 frontmatter 元数据中固定了
idc-index: "0.12.5"与idc-data-version: "v24"; - scripts/check_version.py 中
MIN_VERSION = "0.12.5"、SKILL_VERSION = "1.8.1",脚本本身从不执行安装,仅在版本不满足时打印面向当前解释器的安装命令并以非零码退出,把环境选择权留给调用者。
因此,开始数字病理查询前的标准动作是:
# 在技能包根目录运行,校验 idc-index 是否安装且版本不低于 0.12.5 python skills/imaging-data-commons/scripts/check_version.py会话内则用客户端确认数据版本:
from idc_index import IDCClient client = IDCClient() # 校验 IDC 数据版本(应为 "v24") print(f"IDC data version: {client.get_idc_version()}")对于通用查询与下载(非病理专属),主技能文档 SKILL.md 提供了完整的路由规则(MCP / REST / 本地索引三选一);本篇只聚焦其中的病理分支:SM、ANN、SEG 三类对象。
五张病理专用索引表
数字病理的核心是五张专门化的索引表。它们携带人工整理的(curated)元数据,无需 BigQuery即可完成绝大多数发现工作:
| 表 | 行粒度 | 说明 |
|---|---|---|
sm_index | 1 行 = 1 个 SM 系列 | 全切片显微系列元数据:容器/玻片 ID、组织类型、解剖结构、诊断、物镜倍数、像素间距、图像尺寸 |
sm_instance_index | 1 行 = 1 个 SM 实例 | 单张切片图像的实例级(SOPInstanceUID)元数据 |
seg_index | 1 行 = 1 个 SEG 系列 | DICOM 分割元数据:算法名、segment 数量、源系列引用。放射与病理共用——需按源 Modality 过滤出病理分割 |
ann_index | 1 行 = 1 个 ANN 系列 | 显微批量简单标注系列元数据;含referenced_SeriesInstanceUID,指向被标注的切片 |
ann_group_index | 1 行 = 1 个标注组 | 标注组细节:AnnotationGroupLabel、GraphicType、NumberOfAnnotations、AlgorithmName、属性编码 |
这些表与本仓库 references/index_tables_guide.md 中的完整索引表清单一致,该文档的"Join Column Reference"小节还给出了一致性更强的连接键约定,与病理相关的四条是:
| 表 A | 表 B | 连接条件 |
|---|---|---|
index | sm_index | index.SeriesInstanceUID = sm_index.SeriesInstanceUID |
index | seg_index | index.SeriesInstanceUID = seg_index.segmented_SeriesInstanceUID |
index | ann_index | index.SeriesInstanceUID = ann_index.SeriesInstanceUID(取标注系列自身);ann_index.referenced_SeriesInstanceUID = index.SeriesInstanceUID(取被标注的源系列) |
ann_index | ann_group_index | ann_index.SeriesInstanceUID = ann_group_index.SeriesInstanceUID |
两条硬性规则贯穿所有后续示例:
- 查询任何索引表之前先
client.fetch_index("table_name")。该调用对所有表(包括启动时自动加载的)都安全且幂等。 - 写 SQL 前先查 schema:用
client.indices_overview程序化检查列名与类型,或client.get_index_schema('table')读取缓存的元数据。不要凭记忆假设列名——这是 IDC 查询返回空结果的第一大原因(主技能文档在 Discovery 一节反复强调同一模式:先枚举值,再过滤)。
Slide Microscopy(SM)查询
基本 SM 元数据
sm_index是病理元数据最丰富的表。下面按集合统计切片数量与最高分辨率(min_PixelSpacing_2sf保留两位小数的最小像素间距,间距越小分辨率越高):
from idc_index import IDCClient client = IDCClient() # sm_index 元数据详尽;与 index 连接可取 collection_id client.fetch_index("sm_index") client.sql_query(""" SELECT i.collection_id, COUNT(*) as slides, MIN(s.min_PixelSpacing_2sf) as min_resolution FROM sm_index s JOIN index i ON s.SeriesInstanceUID = i.SeriesInstanceUID GROUP BY i.collection_id ORDER BY slides DESC """)按物镜倍数找高分辨率系列
ObjectiveLensPower记录物镜倍率。找 40 倍及以上、按分辨率排序的高清切片:
client.fetch_index("sm_index") client.sql_query(""" SELECT i.collection_id, i.PatientID, s.ObjectiveLensPower, s.min_PixelSpacing_2sf FROM sm_index s JOIN index i ON s.SeriesInstanceUID = i.SeriesInstanceUID WHERE s.ObjectiveLensPower >= 40 ORDER BY s.min_PixelSpacing_2sf LIMIT 20 """)按标本制备方式过滤(染色 / 包埋 / 固定)
sm_index包含染色(staining)、包埋介质(embedding)、固定液(fixative)三类元数据。注意这些列是数组类型——例如 H&E 切片会是[hematoxylin stain, water soluble eosin stain],因此过滤要用array_to_string()配LIKE,或用list_contains(),直接对数组列做等值匹配会漏掉多值行:
# 在指定集合中找 H&E 染色切片 client.fetch_index("sm_index") client.sql_query(""" SELECT i.PatientID, s.staining_usingSubstance_CodeMeaning as staining, s.embeddingMedium_CodeMeaning as embedding, s.tissueFixative_CodeMeaning as fixative FROM sm_index s JOIN index i ON s.SeriesInstanceUID = i.SeriesInstanceUID WHERE i.collection_id = 'tcga_brca' AND array_to_string(s.staining_usingSubstance_CodeMeaning, ', ') LIKE '%hematoxylin%' LIMIT 10 """)跨集合比较 FFPE 石蜡切片与冷冻切片:
client.sql_query(""" SELECT i.collection_id, s.embeddingMedium_CodeMeaning as embedding, COUNT(*) as slide_count FROM sm_index s JOIN index i ON s.SeriesInstanceUID = i.SeriesInstanceUID GROUP BY i.collection_id, embedding ORDER BY i.collection_id, slide_count DESC """)区分肿瘤与正常切片
sm_index提供了两条互补的组织类型识别路径:
| 列 | 适用场景 |
|---|---|
primaryAnatomicStructureModifier_CodeMeaning | 来自 DICOM 标本元数据的结构化组织类型(如Neoplasm, Primary、Normal、Tumor、Neoplasm, Metastatic)。在所有含 SM 数据的集合上通用。 |
ContainerIdentifier | 切片/容器标识。TCGA 集合中该字段是 TCGA 条形码,其中第 14–15 位的样本类型码编码组织来源:01–09= 肿瘤,10–19= 正常。 |
两条路径各有所长:结构化元数据跨集合通用,但可能为 NULL;条形码方法仅适用于 TCGA 集合,却能兜底结构化元数据缺失的情况。
路径一:结构化组织类型元数据
先枚举全库组织类型取值,再按集合统计。以下结果基于 idc-index 0.12.5 / IDC v24 数据:
from idc_index import IDCClient client = IDCClient() client.fetch_index("sm_index") # 发现所有 SM 数据中的组织类型取值 client.sql_query(""" SELECT s.primaryAnatomicStructureModifier_CodeMeaning as tissue_type, COUNT(*) as slide_count FROM sm_index s WHERE s.primaryAnatomicStructureModifier_CodeMeaning IS NOT NULL GROUP BY tissue_type ORDER BY slide_count DESC """)以 TCGA-BRCA 为例:
# TCGA-BRCA 的组织类型分布 client.sql_query(""" SELECT s.primaryAnatomicStructureModifier_CodeMeaning as tissue_type, COUNT(*) as slide_count, COUNT(DISTINCT i.PatientID) as patient_count FROM sm_index s JOIN index i ON s.SeriesInstanceUID = i.SeriesInstanceUID WHERE i.collection_id = 'tcga_brca' GROUP BY tissue_type ORDER BY slide_count DESC """) # 指南记录的结果:Neoplasm, Primary(2704 张)、Normal(399 张)路径二:TCGA 条形码(仅限 TCGA 集合)
TCGA 集合中ContainerIdentifier即切片条形码(如TCGA-E9-A3X8-01A-03-TSC),第 4 段的前两位就是样本类型码:
# 从 TCGA 条形码解析样本类型码 client.sql_query(""" SELECT SUBSTRING(SPLIT_PART(s.ContainerIdentifier, '-', 4), 1, 2) as sample_type_code, s.primaryAnatomicStructureModifier_CodeMeaning as tissue_type, COUNT(*) as slide_count FROM sm_index s JOIN index i ON s.SeriesInstanceUID = i.SeriesInstanceUID WHERE i.collection_id = 'tcga_brca' GROUP BY sample_type_code, tissue_type ORDER BY sample_type_code """) # 指南记录的结果:01 → Neoplasm, Primary(2704),06 → None(8),11 → Normal(399)条形码方法的价值在最后一行数据上:类型码06(转移灶)对应的 8 张切片在 TCGA-BRCA 中primaryAnatomicStructureModifier_CodeMeaning为 NULL——只依赖结构化元数据的查询会静默丢掉这些切片。实践建议是两条路径并用,用条形码兜底 NULL 情况。
标注(ANN)查询
DICOM Microscopy Bulk Simple Annotations(Modality = 'ANN')是画在显微切片图像之上的标注对象。它们分两级出现在索引中:ann_index(系列级)与ann_group_index(标注组级)。每个 ANN 系列通过referenced_SeriesInstanceUID指向它标注的那张切片——这是做"标注 ↔ 原图"关联的唯一桥梁。
基础标注发现
# 找标注系列及其引用的原图系列 client.fetch_index("ann_index") client.fetch_index("ann_group_index") client.sql_query(""" SELECT a.SeriesInstanceUID as ann_series, a.AnnotationCoordinateType, a.referenced_SeriesInstanceUID as source_series FROM ann_index a LIMIT 10 """)标注组统计
按图形类型汇总标注总量(点、线、多边形等):
client.sql_query(""" SELECT GraphicType, SUM(NumberOfAnnotations) as total_annotations, COUNT(*) as group_count FROM ann_group_index GROUP BY GraphicType ORDER BY total_annotations DESC """)带源切片上下文的标注检索
三级连接:标注组 → 标注系列 → 被引用的源系列,从而拿到集合归属与算法名:
client.sql_query(""" SELECT i.collection_id, g.GraphicType, g.AnnotationPropertyType_CodeMeaning, g.AlgorithmName, g.NumberOfAnnotations FROM ann_group_index g JOIN ann_index a ON g.SeriesInstanceUID = a.SeriesInstanceUID JOIN index i ON a.referenced_SeriesInstanceUID = i.SeriesInstanceUID WHERE g.AlgorithmName IS NOT NULL LIMIT 10 """)全切片显微图像上的分割(SEG)
DICOM Segmentation(Modality = 'SEG')同时服务放射(CT 器官分割)与病理(WSI 组织区域分割)。隔离病理分割的关键是:用seg_index.segmented_SeriesInstanceUID找到源系列,再按源的 Modality 过滤为'SM':
# 找源为显微切片的分割 client.fetch_index("seg_index") client.fetch_index("sm_index") client.sql_query(""" SELECT seg.SeriesInstanceUID as seg_series, seg.AlgorithmName, seg.total_segments, src.collection_id, src.Modality as source_modality FROM seg_index seg JOIN index src ON seg.segmented_SeriesInstanceUID = src.SeriesInstanceUID WHERE src.Modality = 'SM' LIMIT 20 """)注意这里seg_index连接的是index(源系列),而不是sm_index——index_tables_guide.md 的连接键参考表明确index.SeriesInstanceUID = seg_index.segmented_SeriesInstanceUID。sm_index的 fetch 是为后续需要切片级属性(分辨率、物镜)时再连接做准备。
查找预计算分析结果(Analysis Results)
IDC 托管派生数据集——核分割、TIL(肿瘤浸润淋巴细胞)图、AI 标注——在主index表中以analysis_result_id标识。analysis_results_index表用于发现病理方向上有哪些现成结果可用:
from idc_index import IDCClient client = IDCClient() client.fetch_index("analysis_results_index") # 找包含病理标注或分割的分析结果 client.sql_query(""" SELECT ar.analysis_result_id, ar.analysis_result_title, ar.modalities, ar.subjects, ar.collections FROM analysis_results_index ar WHERE ar.modalities LIKE '%ANN%' OR ar.modalities LIKE '%SEG%' ORDER BY ar.subjects DESC """)区分两个 ID 的职责(主技能文档 IDC Data Model 一节的定义):collection_id定位原始影像数据(其中可能自带入库时的标注),analysis_result_id定位跨一个或多个原始集合的派生对象。找 AI/专家生成的标注用后者。
为特定切片找全部派生数据
# 找 TCGA-BRCA 切片的全部派生数据(标注、分割) client.fetch_index("ann_index") client.sql_query(""" SELECT i.analysis_result_id, i.PatientID, a.referenced_SeriesInstanceUID as source_slide, g.AnnotationGroupLabel, g.NumberOfAnnotations, g.AlgorithmName FROM ann_group_index g JOIN ann_index a ON g.SeriesInstanceUID = a.SeriesInstanceUID JOIN index i ON a.SeriesInstanceUID = i.SeriesInstanceUID WHERE i.collection_id = 'tcga_brca' LIMIT 10 """)索引表之外的测量值:标注对象内还可携带逐条标注的测量(如核面积、偏心率),它们存在于 DICOM 文件内部而不在索引表中。指南给出的处理方式是:下载后用 IDC 官方维护的 highdicom 库提取,调用链为ann.get_annotation_groups()→group.get_measurements()。原指南同时指向了 IDC-Tutorials 中的microscopy_dicom_ann_intro教程(含空间分析与细胞密度计算的完整示例)——该教程位于仓库外部,这里仅说明这条提取路径存在,具体 API 以 highdicom 官方文档为准。
按 AnnotationGroupLabel 过滤
AnnotationGroupLabel是按名称或语义内容找标注组最直接的列,用LIKE通配做文本检索(配合LOWER()做大小写不敏感匹配):
简单标签过滤
# 按标签找标注组(如包含 "blast" 的组) client.fetch_index("ann_group_index") client.sql_query(""" SELECT g.SeriesInstanceUID, g.AnnotationGroupLabel, g.GraphicType, g.NumberOfAnnotations, g.AlgorithmName FROM ann_group_index g WHERE LOWER(g.AnnotationGroupLabel) LIKE '%blast%' ORDER BY g.NumberOfAnnotations DESC """)带集合上下文的标签过滤
# 在特定集合内按标签找标注组 client.fetch_index("ann_index") client.fetch_index("ann_group_index") client.sql_query(""" SELECT i.collection_id, g.AnnotationGroupLabel, g.GraphicType, g.NumberOfAnnotations, g.AnnotationPropertyType_CodeMeaning FROM ann_group_index g JOIN ann_index a ON g.SeriesInstanceUID = a.SeriesInstanceUID JOIN index i ON a.SeriesInstanceUID = i.SeriesInstanceUID WHERE i.collection_id = 'your_collection_id' AND LOWER(g.AnnotationGroupLabel) LIKE '%keyword%' ORDER BY g.NumberOfAnnotations DESC """)这个模式与 references/sql_patterns.md 中 "Query Slide Microscopy and Annotation Data" 一节的示例相互印证——该文档把更完整的 SM 查询、ANN 过滤、SM+ANN 交叉引用统一指向本篇指南,可见本篇是技能包内病理 SQL 模式的权威落点。
SM + ANN 交叉引用
要找"显微切片数据上有哪些标注",需要 SM 与 ANN 两张表同时参与。连接枢纽仍是ann_index.referenced_SeriesInstanceUID,只不过这一次把它接到sm_index而非index上,从而直接携带源切片的物镜信息:
# 找集合中显微切片及其标注 client.fetch_index("sm_index") client.fetch_index("ann_index") client.fetch_index("ann_group_index") client.sql_query(""" SELECT i.collection_id, s.ObjectiveLensPower, g.AnnotationGroupLabel, g.NumberOfAnnotations, g.GraphicType FROM ann_group_index g JOIN ann_index a ON g.SeriesInstanceUID = a.SeriesInstanceUID JOIN sm_index s ON a.referenced_SeriesInstanceUID = s.SeriesInstanceUID JOIN index i ON a.SeriesInstanceUID = i.SeriesInstanceUID WHERE i.collection_id = 'your_collection_id' ORDER BY g.NumberOfAnnotations DESC """)注意两个 JOIN 的语义区别:JOIN sm_index s ON a.referenced_SeriesInstanceUID = s.SeriesInstanceUID走的是引用方向(标注 → 被标注的原图),而JOIN index i ON a.SeriesInstanceUID = i.SeriesInstanceUID走的是标注系列自身的归属(用于取collection_id)。混用这两个键是此类查询最常见的错误。
Join 模式速查
原指南给出的两个基础连接模式:
SM 连接(切片显微细节 + 集合上下文)
client.fetch_index("sm_index") result = client.sql_query(""" SELECT i.collection_id, i.PatientID, s.ObjectiveLensPower, s.min_PixelSpacing_2sf FROM index i JOIN sm_index s ON i.SeriesInstanceUID = s.SeriesInstanceUID LIMIT 10 """)ANN 连接(标注组 + 集合上下文)
client.fetch_index("ann_index") client.fetch_index("ann_group_index") result = client.sql_query(""" SELECT i.collection_id, g.AnnotationGroupLabel, g.GraphicType, g.NumberOfAnnotations, a.referenced_SeriesInstanceUID as source_series FROM ann_group_index g JOIN ann_index a ON g.SeriesInstanceUID = a.SeriesInstanceUID JOIN index i ON a.SeriesInstanceUID = i.SeriesInstanceUID LIMIT 10 """)配套工具生态
原指南末尾列出与数字病理工作流配套、基于 DICOM 格式的工具链,按用途分三类(工具名保留,供读者自行检索其官方仓库):
Python 库
- highdicom(IDC 官方开发):高层 DICOM 抽象,用于创建和读取 DICOM Segmentation(SEG)、Structured Report(SR)与 parametric map,覆盖病理与放射场景;也是提取前文提到的逐条标注测量的推荐路径。
- wsidicom:读取 DICOM WSI 数据集的 Python 包,把元数据解析为易用的 dataclass,面向全切片图像分析。
- TIA-Toolbox:端到端计算病理库,通过
DICOMWSIReader支持 DICOM,提供 tile 提取、特征提取与预训练深度学习模型。 - EZ-WSI-DICOMweb:通过 DICOMweb 从 DICOM 全切片图像中抽取图像块,面向云 DICOM 存储的 AI/ML 工作流。
查看器
- Slim(IDC 开发):基于 Web 的 DICOM 显微切片查看器与标注工具,通过 DICOMweb 支持明场与多重免疫荧光成像。主技能文档也提到
client.get_viewer_URL()对 SM 系列会自动路由到 SLIM。 - QuPath:跨平台开源全切片图像分析软件,经 Bio-Formats 与 OpenSlide(v0.4.0 起)支持 DICOM WSI;主技能文档的故障排查一节同样把 QuPath 列为病理 DICOM 打不开时的备选查看器。
格式转换
- dicom_wsi:将专有 WSI 格式转换为符合 DICOM 规范的文件的 Python 实现。
实践清单与排错要点
综合本篇与技能包其余文档,数字病理会话的标准实践是:
- 先验版本:
check_version.py通过 +client.get_idc_version()返回v24,再开始查询; - 先 fetch 后查询:
sm_index、sm_instance_index、seg_index、ann_index、ann_group_index、analysis_results_index全部需要client.fetch_index(...)前置; - 先查 schema 后写 SQL:用
client.indices_overview核对列名;病理列名(如staining_usingSubstance_CodeMeaning)带 CodeMeaning 后缀且可能是数组类型; - 先小后大:探索期一律
LIMIT,确认集合规模再考虑下载——主技能文档提醒部分集合以 TB 计; - 区分连接方向:
referenced_SeriesInstanceUID/segmented_SeriesInstanceUID指向源系列,SeriesInstanceUID自身连接指向对象自身的归属; - 打不开下载文件时:主技能文档的 Troubleshooting 建议先检查
Modality与SOPClassUID,用pydicom.dcmread(file, force=True)验证,SEG、RTSTRUCT、SR 与显微切片都需要专用工具(3D Slicer、QuPath 等)而非普通放射查看器。
需要完整索引表清单、临床数据连接或下载工作流时,可继续参阅 index_tables_guide.md、sql_patterns.md、cli_guide.md 与 use_cases.md——它们与本篇指南同属 skills/imaging-data-commons/ 技能包,按主文档 Quick Navigation 表的触发条件按需加载即可。
【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考