hooks for PMD flow analysis
[u/mrichter/AliRoot.git] / PWG2 / FLOW / macros / mergeOutput.C
1 // Macro mergeOutput.C is used to merge output files "AnalysisResults.root" locally. 
2 // (To merge output files "AnalysisResults.root" on Grid use macro mergeOutputOnGrid.C.)
3 // Its usage relies on the following directory structure and naming conventions:
4 //  1.) In directory <dir> there are subdirectories <subdir1>, <subdir2>, ...;   
5 //  2.) In subdirectory <subdir*> there is a file named "AnalysisResults.root";
6 //  3.) Copy macro mergeOutput.C in directory <dir> and launch it. It will automatically 
7 //      access from each subdirectory a file "AnalysisResults.root" and by making use of 
8 //      TFileMerger utility it will produce a merged file "mergedAnalysisResults.root" 
9 //      and save it in directory <dir>;
10 //  4.) IMPORTANT: Macro mergeOutput.C must be used in a combination with macro redoFinish.C
11 //      in order to get the analysis done on merged, large statistics sample. In particular,
12 //      after you got the file "mergedAnalysisResults.root", copy macro redoFinish.C in 
13 //      directory <dir> and launch it. This macro will access "mergedAnalysisResults.root"
14 //      and produce the output file "AnalysisResults.root" in directory <dir>. This file will 
15 //      hold the final results for merged, large statistics sample. 
16 //  5.) REMARK 1: To see plots for some of results use macro compareFlowResults.C. This macro
17 //      accesses file "AnalysisResults.root" and produces couple of predefined example plots.        
18 //  6.) REMARK 2: To use this macro for merging of other root files (having other name than
19 //      the default "AnalysisResults.root") modify the declaration of TString outputFileName.
20
21 // Name of the output files to be merged (sitting in <subdir1>, <subdir2>, ...):
22 TString outputFileName = "AnalysisResults.root";
23 // Name of the merged, large statistics file (to be saved in <dir>):
24 TString mergedFileName = "mergedAnalysisResults.root";
25 // Optionally set maximum number of files to be merged:
26 Int_t maxNoOfFiles = -1; // -1 = ignore
27 // For a large number of output files merging is done in cycles and this is the cycle period: 
28 const Int_t cycle = 50;
29
30 enum libModes {mLocal,mLocalSource};
31
32 void mergeOutput(Int_t mode=mLocal)
33 {
34  // Mode: if mode = mLocal: analyze data on your computer using aliroot
35  //       if mode = mLocalSource: analyze data on your computer using root + source files 
36  
37  // Cross-check user settings before starting:
38  CrossCheckUserSettings(); 
39  
40  // Load needed flow libraries:
41  LoadLibrariesMO(mode);  
42  
43  // Standard magic:
44  TString *baseDirPath = new TString(gSystem->pwd());
45  TSystemDirectory *baseDir = new TSystemDirectory(".",baseDirPath->Data());          
46  TList *listOfFilesInBaseDir = baseDir->GetListOfFiles();
47  TStopwatch timer;
48  timer.Start();
49  //listOfFilesInBaseDir->Print();
50  
51  // Count number of files to be merged:
52  CountNumberOfFilesToBeMerged(baseDirPath,listOfFilesInBaseDir);
53  
54  // Loop over all files and from each subdirectory add file <outputFileName> to TFileMerger:
55  Int_t nFiles = listOfFilesInBaseDir->GetEntries();
56  Int_t fileCounter = 0;
57  TFileMerger *fileMerger = new TFileMerger(); 
58  cout<<" .... merging in progress, silence please ...."<<"\r"<<flush;
59  for(Int_t iFile=0;iFile<nFiles;iFile++)
60  {
61   TSystemFile *currentFile = (TSystemFile*)listOfFilesInBaseDir->At(iFile);
62   // Consider only subdirectories: 
63   if(!currentFile || 
64      !currentFile->IsDirectory() || 
65      strcmp(currentFile->GetName(), ".") == 0 || 
66      strcmp(currentFile->GetName(), "..") == 0){continue;} 
67   // Accessing the output file <outputFileName> in current subdirectory: 
68   TString currentSubDirName = baseDirPath->Data();
69   (currentSubDirName+="/")+=currentFile->GetName();
70   currentSubDirName+="/";
71   TString fileName = currentSubDirName; 
72   fileName+=outputFileName.Data();
73   if(!(gSystem->AccessPathName(fileName.Data(),kFileExists)))
74   {
75    if(gROOT->GetVersionDate()>=20100404) // to be improved - removed eventually (this is temporary protection)
76    { 
77     Bool_t success = fileMerger->AddFile(fileName.Data(),kFALSE); // kFALSE switches off cp printout (not supported in older Root)
78     if(success){fileCounter++;}
79    } else 
80      {
81       Bool_t success = fileMerger->AddFile(fileName.Data());
82       if(success){fileCounter++;}
83      }    
84    // Merging in cycles:
85    if(fileCounter % cycle == 0)
86    {
87     // If the merged output from previous cycle exists add it to TFileMerger:
88     TString *mergedFileForPreviousCycle = new TString("mergedCycle"); 
89     (*mergedFileForPreviousCycle)+=(fileCounter/cycle - 1);
90     (*mergedFileForPreviousCycle)+=".root";
91     if(!(gSystem->AccessPathName(mergedFileForPreviousCycle->Data(),kFileExists)))
92     {
93      if(gROOT->GetVersionDate()>=20100404) // to be improved - removed eventually (this is temporary protection)
94      {  
95       fileMerger->AddFile(mergedFileForPreviousCycle->Data(),kFALSE); // kFALSE switches off cp printout (not supported in older Root)
96      } else
97        {
98         fileMerger->AddFile(mergedFileForPreviousCycle->Data());
99        }
100      // Delete merged output from previous cycle:
101      TSystemFile *file = new TSystemFile(mergedFileForPreviousCycle->Data(),baseDirPath->Data());
102      file->Delete();
103      delete file;
104     }    
105     // Create merged output for the current cycle:
106     TString *mergedFileForCurrentCycle = new TString("mergedCycle"); 
107     (*mergedFileForCurrentCycle)+=(fileCounter/cycle);
108     (*mergedFileForCurrentCycle)+=".root";    
109     fileMerger->OutputFile(mergedFileForCurrentCycle->Data());
110     fileMerger->Merge();
111     cout<<" .... merged "<<fileCounter<<" files so far, marching on ....                       "<<"\r"<<flush;
112     fileMerger->Reset();    
113     delete mergedFileForPreviousCycle;
114     delete mergedFileForCurrentCycle;
115    } // end of if(fileCounter % cycle == 0) 
116   } // end of if(!(gSystem->AccessPathName(fileName.Data(),kFileExists))) 
117   if(fileCounter==maxNoOfFiles){break;}
118  } // end of for(Int_t iFile=0;iFile<nFiles;iFile++)
119  
120  //=================================================================================================
121  
122  // Final merging at the end of the day (3 distinct cases):
123  gSystem->cd(baseDirPath->Data());
124  if(fileCounter < cycle)
125  {
126   fileMerger->OutputFile(mergedFileName.Data());
127   fileMerger->Merge();
128  } else if(fileCounter % cycle == 0)
129    {
130     TString *mergedFileForPreviousCycle = new TString("mergedCycle"); 
131     (*mergedFileForPreviousCycle)+=(fileCounter/cycle);
132     (*mergedFileForPreviousCycle)+=".root";    
133     if(!(gSystem->AccessPathName(mergedFileForPreviousCycle->Data(),kFileExists)))
134     {
135      gSystem->Rename(mergedFileForPreviousCycle->Data(),mergedFileName.Data());
136     }     
137    } else
138      {
139       TString *mergedFileForPreviousCycle = new TString("mergedCycle"); 
140       (*mergedFileForPreviousCycle)+=((Int_t)fileCounter/cycle);
141       (*mergedFileForPreviousCycle)+=".root";      
142       if(gROOT->GetVersionDate()>=20100404) // to be improved - removed eventually (this is temporary protection)
143       {  
144        fileMerger->AddFile(mergedFileForPreviousCycle->Data(),kFALSE);
145       } else
146         {
147          fileMerger->AddFile(mergedFileForPreviousCycle->Data());      
148         }
149       // Delete merged output from previous cycle:
150       TSystemFile *file = new TSystemFile(mergedFileForPreviousCycle->Data(),baseDirPath->Data());
151       file->Delete();
152       delete file;
153       fileMerger->OutputFile(mergedFileName.Data());
154       fileMerger->Merge();
155       delete mergedFileForPreviousCycle;
156      }
157  delete fileMerger;
158  delete baseDirPath;
159  delete baseDir;
160
161  if(!(gSystem->AccessPathName(mergedFileName.Data(),kFileExists)) && fileCounter > 0)
162  {
163   cout<<" Merging went successfully: "<<fileCounter<<" files \""<<outputFileName.Data()<<"\" were"<<endl;
164   cout<<" merged into the newly created file \""<<mergedFileName.Data()<<"\"."<<endl;
165   cout<<endl;
166   cout<<" Launch now macro redoFinish.C to get the correct final results."<<endl;
167  } else
168    {
169     cout<<" WARNING: Merging failed miserably !!!!"<<endl;
170    }   
171  cout<<endl;
172  timer.Stop();
173  timer.Print(); 
174  cout<<endl;
175
176 } // End of void mergeOutput(Int_t mode=mLocal)
177
178 // ===================================================================================
179
180 void CrossCheckUserSettings()
181 {
182  // Cross-check user settings before starting:
183  
184  if(cycle>100)
185  {
186   cout<<endl;
187   cout<<" WARNING: Cycle is too big !!!!"<<endl; 
188   cout<<"          Set \"const Int_t cycle\" to smaller value in the macro."<<endl;
189   cout<<endl;
190   exit(0);
191  }
192
193 } // void CrossCheckUserSettings() 
194  
195 // ===================================================================================
196
197 void CountNumberOfFilesToBeMerged(TString *baseDirPath,TList *listOfFilesInBaseDir)
198 {
199  // Count number of files to be merged and print info on the screen.
200  
201  if(!(baseDirPath && listOfFilesInBaseDir))
202  {
203   cout<<endl;
204   cout<<" WARNING: baseDirPath||listOfFilesInBaseDir is NULL in CountNumberOfFilesToBeMerged(...) !!!!"<<endl;
205   cout<<endl;
206   exit(0);
207  }
208  
209  Int_t nFiles = listOfFilesInBaseDir->GetEntries();
210  Int_t fileCounter = 0;
211  for(Int_t iFile=0;iFile<nFiles;iFile++)
212  {
213   TSystemFile *currentFile = (TSystemFile*)listOfFilesInBaseDir->At(iFile);
214   // Consider only subdirectories: 
215   if(!currentFile || 
216      !currentFile->IsDirectory() || 
217      strcmp(currentFile->GetName(), ".") == 0 || 
218      strcmp(currentFile->GetName(), "..") == 0) continue; 
219   // Accessing the output file <outputFileName> in current subdirectory: 
220   TString currentSubDirName = baseDirPath->Data();
221   (currentSubDirName+="/")+=currentFile->GetName();
222   currentSubDirName+="/";
223   TString fileName = currentSubDirName; 
224   fileName+=outputFileName.Data();
225   if(!(gSystem->AccessPathName(fileName.Data(),kFileExists)))
226   {
227    fileCounter++;
228   }
229  } // end of for(Int_t iFile=0;iFile<nFiles;iFile++)
230
231  // Print info on the screen:
232  if(fileCounter>0)
233  { 
234   cout<<endl;
235   cout<<" In subdirectores of directory "<<baseDirPath->Data()<<endl;
236   cout<<" there are "<<fileCounter<<" files \""<<outputFileName.Data()<<"\" to be merged."<<endl;
237   cout<<" Let the merging begins!"<<endl;
238   cout<<endl;
239  }
240  else if(fileCounter==0)
241  {
242   cout<<endl;
243   cout<<" TFileMerger wasn't lucky :'( "<<endl;
244   cout<<" Couldn't find a single file \""<<outputFileName.Data()<<"\" to merge"<<endl;
245   cout<<" in subdirectories of directory "<<baseDirPath->Data()<<" !!!!"<<endl;
246   cout<<endl;
247   exit(0);
248  }
249  
250  return;
251  
252 } // void CountNumberOfFilesToBeMerged(TString *dirName,TList *listOfAllFiles)
253
254 // ===================================================================================
255
256 void LoadLibrariesMO(const libModes mode) {
257   
258   //--------------------------------------
259   // Load the needed libraries most of them already loaded by aliroot
260   //--------------------------------------
261   //gSystem->Load("libTree");
262   gSystem->Load("libGeom");
263   gSystem->Load("libVMC");
264   gSystem->Load("libXMLIO");
265   gSystem->Load("libPhysics");
266   
267   //----------------------------------------------------------
268   // >>>>>>>>>>> Local mode <<<<<<<<<<<<<< 
269   //----------------------------------------------------------
270   if (mode==mLocal) {
271     //--------------------------------------------------------
272     // If you want to use already compiled libraries 
273     // in the aliroot distribution
274     //--------------------------------------------------------
275
276   //==================================================================================  
277   //load needed libraries:
278   gSystem->AddIncludePath("-I$ROOTSYS/include");
279   //gSystem->Load("libTree");
280
281   // for AliRoot
282   gSystem->AddIncludePath("-I$ALICE_ROOT/include");
283   gSystem->Load("libANALYSIS");
284   gSystem->Load("libPWG2flowCommon");
285   //cerr<<"libPWG2flowCommon loaded ..."<<endl;
286   
287   }
288   
289   else if (mode==mLocalSource) {
290  
291     // In root inline compile
292   
293     // Constants  
294     gROOT->LoadMacro("AliFlowCommon/AliFlowCommonConstants.cxx+");
295     gROOT->LoadMacro("AliFlowCommon/AliFlowLYZConstants.cxx+");
296     
297     // Flow event
298     gROOT->LoadMacro("AliFlowCommon/AliFlowVector.cxx+"); 
299     gROOT->LoadMacro("AliFlowCommon/AliFlowTrackSimple.cxx+");    
300     gROOT->LoadMacro("AliFlowCommon/AliFlowTrackSimpleCuts.cxx+");    
301     gROOT->LoadMacro("AliFlowCommon/AliFlowEventSimple.cxx+");
302     
303     // Output histosgrams
304     gROOT->LoadMacro("AliFlowCommon/AliFlowCommonHist.cxx+");
305     gROOT->LoadMacro("AliFlowCommon/AliFlowCommonHistResults.cxx+");
306     gROOT->LoadMacro("AliFlowCommon/AliFlowLYZHist1.cxx+");
307     gROOT->LoadMacro("AliFlowCommon/AliFlowLYZHist2.cxx+");
308        
309     cout << "finished loading macros!" << endl;  
310     
311   } // end of else if (mode==mLocalSource) 
312   
313 } // end of void LoadLibrariesMO(const libModes mode)
314