5 #include "TTreeStream.h"
8 ClassImp(TTreeDataElement)
10 ClassImp(TTreeSRedirector)
15 ------------------------------------------------------------------------------------------------
17 Standard stream (cout) like input for the tree
18 Run and see TTreeStreamer::Test() - to see TTreeStreamer functionality
19 ------------------------------------------------------------------------------------------------
21 -------------------------------------------------------------------------------------------------
23 Redirect file to different TTreeStreams
24 Run and see TTreeSRedirector::Test() as an example of TTreeSRedirectorer functionality
29 void TTreeStream::Test()
33 TFile *ftest = new TFile("teststreamer.root","recreate");
34 if (!ftest) ftest = new TFile("teststreamer.root","new");
36 //create to streems Tree1 and Tree2
37 TTreeStream stream1("Tree1");
38 TTreeStream stream2("Tree2");
43 TObject *po = new TObject;
44 TObject *po2 = new TObject;
45 for (Int_t i=0;i<100000;i++) {
48 po2->SetUniqueID(i*100);
52 // The data layout of stream is defined during first invocation of streamer.
53 // Endl is the trigger which define the end of structure.
55 // The name of branch can be specified using strings with = at the the end
56 // if string is not specified automatic convention is u (sed B0, B1, ...Bn)
57 stream1<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
60 //3.) just another example - we can fill the same tree with different objects
63 stream2<<f2<<po2<<"\n";
66 //4.) Close the streeamers (Write the streamed tree's to the file) and close the corresponding file.
73 //5.) and now see results in file tteststreamer.root
78 void TTreeSRedirector::Test()
81 //Example test function to show functionality of TTreeSRedirector
84 //1.)create the redirector associated with file (testredirector.root)
87 TTreeSRedirector *pmistream= new TTreeSRedirector("testredirector.root");
88 TTreeSRedirector &mistream = *pmistream;
92 TObject *po = new TObject;
93 TObject *po2 = new TObject;
94 for (Int_t i=0;i<100000;i++) {
97 po2->SetUniqueID(i*100);
100 //2.) create the tree with identifier specified by first argument
101 // layout specified by sequence of arguments
102 // Tree identifier has to be specified as first argument !!!
103 // if the tree and layout was already defined the consistency if layout is checked
104 // if the data are consisten fill given tree
105 // the name of branch can be specified using strings with = at the the end
106 // if string is not specified use automatic convention B0, B1, ...Bn
107 mistream<<"TreeIdentifier"<<"i="<<i<<"ch="<<ch<<"f="<<f<<"po="<<po<<"\n";
111 //3.) just another example - we can fill the same tree with different objects
113 mistream<<"TreeK"<<f<<po<<"\n";
114 mistream<<"TreeK"<<f2<<po2<<"\n";
117 //4.) write the streamed tree's to the file and close the corresponding file in destructor
121 //5.) and now see results in file testredirector.root
129 TTreeSRedirector::TTreeSRedirector(const char *fname){
132 fFile = new TFile(fname,"recreate");
134 fFile = new TFile(fname,"new");
140 TTreeSRedirector::~TTreeSRedirector(){
143 Close(); //write the tree to the selected file
148 TTreeStream & TTreeSRedirector::operator<<(Int_t id)
151 // return reference to the data layout with given identifier
152 // if not existing - creates new
153 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
154 TTreeStream *clayout=0;
155 Int_t entries = fDataLayouts->GetEntriesFast();
156 for (Int_t i=0;i<entries;i++){
157 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
158 if (!layout) continue;
159 if (layout->fId==id) {
166 sprintf(chname,"Tree%d",id);
167 clayout = new TTreeStream(chname);
169 fDataLayouts->AddAt(clayout,entries);
175 TTreeStream & TTreeSRedirector::operator<<(const char* name)
178 // return reference to the data layout with given identifier
179 // if not existing - creates new
180 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
181 TTreeStream *clayout=0;
182 Int_t hash = TMath::Hash(name);
183 Int_t entries = fDataLayouts->GetEntriesFast();
184 for (Int_t i=0;i<entries;i++){
185 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
186 if (!layout) continue;
187 if (layout->fHash==hash) {
193 clayout = new TTreeStream(name);
195 clayout->SetName(name);
196 clayout->fHash = hash;
197 fDataLayouts->AddAt(clayout,entries);
205 void TTreeSRedirector::Close(){
208 Int_t entries = fDataLayouts->GetEntriesFast();
209 for (Int_t i=0;i<entries;i++){
210 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
212 if (layout->fTree) layout->fTree->Write();
219 //-------------------------------------------------------------
220 TTreeDataElement:: TTreeDataElement(Char_t type){
228 TTreeDataElement:: TTreeDataElement(TDataType* type){
236 TTreeDataElement:: TTreeDataElement(TClass* cl){
245 //-------------------------------------------------------------------
246 TTreeStream::TTreeStream(const char *treename):TNamed(treename,treename){
252 fTree = new TTree(treename, treename);
255 TTreeStream::~TTreeStream()
263 void TTreeStream::Close()
269 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
271 if (!fElements) fElements = new TObjArray(1000);
272 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
274 element = new TTreeDataElement(type);
277 if (fNextName.Length()>0){
278 if (fNextNameCounter==0){
279 sprintf(name,"%s",(const char*)fNextName);
281 if (fNextNameCounter>0){
282 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
286 sprintf(name,"B%d.",fCurrentIndex);
288 element->SetName(name);
290 element->SetPointer(pointer);
291 fElements->AddAt(element,fCurrentIndex);
293 return 0; //new element added
295 if (element->GetType()!=type){
297 return 1; //mismatched data element
299 element->SetPointer(pointer);
304 Int_t TTreeStream::CheckIn(TObject *o){
308 if (!fElements) fElements = new TObjArray(1000);
309 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
311 element = new TTreeDataElement(o->IsA());
314 if (fNextName.Length()>0){
315 if (fNextNameCounter==0){
316 sprintf(name,"%s",(const char*)fNextName);
318 if (fNextNameCounter>0){
319 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
323 sprintf(name,"B%d",fCurrentIndex);
325 element->SetName(name);
327 element->SetPointer(o);
328 fElements->AddAt(element,fCurrentIndex);
330 return 0; //new element added
332 if (element->fClass!=o->IsA()){
334 return 1; //mismatched data element
336 element->SetPointer(o);
341 void TTreeStream::BuildTree(){
344 if (fTree->GetEntries()>0) return;
345 fTree = new TTree(GetName(),GetName());
346 Int_t entries = fElements->GetEntriesFast();
347 fBranches = new TObjArray(entries);
349 for (Int_t i=0;i<entries;i++){
351 TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
353 if (element->GetName()[0]==0){
354 sprintf(bname1,"B%d",i);
357 sprintf(bname1,element->GetName());
359 if (element->fClass){
360 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
361 fBranches->AddAt(br,i);
363 if (element->GetType()>0){
365 sprintf(bname2,"B%d/%c",i,element->GetType());
366 TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
367 fBranches->AddAt(br,i);
372 void TTreeStream::Fill(){
376 Int_t entries=fElements->GetEntriesFast();
377 if (entries>fTree->GetNbranches()) BuildTree();
378 for (Int_t i=0;i<entries;i++){
379 TTreeDataElement* el = (TTreeDataElement*)fElements->At(i);
381 if (!el->GetType()) continue;
382 TBranch * br = (TBranch*)fBranches->At(i);
384 if (el->GetType()) br->SetAddress(el->fPointer);
387 if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
392 TTreeStream & TTreeStream::Endl(){
393 if (fTree->GetNbranches()==0) BuildTree();
401 TTreeStream &TTreeStream::operator<<(Char_t *name)
411 //if tree was already defined ignore
412 if (fTree->GetEntries()>0) return *this;
413 //check branch name if tree was not
416 for (last=0;;last++){
417 if (name[last]==0) break;
420 if (last>0&&name[last-1]=='='){