处理TTree的⼏种⽅法
TTree是ROOT的⼀个存储数据的类,⼤概可以理解成⼀个⼆维数据表格。每⼀个Branch代表⼀种属性(或者⼀列),Entry代表⼀个事例(或者⼀⾏)。⽤户可以通过读取每⼀Entry中的特定Branch,来统计⼀个样本的某个属性的分布。
读取TTree数据的⽅法有很多,这⾥总结⼏个⽐较常⽤的,他们有的⽐较复杂但⽐较灵活,有的简单快捷,但是⾯对更复杂的数据结构或者操作就⽆能为⼒。不同的场景适⽤不同的⽅法,但个⼈觉得RDataFrame在各种情况都相对好⽤⼀些,写这篇博客也是起因于此。
其实可以直接去看⽂档
利⽤TTree本⾝的成员⽅法
以下内容⼤部分来⾃于官⽅⽂档的这⼏个部分:
从⼀个.root⽂件中读取TTree的⽅法:
TFile *f = new TFile("");
TTree *t2 = (TTree*)f->Get("t2");
其中TFile的构造函数打开了⼀个.root⽂件,Get⽅法从⽂件中找到名字对应的TObject,转换成TTree之后即可拿到⼀个TTree的指针。TTree::Draw
TTree内置的Draw⽅法可以快捷的统计某个Branch或者某⼏个Branch的分布,还可以设置筛选条件,以及画图选项。
mgm例如我们有⼀个Tree,其中包含这些Branch:
root [3] pion->Print()
******************************************************************************
*Tree :pion : pion *angle什么意思
*Entries : 14228 : Total = 860959 bytes File Size = 553940 *flowers是什么意思
* : : Tree compression factor = 1.55 *
******************************************************************************
*Br 0 :RunNum : RunNum/I *
*Entries : 14228 : Total Size= 57547 bytes File Size = 547 *
*Baskets : 2 : Basket Size= 32000 bytes Compression= 104.31 * *............................................................................*
*Br 1 :PiNumInEvent : PiNumInEvent/I *
*Entries : 14228 : Total Size= 57583 bytes File Size = 7760 *
*Baskets : 2 : Basket Size= 32000 bytes Compression= 7.35 * *............................................................................*low是什么意思
*Br 2 :EventNum : EventNum/I *
如师通*Entries : 14228 : Total Size= 57559 bytes File Size = 17574 * *Baskets : 2 : Basket Size= 32000 bytes Compression= 3.25 * *............................................................................*
*Br 3 :MCPEn : MCPEn/D *
*Entries : 14228 : Total Size= 114605 bytes File Size = 88737 * *Baskets : 4 : Basket Size= 32000 bytes Compression= 1.29 * *............................................................................*
*Br 4 :MCPTheta : MCPTheta/D *
描写天气的词语*Entries : 14228 : Total Size= 114629 bytes File Size = 89337 * *Baskets : 4 : Basket Size= 32000 bytes Compression= 1.28 * *............................................................................*
*Br 5 :MCPPhi : MCPPhi/D *致敬是什么意思
*Entries : 14228 : Total Size= 114613 bytes File Size = 90367 * *Baskets : 4 : Basket Size= 32000 bytes Compression= 1.26 * *............................................................................*
*Br 6 :DauPhotonEnMax : DauPhotonEnMax/D *
*Entries : 14228 : Total Size= 114677 bytes File Size = 86169 * *Baskets : 4 : Basket Size= 32000 bytes Compression= 1.32 * *............................................................................*
*Br 7 :DauPhotonEnMin : DauPhotonEnMin/D *
*Entries : 14228 : Total Size= 114677 bytes File Size = 86793 * *Baskets : 4 : Basket Size= 32000 bytes Compression= 1.32 * *............................................................................*
*Br 8 :DauPhotonCluDis : DauPhotonCluDis/D *
*Entries : 14228 : Total Size= 114685 bytes File Size = 85405 * *Baskets : 4 : Basket Size= 32000 bytes Compression= 1.34 * *............................................................................*
统计其中“MCPID”的分布:
人力资源薪酬管理
pion->Draw("MCPEn")
⽤⼀个Branch做筛选
pion->Draw("MCPEn","MCPEn != 0")
这些都⽐较简单,⽂档⾥都很好找。还可以⽤TBrowr在交互式界⾯中去观察数据。
可以通过gDirectory拿到这个直⽅图。
pion->Draw("DauPhotonCluDis>>h(40,0,200)");
TH1D* h = (TH1D*)gDirectory->FindObject("h");
如果要处理的Branch对应的数据类型是基本的double,int等,那么以上⽅法⾮常简便。
价值观 英语
如果处理的Branch对应的是⼀个容器,⽐如vector,甚⾄是⼀个⽤户⾃定义的结构体或对象。Draw()的能⼒就⽐较有限。
Draw函数提供了⼀些基本的操作来访问所存储的vector的属性。例如这样⼀个Tree
root [2] Event->Show(0)
======> EVENT:0
RunNum = 1
EventNum = 0
MCPEn = 2.8601
MCPTheta = 2.46585
MCPPhi = 1.49832
Conv = 0
LeadingEn = 1.85087
SubLeadingEn = (vector<double>*)0x7fffbc4e5700
SubLeadingEn是⼀个vector<double>的Branch,每个vector都有⼀个size()⽅法,可以通过@SubLeadingEn.size()的⽅式统计这个⽅法的返回值:
Event->Draw("@SubLeadingEn.size()")terrible怎么读
这样也是可以解决⼀部分问题。但如果要进⾏更复杂的操作,⽐如说统计SubLeadingEn这个vector中所有不为零的项⽬的个数,或者两个等长vector的Branch(A,B),把B按照A的降序排列,统计A最⼤的那个元素所对应的B元素,或者计算所有⾮零A元素对应的B元素之和,这个时候上述⽅法就会⽐较⿇烦。
TBranch::GetEntry
这是⼀个⾮常通⽤的办法,也是我第⼀次接触ROOT所见到的⽅法。
它的逻辑⼤概是这样的:
1. 获取需要的Branch:GetBranch
2. 为处理的Branch都指定⼀个对应数据类型的地址:SetAddress
3. 遍历所有Entries,每经过⼀个Entry,对应地址的数据就刷新⼀次:GetEntry(i)
下⾯是官⽅教程给出的⽰例: