Problem with SetBranchAddress() in function

Dear ROOTers

In the attached macro “macroTestBranch.C” I have two classes, ClassXY and ClassXYZ (derived from ClassXY).
In my main function “TestBranch()” I have to define ClassXY but not ClassXYZ. For this reason I try to
SetBranchAddress() of the different trees in function “InitMyTree()” by passing classXY as parameter,
and converting ClassXY to ClassXYZ.
For comparison purposes I can use SetBranchAddress() in the main function by setting “setbr=1”.

As you can see, this results in different outputs. When you do:

.L macroTestBranch.C+ 
CreateFile("MyTest.root", 10000) 

// in new root session(s):
.L macroTestBranch.C+ 
TestBranch("MyTest.root", "MyTreeXY", 1) 
TestBranch("MyTest.root", "MyTreeXY", 0) 
TestBranch("MyTest.root", "MyTreeXYZ", 1) 
TestBranch("MyTest.root", "MyTreeXYZ", 0) 

you get the following output:

root [0] .L macroTestBranch.C+           
root [1] TestBranch("MyTest.root", "MyTreeXY", 1) 
*classXY = 0
*classXY = 0
*classXY = 0x4fbac40
n= 0   x= 0.0194095   y= 0.0118255   z= 0
n= 1   x= -0.517773   y= 1.50307   z= 0
n= 2   x= 0.161232   y= -1.70265   z= 0
n= 3   x= -0.294612   y= -0.0105459   z= 0
n= 4   x= -1.10784   y= -0.0700279   z= 0
n= 5   x= -0.622189   y= -0.402371   z= 0
(Int_t)(0)
root [2] TestBranch("MyTest.root", "MyTreeXY", 0) 
*classXY = 0
*classXY = 0
*classXY = 0
n= 0   x= 0.0194095   y= 0.0118255   z= 0
n= 1   x= -0.517773   y= 1.50307   z= 0
n= 2   x= 0.161232   y= -1.70265   z= 0
n= 3   x= -0.294612   y= -0.0105459   z= 0
n= 4   x= -1.10784   y= -0.0700279   z= 0
n= 5   x= -0.622189   y= -0.402371   z= 0
(Int_t)(0)
root [3] TestBranch("MyTest.root", "MyTreeXYZ", 1)
*classXY = 0
*classXY = 0
*classXY = 0x4fc14f0
n= 0   x= 2.19823   y= -0.797667   z= 5.46847
n= 1   x= 1.86729   y= 0.0991615   z= 3.4966
n= 2   x= -0.253787   y= -0.158189   z= 0.0894318
n= 3   x= -0.635309   y= 0.921764   z= 1.25327
n= 4   x= -0.769461   y= 0.813726   z= 1.25422
n= 5   x= -0.846865   y= -0.581968   z= 1.05587
(Int_t)(0)
root [4] TestBranch("MyTest.root", "MyTreeXYZ", 0)
*classXY = 0
*classXY = 0
*classXY = 0
n= 0   x= 2.19823   y= -0.797667   z= 5.46847
n= 1   x= 1.86729   y= 0.0991615   z= 3.4966
n= 2   x= -0.253787   y= -0.158189   z= 0.0894318
n= 3   x= -0.635309   y= 0.921764   z= 1.25327
n= 4   x= -0.769461   y= 0.813726   z= 1.25422
n= 5   x= -0.846865   y= -0.581968   z= 1.05587
(Int_t)(0)

It seems that only setting “setbr=1” returns a branch address “*classXY”, but not setting “setbr=0”.

Although this macro seems to work, the same situation in my real program causes root to crash with a bus error.

Thus my question is:
How can I set the branch address in function “InitMyTree()” so that it is recognized in my main function?
Is there another way to SetBranchAddress() outside to the main function “TestBranch()”?

Best regards
Christian
macroTestBranch.C (6.42 KB)

Christian,

see my changes in the attachment.
When setting a branch address you must pass the address of the pointer and not its value!

Rene
cstrato.C (6.75 KB)

Dear Rene

Thank you, I have tried to use the void* pointer but for some reason it did not work.

Sadly, I must admit that my problem is not quite solved yet, because I also want to set the leaf in function SchemeTree():.

   TTree   *scmtree = 0; 
   TLeaf   *scmleaf = 0;
   XScheme *scheme  = 0;

   scmtree = this->SchemeTree(&scheme, scmleaf); 
   if (scmtree == 0) return errGetTree;

Here is the function that I want to use:

