]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/STEERBase/TTreeStream.cxx
option to switch CR off
[u/mrichter/AliRoot.git] / STEER / STEERBase / 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 void TTreeSRedirector::Test2()
94 {
95   //
96   //Example test function to show functionality of TTreeSRedirector
97   //
98   //
99   //1.)create the  redirector associated with file (testredirector.root)
100   //
101   //
102   TFile* file = new TFile("test.root","recreate");
103   TTreeSRedirector *pmistream= new TTreeSRedirector();
104   TTreeSRedirector &mistream = *pmistream;
105   Char_t ch='s';
106   Float_t f=3.;
107   Float_t f2=1;
108   TObject *po  = new TObject;
109   TObject *po2 = new TObject;
110   for (Int_t i=0;i<100000;i++) {
111     f=i*100;
112     po->SetUniqueID(i);
113     po2->SetUniqueID(i*100);
114     ch=i%120;
115     //
116     //2.) create the tree with identifier specified by first argument
117     //                                layout specified by sequence of arguments
118     //                                Tree identifier has to be specified as first argument !!! 
119     //    if the tree and layout was already defined the consistency if layout is checked
120     //                                if the data are consisten fill given tree 
121     //    the name of branch can be specified using strings with = at the the end
122     //    if string is not specified use automatic convention  B0, B1, ...Bn
123     mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
124     f  = 1./(100.1+i);
125     f2 = -f; 
126     
127     //3.) just another example - we can fill the same tree with different objects
128     //
129     mistream<<"TreeK"<<f<<po<<"\n";
130     mistream<<"TreeK"<<f2<<po2<<"\n";
131   }
132   //
133   //4.) write the streamed tree's to the file and close the corresponding file in destructor
134   //
135   delete pmistream;
136   delete file;
137   //
138   //5.) and now see results in file testredirector.root 
139 }
140
141 void TTreeSRedirector::Test()
142 {
143   //
144   //Example test function to show functionality of TTreeSRedirector
145   //
146   //
147   //1.)create the  redirector associated with file (testredirector.root)
148   //
149   //
150   TTreeSRedirector *pmistream= new TTreeSRedirector("testredirector.root");
151   TTreeSRedirector &mistream = *pmistream;
152   Char_t ch='s';
153   Float_t f=3.;
154   Float_t f2=1;
155   TObject *po  = new TObject;
156   TObject *po2 = new TObject;
157   for (Int_t i=0;i<100000;i++) {
158     f=i*100;
159     po->SetUniqueID(i);
160     po2->SetUniqueID(i*100);
161     ch=i%120;
162     //
163     //2.) create the tree with identifier specified by first argument
164     //                                layout specified by sequence of arguments
165     //                                Tree identifier has to be specified as first argument !!! 
166     //    if the tree and layout was already defined the consistency if layout is checked
167     //                                if the data are consisten fill given tree 
168     //    the name of branch can be specified using strings with = at the the end
169     //    if string is not specified use automatic convention  B0, B1, ...Bn
170     mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
171     f  = 1./(100.1+i);
172     f2 = -f; 
173     
174     //3.) just another example - we can fill the same tree with different objects
175     //
176     mistream<<"TreeK"<<f<<po<<"\n";
177     mistream<<"TreeK"<<f2<<po2<<"\n";
178   }
179   //
180   //4.) write the streamed tree's to the file and close the corresponding file in destructor
181   //
182   delete pmistream;
183   //
184   //5.) and now see results in file testredirector.root 
185 }
186
187
188 TTreeSRedirector::TTreeSRedirector(const char *fname,const char * option) :
189   fDirectory(NULL),
190   fDirectoryOwner(kTRUE),
191   fDataLayouts(NULL)
192 {
193   //
194   // Constructor
195   //
196   TString name(fname);
197   if (!name.IsNull()){
198     fDirectory = new TFile(fname,option);
199   }
200   else
201   {
202     fDirectory = gDirectory;
203     fDirectoryOwner = kFALSE;
204   }
205 }
206
207 TTreeSRedirector::~TTreeSRedirector()
208 {
209   //
210   // Destructor
211   //
212   Close();       //write the tree to the selected file
213   if (fDirectoryOwner)
214   {
215     fDirectory->Close();
216     delete fDirectory;
217   }
218 }
219 void TTreeSRedirector::StoreObject(TObject* object){
220   //
221   //
222   //
223   TDirectory * backup = gDirectory;
224   fDirectory->cd();
225   object->Write();
226   if (backup) backup->cd();
227 }
228
229 void  TTreeSRedirector::SetDirectory(TDirectory *sfile){
230   //
231   // Set the external file 
232   // In case other file already attached old file is closed before
233   // Redirector will be the owner of file ?
234   if (fDirectory && fDirectoryOwner) {
235     fDirectory->Close();
236     delete fDirectory;
237   }
238   fDirectory=sfile;
239 }
240
241 TTreeStream  & TTreeSRedirector::operator<<(Int_t id)
242 {
243   //
244   // return reference to the data layout with given identifier
245   // if not existing - creates new
246   if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
247   TTreeStream *clayout=0;
248   Int_t entries = fDataLayouts->GetEntriesFast();
249   for (Int_t i=0;i<entries;i++){
250     TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
251     if (!layout) continue;
252     if (layout->fId==id) {
253       clayout = layout;
254       break;
255     }
256   }
257   if (!clayout){
258     TDirectory * backup = gDirectory;
259     fDirectory->cd();
260     char chname[100];
261     snprintf(chname,100,"Tree%d",id);
262     clayout = new TTreeStream(chname);
263     clayout->fId=id;
264     fDataLayouts->AddAt(clayout,entries);
265     if (backup) backup->cd();
266   }
267   return *clayout;
268 }
269
270 void TTreeSRedirector::SetExternalTree(const char* name, TTree* externalTree)
271 {
272   TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
273
274   if (!clayout){
275     TDirectory * backup = gDirectory;
276     fDirectory->cd();
277     clayout = new TTreeStream(name,externalTree);
278     clayout->fId=-1;
279     clayout->SetName(name);
280     Int_t entries = fDataLayouts->GetEntriesFast();
281     fDataLayouts->AddAt(clayout,entries);
282     if (backup) backup->cd();
283   }
284   //else
285   //  AliError(Form("identifier %s already associated",name));
286 }
287
288
289 TTreeStream  & TTreeSRedirector::operator<<(const char* name)
290 {
291   //
292   // return reference to the data layout with given identifier
293   // if not existing - creates new
294   if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
295   TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
296   Int_t entries = fDataLayouts->GetEntriesFast();
297
298   if (!clayout){
299     TDirectory * backup = gDirectory;
300     fDirectory->cd();
301     clayout = new TTreeStream(name);
302     clayout->fId=-1;
303     clayout->SetName(name);
304     fDataLayouts->AddAt(clayout,entries);    
305     if (backup) backup->cd();
306   }
307   return *clayout;
308 }
309
310
311
312
313 void TTreeSRedirector::Close(){
314   //
315   //
316   TDirectory * backup = gDirectory;
317   fDirectory->cd();
318   if (fDataLayouts){
319     Int_t entries = fDataLayouts->GetEntriesFast();
320     for (Int_t i=0;i<entries;i++){
321       TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
322       if (layout){
323         if (layout->fTree) layout->fTree->Write(layout->GetName());
324       }
325     }
326     delete fDataLayouts;
327     fDataLayouts=0;
328   }
329   if (backup) backup->cd();
330 }
331
332 //-------------------------------------------------------------
333 TTreeDataElement:: TTreeDataElement(Char_t type) :
334   TNamed(),
335   fType(type),
336   fDType(0),
337   fClass(0),
338   fPointer(0)
339 {
340   //
341   //
342   //
343 }
344
345 TTreeDataElement:: TTreeDataElement(TDataType* type) :
346   TNamed(),
347   fType(0),
348   fDType(type),
349   fClass(0),
350   fPointer(0)
351 {
352   //
353   //
354   //
355 }
356
357 TTreeDataElement:: TTreeDataElement(TClass* cl) :
358   TNamed(),
359   fType(0),
360   fDType(0),
361   fClass(cl),
362   fPointer(0)
363 {
364   //
365   //
366   //
367 }
368
369 //-------------------------------------------------------------------
370 TTreeStream::TTreeStream(const char *treename, TTree* externalTree):
371   TNamed(treename,treename),
372   fElements(0),
373   fBranches(0),
374   fTree(externalTree),
375   fCurrentIndex(0),
376   fId(0),
377   fNextName(),
378   fNextNameCounter(),
379   fStatus(0)
380 {
381   //
382   // Standard ctor
383   //
384   if (!fTree) fTree = new TTree(treename, treename);
385 }
386
387 TTreeStream::~TTreeStream()
388 {
389   //
390   // Class dtor
391   //
392   fElements->Delete();
393   fBranches->Clear();
394   delete fElements;
395   delete fBranches;
396 }
397
398 void TTreeStream::Close()
399 {
400   //
401   // Flush data to disk and close
402   //
403   fTree->Write();
404 }
405
406 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
407 {
408   //
409   // Insert object of given type
410   //
411   if (!fElements) fElements = new TObjArray(10000);
412   if (fElements->GetSize()<=fCurrentIndex) fElements->Expand(fCurrentIndex*2);
413   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
414   if (!element) {
415     element = new TTreeDataElement(type);
416     //
417     char name[1000];
418     if (fNextName.Length()>0){
419       if (fNextNameCounter==0){
420         snprintf(name,1000,"%s",(const char*)fNextName);
421       }
422       if (fNextNameCounter>0){
423         snprintf(name,1000,"%s%d",(const char*)fNextName,fNextNameCounter);
424       }      
425     }
426     else{
427       snprintf(name,1000,"B%d.",fCurrentIndex);
428     }
429     element->SetName(name);
430     //
431     element->SetPointer(pointer);
432     fElements->AddAt(element,fCurrentIndex);
433     fCurrentIndex++;
434     return 0; //new element added
435   }
436   if (element->GetType()!=type){
437     fStatus++;
438     return 1; //mismatched data element
439   }
440   element->SetPointer(pointer);
441   fCurrentIndex++;
442   return 0;
443 }
444
445 Int_t TTreeStream::CheckIn(TObject *o){
446   //
447   // Insert TObject
448   //
449   if (!o) return 0;
450   if (!fElements) fElements = new TObjArray(1000);
451   TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
452   if (!element) {
453     element = new TTreeDataElement(o->IsA());
454     //
455     char name[1000];
456     if (fNextName.Length()>0){
457       if (fNextNameCounter==0){
458         snprintf(name,1000,"%s",(const char*)fNextName);
459       }
460       if (fNextNameCounter>0){
461         snprintf(name,1000,"%s%d",(const char*)fNextName,fNextNameCounter);
462       }      
463     }
464     else{
465       snprintf(name,1000,"B%d",fCurrentIndex);
466     }
467     element->SetName(name);
468
469     element->SetPointer(o);
470     fElements->AddAt(element,fCurrentIndex);
471     fCurrentIndex++;
472     return 0; //new element added
473   }
474   if (element->fClass!=o->IsA()){
475     fStatus++;
476     return 1; //mismatched data element
477   }
478   element->SetPointer(o);
479   fCurrentIndex++;
480   return 0;  
481 }
482
483 void TTreeStream::BuildTree(){
484   //
485   // Build the Tree
486   //
487   if (fTree && fTree->GetEntries()>0) return;
488   if (!fTree)  fTree = new TTree(GetName(),GetName());
489   Int_t entries = fElements->GetEntriesFast();  
490   fBranches = new TObjArray(entries);
491   
492   for (Int_t i=0;i<entries;i++){
493     //
494     TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
495     char bname1[1000];
496     if (element->GetName()[0]==0){
497       snprintf(bname1,1000,"B%d",i);
498     }
499     else{
500       snprintf(bname1,1000,"%s",element->GetName());
501     }
502     if (element->fClass){
503       if (element->fClass->GetBaseClass("TClonesArray")){
504         TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
505         fBranches->AddAt(br,i);
506       }else
507         {
508           TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
509           fBranches->AddAt(br,i);
510         }
511     }
512     if (element->GetType()>0){
513       char bname2[1000];
514       snprintf(bname2,1000,"B%d/%c",i,element->GetType());
515       TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
516       fBranches->AddAt(br,i);
517     }
518   }
519 }
520
521 void TTreeStream::Fill(){
522   //
523   // Fill the tree
524   //
525   if (fTree) { 
526     Int_t entries=fElements->GetEntriesFast();
527     if (entries>fTree->GetNbranches()) BuildTree();
528     for (Int_t i=0;i<entries;i++){    
529       TTreeDataElement* el  = (TTreeDataElement*)fElements->At(i);
530       if (!el) continue;
531       if (!el->GetType()) continue;
532       TBranch      * br  = (TBranch*)fBranches->At(i);
533       if (br &&el){
534         if (el->GetType())  br->SetAddress(el->fPointer);
535       }
536     }
537     if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
538     fStatus=0;
539   }
540 }
541
542 TTreeStream & TTreeStream::Endl()
543 {
544   //
545   // Perform pseudo endl operation
546   //
547   if (fTree->GetNbranches()==0) BuildTree();
548   Fill();
549   fStatus =0;
550   fCurrentIndex=0;
551   return *this;
552 }
553
554
555 TTreeStream  &TTreeStream::operator<<(const Char_t *name)
556 {
557   //
558   // Endl 
559   //
560   if (name[0]=='\n'){
561     return Endl();
562   }
563   //
564   //if tree was already defined ignore
565   if (fTree->GetEntries()>0) return *this;
566   //check branch name if tree was not 
567   //
568   Int_t last=0;
569   for (last=0;;last++){
570     if (name[last]==0) break;    
571   }
572   
573   if (last>0&&name[last-1]=='='){
574     fNextName = name;
575     fNextName[last-1]=0;
576     fNextNameCounter=0;
577   }
578   return *this;
579 }
580