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