信息速览
CMS 开放数据是欧洲核子研究中心(CERN)大型强子对撞机上 CMS 实验的公开数据出口。它把 2010 年以来质子—质子对撞与重离子对撞的事例,连同对应的蒙特卡洛模拟,一起放进一个基于 Invenio 的门户里,逐条编号、逐条发 DOI、逐条给许可。挂在 CERN Open Data Portal 名下的记录共 82,414 条,其中 57,889 条属于 CMS,是这个门户里最大的一块,比排第二的 DELPHI 多出四倍半。
它最容易被误判的地方在于「一个数据集」这四个字。这 57,889 条里只有 345 条是真实对撞记录,剩下的五万多条绝大多数是把同一批物理过程用软件重新跑一遍得到的模拟事例。同一份物理内容还会以四种不同的还原层级分别发布一次,最厚的与最薄的在字节上相差两百倍,而这四百多倍的落差里,真正能被普通机器学习流程直接吃下的只有最薄的那一种。
下面的速览表把最该先定下来的几件事排在一起,后面的章节再逐项展开。
| 项目 | 数值 | 来源 |
|---|---|---|
| 全门户记录数 | 82,414 | 门户 API 聚合 |
| CMS 记录数 | 57,889(占 70.2%) | 同上 |
| 其中 Dataset | 51,963 | 同上 |
| 其中 Supplementaries | 5,748 | 同上 |
| 其中 Software | 46(多数 GPL-3.0-only) | 同上 |
| 真实碰撞记录 | 345 | type.secondary:Collision |
| 模拟记录 | 51,365 | type.secondary:Simulated |
| 派生记录 | 253 | type.secondary:Derived |
| 触发配置记录 | 4,149 | type.secondary:Trigger |
| 覆盖年份 | 2010–2016,另有 2024 样本 2 条 | 年份聚合 |
| 格式 | AOD / MiniAOD / NanoAOD / RECO / RAW | file_type 聚合 |
| 体积阶梯 | AOD→MiniAOD 约 1/10,NanoAOD 约 1/200 | 官方 about-cms 原文 |
| 许可 | CC0 1.0(数据与元数据) | 使用条款页 |
| 引用单位 | 每条记录一个 DOI | 官方说明 |
| 软件依赖 | NanoAOD 免 CMSSW;AOD 须 CMSSW | 官方入门页 |
§1 速览:它是什么,也不是什么
§1.1 一句话定义
CMS 开放数据是一份按「格式 × 年份 × Primary Dataset」切块发布的粒子对撞事例存档,每一块是一个自洽的分析单元,自带格式说明、重建软件版本、触发配置、质量认证清单和 DOI。
它不是一份可以直接喂给模型的特征表,也不是一个统一的数据库。它是一个按物理分析的组织方式摆放的仓库:你要先选年份,再选格式,再选 Primary Dataset,最后才拿到一堆 ROOT 文件。
§1.2 为什么它不算「普通表格数据」
把它当普通表格处理,会在四个地方卡住,而这四点恰好定义了它区别于一般 AI 数据集的地方。
第一,一个文件里有一百多棵树,每棵树有上千个分支,分支之间还有变长数组。NanoAOD 的主树叫 Events,一行是一个事例;但同一个事例里可能有十几个缪子、二十几个喷注,所以 Muon_pt 不是一列浮点数,而是一列「浮点数组」。这在 Parquet 里对应 list<float>,在 pandas 里对应一个 object 列。官方入门页给的示例命令 t->Draw("Muon_pt","Muon_pt < 2000") 之所以能跑,是因为 ROOT 的 TTree 原生支持这种 jagged 结构。
第二,体量与信息量不是线性关系。同一批 1 亿个事例,在 NanoAOD 里是 131 GB,在 MiniAOD 里是 3.89 TB。多出来的 3.7 TB 装的是径迹协方差矩阵、量能器簇的逐个读出、粒子流候选的四维动量——这些信息对重做重建有用,对「拿喷注特征训练一个标记器」几乎全是噪声。
第三,数据本身经过算法加工,不是原始读数。AOD 里的每一个「电子」「缪子」「喷注」都是软件从探测器信号里重建出来的对象,带着标记位、能量修正、误判概率。这些对象不是观测事实,是带假设的推断结果。用之前必须知道用的是哪一版重建。
第四,它的检索结果默认把模拟和真实混在一起。不显式按 type.secondary 过滤,你会在同一个列表里看到 /TTTo2L2Nu_TuneCP5_13TeV-powheg-pythia8/RunIISummer20UL16NanoAODv9-106X_mcRun2_asymptotic_v17-v1/NANOAODSIM 和 /BTagCSV/Run2016G-UL2016_MiniAODv2_NanoAODv9-v1/NANOAOD 并排躺着。前者是软件生成的,后者是真机记录。混着用,任何结论都不成立。
§1.3 三十秒决策卡:你的处境,它能帮你什么
| 你的处境 | 它能帮你什么 |
|---|---|
| 想在真实科学数据上试一个新的集合模型 / 图神经网络 | NanoAOD 的 Events 树天然是变长集合:每个事例是一组喷注、一组缪子,元素数不等,正对应集合学习 |
| 需要一个十亿级参数、带物理约束的异常检测基准 | 用已知的标准模型过程做背景、用模拟的信号做前景,标签来自生成器而不是人工标注,没有标注噪声 |
| 想验证一个「可解释特征工程」方法在专家特征上的增益 | NanoAOD 的列本身就是三十年物理分析的专家特征沉淀,拿来当强基线非常合适 |
| 想训练一个从量能器图像到喷注类型的模型 | 需要回到 AOD 或 RECO 取低层沉积信息,NanoAOD 已经把图像压成了几个标量 |
| 需要一个体量可控、许可干净、可精确引用的公开数据集做教学 | NanoAOD 单条记录几十到一百多 GB,CC0,每条一个 DOI,可以直接写进论文的数据可用性声明 |
| 想做重离子物理、夸克胶子等离子体 | 走 RECO 格式,重离子数据官方就是用 RECO 发的,比 AOD 还厚 |
§1.4 不适合谁
如果你的需求是「下载一份 CSV,用 pandas 读进来跑 XGBoost」,那这份数据给不了你——官方在 about-cms 页上写得很直白:AOD 与 MiniAOD「cannot be opened (and understood) as simple data tables」,即使是 NanoAOD,也是 jagged 的 TTree,需要 uproot 或 awkward 才能变成可用的结构。
如果你的需求是「覆盖 2017、2018 年的数据」,它也给不了——Run2 的开放数据只放到 2016 年,2017 与 2018 的 CMS 碰撞数据至今没有以公开数据集形式发布,2024 年只有两条原始格式样本。
如果你的需求是「覆盖全部对撞事例」,它更给不了——公开的是每个 Primary Dataset 的一个子集,触发筛选已经在数据产生时发生过一次,你拿到的不是全部。
如果你的需求是「找到电子或缪子的图像」,它给不了——CMS 开放数据里没有事件显示图像,只有数值化的重建对象;想看图像得自己去画。
§1.5 贯穿本文的案例:一条 131 GB 的 NanoAOD 记录
后面的章节会反复回到同一条记录:/BTagCSV/Run2016G-UL2016_MiniAODv2_NanoAODv9-v1/NANOAOD,门户编号 30517,DOI 10.7483/OPENDATA.CMS.QCRI.DFDV。
选它做贯穿案例,是因为它同时满足四个条件,这在 57,889 条记录里并不多见。
第一,它是真实碰撞数据,type.secondary 为 Collision,不是模拟;第二,它在同一门户里有一整条完整的格式链可以对照——同一个 Primary Dataset 的 2015D 版本同时有 AOD 与 MiniAOD,2016G 版本同时有 MiniAOD 与 NanoAOD,2016H 版本同样两者齐全,四条记录的 distribution.size 一除,官方那句「200 倍」就有了可核对的落点;第三,它的元数据里带着完整的重建链,从 RECO 到 PAT 到 NANO 三步的 CMSSW 版本号与 global tag 一个不缺;第四,它是 B 夸克标记的专用数据集,/BTagCSV/ 这个前缀本身就说明这批事例是按「至少两个 b 标记喷注」这一物理条件在线筛选出来的,正好用来讲「选择偏差从数据产生那一刻就开始了」。
它有多大:63 个文件,100,826,567 个事例,131,283,319,089 字节。平均下来每个事例 1,302 字节。第一章后面每次要说「体积」或「事件数」,指的都是这条记录。
§2 数据构成:57,889 条记录到底在记什么
§2.1 三层口径:门户、实验、数据集
数字对不上,通常是因为口径不同。三层口径要分开记。
第一层是门户。CERN Open Data Portal 当前有 82,414 条记录,覆盖 CMS、ATLAS、ALICE、LHCb 四个 LHC 实验,加上 DELPHI、OPERA、JADE、TOTEM、PHENIX 五个已结束或小规模的实验。
| 实验 | 记录数 | 说明 |
|---|---|---|
| CMS | 57,889 | 主体 |
| DELPHI | 12,757 | LEP 时代(1989–2000)的旧实验 |
| LHCb | 9,348 | 底夸克物理专用 |
| OPERA | 912 | 中微子振荡 |
| ATLAS | 189 | 教学样本为主 |
| ALICE | 171 | 重离子 |
| JADE | 147 | PETRA 时代旧实验 |
| TOTEM | 3 | 弹性散射 |
| PHENIX | 1 | RHIC 时代的单个遗留记录 |
第二层是 CMS 内部。57,889 条按 type 分成七类,其中 Dataset 51,963 条才是「数据」,Supplementaries 5,748 条是配套件(文件索引、触发路径说明),Software 46 条是可运行的分析代码,Environment 55 条是软件环境与运行条件,Documentation 55 条是文档,News 13 条、Glossary 9 条是站点内容。
第三层是 Dataset 内部。这 51,963 条能被三个互不重叠的 type.secondary 标签完整切开:碰撞 345 条、模拟 51,365 条、派生 253 条。三者相加正好等于 51,963,一条不多一条不少。
| 层级 | 口径 | 数量 | 占比 |
|---|---|---|---|
| 门户 | 全部记录 | 82,414 | 100% |
| 实验 | CMS | 57,889 | 70.2% |
| 类型 | Dataset | 51,963 | 63.1% |
| 类型 | Supplementaries | 5,748 | 7.0% |
| 次级 | Collision | 345 | 0.42% |
| 次级 | Simulated | 51,365 | 62.3% |
| 次级 | Derived | 253 | 0.31% |
最后两列的对比是整份数据的性格所在:真实碰撞数据占 CMS 记录的 0.42%。这个比例不是缺陷,是粒子物理的工作方式——每一个真实事例背后,实验组要生成几十上百倍的模拟事例来估计探测效率、本底形状与系统误差。但从「我要一份数据集」的角度看,这意味着检索时必须先想清楚自己要的是哪一种,否则默认结果里 99.6% 是软件产物。
§2.2 三种次级标签与一个不存在的字段
type.secondary 的四个取值各有明确含义,混用会直接毁掉分析。
Collision 是真实对撞记录。345 条,覆盖 2010 至 2016,外加 2017 年 1 条、2024 年 2 条。它们的 file_type 分布是:AOD 207 条、RECO 36 条、NanoAOD 32 条、MiniAOD 51 条,另有 24 条 RAW。注意这些标签可以重叠,同一条记录可能既是 raw 又是 aod 的上游,所以加起来会超过 345。
Simulated 是蒙特卡洛模拟。51,365 条,是整个库的主体。它们的 file_type 是 AODSIM 859 条、MiniAODSIM 28,693 条、NanoAODSIM 21,575 条。模拟数据的组织方式与真实数据镜像对称:一个信号过程或本底过程,配一个产生器设置、一个探测器模拟版本、一个重建版本。
Derived 是派生集。253 条,从真实数据或模拟数据再加工出来的精简格式。nanoaod-reduced、nanoaod-poet、nanoaod-run1 这些非标准格式标签基本都落在这里。它们通常服务于特定分析或教学,命名不带标准三段式,DOI 也不一定有。
Trigger 是触发配置。4,149 条,记的是 HLT 触发路径的定义、版本与生效 run 区间。它们属于 Supplementaries,不是数据,但复现分析时缺了它们就跑不通——你不知道当年哪些事例被哪条路径捞了上来。
这里必须纠正一个流传很广的说法:门户里没有 subtype 字段。用 subtype:Collision 去查,返回 0 条;正确的字段是 type.secondary。subtype 这个词在门户里确实存在,但它只用作文档检索的过滤参数(subtype=Guide),与数据记录的碰撞/模拟之分无关。把两者混为一谈,写出来的查询会静默返回空集。
§2.3 一条记录逐项解剖
拿 §1.5 那条记录(recid 30517)的元数据字段逐项拆开看。门户的每条记录都是一份结构化 JSON,字段不多,但每一个都承担着不同的职责。
{
"recid": "30517",
"title": "/BTagCSV/Run2016G-UL2016_MiniAODv2_NanoAODv9-v1/NANOAOD",
"type": {"primary": "Dataset", "secondary": ["Collision"]},
"experiment": ["CMS"],
"collision_information": {"energy": "13TeV", "type": "pp"},
"run_period": ["Run2016G"],
"date_created": ["2016"],
"date_published": "2024",
"date_reprocessed": "2021",
"doi": "10.7483/OPENDATA.CMS.QCRI.DFDV",
"license": {"attribution": "CC0-1.0"},
"distribution": {
"formats": ["nanoaod", "root"],
"number_events": 100826567,
"number_files": 63,
"size": 131283319089
}
}
| 字段 | 值 | 该怎么读 |
|---|---|---|
recid |
30517 | 门户内的引用号。网页地址是 /record/30517,API 是 /api/records/30517 |
title |
三段式数据集名 | 第一段 /BTagCSV/ 是 Primary Dataset,第二段是 run 区间加处理版本,第三段是格式 |
type.secondary |
["Collision"] |
真实碰撞。这一项决定它能不能当实验数据用 |
collision_information |
13TeV, pp | 质心能量 13 万亿电子伏特,质子—质子。注意这是物理条件,不是「是否真实」的标记 |
run_period |
Run2016G | 2016 年的第七个运行段,run 号 278820–280385 |
date_created |
2016 | 数据采集年份 |
date_published |
2024 | 上线年份,比采集晚了八年 |
date_reprocessed |
2021 | 重处理年份,Ultra-Legacy 重处理 |
doi |
10.7483/OPENDATA.CMS.QCRI.DFDV | 可解析到固定落地页,引用时应给出完整 DOI |
license.attribution |
CC0-1.0 | 机器可读的 SPDX 标识 |
distribution.size |
131,283,319,089 | 字节数,约 122 GiB |
distribution.number_events |
100,826,567 | 事例数,一亿零八十二万 |
这张表里最容易读错的是 collision_information。它写的是 13TeV 与 pp,看起来像是在说「这是真实数据」,其实不是。模拟数据的元数据里同样有 collision_information,因为模拟也要声明它模拟的是哪个能标、哪种碰撞。整个 CMS 记录里 collision_type 为 pp 的有 53,877 条,而真实碰撞记录只有 345 条——相差 156 倍。能标与碰撞类型是物理条件,真伪由 type.secondary 决定。
第二个易错点是 date_published 与 date_created 的分离。2016 年采的数据,2021 年重处理,2024 年才上线。这三个日期之间的落差解释了为什么老论文里的数字和门户上的对不上:它们用的是不同轮次的重建。
§2.4 与同类资源的定位差异
CERN 门户里另外三个 LHC 实验的数据,规模与用途都不同,值得放在一起看。
| 资源 | 记录数 | 主要格式 | 与 CMS 的分工 |
|---|---|---|---|
| CMS 开放数据 | 57,889 | AOD / MiniAOD / NanoAOD / RECO | LHC 上体量最大、格式层次最完整的开放数据集 |
| LHCb 开放数据 | 9,348 | 自定义 ntuple | 底夸克与粲物理,事例级 flat ntuple,比 NanoAOD 更接近表格 |
| ATLAS 开放数据 | 189 | 派生 ntuple | 以教学与可视化为主,13 TeV 教学样本是主力 |
| ALICE 开放数据 | 171 | AOD / ESD | 重离子碰撞,铅—铅与质子—铅 |
| DELPHI 开放数据 | 12,757 | 旧格式 | LEP 时代的电子—正电子对撞,历史价值大于分析价值 |
判断规则可以压成三句:要体量与格式层次、要做喷注与顶夸克 → CMS;要底夸克、要事例级扁平表 → LHCb;要重离子、要夸克胶子等离子体 → ALICE 的 RECO 与 CMS 的重离子子集并用。 至于 ATLAS,189 条记录里有相当一部分是为教学做的精简 ntuple,做严肃分析时它的统计量撑不起结论,但拿来做方法验证非常合适。
还有一个不在这张表里但必须提的邻居:HEPData。它收录的是论文里的表格与图表数值,不是事例级数据。要复现一张截面测量图,HEPData 给的是图上的点,CMS 开放数据给的是产生这些点的原始事例——两者的分工是「结论」与「证据」。
§3 格式层:四种格式,一条体积阶梯
这一章解决一个前置问题:同一份物理内容被包装成了四种厚薄不同的东西,你该拿哪一份。 这个问题不定下来,后面所有的下载规划、算力预算、代码写法都是空的。
§3.1 四种格式各自是什么
CMS 的还原流程是一条从原始读数到分析对象的流水线。每走完一段,产物就发一次,所以同一个 Primary Dataset 会在门户里留下几种不同的「版本」。
| 格式 | 全称 | 内容 | 谁需要它 |
|---|---|---|---|
| RAW | Raw data | 探测器读出、触发后的原始字节流 | 想从零重做重建的人;门户里只有 24 条样本 |
| RECO | Reconstructed | 重建后的完整对象集合,比 AOD 还厚 | 重离子分析;官方为重离子专门用这个格式发布 |
| AOD | Analysis Object Data | 全部高能物理对象、径迹及命中、量能器簇及命中、顶点、粒子流候选、触发信息 | 要做低层重建、要改喷注算法的人 |
| MiniAOD | Mini AOD | 对上者做了通用对象加工、提高存储阈值、丢掉部分低层信息 | 2015 年之后的常规分析 |
| NanoAOD | Nano AOD | 每个对象只留少量观测量、精度降低、探测器信息换成预计算好的标记结果 | 绝大多数分析,尤其是机器学习 |
官方在 about-cms 页上对 AOD 的内容有一段清单式的描述,值得原样记住:全部高能物理对象(缪子、电子等)、带关联命中的径迹、带关联命中的量能器簇、顶点、粒子流算法造出的候选粒子,以及事例选择(触发)信息与进一步筛选所需的数据。
MiniAOD 相对 AOD 的变化,官方用了三句话概括:物理对象被处理成带更多鉴别与选择信息的更轻的 C++ 对象;存储对象的横动量阈值提高;部分低层信息被移除。换句话说,MiniAOD 不是「AOD 的压缩包」,它在压缩的同时丢掉了重新做对象鉴别的可能性,把鉴别结果固化了下来。
NanoAOD 的变化更彻底。官方入门页的原话是:NanoAOD 不再基于 CMS 专用的 C++ 类,而是把数据存成 ROOT TTree 里的标准 C++ 类型,「因此你不需要使用 CMS 虚拟机或 docker 容器来分析 NanoAOD 数据」。about-cms 页补了一句关键的取舍:每个对象只保留有限的一组观测量、数值精度有限,探测器信息通常被换成预计算的鉴别算法结果,粒子流候选被直接丢弃——因为它们的用途本来就是作为更高层对象重建的输入。
§3.2 字节账:三个可以自己算出来的比值
官方说 AOD→MiniAOD 约十分之一,NanoAOD 约是 MiniAOD 的二十分之一、AOD 的二百分之一。这三个数字都能在门户的元数据里找到落点,只要同一个 Primary Dataset 在不同格式下都有记录。
/BTagCSV/ 这个 Primary Dataset 恰好提供了完整的两段链条。2015D 版本同时有 AOD 与 MiniAOD,2016G 与 2016H 版本同时有 MiniAOD 与 NanoAOD。
| 记录 | 格式 | 文件数 | 事例数 | 字节数 | 每事例字节 |
|---|---|---|---|---|---|
| /BTagCSV/Run2015D-16Dec2015-v1/AOD | AOD | 995 | 18,832,713 | 3,442,384,267,829 | 182,787 |
| /BTagCSV/Run2015D-16Dec2015-v1/MINIAOD | MiniAOD | 415 | 18,839,491 | 453,256,944,791 | 24,059 |
| /BTagCSV/Run2016G-UL2016_MiniAODv2-v1/MINIAOD | MiniAOD | 1,105 | 100,826,567 | 3,888,167,538,219 | 38,563 |
| /BTagCSV/Run2016G-UL2016_MiniAODv2_NanoAODv9-v1/NANOAOD | NanoAOD | 63 | 100,826,567 | 131,283,319,089 | 1,302 |
| /BTagCSV/Run2016H-UL2016_MiniAODv2-v2/MINIAOD | MiniAOD | 720 | 65,172,853 | 2,579,351,176,599 | 39,577 |
| /BTagCSV/Run2016H-UL2016_MiniAODv2_NanoAODv9-v1/NANOAOD | NanoAOD | 55 | 64,989,678 | 85,473,447,362 | 1,315 |
三组比值可以直接除出来。
第一组,2015D 的 AOD 与 MiniAOD:3,442,384,267,829 ÷ 453,256,944,791 = 7.59。按每事例字节算,182,787 ÷ 24,059 = 7.60。官方说「约十分之一」,这个 Primary Dataset 上实际是 7.6 分之一,比官方口径还要保守一点。差异来自数据本身:/BTagCSV/ 的事例里喷注多、径迹密,AOD 的径迹与簇信息占比高于平均水平,被 Ministep 压掉的绝对量也就更大。换一个轻事例为主的 Primary Dataset,比值会往 10 靠。
第二组,2016G 的 MiniAOD 与 NanoAOD:3,888,167,538,219 ÷ 131,283,319,089 = 29.61,每事例 38,563 ÷ 1,302 = 29.62。官方说「约二十分之一」,这里是 29.6 分之一。两组算法给出一致的答案,说明这一段的压缩比是稳定的。
第三组,把两段相乘:7.59 × 29.61 = 224.8。官方说 AOD 到 NanoAOD「约二百分之一」,两段真实链条乘出来是 225 分之一。误差在正常范围内,而且解释得通:第二段的 29.6 比官方的 20 更大,第一段的 7.6 比官方的 10 更小,两者部分抵消。
这个乘法是理解整份数据的关键。200 倍不是一个统计出来的平均值,是两段流水线压缩比的乘积。 它意味着 NanoAOD 相对 AOD 丢掉的,是第一段丢掉的低层信息(径迹协方差、簇的逐个读出)与第二段丢掉的低层信息(粒子流候选、未压缩的对象观测量、数值精度)叠加在一起的结果。
把 131 GB 和 3.89 TB 放在一起,还有一个更实际的换算。§1.5 的案例里那条 NanoAOD 有 63 个文件,平均每个文件约 2.1 GB;同一条链上的 MiniAOD 有 1,105 个文件,平均每个 3.5 GB。也就是说,MiniAOD 不但总量大 29.6 倍,文件数还多 17.5 倍——文件数对并行读取的影响往往比总量更致命,因为每一个文件都要单独打开、单独定位、单独付一次元数据开销。
§3.3 为什么官方主线仍然从 AOD 讲起
这是整份数据最值得说的一处错配。
打开 about-cms 页,正文的组织顺序是:先讲 Primary datasets 与重建,然后列 AOD 与 AODSIM 的内容清单,再讲 MiniAOD 是 Run2 起提供的、体积约十分之一,最后才用一段讲 NanoAOD,并说它「从 2016 年起与 MiniAOD 一起提供」。三段「Getting started」链接的排列也是 AOD(Run 1)、MiniAOD(Run 2)、NanoAOD(Run 2)。
这个顺序有它的历史理由。门户 2014 年上线时的主角是 Run1 的 AOD,那时候 MiniAOD 与 NanoAOD 还不存在;AOD 是唯一能覆盖 2010–2012 全部数据的形式,而 Run1 的 190 条碰撞记录(35 + 55 + 100,2010 至 2012 三个年份)至今仍然只有 AOD。文档的骨架是在那个阶段定型的,后来的格式是插进去的。
但对今天的使用者,这个顺序会把注意力引向错误的方向。NanoAOD 才是那个「装上 uproot 十分钟就能开始」的入口,而 AOD 是那个「先装 Scientific Linux 5、再 cmsrel CMSSW_4_2_8、再对着几百行配置调试」的入口。两个入口的启动成本差了一个数量级,官方页面上却把更贵的那个排在前面。
一个具体的对照:
| 环节 | NanoAOD 路径 | AOD 路径 |
|---|---|---|
| 操作系统 | 任意 | Scientific Linux(容器内) |
| 软件 | pip install uproot awkward |
CMSSW,按年份选版本 |
| 首行代码 | uproot.open(uri)["Events"] |
cmsRun 加一份配置 |
| 单文件读取 | 秒级 | 分钟级(需先编译) |
| 可否当表格 | 可以,jagged 列 | 官方明确说不可以 |
这不是说 AOD 没用。AOD 是唯一能做「重新做物理」的层级:改喷注聚类算法、换径迹拟合、研究粒子流候选的内部结构,这些只能回到 AOD。问题是这类工作的比例很低,而文档的主线是按「能做最多事」而不是「最多人要做的事」来排的。
判断规则:先问自己会不会修改重建,答案是不会,就从 NanoAOD 开始;只有当你需要 AOD 独有的信息时,才往下走一层。 这个判断应该在写第一行代码之前做,而不是在下载了 3 TB 之后。
§3.4 Run1 的类 NanoAOD:一个官方自己打的补丁
Run1 没有 NanoAOD,这件事官方是知道的,并且为此做了一件不太被提起的事。
门户里有 31 条记录,标题形如「Run2010A_EG dataset in Run1 NanoAOD-like format」,type.secondary 是 Derived,格式标签是 nanoaod-run1。其中一条(recid 31103)的摘要把动机与做法写得非常清楚:
Run2010A_EG dataset in a NanoAOD-like research-level Ntuple format for CMS Run1 data, readable with bare ROOT or other ROOT-compatible software, and containing the per-event information that is needed in most generic analyses. In contrast to the CMS NanoAOD which is derived from MiniAOD, this dataset is processed directly from the AOD format with code provided by the CMS open data group.
这段话里有三个信息点。第一,它明确承认存在一个「大多数常规分析所需」的信息子集,而 Run1 的标准格式给不了它。第二,它点明了技术路径的差别:标准 NanoAOD 从 MiniAOD 派生,这个类 NanoAOD 直接从 AOD 派生,因为 Run1 根本没有 MiniAOD。第三,它坦诚地说明了代价——「Not all variables are available」。
体量对得上的部分是:这条记录 88 个文件、47,187,984 个事例、60,347,549,466 字节,每事例 1,279 字节。§1.5 的案例里那条 2016G NanoAOD 是每事例 1,302 字节。两个相差六年的产物,每事例成本只差 1.8%——这说明「每事例一千三百字节」是 NanoAOD 这一层级的信息量下限,与年份无关,只与「保留哪些观测量」有关。
作为对照,2010 年 Run2010B 的一条 AOD 记录(recid 2)是 11,907,244 个事例、881,301,807,086 字节,每事例 74,014 字节。类 NanoAOD 是它的 57.9 分之一。这个比值低于官方的 200,因为 2010 年的 AOD 本身比 2016 年的 AOD 薄,而且类 NanoAOD 为了「与标准 NanoAOD 功能重叠」保留了比严格必要更多的量。
这条补丁的存在本身就是一条论据:连官方都承认「能直接读」比「信息完整」更接近多数人的需求,所以才专门为 Run1 再造一个格式。但这个补丁藏在 253 条派生记录里,不在 about-cms 的主线上,命名也不符合三段式,检索时很容易漏掉。
§3.5 RAW 与 RECO:两端各有一个例外
阶梯的两端各有一个容易被忽略的层级。
下端是 RAW。门户里有 24 条 RAW 记录,是最接近探测器的形态:触发之后的原始字节流,没有重建、没有物理对象。对绝大多数人没用,但它是「从零复现整个实验」这条路的起点。
上端是 RECO。官方的说明是:某些数据集,例如含重离子数据的那批,以 RECO 格式提供,它比 AOD 包含更多信息;这么做的原因是 CMS 合作组当年的原始分析就是用这个格式做的。Collision 记录里 RECO 有 36 条,而全库 file_type 为 reco 的只有 36 条——也就是说 RECO 几乎全部是碰撞数据,没有模拟。
这就形成一个反直觉的事实:厚度并不总与「离原始更近」同向。 RECO 比 AOD 厚,但它不是「更原始」,而是「更多信息被保留下来」;RAW 最原始,却最没用。判断该用哪一层,标准不是「哪层更接近真相」,而是「哪层还保留着你要改的那个环节的输入」。
§3.6 一张表收束:格式选择的完整判据
把上面几节压成一张决策表。左列是你要做的事,右列是该选的格式与理由。
| 你要做的事 | 该选 | 理由 |
|---|---|---|
| 训练喷注标记、事例分类、异常检测模型 | NanoAOD | 每事例 1.3 KB,jagged TTree,uproot 直读 |
| 复现一篇 2016 年的标准模型测量 | NanoAOD 或 MiniAOD | 先看原论文用的是哪版重建,版本要对齐 |
| 研究粒子流算法的内部结构 | AOD | 粒子流候选只在 AOD 及更厚层级存在 |
| 改喷注聚类算法并比较效果 | AOD | 需要簇与径迹的原始四维动量 |
| 做重离子碰撞的集体流分析 | RECO | 官方重离子数据就是 RECO 格式 |
| 从零走一遍完整重建 | RAW | 只有它能作为重建的输入 |
| 在 2010–2012 数据上做机器学习 | Run1 NanoAOD-like | 31 条派生记录,每事例约 1.3 KB |
| 复现触发效率研究 | Trigger 补充记录加 AOD | 触发路径定义与事例内容都要 |
| 教学演示、可视化 | 教学用精简 ntuple 或 NanoAOD | 体量小,依赖少 |
最后一行值得单独说一句。教学场景里体量小往往比信息全更重要,因为课堂时间容不下一次 3 TB 的下载。这也是为什么 ATLAS 的 189 条记录里有相当比例是专门为教学做的精简 ntuple——不是他们做不出完整数据,是他们知道教学要什么。
§4 内容层:TTree 里到底装了什么
§4.1 TTree 是列式存储,但不是 Parquet
ROOT 的 TTree 与 Parquet 在物理布局上有相似的出发点:都按列(ROOT 里叫 branch)分别存储,都为了让「只读几列」的查询不必扫全表。NanoAOD 一个文件里,Muon_pt 的所有值连续放在一起,Jet_pt 的所有值放在另一处,读 Muon_pt 时不会顺带把喷注的数据搬进内存。
但两者的差别比相似点更重要,有五处。
第一,元素可以是变长的。一个事例有 0 到几十个缪子,Muon_pt 这一列存的不是 float,而是 vector<float>。Parquet 用 list<float> 表达同样的语义,但 ROOT 的做法更古老也更直接:每个事例先存一个计数 nMuon,再存 nMuon 个值。这个「计数 + 值」的模式贯穿整个 NanoAOD,是理解它的第一把钥匙。
第二,没有统一的 schema 描述文件。TTree 的类型信息写在文件头里,但语义(这个 float 是横动量还是能量、单位是 GeV 还是 MeV)不在文件里,在外部文档里。Parquet 至少有 Arrow schema,语义仍要另外查,但结构至少是自描述的。
第三,压缩是按块做的,不是按列做的。ROOT 的压缩算法(通常是 ZLIB 或 LZ4)作用在篮子上,一个篮子装满若干事例的某一列。这带来一个后果:想读第 100 万个事例的某一列,得先定位到包含它的篮子,再解开整个篮子。随机访问的代价比 Parquet 的行组高。
第四,文件是「一次写死」的。ROOT 文件设计上不支持原地更新,所以数据集一旦发布就基本不再改,这与开放数据的冻结策略正好契合。
第五,生态是分裂的。C++ 侧是 ROOT 自己的 TFile/TTree 类,Python 侧原本要靠 PyROOT 绑定,现在的主流是 uproot——一个纯 Python 的独立实现,不需要装 ROOT。官方入门页点名推荐的就是 Scikit-HEP 生态里的 uproot 与 awkward。
对机器学习的实际影响是:你不能指望「读进来就是一个 DataFrame」。uproot 能做到 tree.arrays(["Muon_pt","Jet_pt"], library="ak") 返回 awkward 数组,那是一个能处理变长嵌套的结构,但要变成固定形状的张量,还得自己做 padding 或做集合模型。
§4.2 一个 Events 分支的解剖
NanoAOD 文件里有若干棵树,官方入门页说最重要的是 Events,其次是 Runs。Events 一行是一个事例,Runs 一行是一个 run 的汇总信息(总亮度、触发计数等)。
Events 的分支可以按含义分五组,这个分组不是官方的,是为了让第一次接触的人知道该从哪儿看起。
| 组 | 代表分支 | 一行的含义 |
|---|---|---|
| 定位 | run、luminosityBlock、event |
三元组唯一确定一个事例,也是与 validated runs 清单对齐的键 |
| 触发 | HLT_* 系列布尔量 |
该事例是否通过了某条触发路径 |
| 对象计数 | nMuon、nJet、nElectron |
该事例里各类对象的个数,变长数组的长度就来自这里 |
| 对象量 | Muon_pt、Muon_eta、Jet_pt、Jet_eta |
与计数一一对应的变长数组 |
| 汇总量 | MET_pt、PV_npvs |
每个事例一个标量:缺失横能量、重建顶点数 |
官方入门页给的交互式示例直接用了三个分支:Muon_pt 画横动量分布,Muon_pt < 2000 做截断(单位是 GeV,2000 GeV 即 2 TeV),Muon_tightId > 0 只留高纯度缪子,Muon_isTight > 0 配合权重做加权。这几个命令值得注意的地方是:判选条件写在字符串里,由 ROOT 在读取时求值,而不是先读进来再过滤。对 TB 级数据,这个差别就是「只搬需要的字节」与「全搬进来再扔」的差别。
Jet_pt 这类分支还有一个隐藏维度:一个事例里的喷注是按横动量降序排的,但「第一个喷注」不等于「最重要的喷注」——喷注算法可以输出多个互相重叠的喷注,官方在 about-cms 页上专门提醒了这一点:一个文件里通常含同一个物理对象的多份实例(同一个喷注用不同算法重建的各一份),有些对象还会被「重复计数」(一个对象既作为自己的类型出现,又作为某个喷注的组成部分出现)。取「前 N 个喷注」时如果不看算法标签,等于把不同算法的结果混在一起。
§4.3 重建是数据的一部分,不是前置黑箱
这是整份数据在方法论上最容易被忽略的一点。
一般的数据集,你拿到的是「测量结果」。CMS 开放数据给你的,是「经过一整套算法推断之后的对象」。AOD 里的一个电子不是「探测器看到的一个电子」,而是「软件认为这是一个电子,置信度多少,能量按什么规则修正过,从哪个顶点来的」。
§1.5 的案例把这条链记得清清楚楚。那条 2016G NanoAOD 记录的元数据里,methodology 字段逐段列出了三个步骤:
Step NANO Release: CMSSW_10_6_26 Global tag: 106X_dataRun2_v35
Output: /BTagCSV/Run2016G-UL2016_MiniAODv2_NanoAODv9-v1/NANOAOD
Step PAT Release: CMSSW_10_6_25 Global tag: 106X_dataRun2_v35
Output: /BTagCSV/Run2016G-UL2016_MiniAODv2-v1/MINIAOD
Step RECO Release: CMSSW_10_6_8_patch1 Global tag: 106X_dataRun2_v27
Output: /BTagCSV/Run2016G-21Feb2020_UL2016-v1/AOD
三个步骤、三个软件版本、两个 global tag。这份清单不是装饰,它是复现的必要条件:拿 CMSSW_10_6_26 去读 2015 年的 MiniAOD 会失败,拿 106X_dataRun2_v27 的标定去解释 2016G 的能量会偏。
global tag 这个东西尤其值得解释一句。它是「探测器状态、标定常数、对齐参数」的一整套版本化快照。同一批原始数据,用两个不同的 global tag 重建,得到的喷注能量会有系统性差别。所以「CMS 开放数据的喷注能量」这句话本身是不完整的,必须补上「在哪一版重建下」。
这就带来一个对机器学习很实际的后果:标签与特征共享同一条重建链,两者不能独立变化。 如果你用 NanoAODv9 的特征去配一篇用 2016 年旧版重建训练的标签,特征分布会对不上,而且对不上的方式不是随机的——能量刻度整体偏移会让模型学到假的阈值。
§4.4 真实与模拟:同一棵树,不同的物理含义
Collision 与 Simulated 的记录在结构上几乎一模一样:同样的三段式命名(只把 AOD 换成 AODSIM、NanoAOD 换成 NANOAODSIM)、同样的 Events 树、同样的一套分支名。这是设计上的刻意为之——为了让分析代码能在两者之间无缝切换。
但它们的语义差别是根本性的,有四处必须知道。
第一,模拟有「真值」。模拟事例在生成时就知道每个粒子的身份与四维动量,genpart 相关的分支记录的就是这个。真实数据没有真值,只有重建结果。用模拟训练、用真实评估,是标准做法;反过来用真实数据「训练」一个需要真值的任务,无从谈起。
第二,模拟需要加权。每个模拟事例代表多少个真实事例,由一个叫「产生截面除以生成事例数」的因子决定,再乘上亮度。不做这一步加权,模拟的分布就没有物理意义。NanoAOD 里通常有 Generator_weight 一类分支承载这件事。
第三,模拟的 pileup 分布是人为设定的。真实数据里同时发生的质子—质子相互作用数目(pileup)由加速器状态决定,模拟里要按测量到的分布去采样。这个分布选错,模拟的喷注能量响应就会偏。
第四,模拟不是全集。官方在 about-cms 页上明说:发布的模拟数据不是完整的模拟集合,只是那些用与对应碰撞数据兼容的软件版本重处理过的数据集。而且 2012 年的模拟有一部分只发布了书目信息,数据集本身要按需申请。这解释了门户里 availability 为 partial 的 20,105 条与 requested 的 15 条是怎么回事。
把这四点压成一句可操作的规则:训练可以用模拟,评估必须用真实数据;用模拟时必须加权;真实数据必须先过 validated runs。 三条里漏一条,结论就站不住。
§4.5 一个反直觉的细节:三个格式的事件数并不相等
§1.5 的案例还暴露了一个几乎没人提的事实。
2016G 的 MiniAOD 与 NanoAOD 事件数完全相同,都是 100,826,567。看起来「同一批事例,换个包装」。但 2016H 不是:MiniAOD 是 65,172,853,NanoAOD 是 64,989,678,差了 183,175 个事例,占 0.28%。2015D 更奇怪,AOD 是 18,832,713,MiniAOD 是 18,839,491,MiniAOD 反而多了 6,778 个。
这三个数字放在一起,说明「同一 Primary Dataset 的不同格式一一对应」这个假设不成立。可能的原因有几类:某些事例在某一级处理中被判为不合格而丢弃;某些 run 段在不同轮次的重处理中被纳入或排除;坏文件在重做时被替换成重新处理过的版本。官方没有在记录页上逐条解释这些差异,但 distribution.number_events 这个字段本身就把它们摆了出来。
对使用的实际影响有三条。
第一,不要用 AOD 的事件数去预估 NanoAOD 的样本量,误差可能到千分之几。要预估就直接查目标记录自己的 number_events。
第二,跨格式做「同一事例」的匹配时,只能用 run、luminosityBlock、event 三元组,不能假设第 N 行对第 N 行。而且既然事件集合不完全相同,匹配率不会是 100%。
第三,训练集与验证集必须按 run 或按亮度段切分,不能按行号切分。这一点在粒子物理里是常识,在机器学习里却不是:按行随机切分会让同一个事例的 MiniAOD 版本进训练、NanoAOD 版本进验证,模型学到的是「这个事例我见过」,不是规律。
§4.6 质量层:一份 TXT 文件决定了哪些事例能用
真实碰撞数据不是采集下来就都能用的。CMS 有一套数据质量认证流程:运行期间的每一次 run 都要经过值班人员初评与各物理对象组的专家复核,结果存进一个叫 Run Registry 的数据库,最后由数据质量监测组核验一致性,产出一份「认证过的 run 与亮度段清单」的 JSON 文件。
这份清单在门户里是独立记录。§1.5 的案例链接的就是 recid 14220,标题为 CMS list of validated runs Cert_271036-284044_13TeV_Legacy2016_Collisions16_JSON.txt,type 是 Environment,secondary 是 Validation,许可同样是 CC0-1.0。它的摘要写着:这个文件描述哪些 run 的哪些亮度段被认为是好的、应当被处理;覆盖 2016 年的 13 TeV 质子—质子碰撞;Run2016G 在 run 278820 到 280385 之间,Run2016H 在 280919 到 284044 之间。
关键的一条在 NanoAOD 入门页上,一句话,很容易漏掉:
Collision data in NanoAOD format has not been filtered to contain only the validated run segments.
也就是说,NanoAOD 里的碰撞数据没有按这份清单过滤过。下载下来的一亿个事例里,包含探测器状态不佳、某个子探测器高压异常、触发效率偏离的时段。官方把过滤的责任交给了使用者,并在每条碰撞记录的页面上放了清单链接。
这件事的分量取决于你要做什么。做教学演示、做方法验证,不过滤问题不大;一旦要报一个物理量的数值,不过滤就是错的,而且错得不容易被发现——坏时段的事例在分布上不会明显异常,只会让尾部变厚一点。
官方推荐的过滤工具是 NanoAOD-tools,一个跑在 CMSSW 之外的工具包,能做的事包括:把没过验证的事例剔掉、按分支内容做分析级筛选、丢掉不需要的分支以减小体积、为模拟计算常见的修正、在用户模块里算新观测量。
这条设计选择值得从「责任分配」的角度看一眼。门户没有替使用者做过滤,因为「哪些亮度段算好」依赖分析要什么——只做缪子分析时,缪子谱仪正常的时段就够用,不必要求全部子探测器都正常。记录页上确实给了两份清单(全验证与仅缪子验证),这个细节说明官方是有意把选择权交出去的。
§5 取数层:四条路径与它们各自的代价
把数据拿下来这件事本身有四类入口,选错的代价不是「慢一点」,而是「几天之后发现走不通」。
§5.1 四类入口一览
| 路径 | 入口 | 适用 | 代价 |
|---|---|---|---|
| REST API | https://opendata.cern.ch/api/records |
先摸清有多少、是什么、多大 | 只能拿元数据,拿不到事例 |
| 客户端 | cernopendata-client |
批量取文件清单、批量下载 | 需要装 Python 包,下载受带宽限制 |
| XRootD | root://eospublic.cern.ch//eos/opendata/... |
只读少量事例做探索、不落地 | 需要稳定网络,断线要重试 |
| 容器 | Docker 镜像加 CMSSW | 读 AOD、跑重建、跑官方示例 | 镜像数十 GB,还要按年份选版本 |
前三类是给 NanoAOD 用的,容器那一类基本只在需要 CMSSW 时才用。官方入门页对 NanoAOD 明确写了一句「你不需要使用 CMS 虚拟机或 docker 容器」,这句话的价值在于它把一个流传很广的误解直接否掉了——很多人以为碰 CMS 数据就必须先装那个几十 GB 的虚拟机。
§5.2 REST API:先查,再下
门户的 API 是 Invenio 的标准接口,返回 JSON,带聚合(aggregations)。聚合是这个接口最有用的部分:请求一条记录,返回里却带着整个结果集的分布统计。
一个最小的可用请求:
curl -sL "https://opendata.cern.ch/api/records?q=type.secondary%3ACollision&f=experiment&experiment=CMS&size=1" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['hits']['total'])"
这条命令输出 345。三个参数各有分工:q 是查询串,f 加 experiment 是 facet 过滤,size 控制返回几条。注意 curl 必须带 -L,因为门户对不带尾斜杠的路径返回 308 重定向,不跟随就会拿到一个空响应。
把 type.secondary%3ACollision 换成 type.secondary%3ASimulated,同一个命令输出 51,365。这两个数字就是整份数据的分水岭。
聚合统计的用法更省事。下面这条一次拿到 CMS 全部记录在格式、类型、年份三个维度上的分布:
curl -sL "https://opendata.cern.ch/api/records?q=&f=experiment&experiment=CMS&size=1" -o cms.json
python3 - <<'PY'
import json
d = json.load(open("cms.json"))
print("total", d["hits"]["total"])
for key in ("type", "file_type", "year"):
buckets = d["aggregations"][key]["buckets"]
print(key, [(b["key"], b["doc_count"]) for b in buckets])
PY
返回的 year 聚合里,键是毫秒时间戳而不是年份数字:1451606400000 对应 2016-01-01,计数 44,628。这一点很容易看错,把 1451606400000 当成一个数量级异常的年份。
有一个实操上必须知道的行为:大响应会被截断。带完整文件清单的记录 JSON 单条可以到几 MB,一次请求多条时响应体很容易超过链路的单次上限,json.load 就会抛 Unterminated string。绕法是:查清单用 size=1 加 facet 逐条筛,取单条用 /api/records/{recid},不要试图一次拉 100 条完整记录。
§5.3 客户端:批量取清单与批量下载
cernopendata-client 是官方维护的命令行工具,PyPI 上当前版本 1.0.2。它的三个子命令覆盖了从「看元数据」到「下文件」的全过程。
pip install cernopendata-client
cernopendata-client get-metadata --recid 30517
cernopendata-client get-file-locations --recid 30517 --protocol xrootd
cernopendata-client download-files --recid 30517
第一条打印该记录的全部元数据,第二条列出全部文件的位置(--protocol 可选 http 或 xrootd),第三条把文件下到当前目录。
get-file-locations 是这个工具最有价值的部分,因为它解决了「我要读的这条记录到底有哪 63 个文件」这个问题。§1.5 的案例里 63 个文件分布在 3 个文件索引里,手工点网页翻页很容易漏。拿到清单后再交给 uproot 或 xargs 并行处理,比逐个手点靠谱得多。
下载前值得先算一笔账:distribution.size 就是这个记录的总字节数。131 GB 的 NanoAOD 在千兆链路上要跑二十分钟左右,在受限出口上可能要跑一整天。先查 size 再决定下不下,是这份数据上最省时间的一条习惯。
§5.4 uproot 直读:不落地也能看
uproot 是纯 Python 的 ROOT 文件读取库,不需要装 ROOT 本身。它能读本地文件,也能通过 XRootD 协议直接读远端文件——后者对「只想看看数据长什么样」特别有用,因为不用先下 131 GB。
import uproot
uri = ("root://eospublic.cern.ch//eos/opendata/cms/Run2016G/BTagCSV/"
"NANOAOD/UL2016_MiniAODv2_NanoAODv9-v1/260000/"
"01472671-4A55-5A4A-B2CE-2C7990D279E3.root")
tree = uproot.open(uri)["Events"]
print(tree.num_entries)
print(tree.keys()[:20])
batch = tree.arrays(["nJet", "Jet_pt", "Muon_pt"], entry_stop=5000, library="ak")
print(len(batch["nJet"]), batch["Jet_pt"][0].tolist())
这段代码做四件事:打开远端文件、取出 Events 树、打印分支名、读前 5000 个事例的三列。library="ak" 让返回值是 awkward 数组,这是处理变长列的正确容器;用默认的 NumPy 后端会在遇到变长分支时报错。
entry_stop 这个参数值得单独说。它让「只读前 N 条」变成一个真正的优化,而不是先全读再切片——因为 TTree 是分块存的,读前 5000 条只需要解开前几个篮子。对 131 GB 的文件,带不带这个参数是「三秒」与「三分钟」的差别。
awkward 数组转张量是下一步的常见卡点。batch["Jet_pt"] 是一个长度 5000 的数组,每个元素是长度不等的浮点数组。要喂给固定输入形状的模型,只有三条路:按固定长度截断或补零、用能处理集合的模型(Deep Sets、Transformer、GNN)、或者先聚合成固定维度的汇总量(前 N 个的 pt、总横能量、多重数)。第三条路最省事,也最容易丢掉信息。
§5.5 CMSSW 什么时候才真的需要
有一类工作绕不开 CMSSW,判断标准很简单:你要不要改变量本身。 只读、只算、只训练,NanoAOD 加 uproot 就够;要重新做径迹拟合、改喷注聚类、读粒子流候选、从 RAW 重建,就必须进 CMSSW。
进了 CMSSW,第二个坑立刻出现:版本必须按年份锁死。官方三个入门页各给了一套版本表。
| 数据 | 格式 | CMSSW 版本 | 操作系统 |
|---|---|---|---|
| 2010 | AOD | CMSSW_4_2_8 | Scientific Linux 5 |
| 2011–2012 | AOD | CMSSW_5_3_32 | Scientific Linux 6 |
| 2015 | MiniAOD | CMSSW_7_6_7 | Scientific Linux 6 |
| 2016 | MiniAOD | CMSSW_10_6_30 | Scientific Linux 7 |
四行四个版本,跨了四个大版本号、三个操作系统。这不是历史遗留的懒惰,是物理必然:每一年的探测器状态、标定、重建算法都不同,软件必须与数据同期。官方在 about-cms 页上也直说了「方法在演进,更先进的技术用在更新的数据上,但软件与旧数据样本不能开箱即用」。
对做机器学习的人,这张表的实际含义是:如果你选 2010–2012 的数据,你就要和一整套 2012 年的软件栈搏斗。 这不是不可能,但它的投入产出比远低于直接用 2016 年的 NanoAOD。这构成了一个具体的选择建议:样本量够用时,优先 2016;只有在需要 Run1 特有的东西(比如更低的 pileup、不同的触发菜单)时才回到 2010–2012。
§5.6 六种常见失败模式
把踩过的坑列成清单,按出现频率排序。
| 现象 | 原因 | 处理 |
|---|---|---|
curl 返回空或 308 |
缺 -L,未跟随重定向 |
加 -L |
json.load 抛 Unterminated string |
响应体被截断 | 改 size=1,单条走 /api/records/{recid} |
subtype:Collision 查出 0 条 |
字段名错,应为 type.secondary |
换字段 |
| NanoAOD 分支名对不上 | 版本不同(v9 与 v12 分支集合不同) | 先 tree.keys() 再写代码 |
| 训练集与真实数据分布对不上 | 模拟未加权,或真实数据未过 validated runs | 补权重、补 JSON 过滤 |
| 读 AOD 时报 C++ 类字典缺失 | 用了错误的 CMSSW 版本 | 按年份对表选版本 |
最后一行值得展开一句。AOD 里存的是 CMS 专用 C++ 类的实例,读它需要对应的类字典(dictionary)。版本不对时,症状不是「报错退出」,而是「读出来一堆空对象」——这种失败比崩溃更危险,因为它会安静地产出错误的统计。
§6 与库内条目的关系
这份数据在库内没有同类。粒子物理这个方向目前只有它一条,去重检索里 %cern%、%lhc%、%particle%、%physics% 都没有命中真实数据条目;%粒子% 与 %对撞% 同样为空。
它真正相邻的是两条天文条目,相邻的方式不是内容相似,而是方法同构。
| 库内条目 | 共同点 | 分工 |
|---|---|---|
| Gaia DR3 | 都是「一次发布 = 一份冻结的科学测量」,都用带误差的表格,都有主键稳定性问题 | Gaia 测的是天体位置,CMS 测的是粒子四维动量;前者按源一行,后者按事例一行 |
| NASA 系外行星档案 | 都是「观测 + 模拟」双轨制,都要区分确认与候选 | 行星档案的模拟是模型拟合,CMS 的模拟是蒙特卡洛生成 |
三条可操作的互链路径:做「大规模科学表格上的表征学习」时,Gaia DR3 提供十亿行级的静态表,CMS 提供千万行级的变长集合,两者恰好覆盖「定长宽表」与「变长集合」两个极端;做「模拟到真实的迁移」时,系外行星档案提供的是同一批观测的不同处理管线,CMS 提供的是真机数据与生成器数据的对照,后者的 domain gap 更硬。
在库内的检索路径上,这份数据挂在「多模态」「目标检测」「图像分类」三个标签下,理由是它的对象级结构与视觉任务同构:一个事例里有若干个喷注,每个喷注有若干个观测量,这与一张图里有若干个目标、每个目标有若干个属性是同一个数学结构。用它做「集合上的目标级预测」,比用图像更干净,因为它的对象边界是算法给的,不是人画的。
§7 质量评估与局限性:先拆掉一个评价框架
§7.0 阅读本节前需要知道的一件事
拿评价普通数据集的标准来衡量 CMS 开放数据,会得出一个很低的分数,而且这个低分没什么意义。
常见的两种误判是这样发生的。
第一种,用「标注质量」的框架去评。会问:标签是谁标的、标注一致性多少、有没有双人复核。这套问题在这里无从回答,因为这里根本没有「标注」这个环节——标签来自物理过程本身(这是一个 b 夸克喷注),或者是生成器在模拟时写下的真值。它的可信度问题不是「标注员是否认真」,而是「重建算法是否收敛」。
第二种,用「覆盖度」的框架去评。会问:样本是否代表总体、有没有采样偏差、类别是否均衡。这套问题同样跑偏,因为 CMS 开放数据从来不以「代表总体」为目标。它的每一个 Primary Dataset 都是被触发条件筛选过的,/BTagCSV/ 里的每一个事例都满足「至少两个 b 标记喷注」这个在线条件。它不是一份抽样调查,它是一份按物理兴趣切出来的档案。
正确的评价框架只有一条:它能不能支撑一次可复现的物理测量。 用这一条衡量,它的成熟度非常高——每条记录带 DOI、带重建版本、带 global tag、带质量认证清单、带触发配置。用前两种框架衡量,它处处不合格,而那些「不合格」恰恰是它的设计前提。
§7.1 逐条局限
第一,统计量有限。 通行的做法是每个 Primary Dataset 只开放一个子集。345 条碰撞记录里,number_events 在千万级以上的有 290 条,百万到千万级 51 条,十万到百万级 1 条。这意味着大部分记录的量级在「够做方法验证」与「不够做精密测量」之间。想复现一个需要十倍统计量的发现,靠开放数据做不到。
第二,年份断档。 Run2 的开放数据只到 2016 年。2017、2018 两年 CMS 采了更多数据,但没有以公开数据集形式发布。2024 年只有两条 EphemeralHLTPhysics 的 RAW 样本,是原始格式,没有重建。这个断档不是技术问题,是发布策略问题,短期内不会变。
第三,软件腐化。 官方在 about-cms 页上写得很直接:发布的数据与用来分析它的软件版本都不再继续开发;方法在演进,更先进的技术用在更新的数据上,但软件与旧数据样本不能开箱即用。这意味着 2010 年的 AOD 需要一个 2012 年前后的 Scientific Linux 5 环境,而这个环境本身已经在多数现代系统上跑不起来,只能靠容器。
第四,模拟不是全集。 官方同样明说:模拟数据只包含那些用与对应碰撞数据兼容的软件版本重处理过的数据集;2012 年的模拟有一部分只发布了书目信息,数据要按需申请。门户里 availability 为 partial 的 20,105 条记录,就是这个限制的可视化——它们的文件没有全部上线。
第五,碰撞数据未按质量清单过滤。 §4.6 已述。这是最容易被低估的一条,因为它不产生报错,只产生偏差。
第六,文档的主线叙事与最优入口错位。 §3.3 已述。这条严格说来不是数据本身的局限,而是使用体验上的,但它的实际影响最大:它让多数人从最贵的那条路开始。
第七,检索接口的字段命名不直观。 type.secondary 与 type.primary 的嵌套、subtype 的语义漂移、year 用毫秒时间戳做键、大响应截断——这些都在 §5 里列过。它们不影响数据质量,只影响上手速度。
§7.2 DAIMS 评估:把它当数据管理对象看
DAIMS(Data and Information Management Standards)本是给生物医学数据设计的成熟度框架,套在这份数据上会显出它的性格:在可追溯性与标识上接近满分,在可获取性与格式亲和度上分数一般。
| DAIMS 维度 | 成熟度 | 依据 |
|---|---|---|
| 唯一标识 | 极高 | 每条 Dataset 一个 DOI,形如 10.7483/OPENDATA.CMS.XXXX.XXXX |
| 元数据描述 | 极高 | 记录级 JSON 含采集年、发布年、重处理年、run 区间、能标、重建链、触发路径 |
| 数据溯源 | 极高 | methodology 字段逐段列出 CMSSW 版本与 global tag |
| 数据质量声明 | 高 | 独立的 validated runs 清单,逐 run 逐亮度段标注 |
| 版本管理 | 高 | 处理版本写在数据集名第二段,旧版本不删 |
| 许可清晰度 | 极高 | CC0 1.0,机器可读,无附加条件 |
| 商业可用性 | 极高 | CC0 放弃全部权利,商用无限制 |
| 机器可读格式 | 中 | ROOT TTree 是标准格式,但不是通用表格格式,需要专门库 |
| 可获取性 | 中 | 单条记录可达数 TB,且 20,105 条仅部分在线 |
| 文档可达性 | 高 | 三套入门页齐全,但主线排序有偏差 |
总分判断:作为「可追溯的科学档案」接近满分,作为「开箱即用的机器学习数据集」有明显门槛。 这两个判断不矛盾,它们描述的是同一份东西的两个侧面。
§7.3 三组能自己做的外部验证
对一份不敢轻信的数据,最好的办法是自己动手验三件事。
第一组,验证体量。随便挑一个 Primary Dataset,在门户上找到它的两种格式,把 distribution.size 相除。如果结果落在 5 到 12 之间(AOD 对 MiniAOD)或 20 到 35 之间(MiniAOD 对 NanoAOD),说明官方的口径是可靠的。§3.2 的 /BTagCSV/ 给出的是 7.59 与 29.61。
第二组,验证许可。用 §5.2 的 curl 命令取任意一条记录的 JSON,看 license.attribution。如果返回 CC0-1.0,与 about-cms 页上的「CC0 waiver」表述一致。这一条尤其值得自己跑一次,因为 CC0 是最宽松的许可,一旦看错成「仅限研究」,整个使用决策都会变。
第三组,验证真实与模拟的分离。用 type.secondary 的两个取值各查一次总数,相加看是否接近 Dataset 总数。345 加 51,365 加 253 等于 51,963,与 type.primary:Dataset 的计数完全相等。这个恒等式成立,说明三个标签是一个完整划分,没有遗漏的第四类。
§8 版本与生态:一份档案如何维持十二年
§8.1 版本节奏:三波发布,两种冻结
CMS 开放数据的发布不是连续的,是三波。
第一波是 2014 年前后,Run1 的 2010–2012 数据以 AOD 形式上线,配 CMSSW_4_2_8 与 CMSSW_5_3_32。这一波定了门户的骨架:三段式命名、DOI、按 Primary Dataset 分卷。
第二波是 2015–2016 年数据上线,随之带来 MiniAOD 与后来的 NanoAOD。这一波的产物在 2020 年前后又经历了一次大规模重处理,叫 Ultra-Legacy,date_reprocessed 字段里的 2021 就是这件事。§1.5 的案例里 UL2016_MiniAODv2_NanoAODv9 这一串后缀,每一个字母都是一个版本决定:UL 是 Ultra-Legacy,v2 是第二次 MiniAOD 生产,v9 是第九版 NanoAOD。
第三波是 2024 年前后,date_published 为 2024 的那批 NanoAOD 集中上线,以及 2025 年那两条 Run3 的 RAW 样本。这一波不是新数据,主要是旧数据的新格式。
§8.2 2024 年的两条记录:一个不该被忽略的裂缝
「CMS 开放数据是冻结的 Run1 加 Run2 档案」这个说法流传很广,它在 2016 年之前是对的,现在不完整了。
门户里有两条例外的记录:/EphemeralHLTPhysics0/Run2024F-v1/RAW 与 /EphemeralHLTPhysics1/Run2024F-v1/RAW。两条都是 type.secondary 为 Collision、collision_information 为 13.6 TeV 的质子—质子、采集年 2024、发布年 2025。其中一条的 DOI 是 10.7483/OPENDATA.CMS.KU3N.B38W。
它们的分量不在于数据量——两条都是原始格式的样本,不是完整数据集——而在于它们打破了一条被反复引用的前提。这条前提是「门户只放 2016 年以前的数据,2017 年以后的 CMS 数据不公开」。至少从 2024 年的运行段开始,CMS 已经开始以 RAW 样本的形式释放 Run3 数据了。
从能标上也能看出这条裂缝:Collision 记录的能标分布是 7 TeV 77 条、8 TeV 100 条、13 TeV 101 条、5.02 TeV 42 条、2.76 TeV 20 条、0.9 TeV 2 条、13.6 TeV 2 条。最后那两条就是 Run3。0.9 TeV 的两条更早,是 2009 年的 commissioning 数据。
这条裂缝对使用的意义是:不要把「Run2 之后没有数据」写进方法部分当作既成事实。 写之前去门户查一次,因为这件事在变。
§8.3 它为何能持续:三个刚性
一份十二年的档案能维持,靠的不是热情,是三个结构性理由。
第一个刚性是发表要求。CMS 的论文在期刊上有数据可用性声明的要求,合作组内部也有开放科学政策。开放数据不是额外的善举,是发表流程的一部分。这保证了它不会因为「没人做」而停。
第二个刚性是可复现性要求。一个物理测量要在十年后被复核,必须能拿回当年的数据与软件。DOI 加 CMSSW 版本加 global tag 这套组合,就是为了让「十年后还能跑起来」成为一个可执行的承诺,而不是一句口号。这也是为什么旧软件版本明明已经过时,却必须原样保留。
第三个刚性是教育需求。门户单列了教育用途与研究用途两条指南,还有 masterclass 与教学工作坊。学生要学粒子物理,就得有真数据;真数据不可能给全部,所以要有精简样本。这条需求支撑了 ATLAS 那 189 条教学记录,也支撑了 CMS 那 31 条 Run1 类 NanoAOD。
三个刚性叠在一起,形成一种少见的稳定:它不靠用户增长,也不靠资金续命,它靠学术制度本身的惯性。
§8.4 起源:一次「把底稿也交出去」的决定
2014 年门户上线时,粒子物理界对开放数据的争论焦点不是「要不要开放」,而是「开放到什么程度」。
一派主张只开放派生结果:截面、图表、统计量。这是 HEPData 的路线,风险低、争议小,因为它交出的是结论。另一派主张开放事例级数据:把重建后的对象、径迹、簇全部交出去。这一派的风险在于,事例级数据一旦公开,任何人都可以重做分析,包括做出错误的、但看起来同样专业的分析。
CMS 选了后者,并且选了最激进的一档——CC0。不是 CC BY,不是 CC BY-NC,是放弃全部权利的 CC0。这个选择的后果是:不需要署名、不需要申请、不需要解释用途,连「不得用于商业」这种常见限制都没有。
与之配套的是一句免责声明,写在 about-cms 页上:CMS 与 CERN 都不为基于这些数据产生的任何成果背书,即使这些成果发布在本门户上或链接自本门户。这句话的位置很关键——它紧跟在许可声明后面,等于说「权利全部给你,责任也全部给你」。
这套组合在开放数据里是罕见的。多数科学数据选 CC BY 4.0,保留署名要求;少数选 CC BY-NC,保留商业限制。选 CC0 的,通常是不在乎归属的基础设施类数据。一份耗资数十亿欧元、由四千多名科研人员产出、涉及国家级实验设施的数据,选择 CC0,这个决定本身就是这份数据最独特的属性之一。
§8.5 那些看起来「不利」的设计,其实是被算过的
最后看三个常被抱怨的设计,它们都不是疏忽。
不提供 CSV。 57,889 条记录里 file_type 为 csv 的只有 34 条,全是配置或小表格。有人会说这是「不友好」。但事例级数据转成 CSV 会让体积涨三到五倍,而且变长数组无法用 CSV 表达。选 ROOT 不是守旧,是因为没有更好的容器能同时装下变长集合与列式压缩。
不替你过滤质量。 §4.6 已述。把选择权交出去,代价是使用者要自己动手,收益是不必为「官方替我做的筛选」买单。对做方法研究的人,未过滤的原始分布比过滤后的干净分布更有价值。
这两个设计指向同一个取向:宁可让人知难而退,也不让人误以为简单。 这在今天的开放数据里不算主流,但它与 CC0 的选择是自洽的——既然责任全部转移给了使用者,就不能同时制造「这很简单」的错觉。
§9 使用指引:三种角色的路径
§9.1 三种角色
| 角色 | 目标 | 路径 |
|---|---|---|
| 方法研究者 | 在一个真实的高维集合数据上验证模型 | 单选一条 2016G 或 2016H 的 NanoAOD,取前 20 个文件,不做全量下载 |
| 物理分析者 | 复现或扩展一次测量 | 按论文锁定重建版本,取 NanoAOD 加 validated runs 清单,必要时补 MiniAOD |
| 教学者 | 让学生在两次课内跑通一次分析 | 用 Run1 类 NanoAOD 或教学 ntuple,体量小、依赖少 |
三者的共同点是都想少下一点。区别在于「少」的标准不同:方法研究者按文件数少,物理分析者按信息完整度不亏,教学者按启动时间短。
§9.2 最小可运行流程
一条从零到看见分布的最短路径,五步。
第一步,确认目标记录的体量与事件数。用 §5.2 的命令取 distribution.size 与 distribution.number_events,先算清楚 131 GB 要不要全下。
第二步,取文件清单。用 cernopendata-client get-file-locations --recid 30517 --protocol xrootd 拿到 63 个文件的地址,先只取前三个。
第三步,直读而不下载。用 §5.4 的 uproot 代码打开第一个文件,entry_stop 设成五万,打印 nJet 的分布。这一步在笔记本上就能跑完。
第四步,补上质量过滤。下载 recid 14220 那份 validated runs 的 TXT,用 NanoAOD-tools 或自己写的解析器,按 run 与 luminosityBlock 过滤。跳过这一步的结果在 §4.6 说过。
第五步,落成训练可用的形状。把 awkward 数组按 nJet 截断到固定长度,或聚合成固定维度的汇总量,存成 Parquet 或 NumPy。
五步里最容易被跳过的是第四步,最容易做错的是第五步——很多人把变长数组直接 np.array(),得到一个 object 数组,然后在 DataLoader 里才发现 collate 失败。
§9.3 在 AI 流程中的位置
这份数据在机器学习流程里最适合的位置是**「真实世界的结构化科学数据」这一格**,而不是「大规模预训练语料」那一格。
它的长处有三:标签来自物理而非人工,没有标注噪声;特征有明确的物理含义,可解释性分析能落地;任务定义清晰(分类、回归、异常检测都有标准做法)。它的短处也有三:体量大、读取需要专门库、类别极不均衡(一个事例里可能一个 b 喷注都没有)。
一个具体的用法建议:把它当「集合学习」的基准,而不是当「大数据」的基准。 它的价值不在于行数多,而在于每一行本身是一个大小可变的集合,且集合元素的物理含义明确。这一点在图像与文本里都难找到同等干净的对应物。
§9.4 一个完整工作流的样子
把上面的建议落成一个可以照着做的顺序:
1. 定问题 例:从喷注集合判断事例是否含 b 夸克
2. 定格式 NanoAOD(不需要改重建)
3. 定样本 2016G 与 2016H,两个 run period 做交叉验证
4. 取清单 cernopendata-client get-file-locations --recid 30517
5. 取质量清单 recid 14220,按 run 与 luminosityBlock 过滤
6. 读入 uproot,library="ak",只读需要的分支
7. 变定长 按 nJet 截断到 20,或聚合成汇总量
8. 切分 按 run 切,不按行切
9. 训练 任意集合模型
10. 报告 写明 recid、DOI、CMSSW 版本、global tag、是否过滤
第十步不是形式。这份数据的可复现性完全依赖这五项被写清楚:没有 recid 就不知道你下的是哪一版,没有 DOI 别人找不到,没有 CMSSW 版本与 global tag 就不知道能量刻度,没写是否过滤就不知道样本干不干净。
§10 AI 使用声明
| 项目 | 说明 |
|---|---|
| 性质 | 科学测量记录与蒙特卡洛模拟,非人工标注数据集 |
| 建议用途 | 集合学习、喷注标记、异常检测、模拟到真实的迁移、可解释性分析 |
| 不建议用途 | 当作通用预训练语料;不做质量过滤就报物理量;把模拟当实验数据 |
| 伦理 | 无个人数据、不涉及任何自然人;CC0 无使用限制,但 CMS 与 CERN 不为成果背书 |
| 引用 | 引用具体记录 DOI,并写明数据集名、CC0 1.0、以及所用的重处理版本 |
| 版本 | 各记录独立冻结;2016 年数据的主流版本是 Ultra-Legacy 重处理 |
| 状态 | 持续以新格式重发旧数据,2024 年起开始释放 Run3 样本 |
| 再分发 | 可自由分发、可商用、可修改,无需署名(署名仍是学术惯例) |
§11 常见误读(避坑清单)
| 常见说法 | 实际情况 | 证据 |
|---|---|---|
| 「57,889 条记录就是 57,889 个数据集」 | 其中只有 345 条是真实碰撞数据,51,365 条是模拟,253 条是派生,5,748 条是配套件 | 门户 API 的 type 与 type.secondary 聚合 |
「用 subtype 区分真实与模拟」 |
没有 subtype 字段,subtype:Collision 返回 0 条;正确字段是 type.secondary |
subtype%3ACollision 查询返回 0 |
| 「数据是冻结在 Run1 加 Run2 的档案」 | 2024 年有两条 Run3 的 13.6 TeV RAW 记录,2025 年发布 | /EphemeralHLTPhysics1/Run2024F-v1/RAW 记录元数据 |
| 「NanoAOD 里的碰撞数据已经是干净的了」 | 官方明说未按 validated run segments 过滤,须自己按 JSON 清单筛 | NanoAOD 入门页原文 |
| 「同一 Primary Dataset 的两种格式事件数相同」 | 2015D 的 AOD 与 MiniAOD 差 6,778 个;2016H 的两种格式差 183,175 个 | 两条记录的 distribution.number_events |
| 「AOD 可以直接读成表格」 | 官方原文:「cannot be opened (and understood) as simple data tables」 | about-cms 页 |
| 「碰 CMS 数据必须先装几十 GB 的虚拟机」 | NanoAOD 不需要 CMSSW、不需要容器,uproot 即可 | 官方入门页与记录 system_details 字段 |
| 「CC0 就意味着没有任何约束」 | 权利上确实没有,但官方明确不为任何基于该数据的成果背书 | about-cms 免责声明 |
| 「所有记录都有 DOI」 | Dataset 记录有,派生集与部分补充记录没有(如 recid 31103) | 该记录 doi 字段为空 |
| 「软件也是 CC0」 | 46 条 Software 记录多数是 GPL-3.0-only | 软件记录的 license.attribution |
| 「NanoAOD 只有 32 条,没什么数据」 | 32 是记录数;一条记录就有 63 个文件、1 亿事例、131 GB | 记录 30517 的 distribution |
「collision_information 写了 13TeV 就是真实数据」 |
模拟记录同样有这个字段,pp 类型共 53,877 条而真实数据只 345 条 | 两个聚合的对比 |
| 「AOD 与 NanoAOD 差 200 倍是官方测出来的平均值」 | 它是两段压缩比的乘积,同一条链上实算是 7.59 乘 29.61 | §3.2 的六条记录 |
§12 FAQ
Q1:这套数据用一句话说是什么?
一份按「格式 × 年份 × Primary Dataset」切块发布的 LHC 对撞事例档卷,每条记录带 DOI、带重建版本、以 CC0 授权。它的主体是模拟而非真实数据,它的最厚格式是 AOD,最好用的格式是 NanoAOD。
Q2:57,889 和 345 这两个数为什么差这么远?
因为粒子物理的工作方式是「一个真实事例配几十倍模拟」。实验组要用模拟估计探测效率、本底形状、系统误差,所以每个 Primary Dataset 会配一整套对应能标与重建版本的模拟样本。345 条真实碰撞记录对应 51,365 条模拟记录,比例约 1 比 149。
Q3:为什么官方从 AOD 讲起?
因为门户 2014 年上线时只有 Run1 的 AOD,文档骨架在那时定型。Run1 的 190 条碰撞记录至今只有 AOD,没有 NanoAOD。官方后来为 Run1 单独做了 31 条「类 NanoAOD」派生集,但那条线不在主叙事里。
Q4:200 倍这个数字能自己验证吗?
能。找同一个 Primary Dataset 在两种格式下的两条记录,把 distribution.size 相除。/BTagCSV/ 上 AOD 对 MiniAOD 是 7.59 倍,MiniAOD 对 NanoAOD 是 29.61 倍,相乘 224.8,与官方说的 200 倍同量级。
Q5:NanoAOD 为什么能不用 CMSSW?
因为它不再用 CMS 专用的 C++ 类存数据,而是把数值写成 ROOT TTree 里的标准 C++ 类型。没有自定义类就没有类字典依赖,纯 Python 的 uproot 就能解析。官方在记录元数据的 system_details 字段里把这句话写死了。
Q6:validated runs 到底是什么?
一份列明哪些 run 的哪些亮度段被认证为可用于物理分析的清单,JSON 或 TXT 格式,每条碰撞记录的页面上有链接。它的存在是因为探测器不是一直处于良好状态。不做这个过滤,样本里会混进探测器异常的时段。
Q7:真实数据和模拟数据能混着训练吗?
能,而且这是标准做法,但有三个前提:模拟要按产生截面加权;模拟的 pileup 分布要与数据匹配;评估必须只用真实数据。缺任何一个,模型学到的都是生成器的偏好而不是物理。
Q8:这份数据能做图像任务吗?
严格说不能。门户里没有事件显示图像,只有数值化的重建对象。要做「量能器图像」,得回到 AOD 或 RECO 取低层沉积信息,自己按探测器几何把它排成二维网格。这是一条可行的路,但它不是「下载即用」。
Q9:为什么一条记录能有 1,105 个文件?
因为数据是按 run 与亮度段切分存储的,一个 run period 跨几十个 run,每个 run 又切成若干段,每段一个文件。MiniAOD 文件大、事例多,所以文件数少;AOD 文件小、事例少,所以文件数多。文件数与总量不成正比。
Q10:CC0 之后我还能要求别人引用我吗?
不能要求,但可以请求。CC0 放弃了署名权,所以别人用了不署名也不违约。学术惯例仍然要求引用 DOI,但那属于社区规范,不是许可义务。
Q11:2024 年那两条 Run3 数据能用吗?
技术上能下载,实用上价值有限。它们是 RAW 格式,没有重建、没有物理对象,要用必须先跑一遍完整重建,而 Run3 的重建需要比 Run2 更新得多的 CMSSW。它们目前的意义主要是「证明 Run3 数据开始释放」,而不是「提供可分析的样本」。
Q12:如果我只需要几万个事例做原型,最小的下载量是多少?
一个 NanoAOD 文件约 2.1 GB,含约 160 万个事例(1 亿除以 63)。要五万个事例,读一个文件的 entry_stop=50000 就够,连下载都可以省掉——直接走 XRootD 远端读。这是这份数据上成本最低的起步方式。
术语表
| 术语 | 含义 |
|---|---|
| 事例(event) | 一次质子—质子(或重离子)对撞的完整记录,是数据分析的基本单位 |
| run | 一段连续采数期,同一 run 内探测器配置基本不变 |
| 亮度段(luminosity block) | run 内约 23 秒的一段,质量认证与 luminosity 计算的最小单位 |
| Primary Dataset | 按触发条件划分的数据流,如 /BTagCSV/ 表示「至少两个 b 标记喷注」 |
| Data Tier | 数据集名的第三段,标明格式:AOD、MINIAOD、NANOAOD、RAW、RECO |
| RAW | 触发后的原始字节流,重建的输入 |
| RECO | 重建后的完整对象集合,比 AOD 更厚,重离子数据用它发布 |
| AOD | Analysis Object Data,Run1 的主力格式,含全部物理对象与低层信息 |
| MiniAOD | AOD 的精简版,约十分之一,2015 年起提供 |
| NanoAOD | 最精简的格式,约 AOD 的二百分之一,存为标准 TTree |
| AODSIM / MiniAODSIM / NanoAODSIM | 对应格式的模拟版本,后缀 SIM 表示来自蒙特卡洛 |
| 重建(reconstruction) | 从原始读数推断物理对象的过程,是数据的一部分而非前置步骤 |
| 触发(trigger) | 在线筛选,把每秒数百万次对撞降到每秒约一千次写入 |
| HLT | High Level Trigger,触发的高层级,按物理对象做判选 |
| 粒子流(particle flow) | 把径迹与量能器簇统一成候选粒子的算法 |
| global tag | 探测器状态、标定、对齐参数的版本化快照,决定能量刻度 |
| CMSSW | CMS 的软件框架,读 AOD 与跑重建都要它 |
| ROOT | 粒子物理的通用数据框架,TTree 是其表格结构 |
| TTree | ROOT 的列式存储结构,支持变长分支 |
| branch | TTree 的一列 |
| jagged array | 每个元素长度不等的数组,对应一个事例里的多个对象 |
| XRootD | 远程读取 ROOT 文件的协议,地址以 root:// 开头 |
| validated runs | 认证为可用于物理分析的 run 与亮度段清单 |
| pileup | 同一次束团交叉中额外发生的对撞数 |
| b 标记(b-tagging) | 判断一个喷注是否源自底夸克的算法 |
| DOI | 数字对象标识,每条 Dataset 记录一个,形如 10.7483/OPENDATA.CMS.XXXX.XXXX |
| Ultra-Legacy | 2016 年数据在 2020 年前后的一轮统一重处理 |
| derived | 从真实或模拟数据再加工出的非标准格式数据集 |
附录 A 速查卡
| 键 | 值 |
|---|---|
| 全名 | CERN CMS Open Data |
| 门户 | opendata.cern.ch |
| CMS 记录数 | 57,889 |
| 真实碰撞记录 | 345 |
| 模拟记录 | 51,365 |
| 覆盖年份 | 2010–2016,另 2024 样本 2 条 |
| 主格式 | AOD、MiniAOD、NanoAOD、RECO、RAW |
| 典型 NanoAOD 体量 | 每事例约 1,300 字节 |
| 体积比 | NanoAOD 约为 AOD 的 1/200 |
| 许可 | CC0 1.0 |
| 引用 | 逐记录 DOI |
| 读取库 | uproot 加 awkward(NanoAOD);CMSSW(AOD) |
| 协议 | XRootD 或 HTTPS |
附录 B 格式与记录对照
| file_type | 记录数 | 属于 | 说明 |
|---|---|---|---|
| aod | 207 | 碰撞 | Run1 主力格式 |
| miniaod | 51 | 碰撞 | 2015–2016 常规分析 |
| nanoaod | 32 | 碰撞 | 可直接读,最轻 |
| reco | 36 | 碰撞 | 重离子与特殊分析 |
| raw | 24 | 碰撞 | 原始样本 |
| aodsim | 859 | 模拟 | 对应 AOD 的模拟 |
| miniaodsim | 28,693 | 模拟 | 模拟记录的主体 |
| nanoaodsim | 21,575 | 模拟 | 模拟记录的第二大块 |
附录 C 官方资源对照
| 资源 | 用途 |
|---|---|
| about-cms 页 | 格式定义、体积比、免责声明的唯一权威来源 |
| 使用条款页 | CC0 的原始表述 |
| NanoAOD 入门页 | 免 CMSSW 的读取路径与示例命令 |
| AOD 入门页 | 按年份对应的 CMSSW 版本表 |
| MiniAOD 入门页 | 2015 与 2016 的版本差异 |
| REST API | 记录检索与聚合统计 |
| cernopendata-client | 文件清单与批量下载 |
| NanoAOD-tools | 按 validated runs 过滤与精简分支 |
编辑说明
核验时间:2026-10-29。核验方式:调用门户 REST API 的 /api/records 与聚合接口,取 experiment、type、type.secondary、file_type、year、collision_energy、availability 六个维度的分布;逐条读取 recid 30517、30500、30533、30550、24114、24131、31103、14220 的完整元数据,用 distribution.size 与 distribution.number_events 计算每事例字节与格式间比值;抓取 about-cms、使用条款、AOD/MiniAOD/NanoAOD 三个入门页的原文,逐句比对体积比、许可、软件版本与免责声明;核对 cernopendata-client 在 PyPI 上的版本与子命令名;解析两条 MiniAOD 与 NanoAOD 论文的 DOI。未能核实:门户未公布 CMS 全量数据的总字节数,因此没有给出总量;date_published 为 2024 的那批记录的实际上线月份未逐条比对;2017 年那 1 条碰撞记录的标题与内容未展开核实,正文因此没有引用它。所有分档计数均来自 API 聚合的 doc_count,未做抽样外推。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- soilgrids — 共享标签:多模态 / 图像分类 / 评测基准
- nasa-exoplanet-archive — 共享标签:多模态 / 图像分类 / 评测基准
- randolph-glacier-inventory — 共享标签:多模态 / 图像分类 / 评测基准
- tcm-tongue — 共享标签:多模态 / 图像分类 / 目标检测 / 评测基准
- oppd — 共享标签:图像分类 / 目标检测 / 评测基准
- wilddog-videos — 共享标签:多模态 / 图像分类 / 目标检测
- gaia-dr3 — 共享标签:多模态 / 图像分类 / 评测基准
- sdss-dr20 — 共享标签:多模态 / 图像分类 / 评测基准
- esa-worldcover — 共享标签:多模态 / 图像分类 / 评测基准
- cryoet-data-portal — 共享标签:多模态 / 目标检测 / 评测基准
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

