Variable size array as leaf in TTree

Hi ROOTers,

I want to add an array as a leaf to my tree; the problem is, I don’t know how big this array is, until I actually run the code, and then too, the array size depends on the event. Is there a way I can make a variable sized array into a leaf of a TTree. I know I can make an overestimate of my array size and fill in just the members that are present, but I am wondering if there is a way to do it as a variable size array instead.

I have attached an example code here, saved as FillATree.C and run as root FillATree.C++. What I want to do is something like var4 in that code. (this code doesn’t work, I can get it to work, if I comment out all the var4 lines).

I also like to use a c-struct to define my variables, like I have shown in the example, for portability purposes. And since this method specifically requires that I initialize my leaves, I just don’t know how to proceed.

Can anyone help?

#include <TTree.h>
#include <TFile.h>
#include <TRandom.h>

class Newclassvar
{
public:
   Newclassvar(): var1(0),var2(0) 
  {
    for(int ii=0; ii<4; ii++)
      {
	var3[ii]=0;
      } 
  }

  int var1;
  int var2;
  int var3[4];
  int var4[];

  ClassDef (Newclassvar,2);
};

#ifdef __MAKECINT__
#pragma link C++ class Newclassvar+;
#endif

class tclassA {
public:
   tclassA() : sfile(0),fOutputTree(0),snewclassvar(0) {}
  virtual ~tclassA() {}

  TFile *sfile;
  TTree* fOutputTree;
  Newclassvar *snewclassvar;

  virtual void Initialize(void) {
    sfile = new TFile ("SFiles.root","RECREATE");
    
    fOutputTree = new TTree("userLoopTree","A simple summary tree");
    fOutputTree->SetDirectory(sfile);

    snewclassvar = new Newclassvar;

    fOutputTree->Branch("SBranch",&snewclassvar, 16000, 99);
    
  }

  bool operator () (int /* event */) {
    
    
    //do some stuff to get variables; for now I'll use dummies
    snewclassvar->var1 = 10;
    snewclassvar->var2 = 11;
    for(Int_t ii=0; ii<4; ii++)
      {
	snewclassvar->var3[ii] = 12+ii;
      }
    Int_t cc = 10*gRandom->Rndm(1);
    for(Int_t ii=0; ii<cc; ii++)
      {
	snewclassvar->var4[ii] = cc+ii;
      }
    fOutputTree->Fill();
    return true; 
  }

  
  void Finalize() {    
    fOutputTree->Print();
    sfile->Write();
    sfile->Close();
  }

};

int FillATree() {
  tclassA usercode;
  usercode.Initialize();
  for(int iev=0; iev<10; iev++)
    {
      usercode(0);
    }
  usercode.Finalize();
  return 0;
}
  • Sujeewa

Hi,

You can either a variable size C-style array (see data member ‘len’ and var5) or a std::vector (see data member var 6).[code]#include <TTree.h>
#include <TFile.h>
#include <TRandom.h>
#include

class Newclassvar
{
public:
Newclassvar(): var1(0),var2(0)
{
for(int ii=0; ii<4; ii++)
{
var3[ii]=0;
}
}

int var1;
int var2;
int var3[4];
int len;
int *var5; //[len] this comment tell ROOT I/O the size of the array
std::vector var6;

ClassDef (Newclassvar,2);
};

#ifdef MAKECINT
#pragma link C++ class Newclassvar+;
#endif

class tclassA {
public:
tclassA() : sfile(0),fOutputTree(0),snewclassvar(0),len(0),var5(0) {}
virtual ~tclassA() {}

TFile sfile;
TTree
fOutputTree;
Newclassvar *snewclassvar;

virtual void Initialize(void) {
sfile = new TFile (“SFiles.root”,“RECREATE”);

fOutputTree = new TTree("userLoopTree","A simple summary tree");
fOutputTree->SetDirectory(sfile);

snewclassvar = new Newclassvar;

fOutputTree->Branch("SBranch",&snewclassvar, 16000, 99);

}

bool operator () (int /* event */) {

//do some stuff to get variables; for now I'll use dummies
snewclassvar->var1 = 10;
snewclassvar->var2 = 11;
for(Int_t ii=0; ii<4; ii++)
  {

snewclassvar->var3[ii] = 12+ii;
}
Int_t cc = 10gRandom->Rndm(1);
if (cc < snewclassvar->len) {
delete [] snewclassvar->var6;
snewclassvar->var6 = new int[cc];
snewclassvar->len = cc;
}
for(Int_t ii=0; ii<cc; ii++)
{
snewclassvar->var5[ii] = cc+ii;
}
cc = 10
gRandom->Rndm(1);
snewclassvar->clear();
for(Int_t jj=0; jj<cc; jj++)
{
snewclassvar->var6.push_back(cc+jj);
}
fOutputTree->Fill();
return true;
}

void Finalize() {
fOutputTree->Print();
sfile->Write();
sfile->Close();
}

};

int FillATree() {
tclassA usercode;
usercode.Initialize();
for(int iev=0; iev<10; iev++)
{
usercode(0);
}
usercode.Finalize();
return 0;
}[/code]

Cheers,
Philippe.

Hi Philippe,

Thanks, but sometime ago when I ran into problems, you told me that I need to initialize my arrays in my C-struct itself Reading a TTree filled using a struct like class Would I run in to problems since I won’t initialize this time in the C-struct? Or maybe the
snewclassvar->var5 = new int[cc];
regardless of if (cc < snewclassvar->len) or not, would actually initialize the array and serve the same purpose, even though it is not done in the C-struct?

Thanks again!

  • Sujeewa

[quote]Would I run in to problems since I won’t initialize this time in the C-struct? [/quote]Yes you would. I indeed forgot to also add this required modification to your code. Either way, you might consider using std::vector.

Cheers,
Philippe.