1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
19 // marian.ivanov@cern.ch
21 // ------------------------------------------------------------------------------------------------
23 // Standard stream (cout) like input for the tree
24 // Run and see TTreeStreamer::Test() - to see TTreeStreamer functionality
25 // ------------------------------------------------------------------------------------------------
27 // -------------------------------------------------------------------------------------------------
29 // Redirect file to different TTreeStreams
30 // Run and see TTreeSRedirector::Test() as an example of TTreeSRedirectorer functionality
35 #include <TObjArray.h>
37 #include <TTreeStream.h>
39 ClassImp(TTreeDataElement)
41 ClassImp(TTreeSRedirector)
45 void TTreeStream::Test()
49 TFile *ftest = new TFile("teststreamer.root","recreate");
50 if (!ftest) ftest = new TFile("teststreamer.root","new");
52 //create to streems Tree1 and Tree2
53 TTreeStream stream1("Tree1");
54 TTreeStream stream2("Tree2");
59 TObject *po = new TObject;
60 TObject *po2 = new TObject;
61 for (Int_t i=0;i<100000;i++) {
64 po2->SetUniqueID(i*100);
68 // The data layout of stream is defined during first invocation of streamer.
69 // Endl is the trigger which define the end of structure.
71 // The name of branch can be specified using strings with = at the the end
72 // if string is not specified automatic convention is u (sed B0, B1, ...Bn)
73 stream1<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
76 //3.) just another example - we can fill the same tree with different objects
79 stream2<<f2<<po2<<"\n";
82 //4.) Close the streeamers (Write the streamed tree's to the file) and close the corresponding file.
89 //5.) and now see results in file tteststreamer.root
94 void TTreeSRedirector::Test()
97 //Example test function to show functionality of TTreeSRedirector
100 //1.)create the redirector associated with file (testredirector.root)
103 TTreeSRedirector *pmistream= new TTreeSRedirector("testredirector.root");
104 TTreeSRedirector &mistream = *pmistream;
108 TObject *po = new TObject;
109 TObject *po2 = new TObject;
110 for (Int_t i=0;i<100000;i++) {
113 po2->SetUniqueID(i*100);
116 //2.) create the tree with identifier specified by first argument
117 // layout specified by sequence of arguments
118 // Tree identifier has to be specified as first argument !!!
119 // if the tree and layout was already defined the consistency if layout is checked
120 // if the data are consisten fill given tree
121 // the name of branch can be specified using strings with = at the the end
122 // if string is not specified use automatic convention B0, B1, ...Bn
123 mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
127 //3.) just another example - we can fill the same tree with different objects
129 mistream<<"TreeK"<<f<<po<<"\n";
130 mistream<<"TreeK"<<f2<<po2<<"\n";
133 //4.) write the streamed tree's to the file and close the corresponding file in destructor
137 //5.) and now see results in file testredirector.root
141 TTreeSRedirector::TTreeSRedirector(const char *fname) :
142 fFile(new TFile(fname,"recreate")),
149 fFile = new TFile(fname,"new");
153 TTreeSRedirector::~TTreeSRedirector()
158 Close(); //write the tree to the selected file
162 void TTreeSRedirector::StoreObject(TObject* object){
166 TFile * backup = gFile;
169 if (backup) backup->cd();
174 TTreeStream & TTreeSRedirector::operator<<(Int_t id)
177 // return reference to the data layout with given identifier
178 // if not existing - creates new
179 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
180 TTreeStream *clayout=0;
181 Int_t entries = fDataLayouts->GetEntriesFast();
182 for (Int_t i=0;i<entries;i++){
183 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
184 if (!layout) continue;
185 if (layout->fId==id) {
193 sprintf(chname,"Tree%d",id);
194 clayout = new TTreeStream(chname);
196 fDataLayouts->AddAt(clayout,entries);
202 TTreeStream & TTreeSRedirector::operator<<(const char* name)
205 // return reference to the data layout with given identifier
206 // if not existing - creates new
207 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
208 TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
209 Int_t entries = fDataLayouts->GetEntriesFast();
213 clayout = new TTreeStream(name);
215 clayout->SetName(name);
216 fDataLayouts->AddAt(clayout,entries);
224 void TTreeSRedirector::Close(){
227 TFile * backup = gFile;
230 Int_t entries = fDataLayouts->GetEntriesFast();
231 for (Int_t i=0;i<entries;i++){
232 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
234 if (layout->fTree) layout->fTree->Write(layout->GetName());
240 if (backup) backup->cd();
245 //-------------------------------------------------------------
246 TTreeDataElement:: TTreeDataElement(Char_t type) :
258 TTreeDataElement:: TTreeDataElement(TDataType* type) :
270 TTreeDataElement:: TTreeDataElement(TClass* cl) :
282 //-------------------------------------------------------------------
283 TTreeStream::TTreeStream(const char *treename):
284 TNamed(treename,treename),
287 fTree(new TTree(treename, treename)),
299 TTreeStream::~TTreeStream()
310 void TTreeStream::Close()
313 // Flush data to disk and close
318 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
321 // Insert object of given type
323 if (!fElements) fElements = new TObjArray(1000);
324 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
326 element = new TTreeDataElement(type);
329 if (fNextName.Length()>0){
330 if (fNextNameCounter==0){
331 sprintf(name,"%s",(const char*)fNextName);
333 if (fNextNameCounter>0){
334 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
338 sprintf(name,"B%d.",fCurrentIndex);
340 element->SetName(name);
342 element->SetPointer(pointer);
343 fElements->AddAt(element,fCurrentIndex);
345 return 0; //new element added
347 if (element->GetType()!=type){
349 return 1; //mismatched data element
351 element->SetPointer(pointer);
356 Int_t TTreeStream::CheckIn(TObject *o){
361 if (!fElements) fElements = new TObjArray(1000);
362 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
364 element = new TTreeDataElement(o->IsA());
367 if (fNextName.Length()>0){
368 if (fNextNameCounter==0){
369 sprintf(name,"%s",(const char*)fNextName);
371 if (fNextNameCounter>0){
372 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
376 sprintf(name,"B%d",fCurrentIndex);
378 element->SetName(name);
380 element->SetPointer(o);
381 fElements->AddAt(element,fCurrentIndex);
383 return 0; //new element added
385 if (element->fClass!=o->IsA()){
387 return 1; //mismatched data element
389 element->SetPointer(o);
394 void TTreeStream::BuildTree(){
398 if (fTree->GetEntries()>0) return;
399 fTree = new TTree(GetName(),GetName());
400 Int_t entries = fElements->GetEntriesFast();
401 fBranches = new TObjArray(entries);
403 for (Int_t i=0;i<entries;i++){
405 TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
407 if (element->GetName()[0]==0){
408 sprintf(bname1,"B%d",i);
411 sprintf(bname1,element->GetName());
413 if (element->fClass){
414 if (element->fClass->GetBaseClass("TClonesArray")){
415 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
416 fBranches->AddAt(br,i);
419 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
420 fBranches->AddAt(br,i);
423 if (element->GetType()>0){
425 sprintf(bname2,"B%d/%c",i,element->GetType());
426 TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
427 fBranches->AddAt(br,i);
432 void TTreeStream::Fill(){
437 Int_t entries=fElements->GetEntriesFast();
438 if (entries>fTree->GetNbranches()) BuildTree();
439 for (Int_t i=0;i<entries;i++){
440 TTreeDataElement* el = (TTreeDataElement*)fElements->At(i);
442 if (!el->GetType()) continue;
443 TBranch * br = (TBranch*)fBranches->At(i);
445 if (el->GetType()) br->SetAddress(el->fPointer);
448 if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
453 TTreeStream & TTreeStream::Endl()
456 // Perform pseudo endl operation
458 if (fTree->GetNbranches()==0) BuildTree();
466 TTreeStream &TTreeStream::operator<<(Char_t *name)
475 //if tree was already defined ignore
476 if (fTree->GetEntries()>0) return *this;
477 //check branch name if tree was not
480 for (last=0;;last++){
481 if (name[last]==0) break;
484 if (last>0&&name[last-1]=='='){