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