編集メニュー > 新規作成 編集 コピー 名前の変更 凍結 アップロード 添付ファイル一覧 バックアップ

TTree

SetBranchStatus?

これを使うと使用しないBranchのactivate/disableを設定できて、余計なBranchを読むのをスキップするので解析を速くできる。

TEventList?

これを使うと、無駄にGetEntry?をしなくて済むようになるので、解析が速くなる。自分の場合は30分かかるものが5分になった。以下は例。例1の方が何が起こっているかを知るためにはわかりやすい。複数のtreeをchainしている時は、globalなentryと各tree内のlocalなentryがあるので気をつけないといけない。elist->GetEntry?(i)はあるtreeのlocalなentryを返すので、chain->GetEntry?(elist->GetEntry?(i))としてはいけない。またchain->SetEntryList?(elist)は省略できない。

例1

 chain->Draw(">>elist","fabs(frag_z-7)<0.35&&fabs(frag_aoz-3)<0.05","entrylist");
 TEntryList *elist = (TEntryList*)gDirectory->FindObject("elist");
 chain->SetEntryList(elist);

 Int_t itree=0;
 Int_t listEntries = elist->GetN();
 cout<<setw(10)<<" i/listEnt itree c_Entry t_Entry el_GetEnt"<<endl;
 for (Long64_t i=0;i<listEntries;i++){
   Long64_t treeEntry = elist->GetEntryAndTree(i,itree);
   Long64_t chainEntry = treeEntry + chain->GetTreeOffset()[itree];
   chain->GetEntry(chainEntry);

   cout<<" "
       <<setw(2)
       <<i<<"/"
       <<listEntries<<"      "
       <<itree<<"    "
       <<setw(7)<<chainEntry<<" "
       <<setw(7)<<treeEntry<<"   "
       <<setw(7)<<elist->GetEntry(i)<<" "
       <<endl;

 }

output

i/listEnt itree c_Entry t_Entry el_GetEnt
 0/13      0      15820   15820     15820 
 1/13      0      16673   16673     16673 
 2/13      0      22085   22085     22085 
 3/13      0      22688   22688     22688 
 4/13      0      29111   29111     29111 
 5/13      0      31800   31800     31800 
 6/13      0      33152   33152     33152 
 7/13      1      62622    6652      6652 
 8/13      1      68255   12285     12285 
 9/13      1      83823   27853     27853 
10/13      1      99632   43662     43662 
11/13      1     104841   48871     48871 
12/13      1     108282   52312     52312 

 例2

 chain->Draw(">>elist","fabs(frag_z-7)<0.35&&fabs(frag_aoz-3)<0.05","entrylist");
 TEntryList *elist = (TEntryList*)gDirectory->FindObject("elist");
 chain->SetEntryList(elist);

 Int_t listEntries = elist->GetN();
 cout<<setw(10)<<" i/listEnt c_Entry el_GetEnt"<<endl;
 for (Long64_t i=0;i<listEntries;i++){
   Long64_t c_entry = chain->GetEntryNumber(i);
   if (c_entry<0) {
     cout<<"TChain Load Error!"<<endl;
     break;
   }

   chain->GetEntry(c_entry);

   cout<<" "
       <<setw(2)<<i<<"/"
       <<listEntries<<"     "
       <<setw(7)<<c_entry<<"   "
       <<setw(7)<<elist->GetEntry(i)<<" "
       <<endl;

 }

output

i/listEnt c_Entry el_GetEnt
 0/13       15820     15820 
 1/13       16673     16673 
 2/13       22085     22085 
 3/13       22688     22688 
 4/13       29111     29111 
 5/13       31800     31800 
 6/13       33152     33152 
 7/13       62622      6652 
 8/13       68255     12285 
 9/13       83823     27853 
10/13       99632     43662 
11/13      104841     48871 
12/13      108282     52312 

複数のtreeの結合

AddFriend?を使えばできるみたいだが、これはEntry数が同じでないといけない。つまり全部のイベントをtreeに詰めて、多くのイベントはダミーの値を入れておくことになる。無駄なイベントを除去してtreeに詰めたいのに。。。イベント数が一致するものを探して、っていうコードを書くと遅いかな?間違えそうなのも少し危険か?

妥協案?

上の無駄なイベントを詰めるのを回避する方法として、

  1. 比較的早く解析できる部分でtreeを作り、無駄なイベントを除く
  2. 別の検出器を解析するときにそのtreeを読み込み、イベント番号でスキップする。

こうするとEntry数は同じになるので、AddFriend?で結合できる。 ただし、あとから作るtreeはすべて初めに作成するtreeに依存してしまう。

Drawのゲートに文字列

Drawの時に

tree->Draw("Tracks.fPosition.fX","Tracks.fID==1")

のようにゲートを掛けてプロットしたりするが、これが文字列の比較の場合なんか少し変。例えばfNameというTStringでゲートを掛ける時には

tree->Draw("Tracks.fPosition.fX","Tracks.fName.Data()==\"Target\"")

とするとうまくいく。うーんこれはたまたま?charの比較を==で行っているのでとっても気持ち悪い。使わないようにした方がいい気がする。。。

vectorの読み書き

http://root.cern.ch/root/html/tutorials/tree/hvector.C.html に例がある。書き出すときは

std::vector<float> vpx;
...
t->Branch("vpx",&vpx);

となっているので、ポインタを渡す。 読み込むときは

std::vector<float> *vpx = 0;
TBranch *bvpx = 0;
t->SetBranchAddress("vpx",&vpx,&bvpx);

となっているので、ポインタのアドレスを渡す。

TClonesArray?の読み書き

TClonesArray?をTTreeに詰めるときには以下のように書く。

TClonesArray *arr = new TClonesArray("TLine");
T.Branch("tcl",&arr);

つまりポインタのポインタをSetBranchAddress?する。 こうして作ったTTreeから取り出す時には同様に

TClonesArray *arr = new TClonesArray("TLine");
T->GetBranch("tcl")->SetAutoDelete(kFALSE);
T->SetBranchAddress("tcl",&arr);

とポインタのポインタを渡す。

配列の時には

float y[20];
tr->SetBranchAddress("y",y);

と書いたりするんですよね。。。いっつもこれと混同してしまう。

SetAutoDelete?をkFALSEとした場合にはt->GetEntry?(i)する前にTClonesArray?->Delete()またはClear()をしないといけない。

forループ内で

 tree->GetEntry(ieve);
 bool IsOK=false;
 for (int i=0;i<array->GetEntries();++i){
   Tnanka *obj = (Tnanka*)array->At(i);
   if (obj->GetA() > value){
     IsOK=true;
     break;
   }
   ...
 }
 ...
 if (!IsOK) continue;
 ...

とか書いているときにあるイベントでarray->At(0)が0x0になっていることがある???なぜだか全然分からない。。。こういう場合は

 array->Delete();
 tree->GetEntry(ieve);
 ...

としておくとそんなことにはならない。ということがあったりするので安全のためにSetAutoDelete?(kFALSE)しなくてもDelete()しておいた方が良いかも。