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