2 // marian.ivanov@cern.ch
4 // ------------------------------------------------------------------------------------------------
6 // Standard stream (cout) like input for the tree
7 // Run and see TTreeStreamer::Test() - to see TTreeStreamer functionality
8 // ------------------------------------------------------------------------------------------------
10 // -------------------------------------------------------------------------------------------------
12 // Redirect file to different TTreeStreams
13 // Run and see TTreeSRedirector::Test() as an example of TTreeSRedirectorer functionality
20 #include "TObjArray.h"
22 #include "TTreeStream.h"
25 ClassImp(TTreeDataElement)
27 ClassImp(TTreeSRedirector)
31 void TTreeStream::Test()
35 TFile *ftest = new TFile("teststreamer.root","recreate");
36 if (!ftest) ftest = new TFile("teststreamer.root","new");
38 //create to streems Tree1 and Tree2
39 TTreeStream stream1("Tree1");
40 TTreeStream stream2("Tree2");
45 TObject *po = new TObject;
46 TObject *po2 = new TObject;
47 for (Int_t i=0;i<100000;i++) {
50 po2->SetUniqueID(i*100);
54 // The data layout of stream is defined during first invocation of streamer.
55 // Endl is the trigger which define the end of structure.
57 // The name of branch can be specified using strings with = at the the end
58 // if string is not specified automatic convention is u (sed B0, B1, ...Bn)
59 stream1<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
62 //3.) just another example - we can fill the same tree with different objects
65 stream2<<f2<<po2<<"\n";
68 //4.) Close the streeamers (Write the streamed tree's to the file) and close the corresponding file.
75 //5.) and now see results in file tteststreamer.root
80 void TTreeSRedirector::Test()
83 //Example test function to show functionality of TTreeSRedirector
86 //1.)create the redirector associated with file (testredirector.root)
89 TTreeSRedirector *pmistream= new TTreeSRedirector("testredirector.root");
90 TTreeSRedirector &mistream = *pmistream;
94 TObject *po = new TObject;
95 TObject *po2 = new TObject;
96 for (Int_t i=0;i<100000;i++) {
99 po2->SetUniqueID(i*100);
102 //2.) create the tree with identifier specified by first argument
103 // layout specified by sequence of arguments
104 // Tree identifier has to be specified as first argument !!!
105 // if the tree and layout was already defined the consistency if layout is checked
106 // if the data are consisten fill given tree
107 // the name of branch can be specified using strings with = at the the end
108 // if string is not specified use automatic convention B0, B1, ...Bn
109 mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
113 //3.) just another example - we can fill the same tree with different objects
115 mistream<<"TreeK"<<f<<po<<"\n";
116 mistream<<"TreeK"<<f2<<po2<<"\n";
119 //4.) write the streamed tree's to the file and close the corresponding file in destructor
123 //5.) and now see results in file testredirector.root
127 TTreeSRedirector::TTreeSRedirector(const char *fname) :
128 fFile(new TFile(fname,"recreate")),
135 fFile = new TFile(fname,"new");
139 TTreeSRedirector::~TTreeSRedirector()
144 Close(); //write the tree to the selected file
149 TTreeStream & TTreeSRedirector::operator<<(Int_t id)
152 // return reference to the data layout with given identifier
153 // if not existing - creates new
154 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
155 TTreeStream *clayout=0;
156 Int_t entries = fDataLayouts->GetEntriesFast();
157 for (Int_t i=0;i<entries;i++){
158 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
159 if (!layout) continue;
160 if (layout->fId==id) {
168 sprintf(chname,"Tree%d",id);
169 clayout = new TTreeStream(chname);
171 fDataLayouts->AddAt(clayout,entries);
177 TTreeStream & TTreeSRedirector::operator<<(const char* name)
180 // return reference to the data layout with given identifier
181 // if not existing - creates new
182 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
183 TTreeStream *clayout=(TTreeStream*)fDataLayouts->FindObject(name);
184 Int_t entries = fDataLayouts->GetEntriesFast();
188 clayout = new TTreeStream(name);
190 clayout->SetName(name);
191 fDataLayouts->AddAt(clayout,entries);
199 void TTreeSRedirector::Close(){
202 TFile * backup = gFile;
205 Int_t entries = fDataLayouts->GetEntriesFast();
206 for (Int_t i=0;i<entries;i++){
207 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
209 if (layout->fTree) layout->fTree->Write(layout->GetName());
220 //-------------------------------------------------------------
221 TTreeDataElement:: TTreeDataElement(Char_t type) :
233 TTreeDataElement:: TTreeDataElement(TDataType* type) :
245 TTreeDataElement:: TTreeDataElement(TClass* cl) :
257 //-------------------------------------------------------------------
258 TTreeStream::TTreeStream(const char *treename):
259 TNamed(treename,treename),
262 fTree(new TTree(treename, treename)),
273 TTreeStream::~TTreeStream()
284 void TTreeStream::Close()
287 // Flush data to disk and close
292 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
295 // Insert object of given type
297 if (!fElements) fElements = new TObjArray(1000);
298 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
300 element = new TTreeDataElement(type);
303 if (fNextName.Length()>0){
304 if (fNextNameCounter==0){
305 sprintf(name,"%s",(const char*)fNextName);
307 if (fNextNameCounter>0){
308 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
312 sprintf(name,"B%d.",fCurrentIndex);
314 element->SetName(name);
316 element->SetPointer(pointer);
317 fElements->AddAt(element,fCurrentIndex);
319 return 0; //new element added
321 if (element->GetType()!=type){
323 return 1; //mismatched data element
325 element->SetPointer(pointer);
330 Int_t TTreeStream::CheckIn(TObject *o){
335 if (!fElements) fElements = new TObjArray(1000);
336 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
338 element = new TTreeDataElement(o->IsA());
341 if (fNextName.Length()>0){
342 if (fNextNameCounter==0){
343 sprintf(name,"%s",(const char*)fNextName);
345 if (fNextNameCounter>0){
346 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
350 sprintf(name,"B%d",fCurrentIndex);
352 element->SetName(name);
354 element->SetPointer(o);
355 fElements->AddAt(element,fCurrentIndex);
357 return 0; //new element added
359 if (element->fClass!=o->IsA()){
361 return 1; //mismatched data element
363 element->SetPointer(o);
368 void TTreeStream::BuildTree(){
372 if (fTree->GetEntries()>0) return;
373 fTree = new TTree(GetName(),GetName());
374 Int_t entries = fElements->GetEntriesFast();
375 fBranches = new TObjArray(entries);
377 for (Int_t i=0;i<entries;i++){
379 TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
381 if (element->GetName()[0]==0){
382 sprintf(bname1,"B%d",i);
385 sprintf(bname1,element->GetName());
387 if (element->fClass){
388 if (element->fClass->GetBaseClass("TClonesArray")){
389 TBranch * br = fTree->Branch(bname1,&(element->fPointer));
390 fBranches->AddAt(br,i);
393 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
394 fBranches->AddAt(br,i);
397 if (element->GetType()>0){
399 sprintf(bname2,"B%d/%c",i,element->GetType());
400 TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
401 fBranches->AddAt(br,i);
406 void TTreeStream::Fill(){
411 Int_t entries=fElements->GetEntriesFast();
412 if (entries>fTree->GetNbranches()) BuildTree();
413 for (Int_t i=0;i<entries;i++){
414 TTreeDataElement* el = (TTreeDataElement*)fElements->At(i);
416 if (!el->GetType()) continue;
417 TBranch * br = (TBranch*)fBranches->At(i);
419 if (el->GetType()) br->SetAddress(el->fPointer);
422 if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
427 TTreeStream & TTreeStream::Endl()
430 // Perform pseudo endl operation
432 if (fTree->GetNbranches()==0) BuildTree();
440 TTreeStream &TTreeStream::operator<<(Char_t *name)
449 //if tree was already defined ignore
450 if (fTree->GetEntries()>0) return *this;
451 //check branch name if tree was not
454 for (last=0;;last++){
455 if (name[last]==0) break;
458 if (last>0&&name[last-1]=='='){