Hi Ben, 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. 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
This archive was generated by hypermail 2b29 : Sun Jan 02 2005 - 05:50:06 MET