]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/TTreeStream.cxx
coverity 10161
[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(10000);
329   if (fElements->GetSize()<=fCurrentIndex) fElements->Expand(fCurrentIndex*2);
330   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
331   if (!element) {
332     element = new TTreeDataElement(type);
333     //
334     char name[1000];
335     if (fNextName.Length()>0){
336       if (fNextNameCounter==0){
337         sprintf(name,"%s",(const char*)fNextName);
338       }
339       if (fNextNameCounter>0){
340         sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
341       }      
342     }
343     else{
344       sprintf(name,"B%d.",fCurrentIndex);
345     }
346     element->SetName(name);
347     //
348     element->SetPointer(pointer);
349     fElements->AddAt(element,fCurrentIndex);
350     fCurrentIndex++;
351     return 0; //new element added
352   }
353   if (element->GetType()!=type){
354     fStatus++;
355     return 1; //mismatched data element
356   }
357   element->SetPointer(pointer);
358   fCurrentIndex++;
359   return 0;
360 }
361
362 Int_t TTreeStream::CheckIn(TObject *o){
363   //
364   // Insert TObject
365   //
366   if (!o) return 0;
367   if (!fElements) fElements = new TObjArray(1000);
368   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
369   if (!element) {
370     element = new TTreeDataElement(o->IsA());
371     //
372     char name[1000];
373     if (fNextName.Length()>0){
374       if (fNextNameCounter==0){
375         sprintf(name,"%s",(const char*)fNextName);
376       }
377       if (fNextNameCounter>0){
378         sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
379       }      
380     }
381     else{
382       sprintf(name,"B%d",fCurrentIndex);
383     }
384     element->SetName(name);
385
386     element->SetPointer(o);
387     fElements->AddAt(element,fCurrentIndex);
388     fCurrentIndex++;
389     return 0; //new element added
390   }
391   if (element->fClass!=o->IsA()){
392     fStatus++;
393     return 1; //mismatched data element
394   }
395   element->SetPointer(o);
396   fCurrentIndex++;
397   return 0;  
398 }
399
400 void TTreeStream::BuildTree(){
401   //
402   // Build the Tree
403   //
404   if (fTree && fTree->GetEntries()>0) return;
405   if (!fTree)  fTree = new TTree(GetName(),GetName());
406   Int_t entries = fElements->GetEntriesFast();  
407   fBranches = new TObjArray(entries);
408   
409   for (Int_t i=0;i<entries;i++){
410     //
411     TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
412     char bname1[1000];
413     if (element->GetName()[0]==0){
414       sprintf(bname1,"B%d",i);
415     }
416     else{
417       sprintf(bname1,element->GetName());
418     }
419     if (element->fClass){
420       if (element->fClass->GetBaseClass("TClonesArray")){
421         TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
422         fBranches->AddAt(br,i);
423       }else
424         {
425           TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
426           fBranches->AddAt(br,i);
427         }
428     }
429     if (element->GetType()>0){
430       char bname2[1000];
431       sprintf(bname2,"B%d/%c",i,element->GetType());
432       TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
433       fBranches->AddAt(br,i);
434     }
435   }
436 }
437
438 void TTreeStream::Fill(){
439   //
440   // Fill the tree
441   //
442   if (fTree) { 
443     Int_t entries=fElements->GetEntriesFast();
444     if (entries>fTree->GetNbranches()) BuildTree();
445     for (Int_t i=0;i<entries;i++){    
446       TTreeDataElement* el  = (TTreeDataElement*)fElements->At(i);
447       if (!el) continue;
448       if (!el->GetType()) continue;
449       TBranch      * br  = (TBranch*)fBranches->At(i);
450       if (br &&el){
451         if (el->GetType())  br->SetAddress(el->fPointer);
452       }
453     }
454     if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
455     fStatus=0;
456   }
457 }
458
459 TTreeStream & TTreeStream::Endl()
460 {
461   //
462   // Perform pseudo endl operation
463   //
464   if (fTree->GetNbranches()==0) BuildTree();
465   Fill();
466   fStatus =0;
467   fCurrentIndex=0;
468   return *this;
469 }
470
471
472 TTreeStream  &TTreeStream::operator<<(const Char_t *name)
473 {
474   //
475   // Endl 
476   //
477   if (name[0]=='\n'){
478     return Endl();
479   }
480   //
481   //if tree was already defined ignore
482   if (fTree->GetEntries()>0) return *this;
483   //check branch name if tree was not 
484   //
485   Int_t last=0;
486   for (last=0;;last++){
487     if (name[last]==0) break;    
488   }
489   
490   if (last>0&&name[last-1]=='='){
491     fNextName = name;
492     fNextName[last-1]=0;
493     fNextNameCounter=0;
494   }
495   return *this;
496 }
497