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