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