* TTree [#kd8fa256] ** SetBranchStatus [#x8cf71be] これを使うと使用しないBranchを読むのをスキップするので解析を速くできる。 これを使うと使用しないBranchのactivate/disableを設定できて、余計なBranchを読むのをスキップするので解析を速くできる。 ** TEventList [#reb43109] これを使うと、無駄に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 [#z0c73ae1] 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 [#h27d1504] 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の結合 [#b08fd263] AddFriendを使えばできるみたいだが、これはEntry数が同じでないといけない。つまり全部のイベントをtreeに詰めて、多くのイベントはダミーの値を入れておくことになる。無駄なイベントを除去してtreeに詰めたいのに。。。イベント数が一致するものを探して、っていうコードを書くと遅いかな?間違えそうなのも少し危険か? *** 妥協案? [#q55bc6e2] 上の無駄なイベントを詰めるのを回避する方法として、 +比較的早く解析できる部分でtreeを作り、無駄なイベントを除く +別の検出器を解析するときにそのtreeを読み込み、イベント番号でスキップする。 こうするとEntry数は同じになるので、AddFriendで結合できる。 ただし、あとから作るtreeはすべて初めに作成するtreeに依存してしまう。 ** Drawのゲートに文字列 [#we1086e7] Drawの時に tree->Draw("Tracks.fPosition.fX","Tracks.fID==1") のようにゲートを掛けてプロットしたりするが、これが文字列の比較の場合なんか少し変。例えばfNameというTStringでゲートを掛ける時には tree->Draw("Tracks.fPosition.fX","Tracks.fName.Data()==\"Target\"") とするとうまくいく。うーんこれはたまたま?charの比較を==で行っているのでとっても気持ち悪い。使わないようにした方がいい気がする。。。 ** vectorの読み書き [#l44e7a9c] 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の読み書き [#mc8624d1] 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()しておいた方が良いかも。