Tree with entries created from another tree: how to "link"?

Hello everyone,
I’m (almost) new to root, my problem is: I have a tree with some “raw data”, I want to do some analysis and save the output to another tree but keeping a “link” between the two trees.

More detailed version: in the first tree I have signals from several detectors. The analysis consists in putting toghether the right data (signals coming from same detector, same plane, same bar, etc…) and creating new things, for example a “hit” (which will be described by more than one variable, e.g. “hit position”, etc…).
The so created “hit” comes from a well defined subset of entries of the first tree.

According to your expertise, which could be the best approach to save this “hits” in a second tree, keeping track of which entries of the first tree they come from?

My searches led me to a lot of pages from the User Manual, I read about Friend trees, BuildIndex, EntryLists … and some threads of this forum as well (as an example this [url=https://root-forum.cern.ch/t/ttree-with-a-fixed-branch/13996/6 with a “fixed” branch[/url] which seems to be similar to what I need), but I still cannot put all the things togheter to build a simple working model. I think I need some smart hint!

:cry:

I wrote a simple macro modifying some tutorials to describe my problem in a more pratical way.
In the macro below the first tree is “T” and it has a single branch n which is a random integer. T has 10 entries. The (stupid) analysis consists in taking all the even numbers and computing the average, and the same thing for the odd ones. Then I save these (two) averages to an output tree called AVE. Then I save both T and AVE to a file called “outfile.root”. Then AVE will have 2 entries.

Here is the code for this simple working model:

[code]#include “TTree.h”
#include “TFile.h”
#include "TRandom.h"
void TheFirstTree() {
// create a simple tree with integers
TFile *f = new TFile(“firstfile.root”,“recreate”);
TTree *T = new TTree(“T”,“tree with random integers”);

int n ;
TRandom1 r;
T->Branch(“n”,&n,“n/I”);
for (int i=0;i<10;i++) {
r.SetSeed(0);
n=int(100*r.Rndm(0)) ;
// fill T tree with the random integers
T->Fill();
}
f->cd();
T->Write();
f->Close();
}

void SecondTree() {
// open the first tree with the integers
TFile *f = new TFile(“firstfile.root”,“READ”);
// open another file for the output
TFile *f2 = new TFile(“outfile.root”,“RECREATE”);

// get the first tree
TTree * T = (TTree*)f->Get(“T”);
int n ;
T->SetBranchAddress(“n”,&n);

// prepare another tree for the the “average”
// of a given subset of the orginal tree
TTree *AVE = new TTree(“AVE”,“tree for the averages”);
float a;
AVE->Branch(“a”,&a,“a/f”);

// define an array in which some “averages” will be stored
const int max_possible_average_type=2;
float averages[max_possible_average_type]={0.};
int avcounter[max_possible_average_type]={0};

// LOOP on entries of the first tree
// => do some analysis

for (int i=0 ; i< T->GetEntries() ; i++) {
T->GetEntry(i);
cout << "reading entry nr. "<< i << ", n is "<<n ;

// if n is EVEN (average type 0)...
if (n%2==0) {
  averages[0] = (averages[0]*avcounter[0] + n) / (avcounter[0]+1) ; 
  avcounter[0]++;
  cout << " EVEN => average now is "<< averages[0] << endl;
}
// if n is ODD (average type 1)...
if (n%2==1) {
  averages[1] = (averages[1]*avcounter[1] + n) / (avcounter[1]+1) ; 
  avcounter[1]++;
  cout << " ODD => average now is "<< averages[1] << endl;
}

}
// end of the LOOP ==> write results to the output tree
for (int atype=0 ; atype < max_possible_average_type ; atype++) {
a = averages[atype] ;
AVE->Fill();
}

// write both the 1st tree and the 2nd one to the output file
f2->cd();
T->Write();
AVE->Write();
f2->Close();
}
void test(){
cout << “START…”<<endl;
TheFirstTree();
SecondTree();
cout << “…END”<<endl;
}
[/code]

Well, my question applied to this model is: how do I have to create AVE in a way that I can open outfile.root and plot

T->Draw(“n”,mysmartcut)
where mysmartcut is “consider only the entries of T which have been used to create the ODD average during the analysis”?
[size=85](well, I know that the result can be obtained with T->Draw(“n”,“n%2==1”), but it’s not what I need. I hope it’s clear from my post)[/size]

Thanks a lot in advance!

Hi,

In your example the information is lost. As it is there no trace whatsoever of which entries were used. One possibly solution is to register this information is a TEntryList, in which case the ‘smartcut’ would be to call SetEntryList on the input tree.

Cheers,
Philippe.

Hi,

In your example the information is lost. As it is there no trace whatsoever of which entries were used. One possibly solution is to register this information is a TEntryList, in which case the ‘smartcut’ would be to call SetEntryList on the input tree.

Cheers,
Philippe.

[quote=“pcanal”]Hi,

In your example the information is lost. As it is there no trace whatsoever of which entries were used. One possibly solution is to register this information is a TEntryList, in which case the ‘smartcut’ would be to call SetEntryList on the input tree.

Cheers,
Philippe.[/quote]
Hi,
thanks a lot for the reply, I will follow your suggestion and try using TEntryList!

Valerio