Re: [ROOT] TTree question

From: Pasha Murat (630)840-8237@169G ((630)840-8237@169G)
Date: Wed May 24 2000 - 16:43:25 MEST


Hi Sue - I'd guess that in principle your problem is solvable - if before
writing out every single object one writes out its classname, then, provided
that one makes it a requirement that every class to be written out has a CINT 
dictionary, it would be possible to read everything back correctly. However
in this scenario the performance of I/O system might be severely hurt.
	A simple practical solution might be not to use an automatically 
generated Streamer but to write it yourself - this of course will not work
if `fShape' means different things for different objects.
	Another possibility would be to write a TMyShape class with hand-written
Streamer which would know how to write/read the classes derived from it and to 
replace `TShape' in `Simple' with `TMyShape'. This solution will work in most 
practical cases, it also implies much less performance penalty.

							-best, Pasha

Susan Kasahara wrote:
> 
> Hi Rooter's,
> I am wondering if the following is possible:
>   I have a class "Simple" (since this is a simplified example of what
> I'm actually trying to do) that has two data members:
> Int_t   fID;
> TShape* fShape;
> 
> It has a constructor:
> Simple(Int_t id, TShape* shape): fID(id), fShape(shape) { }
> 
> that can be called with an object of any class that inherits from TShape, e.g.
> 
> TTUBE* tube = new TTUBE("TUBE","TUBE","void",150,200,400); // TTUBE inherits from TShape
> Simple* simple = new Simple(1,tube);  // invoke Simple constructor
> 
> I am trying to store the Simple objects in a ROOT Tree.  What I find
> is that when I fill the tree with the Simple objects, e.g.
> 
> TTree *simpletree = new TTree("SimpleTree","Simple Tree");
> Simple *simple = 0;
> // Split branches to store fShape objects & fID on separate branches
> simpletree->Branch("Simple","Simple",&simple,16000,1);
> TTUBE *tube = new TTUBE("TUBE","TUBE","void",150,200,400);
> simple = new Simple(1,tube);
> simpletree -> Fill(); // store first Simple object in Tree
> ...
> 
> ,that the TTree::Fill method correctly recognizes that the fShape pointer should
> invoke the TTUBE::Streamer method to write the TTUBE object to the TTree.
> 
> But when I try to read the Simple object back in from the tree, e.g.:
> 
> ...
> // Retrieve ROOT tree holding the data
> TTree *tree = (TTree*)file -> Get("SimpleTree");
> Simple *simple = new Simple();
> tree -> SetBranchAddress("Simple",&simple);
> nb = tree -> GetEntry(0);
> ...
> 
> it does not invoke the TTUBE::Streamer method to read the TTUBE object
> back into memory, instead it invokes the TShape::Streamer method (and
> then I get an error message).
> 
> Has anybody tried something similar or have any ideas on how to
> make this work?  Or is this just a bad design idea, I'd appreciate input
> on that too.
> I attach the code that I'm using on a RH Linux 6.0 system using
> ROOT v2.24/02.
> 
> Thanks for any help,
> Sue Kasahara
> 
> #ifndef SIMPLE_H
> #define SIMPLE_H
> ///////////////////////////////////////////////////////////////////////////
> //                                                                       //
> // Simple class                                                 //
> //                                                                       //
> ///////////////////////////////////////////////////////////////////////////
> #include "TShape.h"
> #include <iostream.h>
> 
> class Simple : public TObject {
> 
> private:
>    Int_t   fID;         // id number
>    TShape* fShape;      // pointer to base class shape
> 
> public:
> 
>    Simple() : fID(0), fShape(0) { }
>    Simple(Int_t id, TShape* shape): fID(id), fShape(shape) { }
>    virtual ~Simple();
>    virtual void Print(Option_t *option = "") const;
> 
>    ClassDef(Simple,1)  //Simple class
> };
> 
> #endif                         // SIMPLE_H
> 
> /////////////////////////////////////////////////////////////////////////////////
> // Simple.cxx                                                          //
> /////////////////////////////////////////////////////////////////////////////////
> #include <iostream.h>
> #include "Simple.h"
> 
> ClassImp(Simple)
> 
> Simple::~Simple() {
> // Destructor
>   if (fShape) {
>     delete fShape;
>     fShape =0;
>   }
> }
> 
> void Simple::Print(Option_t *option) const {
>   // Print the contents
>   cout << "fID= " << fID << endl;
>   fShape -> Print();
> 
> }
> 
> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> // Driver code to open file, create tree, and write 3 Simple objects to     //
> // tree.                                                                                                           //
> ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> #include "TROOT.h"
> #include "TFile.h"
> #include "TTree.h"
> #include "TTUBE.h"
> #include "Simple.h"
> 
> TROOT test("test","Program to test simple classes");
> 
> int main(int argc, char **argv)
> {
> 
> // Open output file to hold events
>   TFile *simplefile = new TFile("simple.root","RECREATE","Simple root file");
> 
> // Create a ROOT tree to hold the simple data
>   TTree *simpletree = new TTree("SimpleTree","Simple Tree");
> 
>   Simple *simple = 0;
>   // Split branches to store fShape objects & fID on separate branches
>   simpletree->Branch("Simple","Simple",&simple,16000,1);
> 
>   for (Int_t ient=0; ient < 3; ient++) {
> // Create 3 Simple objects containing TTube's and store each in tree
>     TTUBE *tube = new TTUBE("TUBE","TUBE","void",150,200,400);
>     // tube is adopted & deleted by Simple
>     simple = new Simple(ient,tube);
>     simple -> Print();
>     simpletree -> Fill();
>     delete simple;
>   }
> 
> // Write the simple tree to file
>   simplefile->Write();
> // Print final summary of simple tree contents
>   simpletree->Print();
> 
>   return 0;
> }
> 
> ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> //                                                                                                                       //
> // Code to open root file containing tree, Get tree, and attempt to read in //
> // 3 Simple objects from tree                                                                         //
> //                                                                                                                      //
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> #include "TROOT.h"
> #include "TFile.h"
> #include "TTree.h"
> #include "TTUBE.h"
> #include "Simple.h"
> 
> TROOT test("test","Program to test simple classes");
> 
> int main(int argc, char **argv)
> {
> 
> // Open file to read Simple entries
>   TFile *file = new TFile("simple.root","READ");
> 
> // Retrieve ROOT tree holding the data
>   TTree *tree = (TTree*)file -> Get("SimpleTree");
> 
>   Simple *simple = new Simple();
>   tree -> SetBranchAddress("Simple",&simple);
> 
>   Int_t nentries = (Int_t)tree -> GetEntries();
>   Int_t nb;
>   for (Int_t ient=0; ient < nentries; ient++) {
>      nb = tree -> GetEntry(ient);
>      simple -> Print();
>   }
> 
>   return 0;
> 
> }



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:26 MET