How to create sub-sub branch manually


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.36.000
Platform: MacOS 26
Compiler: clang


Hi,

I was developing the ROOTIO.jl package, which is a Julia interface for ROOT. We want to support creating nested structures from Julia, and to do that, we need to add sub-branches, sub-sub-branches and so on.

I came across the this post that talks about creating sub-branches. However, the final example doesn’t work with the TBrowser. Also, creating a sub-sub-branch gives the error missing StreamerInfo.

Code:

#include <TFile.h>
#include <TTree.h>
#include <TBranch.h>
#include <TBranchElement.h>
#include <TLeafElement.h>
#include <TObject.h>
#include <TList.h>

struct TBranchElementModifier : public TBranchElement {
   void SetID (int id) { fID = id; }
};

int tst ()
{
  TFile * outFile = new TFile ( "Trees/TreeFile.root", "RECREATE" );
  TTree * outTree = new TTree ( "MyTree", "MyTree" );

  Int_t buffer0[2] = { -1, -1 };       // dummy top-level buffer
  Int_t buffer1[2] = { -1, -1 };   // buffer for sub-branch 1
  Int_t buffer2[2] = { -1, -1 };       // buffer for sub-branch 2
  Int_t buffer3[2] = { -1 };       // buffer for sub-sub-branch of sub-branch 1

  // define the top branch
  TBranch * topBranch = new TBranchElement ( );
  topBranch->SetName ( "MainBr" );
  topBranch->SetTree ( outTree );
  outTree->GetListOfBranches()->Add ( topBranch );

  // --> correction needed of branch ID
  ((TBranchElementModifier*)topBranch)->SetID(-1);

  // --> an address is required also... (most likely dummy)
  topBranch->SetAddress ( &buffer0[0] );
  //        it also works with:
  //            topBranch->SetAddress ( topBranch );

  // --> a dummy leaf must be added
  TLeaf * leaf = new TLeafElement ( topBranch, "", -1, 0 );
  topBranch->GetListOfLeaves()->Add(leaf);

  // define the sub-branches

  TBranch * subBranch1 = new TBranchElement ( );
  subBranch1->SetName ( "Sub1" );
  subBranch1->SetTree ( outTree );
  ((TBranchElementModifier*)subBranch1)->SetID(-1);
  subBranch1->SetAddress ( &buffer1[0] );
  TLeaf * leaf2 = new TLeafElement ( subBranch1, "", -1, 0 );
  subBranch1->GetListOfLeaves()->Add(leaf2);

  TBranch * subBranch2 = new TBranch ( outTree, "Sub2", &buffer2[0], "VarA2/I:VarB2/I" );

  TBranch * subSubBranch11 = new TBranch ( outTree, "SubSub11", &buffer3[0], "VarAA1/I" );

  topBranch->GetListOfBranches()->Add ( subBranch1 );
  topBranch->GetListOfBranches()->Add ( subBranch2 );

  subBranch1->GetListOfBranches()->Add( subSubBranch11 );

  //------------------------------------------------------------
  // Fill the TTree with outTree->Fill()
  for (int i = 0; i < 10; ++i) {
    buffer1[0] = i;
    buffer1[1] = i + 10;

    buffer2[0] = i * 2;
    buffer2[1] = i * 3;

    buffer3[0] = 100 * i;

    outTree->Fill();
  }
  //------------------------------------------------------------

  outTree->Write();

  outFile->Close();
  delete outFile;

  return ( 0 );
}

void readtst() {
    TFile *f = TFile::Open("Trees/TreeFile.root");
    TTree *t = (TTree*)f->Get("MyTree");
    t->Scan();
    t->Print();
}

Best,
Yash

Hi @yashnator, @pcanal might be able to help you with this.