TTree *XGCProcesSet::SchemeTree(void *scheme, TLeaf *scmleaf)
//TTree *XGCProcesSet::SchemeTree(void *scheme, void *scmleaf)
{
   TTree *scmtree = (TTree*)gDirectory->Get("SchemeTree"); 
   if (scmtree == 0) return 0;
   scmtree->SetBranchAddress("ScmBranch", scheme);
   scmleaf = scmtree->FindLeaf("fUnitID");      
//?   memcpy(scmleaf, scmtree->FindLeaf("fUnitID"), sizeof(TLeaf));

   return scmtree;
}//SchemeTree

I know that the problem is similar, but as you see I do not find the solution.

1, How can I create “scmleaf” and pass it to the main function?

2, Do I really have to “delete scheme;” at the end of my main function,
as mentioned in the document for TBranchElement::SetAddress()?

Best regards
Christian

[quote]Sadly, I must admit that my problem is not quite solved yet, because I also want to set the leaf in function SchemeTree([/quote]This may or may not be what you actually intend to do :slight_smile:. For what purpose to want to keep a pointer to the TLeaf? In most case the TLeaf in not that usually and getting a pointer to the TBranch is more appropriate.

Cheers,
Philippe.

Dear Philippe

Here is the reason why:

TTree *XExonProcesSet::UnitTree(TTree *scmtree, void *scheme, TLeaf *scmleaf,
                       void *unit, Int_t &numunits)
{
   XExonChip *chip = (XExonChip*)fSchemes->FindObject(fSchemeName, kTRUE);
   if (!chip) return 0;

   scmtree = (TTree*)gDirectory->Get(chip->GetSchemeTree()); 
   if (scmtree == 0) return 0;
   scheme = ((XExonScheme*)scheme);
   scmtree->SetBranchAddress("ScmBranch", scheme);

   TTree *idxtree = 0; 
   if (strcmp(fCaller->GetOption(), "exon") == 0) { 
      idxtree  = (TTree*)gDirectory->Get(chip->GetExonUnitTree()); //tree.exn
      if (idxtree == 0) return 0;

      numunits = chip->GetNumExonUnits();
      scmleaf  = scmtree->FindLeaf("fExonID");      
   } else if (strcmp(fCaller->GetOption(), "probeset") == 0) {
      idxtree  = (TTree*)gDirectory->Get(chip->GetProbesetUnitTree()); //tree.pbs
      if (idxtree == 0) return 0;

      numunits = idxtree->GetEntries();
      scmleaf  = scmtree->FindLeaf("fProbesetID");      
   } else {
      idxtree  = (TTree*)gDirectory->Get(chip->GetUnitTree());     //tree.idx
      if (idxtree == 0) return 0;

      numunits = chip->GetNumUnits();
      scmleaf  = scmtree->FindLeaf("fUnitID");      
   }//if
   idxtree->SetBranchAddress("IdxBranch", unit);

   return idxtree;
}//UnitTree

As you see, in this case the leaf to be returned depends on the setting of the option.

If you have a better solution I would appreciate it.

Furthermore, I would really like to know how to return the address of TLeaf.
I suppose it is basic C++ but at the moment I don’t find the solution.

Best regards
Christian

Hi,

[quote]Here is the reason why: [/quote]This tells ‘how’ you are trying to retrieve it. It does not tell me why the caller of XExonProcesSet::UnitTree is wanting the address of the leaf.

Cheers,
Philippe.

scheme = ((XExonScheme*)scheme); scmtree->SetBranchAddress("ScmBranch", scheme); This is incorrect. In needs to be XExonScheme **scheme_ptr_ptr = (XExonScheme**)scheme; scmtree->SetBranchAddress("ScmBranch", scheme);
AND the value passed in the scheme parameter MUST the address of a pointer to a XEonScheme.

Dear Philippe

Thank you for your hints. I realized that I made also another mistake by writing “myleaf = &leaf” instead of “*myleaf = leaf”.

The reason why I need to get the leaf is as follows:
In my macro I define classes ClassXY and ClassXYZ. When I want to access fZ in my main function I cannot
call “classXY->GetZ()” since this method does not exist in ClassXY. Thus in a function, which is dependent
on the type of derived class, I set “leaf = tree->FindLeaf(“fZ”)”, which I can then use in my main function.

Best regards
Christian

Hi Christian,

[quote]Thank you for your hints. I realized that I made also another mistake by writing “myleaf = &leaf” instead of “*myleaf = leaf”.[/quote]I assume that your core is now working or do you still have some additional issues?

Cheers,
Philippe

Dear Philippe

Thank you, at the moment everything seems to work fine. I am currently running diverse test files and until now everything looks ok.

Best regards
Christian