]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/STEERBase/TTreeStream.cxx
Changes for #95136: CPass0/CPass1 porting request for STEER and ANALISYS directory
[u/mrichter/AliRoot.git] / STEER / STEERBase / TTreeStream.cxx
CommitLineData
9edefa04 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
9996a03b 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
9edefa04 33#include <TClass.h>
34#include <TFile.h>
e619a839 35#include <TDirectory.h>
9edefa04 36#include <TObjArray.h>
37#include <TTree.h>
7330f0e5 38#include "TTreeStream.h"
cd246117 39
40ClassImp(TTreeDataElement)
41ClassImp(TTreeStream)
42ClassImp(TTreeSRedirector)
43
cd246117 44
45
46void 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
95void 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
d01710c6 142TTreeSRedirector::TTreeSRedirector(const char *fname,const char * option) :
143 fFile(new TFile(fname,option)),
90e48c0c 144 fDataLayouts(0)
145{
cd246117 146 //
90e48c0c 147 // Constructor
cd246117 148 //
cd246117 149 if (!fFile){
d01710c6 150 fFile = new TFile(fname,option);
cd246117 151 }
cd246117 152}
153
d01710c6 154
155
90e48c0c 156TTreeSRedirector::~TTreeSRedirector()
157{
cd246117 158 //
90e48c0c 159 // Destructor
cd246117 160 //
161 Close(); //write the tree to the selected file
162 fFile->Close();
163 delete fFile;
164}
df1e0cdc 165void TTreeSRedirector::StoreObject(TObject* object){
166 //
167 //
168 //
e619a839 169 TDirectory * backup = gDirectory;
df1e0cdc 170 fFile->cd();
171 object->Write();
172 if (backup) backup->cd();
173}
174
175
d01710c6 176void TTreeSRedirector::SetFile(TFile *sfile){
177 //
178 // Set the external file
179 // In case other file already attached old file is closed before
180 // Redirector will be the owner of file ?
181 if (fFile) {
182 fFile->Close();
183 delete fFile;
184 }
185 fFile=sfile;
186}
187
cd246117 188
189TTreeStream & TTreeSRedirector::operator<<(Int_t id)
190{
191 //
192 // return reference to the data layout with given identifier
193 // if not existing - creates new
194 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
195 TTreeStream *clayout=0;
196 Int_t entries = fDataLayouts->GetEntriesFast();
197 for (Int_t i=0;i<entries;i++){
198 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
199 if (!layout) continue;
200 if (layout->fId==id) {
201 clayout = layout;
202 break;
203 }
204 }
205 if (!clayout){
2c69896b 206 TDirectory * backup = gDirectory;
2fca8fe0 207 fFile->cd();
cd246117 208 char chname[100];
cd507f9c 209 snprintf(chname,100,"Tree%d",id);
cd246117 210 clayout = new TTreeStream(chname);
211 clayout->fId=id;
212 fDataLayouts->AddAt(clayout,entries);
2c69896b 213 if (backup) backup->cd();
cd246117 214 }
215 return *clayout;
216}
217
218
219TTreeStream & TTreeSRedirector::operator<<(const char* name)
220{
221 //
222 // return reference to the data layout with given identifier
223 // if not existing - creates new
224 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
2fca8fe0 225 TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
cd246117 226 Int_t entries = fDataLayouts->GetEntriesFast();
2fca8fe0 227
cd246117 228 if (!clayout){
2c69896b 229 TDirectory * backup = gDirectory;
2fca8fe0 230 fFile->cd();
cd246117 231 clayout = new TTreeStream(name);
232 clayout->fId=-1;
233 clayout->SetName(name);
cd246117 234 fDataLayouts->AddAt(clayout,entries);
2c69896b 235 if (backup) backup->cd();
cd246117 236 }
237 return *clayout;
238}
239
240
241
242
243void TTreeSRedirector::Close(){
244 //
245 //
e619a839 246 TDirectory * backup = gDirectory;
2fca8fe0 247 fFile->cd();
248 if (fDataLayouts){
249 Int_t entries = fDataLayouts->GetEntriesFast();
250 for (Int_t i=0;i<entries;i++){
251 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
252 if (layout){
253 if (layout->fTree) layout->fTree->Write(layout->GetName());
254 }
255 }
256 delete fDataLayouts;
257 fDataLayouts=0;
cd246117 258 }
d0742e95 259 if (backup) backup->cd();
cd246117 260}
261
262
263
264//-------------------------------------------------------------
90e48c0c 265TTreeDataElement:: TTreeDataElement(Char_t type) :
fdf65bb5 266 TNamed(),
90e48c0c 267 fType(type),
268 fDType(0),
269 fClass(0),
270 fPointer(0)
271{
272 //
cd246117 273 //
274 //
cd246117 275}
90e48c0c 276
277TTreeDataElement:: TTreeDataElement(TDataType* type) :
fdf65bb5 278 TNamed(),
81e97e0d 279 fType(0),
90e48c0c 280 fDType(type),
281 fClass(0),
282 fPointer(0)
283{
284 //
cd246117 285 //
286 //
cd246117 287}
90e48c0c 288
289TTreeDataElement:: TTreeDataElement(TClass* cl) :
fdf65bb5 290 TNamed(),
81e97e0d 291 fType(0),
90e48c0c 292 fDType(0),
293 fClass(cl),
294 fPointer(0)
295{
296 //
cd246117 297 //
298 //
cd246117 299}
300
301//-------------------------------------------------------------------
90e48c0c 302TTreeStream::TTreeStream(const char *treename):
303 TNamed(treename,treename),
304 fElements(0),
305 fBranches(0),
306 fTree(new TTree(treename, treename)),
307 fCurrentIndex(0),
fe12e09c 308 fId(0),
90e48c0c 309 fNextName(),
310 fNextNameCounter(),
311 fStatus(0)
312{
9996a03b 313 //
314 // Standard ctor
315 //
cd246117 316}
317
318TTreeStream::~TTreeStream()
319{
9996a03b 320 //
321 // Class dtor
322 //
cd246117 323 fElements->Delete();
324 fBranches->Clear();
325 delete fElements;
326 delete fBranches;
327}
328
329void TTreeStream::Close()
330{
9996a03b 331 //
332 // Flush data to disk and close
cd246117 333 //
334 fTree->Write();
335}
336
337Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
338{
9996a03b 339 //
340 // Insert object of given type
341 //
78e18d24 342 if (!fElements) fElements = new TObjArray(10000);
343 if (fElements->GetSize()<=fCurrentIndex) fElements->Expand(fCurrentIndex*2);
cd246117 344 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
345 if (!element) {
346 element = new TTreeDataElement(type);
347 //
348 char name[1000];
349 if (fNextName.Length()>0){
350 if (fNextNameCounter==0){
cd507f9c 351 snprintf(name,1000,"%s",(const char*)fNextName);
cd246117 352 }
353 if (fNextNameCounter>0){
cd507f9c 354 snprintf(name,1000,"%s%d",(const char*)fNextName,fNextNameCounter);
cd246117 355 }
356 }
357 else{
cd507f9c 358 snprintf(name,1000,"B%d.",fCurrentIndex);
cd246117 359 }
360 element->SetName(name);
361 //
362 element->SetPointer(pointer);
363 fElements->AddAt(element,fCurrentIndex);
364 fCurrentIndex++;
365 return 0; //new element added
366 }
367 if (element->GetType()!=type){
368 fStatus++;
369 return 1; //mismatched data element
370 }
371 element->SetPointer(pointer);
372 fCurrentIndex++;
373 return 0;
374}
375
376Int_t TTreeStream::CheckIn(TObject *o){
377 //
9996a03b 378 // Insert TObject
cd246117 379 //
380 if (!o) return 0;
381 if (!fElements) fElements = new TObjArray(1000);
382 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
383 if (!element) {
384 element = new TTreeDataElement(o->IsA());
385 //
386 char name[1000];
387 if (fNextName.Length()>0){
388 if (fNextNameCounter==0){
cd507f9c 389 snprintf(name,1000,"%s",(const char*)fNextName);
cd246117 390 }
391 if (fNextNameCounter>0){
cd507f9c 392 snprintf(name,1000,"%s%d",(const char*)fNextName,fNextNameCounter);
cd246117 393 }
394 }
395 else{
cd507f9c 396 snprintf(name,1000,"B%d",fCurrentIndex);
cd246117 397 }
398 element->SetName(name);
399
400 element->SetPointer(o);
401 fElements->AddAt(element,fCurrentIndex);
402 fCurrentIndex++;
403 return 0; //new element added
404 }
405 if (element->fClass!=o->IsA()){
406 fStatus++;
407 return 1; //mismatched data element
408 }
409 element->SetPointer(o);
410 fCurrentIndex++;
411 return 0;
412}
413
414void TTreeStream::BuildTree(){
415 //
9996a03b 416 // Build the Tree
cd246117 417 //
bbc15444 418 if (fTree && fTree->GetEntries()>0) return;
419 if (!fTree) fTree = new TTree(GetName(),GetName());
cd246117 420 Int_t entries = fElements->GetEntriesFast();
421 fBranches = new TObjArray(entries);
422
423 for (Int_t i=0;i<entries;i++){
424 //
425 TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
426 char bname1[1000];
427 if (element->GetName()[0]==0){
cd507f9c 428 snprintf(bname1,1000,"B%d",i);
cd246117 429 }
430 else{
389410ea 431 snprintf(bname1,1000,"%s",element->GetName());
cd246117 432 }
433 if (element->fClass){
2fca8fe0 434 if (element->fClass->GetBaseClass("TClonesArray")){
3194e208 435 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
2fca8fe0 436 fBranches->AddAt(br,i);
437 }else
438 {
439 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
440 fBranches->AddAt(br,i);
441 }
cd246117 442 }
443 if (element->GetType()>0){
444 char bname2[1000];
cd507f9c 445 snprintf(bname2,1000,"B%d/%c",i,element->GetType());
cd246117 446 TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
447 fBranches->AddAt(br,i);
448 }
449 }
450}
451
452void TTreeStream::Fill(){
453 //
9996a03b 454 // Fill the tree
cd246117 455 //
456 if (fTree) {
457 Int_t entries=fElements->GetEntriesFast();
458 if (entries>fTree->GetNbranches()) BuildTree();
459 for (Int_t i=0;i<entries;i++){
460 TTreeDataElement* el = (TTreeDataElement*)fElements->At(i);
461 if (!el) continue;
462 if (!el->GetType()) continue;
463 TBranch * br = (TBranch*)fBranches->At(i);
464 if (br &&el){
465 if (el->GetType()) br->SetAddress(el->fPointer);
466 }
467 }
468 if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
469 fStatus=0;
470 }
471}
472
9996a03b 473TTreeStream & TTreeStream::Endl()
474{
475 //
476 // Perform pseudo endl operation
477 //
cd246117 478 if (fTree->GetNbranches()==0) BuildTree();
479 Fill();
480 fStatus =0;
481 fCurrentIndex=0;
482 return *this;
483}
484
485
4f57cad7 486TTreeStream &TTreeStream::operator<<(const Char_t *name)
cd246117 487{
488 //
9996a03b 489 // Endl
cd246117 490 //
cd246117 491 if (name[0]=='\n'){
492 return Endl();
493 }
494 //
495 //if tree was already defined ignore
496 if (fTree->GetEntries()>0) return *this;
497 //check branch name if tree was not
498 //
499 Int_t last=0;
500 for (last=0;;last++){
501 if (name[last]==0) break;
502 }
503
504 if (last>0&&name[last-1]=='='){
505 fNextName = name;
506 fNextName[last-1]=0;
507 fNextNameCounter=0;
508 }
509 return *this;
510}
511