如何从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识别:
- 编写
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
- 用
rootcling生成字典:
rootcling -f CustomDict.cxx -c Header.h StepBase.h LinkDef.h
- 编译为共享库:
g++ -fPIC -shared CustomDict.cxx -o libCustomDict.so $(root-config --cflags --libs)
- 在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
相关产品推荐
相关产品推荐

