]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliXRDPROOFtoolkit.cxx
Always delete TObjArrays created by TString::Tokenize (Ruben)
[u/mrichter/AliRoot.git] / TPC / AliXRDPROOFtoolkit.cxx
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 /*
17   marian.ivanov@cern.ch
18   
19   //TOOLKIT for chain manipulation:  
20   //Example usage:
21   //
22   // 1. Check the list of files
23   AliXRDPROOFtoolkit toolkit;
24   AliXRDPROOFtoolkit::FilterList("pp.txt","AliESDs.root esdTree AliESDfriends.root * Kinematics.root *",0)
25   AliXRDPROOFtoolkit::FilterList("pp.txt","AliESDs.root esdTree AliESDfriends.root * Kinematics.root *",1)
26   //
27   //2. make a chain or random chain form the list of files
28   TChain * chain = toolkit.MakeChain("esd.txt","esdTree",0,10)
29   TChain * chainRandom = toolkit.MakeChainrandom("esd.txt","esdTree",0,10)
30   chain->Draw("fTPCnclsF");
31   
32
33 */
34 #include <TTree.h>
35 #include <TEnv.h>
36 #include <TString.h>
37 #include <TObjArray.h>
38 #include <TObjString.h>
39 #include <TTree.h>
40 #include <TFile.h>
41 #include <TChain.h>
42 #include <TDSet.h>
43 #include <TH1.h>
44 #include <TGraph.h>
45 #include <TMath.h>
46 #include <TPad.h>
47 #include <exception>
48 #include <fstream>
49 #include <TRandom.h>
50 #include <AliXRDPROOFtoolkit.h>
51
52
53 ClassImp(AliXRDPROOFtoolkit)
54
55
56
57 //______________________________________________________________________________
58   AliXRDPROOFtoolkit::AliXRDPROOFtoolkit () : 
59     TObject () ,
60     fVerbose(kFALSE),          // verbso mode  - print command 
61     fUserName(""),         // user name
62     fUserGroup(0)        // user group info
63 {
64   //
65   // 
66   //
67   fUserGroup = gSystem->GetUserInfo();
68   fUserName  = fUserGroup->fUser;       
69   fVerbose=1;
70 }
71
72
73
74
75
76 TChain* AliXRDPROOFtoolkit::MakeChain(const char*fileIn, const char * treeName, const char *fName, Int_t maxFiles, Int_t startFile)
77 {
78   //
79   // Create the chain
80   //
81   TChain* chain = new TChain(treeName);
82
83   // Open the input stream
84   ifstream in;
85   in.open(fileIn);
86
87   // Read the input list of files and add them to the chain
88   TString currentFile;
89   Int_t counter=0;
90   while(in.good()) {
91     in >> currentFile;
92     if (fName) {
93       currentFile+="#";
94       currentFile+=fName;
95     }
96     if (!currentFile.Contains("root")) continue; // protection
97     counter++;
98     if (counter<startFile) continue;
99     if (counter>maxFiles+startFile) break;
100     TFile * f = TFile::Open(currentFile.Data());
101     if (f){
102       chain->Add(currentFile.Data());
103     }
104     delete f;
105   }
106
107   in.close();
108
109   return chain;
110 }
111
112 TChain* AliXRDPROOFtoolkit::MakeChainRandom(const char*fileIn, const char * treeName,const char *fName, Int_t maxFiles, Int_t startFile)
113 {
114   //
115   // Create a TDSet - files are in random order
116   //
117   // filein    - input list text file
118   // treename  - containg tree 
119   // maxFiles  - maximum number of files included
120
121   TObjArray array(10000);
122   
123   TChain* chain = new TChain(treeName);
124
125   // Open the input stream
126   ifstream in;
127   in.open(fileIn);
128
129   // Read the input list of files and add them to the chain
130   TString currentFile;
131   Int_t counter=0;
132   while(in.good()) {
133     in >> currentFile;
134     if (fName) {
135       currentFile+="#";
136       currentFile+=fName;
137     }
138     if (!currentFile.Contains("root")) continue; // protection
139     counter++;
140     //    chain->Add(currentFile.Data());
141     array.AddLast(new TObjString(currentFile));
142   }
143   in.close();
144   Int_t entries = array.GetEntries();
145   printf("Number of entries\t%d\n",entries);
146   //
147   //
148   //
149   Double_t *randomI = new Double_t[entries];
150   Int_t *indexes = new Int_t[entries];
151   for (Int_t i=0;i<entries; i++) randomI[i]=gRandom->Rndm();
152   TMath::Sort(entries,randomI,indexes); 
153   
154   for (Int_t i=startFile; (i<startFile+maxFiles) && (i<entries); i++){
155     Int_t ifile = indexes[i];
156     if (ifile<entries && (array.At(ifile)) &&  array.At(ifile)->TestBit(TObject::kCannotPick)==kFALSE){ 
157       printf("%d\t%d\t%s\n",i, ifile, array.At(ifile)->GetName());
158       chain->Add(array.At(ifile)->GetName());
159       array.At(ifile)->SetBit(TObject::kCannotPick);
160     }
161   }
162   return chain;
163 }
164
165
166
167 TDSet* AliXRDPROOFtoolkit::MakeSet(const char*fileIn, const char * treeName, const char *fName, Int_t maxFiles)
168 {
169   //
170   // Create the TDSet out of list
171   // filein    - input list text file
172   // treename  - containg tree 
173   // maxFiles  - maximum number of files included
174
175   TDSet* chain = new TDSet(treeName);
176
177   // Open the input stream
178   ifstream in;
179   in.open(fileIn);
180
181   // Read the input list of files and add them to the chain
182   TString currentFile;
183   Int_t counter=0;
184   while(in.good()) {
185     in >> currentFile;
186     if (fName) {
187       currentFile+="#";
188       currentFile+=fName;
189     }
190     if (!currentFile.Contains("root")) continue; // protection
191     counter++;
192     if (maxFiles>0 && counter>maxFiles) break;
193     chain->Add(currentFile.Data());
194   }
195
196   in.close();
197   chain->Validate();
198   return chain;
199 }
200
201
202 TDSet* AliXRDPROOFtoolkit::MakeSetRandom(const char*fileIn, const char * treeName, const char *fName, Int_t maxFiles)
203 {
204   //
205   // Create a TDSet - files are in random order
206   //
207   // filein    - input list text file
208   // treename  - containg tree 
209   // maxFiles  - maximum number of files included
210
211   TObjArray array(10000);
212   
213   TDSet* chain = new TDSet(treeName);
214
215   // Open the input stream
216   ifstream in;
217   in.open(fileIn);
218
219   // Read the input list of files and add them to the chain
220   TString currentFile;
221   Int_t counter=0;
222   while(in.good()) {
223     in >> currentFile;
224     if (fName) {
225       currentFile+="#";
226       currentFile+=fName;
227     }
228     if (!currentFile.Contains("root")) continue; // protection
229     counter++;
230     //    chain->Add(currentFile.Data());
231     array.AddLast(new TObjString(currentFile));
232   }
233   in.close();
234   Int_t entries = array.GetEntries();
235   printf("Number of entries\t%d",entries);
236   if (maxFiles<0) maxFiles=entries;
237   if (maxFiles>entries) maxFiles=entries;
238   for (Int_t i=0; i<maxFiles; i++){
239     Int_t ifile = TMath::Nint(gRandom->Rndm()*Float_t(entries));
240     if (ifile<entries && (array.At(ifile)) &&  array.At(ifile)->TestBit(TObject::kCannotPick)==kFALSE){ 
241       printf("%d\t%d\t%s\n",i, ifile, array.At(ifile)->GetName());
242       chain->Add(array.At(ifile)->GetName());
243       array.At(ifile)->SetBit(TObject::kCannotPick);
244     }
245   }
246
247
248   chain->Validate();
249   return chain;
250 }
251
252
253
254
255
256
257
258 Int_t  AliXRDPROOFtoolkit::CheckTreeInFile(const char*fileName,const char*treeName, Int_t debugLevel, const char *branchName){
259   //
260   // Check the tree in file 
261   // fileName   - the name of the file with tree
262   // treeName   - the name of file
263   // debugLevel - 0 check the existance of the file -  1 make loop over entries
264   // branchName - if debugLevel>0 the branch is chcecked
265   //              if brnachName =0 the content of full tree is chcecked
266   // return value = 0 - Check things  OK
267   //               -1 - file not exist or not accesible
268   //               -2 - file is zombie
269   //               -3 - tree not present
270   //               -4 - branch not present
271   TFile * file = TFile::Open(fileName);
272   if (!file) { return -1;}
273   if (file->IsZombie()) {file->Close(); delete file; return -2;};
274
275   TString TrName(treeName);
276   if (TrName=="*") {
277     //cout <<"        treename ==== *"<<endl;;
278     file->Close(); delete file; 
279     return 0;
280   }
281   TTree * tree = (TTree*)file->Get(treeName);
282   if (!tree) {file->Close(); delete file; return -3;}
283   TBranch * branch = 0;
284   if (branchName) {
285     branch = tree->GetBranch(branchName);
286     if (!branch) {file->Close(); delete file; return -4;}
287   }
288   //
289   if (debugLevel==1 &&  tree->GetEntries()==0 ) return 1; //empty 
290
291   tree->SetBranchStatus("*",1);
292   try {
293     if (debugLevel>1){
294       Int_t entries = tree->GetEntries();
295       for (Int_t i=0;i<entries; i++){
296         if (branch) branch->GetEntry(i);
297         else tree->GetEntry();      
298       }
299     }
300   }catch ( ... ) {
301     printf("PROBLEM\n");  
302     // never catched  - as there is no exception in the ROOT IO
303     file->Close(); delete file;
304     return 1 ;
305   }
306
307   file->Close(); delete file;
308   return 0;
309 }
310
311
312 Bool_t  AliXRDPROOFtoolkit::FilterList(const char*inputList, const char*fileList, Int_t checkLevel){
313   //
314   // Filter the list  
315   // inputList - list of original file names
316   // fileList  - list of file to be checked
317   //           - 0 - fileName
318   //           - 1 - treeName (if * not checked)
319   //           - 2 - fileName 
320   //                 ....
321   // checkLevel - 0 - check only existance of the files and tree's + 
322   //                  simple file corruption
323   //            > 1 - check the content of the tree - 
324   //                  (can crash as there do not exest exception handling in ROOT)
325   // Output -  two streams are created - file with good entries
326   // "%s.Good a,d file with bad entries %s.Bad
327   //EXAMPLE:
328   // AliXRDPROOFtoolkit::FilterList("ppgrid2.txt","AliESDs.root esdTree AliESDfriends.root * Kinematics.root *",1) 
329   gEnv->SetValue("TFile.Recover", 0);
330   //
331   fstream finput;
332   finput.open(inputList, ios_base::in);
333   fstream focGood;
334   fstream focBad;
335   focGood.open(Form("%s.Good",inputList), ios_base::out|ios_base::trunc);
336   focBad.open(Form("%s.Bad",inputList), ios_base::out|ios_base::trunc);
337   //
338   if(!finput.is_open()) {
339     cout<<"Can't open file "<<inputList<<endl;
340     return kFALSE;
341   }
342   //
343   // Read the input list of files and add them to the chain
344   //
345   TObjArray *array = (TString(fileList)).Tokenize(" ");
346   TString currentFile;
347   Int_t counter=0;
348   while(finput.good()) {
349     finput >> currentFile;
350     if (!currentFile.Contains("root")) continue; // protection
351     if (currentFile.Contains("alien://")){
352       focGood<<currentFile<<endl;
353       continue;
354     }
355     Bool_t isZip = currentFile.Contains("#");
356     const char * dirname = gSystem->DirName(currentFile.Data());
357     Int_t status = 0;
358     //
359     for (Int_t i=0; i<array->GetEntries(); i+=2){
360       char fname[1000];
361       if (!isZip){
362         snprintf(fname,1000, "%s/%s",dirname,array->At(i)->GetName());
363         if (((TObjString*)array->At(i))->String().Contains("*")){
364           snprintf(fname,1000, "%s", currentFile.Data());
365         }
366       }
367       if (isZip) {
368         const char * fileName   =  gSystem->BaseName(currentFile.Data());
369         TString fstring=fileName;
370         fstring[fstring.First("#")]=0;
371         snprintf(fname,1000, "%s/%s#%s",dirname,fstring.Data(),array->At(i)->GetName());
372         printf(fname, "To check %s%s#%s\n",dirname,fstring.Data(),array->At(i)->GetName());
373       }
374
375       printf("\nFile to be checked %s\n",fname);
376       //cout <<"\n arguments: "<< array->At(i+1)->GetName()<<" "<<checkLevel<<endl;
377       Int_t cstatus = CheckTreeInFile(fname, array->At(i+1)->GetName(), checkLevel,0);
378       //printf("  CheckTreeInFile returns %d",cstatus);
379       if (cstatus!=0) {
380         status = cstatus; 
381         break;
382       }
383     }
384     if (status==0){
385       focGood<<currentFile<<endl;
386     }else{
387       focBad<<currentFile<<endl;
388     }
389     counter++;    
390   }
391   finput.close();
392   delete array;
393   return kTRUE;
394 }
395
396
397 Bool_t  AliXRDPROOFtoolkit::FilterListZip(const char*inputList, const char*fileList, Int_t checkLevel){
398   //
399   // Filter the list  
400   // inputList - list of original file names
401   // fileList  - list of file to be checked
402   //           - 0 - fileName
403   //           - 1 - treeName (if * not checked)
404   //           - 2 - fileName 
405   //                 ....
406   // checkLevel - 0 - check only existance of the files and tree's + 
407   //                  simple file corruption
408   //            > 1 - check the content of the tree - 
409   //                  (can crash as there do not exest exception handling in ROOT)
410   // Output -  two streams are created - file with good entries
411   // "%s.Good a,d file with bad entries %s.Bad
412   //EXAMPLE:
413   // AliXRDPROOFtoolkit::FilterList("ppgrid2.txt","AliESDs.root esdTree AliESDfriends.root * Kinematics.root *",1) 
414
415   fstream finput;
416   finput.open(inputList, ios_base::in);
417   fstream focGood;
418   fstream focBad;
419   focGood.open(Form("%s.Good",inputList), ios_base::out|ios_base::trunc);
420   focBad.open(Form("%s.Bad",inputList), ios_base::out|ios_base::trunc);
421   //
422   if(!finput.is_open()) {
423     cout<<"Can't open file "<<inputList<<endl;
424     return kFALSE;
425   }
426   //
427   // Read the input list of files and add them to the chain
428   //
429   TObjArray *array = (TString(fileList)).Tokenize(" ");
430   TString currentFile;
431   Int_t counter=0;
432   while(finput.good()) {
433     finput >> currentFile;
434     if (!currentFile.Contains("root")) continue; // protection
435     if (currentFile.Contains("alien://")){
436       focGood<<currentFile<<endl;
437       continue;
438     }
439     //Bool_t isZip = currentFile.Contains("#");
440     const char * dirname = gSystem->DirName(currentFile.Data());
441     const char * fileName   =  gSystem->BaseName(currentFile.Data());
442     TString fstring=fileName;
443     fstring[fstring.First("#")]=0;
444     Int_t status = 0;
445     for (Int_t i=0; i<array->GetEntries(); i+=2){
446       char fname[1000];
447       //if (isZip) sprintf(fname,
448       snprintf(fname,1000, "%s/%s#%s",dirname,fstring.Data(),array->At(i)->GetName());
449       printf(fname, "To check %s%s#%s\n",dirname,fstring.Data(),array->At(i)->GetName());
450       //cout <<"\n arguments: "<< array->At(i+1)->GetName()<<" "<<checkLevel<<endl;
451       Int_t cstatus = CheckTreeInFile(fname, array->At(i+1)->GetName(), checkLevel,0);
452       //printf("  CheckTreeInFile returns %d",cstatus);
453       if (cstatus!=0) {
454         status = cstatus; 
455         break;
456       }
457     }
458     if (status==0){
459       focGood<<currentFile<<endl;
460     }else{
461       focBad<<currentFile<<endl;
462     }
463     counter++;    
464   }
465   finput.close();
466   return kTRUE;
467 }
468
469
470
471
472
473 Bool_t  AliXRDPROOFtoolkit::XRDCopyDir(const char * idir, const char * files, const char *odir, Bool_t /*zip*/){
474   //
475   // idir  - input directory
476   // odir  - output directory
477   // files - the list of files to be coppied
478   // zip   - not supported yet
479   //
480   // Example :                                                                  
481   //
482   // idir ="root://gsiaf.gsi.de:1094//sma/sim/v4-05-Rev-03/pp/0000";
483   // odir ="root://lxgrid2.gsi.de:1094//miranov/test/pp/0000"; 
484   // char *files="AliESDs.root AliESDfriend.root Kinematics.root";
485   TString str(files);
486   TObjArray * array = str.Tokenize(" "); 
487   Int_t nfiles = array->GetEntries();
488   char infile[1000];
489   char outfile[1000];
490   Bool_t succes=kTRUE;
491   for (Int_t ifile =0; ifile<nfiles; ifile++){
492     snprintf(infile,1000,"%s/%s", idir, array->At(ifile)->GetName());
493     snprintf(outfile,1000,"%s/%s", odir, array->At(ifile)->GetName());
494     printf("%s - %s\n",infile, outfile);
495     Bool_t result = TFile::Cp(infile,outfile); 
496     succes &= result;
497   }
498   delete array;
499   return succes;
500 }
501
502
503
504 void AliXRDPROOFtoolkit::JoinTreesIndex(const char * outputFile, const char * outputTree, const char *indexName, const char *inputTrees, Int_t debugLevel){
505   //
506   // Join together several tree according to the index
507   // 
508   // Parameters:
509   // Output:
510   //     outputFile : name of the output file
511   //     outputTree : name of the output Tree
512   //     indexName  : name of the branch to be used as an index
513   // Input:
514   //     inputTrees : decription of the input trees setup
515   /*
516     Example usage:
517     
518     AliXRDPROOFtoolkit::JoinTreesIndex("outAll.root","joinAll","run","1#CPass1#run#tpcQA#TPCCPass1.root+1#VPass1#run#tpcQA#TPCVPass1.root+1#Pass1#run#tpcQA#TPCPass1.root+0#DAQ#run#joinTree#fproductionJoin.root+0#C#run#dcs#OCDBscan.root+0#CE#run#Fits#CEtrend.root");
519     ==>
520     Combine information form the Cpass1,VPass, and Pass1QA, calibration tree, DAQ information, trigger information 
521     Make a File "outAll.root",  with tree "joinAll", index of tree with name "run"
522     //
523     // Input tree configuration string:
524     //
525     const char *inputTrees="1#CPass1#run#tpcQA#TPCCPass1.root+1#VPass1#run#tpcQA#TPCVPass1.root+1#Pass1#run#tpcQA#TPCPass1.root+0#DAQ#run#joinTree#/home/miranov/test/dbQueries/fproductionJoin.root+0#C#run#dcs#OCDBscan.root+0#CE#run#Fits#CEtrend.root"
526     Describe 6 trees to be merged (string separated be +):
527       TObjArray *arrayInput = TString(inputTrees).Tokenize("+");
528       TObjString = 1#CPass1#run#tpcQA#TPCCPass1.root
529       TObjString = 1#VPass1#run#tpcQA#TPCVPass1.root
530       TObjString = 1#Pass1#run#tpcQA#TPCPass1.root
531       TObjString = 0#DAQ#run#joinTree#/home/miranov/test/dbQueries/fproductionJoin.root
532       TObjString = 0#C#run#dcs#OCDBscan.root
533       TObjString = 0#CE#run#Fits#CEtrend.root
534     //  
535     Each tree is characterize by 5 parameters - separate by #
536        description="1#CPass1#run#tpcQA#TPCCPass1.root"
537        TString(description)->Tokenize("#").Print()
538        Collection name='TObjArray', class='TObjArray', size=16
539        TObjString = 1                    ==> (0/1) index is used 
540        TObjString = CPass1               ==> name of output branch  in output tree
541        TObjString = run                  ==> name of the index
542        TObjString = tpcQA                ==> name of the input tree in the input file
543        TObjString = TPCCPass1.root       ==> name of the input file
544   */
545   //
546   //
547   //
548                 
549   TFile * fout = new TFile(outputFile,"recreate");
550   fout->cd();
551   TTree *joinTree=new TTree(outputTree,outputTree);
552   //
553   // 1. Define setup. parse definition string
554   //
555   TObjArray *arrayInput = TString(inputTrees).Tokenize("+");
556   Int_t nTrees = arrayInput->GetEntries();
557   TObjArray * arrayFile  = new TObjArray(nTrees);    // array of TFiles with trees
558   TObjArray * arrayTrees = new TObjArray(nTrees);    // array of trees 
559   TObjArray * arrayNames = new TObjArray(nTrees);    // name of tree
560   TObjArray * arrayRunID = new TObjArray(nTrees);    // name of tree
561   TArrayI arrayEnableTree(nTrees);  
562   for (Int_t i=0; i<2; i++) printf("\n");
563   printf("Joing query\n");
564   arrayInput->Print();
565   for (Int_t i=0; i<2; i++) printf("\n");
566   {for (Int_t itree=0; itree<nTrees; itree++){
567       //
568       TObjArray *description = TString(arrayInput->At(itree)->GetName()).Tokenize("#");
569       if (description->GetEntries()<4) {
570         printf("Fatal: Invalid description:  %s\n", arrayInput->At(itree)->GetName());
571         continue;
572       }
573       TFile * f = TFile::Open(description->At(4)->GetName());
574       if (!f){
575         printf("Fatal: Invalid description: fileName %s\n", description->At(4)->GetName());
576         delete arrayInput;
577         return;
578       }
579       arrayFile->AddAt(f,itree);
580       TTree * tree = (TTree*)f->Get(description->At(3)->GetName());
581       if (!tree){
582         printf("Fatal: Invalid description. Tree name\t%s\n", description->At(3)->GetName());
583         delete arrayInput;
584         return;
585       }
586       tree->SetCacheSize(400000000);
587       //    
588       arrayTrees->AddAt(tree,itree);
589       //
590       arrayRunID->AddAt(new TObjString(description->At(2)->GetName()),itree);
591       arrayNames->AddAt(new TObjString(description->At(1)->GetName()),itree);
592       arrayEnableTree[itree]=atoi(description->At(0)->GetName());    
593
594     }}
595   //  
596   delete arrayInput;
597   // 2. Make the run list
598   //
599   //
600   map<int, int> runMap;
601   map<int, int> *runMapTree = new map<int, int>[nTrees];
602   //map<int, int> runMapTree[nTrees];
603   {for (Int_t itree=0; itree<nTrees; itree++){
604       TTree * tree = (TTree*)arrayTrees->At(itree);
605       Int_t entries=tree->GetEntries();
606       char query[2000];
607       snprintf(query,2000,"%s:Entry$", arrayRunID->At(itree)->GetName());
608       entries = tree->Draw(query,"","goff");      
609       for (Int_t ientry=0;ientry<entries; ientry++){
610         Int_t irun=Int_t(tree->GetV1()[ientry]);
611         //      Int_t entryNr=Int_t(tree->GetV2()[ientry]);
612         if (arrayEnableTree[itree]>0) runMap[irun]+=1;
613         runMapTree[itree][irun]=ientry;
614         if (debugLevel>0) printf("%s\t%d\t%d\n",tree->GetName(), irun,  runMapTree[itree][irun]);
615       }
616     }
617   }
618   //
619   // 3. Make join tree
620   //
621   Int_t jrun=0;
622   joinTree->Branch(indexName, &jrun,Form("%s/I",indexName));
623   Int_t *status=new Int_t[nTrees];
624   char *brName = new char[10000];
625   char *brTitle= new char[10000];
626   //
627   
628   {for (Int_t itree=0; itree<nTrees; itree++){
629       TTree * tree = (TTree*)arrayTrees->At(itree);      
630       tree->GetEntry(1);
631       TString treeName=arrayNames->At(itree)->GetName();
632       if (treeName.Length()>0){
633         joinTree->Branch(Form("%s.status",treeName.Data()), &status[itree],Form("%s.status/I",treeName.Data()));
634       }else{
635         joinTree->Branch("status", &status[itree],"status/I");
636       }
637       //
638       Int_t nbranches= tree->GetListOfBranches()->GetEntries();
639       for (Int_t ibr=0; ibr<nbranches; ibr++){
640         TBranch * br = (TBranch*)(tree->GetListOfBranches()->At(ibr));
641         if (treeName.Length()>0){
642           sprintf(brName,"%s.%s",treeName.Data(), br->GetName());
643           sprintf(brTitle,"%s.%s",treeName.Data(), br->GetTitle());
644         }else{
645           sprintf(brName,"%s",br->GetName());
646           sprintf(brTitle,"%s",br->GetTitle());
647         }
648         void* addr = 0;
649         TString className=br->GetClassName();
650         if (className.Length()==0){
651           TString str(br->GetTitle());
652           if (str[str.Length()-1]=='I') addr=new Int_t;
653           if (str[str.Length()-1]=='F') addr=new Float_t;
654           if (str[str.Length()-1]=='D') addr=new Double_t;
655           if (str[str.Length()-1]=='C') addr=new Char_t[10000];
656           if (addr) joinTree->Branch(brName, addr, brTitle);
657           br->SetAddress(addr);
658         }else{
659           TClass cclass(className);
660           TObject **addrClass =  new TObject *;
661           (*addrClass)=0;
662           printf("%s\t%s\n",br->GetName(), className.Data());
663           br->SetAddress(addrClass);      
664           br->GetEntry(0);        
665           joinTree->Branch(brName,addrClass);             
666         }       
667       }
668     }
669   }
670   joinTree->Write();
671   //
672   // 4. Fill the trees
673   //
674   map<int, int>::iterator riter;   
675   {for (riter=runMap.begin(); riter != runMap.end(); ++riter){
676       printf("%d\t%d\t", riter->first, riter->second);
677       jrun=riter->first;
678       for (Int_t itree=0; itree<nTrees; itree++){
679         TTree * tree = (TTree*)arrayTrees->At(itree); 
680         Int_t entry= runMapTree[itree][jrun];
681         status[itree]=(entry>0)?1:0;
682         if (entry>=0) tree->GetEntry(entry);
683         printf("%d\t",entry);
684         //
685       }
686       joinTree->Fill();
687       printf("\n");
688     }}
689   joinTree->Write("joinTree");
690   fout->Close();
691
692 }
693
694