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");
139 TTreeSRedirector::~TTreeSRedirector(){
142 Close(); //write the tree to the selected file
147 TTreeStream & TTreeSRedirector::operator<<(Int_t id)
150 // return reference to the data layout with given identifier
151 // if not existing - creates new
152 if (!fDataLayouts) fDataLayouts = new TObjArray(10000);
153 TTreeStream *clayout=0;
154 Int_t entries = fDataLayouts->GetEntriesFast();
155 for (Int_t i=0;i<entries;i++){
156 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
157 if (!layout) continue;
158 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=(TTreeStream*)fDataLayouts->FindObject(name);
182 Int_t entries = fDataLayouts->GetEntriesFast();
186 clayout = new TTreeStream(name);
188 clayout->SetName(name);
189 fDataLayouts->AddAt(clayout,entries);
197 void TTreeSRedirector::Close(){
200 TFile * backup = gFile;
203 Int_t entries = fDataLayouts->GetEntriesFast();
204 for (Int_t i=0;i<entries;i++){
205 TTreeStream * layout = (TTreeStream*)fDataLayouts->At(i);
207 if (layout->fTree) layout->fTree->Write(layout->GetName());
218 //-------------------------------------------------------------
219 TTreeDataElement:: TTreeDataElement(Char_t type){
227 TTreeDataElement:: TTreeDataElement(TDataType* type){
235 TTreeDataElement:: TTreeDataElement(TClass* cl){
244 //-------------------------------------------------------------------
245 TTreeStream::TTreeStream(const char *treename):TNamed(treename,treename){
251 fTree = new TTree(treename, treename);
254 TTreeStream::~TTreeStream()
262 void TTreeStream::Close()
268 Int_t TTreeStream::CheckIn(Char_t type, void *pointer)
270 if (!fElements) fElements = new TObjArray(1000);
271 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
273 element = new TTreeDataElement(type);
276 if (fNextName.Length()>0){
277 if (fNextNameCounter==0){
278 sprintf(name,"%s",(const char*)fNextName);
280 if (fNextNameCounter>0){
281 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
285 sprintf(name,"B%d.",fCurrentIndex);
287 element->SetName(name);
289 element->SetPointer(pointer);
290 fElements->AddAt(element,fCurrentIndex);
292 return 0; //new element added
294 if (element->GetType()!=type){
296 return 1; //mismatched data element
298 element->SetPointer(pointer);
303 Int_t TTreeStream::CheckIn(TObject *o){
307 if (!fElements) fElements = new TObjArray(1000);
308 TTreeDataElement* element = (TTreeDataElement*)fElements->At(fCurrentIndex);
310 element = new TTreeDataElement(o->IsA());
313 if (fNextName.Length()>0){
314 if (fNextNameCounter==0){
315 sprintf(name,"%s",(const char*)fNextName);
317 if (fNextNameCounter>0){
318 sprintf(name,"%s%d",(const char*)fNextName,fNextNameCounter);
322 sprintf(name,"B%d",fCurrentIndex);
324 element->SetName(name);
326 element->SetPointer(o);
327 fElements->AddAt(element,fCurrentIndex);
329 return 0; //new element added
331 if (element->fClass!=o->IsA()){
333 return 1; //mismatched data element
335 element->SetPointer(o);
340 void TTreeStream::BuildTree(){
343 if (fTree->GetEntries()>0) return;
344 fTree = new TTree(GetName(),GetName());
345 Int_t entries = fElements->GetEntriesFast();
346 fBranches = new TObjArray(entries);
348 for (Int_t i=0;i<entries;i++){
350 TTreeDataElement* element = (TTreeDataElement*)fElements->At(i);
352 if (element->GetName()[0]==0){
353 sprintf(bname1,"B%d",i);
356 sprintf(bname1,element->GetName());
358 if (element->fClass){
359 if (element->fClass->GetBaseClass("TClonesArray")){
360 TBranch * br = fTree->Branch(bname1,&(element->fPointer));
361 fBranches->AddAt(br,i);
364 TBranch * br = fTree->Branch(bname1,element->fClass->GetName(),&(element->fPointer));
365 fBranches->AddAt(br,i);
368 if (element->GetType()>0){
370 sprintf(bname2,"B%d/%c",i,element->GetType());
371 TBranch * br = fTree->Branch(bname1,element->fPointer,bname2);
372 fBranches->AddAt(br,i);
377 void TTreeStream::Fill(){
381 Int_t entries=fElements->GetEntriesFast();
382 if (entries>fTree->GetNbranches()) BuildTree();
383 for (Int_t i=0;i<entries;i++){
384 TTreeDataElement* el = (TTreeDataElement*)fElements->At(i);
386 if (!el->GetType()) continue;
387 TBranch * br = (TBranch*)fBranches->At(i);
389 if (el->GetType()) br->SetAddress(el->fPointer);
392 if (fStatus==0) fTree->Fill(); //fill only in case of non conflicts
397 TTreeStream & TTreeStream::Endl(){
398 if (fTree->GetNbranches()==0) BuildTree();
406 TTreeStream &TTreeStream::operator<<(Char_t *name)
416 //if tree was already defined ignore
417 if (fTree->GetEntries()>0) return *this;
418 //check branch name if tree was not
421 for (last=0;;last++){
422 if (name[last]==0) break;
425 if (last>0&&name[last-1]=='='){