Re: [ROOT] TClonesArray gathering

From: Ben Kilminster (bjk@fnal.gov)
Date: Fri Apr 09 2004 - 20:42:37 MEST


> I do not understand the logic in your test program.
> Nowhere you fill the TClonesArray.
> I had to make a few changes to compile your code. See attached tar 
> file.
> The results correspond to what I expect from the code.
> As I am now leaving for 2 weeks, I suggest you communicate directly
> with Philippe to make progress.

Hi,

The basic logic is that I want to take several TClonesArrays and merge 
them together, and put them in a TTree.

Here are the steps.
1)  Several "Daughter" objects have TClonesArrays of "Thing" objects.
2)  The Parent makes a tree of all of the "Thing" objects.

Here is how I implemented it:
1)  In the Parent code, I call Daughter::Want(int val) several times 
for each Daughter object.
2)  Daughter::Want(int val) adds a Thing to its TClonesArray of Things :
      MyThing = new ((*CloneThing)[GotAThing]) Thing;
3)  At the end of the Parent code, the Parent loops over all the 
Daughters, and adds all the Thing objects to a Tree.

Here is the problem:
1)  The parent is able to get the number of Things from each Daughter.  
(ie, I am able to pass an integer from the Daughter object to the 
Parent object).
2)  The parent is unable to merge multiple TClonesArrays together.  And 
it is unable to put them in a tree.  I tried two ways:  getting a 
pointer to each Thing in each of the Daughter's TClonesArrays, and 
getting a pointer to each TClonesArray of Things and combining these.
I'll bet that I am just not referencing the TClonesArrays properly.


Sorry if it wasn't clear before, I hope this is better.  It was 
probably my geeky coding analogy of the Parent - Daughter relationship 
that made it tough to follow.


Ben




