Hi Rene, I have had a chance now (after being out of town for a week) to test out the TTree::Bronch support of the two cases of storing a TObjArray as a data member of a class: by value and by pointer, and find that it does correctly support storage of the intact TObjArray in both cases - thank you. I have also begun to experiment with TTree::Bronch more extensively, in anticipation of applying it to the MINOS data model when it becomes the standard Branch splitting tool (in ROOT v3.01). One thing I've noticed is that unlike TTree::Branch, TTree::Bronch does not seem to split the data members of base classes of the object being stored on the Bronch, no matter what splitlevel I set for the Bronch. For example, for an Event class inheriting from an EvtBase class: class Event : public EvtBase { public: ... private: ... }; where EvtBase has an EvtHeader as a data member: class EvtBase: public TObject { public: ... private: EvtHeader fHeader; }; and the EvtHeader in turn has two data members, fRun & fEvent: class EvtHeader: public TObject { public: ... private: Int_t fRun; Int_t fEvent; }; The EvtHeader data members, fRun& fEvent, will be split onto two subbranches when storing the Event on a tree using TTree::Branch w/splitlevel =1, e.g. TTree* tree = new TTree("TestTree","test tree"); Event* event = 0; tree -> Branch("EventBranch","Event",&event,32000,1); will create two branches fHeader.fRun and fHeader.fEvent. But the EvtHeader will not be split into subbranches when storing the Event on a tree using TTree::Bronch w/splitlevel = 9 (or 100), e.g. TTree* tree = new TTree("TestTree","test tree"); Event* event = 0; tree -> Bronch("EventBranch","Event",&event,32000,9); produces only a single EvtHeader branch, fHeader. Is this an actual limitation of the TTree::Bronch method, or am I using it incorrectly? I would expect that setting the splitlevel higher would allow me to extend the depth of the splitting to the base class objects. I am using ROOT version 3.00.06 and gcc 2.95.2 on RH Linux. The driver code and classes are attached. Thanks again, -Sue *************** test driver code ****************************** #include <iostream.h> #include "TROOT.h" #include "TFile.h" #include "TTree.h" #include "Event.h" TROOT root("TestWrt","MINOS Persistency Package Test Write"); int main() { TFile* file = TFile::Open("test.root","RECREATE","test file"); TTree* tree = new TTree("TestTree","test tree"); Event* event = 0; tree -> Branch("EventBranch","Event",&event,32000,1); // or tree -> Bronch("EventBranch","Event",&event,32000,9); // Begin entry loop Int_t nent = 100; for (Int_t ient=0; ient < nent; ient++) { Event* event = new Event(1,ient,100); if (event) { tree -> Fill(); } delete event; } tree -> Write(); tree -> Print(); file -> Close(); return 0; } ********************** Event Class ********************* #ifndef EVENT_H #define EVENT_H #include "EvtBase.h" class Event : public EvtBase { public: Event(); Event(Int_t run, Int_t event, Int_t nsize); virtual ~Event(); private: Int_t fNSize; ClassDef(Event,1) // Event version 1 }; #endif // EVENT_H #include "Event.h" ClassImp(Event) Event::Event() : fNSize(0) { // Default constructor } Event::Event(Int_t run, Int_t event, Int_t nsize) : EvtBase(run,event), fNSize(nsize) { // Normal constructor } Event::~Event() { // Destructor } ***************** EvtBase class ******************************* #ifndef EVTBASE_H #define EVTBASE_H #include "EvtHeader.h" class EvtBase : public TObject { public: EvtBase(); EvtBase(Int_t run, Int_t event); virtual ~EvtBase(); private: EvtHeader fHeader; ClassDef(EvtBase,1) // EvtBase version 1 }; #endif // EVTBASE_H #include "EvtBase.h" ClassImp(EvtBase) EvtBase::EvtBase() { // Default constructor } EvtBase::EvtBase(Int_t run, Int_t event) { // Normal constructor fHeader.SetRun(run); fHeader.SetEvent(event); } EvtBase::~EvtBase() { // Destructor } *****************EvtHeader class *************************************** #ifndef EVTHEADER_H #define EVTHEADER_H #include "TObject.h" class EvtHeader : public TObject { public: EvtHeader(); EvtHeader(Int_t run, Int_t event); virtual ~EvtHeader(); void SetRun(Int_t run) {fRun = run;} void SetEvent(Int_t event) {fEvent = event;} private: Int_t fRun; Int_t fEvent; ClassDef(EvtHeader,1) // EvtHeader version 1 }; #endif // EVTHEADER_H #include "EvtHeader.h" ClassImp(EvtHeader) EvtHeader::EvtHeader() : fRun(0), fEvent(0) { // Default constructor } EvtHeader::EvtHeader(Int_t run, Int_t event) : fRun(run), fEvent(event){ // Normal constructor } EvtHeader::~EvtHeader() { // Destructor } Rene Brun wrote: > Hi Sue, > > As I said in my previous mail, the split mode supported by the current > TTree::Branch has many restrictions, including the one you mention > about the TObjArray. The new split mode supported by TTree::Bronch > has no limitations compared to the non-split mode. Bronch supports correctly > the two cases: TObjArray and TObjArray*. > With Bronch, the splitlevel can be used to control the depth of splitting. > Try for example: > > tree -> Bronch("Validity","VldContext",&valid,32000,9); > > I encourage people to start playing with TTree::Bronch instead of TTree::Branch. > However, note that, as indicated in the documentation of this function, > one cannot use TTree::Draw or the TreeViewer with Trees created with > TTree::Bronch in the production version 3.00/06. > This already works in my development version (not yet in CVS). > > Rene Brun > > Susan Kasahara wrote: > > > > Hi Rene and Pasha, > > Thank you both for your advice. I tried the TTree::Bronch method > > as you suggested and it did successfully write out the enumerated > > fDetector data member. I did notice that when I switched to the > > TTree::Bronch method, i.e. from > > tree -> Branch("Validity","VldContext",&valid,32000,1); > > to > > tree -> Bronch("Validity","VldContext",&valid,32000,1); > > that the TObject base class of VldContext was not longer split > > into two separate branches for the fUniqueId and fBits data members > > as it was using TTree::Branch. > > Is this to be expected? > > > > I have another TTree splitting question. I've noticed that when > > I attempt to store a class in split mode that has a TObjArray data member , e.g. > > class Event { > > public: > > ... > > private: > > TObjArray fData; > > Int_t fEvtNumber; > > }; > > > > And store it on a tree in split mode: > > TTree* tree = new TTree("TestTree","test tree"); > > Event* event = 0; > > tree -> Branch("EventBranch","Event",&event,32000,1); > > > > That ROOT will attempt to split the TObjArray (to 7 branches), and since the > > data member of the TObjArray which contains the array's data has been "!" out, ROOT will > > not write the actual data of the TObjArray to the TTree. > > On the other hand, storing the TObjArray by pointer as a data member of the > > Event class, e.g. > > class Event { > > public: > > ... > > private: > > TObjArray* fData; > > Int_t fEvtNumber; > > }; > > does seem to work since the customized Streamer of the TObjArray is invoked > > to stream the TObjArray data out to a single ROOT TBranch. > > I guess what I'd like is to preserve the Event structure of the first case (with > > the fData TObjArray stored by value), but have the Event splitting results of the > > second case, with the TObjArray data streamed out to a single ROOT TBranch. > > Is this possible? > > Thanks again, > > -Sue > > > > Rene Brun wrote: > >
This archive was generated by hypermail 2b29 : Fri Jun 08 2001 - 11:51:22 MEST