MakeClass and AddFriend

[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 …

Cheers,
Philippe.

Yes - sorry, that fixed the seg.violation.

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!

Maiken

Hi,

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).

Philippe.

Hi

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.

How should this be done correctly?

Thank you very much!
Maiken

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]

Philippe.

Hello,

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.

Thanks!!
Maiken

[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.

Philippe.

Ok, thank you very much for your help. It works well now!

Maiken

Hi,

I would like to go back to this:

[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?

Cheers,
delo

Hi,

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]

Cheers,
Philippe.

hi,

is seems I am having problem with the

 TFile *f = tree->GetCurrentFile();

if checking if isZombie I get:

Object.h:171
171 Bool_t TestBit(UInt_t f) const { return (Bool_t) ((fBits & f) != 0); }

and without this check it crashes when getting the Tree

tree2 = (TTree*)f->Get(“Validation/PixelRIOs”);

How does GetCurrentFile(); work?

cheers,
delo

Hi,

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) …

Cheers,
Philippe.

Hi,
I don’t understand this:

[code]if (tree->IsA() == TChain::Class()) {
tree2 = (TTree*)tree->Clone(“Photon”);
else {
TFile *f = tree->GetCurrentFile();

   tree2 = (TTree*)f->Get("Photon");

//…
//…

}
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.

Electron::Electron(TTree *tree)
{

 Init(tree);

 TFile *f = tree->GetCurrentFile();
 tree2 = (TTree*)f->Get("Photon");
 fOther = new Photon( tree2 );

}

cheers,
delo

[quote]are you missing a } before
[/quote]yes,

[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 );

Cheers,
Philippe.

[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.

thanks,
delo

but I doesn’t seem to work for me…
doing
tree2->Print()
or similarly
fOther->fChain->Print();

it shows the branches of the “Electron” tree from which we cloned the tree and not the Photon branches.

cheers,
delo

Hi,

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()); }

Cheers,
Philippe.