last-modified: 2019-04-28 (日) 18:36:58 (1834d)[変更箇所]
これを使うと使用しないBranchのactivate/disableを設定できて、余計なBranchを読むのをスキップするので解析を速くできる。
これを使うと、無駄に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)は省略できない。
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
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
AddFriend?を使えばできるみたいだが、これはEntry数が同じでないといけない。つまり全部のイベントをtreeに詰めて、多くのイベントはダミーの値を入れておくことになる。無駄なイベントを除去してtreeに詰めたいのに。。。イベント数が一致するものを探して、っていうコードを書くと遅いかな?間違えそうなのも少し危険か?
上の無駄なイベントを詰めるのを回避する方法として、
こうするとEntry数は同じになるので、AddFriend?で結合できる。 ただし、あとから作るtreeはすべて初めに作成するtreeに依存してしまう。
Drawの時に
tree->Draw("Tracks.fPosition.fX","Tracks.fID==1")
のようにゲートを掛けてプロットしたりするが、これが文字列の比較の場合なんか少し変。例えばfNameというTStringでゲートを掛ける時には
tree->Draw("Tracks.fPosition.fX","Tracks.fName.Data()==\"Target\"")
とするとうまくいく。うーんこれはたまたま?charの比較を==で行っているのでとっても気持ち悪い。使わないようにした方がいい気がする。。。
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?を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()しておいた方が良いかも。