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