You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从TTree中导出或获取实验专属/自定义类对象的内容?

使用Uproot读取TTree分支内容的解决方案

一、处理标准ROOT对象分支

Uproot原生支持大部分标准ROOT类的解析,直接通过分支对象的array()方法提取数据,再根据对象类型做相应处理即可:

1. 读取TObjString*[]类型分支(如Vtx/Vtx.NuFileName)

import uproot

# 打开文件并获取TTree
file = uproot.open("your_file.root")
tree = file["your_tree_name"]

# 提取分支数据
nu_file_names = tree["Vtx/Vtx.NuFileName"].array()

# 遍历输出每个TObjString的字符串内容
for entry in nu_file_names:
    for obj_str in entry:
        print(obj_str.GetString())

2. 读取TMatrixT<double>[]类型分支(如SYST/SYST._cov_matrix)

TMatrixT可以直接转换为NumPy数组,方便后续计算:

cov_matrices = tree["SYST/SYST._cov_matrix"].array()

for mat in cov_matrices:
    # 转换为NumPy数组
    np_matrix = mat.to_numpy()
    print(np_matrix)

二、处理无ROOT字典的自定义类分支

这类分支因为缺少ROOT字典,Uproot无法自动解析类结构,可通过以下三种方式处理:

方法1:手动定义类模型(适用于已知类结构)

如果清楚自定义类的成员变量类型和顺序,可以继承uproot.model.Model手动实现解析逻辑:

import uproot

# 自定义Header类的解析模型
class Model_Header(uproot.model.Model):
    def __init__(self, stream, context, cursor, parent, file):
        super().__init__(stream, context, cursor, parent, file)
        # 根据实际类成员变量调整,示例假设Header包含run_num(int)和pot_val(double)
        self.run_num = self.read_member("run_num", uproot.models.TModel_INT32)
        self.pot_val = self.read_member("pot_val", uproot.models.TModel_FLOAT64)

# 将模型注册到对应类名
uproot.classes["Header"] = Model_Header

# 正常读取分支
pot_info = tree["POTInfo_v2"].array()
for entry in pot_info:
    print(f"Run编号: {entry.run_num}, POT值: {entry.pot_val}")

方法2:读取原始字节手动解析(适用于未知类结构)

如果不知道类结构,可先读取原始字节流,再结合C++内存布局解析:

# 读取分支的原始字节数据(用numpy存储)
raw_step_data = tree["SEL/SEL._rootStep"].array(library="np", dtype="bytes")

# 示例:解析64位指针数组(每个指针占8字节)
for entry_bytes in raw_step_data:
    ptr_count = len(entry_bytes) // 8
    for i in range(ptr_count):
        # 读取指针地址(小端字节序)
        ptr_addr = int.from_bytes(entry_bytes[i*8:(i+1)*8], byteorder="little")
        # 后续需结合ROOT文件的对象存储逻辑,读取指针指向的对象字节并解析
        # 若对象为内联存储,可直接解析后续字节段

方法3:生成ROOT字典(适用于能获取类定义的情况)

如果能拿到自定义类的C++头文件,可通过ROOT生成字典让Uproot识别:

  1. 编写LinkDef.h文件(指定需要生成字典的类):
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class Header+;
#pragma link C++ class StepBase+;
#endif
  1. 用rootcling生成字典:
rootcling -f CustomDict.cxx -c Header.h StepBase.h LinkDef.h
  1. 编译为共享库:
g++ -fPIC -shared CustomDict.cxx -o libCustomDict.so $(root-config --cflags --libs)
  1. 在Python中加载库,Uproot即可自动解析分支:
import ctypes
ctypes.CDLL("./libCustomDict.so")
import uproot

tree = uproot.open("your_file.root")["your_tree_name"]
step_data = tree["SEL/SEL._rootStep"].array()

内容的提问来源于stack exchange,提问作者Jacek Holeczek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:05:38