]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/TTreeStream.cxx
Unnecessary include of TNamed removed.
[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     TDirectory * backup = gDirectory;
193     fFile->cd();
194     char chname[100];
195     sprintf(chname,"Tree%d",id);
196     clayout = new TTreeStream(chname);
197     clayout->fId=id;
198     fDataLayouts->AddAt(clayout,entries);
199     if (backup) backup->cd();
200   }
201   return *clayout;
202 }
203
204
205 TTreeStream  & TTreeSRedirector::operator<<(const char* name)
206 {
207   //
208   // return reference to the data layout with given identifier
209   // if not existing - creates new
210   if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
211   TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
212   Int_t entries = fDataLayouts->GetEntriesFast();
213
214   if (!clayout){
215     TDirectory * backup = gDirectory;
216     fFile->cd();
217     clayout = new TTreeStream(name);
218     clayout->fId=-1;
219     clayout->SetName(name);
220     fDataLayouts->AddAt(clayout,entries);    
221     if (backup) backup->cd();
222   }
223   return *clayout;
224 }
225
226
227
228
229 void TTreeSRedirector::Close(){
230   //
231   //
232   TDirectory * backup = gDirectory;
233   fFile->cd();
234   if (fDataLayouts){
235     Int_t entries = fDataLayouts->GetEntriesFast();
236     for (Int_t i=0;i<entries;i++){
237       TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
238       if (layout){
239         if (layout->fTree) layout->fTree->Write(layout->GetName());
240       }
241     }
242     delete fDataLayouts;
243     fDataLayouts=0;
244   }
245   if (backup) backup->cd();
246 }
247
248
249
250 //-------------------------------------------------------------
251 TTreeDataElement:: TTreeDataElement(Char_t type) :
252   TNamed(),
253   fType(type),
254   fDType(0),
255   fClass(0),
256   fPointer(0)
257 {
258   //
259   //
260   //
261 }
262
263 TTreeDataElement:: TTreeDataElement(TDataType* type) :
264   TNamed(),
265   fType(0),
266   fDType(type),
267   fClass(0),
268   fPointer(0)
269 {
270   //
271   //
272   //
273 }
274
275 TTreeDataElement:: TTreeDataElement(TClass* cl) :
276   TNamed(),
277   fType(0),
278   fDType(0),
279   fClass(cl),
280   fPointer(0)
281 {
282   //
283   //
284   //
285 }
286
287 //-------------------------------------------------------------------
288 TTreeStream::TTreeStream(const char *treename):
289   TNamed(treename,treename),
290   fElements(0),
291   fBranches(0),
292   fTree(new TTree(treename, treename)),
293   fCurrentIndex(0),
294   fId(0),
295   fNextName(),
296   fNextNameCounter(),
297   fStatus(0)
298 {
299   //
300   // Standard ctor
301   //
302 }
303
304 TTreeStream::~TTreeStream()
305 {
306   //
307   // Class dtor
308   //
309   fElements->Delete();
310   fBranches->Clear();
311   delete fElements;
312   delete fBranches;
313 }
314
315 void TTreeStream::Close()
316 {
317   //
318   // Flush data to disk and close
319   //
320   fTree->Write();
321 }
322
323 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
324 {
325   //
326   // Insert object of given type
327   //
328   if (!fElements) fElements = new TObjArray(1000);
329   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
330   if (!element) {
331     element = new TTreeDataElement(type);
332     //
333     char name[1000];
334     if (fNextName.Length()>0){
335       if (fNextNameCounter==0){
336         sprintf(name,"%s",(const char*)fNextName);
337       }
338       if (fNextNameCounter>0){
339         sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
340       }      
341     }
342     else{
343       sprintf(name,"B%d.",fCurrentIndex);
344     }
345     element->SetName(name);
346     //
347     element->SetPointer(pointer);
348     fElements->AddAt(element,fCurrentIndex);
349     fCurrentIndex++;
350     return 0; //new element added
351   }
352   if (element->GetType()!=type){
353     fStatus++;
354     return 1; //mismatched data element
355   }
356   element->SetPointer(pointer);
357   fCurrentIndex++;
358   return 0;
359 }
360
361 Int_t TTreeStream::CheckIn(TObject *o){
362   //
363   // Insert TObject
364   //
365   if (!o) return 0;
366   if (!fElements) fElements = new TObjArray(1000);
367   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
368   if (!element) {
369     element = new TTreeDataElement(o->IsA());
370     //
371     char name[1000];
372     if (fNextName.Length()>0){
373       if (fNextNameCounter==0){
374         sprintf(name,"%s",(const char*)fNextName);
375       }
376       if (fNextNameCounter>0){
377         sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
378       }      
379     }
380     else{
381       sprintf(name,"B%d",fCurrentIndex);
382     }
383     element->SetName(name);
384
385     element->SetPointer(o);
386     fElements->AddAt(element,fCurrentIndex);
387     fCurrentIndex++;
388     return 0; //new element added
389   }
390   if (element->fClass!=o->IsA()){
391     fStatus++;
392     return 1; //mismatched data element
393   }
394   element->SetPointer(o);
395   fCurrentIndex++;
396   return 0;  
397 }
398
399 void TTreeStream::BuildTree(){
400   //
401   // Build the Tree
402   //
403   if (fTree && fTree->GetEntries()>0) return;
404   if (!fTree)  fTree = new TTree(GetName(),GetName());
405   Int_t entries = fElements->GetEntriesFast();  
406   fBranches = new TObjArray(entries);
407   
408   for (Int_t i=0;i<entries;i++){
409     //
410     TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
411     char bname1[1000];
412     if (element->GetName()[0]==0){
413       sprintf(bname1,"B%d",i);
414     }
415     else{
416       sprintf(bname1,element->GetName());
417     }
418     if (element->fClass){
419       if (element->fClass->GetBaseClass("TClonesArray")){
420         TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
421         fBranches->AddAt(br,i);
422       }else
423         {
424           TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
425           fBranches->AddAt(br,i);
426         }
427     }
428     if (element->GetType()>0){
429       char bname2[1000];
430       sprintf(bname2,"B%d/%c",i,element->GetType());
431       TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
432       fBranches->AddAt(br,i);
433     }
434   }
435 }
436
437 void TTreeStream::Fill(){
438   //
439   // Fill the tree
440   //
441   if (fTree) { 
442     Int_t entries=fElements->GetEntriesFast();
443     if (entries>fTree->GetNbranches()) BuildTree();
444     for (Int_t i=0;i<entries;i++){    
445       TTreeDataElement* el  = (TTreeDataElement*)fElements->At(i);
446       if (!el) continue;
447       if (!el->GetType()) continue;
448       TBranch      * br  = (TBranch*)fBranches->At(i);
449       if (br &&el){
450         if (el->GetType())  br->SetAddress(el->fPointer);
451       }
452     }
453     if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
454     fStatus=0;
455   }
456 }
457
458 TTreeStream & TTreeStream::Endl()
459 {
460   //
461   // Perform pseudo endl operation
462   //
463   if (fTree->GetNbranches()==0) BuildTree();
464   Fill();
465   fStatus =0;
466   fCurrentIndex=0;
467   return *this;
468 }
469
470
471 TTreeStream  &TTreeStream::operator<<(Char_t *name)
472 {
473   //
474   // Endl 
475   //
476   if (name[0]=='\n'){
477     return Endl();
478   }
479   //
480   //if tree was already defined ignore
481   if (fTree->GetEntries()>0) return *this;
482   //check branch name if tree was not 
483   //
484   Int_t last=0;
485   for (last=0;;last++){
486     if (name[last]==0) break;    
487   }
488   
489   if (last>0&&name[last-1]=='='){
490     fNextName = name;
491     fNextName[last-1]=0;
492     fNextNameCounter=0;
493   }
494   return *this;
495 }
496