Schizophrenic behaviour of TChain::SetBranchAddress

Hi,
I have sent this twice to roottalk today, and my emails (from two different
adresses) don’t seem to arrive…

Basically, I have a TChain of files I wish to analyse with v3.10/01.
When I do

TChain tchen(“tree”);

tchen.Add(“rfio:cchpssindra:/hpss/in2p3.fr/group/indra/campagne5/root/run6020.root”);

tchen.Add(“rfio:cchpssindra:/hpss/in2p3.fr/group/indra/campagne5/root/run6021.root”);

tchen.Add(“rfio:cchpssindra:/hpss/in2p3.fr/group/indra/campagne5/root/run6022.root”);
KVINDRAReconEvent *data = 0;
tchen.SetBranchAddress(“data”,&data);

nothing happens, that is to say that the ctor for KVINDRAReconEvent is not called
when I “SetBranchAddress”. This is fine because as soon as I do

tchen.GetEntry(0)

then the ctor is called and at the moment when it is called at least one of the files in the TChain
is open and in memory, because the ctor in question looks for an object in the file which was
saved along with the TTree. This is the behaviour I expect.

Now, I have created an analysis class with tchen.MakeSelector(), and I do

TChain tchen(“tree”);

tchen.Add(“rfio:cchpssindra:/hpss/in2p3.fr/group/indra/campagne5/root/run6020.root”);

tchen.Add(“rfio:cchpssindra:/hpss/in2p3.fr/group/indra/campagne5/root/run6021.root”);

tchen.Add(“rfio:cchpssindra:/hpss/in2p3.fr/group/indra/campagne5/root/run6022.root”);
tchen.Process(“Analysis.C+”);

In the Analysis::Init() method, I have the following lines:

// Set object pointer
data = 0;
// Set branch addresses
if (tree == 0) return;
fChain = (TChain*)tree;
fChain->SetMakeClass(1);
fChain->SetBranchAddress(“data”,&data);

and so I would expect the same behaviour as the previous example, but in fact the call
to SetBranchAddress in this case actually calls the ctor for KVINDRAReconEvent, and apparently
none of the files in the TChain is open at this time, because the ctor does not find the object
it looks for, with the inevitable consequences (segv…).

Can you tell me how to get the same behaviour as in the first case when I use TChain::Process ?

Thankyou
John

Hi John,

I have not seen your mails to roottalk.
They are not visible in the roottalk digest too. This means that roottalk did not see you mails at all. Are you sure you sent the mails to roottalk@root.cern.ch ?

Back to your problem. Did you generate your selector via TTree::MakeSelector with no changes? or did you implement the selector from scratch by hand ?

Note that TTree::MakeSelector has several limitations in case your objects contain embedded objects or pointers to other objects.

In case uou implemented the selector yourself, remove the line
fChain->SetMakeClass(1);

Rene

Hi Rene

Did you generate your selector via TTree::MakeSelector with no changes?
or did you implement the selector from scratch by hand ?

I used MakeSelector, the only changes I made to the code were essential:

  • remove ProcessCut and ProcessFill from the header file
  • add #include “KVINDRAReconEvent.h” in the appropriate place

I tried removing SetMakeClass anyway, it didn’t change anything.

I looked at the code for TChain::Process (going through TTreeVirtualPlayer or whatever on the way), it’s pretty complicated in places but I can’t see where anything might happen different to what I do by hand. The question seems to be: what can affect the behaviour of SetBranchAddress i.e. in one case make it call the default ctor for the branch object, and not in another case. And when calling “Process” for a TChain, at what point are the files of the chain actually loaded into memory ?

John

Hi John,

TChain::SetBranchAddress does not call your object constructor. It stores only the address of your pointer. When the TChain loads a new file, then TTree::SetBranchAddress is called with the address stored in the TChain. Your object constructor will be called once in order to build the dictionary for the class.
Typically when a TSelector is used, the shared library containing the classes is not available. In this case, ROOT will emulate the creation of an object in memory and you will not see a call to your constructor.
To make progress with this, I will need (as usual) the shortest possible tar file with a complete test reproducing the problem.

Rene

OK Rene, I’ve prepared a .tgz with a simple example showing exactly the same behaviour I’m seeing with my (far more complicated) real-life classes.
The libraries were compiled with v3.10/01 on a RH9 Linux system with gcc3.2. The Makefile and the LinkDef follow the same model as my real-life versions.

In Classes.C/h are two classes, ClassA and ClassB. The ctor of ClassA looks in gROOT to see if an object “ClassB” exists.

In MakeTree.C are three functions. I used the first one (MakeTree(i)) to create 3 files (tests_1.root, tests_2.root, tests_3.root), each containing a TTree of ClassA objects, and one ClassB object.

The second function (MakeSelector) creates the analysis script TestAnalysis and demonstrates that (i) SetBranchAddress behaves correctly and (ii) when the ctor for ClassA is called (by MakeSelector) the files are open and a ClassB object is found. I see the following output:

root [0] .L libClasses.so
root [1] .L MakeTree.C+
Info in TUnixSystem::ACLiC: creating shared library /home/john/ROOT/TestTChainProcess/./MakeTree_C.so
root [2] MakeSelector()
Calling SetBranchAddress
Calling MakeSelector
Found object
Found object
Info in TTreePlayer::MakeClass: Files: TestAnalysis.h and TestAnalysis.C generated from Tree: tree

I modified the TestAnalysis.h file (indicated by comments) to remove ProcessFill/Cut, add the #include for Classes.h, and print a message just before SetBranchAddress in Init.

Finally, the third function in MakeTree.C (ProcessChain) chains together the files and calls TChain::Process. When I do this I see the following:

root [0] .L libClasses.so
root [1] .L MakeTree.C+
Info in TUnixSystem::ACLiC: creating shared library /home/john/ROOT/TestTChainProcess/./MakeTree_C.so
root [2] ProcessChain()
Calling SetBranchAddress
Not found
Not found
After call

Therefore once again in this case SetBranchAddress is calling the ctor, the files are not open and the ClassB object is not found.

Have fun!!
Thanks a lot for your time
John
TestTChainProcess.tar (220 KB)