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