]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGHF/correlationHF/macros/run-single-task.C
Updated macros for D-electron correlation analysis (Matthias):
[u/mrichter/AliRoot.git] / PWGHF / correlationHF / macros / run-single-task.C
1 //-*- Mode: C++ -*-
2 // $Id$
3
4 /// @file   run-single-task.C
5 /// @author Matthias.Richter@ift.uib.no
6 /// @date   2012-04-06
7 /// @brief  Run a single task
8 ///
9 /// Helper macro to run a single task either locally or on Grid
10 /// Usage:
11 /// aliroot -b -q -l run-single-task.C'("mode", "run", "tasks", "name", useMC, events, "path", "pattern", "friendPattern", "outputDir", "user")'
12 ///  arguments
13 ///   mode:    local, full, test
14 ///   run:     list of run numbers. Or if using AODs with predefined list/AODs in same folder, specifiy as "AOD"
15 ///   tasks:   list of class names/source or header files of task
16 ///
17 ///  optional arguments
18 ///   name:    analysis name (default 'myanalysis')
19 ///   useMC:   MC analysis enabled if true (default false')
20 ///   events:  number of events to be processed (default -1 -> all)
21 ///   path:    data search path for grid analysis (default from configuration file)
22 ///   pattern: data search pattern (default from configuration file)
23 ///   friend pattern: friend file search pattern (default from configuration file)
24 ///   output dir: output directory in Grid home (default gridwork/yyyy-mm-dd_hh-mm)
25 ///   user:    default NULL, using user of active token
26 ///
27 /// Examples:
28 /// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "myanalysis_LHC11a")'
29 ///
30 /// aliroot -b -q -l run-single-task.C'("local", "$ALICE_ROOT/test/ppbench/AliESDs.root", "AliAnalysisTaskSample")'
31 ///
32 /// aliroot -b -q -l run-single-task.C'("local", "AOD", "AddTaskSample.C")'
33 ///
34 /// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "correlation3p_LHC11a", 0, -1, "/alice/data/2011/LHC11a", "*/pass2_without_SDD/AOD*/*/AliAOD.root")'
35 ///
36 /// Data input:
37 /// depending on the format of the search pattern either the ESD or AOD input handler is used.
38 ///
39 /// Source files:
40 /// If the task and classes used by the task are not in an AliRoot library available, e.g.
41 /// for the purpose of development, all header and source files need to be in the local
42 /// directory. The macro searches automatically for dependencies, compiles those and
43 /// copies files to the Grid working directory. In order to make the files accessible in
44 /// the local directory, the files can be just linked.
45 /// <pre>
46 /// for f in <search path>; do ln -s $f; done
47 /// </pre>
48 ///
49 /// Local analysis:
50 /// requires only the path to the input file and the task class name. If the specified file is
51 /// a text file (.txt) each line can contain an input ESD file path, all files are chained.
52 /// Analysis on local AOD files needs to be setup prior to this macro. gDirectory must contain
53 /// a TChain object of name 'aodTree'. This is for example created by macros like
54 /// $ALICE_ROOT/PWGHF/vertexingHF/MakeAODInputChain.C
55 /// Set $ALICE_ROOT/PWGHF/correlationHF/macros/setupDxHFE.C for an example.
56 ///
57 /// Grid analysis:
58 /// All modes provided by the AliAnalysisAlien plugin can be used, e.g. full, test, offline
59 /// A couple of settings need to be defined in a configuration file 'grid-config.C' which can be
60 /// either in the local directory or home directory. The file can look like
61 /// <pre>
62 ///   const char* alienAPIVersion="V1.1x";
63 ///   const char* alienROOTVersion="v5-34-01";
64 ///   const char* alienAliROOTVersion="v5-03-61-AN";
65 ///   const char* defaultGridDataDir="/alice/data/2011/LHC11a";
66 ///   const char* defaultDataPattern="*/pass2_without_SDD/*/AliESDs.root";
67 ///   const char* defaultFriendDataPattern="";
68 ///   {} // note this empty body
69 /// </pre>
70 /// Data path and pattern can also be specified as command line arguments.
71 /// The working directory in the grid home directory of the user is set to
72 /// gridwork/<date>_<time> (gridwork/yyyy-mm-dd_hh-mm), can be overridden by command line
73 /// parameter.
74 ///
75 /// 
76
77 ///////////////////////////////////////////////////////////////////////////////////////////////////
78 //
79 // environment
80 //
81 int macroVerbosity=0;
82 const char* defaultAnalysisName="myanalysis";
83 const char* includePath="-I. -I$ROOTSYS/include -I$ALICE_ROOT/include";
84 const char* libraryDependencies=
85   "libSTEERBase.so "
86   "libESD.so "
87   "libAOD.so "
88   "libANALYSIS.so "
89   "libANALYSISalice.so "
90   ;
91
92 TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass=true);
93 void ErrorConfigurationFile(const char* fileName);
94
95 void run_single_task(const char* mode,
96                      const char* input,
97                      const char* tasknames,
98                      const char* analysisName=defaultAnalysisName,
99                      Bool_t useMC=kFALSE,
100                      int nevents=-1,
101                      const char* gridDataDir=NULL,
102                      const char* dataPattern=NULL,
103                      const char* friendDataPattern=NULL,
104                      TString odir="",
105                      const char* user=NULL
106                      )
107 {
108   ///////////////////////////////////////////////////////////////////////////////////////////////////
109   ///////////////////////////////////////////////////////////////////////////////////////////////////
110   ///////////////////////////////////////////////////////////////////////////////////////////////////
111   //
112   // defaults
113   //
114   if (analysisName==defaultAnalysisName && gDirectory!=NULL) {
115     // NOTE: the direct pointer comparison is on purpose
116     // string comparison not necessary in this special case
117
118     // fetch the analysis name from the setup file
119     const char* confObjectName="analysis_name";
120     TObject* confObject=gDirectory->FindObject(confObjectName);
121     if (confObject) {
122       analysisName=confObject->GetTitle();
123     }
124   }
125
126   bool bRunLocal=strcmp(mode, "local")==0;
127   const char* gridConfigFile="grid-config.C";
128   TString strGridConfigFile=gridConfigFile;
129   if (gSystem->AccessPathName(strGridConfigFile)!=0) {
130     strGridConfigFile.Prepend("/");
131     strGridConfigFile.Prepend(gSystem->Getenv("HOME"));
132     if (gSystem->AccessPathName(strGridConfigFile)!=0) {
133       if (!bRunLocal) {
134         ErrorConfigurationFile(gridConfigFile);
135         return;
136       }
137       strGridConfigFile="";
138     }
139   }
140
141   if (strGridConfigFile.IsNull()==0 && !bRunLocal) {
142     cout << "loading grid configuration from file '" << strGridConfigFile << "':" << endl;
143     gROOT->LoadMacro(strGridConfigFile);
144     cout << " alienAPIVersion          =" << alienAPIVersion     << endl;
145     cout << " alienROOTVersion         =" << alienROOTVersion    << endl;
146     cout << " alienAliROOTVersion      =" << alienAliROOTVersion << endl;
147     cout << " defaultGridDataDir       =" << defaultGridDataDir  << endl;
148     cout << " defaultDataPattern       =" << defaultDataPattern  << endl;
149     cout << " defaultFriendDataPattern =" << defaultFriendDataPattern  << endl;
150
151     if (gridDataDir==NULL) gridDataDir=defaultGridDataDir;
152     if (dataPattern==NULL) dataPattern=defaultDataPattern;
153     if (friendDataPattern==NULL) friendDataPattern=defaultFriendDataPattern;
154   } else if (bRunLocal) {
155     if (dataPattern==NULL) {
156       TString strin=input;
157       if (strin.EndsWith("AOD"))
158         dataPattern="AOD";
159       else if (strin.EndsWith("ESD"))
160         dataPattern="ESD";
161     }
162   }
163
164   if(!bRunLocal) {
165     // Connect to AliEn
166     TGrid::Connect("alien://");
167   }
168   ///////////////////////////////////////////////////////////////////////////////////////////////////
169   ///////////////////////////////////////////////////////////////////////////////////////////////////
170   ///////////////////////////////////////////////////////////////////////////////////////////////////
171   //
172   // make the analysis manager
173   //
174   AliAnalysisManager *pManager  = new AliAnalysisManager("AnalysisManager");
175   if (!pManager) {
176     cerr << "failed to created AnalysisManager" << endl;
177     return;
178   }
179   AliInputEventHandler *pInputHandler = NULL;
180   TString strDataPattern(dataPattern);
181   if (strDataPattern.Contains("AOD")) pInputHandler=new AliAODInputHandler;
182   else if (strDataPattern.Contains("ESD")) pInputHandler=new AliESDInputHandler;
183   else {
184     cerr << "can not determine input type from data pattern '" << dataPattern << "'" << endl;
185     return;
186   }
187   if (!pInputHandler) {
188     cerr << "failed to created input handler" << endl;
189     return;
190   }
191   //pInputHandler->SetReadFriends(kFALSE);
192   pManager->SetInputEventHandler(pInputHandler);  
193   pManager->SetNSysInfo(1000);
194
195   TString ofile=Form("%s.root", analysisName);
196
197   ///////////////////////////////////////////////////////////////////////////////////////////////////
198   ///////////////////////////////////////////////////////////////////////////////////////////////////
199   ///////////////////////////////////////////////////////////////////////////////////////////////////
200   //
201   // load task classes and find and load all dependencies
202   //
203   gSystem->AddIncludePath(includePath);
204   TString libraries=libraryDependencies;
205   if (gDirectory!=NULL) {
206     // fetch the analysis libraries from the setup file
207     const char* confObjectName="analysis_libraries";
208     TObject* confObject=gDirectory->FindObject(confObjectName);
209     if (confObject) {
210       TString analysisLibraries(confObject->GetTitle());
211       TObjArray* pTokens=analysisLibraries.Tokenize(" ");
212       if (pTokens) {
213         for (int i=0; i<pTokens->GetEntriesFast(); i++) {
214           if (libraries.Contains(pTokens->At(i)->GetName())==0) {
215             libraries+=" ";
216             libraries+=pTokens->At(i)->GetName();
217           }
218         }
219         delete pTokens;
220       }
221     }
222   }
223   TObjArray* pTokens=libraries.Tokenize(" ");
224   if (pTokens) {
225     for (int i=0; i<pTokens->GetEntriesFast(); i++) {
226       if (gSystem->Load(pTokens->At(i)->GetName())==0) {
227         cout << "loading " << pTokens->At(i)->GetName() << endl;
228       }
229     }
230     delete pTokens;
231   }
232
233   TString taskNames=tasknames;
234   TString taskClasses="";
235   TString taskSources="";
236   TString taskHeaders="";
237   TString addTaskMacros="";
238   TString parPackages="";
239   TObjArray* pTaskNames=taskNames.Tokenize(" ");
240   if (pTaskNames) {
241     for (int iTaskName=0; iTaskName<pTaskNames->GetEntriesFast(); iTaskName++) {
242       TString taskSource=pTaskNames->At(iTaskName)->GetName();
243       TString taskHeader=pTaskNames->At(iTaskName)->GetName();
244       bool bIsAddTask=false;
245       if (taskSource.EndsWith(".C")) {
246         // suppose that's an 'AddTask' macro
247         taskHeader="";
248         bIsAddTask=true;
249       } else if (taskSource.EndsWith(".par")) {
250         // par file
251         if (gSystem->AccessPathName(taskSource)!=0) {
252           ::Error("run_single_task", Form("par file '%s' not found in current directory, you might want to set a symbolic link", taskSource.Data()));
253           return;
254         }
255         parPackages+=" ";
256         parPackages+=taskSource;
257         continue;
258       } else if (taskSource.EndsWith(".h")) {
259         taskSource.ReplaceAll(".h", "");
260         taskClasses+=" ";
261         taskClasses+=taskSource;
262         taskSource+=".cxx";
263       } else if (taskSource.EndsWith(".cxx")) {
264         taskHeader.ReplaceAll(".cxx", "");
265         taskClasses+=" ";
266         taskClasses+=taskHeader;
267         taskHeader+=".h";
268       } else {
269         taskClasses+=" ";
270         taskClasses+=taskSource;
271         taskSource+=".cxx";
272         taskHeader+=".h";
273       }
274       TString dependencyHeader;
275       TString dependencySource;
276       if (gSystem->AccessPathName(taskHeader)==0) {
277         GetIncludeHeaders(taskHeader, dependencyHeader, libraries);
278         taskHeaders+=" "; taskHeaders+=taskHeader;
279       }
280       if (gSystem->AccessPathName(taskSource)==0) {
281         GetIncludeHeaders(taskSource, dependencyHeader, libraries);
282         if (!bIsAddTask) {taskSources+=" "; taskSources+=taskSource;}
283         else {addTaskMacros+=" "; addTaskMacros+=taskSource;}
284       }
285       TObjArray* pTokens=dependencyHeader.Tokenize(" ");
286       if (pTokens) {
287         for (int i=0; i<pTokens->GetEntriesFast(); i++) {
288           TString sourceFile=pTokens->At(i)->GetName();
289           sourceFile.ReplaceAll(".h", ".cxx");
290           if (gSystem->AccessPathName(sourceFile)!=0) continue;
291           if (!dependencySource.IsNull()) dependencySource+=" ";
292           dependencySource+=sourceFile;
293           if (!libraries.IsNull()) libraries+=" ";
294           libraries+=sourceFile;
295         }
296         delete pTokens;
297       }
298       dependencySource.ReplaceAll(taskSource, "");
299       dependencyHeader.ReplaceAll(taskHeader, "");
300     }
301     delete pTaskNames;
302   }
303   cout << "Tasks: " << taskClasses << endl;
304   cout << "Task files: " << taskSources << addTaskMacros << taskHeaders << endl;
305   cout << "Dependency classes: " << dependencySource << endl;
306   cout << "Dependency headers: " << dependencyHeader << endl;
307   cout << "Dependency libraries: " << libraries << endl;
308   cout << "Packages: " << parPackages << endl;
309
310   ///////////////////////////////////////////////////////////////////////////////////////////////////
311   ///////////////////////////////////////////////////////////////////////////////////////////////////
312   ///////////////////////////////////////////////////////////////////////////////////////////////////
313   //
314   // init for local or GRID analysis
315   //
316   AliAnalysisAlien *alienHandler = NULL; // for grid analysis
317   TChain *chain=NULL; // for local analysis
318   TString strInput=input;
319   if (bRunLocal) {
320     ///////////////////////////////////////////////////////////////////////////////////////////////////
321     //
322     // local analysis
323     //
324     if(strInput.EndsWith("AliESDs.root")){
325       // suppose it's a single ESD file
326       chain = new TChain("esdTree"); 
327       chain->Add(strInput);
328     } else if(strInput.EndsWith(".txt")) {
329       // Constructs chain from filenames in *.txt
330       // in the form $DIR/AliESDs.root  
331       gROOT->LoadMacro("$ALICE_ROOT/PWG0/CreateESDChain.C");
332       // chain can contain up to 200 files, value can be modified to 
333       // include a subset of what the *txt file contains
334       chain = CreateESDChainf(strInput.Data(),200); 
335
336       // check if the files are on grid
337       TIter next(chain->GetListOfFiles());
338       TChainElement *chEl = 0;
339       while(( chEl = (TChainElement*)next() )){
340         TString tmp = chEl->GetTitle();     
341         if(tmp.BeginsWith("alien://")) {
342           TGrid::Connect("alien://");
343           break;
344         }
345       }
346     } else if(strInput.EndsWith("AOD")){
347       // fetch aod tree from the setup macro
348       if (gDirectory!=NULL) {
349         const char* aodTreeName="aodTree";
350         TObject* chainObject=gDirectory->FindObject(aodTreeName);
351         if (chainObject) {
352           chain=dynamic_cast<TChain*>(chainObject);
353         }
354       }
355       if (!chain) {
356         ::Error("run_single_task", Form("failed to fetch aod tree object from setup; the chain with name '%s' has to be created before calling this macro", aodTreeName));
357         return;
358       }
359     } else {
360       ::Error("run_single_task", Form("invalid input"));
361       return;
362     }
363   } else {
364     ///////////////////////////////////////////////////////////////////////////////////////////////////
365     //
366     // grid analysis
367     //
368     bool bSetRun=true;
369     TString strInput(input);
370     if (!strInput.IsDigit()) {
371       // support for external macros specifying the the runs to be
372       // analyzed
373       // the input is expected to be an external plugin with name 'input'
374       // and all run numbers being set
375       TObject* pObj=gDirectory->FindObject(input);
376       if (pObj) alienHandler=dynamic_cast<AliAnalysisAlien*>(pObj);
377       if (!alienHandler) {
378         ::Error("run_single_task", Form("can not find plugin of name '%s', please setup alien handler with name and run numbers before calling this macro", input));
379         return;
380       }
381       bSetRun=false;
382     } else {
383       alienHandler=new AliAnalysisAlien();
384     }
385     if (!alienHandler) {
386       ::Error("run_single_task", Form("failed to create alien handler"));
387       return;
388     }
389
390     // do not check for copying to grid (CLOSE_SE)
391     alienHandler->SetCheckCopy(kFALSE);
392
393     // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
394     alienHandler->SetRunMode(mode);
395   
396     // check the versions available on alien with the command 'packages'
397     alienHandler->SetAPIVersion(alienAPIVersion);
398     alienHandler->SetROOTVersion(alienROOTVersion);
399     alienHandler->SetAliROOTVersion(alienAliROOTVersion);
400
401     //Allow non-default outputs
402     //This is required to set non-default output files with the SetOutputFiles
403     //function below
404     alienHandler->SetDefaultOutputs(kFALSE);
405     if (user && user[0]!=0) alienHandler->SetUser(user);
406
407     // data alien directory
408     alienHandler->SetGridDataDir(gridDataDir);
409   
410     // Set data search pattern
411     alienHandler->SetDataPattern(dataPattern);
412     alienHandler->SetFriendChainName(friendDataPattern);
413
414     TObjArray* packageTokens=parPackages.Tokenize(" " );
415     if (packageTokens) {
416       for (int iPackageToken=0; iPackageToken<packageTokens->GetEntriesFast(); iPackageToken++) {
417         alienHandler->EnablePackage(packageTokens->At(iPackageToken)->GetName());
418       }
419       delete packageTokens;
420     }
421
422     if (bSetRun) {
423       // only set if input is a run number
424       if (!useMC && !strInput.BeginsWith("000"))
425         alienHandler->SetRunPrefix("000");   // real data
426
427       alienHandler->AddRunNumber(input);
428     }
429
430     // define working and output directories
431     TDatime dt;
432     if(odir.IsNull())
433       odir=(Form("gridwork/%04d-%02d-%02d_%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute()));
434     cout << odir << endl;
435     alienHandler->SetGridWorkingDir(odir); // relative to $HOME
436     alienHandler->SetGridOutputDir("output");   // relative to working dir
437     //alienHandler->SetOverwriteMode();                // overwrites the contents of the working and output directory
438
439     // workaround for a Root feature: GetIncludePath() appends always
440     // the current Root include path including escaped quotes. Those
441     // quotes make it difficult to pass the output directly. Search for the
442     // last appended include path and truncate
443     TString strIncludePath(gSystem->GetIncludePath());
444     Int_t pos=strIncludePath.Index(includePath);
445     if (pos>=0) {
446       Int_t cut=0;
447       do {
448         cut=pos+strlen(includePath);
449       } while ((pos=strIncludePath.Index(includePath, cut))>cut);
450       strIncludePath.Resize(cut);
451     }
452     alienHandler->AddIncludePath(strIncludePath);
453
454     // Note: there is no extra source or header file to be transferred if 'AddTask' macros are used
455     alienHandler->SetAnalysisSource(Form("%s %s %s %s", dependencySource.Data(), dependencyHeader.Data(), taskSources.Data(), taskHeaders.Data()));
456     alienHandler->SetAdditionalLibs(Form("%s %s %s", libraries.Data(), taskHeaders.Data(), dependencyHeader.Data()));
457
458     alienHandler->SetOutputFiles(ofile);
459
460     // Optionally define the files to be archived.
461     alienHandler->SetOutputArchive("log_archive.zip:stdout,stderr");
462   
463     // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
464     TString macroName; macroName.Form("run_%s.C",analysisName); macroName.ReplaceAll("-","_");
465     alienHandler->SetAnalysisMacro(macroName);
466   
467     //alienHandler->SetExecutable("comparison.sh");
468     alienHandler->SetExecutable(Form("run_%s.sh",analysisName));
469
470     alienHandler->SetSplitMaxInputFileNumber(100);
471   
472     // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
473     alienHandler->SetMaxInitFailed(10);
474   
475     // Optionally resubmit threshold.
476     alienHandler->SetMasterResubmitThreshold(90); // in %
477
478     alienHandler->SetTTL(86400);// in sec
479   
480     // Optionally set input format (default xml-single)
481     alienHandler->SetInputFormat("xml-single");
482  
483     // Optionally modify the name of the generated JDL (default analysis.jdl)
484     alienHandler->SetJDLName(Form("run_%s.jdl",analysisName));
485  
486     // Optionally modify job price (default 1)
487     alienHandler->SetPrice(1);
488   
489     // Optionally modify split mode (default 'se')
490     alienHandler->SetSplitMode("se");
491   
492     // comment out the next line when using the "terminate" option, unless
493     // you want separate merged files for each run
494     if (strcmp(mode, "terminate")==0) {
495       alienHandler->SetMergeViaJDL(kFALSE);
496     }
497
498     alienHandler->SetOneStageMerging(kFALSE);
499     alienHandler->SetMaxMergeStages(2);
500   }
501
502   // Connect plugin to the analysis manager
503   if (alienHandler) {
504     pManager->SetGridHandler(alienHandler);
505   }
506
507   ///////////////////////////////////////////////////////////////////////////////////////////////////
508   ///////////////////////////////////////////////////////////////////////////////////////////////////
509   ///////////////////////////////////////////////////////////////////////////////////////////////////
510   //
511   // create task from the name, create output container, connect slots
512   //
513   TObjArray* taskClassTokens=taskClasses.Tokenize(" ");
514   if (taskClassTokens) {
515     for (int iTaskClassToken=0; iTaskClassToken<taskClassTokens->GetEntriesFast(); iTaskClassToken++) {
516       AliAnalysisTaskSE *pTask=NULL;
517       TString taskName=taskClassTokens->At(iTaskClassToken)->GetName();
518       taskName.ReplaceAll(".cxx", "");
519       TClass* pCl=TClass::GetClass(taskName);
520       if (!pCl) {
521         cerr << "can not load class " << taskName << endl;
522         return;
523       }
524       TObject* p=pCl->New();
525       if (!p) {
526         cerr << "failed to instantiate class " << taskName << endl;
527         return;
528       }
529       pTask=reinterpret_cast<AliAnalysisTaskSE*>(p);
530       pManager->AddTask(pTask);
531       AliAnalysisDataContainer *pContainer=pManager->CreateContainer(analysisName ,TObject::Class(), AliAnalysisManager::kOutputContainer, ofile);       
532       pManager->ConnectInput(pTask,0,pManager->GetCommonInputContainer());
533       pManager->ConnectOutput(pTask,1,pContainer);
534     }
535     delete taskClassTokens;
536   }
537   TObjArray* taskMacroTokens=addTaskMacros.Tokenize(" ");
538   if (taskMacroTokens) {
539     for (int iTaskMacroToken=0; iTaskMacroToken<taskMacroTokens->GetEntriesFast(); iTaskMacroToken++) {
540       taskSource+="+g";
541       TString configuration;
542       configuration.Form("name=%s file=%s %s", analysisName, ofile.Data(), useMC?"mc":"");
543       if (gDirectory) gDirectory->Add(new TNamed("run_single_task_configuration", configuration.Data()));
544       gROOT->Macro(taskMacroTokens->At(iTaskMacroToken)->GetName());
545     }
546     delete taskMacroTokens;
547   }
548
549   ///////////////////////////////////////////////////////////////////////////////////////////////////
550   ///////////////////////////////////////////////////////////////////////////////////////////////////
551   ///////////////////////////////////////////////////////////////////////////////////////////////////
552   //
553   // run
554   //
555   
556   if (!pManager->InitAnalysis()) {
557     cerr << "failed to initialize analysis" << endl;
558     return;
559   }
560   if (nevents<0) nevents=1000000000;
561   pManager->PrintStatus();
562   if (bRunLocal) {
563     pManager->StartAnalysis("local", chain, nevents);
564   } else {
565     pManager->StartAnalysis("grid", nevents);
566   }
567 }
568
569 TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass)
570 {
571   // scan the file and add all include headers found by path
572   // to the parameter headers
573   ifstream input(filename);
574   if (input.bad()) {
575     cerr << "failed to open file " << filename << endl;
576     return headers;
577   }
578   TString line; 
579   while (!line.ReadLine(input).eof()) {
580     if (!line.Contains("#include") || !line.Contains(".h")) continue;
581     line=line(0, line.Index(".h"));line+=".h";
582     line.Replace(0, line.Index("#include"), "");
583     line.ReplaceAll("#include", "");
584     line.ReplaceAll(" ", "");
585     line.ReplaceAll("\"", "");
586     if (!line.BeginsWith("Ali") && !line.BeginsWith("T")) continue;
587     if (gSystem->AccessPathName(line)!=0) {
588       // not an include file in the current directory, check if class
589       // is available or find library
590       line.ReplaceAll(".h","");
591       //cout << "checking class " << line << endl;
592       if (TClass::GetClass(line)==NULL) {
593         TString command;
594         TString resfilename(gSystem->TempDirectory()); resfilename+="/findlib.txt";
595         command.Form("for lib in $ALICE_ROOT/lib/*/lib*.so; do (nm $lib | grep %s | grep ' T ' | grep Class_Name > /dev/null) && echo $lib > %s; done", line.Data(), resfilename.Data());
596         gSystem->Exec(command);
597         ifstream resfile(resfilename.Data());
598         if (resfile.good()) {
599           TString result;
600           if (!result.ReadLine(resfile).eof()) {
601             Ssiz_t haveSlash=-1;
602             while ((haveSlash=result.First('/'))>=0) result.Replace(0, haveSlash+1, "");
603             if (!libs.Contains(result)) {
604               cout << "loading dependency library '" << result << "' for class '" << line << "'" << endl;
605               gSystem->Load(result);
606               if (!libs.IsNull()) libs+=" ";
607               libs+=result;
608             }
609           }
610           command="rm "; command+=resfilename;
611           gSystem->Exec(command);
612         }
613       }
614     } else {
615       if (headers.Contains(line)) {
616         if (!headers.BeginsWith(line)) {
617           headers.ReplaceAll(line, "");
618           if (!headers.IsNull()) headers.Insert(0, " ");
619           if (macroVerbosity>0) cout << "moving " << line << endl;
620           headers.Insert(0, line);
621         }
622         continue;
623       }
624       if (!headers.IsNull()) headers.Insert(0, " ");
625       if (macroVerbosity>0) cout << "inserting " << line << endl;
626       headers.Insert(0, line);
627       TString source=line; source.ReplaceAll(".h", ".cxx");
628       if (gSystem->AccessPathName(source)==0) {
629         GetIncludeHeaders(source, headers, libs);
630       }
631       GetIncludeHeaders(line, headers, libs);
632       if (loadClass && gSystem->AccessPathName(source)==0) {
633         line.ReplaceAll(".h", "");
634         if (TClass::GetClass(line)==NULL) {
635           source+="+g";
636           gROOT->LoadMacro(source);
637         }
638       }
639     }
640   }
641
642   return headers;
643 }
644
645 void ErrorConfigurationFile(const char* fileName) {
646   cout << endl;
647   cout << "/// -------------------------------------------------------------------" << endl;
648   cout << "/// Warning: can not find configuration file '" << fileName << "'" << endl;
649   cout << "/// please create a configuration file in either local or HOME directory, or in" << endl;
650   cout << "/// specified location. Below is an example, fill in your preferred defaults." << endl;
651   cout << "/// -------------------------------------------------------------------" << endl;
652   cout << endl;
653   cout << "const char* alienAPIVersion=\"V1.1x\";" << endl;
654   cout << "const char* alienROOTVersion=\"v5-33-02a\";" << endl;
655   cout << "const char* alienAliROOTVersion=\"v5-01-Rev-29\";" << endl;
656   cout << "const char* defaultGridDataDir=\"/alice/data/2011/LHC11f\";" << endl;
657   cout << "const char* defaultDataPattern=\"*ESDs.root\";" << endl;
658   cout << "const char* defaultFriendDataPattern=\"\";" << endl;
659   cout << "{} // note this empty body";
660   cout << endl;
661 }