Hi,
I’m trying to upgrade a routine I wrote to do general tree filtration and dst->microdst. Essentially the code takes a chain, applies a selection (e.g. as in Draw()) and only writes out specified branches. I can make this work if I do it in two passes:
(1) Apply selection on the input chain via TChain::Draw() into an event list.
(2) Set the event list on the original tree, turn all branches off on the input chain, go back and turn on only the ones we want to save.
(3) Clone the original chain via CloneTree(0)
(4) loop over the event list, GetEntry() in the original chain, Fill() output tree.
This works like a charm but I’d like to do it in one pass. Here is my attempt:
TTree* filter_tree(TTree* t, const char* selection, const char* vars, TFile* fout)
{
// ttf implements the event selection
TTreeFormula ttf("filter_tree",selection,t);
// turn off all branches in input
t->SetBranchStatus("*",0);
// tokenize array of variable names
TString s(vars);
TObjArray* vlist = s.Tokenize(", ");
// loop over variable names, turning on associated branch in input
std::cout<<"filter_tree: writing out the following variables:"<<std::endl;
for(int i=0; i<vlist->GetEntries(); i++){
TObjString* obj = dynamic_cast<TObjString*>(vlist->At(i));
TString v=obj->GetString();
std::cout<<v<<std::endl;
t->SetBranchStatus(v.Data(),1);
}
std::cout<<"end of variables"<<std::endl;
fout->cd();
TTree* tc = t->CloneTree(0);
// go through and turn on branches needed by selection
std::cout<<"Turning on branches"<<std::endl;
for(Int_t j=0; j< ttf.GetNcodes(); j++){
std::cout<<"Enabling branch : "<<ttf.GetLeaf(j)->GetBranch()->GetName()<<std::endl;
t->SetBranchStatus(ttf.GetLeaf(j)->GetBranch()->GetName(),1);
}
ttf.UpdateFormulaLeaves();
Long64_t nbr=0;
std::cout.precision(3);
Long64_t i=0;
Long64_t npass=0;
bool keep_going=true;
Int_t current_tree=-1;
while(true) {
if(t->GetTreeNumber()!=current_tree) {
current_tree=t->GetTreeNumber();
ttf.UpdateFormulaLeaves();
}
// load branches needed by selection
for(Int_t j=0; j< ttf.GetNcodes(); j++){
Long64_t nb = ttf.GetLeaf(j)->GetBranch()->GetEntry(i);
if(nb<=0){
// done reading
std::cout<<"Should be done (1)? : [i,j] = "<<i<<" , "<<j<<std::endl;
keep_going=false;
break;
}
nbr+=nb;
}
if(!keep_going) break;
// evaluate the selection, if true, fill output
Double_t val = ttf.EvalInstance();
if(val > 0.0){
npass++;
Long64_t nb=t->GetEntry(i,0);
if(nb<=0){
// done reading
std::cout<<"Should be done (2)?"<<std::endl;
keep_going=false;
continue;
}
nbr+=nb;
tc->Fill();
}
// how's it going
if(i%100000==0){
std::cout<<i<<" entries read : "<<npass<<" filled : "
<<nbr/(1024.0*1024.0)<<" Mb read"<<std::endl;
}
i++; // don't forget
}
std::cout<<"Done "<<std::endl;
std::cout<<"filter_tree: output has "
<<npass<<" entries."<<std::endl;
return tc;
}
Now, the output is:
root [0]filter_tree("pan","pan_n13011001_0000*.root","is_pitt_fid==1","reco_enu,pass","blah.root");
filter_tree: building chain of 'pan' ntuples from pan_n13011001_0000*.root
filter_tree: using 1 trees.
Warning in <TClass::TClass>: no dictionary for class NuParent is available
filter_tree: writing out the following variables:
reco_enu
pass
end of variables
Turning on branches
Enabling branch : is_pitt_fid
0 entries read : 0 filled : 3.81e-06 Mb read
Should be done (1)? : [i,j] = 3349 , 0
Done
filter_tree: output has 0 entries.
The TTreeFormula never returns a true value but doesn’t issue any errors and I know that there are events that pass the cut. The number 3349 is the number of events in my input file. Can anyone advise me on what I’m doing wrong? I’ve attached the code.
mike kordosky
filter_tree.C (3.1 KB)