複雑な構造のデータを読み込みたい( TTree::Branch
)
… code:: cpp
tree->Branch("run", &run, "run/I")
1TBranch* Branch(const char* name,
2 Long_t address,
3 const char* leaflist,
4 Int_t bufsize = 32000)
name
ブランチ名を指定します。 変数名とのひも付けは次の
address
で行います。address
変数のアドレスを指定します。 変数は事前に宣言をしておきます。 変数が実体の場合は&が先頭に必要です。 配列の場合はそのまま(
array
)もしくは配列の最初のアドレス(&array[0]
)を指定します。leaflist
変数の型を指定します。
変数/型
という形式で記述し、int型
はi
、float型
/double型
はF
など。
サンプルコード
1// data2tree.C
2{
3 // STEP1: データファイルを読み込む
4 TString ifn = "inputfilename"
5 ifstream fin;
6 fin.open(ifn);
7
8 // STEP2: データを格納するための変数を定義する
9 int val1, val2, val3, val4;
10
11 // STEP3: TTreeを作成する
12 TTree *tree = new TTree("name", "title);
13
14 // STEP4: TTree::Branch(...)を使って、各変数のブランチを作成する
15 tree->Branch("val1", &val1, "val1/I");
16 tree->Branch("val2", &val2, "val2/I");
17 tree->Branch("val3", &val3, "val3/I");
18 tree->Branch("val4", &val4, "val4/I");
19
20 // STEP5: cppでファイルを読み込むときの常套手段
21 while (fin >> val1 >> val2 >> val3 >> val4) {
22 // STEP6: データのエントリの区切りで必ずTTree::Fill()する
23 tree->Fill();
24 }
25
26 // STEP7: 作成したTTreeを保存するためのTFileを作成する
27 TString ofn = "outputfilename";
28 TFile *fout = new TFile(ofn, "recreate");
29
30 // STEP8: TFileにTTreeを書き込む
31 tree->Write(); //
32
33 // STEP9: TFileを閉じる
34 // プログラム(やマクロ)終了時に勝手に閉じてくれるらしいが一応
35 fout->Close();
36
37 return;
38}
TTree::ReadFileを使った方法と比べると、 コードの行数がぐーんと多くなりました。
行数が増えた分(?)、汎用性は高くなっています。 この方法だと、ブランチに配列を設定ができます。
ブランチに配列を使いたい
1Int_t val1[100];
2TTree *tree = new TTree("tree", "tree using array");
3tree->Branch("val1", val1, "val1[100]/I");
第1引数はブランチの名前なので、任意の文字列を指定します。
第2引数には変数のアドレスが必要とされています。
配列の変数名は、その先頭アドレスを返すので、そのままval1
と書けばよいです。
第3引数では、変数名に配列の長さをベタ書きします。
ブランチに可変長配列を使いたい
少し手間を加えると可変長配列も扱えます。
配列の大きさ fN を定義する
配列 val を定義する
fN のブランチを作る
val のブランチを作る
1Int_t fN; // (1) 設定したい配列の大きさ
2Int_t val[max]; // (2) val[max]: maxはfNよりも大きな数
3tree->Branch("nch", &fN, "nch/I"); // (3) まずfNをブランチにセットする;fNだと何の変数か分かりづらいので、nch(全チャンネル数の意)に変更した点に注意
4tree->Branch("val", val, "val[nch]/I"); // (4) 次にval[fN]をセットする;maxでも、fNでもなくなく、nchにする点に注意
5
6// (4)を以下のようにすると、"Illegal leaf ..." と怒られる
7tree->Branch("val", val, "val[fN]/I"); // fNには、ブランチ名を入れる必要があるらしい(
可変長文字列を使いたい
1#include <string.h> // strlen()を使うために必要
2
3const Int_t NMAX_MOJI = 100;
4char hoge[NMAX_MOJI];
5Int_t nmoji;
6tree->Branch("nmoji", &nmoji, "nmoji/I");
7tree->Branch("moji", hoge, "hoge[nmoji]/C");
8
9sprintf(hoge, "hoge-hoge-fuga-ga");
10nmoji = strlen(hoge)
11tree->Fill()
std::vector
を使いたい
1#include <vector>
2
3std::vector<Double_t> vec;
4TTree *tree = new TTree("tree", "tree using vector");
5tree->Branch("vec", &vec);
<vector>
をincludeする。
namespaceを定義しない場合はstd::vector<型> 変数名
と宣言すること。
当たり前のことだけど、結構忘れてしまう。
ROOT(CINT)を起動させるとvector<型> 変数名
で使えてしまうため、よく忘れる…orz。
vector型
の変数は実体であるため、第2引数は先頭に&が必要。
array
と同じようにすると怒られる。
ROOTが空気を読んでくれるため、第3引数はなくてよいみたい。
まぁでも一番最後のブランチにするのが無難かもしれない。