Line data Source code
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 : // includes for test procedures
40 : #include "TVectorD.h"
41 : #include "TRandom.h"
42 :
43 176 : ClassImp(TTreeDataElement)
44 176 : ClassImp(TTreeStream)
45 176 : ClassImp(TTreeSRedirector)
46 :
47 :
48 :
49 : void TTreeStream::Test()
50 : {
51 : //
52 : //
53 0 : TFile *ftest = new TFile("teststreamer.root","recreate");
54 0 : if (!ftest) ftest = new TFile("teststreamer.root","new");
55 : //
56 : //create to streems Tree1 and Tree2
57 0 : TTreeStream stream1("Tree1");
58 0 : TTreeStream stream2("Tree2");
59 : //
60 0 : Char_t ch='s';
61 0 : Float_t f=3.;
62 0 : Float_t f2=1;
63 0 : TObject *po = new TObject;
64 0 : TObject *po2 = new TObject;
65 0 : for (Int_t i=0;i<100000;i++) {
66 0 : f=i*100;
67 0 : po->SetUniqueID(i);
68 0 : po2->SetUniqueID(i*100);
69 0 : ch=i%120;
70 : //
71 : // Stream the data
72 : // The data layout of stream is defined during first invocation of streamer.
73 : // Endl is the trigger which define the end of structure.
74 : //
75 : // The name of branch can be specified using strings with = at the the end
76 : // if string is not specified automatic convention is u (sed B0, B1, ...Bn)
77 0 : stream1<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
78 0 : f = 1./(100.1+i);
79 0 : f2 = -f;
80 : //3.) just another example - we can fill the same tree with different objects
81 : //
82 0 : stream2<<f<<po<<"\n";
83 0 : stream2<<f2<<po2<<"\n";
84 : }
85 : //
86 : //4.) Close the streeamers (Write the streamed tree's to the file) and close the corresponding file.
87 : //
88 0 : stream1.Close();
89 0 : stream2.Close();
90 0 : ftest->Close();
91 0 : delete ftest;
92 : //
93 : //5.) and now see results in file tteststreamer.root
94 0 : }
95 :
96 : void TTreeSRedirector::Test2()
97 : {
98 : //
99 : //Example test function to show functionality of TTreeSRedirector
100 : //
101 : //
102 : //1.)create the redirector associated with file (testredirector.root)
103 : //
104 : //
105 0 : TFile* file = new TFile("test.root","recreate");
106 0 : TTreeSRedirector *pmistream= new TTreeSRedirector();
107 : TTreeSRedirector &mistream = *pmistream;
108 0 : Char_t ch='s';
109 0 : Float_t f=3.;
110 0 : Float_t f2=1;
111 0 : TObject *po = new TObject;
112 0 : TObject *po2 = new TObject;
113 0 : for (Int_t i=0;i<100000;i++) {
114 0 : f=i*100;
115 0 : po->SetUniqueID(i);
116 0 : po2->SetUniqueID(i*100);
117 0 : ch=i%120;
118 : //
119 : //2.) create the tree with identifier specified by first argument
120 : // layout specified by sequence of arguments
121 : // Tree identifier has to be specified as first argument !!!
122 : // if the tree and layout was already defined the consistency if layout is checked
123 : // if the data are consisten fill given tree
124 : // the name of branch can be specified using strings with = at the the end
125 : // if string is not specified use automatic convention B0, B1, ...Bn
126 0 : mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
127 0 : f = 1./(100.1+i);
128 0 : f2 = -f;
129 :
130 : //3.) just another example - we can fill the same tree with different objects
131 : //
132 0 : mistream<<"TreeK"<<f<<po<<"\n";
133 0 : mistream<<"TreeK"<<f2<<po2<<"\n";
134 : }
135 : //
136 : //4.) write the streamed tree's to the file and close the corresponding file in destructor
137 : //
138 0 : delete pmistream;
139 0 : delete file;
140 : //
141 : //5.) and now see results in file testredirector.root
142 0 : }
143 :
144 : void TTreeSRedirector::Test()
145 : {
146 : //
147 : //Example test function to show functionality of TTreeSRedirector
148 : //
149 : //
150 : //1.)create the redirector associated with file (testredirector.root)
151 : //
152 : //
153 0 : TTreeSRedirector *pmistream= new TTreeSRedirector("testredirector.root");
154 : TTreeSRedirector &mistream = *pmistream;
155 0 : Char_t ch='s';
156 0 : Float_t f=3.;
157 0 : Float_t f2=1;
158 0 : TObject *po = new TObject;
159 0 : TObject *po2 = new TObject;
160 0 : for (Int_t i=0;i<100000;i++) {
161 0 : f=i*100;
162 0 : po->SetUniqueID(i);
163 0 : po2->SetUniqueID(i*100);
164 0 : ch=i%120;
165 : //
166 : //2.) create the tree with identifier specified by first argument
167 : // layout specified by sequence of arguments
168 : // Tree identifier has to be specified as first argument !!!
169 : // if the tree and layout was already defined the consistency if layout is checked
170 : // if the data are consisten fill given tree
171 : // the name of branch can be specified using strings with = at the the end
172 : // if string is not specified use automatic convention B0, B1, ...Bn
173 0 : mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
174 0 : f = 1./(100.1+i);
175 0 : f2 = -f;
176 :
177 : //3.) just another example - we can fill the same tree with different objects
178 : //
179 0 : mistream<<"TreeK"<<f<<po<<"\n";
180 0 : mistream<<"TreeK"<<f2<<po2<<"\n";
181 : }
182 : //
183 : //4.) write the streamed tree's to the file and close the corresponding file in destructor
184 : //
185 0 : delete pmistream;
186 : //
187 : //5.) and now see results in file testredirector.root
188 0 : }
189 :
190 : void TTreeSRedirector::UnitTest(Int_t testEntries){
191 : //
192 : //
193 : //
194 0 : UnitTestSparse(0.5,testEntries);
195 0 : UnitTestSparse(0.1,testEntries);
196 0 : UnitTestSparse(0.01,testEntries);
197 0 : }
198 :
199 : void TTreeSRedirector::UnitTestSparse(Double_t scale, Int_t testEntries){
200 : //
201 : // Unit test for the TTreeSRedirector
202 : // 1.) Test TTreeRedirector
203 : // a.) Fill tree with random vectors
204 : // b.) Fill downscaled version of vectors
205 : // c.) The same skipping first entry
206 : // 2.) Check results wtitten to terminale
207 : // a.) Disk consumption
208 : // skip data should be scale time smaller than full
209 : // zerro replaced ata should be compresed time smaller than full
210 : // b.) Test invariants
211 : // Input parameter scale => downscaling of sprse element
212 : //
213 0 : if (scale<=0) scale=1;
214 0 : if (scale>1) scale=1;
215 0 : TTreeSRedirector *pcstream = new TTreeSRedirector("testpcstreamSparse.root","recreate");
216 0 : for (Int_t ientry=0; ientry<testEntries; ientry++){
217 0 : TVectorD vecRandom(200);
218 0 : TVectorD vecZerro(200); // zerro vector
219 0 : for (Int_t j=0; j<200; j++) vecRandom[j]=j+ientry+0.1*gRandom->Rndm();
220 0 : Bool_t isSelected= (gRandom->Rndm()<scale);
221 : TVectorD *pvecFull = &vecRandom;
222 0 : TVectorD *pvecSparse = isSelected ? &vecRandom:0;
223 : TVectorD *pvecSparse0 = isSelected ? &vecRandom:0;
224 0 : TVectorD *pvecSparse1 = isSelected ? &vecRandom:&vecZerro;
225 :
226 0 : if (ientry==0) {
227 : pvecSparse0=0;
228 : pvecSparse=&vecRandom;
229 0 : }
230 0 : (*pcstream)<<"Full"<< // stored all vectors
231 0 : "ientry="<<ientry<<
232 0 : "vec.="<<pvecFull<<
233 : "\n";
234 0 : (*pcstream)<<"SparseSkip"<< // fraction of vectors stored
235 0 : "ientry="<<ientry<<
236 0 : "vec.="<<pvecSparse<<
237 : "\n";
238 0 : (*pcstream)<<"SparseSkip0"<< // fraction with -pointer
239 0 : "ientry="<<ientry<<
240 0 : "vec.="<<pvecSparse0<<
241 : "\n";
242 0 : (*pcstream)<<"SparseZerro"<< // all vectors filled, franction filled with 0
243 0 : "ientry="<<ientry<<
244 0 : "vec.="<<pvecSparse1<<
245 : "\n";
246 0 : }
247 0 : delete pcstream;
248 : //
249 : // 2.) check results
250 : //
251 :
252 0 : TFile* f = TFile::Open("testpcstreamSparse.root");
253 0 : if (!f){
254 0 : printf("FAILED: file: %p, TTreeSRedirector::IsDisabled()=%i\n",f,TTreeSRedirector::IsDisabled()?1:0);
255 0 : return;
256 : }
257 0 : TTree * treeFull = (TTree*)f->Get("Full");
258 0 : TTree * treeSparseSkip = (TTree*)f->Get("SparseSkip");
259 0 : TTree * treeSparseSkip0 = (TTree*)f->Get("SparseSkip0");
260 0 : TTree * treeSparseZerro = (TTree*)f->Get("SparseZerro");
261 : // a.) data volume
262 : //
263 0 : Double_t ratio=(1./scale)*treeSparseSkip->GetZipBytes()/Double_t(treeFull->GetZipBytes());
264 0 : Double_t ratio0=(1./scale)*treeSparseSkip0->GetZipBytes()/Double_t(treeFull->GetZipBytes());
265 0 : Double_t ratio1=(1./scale)*treeSparseZerro->GetZipBytes()/Double_t(treeFull->GetZipBytes());
266 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tRatioSkip\t%f\n",scale,ratio);
267 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tRatioSkip0\t%f\n",scale,ratio0);
268 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tRatioZerro\t%f\n",scale,ratio1);
269 : // b.) Integrity
270 0 : Int_t outlyersSparseSkip=treeSparseSkip->Draw("1","(vec.fElements-ientry-Iteration$-0.5)>0.5","goff");
271 0 : Int_t outlyersSparseSkip0=treeSparseSkip0->Draw("1","(vec.fElements-ientry-Iteration$-0.5)>0.5","goff");
272 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tOutlyersSkip\t%d\n",scale,outlyersSparseSkip!=0);
273 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tOutlyersSkip0\t%d\n",scale,outlyersSparseSkip0!=0);
274 : // c.) Number of entries
275 : //
276 0 : Int_t entries=treeFull->GetEntries();
277 0 : Int_t entries0=treeSparseSkip0->GetEntries();
278 0 : Bool_t isOKStat =(entries==entries0);
279 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tEntries\t%d\n",scale,isOKStat);
280 : //
281 : // d.)Reading test
282 0 : TVectorD *pvecRead = 0;
283 0 : treeSparseSkip0->SetBranchAddress("vec.",&pvecRead);
284 : Bool_t readOK=kTRUE;
285 0 : for (Int_t ientry=0; ientry<testEntries; ientry++){
286 0 : if (!pvecRead) continue;
287 0 : if (pvecRead->GetNrows()==0) continue;
288 0 : if (TMath::Abs((*pvecRead)[0]-ientry)>0.5) readOK=kFALSE;
289 : }
290 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tReadOK\t%d\n",scale,readOK);
291 : //
292 : // e.)Global test
293 0 : Bool_t isOK=(outlyersSparseSkip0==0)&&isOKStat&&readOK;
294 0 : printf("#UnitTest:\tTTreeSRedirector::TestSparse(%f)\tisOk\t%d\n",scale,isOK);
295 :
296 0 : }
297 :
298 : Bool_t TTreeSRedirector::fgDisabled=kFALSE;
299 2 : TTreeSRedirector::TTreeSRedirector(const char *fname,const char * option) :
300 2 : fDirectory(NULL),
301 2 : fDirectoryOwner(kTRUE),
302 2 : fDataLayouts(NULL)
303 10 : {
304 : //
305 : // Constructor
306 : //
307 2 : if (fgDisabled) {fDirectory=gDirectory;fDirectoryOwner=kFALSE;return;}
308 :
309 2 : TString name(fname);
310 4 : if (!name.IsNull()){
311 6 : fDirectory = new TFile(fname,option);
312 2 : }
313 : else
314 : {
315 0 : fDirectory = gDirectory;
316 0 : fDirectoryOwner = kFALSE;
317 : }
318 6 : }
319 :
320 : TTreeSRedirector::~TTreeSRedirector()
321 12 : {
322 : //
323 : // Destructor
324 : //
325 2 : Close(); //write the tree to the selected file
326 2 : if (fDirectoryOwner)
327 : {
328 2 : fDirectory->Close();
329 4 : delete fDirectory;
330 : }
331 6 : }
332 : void TTreeSRedirector::StoreObject(TObject* object){
333 : //
334 : //
335 : //
336 0 : if (fgDisabled) return;
337 0 : TDirectory * backup = gDirectory;
338 0 : fDirectory->cd();
339 0 : object->Write();
340 0 : if (backup) backup->cd();
341 0 : }
342 :
343 : void TTreeSRedirector::SetDirectory(TDirectory *sfile){
344 : //
345 : // Set the external file
346 : // In case other file already attached old file is closed before
347 : // Redirector will be the owner of file ?
348 0 : if (fDirectory && fDirectoryOwner) {
349 0 : fDirectory->Close();
350 0 : delete fDirectory;
351 : }
352 0 : fDirectory=sfile;
353 0 : }
354 :
355 : TTreeStream & TTreeSRedirector::operator<<(Int_t id)
356 : {
357 : //
358 : // return reference to the data layout with given identifier
359 : // if not existing - creates new
360 0 : if (!fDataLayouts) fDataLayouts = new TObjArray(fgDisabled?1:10000);
361 : TTreeStream *clayout=0;
362 0 : Int_t entries = fDataLayouts->GetEntriesFast();
363 0 : for (Int_t i=0;i<entries;i++){
364 0 : TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
365 0 : if (!layout) continue;
366 0 : if (fgDisabled?kTRUE:layout->fId==id) {
367 : clayout = layout;
368 0 : break;
369 : }
370 0 : }
371 0 : if (!clayout){
372 0 : TDirectory * backup = gDirectory;
373 0 : fDirectory->cd();
374 0 : char chname[100];
375 0 : snprintf(chname,100,"Tree%d",id);
376 0 : clayout = new TTreeStream(chname);
377 0 : clayout->fId=id;
378 0 : fDataLayouts->AddAt(clayout,entries);
379 0 : if (backup) backup->cd();
380 0 : }
381 0 : return *clayout;
382 0 : }
383 :
384 : void TTreeSRedirector::SetExternalTree(const char* name, TTree* externalTree)
385 : {
386 0 : TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
387 :
388 0 : if (!clayout){
389 0 : TDirectory * backup = gDirectory;
390 0 : fDirectory->cd();
391 0 : clayout = new TTreeStream(name,externalTree);
392 0 : clayout->fId=-1;
393 0 : clayout->SetName(name);
394 0 : Int_t entries = fDataLayouts->GetEntriesFast();
395 0 : fDataLayouts->AddAt(clayout,entries);
396 0 : if (backup) backup->cd();
397 0 : }
398 : //else
399 : // AliError(Form("identifier %s already associated",name));
400 0 : }
401 :
402 :
403 : TTreeStream & TTreeSRedirector::operator<<(const char* name)
404 : {
405 : //
406 : // return reference to the data layout with given identifier
407 : // if not existing - creates new
408 0 : if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
409 0 : TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
410 0 : Int_t entries = fDataLayouts->GetEntriesFast();
411 :
412 0 : if (!clayout){
413 0 : TDirectory * backup = gDirectory;
414 0 : fDirectory->cd();
415 0 : clayout = new TTreeStream(name);
416 0 : clayout->fId=-1;
417 0 : clayout->SetName(name);
418 0 : fDataLayouts->AddAt(clayout,entries);
419 0 : if (backup) backup->cd();
420 0 : }
421 0 : return *clayout;
422 0 : }
423 :
424 :
425 :
426 :
427 : void TTreeSRedirector::Close(){
428 : //
429 : //
430 4 : TDirectory * backup = gDirectory;
431 2 : fDirectory->cd();
432 2 : if (fDataLayouts){
433 0 : Int_t entries = fDataLayouts->GetEntriesFast();
434 0 : for (Int_t i=0;i<entries;i++){
435 0 : TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
436 0 : if (layout && !fgDisabled){
437 0 : if (layout->fTree) layout->fTree->Write(layout->GetName());
438 : }
439 : }
440 0 : delete fDataLayouts;
441 0 : fDataLayouts=0;
442 0 : }
443 4 : if (backup) backup->cd();
444 2 : }
445 :
446 : //-------------------------------------------------------------
447 : TTreeDataElement:: TTreeDataElement(Char_t type) :
448 0 : TNamed(),
449 0 : fType(type),
450 0 : fDType(0),
451 0 : fClass(0),
452 0 : fPointer(0)
453 0 : {
454 : //
455 : //
456 : //
457 0 : }
458 :
459 : TTreeDataElement:: TTreeDataElement(TDataType* type) :
460 0 : TNamed(),
461 0 : fType(0),
462 0 : fDType(type),
463 0 : fClass(0),
464 0 : fPointer(0)
465 0 : {
466 : //
467 : //
468 : //
469 0 : }
470 :
471 : TTreeDataElement:: TTreeDataElement(TClass* cl) :
472 0 : TNamed(),
473 0 : fType(0),
474 0 : fDType(0),
475 0 : fClass(cl),
476 0 : fPointer(0)
477 0 : {
478 : //
479 : //
480 : //
481 0 : }
482 :
483 : //-------------------------------------------------------------------
484 : TTreeStream::TTreeStream(const char *treename, TTree* externalTree):
485 0 : TNamed(treename,treename),
486 0 : fElements(0),
487 0 : fBranches(0),
488 0 : fTree(externalTree),
489 0 : fCurrentIndex(0),
490 0 : fId(0),
491 0 : fNextName(),
492 0 : fNextNameCounter(),
493 0 : fStatus(0)
494 0 : {
495 : //
496 : // Standard ctor
497 : //
498 0 : if (!fTree) fTree = new TTree(treename, treename);
499 0 : }
500 :
501 : TTreeStream::~TTreeStream()
502 0 : {
503 : //
504 : // Class dtor
505 : //
506 0 : fElements->Delete();
507 0 : fBranches->Clear();
508 0 : delete fElements;
509 0 : delete fBranches;
510 0 : }
511 :
512 : void TTreeStream::Close()
513 : {
514 : //
515 : // Flush data to disk and close
516 : //
517 0 : if (TTreeSRedirector::IsDisabled()) return;
518 0 : fTree->Write();
519 0 : }
520 :
521 : Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
522 : {
523 : //
524 : // Insert object of given type
525 : //
526 0 : if (TTreeSRedirector::IsDisabled()) return 0;
527 0 : if (!fElements) fElements = new TObjArray(10000);
528 0 : if (fElements->GetSize()<=fCurrentIndex) fElements->Expand(fCurrentIndex*2);
529 0 : TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
530 0 : if (!element) {
531 0 : element = new TTreeDataElement(type);
532 : //
533 0 : char name[1000];
534 0 : if (fNextName.Length()>0){
535 0 : if (fNextNameCounter==0){
536 0 : snprintf(name,1000,"%s",(const char*)fNextName);
537 0 : }
538 0 : if (fNextNameCounter>0){
539 0 : snprintf(name,1000,"%s%d",(const char*)fNextName,fNextNameCounter);
540 0 : }
541 : }
542 : else{
543 0 : snprintf(name,1000,"B%d.",fCurrentIndex);
544 : }
545 0 : element->SetName(name);
546 : //
547 0 : element->SetPointer(pointer);
548 0 : fElements->AddAt(element,fCurrentIndex);
549 0 : fCurrentIndex++;
550 : return 0; //new element added
551 0 : }
552 0 : if (element->GetType()!=type){
553 0 : fStatus++;
554 0 : return 1; //mismatched data element
555 : }
556 0 : element->SetPointer(pointer);
557 0 : fCurrentIndex++;
558 0 : return 0;
559 0 : }
560 :
561 : Int_t TTreeStream::CheckIn(TObject *pObject){
562 : //
563 : // Insert TObject
564 : //
565 0 : if (TTreeSRedirector::IsDisabled()) return 0;
566 : TClass *pClass = 0;
567 0 : if (pObject) pClass=pObject->IsA();
568 0 : if (!fElements) fElements = new TObjArray(1000);
569 0 : TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
570 0 : if (!element) {
571 0 : element = new TTreeDataElement(pClass);
572 : //
573 0 : char name[1000];
574 0 : if (fNextName.Length()>0){
575 0 : if (fNextNameCounter==0){
576 0 : snprintf(name,1000,"%s",(const char*)fNextName);
577 0 : }
578 0 : if (fNextNameCounter>0){
579 0 : snprintf(name,1000,"%s%d",(const char*)fNextName,fNextNameCounter);
580 0 : }
581 : }
582 : else{
583 0 : snprintf(name,1000,"B%d",fCurrentIndex);
584 : }
585 0 : element->SetName(name);
586 :
587 0 : element->SetPointer(pObject);
588 0 : fElements->AddAt(element,fCurrentIndex);
589 0 : fCurrentIndex++;
590 : return 0; //new element added
591 0 : }
592 0 : if (element->fClass==0) {
593 0 : element->fClass=pClass;
594 0 : }else{
595 0 : if (element->fClass!=pClass && pClass!=0){
596 0 : fStatus++;
597 0 : return 1; //mismatched data element
598 : }
599 : }
600 0 : element->SetPointer(pObject);
601 0 : fCurrentIndex++;
602 0 : return 0;
603 0 : }
604 :
605 : void TTreeStream::BuildTree(){
606 : //
607 : // Build the Tree
608 : //
609 : //if (fTree && fTree->GetEntries()>0) return;
610 0 : if (TTreeSRedirector::IsDisabled()) return;
611 : Int_t entriesFilled=0;
612 0 : if (!fTree) {
613 0 : fTree = new TTree(GetName(),GetName());
614 0 : }else{
615 0 : entriesFilled=fTree->GetEntries();
616 : }
617 0 : Int_t entries = fElements->GetEntriesFast();
618 0 : if (!fBranches) fBranches = new TObjArray(entries);
619 :
620 0 : for (Int_t i=0;i<entries;i++){
621 : //
622 0 : TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
623 0 : if (fBranches->At(i)) continue;
624 0 : char bname1[1000];
625 0 : if (element->GetName()[0]==0){
626 0 : snprintf(bname1,1000,"B%d",i);
627 0 : }
628 : else{
629 0 : snprintf(bname1,1000,"%s",element->GetName());
630 : }
631 0 : if (element->fClass){
632 0 : if (element->fClass->GetBaseClass("TClonesArray")){
633 0 : TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
634 0 : if (entriesFilled!=0) {
635 0 : br->SetAddress(0);
636 0 : for (Int_t ientry=0; ientry<entriesFilled;ientry++) br->Fill();
637 0 : br->SetAddress(&(element->fPointer));
638 0 : }
639 0 : fBranches->AddAt(br,i);
640 0 : }else
641 : {
642 0 : TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
643 0 : if (entriesFilled!=0) {
644 0 : br->SetAddress(0);
645 0 : for (Int_t ientry=0; ientry<entriesFilled;ientry++) br->Fill();
646 0 : br->SetAddress(&(element->fPointer));
647 0 : }
648 0 : fBranches->AddAt(br,i);
649 : }
650 : }
651 0 : if (element->GetType()>0){
652 0 : char bname2[1000];
653 0 : snprintf(bname2,1000,"B%d/%c",i,element->GetType());
654 0 : TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
655 0 : if (entriesFilled!=0) {
656 0 : br->SetAddress(0);
657 0 : for (Int_t ientry=0; ientry<entriesFilled;ientry++) br->Fill();
658 0 : br->SetAddress(element->fPointer);
659 0 : }
660 :
661 0 : fBranches->AddAt(br,i);
662 0 : }
663 0 : }
664 0 : }
665 :
666 : void TTreeStream::Fill(){
667 : //
668 : // Fill the tree
669 : //
670 0 : if (TTreeSRedirector::IsDisabled()) return;
671 0 : if (fTree) {
672 0 : Int_t entries=fElements->GetEntriesFast();
673 0 : if (entries>fTree->GetNbranches()) BuildTree();
674 0 : for (Int_t i=0;i<entries;i++){
675 0 : TTreeDataElement* el = (TTreeDataElement*)fElements->At(i);
676 0 : if (!el) continue;
677 0 : if (!el->GetType()) continue;
678 0 : TBranch * br = (TBranch*)fBranches->At(i);
679 0 : if (br &&el){
680 0 : if (el->GetType()) br->SetAddress(el->fPointer);
681 : }
682 0 : }
683 0 : if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
684 0 : fStatus=0;
685 0 : }
686 0 : }
687 :
688 : TTreeStream & TTreeStream::Endl()
689 : {
690 : //
691 : // Perform pseudo endl operation
692 : //
693 0 : if (TTreeSRedirector::IsDisabled()) return *this;
694 0 : if (fTree->GetNbranches()==0) BuildTree();
695 0 : Fill();
696 0 : fStatus =0;
697 0 : fCurrentIndex=0;
698 0 : return *this;
699 0 : }
700 :
701 :
702 : TTreeStream &TTreeStream::operator<<(const Char_t *name)
703 : {
704 : //
705 : // Endl
706 : //
707 0 : if (name[0]=='\n'){
708 0 : return Endl();
709 : }
710 : //
711 : //if tree was already defined ignore
712 0 : if (fTree->GetEntries()>0) return *this;
713 : //check branch name if tree was not
714 : //
715 : Int_t last=0;
716 0 : for (last=0;;last++){
717 0 : if (name[last]==0) break;
718 : }
719 :
720 0 : if (last>0&&name[last-1]=='='){
721 0 : fNextName = name;
722 0 : fNextName[last-1]=0;
723 0 : fNextNameCounter=0;
724 0 : }
725 : return *this;
726 0 : }
727 :
|