]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/TTreeStream.cxx
Bug fix
[u/mrichter/AliRoot.git] / STEER / TTreeStream.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 //
19 //  marian.ivanov@cern.ch
20 //
21 //  ------------------------------------------------------------------------------------------------
22 //  TTreeStream
23 //  Standard stream (cout) like input for the tree
24 //  Run and see TTreeStreamer::Test() - to see TTreeStreamer functionality
25 //  ------------------------------------------------------------------------------------------------  
26 //
27 //  -------------------------------------------------------------------------------------------------
28 //  TTreeSRedirector
29 //  Redirect file to  different TTreeStreams  
30 //  Run and see   TTreeSRedirector::Test() as an example of TTreeSRedirectorer functionality 
31 // 
32
33 #include <TClass.h>
34 #include <TFile.h>
35 #include <TDirectory.h>
36 #include <TObjArray.h>
37 #include <TTree.h>
38 #include <TTreeStream.h>
39
40 ClassImp(TTreeDataElement)
41 ClassImp(TTreeStream)
42 ClassImp(TTreeSRedirector)
43
44
45
46 void TTreeStream::Test()
47 {
48   //
49   // 
50   TFile *ftest = new TFile("teststreamer.root","recreate");
51   if (!ftest) ftest = new TFile("teststreamer.root","new");
52   //
53   //create to streems Tree1 and Tree2
54   TTreeStream stream1("Tree1");
55   TTreeStream stream2("Tree2");
56   //
57   Char_t ch='s';
58   Float_t f=3.;
59   Float_t f2=1;
60   TObject *po  = new TObject;
61   TObject *po2 = new TObject;
62   for (Int_t i=0;i<100000;i++) {
63     f=i*100;
64     po->SetUniqueID(i);
65     po2->SetUniqueID(i*100);
66     ch=i%120;
67     //
68     //    Stream the data
69     //    The data layout of stream is defined during first invocation of streamer.
70     //    Endl is the trigger which define the end of structure.
71     // 
72     //    The name of branch can be specified using strings with = at the the end
73     //    if string is not specified automatic convention is u (sed B0, B1, ...Bn)
74     stream1<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
75     f  = 1./(100.1+i);
76     f2 = -f;     
77     //3.) just another example - we can fill the same tree with different objects
78     //
79     stream2<<f<<po<<"\n";
80     stream2<<f2<<po2<<"\n";
81   }
82   //
83   //4.) Close the streeamers (Write the streamed tree's to the file) and close the corresponding file.
84   //
85   stream1.Close();
86   stream2.Close();
87   ftest->Close();
88   delete ftest;
89   //
90   //5.) and now see results  in file tteststreamer.root
91 }
92
93
94
95 void TTreeSRedirector::Test()
96 {
97   //
98   //Example test function to show functionality of TTreeSRedirector
99   //
100   //
101   //1.)create the  redirector associated with file (testredirector.root)
102   //
103   //
104   TTreeSRedirector *pmistream= new TTreeSRedirector("testredirector.root");
105   TTreeSRedirector &mistream = *pmistream;
106   Char_t ch='s';
107   Float_t f=3.;
108   Float_t f2=1;
109   TObject *po  = new TObject;
110   TObject *po2 = new TObject;
111   for (Int_t i=0;i<100000;i++) {
112     f=i*100;
113     po->SetUniqueID(i);
114     po2->SetUniqueID(i*100);
115     ch=i%120;
116     //
117     //2.) create the tree with identifier specified by first argument
118     //                                layout specified by sequence of arguments
119     //                                Tree identifier has to be specified as first argument !!! 
120     //    if the tree and layout was already defined the consistency if layout is checked
121     //                                if the data are consisten fill given tree 
122     //    the name of branch can be specified using strings with = at the the end
123     //    if string is not specified use automatic convention  B0, B1, ...Bn
124     mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
125     f  = 1./(100.1+i);
126     f2 = -f; 
127     
128     //3.) just another example - we can fill the same tree with different objects
129     //
130     mistream<<"TreeK"<<f<<po<<"\n";
131     mistream<<"TreeK"<<f2<<po2<<"\n";
132   }
133   //
134   //4.) write the streamed tree's to the file and close the corresponding file in destructor
135   //
136   delete pmistream;
137   //
138   //5.) and now see results in file testredirector.root 
139 }
140
141
142 TTreeSRedirector::TTreeSRedirector(const char *fname) :
143   fFile(new TFile(fname,"recreate")),
144   fDataLayouts(0)
145 {
146   //
147   // Constructor
148   //
149   if (!fFile){
150     fFile = new TFile(fname,"new");
151   }
152 }
153
154 TTreeSRedirector::~TTreeSRedirector()
155 {
156   //
157   // Destructor
158   //
159   Close();       //write the tree to the selected file
160   fFile->Close();
161   delete fFile;
162 }
163 void TTreeSRedirector::StoreObject(TObject* object){
164   //
165   //
166   //
167   TDirectory * backup = gDirectory;
168   fFile->cd();
169   object->Write();
170   if (backup) backup->cd();
171 }
172
173
174
175 TTreeStream  & TTreeSRedirector::operator<<(Int_t id)
176 {
177   //
178   // return reference to the data layout with given identifier
179   // if not existing - creates new
180   if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
181   TTreeStream *clayout=0;
182   Int_t entries = fDataLayouts->GetEntriesFast();
183   for (Int_t i=0;i<entries;i++){
184     TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
185     if (!layout) continue;
186     if (layout->fId==id) {
187       clayout = layout;
188       break;
189     }
190   }
191   if (!clayout){
192     fFile->cd();
193     char chname[100];
194     sprintf(chname,"Tree%d",id);
195     clayout = new TTreeStream(chname);
196     clayout->fId=id;
197     fDataLayouts->AddAt(clayout,entries);
198   }
199   return *clayout;
200 }
201
202
203 TTreeStream  & TTreeSRedirector::operator<<(const char* name)
204 {
205   //
206   // return reference to the data layout with given identifier
207   // if not existing - creates new
208   if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
209   TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
210   Int_t entries = fDataLayouts->GetEntriesFast();
211
212   if (!clayout){
213     fFile->cd();
214     clayout = new TTreeStream(name);
215     clayout->fId=-1;
216     clayout->SetName(name);
217     fDataLayouts->AddAt(clayout,entries);    
218   }
219   return *clayout;
220 }
221
222
223
224
225 void TTreeSRedirector::Close(){
226   //
227   //
228   TDirectory * backup = gDirectory;
229   fFile->cd();
230   if (fDataLayouts){
231     Int_t entries = fDataLayouts->GetEntriesFast();
232     for (Int_t i=0;i<entries;i++){
233       TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
234       if (layout){
235         if (layout->fTree) layout->fTree->Write(layout->GetName());
236       }
237     }
238     delete fDataLayouts;
239     fDataLayouts=0;
240   }
241   if (backup) backup->cd();
242 }
243
244
245
246 //-------------------------------------------------------------
247 TTreeDataElement:: TTreeDataElement(Char_t type) :
248   TNamed(),
249   fType(type),
250   fDType(0),
251   fClass(0),
252   fPointer(0)
253 {
254   //
255   //
256   //
257 }
258
259 TTreeDataElement:: TTreeDataElement(TDataType* type) :
260   TNamed(),
261   fType(0),
262   fDType(type),
263   fClass(0),
264   fPointer(0)
265 {
266   //
267   //
268   //
269 }
270
271 TTreeDataElement:: TTreeDataElement(TClass* cl) :
272   TNamed(),
273   fType(0),
274   fDType(0),
275   fClass(cl),
276   fPointer(0)
277 {
278   //
279   //
280   //
281 }
282
283 //-------------------------------------------------------------------
284 TTreeStream::TTreeStream(const char *treename):
285   TNamed(treename,treename),
286   fElements(0),
287   fBranches(0),
288   fTree(new TTree(treename, treename)),
289   fCurrentIndex(0),
290   fId(0),
291   fNextName(),
292   fNextNameCounter(),
293   fStatus(0)
294 {
295   //
296   // Standard ctor
297   //
298 }
299
300 TTreeStream::~TTreeStream()
301 {
302   //
303   // Class dtor
304   //
305   fElements->Delete();
306   fBranches->Clear();
307   delete fElements;
308   delete fBranches;
309 }
310
311 void TTreeStream::Close()
312 {
313   //
314   // Flush data to disk and close
315   //
316   fTree->Write();
317 }
318
319 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
320 {
321   //
322   // Insert object of given type
323   //
324   if (!fElements) fElements = new TObjArray(1000);
325   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
326   if (!element) {
327     element = new TTreeDataElement(type);
328     //
329     char name[1000];
330     if (fNextName.Length()>0){
331       if (fNextNameCounter==0){
332         sprintf(name,"%s",(const char*)fNextName);
333       }
334       if (fNextNameCounter>0){
335         sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
336       }      
337     }
338     else{
339       sprintf(name,"B%d.",fCurrentIndex);
340     }
341     element->SetName(name);
342     //
343     element->SetPointer(pointer);
344     fElements->AddAt(element,fCurrentIndex);
345     fCurrentIndex++;
346     return 0; //new element added
347   }
348   if (element->GetType()!=type){
349     fStatus++;
350     return 1; //mismatched data element
351   }
352   element->SetPointer(pointer);
353   fCurrentIndex++;
354   return 0;
355 }
356
357 Int_t TTreeStream::CheckIn(TObject *o){
358   //
359   // Insert TObject
360   //
361   if (!o) return 0;
362   if (!fElements) fElements = new TObjArray(1000);
363   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
364   if (!element) {
365     element = new TTreeDataElement(o->IsA());
366     //
367     char name[1000];
368     if (fNextName.Length()>0){
369       if (fNextNameCounter==0){
370         sprintf(name,"%s",(const char*)fNextName);
371       }
372       if (fNextNameCounter>0){
373         sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
374       }      
375     }
376     else{
377       sprintf(name,"B%d",fCurrentIndex);
378     }
379     element->SetName(name);
380
381     element->SetPointer(o);
382     fElements->AddAt(element,fCurrentIndex);
383     fCurrentIndex++;
384     return 0; //new element added
385   }
386   if (element->fClass!=o->IsA()){
387     fStatus++;
388     return 1; //mismatched data element
389   }
390   element->SetPointer(o);
391   fCurrentIndex++;
392   return 0;  
393 }
394
395 void TTreeStream::BuildTree(){
396   //
397   // Build the Tree
398   //
399   if (fTree->GetEntries()>0) return;
400   fTree = new TTree(GetName(),GetName());
401   Int_t entries = fElements->GetEntriesFast();  
402   fBranches = new TObjArray(entries);
403   
404   for (Int_t i=0;i<entries;i++){
405     //
406     TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
407     char bname1[1000];
408     if (element->GetName()[0]==0){
409       sprintf(bname1,"B%d",i);
410     }
411     else{
412       sprintf(bname1,element->GetName());
413     }
414     if (element->fClass){
415       if (element->fClass->GetBaseClass("TClonesArray")){
416         TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
417         fBranches->AddAt(br,i);
418       }else
419         {
420           TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
421           fBranches->AddAt(br,i);
422         }
423     }
424     if (element->GetType()>0){
425       char bname2[1000];
426       sprintf(bname2,"B%d/%c",i,element->GetType());
427       TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
428       fBranches->AddAt(br,i);
429     }
430   }
431 }
432
433 void TTreeStream::Fill(){
434   //
435   // Fill the tree
436   //
437   if (fTree) { 
438     Int_t entries=fElements->GetEntriesFast();
439     if (entries>fTree->GetNbranches()) BuildTree();
440     for (Int_t i=0;i<entries;i++){    
441       TTreeDataElement* el  = (TTreeDataElement*)fElements->At(i);
442       if (!el) continue;
443       if (!el->GetType()) continue;
444       TBranch      * br  = (TBranch*)fBranches->At(i);
445       if (br &&el){
446         if (el->GetType())  br->SetAddress(el->fPointer);
447       }
448     }
449     if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
450     fStatus=0;
451   }
452 }
453
454 TTreeStream & TTreeStream::Endl()
455 {
456   //
457   // Perform pseudo endl operation
458   //
459   if (fTree->GetNbranches()==0) BuildTree();
460   Fill();
461   fStatus =0;
462   fCurrentIndex=0;
463   return *this;
464 }
465
466
467 TTreeStream  &TTreeStream::operator<<(Char_t *name)
468 {
469   //
470   // Endl 
471   //
472   if (name[0]=='\n'){
473     return Endl();
474   }
475   //
476   //if tree was already defined ignore
477   if (fTree->GetEntries()>0) return *this;
478   //check branch name if tree was not 
479   //
480   Int_t last=0;
481   for (last=0;;last++){
482     if (name[last]==0) break;    
483   }
484   
485   if (last>0&&name[last-1]=='='){
486     fNextName = name;
487     fNextName[last-1]=0;
488     fNextNameCounter=0;
489   }
490   return *this;
491 }
492