On Mar 26, 2004, at 7:43 AM, Rene Brun wrote: > > Rene Brun > > Ben Kilminster wrote: >> >> Hi, >> >> Here is the code to gather TClonesArrays of objects and put them in a >> TTree. >> There is a Parent class, a Daughter class, and a Thing class. >> The Parent object creates some Daughter objects. The Daughters decide >> they want some Things. The Parent object then checks the Daughters, >> finds out what Things are wanted and makes an entry in the tree. The >> following example doesn't crash, but it also doesn't store the >> TClonesArray into the TTree. I tried to do this by adding the >> Daughters' Things one at a time to the tree, but I couldn't get the >> syntax correct (commented part). >> >> { >> // This macro requires Thing.hh, Thing.cc, Daughter.hh, Daughter.cc, >> Parent.hh, Parent.cc >> gSystem->CompileMacro("Thing.cc"); >> gSystem->CompileMacro("Daughter.cc"); >> gSystem->CompileMacro("Parent.cc"); >> Parent P(1); >> P->HasDaughters(); >> } >> >> ----------------------------------------- >> //Thing.hh >> class Thing : public TObject { >> public: >> Thing(); >> ~Thing() {}; >> int Value; >> int ThingID; >> ClassDef(Thing,1) >> }; >> ----------------------------------------- >> //Thing.cc >> #include "Thing.hh" >> Thing::Thing() { >> ThingID = -999; >> Value = -999; >> } >> ClassImp(Thing) >> ----------------------------------------- >> // Daughter.hh >> #include "TClonesArray.h" >> #include "Thing.hh" >> class Daughter >> { >> public: >> int ID; >> int GotAThing; >> TClonesArray* CloneThing; Thing* MyThing; >> Daughter (); >> Daughter (int minutes_apart); >> void Reset(); >> void Want(int cash); >> }; >> ----------------------------------------- >> // Daughter.cc >> Daughter::Daughter (){} >> Daughter::Daughter (int minutes_apart) >> { >> this->ID = minutes_apart; >> CloneThing = new TClonesArray("Thing"); >> } >> void Daughter::Reset() >> { >> CloneThing->Clear(); >> GotAThing = 0; >> } >> void Daughter::Want(int cash) >> { >> MyThing = new ((*CloneThing)[GotAThing]) Thing; >> MyThing->ThingID = this->ID; >> MyThing->Value = cash; >> GotAThing++; >> } >> ----------------------------------------- >> // Parent.hh >> #include "Daughter.hh" >> #include "TClonesArray.h" >> #include "TFile.h" >> #include "TTree.h" >> >> class Parent { >> public: >> Parent( ); >> Parent(int tree); >> ~Parent( ); >> void HasDaughters(); >> private: >> TFile* newfile; >> TTree* MoneyTree; >> Daughter* Triplet[3]; >> TClonesArray* CloneThing; >> Thing* MyThing; >> int numThings; >> }; >> ----------------------------------------- >> // Parent.cc >> #include "Parent.hh" >> #include "TClonesArray.h" >> #include "TFile.h" >> #include "TRandom.h" >> >> #include <assert.h> >> #include <string> >> #include <strstream> >> #include <iostream> >> #include <stdio.h> >> >> using namespace std; >> >> Parent::Parent(int tree) { >> // Open a file, and a tree >> newfile = new TFile("MoneyTree.root","RECREATE","Simple ROOT >> Ntuple"); >> MoneyTree = new TTree("T","MoneyTree"); >> // Add a branch for things >> CloneThing = new TClonesArray("Thing"); >> MoneyTree->Branch("CloneThing",&CloneThing,32000,2); >> MoneyTree->Branch("numThings",&numThings,"numThings/I"); >> // Verify what we have constructed... >> newfile->ls(); >> TObjArray * br = MoneyTree->GetListOfBranches(); >> TIter i(br); >> cout << "-----------------------------------------------------" >> << >> endl; >> cout << "Branches:" << endl; >> while( TBranch * b = (TBranch*)i()){ >> cout << b->GetName() << " : " << b->GetTitle() << endl; >> } >> cout << "-----------------------------------------------------" >> << >> endl; >> } >> >> Parent::Parent( ) >> {} >> Parent::~Parent( ) >> {} >> >> void Parent::HasDaughters() >> { >> CloneThing->Clear(); >> // make daughters >> *Triplet = new Daughter[3]; >> Triplet[0] = new Daughter(0); >> Triplet[1] = new Daughter(35); >> Triplet[2] = new Daughter(56); >> >> // Daughters want things >> Triplet[0]->Reset(); >> Triplet[1]->Reset(); >> Triplet[2]->Reset(); >> Triplet[0]->Want(100); >> Triplet[0]->Want(150); >> Triplet[2]->Want(100); >> >> // Parent checks what daughters want, puts entry in money tree >> numThings = 0; >> for(int nd=0; nd <3; nd++) { >> int wantCash = Triplet[nd]->GotAThing; >> printf("Daughter %d wants %d things\n",nd, >> wantCash);fflush(stdout); >> // Tried to add the whole clone array: runs, but doesn't store >> Things >> if (wantCash > 0) { >> CloneThing = (TClonesArray*) Triplet[nd]->CloneThing->Clone(); >> numThings += wantCash; >> } >> >> // // Also tried to add one at a time, can't get syntax right >> // for (int i = 0; i < wantCash; i++) { >> // MyThing = new >> ((*CloneThing)[numThings])Triplet[nd]->CloneThing->At(i); >> // numThings++; >> // } >> >> } >> MoneyTree->Fill(); >> >> // The above steps may repeat, then the file closes >> MoneyTree->GetCurrentFile()->Write(); >> MoneyTree->GetCurrentFile()->Close(); >> } >> ----------------------------------------- >> >> On Mar 12, 2004, at 2:25 AM, Rene Brun wrote: >> >>> Hi Ben, >>> >>> It is not obvious to follow your explanations without looking at a >>> concrete >>> piece of code ::) >>> I have the feeling that you do not fill the TClonesArray correctly. >>> You must >>> call the constructor of the class in the TClonesArray (as shown in >>> $ROOTSYS/test/Event.cxx). >>> Could you send the shortest possible file reproducing the problem? >>> >>> Rene brun >>> >>> >>> >>> Ben Kilminster wrote: >>>> >>>> I am trying to figure out how to fill a Tree in one object with a >>>> TClonesArray from another object. >>>> My code is crashing when I try to do the copying. >>>> >>>> In my main class, I define a tree with a branch, with a TClonesArray >>>> of >>>> objects in it: >>>> >>>> class MainSim >>>> { >>>> TTree* SimTree; >>>> TClonesArray* CloneXftpixel; >>>> xft2Lpixel* xftpixelB; >>>> ... >>>> } >>>> >>>> MainSim::MainSim() >>>> { >>>> CloneXftpixel = new TClonesArray("xft2Lpixel"); >>>> SimTree = new TTree("T","SimTree"); >>>> SimTree->Branch("xft2Lpixel",&CloneXftpixel,32000,2); >>>> ... >>>> } >>>> >>>> I then fill the TClonesArray in another class, like : >>>> >>>> class FinderChip >>>> { TClonesArray* CloneXftpixel; >>>> xft2Lpixel* xft2pixelF; >>>> int iPixel; >>>> ... >>>> } >>>> >>>> FinderChip::FillBlock() >>>> { >>>> iPixel++; >>>> xft2pixelF = new ((*CloneXftpixel)[iPixel]) xft2Lpixel; >>>> xft2pixelF->Chip = this->COT_chip; >>>> ... >>>> } >>>> >>>> Now, I want to fill the SimTree with the array of xft2Lpixels from >>>> the >>>> FinderChip object. >>>> But I have many FinderChip objects, with any number of xft2pixelF >>>> objects, so I have to gather them by checking the iPixel counter >>>> for >>>> each FinderChip : >>>> >>>> MainSim::FillTree() >>>> { >>>> CloneXftpixel->Clear() >>>> >>>> for(int nbrd=0; nbrd<8; nbrd++) { >>>> for (int nchp=0;nchp<8;nchp++) { >>>> int nPix = >>>> XFTSystem->finderCrate[crate]->FinderBoard2_4Elements[nbrd]- >>>>> finderChipElements[nchp]->iPixel; >>>> if (nPix > 0) >>>> CloneXftpixel = >>>> (TClonesArray*)XFTSystem->finderCrate[crate]- >>>>> FinderBoard2_4Elements[nbrd]->finderChipElements[nchp]- >>>>>> CloneXftpixel- >>>>> Clone(); >>>> } >>>> } >>>> >>>> SimTree->Fill() >>>> >>>> This compiles and runs, but crashes filling the CloneXftpixel in the >>>> FillTree() method. >>>> >>>> Instead of the if (nPix>0), I also tried to do this with a loop as >>>> in >>>> the At() statement : >>>> for (int i=0; i < nPix; nPix++) { >>>> xftpixelB = >>>> (xft2Lpixel*)XFTSystem->finderCrate[crate]- >>>>> FinderBoard2_4Elements[nbrd]->finderChipElements[nchp]- >>>>>> CloneXftpixel- >>>>> At(i); >>>> } >>>> >>>> but this crashed in the same place. >>>> >>>> What is the correct way to do this ? >>>> >>>> Cheers, >>>> Ben > <ben.tar.gz>



This archive was generated by hypermail 2b29 : Sun Jan 02 2005 - 05:50:07 MET