]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/trains/TrainSetup.C
Fixed references from PWG2 -> PWGLF - very efficiently done using ETags.
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / trains / TrainSetup.C
1 /**
2  * @defgroup pwglf_forward_trains Trains
3  * 
4  * @ingroup pwglf_forward
5  */
6 /**
7  * @file   TrainSetup.C
8  * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
9  * @date   Wed Mar 23 12:12:00 2011
10  * 
11  * @brief  
12  * 
13  * @ingroup pwglf_forward_trains
14  * 
15  */
16
17 #ifndef __CINT__
18 #include <fstream>
19 #include <iostream>
20
21 #include <TAlienCollection.h>
22 #include <TArrayI.h>
23 #include <TChain.h>
24 #include <TDatime.h>
25 #include <TEnv.h>
26 #include <TFile.h>
27 #include <TGrid.h>
28 #include <TList.h>
29 #include <TObjString.h>
30 #include <TProof.h>
31 #include <TString.h>
32 #include <TSystem.h>
33 #include <TSystemDirectory.h>
34 #include <TSystemFile.h>
35 #include <TROOT.h>
36
37 #include <AliAODHandler.h>
38 #include <AliAODInputHandler.h>
39 #include <AliAnalysisDataContainer.h>
40 #include <AliAnalysisManager.h>
41 #include <AliAnalysisAlien.h>
42 #include <AliESDInputHandler.h>
43 #include <AliMCEventHandler.h>
44 #include <AliVEventHandler.h>
45 #include <AliPhysicsSelection.h>
46 #include <AliCentralitySelectionTask.h>
47 #else
48 class TArrayI;
49 class TChain;
50 class AliAnalysisManager;
51 #endif
52
53 //====================================================================
54 /** 
55  * Generic set-up of an analysis train using the grid-handler (AliEn plugin). 
56  * 
57  * Users should define a class that derives from this.  The class
58  * should implement the member function CreateTasks to add needed
59  * tasks to the train
60  * 
61  * @code 
62  * // MyTrain.C 
63  * class MyTrain : public TrainSetup
64  * {
65  * public:
66  *   MyTrain(Bool_t   dateTime = false, 
67  *           UShort_t year     = 0, 
68  *           UShort_t month    = 0, 
69  *           UShort_t day      = 0, 
70  *           UShort_t hour     = 0, 
71  *           UShort_t min      = 0) 
72  *     : TrainSetup("My train", dateTime, year, month, day, hour, min)
73  *   {}
74  *   void Run(const char* type, const char* mode, const char* oper, 
75  *            Int_t nEvents=-1, Bool_t mc=false,
76  *            Bool_t usePar=false)
77  *   {
78  *     Exec(type, mode, oper, nEvents, mc, usePar);
79  *   }
80  * protected:
81  *   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
82  *   {
83  *     AliAnalysisManager::SetCommonFileName("my_analysis.root");
84  *     LoadLibrary("MyAnalysis", mode, par, true);
85  *     Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
86  *     gROOT->Macro("MyAnalysis.C");
87  *   }
88  * };
89  * @endcode 
90  * 
91  * This can then be run like 
92  * 
93  * @verbatim 
94  * > aliroot 
95  * Root> .L TrainSetup.C 
96  * Root> .L MyTrain.C 
97  * Root> MyTrain t;
98  * Root> t.Run();
99  * @endverbatim 
100  * 
101  * or as a script 
102  * 
103  * @code 
104  * {
105  *   gROOT->LoadMacro("TrainSetup.C");
106  *   gROOT->LoadMacro("MyTrain.C");
107  *   MyTrain t;
108  *   t.Run();
109  * }
110  * @endcode 
111  * 
112  * To byte compile this, you need to 
113  * - load the ROOT AliEn library
114  * - load the analysis libraries 
115  * - add $ALICE_ROOT/include to header search 
116  * first 
117  *
118  * @verbatim 
119  * > aliroot 
120  * Root> gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2:"
121  * Root>                          "$ALICE_ROOT/ANALYSIS/macros",
122  * Root>                          gROOT->GetMacroPath()));
123  * Root> gSystem->AddIncludePath("-I${ALICE_ROOT}/include");
124  * Root> gSystem->Load("libRAliEn");
125  * Root> gSystem->Load("libANALYSIS");
126  * Root> gSystem->Load("libANALYSISalice");
127  * Root> gROOT->LoadMacro("TrainSetup.C+");
128  * @endverbatim 
129  * 
130  * 
131  * @ingroup pwglf_forward_trains
132  * 
133  */
134 struct TrainSetup
135 {
136   /** 
137    * Data type to process 
138    */
139   enum EType { 
140     /** Event Summary Data */
141     kESD, 
142     /** Analysis Object Data */
143     kAOD
144   };
145   /**
146    * How to run the analysis
147    * 
148    */
149   enum EMode {
150     /** Locally */ 
151     kLocal = 1, 
152     /** In PROOF(-Lite) cluster */
153     kProof, 
154     /** On the Grid */
155     kGrid 
156   };
157   /**
158    * What stage of the analysis to run 
159    * 
160    */
161   enum EOper { 
162     /** Testing.  Local processing, a single copied from Grid */
163     kTest, 
164     /** Off-line */
165     kOffline, 
166     /** Submit to queue */
167     kSubmit, 
168     /** Merge and terminate */
169     kTerminate, 
170     /** Full run */
171     kFull
172   };
173
174   //__________________________________________________________________
175   /** 
176    * Constructor 
177    * 
178    * @param name         Name of analysis (free-form)
179    * @param useDateTime  Whether to append date and time to the name 
180    * @param year         Year - if not specified, taken from current date
181    * @param month        Month - if not specified, taken from current date 
182    * @param day          Day - if not specified, taken from current date 
183    * @param hour         Hour - if not specified, taken from current time  
184    * @param min          Minute - if not specified, taken from current time  
185    */
186   TrainSetup(const char* name, Bool_t useDateTime=true, 
187              UShort_t year=0, UShort_t month=0, 
188              UShort_t day=0, UShort_t hour=0, UShort_t min=0) 
189     : fName(name),
190       fRootVersion("v5-28-00a"),
191       fAliRootVersion("v4-21-18-AN"),
192       fAliEnAPIVersion("V1.1x"),
193       fProofServer("alicecaf.cern.ch"),
194       fDataDir("/alice/data/2010/LHC10c"),
195       fDataSet("/COMMON/COMMON/LHC09a4_run8100X#/esdTree"),
196       fXML(""), 
197       fRunNumbers(0),
198       fListOfPARs(),
199       fListOfSources(),
200       fListOfLibraries(),
201       fListOfExtras(),
202       fNReplica(4),
203       fESDPass(3),
204       fPassPostfix(""),
205       fEscapedName(name),
206       fAllowOverwrite(kFALSE),
207       fUseGDB(kFALSE)
208   {
209     char  c[] = { ' ', '/', '@', 0 };
210     char* p   = c;
211     while (*p) { 
212       fEscapedName.ReplaceAll(Form("%c", *p), "_");
213       p++;
214     }
215
216     if (useDateTime) { 
217       if (year == 0 || month == 0 || day == 0) {
218         TDatime now;
219         year  = now.GetYear();
220         month = now.GetMonth();
221         day   = now.GetDay();
222         hour  = now.GetHour();
223         min   = now.GetMinute();
224       }
225       fEscapedName.Append(Form("_%04d%02d%02d_%02d%02d", 
226                                year, month, day, hour, min));
227     }
228
229   }
230
231   //__________________________________________________________________
232   /** 
233    * Parse a string into a type enum
234    * 
235    * @param type String to pass
236    * 
237    * @return Enumaration value 
238    */
239   static EType ParseType(const char* type, Bool_t& /*mc*/)
240   {
241     // mc = false;
242     TString sType(type);
243     sType.ToUpper();
244     EType eType = kESD;
245     // if      (sType.Contains("MC"))    mc    = true;
246     if      (sType.Contains("ESD"))   eType = kESD; 
247     else if (sType.Contains("AOD"))   eType = kAOD;
248     else 
249       Fatal("Run", "Unknown type '%s'", type);
250     
251     return eType;
252   }
253   //__________________________________________________________________
254   /** 
255    * Return a string that reflects the passed mode
256    * 
257    * @param eMode Mode 
258    * 
259    * @return String representation of mode 
260    */
261   static const char* ModeString(EMode eMode) 
262   {
263     switch (eMode) {
264     case kLocal:        return "LOCAL";
265     case kProof:        return "PROOF";
266     case kGrid:         return "GRID";
267     }
268     return 0;
269   }
270   //__________________________________________________________________
271   /** 
272    * Parse a string for mode specifier 
273    * 
274    * @param mode Mode string
275    * 
276    * @return EMode value
277    */
278   static EMode ParseMode(const char* mode)
279   {
280     TString sMode(mode);
281     sMode.ToUpper();
282     EMode eMode = kLocal;
283     if      (sMode == "LOCAL") eMode = kLocal;
284     else if (sMode == "PROOF") eMode = kProof;
285     else if (sMode == "GRID")  eMode = kGrid;
286     else 
287       Fatal("Run", "Unknown mode '%s'", mode);
288     return eMode;
289   }
290
291   //__________________________________________________________________
292   /** 
293    * Return a string that reflects the passed operation
294    * 
295    * @param eOper Operation
296    * 
297    * @return String representation of operation 
298    */
299   static const char* OperString(EOper eOper) 
300   {
301     switch (eOper) {
302     case kTest:         return "TEST";
303     case kOffline:      return "OFFLINE";
304     case kSubmit:       return "SUBMIT";
305     case kTerminate:    return "TERMINATE";
306     case kFull:         return "FULL";
307     }
308     return 0;
309   }
310   //__________________________________________________________________
311   /** 
312    * Parse an operation string 
313    * 
314    * @param oper Operation 
315    * 
316    * @return An EOper value
317    */
318   static EOper ParseOperation(const char* oper)
319   {
320     TString sOper(oper);
321     sOper.ToUpper();
322     EOper eOper = kFull;
323     if      (sOper == "TEST")      eOper = kTest;
324     else if (sOper == "OFFLINE")   eOper = kOffline;
325     else if (sOper == "SUBMIT")    eOper = kSubmit;
326     else if (sOper == "TERMINATE") eOper = kTerminate;
327     else if (sOper == "FULL")      eOper = kFull;
328     else 
329       Fatal("Run", "unknown operation '%s'", oper);
330     return eOper;
331   }
332
333   //__________________________________________________________________
334   /** 
335    * Set ROOT version to use 
336    * 
337    * @param v Version string of ROOT 
338    */
339   void SetROOTVersion(const char* v)    { fRootVersion = v; }
340   //__________________________________________________________________
341   /** 
342    * Set AliROOT version to use 
343    * 
344    * @param v Version string of AliROOT 
345    */
346   void SetAliROOTVersion(const char* v) { fAliRootVersion = v; }
347   //__________________________________________________________________
348   /** 
349    * Set the PROOF server URL
350    * 
351    * @param s PROOF server URL 
352    */
353   void SetProofServer(const char* s)    { fProofServer = s; }
354   //__________________________________________________________________
355   /** 
356    * Set the GRID/Local data dir 
357    * 
358    * @param d Directory with data 
359    */
360   void SetDataDir(const char* d) { fDataDir = d; }
361   //__________________________________________________________________
362   /** 
363    * Set the PROOF data set 
364    * 
365    * @param d PROOF registered data set 
366    */
367   void SetDataSet(const char* d) { fDataSet = d; }
368   //__________________________________________________________________
369   /** 
370    * Set the XML file to use 
371    * 
372    * @param x XML file 
373    */
374   void SetXML(const char* x) { fXML = x; }
375   //__________________________________________________________________
376   /** 
377    * Set how many replicas of the output we want 
378    * 
379    * @param n Number of replicas requested 
380    */
381   void SetNReplica(Int_t n) { fNReplica = n; }
382   /** 
383    * Set the ESD pass to use 
384    * 
385    * @param pass Pass number 
386    */
387   void SetESDPass(Int_t pass) { fESDPass = pass; }
388   /** 
389    * Set the ESD pass to use 
390    * 
391    * @param postfix Post fix to pass number 
392    */
393   void SetPassPostfix(const char* postfix) { fPassPostfix = postfix; }
394   //__________________________________________________________________
395   /** 
396    * Use GDB to wrap PROOF slaves 
397    * 
398    * @param use Whether to use GDB or not 
399    */
400   void SetUseGDB(Bool_t use=kTRUE) { fUseGDB = use; }
401   //__________________________________________________________________
402   /** 
403    * Add a source file to be copied and byte compiled on slaves 
404    * 
405    * @param src          Sources 
406    * @param addToExtra   If false, do not copy 
407    */
408   void AddSource(const char* src, bool addToExtra=true) 
409   { 
410     fListOfSources.Add(new TObjString(src)); 
411     if (addToExtra) AddExtraFile(src); // Source code isn't copied!
412   }
413   //__________________________________________________________________
414   /** 
415    * Add binary data to be uploaded to slaves 
416    * 
417    * @param lib Name of binary file 
418    */
419   void AddLibrary(const char* lib) { fListOfLibraries.Add(new TObjString(lib));}
420   //__________________________________________________________________
421   /** 
422    * Add a run to be analysed
423    *  
424    * @param run Run number
425    */
426   void AddRun(Int_t run) 
427   {
428     Int_t i = fRunNumbers.fN; fRunNumbers.Set(i+1); fRunNumbers[i] = run;
429   }
430   //__________________________________________________________________
431   /** 
432    * Read run numbers from a file 
433    * 
434    * @param filename File name 
435    */
436   void ReadRunNumbers(const char* filename)
437   {
438     std::ifstream file(filename);
439     if (!file) 
440       Fatal("ReadRunNumbers", "Cannot read from %s", filename);
441     
442     while (!file.eof()) { 
443       Int_t run;
444       file >> run;
445       AddRun(run);
446       Char_t c;
447       file >> c;
448       if (file.bad()) break;
449     }
450     file.close();
451   }
452   //__________________________________________________________________
453   /** 
454    * Add an extra file to be uploaded to slave 
455    * 
456    * @param file Extra file to be uploaded 
457    */
458   void AddExtraFile(const char* file)
459   {
460     if (!file || file[0] == '\0') return;
461     fListOfExtras.Add(new TObjString(file));
462   }
463   //__________________________________________________________________
464   /** 
465    * Set whether to allow overwritting existing files/directories 
466    * 
467    * @param allow If true, allow overwritting files/directories
468    */
469   void SetAllowOverwrite(Bool_t allow) { fAllowOverwrite = allow; }
470   //__________________________________________________________________
471   /** 
472    * Service function to make a PAR out of a script.  
473    * 
474    * The script should contain can contain a sub-class of AliAnalysisTask. 
475    * The script will be compiled on the slaves before loading the 
476    * AliAnalysisManager.  Parts to (not) be compiled can be protected like 
477    * 
478    * @code 
479    * #ifdef BUILD_PAR
480    * // This will _only_ be compiled in the servers 
481    * #endif
482    * #ifndef BUILD_PAR
483    * // This will not be compiled in the servers 
484    * #endif
485    * @endcode
486    * 
487    * @param script Script to upload and compile in the PAR
488    * @param deps   Dependency pars 
489    * 
490    * @return true on success. 
491    */
492   static Bool_t MakeScriptPAR(const char* script, const char* deps)
493   {
494     // Get the base name 
495     TString base(gSystem->BaseName(script));
496     Int_t   idx = base.Last('.');
497     if (idx != kNPOS) base.Remove(idx);
498     Bool_t retval = true;
499     Info("MakeScriptPAR", "script=%s, base=%s", script, base.Data());
500
501     try {
502       // Check name of script file 
503       TString scr(script);
504       TString ext;
505       if      (scr.EndsWith(".C"))   ext = "C"; 
506       else if (scr.EndsWith(".cxx")) ext = "cxx";
507       else                           { ext = "C"; scr.Append(".C"); }
508       
509       // Check if we can access the file 
510       TString path = TString::Format(".:%s", TROOT::GetMacroPath());
511       char* loc = gSystem->Which(path, scr);
512       if (!loc) throw TString::Format("Script %s not found in %s", 
513                                       scr.Data(), path.Data());
514       TString full(loc);
515
516       
517       // Set-up directories 
518       if (gSystem->MakeDirectory(base) < 0) {
519         base = "";
520         throw TString::Format("Could not make directory '%s'", base.Data());
521       }
522       
523       if (gSystem->MakeDirectory(Form("%s/PROOF-INF", base.Data()))) 
524         throw TString::Format("Could not make directory %s/PROOF-INF", 
525                               base.Data());
526       
527       // Copy the script to the setup directory 
528       TString dest = TString::Format("%s/%s.%s", base.Data(),
529                                      base.Data(), ext.Data());
530       Int_t ret = gSystem->CopyFile(full, dest, true);
531       switch (ret) { 
532       case -1: throw TString::Format("Couldn't open %s for copy", scr.Data());
533       case -2: throw TString::Format("File %s exists", dest.Data());
534       case -3: throw TString::Format("Error while copying %s", scr.Data());
535       }
536       
537       // Make our build file 
538       std::ofstream build(Form("%s/PROOF-INF/BUILD.sh", base.Data()));
539       if (!build) 
540         throw TString::Format("Failed to open build shell script");
541       build << "#!/bin/sh\n"
542             << "echo BUILD.sh@`hostname`: Building " << base << "\n"
543             << "root.exe -l -b -q PROOF-INF/BUILD.C 2>&1 | tee " << base << ".log\n"
544             << "echo BUILD.sh@`hostname`: done: $?\n"
545             << std::endl;
546       build.close();
547       if (gSystem->Chmod(Form("%s/PROOF-INF/BUILD.sh", base.Data()), 0755) != 0)
548         throw TString::Format("Failed to set exectuable flags on "
549                               "%s/PROOF-INF/BUILD.sh", base.Data());
550       
551       std::ofstream util(Form("%s/PROOF-INF/UTIL.C", base.Data()));
552       if (!util) 
553         throw TString::Format("Failed to open utility script");
554       util << "void LoadROOTLibs() {\n"
555            << "  gSystem->Load(\"libVMC\");\n"
556            << "  gSystem->Load(\"libNet\");\n"
557            << "  gSystem->Load(\"libTree\");\n"
558            << "  gSystem->Load(\"libPhysics\");\n"
559            << "  gSystem->Load(\"libMinuit\");\n"
560            << "}\n\n"
561            << "void AddDep(const char* env) {\n"
562            << "  TString val(gSystem->Getenv(Form(\"%s_INCLUDE\",env)));\n"
563            << "  if (val.IsNull())\n"
564            << "    Warning(\"Add\",\"%s_INCLUDE not defined\", env);\n"
565            << "  else {\n"
566            << "    gSystem->AddIncludePath(Form(\"-I../%s\",val.Data()));\n"
567            << "  }\n"
568            << "}\n\n"
569            << "void LoadDep(const char* name) {\n"
570            << "  gSystem->AddDynamicPath(Form(\"../%s\",name));\n"
571            << "  char* full = gSystem->DynamicPathName(name,true);\n"
572            << "  if (!full) \n"
573            << "   full = gSystem->DynamicPathName(Form(\"lib%s\",name),true);\n"
574            << "  if (!full) \n"
575            << "   full = gSystem->DynamicPathName(Form(\"lib%s.so\",name),true);\n"
576            << "  if (!full) {\n"
577            << "    Warning(\"LoadDep\",\"Module %s not found\", name);\n"
578            << "    return;\n"
579            << "  }\n"
580            << "  gSystem->Load(full);\n"
581            << "}\n"
582            << std::endl;
583                   
584       std::ofstream cbuild(Form("%s/PROOF-INF/BUILD.C", base.Data()));
585       if (!cbuild) 
586         throw TString::Format("Failed to open build script");
587       cbuild << "void BUILD() {\n"
588              << "  gSystem->AddIncludePath(\"-DBUILD_PAR=1\");\n"
589              << "  gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
590              << "  LoadROOTLibs();\n";
591       TObjArray*  depList = TString(deps).Tokenize(",");
592       TIter       next(depList);
593       TObject*    dep = 0;
594       while ((dep = next())) {
595         cbuild << "  AddDep(\"" << dep->GetName() << "\");\t"
596                << "  LoadDep(\"" << dep->GetName() << "\");\n";
597       }
598       cbuild << "  // gDebug = 5;\n"
599              << "  int ret = gROOT->LoadMacro(\"" 
600              << base << "." << ext << "++g\");\n"
601              << "  if (ret != 0) Fatal(\"BUILD\",\"Failed to build\");\n"
602              << "  else Info(\"BUILD\", \"Made " << base << "\");\n"
603             << "}\n"
604             << std::endl;
605       cbuild.close();
606       
607       // Make our set-up script 
608       std::ofstream setup(Form("%s/PROOF-INF/SETUP.C", base.Data()));
609       if (!build) 
610         throw TString::Format("Failed to open setup script");
611       setup << "void SETUP() {\n"
612             << "  gROOT->LoadMacro(\"PROOF-INF/UTIL.C\");\n"
613             << "  LoadROOTLibs();\n"
614             << "  Info(\"SETUP\",\"Loading libraries\");\n";
615       next.Reset();
616       dep = 0;
617       while ((dep = next())) 
618         setup << "  LoadDep(\"" << dep->GetName() << "\");\n";
619       setup << "  gDebug = 5;\n"
620             << "  gSystem->Load(\"" << base << "_" << ext << ".so\");\n"
621             << "  gDebug = 0;\n"
622             << "  gROOT->ProcessLine(\".include " << base << "\");\n"
623             << "  gSystem->Setenv(\"" << base << "_INCLUDE\",\"" 
624             << base << "\");\n"
625             << "  Info(\"SETUP\", \"Done\");\n"
626             << "}\n"
627             << std::endl;
628       setup.close();
629
630       ret = gSystem->Exec(Form("tar -czvf %s.par %s", base.Data(),base.Data()));
631       if (ret != 0) 
632         throw TString::Format("Failed to create PAR file %s.PAR", base.Data());
633     }
634     catch (TString& e) { 
635       Error("MakeScriptPAR", e.Data()); 
636       retval = false;
637     }
638     if (!base.IsNull())
639       gSystem->Exec(Form("rm -vrf %s", base.Data()));
640     return retval;
641   }
642   //__________________________________________________________________
643   /** 
644    * Print the setup 
645    * 
646    */
647   void Print() const 
648   {
649     bool mc = AliAnalysisManager::GetAnalysisManager()
650       ->GetMCtruthEventHandler();
651     std::cout << fName << " train setup\n"
652               << std::boolalpha
653               << "  ROOT version:         " << fRootVersion    << "\n"
654               << "  AliROOT version:      " << fAliRootVersion << "\n"
655               << "  Name of proof server: " << fProofServer    << "\n"
656               << "  Grid Input directory: " << fDataDir        << "\n"
657               << "  Proof data set name:  " << fDataSet        << "\n"
658               << "  XML collection:       " << fXML            << "\n"
659               << "  Monte-Carlo input:    " << mc              << "\n"
660               << "  Storage replication:  " << fNReplica       << "\n"
661               << "  Run numbers:          " << std::flush;
662     for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
663       std::cout << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
664
665     std::cout << "\n"
666               << "  PAR files:            " << std::flush;
667     Bool_t first = true;
668     TObject* obj = 0;
669     TIter nextPar(&fListOfPARs);
670     while ((obj = nextPar())) {
671       std::cout << (first ? "" : ", ") << obj->GetName();
672       first = false;
673     }
674
675     std::cout << "\n"
676               << "  Script sources:       " << std::flush;
677     first = true;
678     TIter nextSrc(&fListOfSources);
679     while ((obj = nextSrc())) {
680       std::cout << (first ? "" : ", ") << obj->GetName();
681       first = false;
682     }
683
684     std::cout << "\n"
685               << "  Libraries to load:    " << std::flush;
686     first = true;
687     TIter nextLib(&fListOfLibraries);
688     while ((obj = nextLib())) {
689       std::cout << (first ? "" : ", ") << obj->GetName();
690       first = false;
691     }
692     std::cout << std::noboolalpha << std::endl;
693
694     AliAnalysisGrid* plugin = 
695       AliAnalysisManager::GetAnalysisManager()->GetGridHandler();
696     if (!plugin) return;
697     
698   }
699
700 protected:
701   //__________________________________________________________________
702   /** 
703    * Copy constructor 
704    * 
705    * @param o Object to copy from
706    */
707   TrainSetup(const TrainSetup& o)
708     : fName(o.fName),
709       fRootVersion(o.fRootVersion),
710       fAliRootVersion(o.fAliRootVersion),
711       fProofServer(o.fProofServer),
712       fDataDir(o.fDataDir),     
713       fDataSet(o.fDataSet),     
714       fXML(o.fXML),     
715       fRunNumbers(o.fRunNumbers),
716       fListOfPARs(),
717       fListOfSources(),
718       fListOfLibraries(),
719       fListOfExtras(),
720       fNReplica(o.fNReplica),
721       fESDPass(o.fESDPass)
722   {
723     if (isdigit(fName[0])) { 
724       Warning("TrainSetup", "Name starts with a digit, prepending 'a' to name");
725       fName = Form("a%s", fName.Data());
726     }
727     TObject* obj = 0;
728     TIter nextPar(&o.fListOfPARs);
729     while ((obj = nextPar())) fListOfPARs.Add(obj->Clone());
730     TIter nextSrc(&o.fListOfSources);
731     while ((obj = nextSrc())) fListOfSources.Add(obj->Clone());
732     TIter nextLib(&o.fListOfLibraries);
733     while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone());
734     TIter nextExa(&o.fListOfExtras);
735     while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
736   }
737   //__________________________________________________________________
738   /** 
739    * Assignment operator 
740    * 
741    * @param o Object to assign from 
742    * 
743    * @return Reference to this object. 
744    */
745   TrainSetup& operator=(const TrainSetup& o)
746   {
747     fName               = o.fName;
748     fRootVersion        = o.fRootVersion;
749     fAliRootVersion     = o.fAliRootVersion;
750     fProofServer        = o.fProofServer;
751     fDataDir            = o.fDataDir;   
752     fDataSet            = o.fDataSet;   
753     fXML                = o.fXML;       
754     fNReplica           = o.fNReplica;  
755     fESDPass            = o.fESDPass;
756     fRunNumbers         = o.fRunNumbers;
757     TObject* obj = 0;
758     TIter nextPar(&o.fListOfPARs);
759     while ((obj = nextPar())) fListOfPARs.Add(obj->Clone());
760     TIter nextSrc(&o.fListOfSources);
761     while ((obj = nextSrc())) fListOfSources.Add(obj->Clone());
762     TIter nextLib(&o.fListOfLibraries);
763     while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone());
764     TIter nextExa(&o.fListOfExtras);
765     while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
766
767     return *this;
768   }
769
770   //__________________________________________________________________
771   /** 
772    * Run this analysis 
773    * 
774    * @param type    Type of input for analysis  (kESD, kAOD)
775    * @param mode    Mode of job (kLocal, kProof, kGrid)
776    * @param oper    Operation 
777    * @param nEvents Number of events to analyse (<0 means all)
778    * @param mc      Whether to connect MC data 
779    * @param usePar  Whether to use PARs  
780    * @param dbg     Debug level
781    */
782   void Exec(const char*  type, 
783             const char*  mode="GRID", 
784             const char*  oper="FULL", 
785             Int_t        nEvents=-1, 
786             Bool_t       mc=false, 
787             Bool_t       usePar=false, 
788             Int_t        dbg=0)
789   {
790     Info("Exec", "Doing exec with type=%s, mode=%s, oper=%s, events=%d "
791          "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar);
792     EType eType = ParseType(type, mc);
793     EMode eMode = ParseMode(mode);
794     EOper eOper = ParseOperation(oper);
795
796     Exec(eType, eMode, eOper, nEvents, mc, usePar, dbg);
797   }
798
799   //__________________________________________________________________
800   /** 
801    * Run this analysis 
802    * 
803    * @param type    Type of input for analysis  (kESD, kAOD)
804    * @param mode    Mode of job (kLocal, kProof, kGrid)
805    * @param oper    Operation 
806    * @param nEvents Number of events to analyse (<0 means all)
807    * @param mc      Whether to connect MC data 
808    * @param usePar  Whether to use PARs  
809    * @param dbg     Debug level
810    */
811   void Exec(EType  type, 
812             EMode  mode, 
813             EOper  oper, 
814             Int_t  nEvents, 
815             Bool_t mc, 
816             Bool_t usePar, 
817             Int_t  dbg=0)
818   {
819     Info("Exec", "Doing exec with type=%d, mode=%d, oper=%d, events=%d "
820          "mc=%d, usePar=%d", type, mode, oper, nEvents, mc, usePar);
821
822     if (mode == kProof) usePar    = true;
823
824     Info("Exec", "Connecting in mode=%d", mode);
825     if (!Connect(mode)) return;
826
827     TString cwd = gSystem->WorkingDirectory();
828     TString nam = EscapedName();
829     Info("Exec", "Current directory=%s, escaped name=%s", 
830          cwd.Data(), nam.Data());
831     if (oper != kTerminate) { 
832       if (!fAllowOverwrite && !gSystem->AccessPathName(nam.Data())) {
833         Error("Exec", "File/directory %s already exists", nam.Data());
834         return;
835       }
836       if (gSystem->AccessPathName(nam.Data())) {
837         if (gSystem->MakeDirectory(nam.Data())) {
838           Error("Exec", "Failed to make directory '%s'", nam.Data());
839           return;
840         }
841       }
842     }
843     else {
844       if (gSystem->AccessPathName(nam.Data())) {
845         Error("Exec", "File/directory %s does not exists", nam.Data());
846         return;
847       }
848     }
849       
850     if (!gSystem->ChangeDirectory(nam.Data())) { 
851       Error("Exec", "Failed to change directory to %s", nam.Data());
852       return;
853     }
854     Info("Exec", "Made subdirectory %s, and cd'ed there", nam.Data());
855       
856     if (!LoadCommonLibraries(mode, usePar)) return;
857     
858     // --- Create analysis manager -----------------------------------
859     AliAnalysisManager *mgr  = new AliAnalysisManager(fName,"Analysis Train");
860
861     // In test mode, collect system information on every event 
862     // if (oper == kTest)  mgr->SetNSysInfo(1); 
863     if (dbg  >  0)      mgr->SetDebugLevel(dbg);
864     if (mode == kLocal) mgr->SetUseProgressBar(kTRUE, 100);
865    
866     // --- ESD input handler ------------------------------------------
867     AliVEventHandler*  inputHandler = CreateInputHandler(type);
868     if (inputHandler) mgr->SetInputEventHandler(inputHandler);
869     
870     // --- Monte-Carlo ------------------------------------------------
871     AliVEventHandler*  mcHandler = CreateMCHandler(type,mc);
872     if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
873     
874     // --- AOD output handler -----------------------------------------
875     AliVEventHandler*  outputHandler = CreateOutputHandler(type);
876     if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
877     
878     // --- Include analysis macro path in search path ----------------
879     gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
880                              cwd.Data(), gROOT->GetMacroPath()));
881
882     // --- Physics selction - only for ESD ---------------------------
883     if (type == kESD) CreatePhysicsSelection(mc, mgr);
884     
885     // --- Create centrality task ------------------------------------
886     CreateCentralitySelection(mc, mgr);
887
888     // --- Create tasks ----------------------------------------------
889     CreateTasks(mode, usePar, mgr);
890
891     // --- Create Grid handler ----------------------------------------
892     // _must_ be done after all tasks has been added
893     AliAnalysisAlien* gridHandler = CreateGridHandler(type, mode, oper);
894     if (gridHandler) mgr->SetGridHandler(gridHandler);
895     
896     // --- Create the chain ------------------------------------------
897     TChain* chain = CreateChain(type, mode, oper, mc);
898     if (mode == kLocal && !chain) {
899       Error("Exec", "No chain defined in local mode!");
900       return;
901     }
902
903     // --- Print setup -----------------------------------------------
904     Print();
905     // if (mode == kProof) {
906     // Info("Run", "Exported environment variables to PROOF slaves:");
907     // TProof::GetEnvVars()->ls();
908     // Info("Run", "Environment variables for this session:");
909     // gSystem->Exec("printenv");
910     // }
911
912     // --- Initialise the train --------------------------------------
913     if (!mgr->InitAnalysis())  {
914       gSystem->ChangeDirectory(cwd.Data());
915       Error("Run","Failed to initialise train");
916       return;
917     }
918
919     // --- Show status -----------------------------------------------
920     mgr->PrintStatus();
921
922     Long64_t ret = StartAnalysis(mgr, mode, chain, nEvents);
923
924     // Make sure we go back 
925     gSystem->ChangeDirectory(cwd.Data());
926
927     if (ret < 0) Error("Exec", "Analysis failed");
928   }
929   //__________________________________________________________________
930   /** 
931    * Start the analysis 
932    * 
933    * @param mgr       Analysis manager
934    * @param mode      Run mode
935    * @param chain     Input data (local and proof only)
936    * @param nEvents   Number of events to analyse 
937    */
938   Long64_t StartAnalysis(AliAnalysisManager* mgr, 
939                          EMode               mode, 
940                          TChain*             chain,
941                          Int_t               nEvents)
942   {
943     // --- Run the analysis ------------------------------------------
944     switch (mode) { 
945     case kLocal: 
946       if (!chain) {
947         Error("StartAnalysis", "No chain defined");
948         return -1;
949       }
950       if (nEvents < 0) nEvents = chain->GetEntries();
951       return mgr->StartAnalysis(ModeString(mode), chain, nEvents);
952     case kProof: 
953       if (fDataSet.IsNull()) {
954         if (!chain) { 
955           Error("StartAnalysis", "No chain defined");
956           return -1;
957         }
958         if (nEvents < 0) nEvents = chain->GetEntries();
959         return mgr->StartAnalysis(ModeString(mode), chain, nEvents);
960       }
961       return mgr->StartAnalysis(ModeString(mode), fDataSet);
962     case kGrid: 
963       if (nEvents < 0)
964         return mgr->StartAnalysis(ModeString(mode));
965       return mgr->StartAnalysis(ModeString(mode), nEvents);
966     }
967     // We should never get  here 
968     return -1;
969   }
970   //__________________________________________________________________
971   /** 
972    * Return the escaped name 
973    * 
974    * 
975    * @return Escaped name 
976    */
977   const TString& EscapedName() const 
978   {
979     return fEscapedName;
980   }
981   //__________________________________________________________________
982   /** 
983    * Create a grid handler 
984    * 
985    * @param type Data type
986    * @param mode Run mode 
987    * @param oper Operation 
988    * 
989    * @return Grid handler 
990    */
991   virtual AliAnalysisAlien* 
992   CreateGridHandler(EType type, EMode mode, EOper oper)
993   {
994     if (mode != kGrid) return 0;
995
996     TString name = EscapedName();
997
998     // Create the plug-in object, and set run mode 
999     AliAnalysisAlien* plugin = new AliAnalysisAlien();
1000     plugin->SetRunMode(OperString(oper));
1001     
1002     // Production mode - not used here 
1003     // plugin->SetProductionMode();
1004     
1005     // Set output to be per run 
1006     plugin->SetOutputToRunNo();
1007
1008     // Set the job tag 
1009     plugin->SetJobTag(fName);
1010
1011     // Set number of test files - used in test mode only 
1012     plugin->SetNtestFiles(1);
1013     
1014     // Set required version of software 
1015     plugin->SetAPIVersion(fAliEnAPIVersion);
1016     plugin->SetROOTVersion(fRootVersion);
1017     plugin->SetAliROOTVersion(fAliRootVersion);
1018
1019     // Keep log files 
1020     plugin->SetKeepLogs();
1021
1022     // Declare root of input data directory 
1023     plugin->SetGridDataDir(fDataDir);
1024
1025     // Data search patterns 
1026     TString pat;
1027     if (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()) {
1028       pat = "*/";
1029       plugin->SetRunPrefix("");
1030     }
1031     else {
1032       pat = Form("*ESDs/pass%d%s/*/", fESDPass, fPassPostfix.Data());
1033       plugin->SetRunPrefix("000");
1034     }
1035     pat.Append(Form("*%s.root", type == kESD ? "ESDs" : "AOD"));
1036     plugin->SetDataPattern(pat);
1037
1038     // Add the run numbers 
1039     for (Int_t i = 0; i < fRunNumbers.fN; i++) {
1040       if (fRunNumbers[i] < 0) continue; 
1041       plugin->AddRunNumber(fRunNumbers[i]);
1042     }
1043     
1044     // Set the working directory to be the trains name (with special
1045     // characters replaced by '_' and the date appended), and also set
1046     // the output directory (relative to working directory)
1047     plugin->SetGridWorkingDir(name.Data());
1048     plugin->SetGridOutputDir("output");
1049
1050     // Enable configured PARs 
1051     TIter nextPar(&fListOfPARs);
1052     TObject* parName;
1053     while ((parName = nextPar()))
1054       plugin->EnablePackage(parName->GetName());
1055     
1056     // Add sources that need to be compiled on the workers using
1057     // AcLIC. 
1058     TString addSources = SetupSources();
1059     if (!addSources.IsNull()) plugin->SetAnalysisSource(addSources.Data());
1060
1061     // Add binary libraries that should be uploaded to the workers 
1062     TString addLibs = SetupLibraries();
1063     if (!addLibs.IsNull()) plugin->SetAdditionalLibs(addLibs.Data());
1064     
1065     // Disable default outputs 
1066     plugin->SetDefaultOutputs(true);
1067
1068     // Merge parameters 
1069     plugin->SetMaxMergeFiles(20);
1070     plugin->SetMergeExcludes("AliAOD.root "
1071                             "*EventStat*.root "
1072                             "*event_stat*.root");
1073
1074     // Set number of runs per master - set to one to per run
1075     plugin->SetNrunsPerMaster(1);
1076
1077     // Loop over defined containers in the analysis manager, 
1078     // and declare these as outputs 
1079     TString listOfAODs  = "";
1080     TString listOfHists = "";
1081     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
1082     AliAnalysisDataContainer* cont = 0;
1083     TIter nextCont(mgr->GetOutputs());
1084     while ((cont = static_cast<AliAnalysisDataContainer*>(nextCont()))) {
1085       TString outName(cont->GetFileName());
1086       TString& list = (outName == "default" ? listOfAODs : listOfHists);
1087       if (outName == "default") { 
1088         if (!mgr->GetOutputEventHandler()) continue; 
1089
1090         outName = mgr->GetOutputEventHandler()->GetOutputFileName();
1091       }
1092       if (list.Contains(outName)) continue;
1093       if (!list.IsNull()) list.Append(",");
1094       list.Append(outName);
1095     }
1096     if (!mgr->GetExtraFiles().IsNull()) { 
1097       if (!listOfAODs.IsNull()) listOfAODs.Append("+");
1098       TString extra = mgr->GetExtraFiles();
1099       extra.ReplaceAll(" ", ",");
1100       listOfAODs.Append(extra);
1101    }
1102     TString outArchive = Form("stderr, stdout@disk=%d", fNReplica);
1103     if (!listOfHists.IsNull()) 
1104       outArchive.Append(Form(" hist_archive.zip:%s@disk=%d", 
1105                              listOfHists.Data(), fNReplica));
1106     if (!listOfAODs.IsNull()) 
1107       outArchive.Append(Form(" aod_archive.zip:%s@disk=%d", 
1108                              listOfAODs.Data(), fNReplica));
1109     if (listOfAODs.IsNull() && listOfHists.IsNull()) 
1110       Fatal("CreateGridHandler", "No outputs defined");
1111     // Disabled for now 
1112     // plugin->SetOutputArchive(outArchive);
1113     
1114     // Set name of generated analysis macro 
1115     plugin->SetAnalysisMacro(Form("%s.C", name.Data()));
1116     
1117     // Maximum number of sub-jobs 
1118     // plugin->SetSplitMaxInputFileNumber(25);
1119     
1120     // Set the Time-To-Live 
1121     plugin->SetTTL(70000);
1122     
1123     // Re-submit failed jobs as long as the ratio of failed jobs is
1124     // below this percentage. 
1125     plugin->SetMasterResubmitThreshold(95);
1126
1127     // Set the input format
1128     plugin->SetInputFormat("xml-single");
1129
1130     // Set the name of the generated jdl 
1131     plugin->SetJDLName(Form("%s.jdl", name.Data()));
1132
1133     // Set the name of the generated executable 
1134     plugin->SetExecutable(Form("%s.sh", name.Data()));
1135     
1136     // Set the job price !?
1137     plugin->SetPrice(1);
1138
1139     // Set whether to merge via JDL 
1140     plugin->SetMergeViaJDL(true);
1141     
1142     // Fast read otion 
1143     plugin->SetFastReadOption(false);
1144
1145     // Whether to overwrite existing output 
1146     plugin->SetOverwriteMode(true);
1147
1148     // Set the executable binary name and options 
1149     plugin->SetExecutableCommand("aliroot -b -q -x");
1150     
1151     // Split by storage element - must be lower case!
1152     plugin->SetSplitMode("se");
1153
1154     return plugin;
1155   }
1156   //__________________________________________________________________
1157   /** 
1158    * Create input handler 
1159    * 
1160    * @param type 
1161    * 
1162    * @return 
1163    */
1164   virtual AliVEventHandler* CreateInputHandler(EType type)
1165   {
1166     switch (type) {
1167     case kESD: return new AliESDInputHandler(); 
1168     case kAOD: return new AliAODInputHandler(); 
1169     }
1170     return 0;
1171   }
1172   //__________________________________________________________________
1173   /** 
1174    * Create input handler 
1175    * 
1176    * @param type  Run type (ESD or AOD)
1177    * @param mc    Assume monte-carlo input 
1178    * 
1179    * @return 
1180    */
1181   virtual AliVEventHandler* CreateMCHandler(EType type, bool mc)
1182   {
1183     if (!mc)          return 0;
1184     if (type != kESD) return 0;
1185     Info("CreateMCHandler", "Making MC handler");
1186     AliMCEventHandler* mcHandler = new AliMCEventHandler();
1187     mcHandler->SetReadTR(true); 
1188     return mcHandler;
1189   }
1190   //__________________________________________________________________
1191   /** 
1192    * Create output event handler 
1193    * 
1194    * @param type 
1195    * 
1196    * @return 
1197    */
1198   virtual AliVEventHandler* CreateOutputHandler(EType type)
1199   {
1200     AliAODHandler* ret = new AliAODHandler();
1201     switch (type) { 
1202     case kESD: 
1203       ret->SetOutputFileName("AliAOD.root");
1204       break;
1205     case kAOD: 
1206       ret->SetOutputFileName("AliAOD.pass2.root");
1207       break;
1208     }
1209     return ret;
1210   }
1211   //__________________________________________________________________
1212   /** 
1213    * Create physics selection , and add to manager
1214    * 
1215    * @param mc Whether this is for MC 
1216    * @param mgr Manager
1217    */
1218   virtual void CreatePhysicsSelection(Bool_t mc,
1219                                       AliAnalysisManager* mgr)
1220   {
1221     gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
1222     mgr->RegisterExtraFile("event_stat.root");
1223   }
1224   //__________________________________________________________________
1225   /** 
1226    * Create physics selection , and add to manager
1227    * 
1228    * @param mc Whether this is for MC 
1229    * @param mgr Manager
1230    */
1231   virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
1232   {
1233     gROOT->Macro("AddTaskCentrality.C");
1234     AliCentralitySelectionTask* ctask = 
1235       dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask("CentralitySelection"));
1236     if (!ctask) return;
1237     // ctask->SetPass(fESDPass);
1238     if (mc) ctask->SetMCInput();
1239   }
1240   //__________________________________________________________________
1241   /** 
1242    * Create analysis tasks 
1243    * 
1244    * @param mode Run mode
1245    * @param mgr  Manager
1246    * @param par  Whether to use pars 
1247    */
1248   virtual void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)=0;
1249   //__________________________________________________________________
1250   /** 
1251    * Connect to external services (Proof and/or grid)
1252    * 
1253    * @param mode Running mode 
1254    * 
1255    * @return true on success 
1256    */
1257   virtual Bool_t Connect(EMode mode)
1258   {
1259     if (mode == kLocal) return true;
1260                           
1261     // --- Set-up connections to Proof cluster and alien -------------
1262     if (mode == kProof) { 
1263       Info("Connect", "Opening connection to proof server");
1264       // --- Find user name ------------------------------------------
1265       TString userName(gSystem->Getenv("alien_API_USER"));
1266       if (userName.IsNull()) {
1267         userName = gSystem->GetUserInfo()->fUser;
1268         Warning("Connect", 
1269                 "environment variable 'alien_API_USER' not set, using %s", 
1270                 userName.Data());
1271       }
1272
1273       // --- Set prefered GSI method ---------------------------------
1274       gEnv->SetValue("XSec.GSI.DelegProxy", "2");
1275
1276       // --- Figure out some server settings -------------------------
1277       TString serv = "";
1278       Bool_t  lite = false;
1279       if (fProofServer.BeginsWith("workers=") || fProofServer.IsNull()) {
1280         lite = true;
1281         serv = fProofServer;
1282       }
1283       else 
1284         serv = Form("%s@%s", userName.Data(), fProofServer.Data());
1285
1286       // --- Possibly debug slave sessions with GDB ------------------
1287       if (fUseGDB) { 
1288         TString gdbCmd("\"gdb --batch -ex run -ex bt --args\"");
1289         Info("Connect", "Using GDB to wrap slaves: %s", gdbCmd.Data());
1290         TProof::AddEnvVar("PROOF_WRAPPERCMD", gdbCmd);
1291       }
1292       
1293       // --- Add ALICE_ROOT directory to search path for packages ----
1294       Info("Connect", "Set location of packages");
1295       gEnv->SetValue("Proof.GlobalPackageDirs", 
1296                      Form("%s:%s", 
1297                           gEnv->GetValue("Proof.GlobalPackageDirs", "."), 
1298                           gSystem->Getenv("ALICE_ROOT")));
1299                                                      
1300       // --- Set OADB path on workers --------------------------------
1301       const char* oadbPath = AliAnalysisManager::GetOADBPath();
1302       TProof::AddEnvVar("OADB_PATH", oadbPath);
1303       // if (lite) gSystem->Setenv("OADB_PATH", oadbPath);
1304       // Info("Connect", "OADB_PATH=%s", gSystem->Getenv("OADB_PATH"));
1305
1306       // --- Now open connection to PROOF cluster --------------------
1307       TProof::Open(serv);
1308       if (!gProof) { 
1309         Error("Connect", "Failed to connect to Proof cluster %s as %s",
1310               fProofServer.Data(), userName.Data());
1311         return false;
1312       }
1313       Info("Connect", "Now connected to Proof");
1314       // gProof->SetParameter("PROOF_LookupOpt", "all");
1315       if (lite) return true;
1316     }
1317
1318     // --- Open a connection to the grid -----------------------------
1319 #if 0
1320     TGrid::Connect("alien://");
1321     if (!gGrid || !gGrid->IsConnected()) { 
1322       // This is only fatal in grid mode 
1323       Error("Connect", "Failed to connect to AliEN");
1324       if (mode == kGrid) return false; 
1325       return true;
1326     }
1327     if (mode == kGrid) return true;
1328
1329     
1330     // --- Set and make output directory -----------------------------
1331     TString name = EscapedName();
1332     TString homeDir(gGrid->GetHomeDirectory());
1333     TString workDir(homeDir);
1334     workDir.Append("/");
1335     workDir.Append(name);
1336     
1337     // Make working directory 
1338     if (!gGrid->Cd(workDir)) { 
1339       gGrid->Cd(homeDir);
1340       if (gGrid->Mkdir(workDir)) {
1341         gGrid->Cd(name);
1342         Info("Connect", "Directory %s created", workDir.Data());
1343       }
1344     }
1345     // Make output directory 
1346     gGrid->Mkdir("proof_output");
1347     gGrid->Cd("proof_output");
1348 #endif
1349     return true;
1350   }       
1351   //__________________________________________________________________
1352   /** 
1353    * Load common libraries 
1354    * 
1355    * @param mode Running mode                   
1356    * @param par  If true, load as PARs 
1357    * 
1358    * @return true on success 
1359    */
1360   Bool_t LoadCommonLibraries(EMode mode, Bool_t par) 
1361   {
1362     if (!gSystem->Getenv("ALICE_ROOT")) { 
1363       Error("LoadCommonLibraries", "Local AliROOT not available");
1364       return false;
1365     }
1366     gSystem->Load("libTree.so");
1367     gSystem->Load("libGeom.so");
1368     gSystem->Load("libVMC.so");
1369     gSystem->Load("libPhysics.so");
1370     gSystem->Load("libMinuit.so");
1371     if (mode == kProof) { 
1372       gProof->Exec("gSystem->Load(\"libTree.so\");");
1373       gProof->Exec("gSystem->Load(\"libGeom.so\");");
1374       gProof->Exec("gSystem->Load(\"libMinuit.so\");");
1375       gProof->Exec("gSystem->Load(\"libVMC.so\");");
1376
1377       
1378     }
1379
1380 #if 0
1381     // We need to activate the workers here in case 
1382     // we have dynamic slaves - otherwise they won't get
1383     // the packages 
1384     if (mode == kProof) { 
1385       Info("LoadCommonLibraries", "Starting slaves");
1386       if (!gProof->StartSlaves()) { 
1387         Error("LoadCommonLibraries", "Failed to start slaves");
1388         return false;
1389       }
1390       Info("LoadCommonLibraries", "Slaves started");
1391     }
1392 #endif       
1393       
1394     Bool_t ret   = true;
1395     Bool_t basic = mode == kGrid ? false : par;
1396     
1397     ret &= LoadLibrary("STEERBase",     mode, basic, false);
1398     ret &= LoadLibrary("ESD",           mode, basic, false);
1399     ret &= LoadLibrary("AOD",           mode, basic, false);
1400     ret &= LoadLibrary("ANALYSIS",      mode, basic, true);
1401     ret &= LoadLibrary("OADB",          mode, basic, true);
1402     ret &= LoadLibrary("ANALYSISalice", mode, basic, true);
1403
1404     return ret;
1405   }
1406   //__________________________________________________________________
1407   /** 
1408    * Load a library 
1409    * 
1410    * @param what What library to load
1411    * @param mode Mode (local, proof, grid)
1412    * @param par  If true, load as PAR
1413    * @param rec  If true, also load on slaves
1414    * 
1415    * @return true on success 
1416    */
1417   Bool_t LoadLibrary(const char* what, EMode mode, Bool_t par, Bool_t rec=false)
1418   {
1419     if (!what || what[0] == '\0') return true;
1420     
1421     TString module(what);
1422     TString libName(what);
1423     if (!libName.BeginsWith("lib")) libName = Form("lib%s", libName.Data());
1424     if (!libName.EndsWith(".so"))   libName.Append(".so");
1425
1426     Int_t ret = 0;
1427
1428     switch (mode) { 
1429     case kLocal: // Just load and exit 
1430       gSystem->Load(libName.Data());
1431       break;
1432     case kGrid: 
1433       if (par) { 
1434         ret = SetupPAR(what) ? 0 : -1;
1435         if (rec) fListOfPARs.Add(new TObjString(what));
1436       } else  {
1437         ret = gSystem->Load(libName.Data());
1438         if (rec) fListOfLibraries.Add(new TObjString(libName));
1439       }
1440       break;
1441     case kProof: 
1442       Info("LoadLibrary", "Uploading %s", what);
1443       ret = gProof->UploadPackage(what, TProof::kRemoveOld);
1444       if (ret < 0)  {   
1445           ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par",
1446                                                                    what)));
1447         if (ret < 0) {  
1448           ret = 
1449             gProof->UploadPackage(gSystem
1450                                   ->ExpandPathName(Form("$ALICE_ROOT/%s.par", 
1451                                                         what)));
1452           if (ret < 0) {
1453             Error("LoadLibrary", 
1454                   "Could not find module %s.par in current directory nor "
1455                   "in $ALICE_ROOT", module.Data());
1456             return false;
1457           }
1458         }
1459       }
1460       Info("LoadLibrary", "Enabling package %s", what);
1461       ret = gProof->EnablePackage(what);
1462       break;
1463     }
1464     if (ret < 0) { 
1465       Error("LoadLibrary", "Couldn't load %s", what);
1466       return false;
1467     }
1468     return true;
1469   }
1470           
1471   //__________________________________________________________________
1472   Bool_t SetupPAR(const char* what)
1473   {
1474     if (!what || what[0] == '\0') return -1;
1475     
1476     TString parFile(Form("%s.par", what));
1477     if (gSystem->AccessPathName(parFile.Data())) { 
1478       if (gSystem->AccessPathName(Form("../%s.par", what))) { 
1479         // If not found 
1480         TString aliParFile = 
1481           gSystem->ExpandPathName(Form("$(ALICE_ROOT)/%s.par", what));
1482         if (gSystem->AccessPathName(aliParFile.Data())) { 
1483           Error("SetupPAR", "PAR file %s not found in current directory or "
1484                 "$(ALICE_ROOT)", what);
1485           return false;
1486         }
1487         // Copy to current directory 
1488         TFile::Cp(aliParFile, parFile);
1489       }
1490       else 
1491         gSystem->Exec(Form("ln -s ../%s.par .", what));
1492     }
1493     
1494     // Extract archive 
1495     gSystem->Exec(Form("tar xvzf %s", parFile.Data()));
1496     
1497     // Change directory into par archive
1498     TString cwd = gSystem->WorkingDirectory();
1499     
1500     if (!gSystem->ChangeDirectory(what)) { 
1501       Error("SetupPAR", "Failed to change directory to %s", what);
1502       return false;
1503     }
1504     
1505     // Test the build 
1506     if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
1507       Info("SetupPar", "Building in PAR archive %s", what);
1508       if (gSystem->Exec("PROOF-INF/BUILD.sh")) { 
1509         Error("SetupPar", "Failed to build in PAR directory %s", what);
1510         gSystem->ChangeDirectory(cwd.Data());
1511         return false;
1512       }
1513     }
1514     
1515     // Check for setup script
1516     if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
1517       Info("SetupPAR", "Setting up for PAR %s", what);
1518       gROOT->Macro("PROOF-INF/SETUP.C");
1519     }
1520     if (!gSystem->ChangeDirectory(cwd.Data())) return false;
1521
1522     return true;
1523   }
1524   //__________________________________________________________________
1525   TString SetupExtras()
1526   {
1527     TString ret;
1528     TIter next(&fListOfExtras);
1529     TObjString* obj = 0;
1530     while ((obj = static_cast<TObjString*>(next()))) {
1531       TString path = gSystem->ExpandPathName(obj->GetName());
1532       if (!path.BeginsWith("/")) 
1533         // If not an absolute path, prepend to up-one
1534         path = Form("../%s", path.Data());
1535       if (gSystem->AccessPathName(path.Data())) { 
1536         // File not accessible 
1537         Warning("SetupExtras", "File %s not accessible", path.Data());
1538         continue;
1539       }
1540       ret.Append(Form("%s ", gSystem->BaseName(obj->GetName())));
1541       gSystem->Exec(Form("ln -s %s .", path.Data()));
1542     }
1543     ret = ret.Strip();
1544     return ret;
1545   }
1546   //__________________________________________________________________
1547   TString SetupSources()
1548   {
1549     TString nam = EscapedName();
1550     TString ret;
1551     TIter next(&fListOfSources); 
1552     TObject* src;
1553     while ((src = next())) {
1554       TString path = gSystem->ExpandPathName(src->GetName());
1555       if (!path.BeginsWith("/")) 
1556         // If not an absolute path, prepend to up-one
1557         path = Form("../%s", path.Data());
1558       if (gSystem->AccessPathName(path.Data())) { 
1559         // File not accessible 
1560         Warning("SetupSources", "File %s not accessible", path.Data());
1561         continue;
1562       }
1563       ret.Append(Form("%s ", gSystem->BaseName(src->GetName())));
1564       gSystem->Exec(Form("ln -s %s .", path.Data()));
1565     }
1566     ret = ret.Strip();
1567     return ret;
1568   }
1569   //__________________________________________________________________
1570   TString SetupLibraries()
1571   {
1572     TString ret;
1573     TIter next(&fListOfLibraries); 
1574     TObject* lib;
1575     while ((lib = next())) {
1576       ret.Append(lib->GetName());
1577       ret.Append(" ");
1578     }
1579     // Also add extra files to this variable 
1580     ret.Append(SetupExtras());
1581     ret = ret.Strip();
1582     return ret;
1583   }
1584   //__________________________________________________________________
1585   /** 
1586    * Scan directory @a dir (possibly recursive) for tree files to add
1587    * to the chain.    This does not follow sym-links
1588    * 
1589    * @param dir        Directory to scan
1590    * @param chain      Chain to add to
1591    * @param type       Type of tree (ESD or AOD)
1592    * @param recursive  Whether to scan recursively 
1593    * @param mc         Look also for MC files if true 
1594    *
1595    * @return true if any files where added 
1596    */
1597   Bool_t ScanDirectory(TSystemDirectory* dir, TChain* chain, 
1598                        EType type, bool recursive, bool mc)
1599   {
1600     TString fnPattern;
1601     switch (type) { 
1602     case kESD:  fnPattern = "AliESD"; break;
1603     case kAOD:  fnPattern = "AliAOD"; break;
1604     }
1605
1606     // Assume failure 
1607     Bool_t ret = false;
1608
1609     // Get list of files, and go back to old working directory
1610     TString oldDir(gSystem->WorkingDirectory());
1611     TList*  files = dir->GetListOfFiles();
1612     if (!gSystem->ChangeDirectory(oldDir)) { 
1613       Error("ScanDirectory", "Failed to go back to %s", oldDir.Data());
1614       return false;
1615     }
1616     if (!files) return false;
1617
1618     TList toAdd;
1619     toAdd.SetOwner();
1620     Bool_t hasGAlice = (!mc ? true : false);
1621     Bool_t hasKine   = (!mc ? true : false);
1622     Bool_t hasTrRef  = (!mc ? true : false);
1623     
1624     // Sort list of files and check if we should add it 
1625     files->Sort();
1626     TIter next(files);
1627     TSystemFile* file = 0;
1628     while ((file = static_cast<TSystemFile*>(next()))) {
1629       TString name(file->GetName());
1630       TString title(file->GetTitle());
1631       TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data()));
1632       if (dynamic_cast<TSystemDirectory*>(file)) full = title;
1633       // Ignore special links 
1634       if (name == "." || name == "..") { 
1635         // Info("ScanDirectory", "Ignoring %s", name.Data());
1636         continue;
1637       }
1638
1639       FileStat_t fs;
1640       if (gSystem->GetPathInfo(full.Data(), fs)) {
1641         Warning("ScanDirectory", "Cannot stat %s (%s)", full.Data(),
1642                 gSystem->WorkingDirectory());
1643         continue;
1644       }
1645       // Check if this is a directory 
1646       if (file->IsDirectory(full)) { 
1647         if (recursive) {
1648           // if (title[0] == '/') 
1649           TSystemDirectory* d = new TSystemDirectory(file->GetName(),
1650                                                      full.Data());
1651           if (ScanDirectory(d,chain,type,recursive,mc))
1652             ret = true;
1653           delete d;
1654         }
1655         continue;
1656       }
1657     
1658       // If this is not a root file, ignore 
1659       if (!name.EndsWith(".root")) continue;
1660
1661       // If this file does not contain AliESDs, ignore 
1662       if (!name.Contains(fnPattern)) { 
1663         // Info("ScanDirectory", "%s does not match pattern %s", 
1664         //      name.Data(), fnPattern.Data());
1665         if (mc) { 
1666           if (name.CompareTo("galice.root") == 0)     hasGAlice = true;
1667           if (name.CompareTo("Kinematics.root") == 0) hasKine   = true;
1668           if (name.CompareTo("TrackRefs.root")  == 0) hasTrRef = true;
1669         }
1670         continue;
1671       }
1672     
1673       // Add 
1674       // Info("ScanDirectory", "Adding %s", full.Data());
1675       toAdd.Add(new TObjString(full));
1676     }
1677
1678     if (mc && toAdd.GetEntries() > 0 && 
1679         (!hasGAlice || !hasKine || !hasTrRef)) { 
1680       Warning("ScanDirectory", 
1681               "one or more of {galice,Kinematics,TrackRefs}.root missing from "
1682               "%s, not adding anything from this directory", 
1683               dir->GetTitle());
1684       toAdd.Delete();
1685     }
1686
1687     TIter nextAdd(&toAdd);
1688     TObjString* s = 0;
1689     while ((s = static_cast<TObjString*>(nextAdd()))) {
1690       // Info("ScanDirectory", "Adding %s", s->GetString().Data());
1691       chain->Add(s->GetString());
1692     }
1693     if (toAdd.GetEntries() > 0) ret = true;
1694
1695     gSystem->ChangeDirectory(oldDir);
1696     return ret;
1697   }
1698   //__________________________________________________________________
1699   /** 
1700    * Create a chain from an XML containing an collection
1701    * 
1702    * @param treeName Name of tree's 
1703    * @param xmlFile  XML collection
1704    * 
1705    * @return Newly allocated chain or null
1706    */
1707   TChain* CreateChainFromXML(const char* treeName, 
1708                              const char* xmlFile) 
1709   {
1710     TGridCollection* collection = TAlienCollection::Open(xmlFile);
1711     if (!collection) { 
1712       Error("CreateChainFromXML", "Cannot create AliEn collection from "
1713             "XML file %s", xmlFile);
1714       return 0;
1715     }
1716
1717     TChain* chain = new TChain(treeName);
1718     collection->Reset();
1719     while (collection->Next()) chain->Add(collection->GetTURL(""));
1720     
1721     return chain;
1722   }
1723   //__________________________________________________________________
1724   /** 
1725    * Create a chain of data 
1726    * 
1727    * @param type Type of data
1728    * @param mode Operation mode 
1729    * @param mc   Assume MC input if true
1730    *
1731    * @return TChain of data 
1732    */    
1733   TChain* CreateChain(EType type, EMode mode, EOper /* oper */, Bool_t mc)
1734   {
1735     TString treeName;
1736     switch (type) { 
1737     case kESD:  treeName = "esdTree"; break;
1738     case kAOD:  treeName = "aodTree"; break;
1739     }
1740
1741     TChain* chain = 0;
1742     switch (mode) { 
1743     case kProof: 
1744       if (!fDataSet.IsNull()) break; 
1745       // Otherwise fall through
1746     case kLocal:
1747       if (fXML.IsNull()) {
1748         chain = new TChain(treeName.Data());
1749         TString dir(fDataDir);
1750         if (dir == ".") dir = "";
1751         if (!dir.BeginsWith("/")) dir = Form("../%s", dir.Data());
1752         TString savdir(gSystem->WorkingDirectory());
1753         TSystemDirectory d(gSystem->BaseName(dir.Data()), dir.Data());
1754         if (!ScanDirectory(&d, chain, type, true, mc)) { 
1755           delete chain;
1756           chain = 0;
1757         }
1758         gSystem->ChangeDirectory(savdir);
1759       }
1760       else 
1761         chain = CreateChainFromXML(treeName.Data(), fXML.Data());
1762       break;
1763     case kGrid:  break; // Do nothing - we use plugin
1764     }
1765     
1766     if (chain && chain->GetNtrees() <= 0) { 
1767       delete chain;
1768       return 0;
1769     }
1770     return chain;
1771   }
1772   //__________________________________________________________________
1773   TString fName;             // Name of analysis
1774   TString fRootVersion;      // ROOT version to use 
1775   TString fAliRootVersion;   // AliROOT version to use 
1776   TString fAliEnAPIVersion;  // AliEn API version to use 
1777   TString fProofServer;      // Name of proof server
1778   TString fDataDir;          // Grid Input directory 
1779   TString fDataSet;          // Proof data set name 
1780   TString fXML;              // XML collection for local/proof mode
1781   TArrayI fRunNumbers;       // List of run number 
1782   TList   fListOfPARs;       // List of PAR files to use 
1783   TList   fListOfSources;    // List of sources to upload and AcLIC
1784   TList   fListOfLibraries;  // List of libraries to load
1785   TList   fListOfExtras;     // List of extra files to upload
1786   Int_t   fNReplica;         // Storage replication
1787   Int_t   fESDPass;          // ESD pass number 
1788   TString fPassPostfix;      // Possible pass postfix
1789   TString fEscapedName;      // Name escaped for special chars
1790   Bool_t  fAllowOverwrite;   // Allow overwriting output dir
1791   Bool_t  fUseGDB;           // Wrap PROOF slaves in GDB 
1792 };
1793
1794
1795 void
1796 BuildTrainSetup()
1797 {
1798   gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2:"
1799                            "$ALICE_ROOT/ANALYSIS/macros",
1800                            gROOT->GetMacroPath()));
1801   gSystem->AddIncludePath("-I${ALICE_ROOT}/include");
1802   gSystem->Load("libRAliEn");
1803   gSystem->Load("libANALYSIS");
1804   gSystem->Load("libANALYSISalice");
1805   TString path = gSystem->Which(gROOT->GetMacroPath(), "TrainSetup.C");
1806   Info("BuildTrainSetup", "Path=%s", path.Data());
1807   TString tmp("TrainSetup");
1808   FILE* fp = gSystem->TempFileName(tmp, ".");
1809   fclose(fp);
1810   gSystem->Unlink(tmp);
1811   tmp.Append(".C");
1812   Info("BuildTrainSetup", "Copy %s -> %s", path.Data(), tmp.Data());
1813   gSystem->CopyFile(path, tmp);
1814   gROOT->LoadMacro(Form("%s+g", tmp.Data()));
1815   gSystem->Unlink(tmp);
1816   tmp.ReplaceAll(".C", "_C.so");
1817   gSystem->Unlink(tmp);
1818   tmp.ReplaceAll("_C.so", "_C.d");
1819   gSystem->Unlink(tmp);
1820 }
1821
1822   
1823 //____________________________________________________________________
1824 //
1825 // EOF
1826 //