[quote]Both CollectionTree and physics trees are in physics.root [/quote]Humm … so the name the of TTree is ‘CollectionTree’ and not ‘CollectionLooper’ as it is attempted to be retrieved as! So simply using the correct name:tree = (TTree*)gDirectory->Get("CollectionTree");should solve the problem …
Now: how to manage to access the variables in the physics tree? This is the core of what I am trying. Will I need to add this thephysics tree as a friend to the CollectionTree?
How exactly to do this, and how to print out a variable from thephysics tree in CollectionLooper.C ?
Hope you still have patience to solve this last but crucial missing step!
You will need to access the variable of the physics via the physicsObject pointer. If you only have one file, make the physics tree friend of the CollectionTree is sufficient (as long as the entry number you want in both TTree are the same and/or the physics TTree has an adequate TTreeIndex).
Alternatively you can add to CollectionLooper::Loop inside the for loop calls to physicsObject->LoadTree(jentry) and physicsObject->fChain->GetEntry(jEntry).
sorry for being so pushy, but I would really like to know exactly (meaning code) to do this. I have tried to add the tree as friend, but do not succeed, this is why I would like to know exactly what to do.
What I do now is in CollectionLooper.h
then in CollectionLooper.C:
But this is obviously not correct as root does not recognize my jet_n variable.
humm … [code]Long64_t nbytes = 0, nb = 0;
for (Long64_t jentry=0; jentry<nentries;jentry++) {
Long64_t ientry = LoadTree(jentry);
if (ientry < 0) break;
nb = fChain->GetEntry(jentry); nbytes += nb;
// The following 3 lines are needed if the 2 tree are not friend.
ientry = physicsObject->LoadTree(jentry);
if (ientry < 0) break;
nb += physicsObject->fChain->GetEntry(jentry); nbytes += nb;
/how to access jet_n in the tree physics ??/
cout<<"From thephysics jet_n: "<jet_n<<endl;
cout<<"From CollectionLooper - stacomu_nTrack: "<<stacomu_nTrack<<endl;
}[/code]
now I understand that my problem was stupid, I did
physicsObject.jet_n instead of physicsObject->jet_n !!
This seems to work beautifully!
But I thought that when two trees are friends I do not have to specify in which tree to find it? That I should be able to just do
cout<<jet_n <<endl; ??
It is not a big problem, but would be good to know.
[quote]But I thought that when two trees are friends I do not have to specify in which tree to find it?[/quote]This is strictly true only for TTree::Draw and some of the Get/FindBranch variation.
[code]Electron::Electron(TTree tree)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
if (tree == 0) {
TFile f = (TFile)gROOT->GetListOfFiles()->FindObject(“AnalysisSkeleton.aan.root”);
if (!f) {
f = new TFile(“AnalysisSkeleton.aan.root”);
}
tree = (TTree)gDirectory->Get(“Electron”);
}
Init(tree);
TFile f = (TFile)gROOT->GetListOfFiles()->FindObject(“AnalysisSkeleton.aan.root”);
if (!f) {
f = new TFile(“AnalysisSkeleton.aan.root”);
}
tree2 = (TTree*)gDirectory->Get(“Photon”);
fOther = new Photon( tree2 );
}[/code]
which actually works like a charm.
But let’s say that we want to use a TChain as input tree; I should have something like:
{
gROOT->ProcessLine(".L Photon.C++g");
gROOT->ProcessLine(".L Electron.C++g");
TChain* ch = new TChain("Electron");
ch->AddFile("file1.root");
ch->AddFile("file2.root");
Electron* l = new Electron(ch);
}
which clearly doesn’t work because it doesen’t find the “Photon” TTree.
do you know any easy solution?
I recommend using:[code]Electron::Electron(TTree tree)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
if (tree == 0) {
TFile f = (TFile)gROOT->GetListOfFiles()->FindObject(“AnalysisSkeleton.aan.root”);
if (!f) {
f = new TFile(“AnalysisSkeleton.aan.root”);
}
tree = (TTree)f->Get(“Electron”);
}
Init(tree);
if (tree->IsA() == TChain::Class()) {
tree2 = (TTree*)tree->Clone(“Photon”); // Create a copy of the TChain with a different name but the same list of files.
} else {
TFile f = tree->GetCurrentFile();
tree2 = (TTree)f->Get(“Photon”);
if (tree2 == 0) {
f = (TFile*)gROOT->GetListOfFiles()->FindObject(“AnalysisSkeleton.aan.root”);
if (!f) {
f = new TFile(“AnalysisSkeleton.aan.root”);
}
tree2 = (TTree*)f->Get(“Photon”);
}
fOther = new Photon( tree2 );
}[/code]
TTree::GetCurrentFile returns the TFile to which the (current if in a TChain) TTree is associated. The symptom you describe seems to indicate that the TTree is either not associated with any file (i.e. GetCurrentFile() == 0) or that the TFile holding it has been deleted (in which case the TTree object has also been deleted) …
}
fOther = new Photon( tree2 );
[/code]
what’s the purpose of this cloning?
are you missing a } before
fOther = new Photon( tree2 );
?
and also
the code you posted is a constructor.
So in the case of
TChain* ch = new TChain("Electron");
ch->AddFile("file1.root");
ch->AddFile("file2.root");
Electron* l = new Electron(ch);
when calling the constructor Electron(ch) we also want to call the constructor of Photon but
what does it mean to get the current file when calling the constructor?
I tried to make a minimal code (not very general) which in theory should work but it doesn’t.
[quote]what’s the purpose of this cloning?[/quote]To get a copy of the list of files into a new TChain object with a new name so that the secondary MakeClass object can use it to look at the secondary set of TTree objects.
[quote]I tried to make a minimal code (not very general) which in theory should work but it doesn’t.
[/quote]To achieve what goal? The goal you provided with work only if the ‘tree’ pointer points directly to a TTree and does not point to a TChain object. You other code snipper indicates that you do pass a TChain so it will not work and you must use the code:if (tree->IsA() == TChain::Class()) {
// Make a copy of the TChain with a new name to point to the other set of TTree.
tree2 = (TTree*)tree->Clone("Photon");
} else {
// We have a real TTree.
TFile *f = tree->GetCurrentFile();
if (f == 0) {
Fatal("Constructor","The TTree we are being passed in not disk resident");
}
// This assumes that the other TTree (Photon) is located in the top level directory of the TFile.
tree2 = (TTree*)f->Get("Photon");
}
// Create the secondary MakeClass/MakeSelector object pointing to the secondary TTree.
fOther = new Photon( tree2 );
[quote=“pcanal”]To get a copy of the list of files into a new TChain object with a new name so that the secondary MakeClass object can use it to look at the secondary set of TTree objects.
[/quote]
this clearified completely.
I didn’t realize that it was possible to keep the list of files but changing th tree name.
Indeed, it is not working as expected. You can use the following work around:
tree2 = new TChain("Photon");
TIter next( ((TChain*)tree)->GetListOfFiles());
TObject *obj;
while( ( obj = (TChainElement*) next() ) ) {
tree2->Add(obj->GetTitle());
}