ROOTでデータを扱おうと思った場合TTreeに値をつめて、解析をしていくことが多い。 ここでは、そのTTreeの構造と、その作り方を説明する。
参考: ROOT referece (TTree)
参考: ROOT referece
ROOTにはTTreeというデータ構造がある。TTreeにはBranch(枝)があり、これはイベントが発生した際にこの用意しておいたBranchにeventの番号と紐付いた値を詰めておくことができる。
Branchには様々なデータ形式が使え、C++のdouble, float, int, bool, std::vector, TVector, 配列, 自作Class等、大体の形式は使える。
またこのTTree上にデータを詰めておけば、rootを使った解析がやりやすくなるメリットがある。
TTreeは最初にどういう構造にするか考える必要があり、最初にBranchを設定してしまうと、あるイベントでは値を入れたくないのようなことは基本的にできない。 そのためよく考えてデータ構造を構築すること。
TTreeの構築には、まずBranchを作ることから始める。
(中略)
TTree *tree = new TTree("<treeの名前>", "<treeの名前>"); // 変数名(tree)は任意でok
// Branchと紐付けるための変数を用意 (ここではdouble std::vector intの3種類を用意)
double variable1; // もちろん変数名は任意
std::vector<double> variable2;
int variable3;
// Branchと変数を紐付ける
tree->Branch("example1", &variable1, "example1/D"); //変数は&でアドレスを渡している。 /の後ろはデータ型
tree->Branch("example2", &variable2);
tree->Branch("example3", &variable3, "example3/I");
以上のように書くことで、Branchを設定できる。ここで、Branchを設定するためには各イベントの際に一時的に値を入れておく変数が必要となる。
そのため3-5行目では変数を作成している。次にBranchをそれぞれの変数のアドレスと紐付ける(図1)。
このことで、変数に値をいれてTTreeにFillという操作をしてあげることで、自動的にBranchに値が入る。
ここまで準備しても、変数に値を入れただけではtreeに記録されない(図2)。
あるイベントが発生して変数にそのイベント時の値を入れた後は必ず"Fill"をしなければならない。 Fillの仕方は簡単で、以下のような処理をイベント終了時に行えば良い。
tree->Fill();
これで値が記録された(図3)。
イベント発生→変数に値を代入→treeにFill→イベント発生→変数に値を代入→treeにFill ...
という操作の流れを各イベントで必ず行う(図4)。