]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - STEER/TTreeStream.cxx
Adding Generate method to build a store with identical values (Laurent)
[u/mrichter/AliRoot.git] / STEER / TTreeStream.cxx
... / ...
CommitLineData
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
40ClassImp(TTreeDataElement)
41ClassImp(TTreeStream)
42ClassImp(TTreeSRedirector)
43
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
142TTreeSRedirector::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
154TTreeSRedirector::~TTreeSRedirector()
155{
156 //
157 // Destructor
158 //
159 Close(); //write the tree to the selected file
160 fFile->Close();
161 delete fFile;
162}
163void 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
175TTreeStream & 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
203TTreeStream & 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
225void 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//-------------------------------------------------------------
247TTreeDataElement:: TTreeDataElement(Char_t type) :
248 TNamed(),
249 fType(type),
250 fDType(0),
251 fClass(0),
252 fPointer(0)
253{
254 //
255 //
256 //
257}
258
259TTreeDataElement:: TTreeDataElement(TDataType* type) :
260 TNamed(),
261 fType(0),
262 fDType(type),
263 fClass(0),
264 fPointer(0)
265{
266 //
267 //
268 //
269}
270
271TTreeDataElement:: TTreeDataElement(TClass* cl) :
272 TNamed(),
273 fType(0),
274 fDType(0),
275 fClass(cl),
276 fPointer(0)
277{
278 //
279 //
280 //
281}
282
283//-------------------------------------------------------------------
284TTreeStream::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
300TTreeStream::~TTreeStream()
301{
302 //
303 // Class dtor
304 //
305 fElements->Delete();
306 fBranches->Clear();
307 delete fElements;
308 delete fBranches;
309}
310
311void TTreeStream::Close()
312{
313 //
314 // Flush data to disk and close
315 //
316 fTree->Write();
317}
318
319Int_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
357Int_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
395void 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
433void 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
454TTreeStream & 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
467TTreeStream &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