bb6847c0a8e48edde2804c353f825711aa424eb4
[u/mrichter/AliRoot.git] / PWG2 / FORWARD / analysis2 / TrainSetup.C
1 #ifndef __CINT__
2 #include <fstream>
3
4 #include <TAlienCollection.h>
5 #include <TArrayI.h>
6 #include <TChain.h>
7 #include <TDatime.h>
8 #include <TEnv.h>
9 #include <TFile.h>
10 #include <TGrid.h>
11 #include <TList.h>
12 #include <TObjString.h>
13 #include <TProof.h>
14 #include <TString.h>
15 #include <TSystem.h>
16 #include <TSystemDirectory.h>
17 #include <TSystemFile.h>
18 #include <TROOT.h>
19
20 #include <AliAODHandler.h>
21 #include <AliAODInputHandler.h>
22 #include <AliAnalysisDataContainer.h>
23 #include <AliAnalysisManager.h>
24 #include <AliAnalysisAlien.h>
25 #include <AliESDInputHandler.h>
26 #include <AliMCEventHandler.h>
27 #include <AliVEventHandler.h>
28 #else
29 class TArrayI;
30 class TChain;
31 class AliAnalysisManager;
32 #endif
33
34 //====================================================================
35 struct TrainSetup
36 {
37   enum EType { 
38     kESD, 
39     kAOD
40   };
41   enum EMode {
42     kLocal = 1, 
43     kProof, 
44     kGrid 
45   };
46   enum EOper { 
47     kTest, 
48     kOffline, 
49     kSubmit, 
50     kTerminate, 
51     kFull
52   };
53
54   //__________________________________________________________________
55   /** 
56    * Constructor
57    * 
58     * @param name Name of analysis 
59    */
60   TrainSetup(const char* name, UShort_t year=0, UShort_t month=0, 
61              UShort_t day=0, UShort_t hour=0, UShort_t min=0) 
62     : fName(name),
63       fRootVersion("v5-27-06b"),
64       fAliRootVersion("v4-21-13-AN"),
65       fProofServer("alicecaf.cern.ch"),
66       fDataDir("/alice/data/2010/LHC10c"),
67       fDataSet("/COMMON/COMMON/LHC09a4_run8100X#/esdTree"),
68       fXML(""), 
69       fRunNumbers(0),
70       fListOfPARs(),
71       fListOfSources(),
72       fListOfLibraries(),
73       fListOfExtras(),
74       fNReplica(4),
75       fESDPass(3),
76       fEscapedName(name)
77   {
78     char  c[] = { ' ', '/', '@', 0 };
79     char* p   = c;
80     while (*p) { 
81       fEscapedName.ReplaceAll(Form("%c", *p), "_");
82       p++;
83     }
84
85     if (year == 0 || month == 0 || day == 0) {
86       TDatime now;
87       year  = now.GetYear();
88       month = now.GetMonth();
89       day   = now.GetDay();
90       hour  = now.GetHour();
91       min   = now.GetMinute();
92     }
93     fEscapedName.Append(Form("_%04d%02d%02d_%02d%02d", 
94                              year, month, day, hour, min));
95
96   }
97
98   //__________________________________________________________________
99   /** 
100    * Parse a string into a type enum
101    * 
102    * @param type String to pass
103    * @param mc   True on return if the string contained "MC"
104    * 
105    * @return Enumaration value 
106    */
107   static EType ParseType(const char* type, Bool_t& mc)
108   {
109     mc = false;
110     TString sType(type);
111     sType.ToUpper();
112     EType eType = kESD;
113     if      (sType.Contains("MC"))    mc    = true;
114     if      (sType.Contains("ESD"))   eType = kESD; 
115     else if (sType.Contains("AOD"))   eType = kAOD;
116     else 
117       Fatal("Run", "Unknown type '%s'", type);
118     
119     return eType;
120   }
121   //__________________________________________________________________
122   /** 
123    * Return a string that reflects the passed mode
124    * 
125    * @param eMode Mode 
126    * 
127    * @return String representation of mode 
128    */
129   static const char* ModeString(EMode eMode) 
130   {
131     switch (eMode) {
132     case kLocal:        return "LOCAL";
133     case kProof:        return "PROOF";
134     case kGrid:         return "GRID";
135     }
136     return 0;
137   }
138   //__________________________________________________________________
139   /** 
140    * Parse a string for mode specifier 
141    * 
142    * @param mode Mode string
143    * 
144    * @return EMode value
145    */
146   static EMode ParseMode(const char* mode)
147   {
148     TString sMode(mode);
149     sMode.ToUpper();
150     EMode eMode = kLocal;
151     if      (sMode == "LOCAL") eMode = kLocal;
152     else if (sMode == "PROOF") eMode = kProof;
153     else if (sMode == "GRID")  eMode = kGrid;
154     else 
155       Fatal("Run", "Unknown mode '%s'", mode);
156     return eMode;
157   }
158
159   //__________________________________________________________________
160   /** 
161    * Return a string that reflects the passed operation
162    * 
163    * @param eOper Operation
164    * 
165    * @return String representation of operation 
166    */
167   static const char* OperString(EOper eOper) 
168   {
169     switch (eOper) {
170     case kTest:         return "TEST";
171     case kOffline:      return "OFFLINE";
172     case kSubmit:       return "SUBMIT";
173     case kTerminate:    return "TERMINATE";
174     case kFull:         return "FULL";
175     }
176     return 0;
177   }
178   //__________________________________________________________________
179   /** 
180    * Parse an operation string 
181    * 
182    * @param oper Operation 
183    * 
184    * @return An EOper value
185    */
186   static EOper ParseOperation(const char* oper)
187   {
188     TString sOper(oper);
189     sOper.ToUpper();
190     EOper eOper = kFull;
191     if      (sOper == "TEST")      eOper = kTest;
192     else if (sOper == "OFFLINE")   eOper = kOffline;
193     else if (sOper == "SUBMIT")    eOper = kSubmit;
194     else if (sOper == "TERMINATE") eOper = kTerminate;
195     else if (sOper == "FULL")      eOper = kFull;
196     else 
197       Fatal("Run", "unknown operation '%s'", oper);
198     return eOper;
199   }
200
201   //__________________________________________________________________
202   void SetROOTVersion(const char* v)    { fRootVersion = v; }
203   void SetAliROOTVersion(const char* v) { fAliRootVersion = v; }
204   void SetProofServer(const char* s)    { fProofServer = s; }
205   void SetDataDir(const char* d)        { fDataDir = d; }
206   void SetDataSet(const char* d)        { fDataSet = d; }
207   void SetXML(const char* x)            { fXML = x; }
208   void SetNReplica(Int_t n)             { fNReplica = n; }
209   void AddSource(const char* src, bool addToExtra=true) 
210   { 
211     fListOfSources.Add(new TObjString(src)); 
212     if (addToExtra) AddExtraFile(src); // Source code isn't copied!
213   }
214   void AddLibrary(const char* lib) { fListOfLibraries.Add(new TObjString(lib));}
215   void AddRun(Int_t run) 
216   {
217     Int_t i = fRunNumbers.fN; fRunNumbers.Set(i+1); fRunNumbers[i] = run;
218   }
219   void ReadRunNumbers(const char* filename)
220   {
221     std::ifstream file(filename);
222     if (!file) 
223       Fatal("ReadRunNumbers", "Cannot read from %s", filename);
224     
225     while (!file.eof()) { 
226       Int_t run;
227       file >> run;
228       AddRun(run);
229       Char_t c;
230       file >> c;
231       if (file.bad()) break;
232     }
233     file.close();
234   }
235   void AddExtraFile(const char* file)
236   {
237     fListOfExtras.Add(new TObjString(file));
238   }
239   //__________________________________________________________________
240   /** 
241    * Print the setup 
242    * 
243    */
244   void Print() const 
245   {
246     std::cout << fName << " train setup\n"
247               << "  ROOT version:         " << fRootVersion    << "\n"
248               << "  AliROOT version:      " << fAliRootVersion << "\n"
249               << "  Name of proof server: " << fProofServer    << "\n"
250               << "  Grid Input directory: " << fDataDir        << "\n"
251               << "  Proof data set name:  " << fDataSet        << "\n"
252               << "  XML collection:       " << fXML            << "\n"
253               << "  Storage replication:  " << fNReplica       << "\n"
254               << "  Run numbers:          " << std::flush;
255     for (Int_t i = 0; i < fRunNumbers.GetSize(); i++) 
256       std::cout << (i == 0 ? "" : ", ") << fRunNumbers.At(i);
257
258     std::cout << "\n"
259               << "  PAR files:            " << std::flush;
260     Bool_t first = true;
261     TObject* obj = 0;
262     TIter nextPar(&fListOfPARs);
263     while ((obj = nextPar())) {
264       std::cout << (first ? "" : ", ") << obj->GetName();
265       first = false;
266     }
267
268     std::cout << "\n"
269               << "  Script sources:       " << std::flush;
270     first = true;
271     TIter nextSrc(&fListOfSources);
272     while ((obj = nextSrc())) {
273       std::cout << (first ? "" : ", ") << obj->GetName();
274       first = false;
275     }
276
277     std::cout << "\n"
278               << "  Libraries to load:    " << std::flush;
279     first = true;
280     TIter nextLib(&fListOfLibraries);
281     while ((obj = nextLib())) {
282       std::cout << (first ? "" : ", ") << obj->GetName();
283       first = false;
284     }
285     std::cout << std::endl;
286
287     AliAnalysisGrid* plugin = 
288       AliAnalysisManager::GetAnalysisManager()->GetGridHandler();
289     if (!plugin) return;
290     
291   }
292
293 protected:
294   //__________________________________________________________________
295   TrainSetup(const TrainSetup& o)
296     : fName(o.fName),
297       fRootVersion(o.fRootVersion),
298       fAliRootVersion(o.fAliRootVersion),
299       fProofServer(o.fProofServer),
300       fDataDir(o.fDataDir),     
301       fDataSet(o.fDataSet),     
302       fXML(o.fXML),     
303       fRunNumbers(o.fRunNumbers),
304       fListOfPARs(),
305       fListOfSources(),
306       fListOfLibraries(),
307       fListOfExtras(),
308       fNReplica(o.fNReplica),
309       fESDPass(o.fESDPass)
310   {
311     TObject* obj = 0;
312     TIter nextPar(&o.fListOfPARs);
313     while ((obj = nextPar())) fListOfPARs.Add(obj->Clone());
314     TIter nextSrc(&o.fListOfSources);
315     while ((obj = nextSrc())) fListOfSources.Add(obj->Clone());
316     TIter nextLib(&o.fListOfLibraries);
317     while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone());
318     TIter nextExa(&o.fListOfExtras);
319     while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
320   }
321   //__________________________________________________________________
322   TrainSetup& operator=(const TrainSetup& o)
323   {
324     fName               = o.fName;
325     fRootVersion        = o.fRootVersion;
326     fAliRootVersion     = o.fAliRootVersion;
327     fProofServer        = o.fProofServer;
328     fDataDir            = o.fDataDir;   
329     fDataSet            = o.fDataSet;   
330     fXML                = o.fXML;       
331     fNReplica           = o.fNReplica;  
332     fESDPass            = o.fESDPass;
333     fRunNumbers         = o.fRunNumbers;
334     TObject* obj = 0;
335     TIter nextPar(&o.fListOfPARs);
336     while ((obj = nextPar())) fListOfPARs.Add(obj->Clone());
337     TIter nextSrc(&o.fListOfSources);
338     while ((obj = nextSrc())) fListOfSources.Add(obj->Clone());
339     TIter nextLib(&o.fListOfLibraries);
340     while ((obj = nextLib())) fListOfLibraries.Add(obj->Clone());
341     TIter nextExa(&o.fListOfExtras);
342     while ((obj = nextExa())) fListOfExtras.Add(obj->Clone());
343
344     return *this;
345   }
346
347   //__________________________________________________________________
348   /** 
349    * Run this analysis 
350    * 
351    * @param type Type of input for analysis  (kESD, kAOD)
352    * @param mode Mode of job (kLocal, kProof, kGrid)
353    * @param oper Operation 
354    * @param mc   Whether to connect MC data 
355    * @param dbg  Debug level
356    */
357   void Exec(EType type, EMode mode, EOper oper, Int_t nEvents, 
358             Bool_t mc, Bool_t usePar, Int_t dbg=0)
359   {
360     if (mode == kProof) usePar    = true;
361
362     if (!Connect(mode)) return;
363
364     TString cwd = gSystem->WorkingDirectory();
365     TString nam = EscapedName();
366     if (!gSystem->AccessPathName(nam.Data())) {
367       Error("Exec", "File/directory %s already exists", nam.Data());
368       return;
369     }
370     if (gSystem->MakeDirectory(nam.Data())) {
371       Error("Exec", "Failed to make directory %s", nam.Data());
372       return;
373     }
374     if (!gSystem->ChangeDirectory(nam.Data())) { 
375       Error("Exec", "Failed to change directory to %s", nam.Data());
376       return;
377     }
378     Info("Exec", "Made subdirectory %s, and cd'ed there", nam.Data());
379       
380     if (!LoadCommonLibraries(mode, usePar)) return;
381     
382     // --- Create analysis manager -----------------------------------
383     AliAnalysisManager *mgr  = new AliAnalysisManager(fName,"Analysis Train");
384
385     // In test mode, collect system information on every event 
386     // if (oper == kTest)  mgr->SetNSysInfo(1); 
387     if (dbg  >  0)      mgr->SetDebugLevel(dbg);
388     if (mode == kLocal) mgr->SetUseProgressBar(kTRUE, 100);
389    
390     // --- ESD input handler ------------------------------------------
391     mgr->SetInputEventHandler(CreateInputHandler(type));
392     
393    // --- Monte-Carlo ------------------------------------------------
394     mgr->SetMCtruthEventHandler(CreateMCHandler(type,mc));
395     
396    // --- AOD output handler -----------------------------------------
397     mgr->SetOutputEventHandler(CreateOutputHandler(type));
398     
399     // --- Physics selction ------------------------------------------
400     gROOT->Macro(Form("$ALICE_ROOT/ANALYSIS/macros/"
401                       "AddTaskPhysicsSelection.C(%d)", mc));
402     mgr->RegisterExtraFile("event_stat.root");
403     
404     // --- Create tasks ----------------------------------------------
405     CreateTasks(mode, usePar, mgr);
406
407     // --- Create Grid handler ----------------------------------------
408     // _must_ be done after all tasks has been added
409     mgr->SetGridHandler(CreateGridHandler(mode, oper));
410     
411     
412     // --- Create the chain ------------------------------------------
413     TChain* chain = CreateChain(type, mode, oper);
414
415     // --- Print setup -----------------------------------------------
416     Print();
417
418     // --- Initialise the train --------------------------------------
419     if (!mgr->InitAnalysis())  {
420       gSystem->ChangeDirectory(cwd.Data());
421       Fatal("Run","Failed initialise train");
422     }
423
424     // --- Show status -----------------------------------------------
425     mgr->PrintStatus();
426
427     StartAnalysis(mgr, mode, chain, nEvents);
428
429     gSystem->ChangeDirectory(cwd.Data());
430   }
431
432   void StartAnalysis(AliAnalysisManager* mgr, 
433                      EMode mode, 
434                      TChain* chain,
435                      Int_t nEvents)
436   {
437     // --- Run the analysis ------------------------------------------
438     switch (mode) { 
439     case kLocal: 
440       if (!chain) Fatal("Run", "No chain defined");
441       if (nEvents < 0) nEvents = chain->GetEntries();
442       mgr->StartAnalysis(ModeString(mode), chain, nEvents);
443       break;
444     case kProof: 
445       if (fDataSet.IsNull()) {
446         if (!chain) Fatal("Run", "No chain defined");
447         if (nEvents < 0) nEvents = chain->GetEntries();
448         mgr->StartAnalysis(ModeString(mode), chain, nEvents);
449       }
450       else 
451         mgr->StartAnalysis(ModeString(mode), fDataSet);
452       break;
453     case kGrid: 
454       mgr->StartAnalysis(ModeString(mode));
455     }
456   }
457   //__________________________________________________________________
458   const TString& EscapedName() const 
459   {
460     return fEscapedName;
461   }
462   //__________________________________________________________________
463   /** 
464    * Create a grid handler 
465    * 
466    * @param oper Operation 
467    * 
468    * @return Grid handler 
469    */
470   AliAnalysisAlien* CreateGridHandler(EMode mode, EOper oper)
471   {
472     if (mode != kGrid) return 0;
473
474     TString name = EscapedName();
475
476     // Create the plug-in object, and set run mode 
477     AliAnalysisAlien* plugin = new AliAnalysisAlien();
478     plugin->SetRunMode(OperString(oper));
479     
480     // Production mode - not used here 
481     // plugin->SetProductionMode();
482     
483     // Set output to be per run 
484     plugin->SetOutputToRunNo();
485
486     // Set the job tag 
487     plugin->SetJobTag(fName);
488
489     // Set number of test files - used in test mode only 
490     plugin->SetNtestFiles(1);
491     
492     // Set required version of software 
493     plugin->SetAPIVersion("V1.1x");
494     plugin->SetROOTVersion(fRootVersion);
495     plugin->SetAliROOTVersion(fAliRootVersion);
496
497     // Keep log files 
498     plugin->SetKeepLogs();
499
500     // Declare root of input data directory 
501     plugin->SetGridDataDir(fDataDir);
502
503     // Data search patterns 
504     plugin->SetRunPrefix("000");
505     plugin->SetDataPattern(Form("*ESDs/pass%d/*/*ESDs.root", fESDPass));
506
507     // Add the run numbers 
508     for (Int_t i = 0; i < fRunNumbers.fN; i++) {
509       if (fRunNumbers[i] < 0) continue; 
510       plugin->AddRunNumber(fRunNumbers[i]);
511     }
512     
513     // Set the working directory to be the trains name (with special
514     // characters replaced by '_' and the date appended), and also set
515     // the output directory (relative to working directory)
516     plugin->SetGridWorkingDir(name.Data());
517     plugin->SetGridOutputDir("output");
518
519     // Enable configured PARs 
520     TIter nextPar(&fListOfPARs);
521     TObject* parName;
522     while ((parName = nextPar()))
523       plugin->EnablePackage(parName->GetName());
524     
525     // Add sources that need to be compiled on the workers using
526     // AcLIC. 
527     TString addSources = SetupSources();
528     if (!addSources.IsNull()) plugin->SetAnalysisSource(addSources.Data());
529
530     // Add binary libraries that should be uploaded to the workers 
531     TString addLibs = SetupLibraries();
532     if (!addLibs.IsNull()) plugin->SetAdditionalLibs(addLibs.Data());
533     
534     // Disable default outputs 
535     plugin->SetDefaultOutputs(true);
536
537     // Merge parameters 
538     plugin->SetMaxMergeFiles(20);
539     plugin->SetMergeExcludes("AliAOD.root "
540                             "EventStat_temp.root "
541                             "*event_stat*.root");
542
543     // Set number of runs per master - set to one to per run
544     plugin->SetNrunsPerMaster(1);
545
546     // Loop over defined containers in the analysis manager, 
547     // and declare these as outputs 
548     TString listOfAODs  = "";
549     TString listOfHists = "";
550     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
551     AliAnalysisDataContainer* cont = 0;
552     TIter nextCont(mgr->GetOutputs());
553     while ((cont = static_cast<AliAnalysisDataContainer*>(nextCont()))) {
554       TString outName(cont->GetFileName());
555       TString& list = (outName == "default" ? listOfAODs : listOfHists);
556       if (outName == "default") { 
557         if (!mgr->GetOutputEventHandler()) continue; 
558
559         outName = mgr->GetOutputEventHandler()->GetOutputFileName();
560       }
561       if (list.Contains(outName)) continue;
562       if (!list.IsNull()) list.Append(",");
563       list.Append(outName);
564     }
565     if (!mgr->GetExtraFiles().IsNull()) { 
566       if (!listOfAODs.IsNull()) listOfAODs.Append("+");
567       TString extra = mgr->GetExtraFiles();
568       extra.ReplaceAll(" ", ",");
569       listOfAODs.Append(extra);
570     }
571     TString outArchive = Form("stderr, stdout@disk=%d", fNReplica);
572     if (!listOfHists.IsNull()) 
573       outArchive.Append(Form(" hist_archive.zip:%s@disk=%d", 
574                              listOfHists.Data(), fNReplica));
575     if (!listOfAODs.IsNull()) 
576       outArchive.Append(Form(" aod_archive.zip:%s@disk=%d", 
577                              listOfAODs.Data(), fNReplica));
578     if (listOfAODs.IsNull() && listOfHists.IsNull()) 
579       Fatal("CreateGridHandler", "No outputs defined");
580     // Disabled for now 
581     // plugin->SetOutputArchive(outArchive);
582     
583     // Set name of generated analysis macro 
584     plugin->SetAnalysisMacro(Form("%s.C", name.Data()));
585     
586     // Maximum number of sub-jobs 
587     plugin->SetSplitMaxInputFileNumber(25);
588     
589     // Set the Time-To-Live 
590     plugin->SetTTL(70000);
591     
592     // Re-submit failed jobs as long as the ratio of failed jobs is
593     // below this percentage. 
594     plugin->SetMasterResubmitThreshold(95);
595
596     // Set the input format
597     plugin->SetInputFormat("xml-single");
598
599     // Set the name of the generated jdl 
600     plugin->SetJDLName(Form("%s.jdl", name.Data()));
601
602     // Set the name of the generated executable 
603     plugin->SetExecutable(Form("%s.sh", name.Data()));
604     
605     // Set the job price !?
606     plugin->SetPrice(1);
607
608     // Set whether to merge via JDL 
609     plugin->SetMergeViaJDL(true);
610     
611     // Fast read otion 
612     plugin->SetFastReadOption(false);
613
614     // Whether to overwrite existing output 
615     plugin->SetOverwriteMode(true);
616
617     // Set the executable binary name and options 
618     plugin->SetExecutableCommand("aliroot -b -q -x");
619     
620     // Split by storage element - must be lower case!
621     plugin->SetSplitMode("se");
622
623     return plugin;
624   }
625   //__________________________________________________________________
626   /** 
627    * Create input handler 
628    * 
629    * @param type 
630    * 
631    * @return 
632    */
633   AliVEventHandler* CreateInputHandler(EType type)
634   {
635     switch (type) {
636     case kESD: return new AliESDInputHandler(); 
637     case kAOD: return new AliAODInputHandler(); 
638     }
639     return 0;
640   }
641   //__________________________________________________________________
642   /** 
643    * Create input handler 
644    * 
645    * @param type 
646    * 
647    * @return 
648    */
649   AliVEventHandler* CreateMCHandler(EType type, bool mc)
650   {
651     if (!mc || type != kESD) return 0;
652     AliMCEventHandler* mcHandler = new AliMCEventHandler();
653     mcHandler->SetReadTR(true); 
654     return mcHandler;
655   }
656   //__________________________________________________________________
657   /** 
658    * Create output event handler 
659    * 
660    * @param type 
661    * 
662    * @return 
663    */
664   AliVEventHandler* CreateOutputHandler(EType type)
665   {
666     switch (type) { 
667     case kESD: // Fall through 
668     case kAOD: { 
669       AliAODHandler* ret = new AliAODHandler();
670       ret->SetOutputFileName("AliAOD.root");
671       return ret;
672     }
673     }
674     return 0;
675   }
676   //__________________________________________________________________
677   /** 
678    * Create analysis tasks 
679    * 
680    * @param mgr Manager
681    * @param par Whether to use pars 
682    */
683   virtual void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)=0;
684   //__________________________________________________________________
685   /** 
686    * Connect to external services (Proof and/or grid)
687    * 
688    * @param mode Running mode 
689    * 
690    * @return true on success 
691    */
692   virtual Bool_t Connect(EMode mode)
693   {
694     if (mode == kLocal) return true;
695                           
696     // --- Set-up connections to Proof cluster and alien -------------
697     if (mode == kProof) { 
698       // --- Find user name ------------------------------------------
699       TString userName(gSystem->Getenv("alien_API_USER"));
700       if (userName.IsNull()) {
701         userName = gSystem->GetUserInfo()->fUser;
702         Warning("Connect", 
703                 "environment variable 'alien_API_USER' not set, using %s", 
704                 userName.Data());
705       }
706
707       // --- Set prefered GSI method ---------------------------------
708       gEnv->SetValue("XSec.GSI.DelegProxy", "2");
709       
710       // --- Now open connection to PROOF cluster --------------------
711       TProof::Open(Form("%s@%s", userName.Data(), fProofServer.Data()));
712       if (!gProof) { 
713         Error("Connect", "Failed to connect to Proof cluster %s as %s",
714               fProofServer.Data(), userName.Data());
715         return false;
716       }
717     }
718
719     // --- Open a connection to the grid -----------------------------
720     TGrid::Connect("alien://");
721     if (!gGrid || !gGrid->IsConnected()) { 
722       // This is only fatal in grid mode 
723       Error("Connect", "Failed to connect to AliEN");
724       if (mode == kGrid) return false; 
725     }
726     if (mode == kGrid) return true;
727
728     
729     // --- Set and make output directory -----------------------------
730     TString name = EscapedName();
731     TString homeDir(gGrid->GetHomeDirectory());
732     TString workDir(homeDir);
733     workDir.Append("/");
734     workDir.Append(name);
735     
736     // Make working directory 
737     if (!gGrid->Cd(workDir)) { 
738       gGrid->Cd(homeDir);
739       if (gGrid->Mkdir(workDir)) {
740         gGrid->Cd(name);
741         Info("Connect", "Directory %s created", workDir.Data());
742       }
743     }
744     // Make output directory 
745     gGrid->Mkdir("proof_output");
746     gGrid->Cd("proof_output");
747
748     return true;
749   }       
750   //__________________________________________________________________
751   /** 
752    * Load common libraries 
753    * 
754    * @param mode Running mode 
755    * 
756    * @return true on success 
757    */
758   Bool_t LoadCommonLibraries(EMode mode, Bool_t par) 
759   {
760     if (!gSystem->Getenv("ALICE_ROOT")) { 
761       Error("LoadCommonLibraries", "Local AliROOT not available");
762       return false;
763     }
764     gSystem->Load("libTree.so");
765     gSystem->Load("libGeom.so");
766     gSystem->Load("libVMC.so");
767     gSystem->Load("libPhysics.so");
768     gSystem->Load("libMinuit.so");
769
770     Bool_t ret   = true;
771     Bool_t basic = mode == kGrid ? false : par;
772     
773     ret &= LoadLibrary("STEERBase",     mode, basic, false);
774     ret &= LoadLibrary("ESD",           mode, basic, false);
775     ret &= LoadLibrary("AOD",           mode, basic, false);
776     ret &= LoadLibrary("ANALYSIS",      mode, basic, true);
777     ret &= LoadLibrary("ANALYSISalice", mode, basic, true);
778
779     return ret;
780   }
781   //__________________________________________________________________
782   /** 
783    * Load a library 
784    * 
785    * @param what What library to load
786    * @param mode Mode (local, proof, grid)
787    * @param rec  If true, also load on slaves
788    * 
789    * @return true on success 
790    */
791   Bool_t LoadLibrary(const char* what, EMode mode, Bool_t par, Bool_t rec=false)
792   {
793     if (!what || what[0] == '\0') return true;
794     
795     TString module(what);
796     TString libName(what);
797     if (!libName.BeginsWith("lib")) libName = Form("lib%s", libName.Data());
798     if (!libName.EndsWith(".so"))   libName.Append(".so");
799
800     Int_t ret = 0;
801
802     switch (mode) { 
803     case kLocal: // Just load and exit 
804       gSystem->Load(libName.Data());
805       break;
806     case kGrid: 
807       if (par) { 
808         ret = SetupPAR(what) ? 0 : -1;
809         if (rec) fListOfPARs.Add(new TObjString(what));
810       } else  {
811         ret = gSystem->Load(libName.Data());
812         if (rec) fListOfLibraries.Add(new TObjString(libName));
813       }
814       break;
815     case kProof: 
816       ret = gProof->UploadPackage(what);
817       if (ret < 0)  {   
818           ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par",
819                                                                    what)));
820         if (ret < 0) {  
821           ret = 
822             gProof->UploadPackage(gSystem
823                                   ->ExpandPathName(Form("$ALICE_ROOT/%s.par", 
824                                                         what)));
825           if (ret < 0) {
826             Error("LoadLibrary", 
827                   "Could not find module %s.par in current directory nor "
828                   "in $ALICE_ROOT", module.Data());
829             return false;
830           }
831         }
832       }
833       ret = gProof->EnablePackage(what);
834       break;
835     }
836     if (ret < 0) { 
837       Error("LoadLibrary", "Couldn't load %s", what);
838       return false;
839     }
840     return true;
841   }
842           
843   //__________________________________________________________________
844   Bool_t SetupPAR(const char* what)
845   {
846     if (!what || what[0] == '\0') return -1;
847     
848     TString parFile(Form("%s.par", what));
849     if (gSystem->AccessPathName(parFile.Data())) { 
850       if (gSystem->AccessPathName(Form("../%s.par", what))) { 
851         // If not found 
852         TString aliParFile = 
853           gSystem->ExpandPathName(Form("$(ALICE_ROOT)/%s.par", what));
854         if (gSystem->AccessPathName(aliParFile.Data())) { 
855           Error("SetupPAR", "PAR file %s not found in current directory or "
856                 "$(ALICE_ROOT)", what);
857           return false;
858         }
859         // Copy to current directory 
860         TFile::Cp(aliParFile, parFile);
861       }
862       else 
863         gSystem->Exec(Form("ln -s ../%s.par .", what));
864     }
865     
866     // Extract archive 
867     gSystem->Exec(Form("tar xvzf %s", parFile.Data()));
868     
869     // Change directory into par archive
870     TString cwd = gSystem->WorkingDirectory();
871     
872     if (!gSystem->ChangeDirectory(what)) { 
873       Error("SetupPAR", "Failed to change directory to %s", what);
874       return false;
875     }
876     
877     // Test the build 
878     if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
879       Info("SetupPar", "Building in PAR archive %s", what);
880       if (gSystem->Exec("PROOF-INF/BUILD.sh")) { 
881         Error("SetupPar", "Failed to build in PAR directory %s", what);
882         gSystem->ChangeDirectory(cwd.Data());
883         return false;
884       }
885     }
886     
887     // Check for setup script
888     if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
889       Info("SetupPAR", "Setting up for PAR %s", what);
890       gROOT->Macro("PROOF-INF/SETUP.C");
891     }
892     if (!gSystem->ChangeDirectory(cwd.Data())) return false;
893
894     return true;
895   }
896   //__________________________________________________________________
897   TString SetupExtras()
898   {
899     TString ret;
900     TIter next(&fListOfExtras);
901     TObjString* obj = 0;
902     while ((obj = static_cast<TObjString*>(next()))) {
903       TString path = gSystem->ExpandPathName(obj->GetName());
904       if (!path.BeginsWith("/")) 
905         // If not an absolute path, prepend to up-one
906         path = Form("../%s", path.Data());
907       if (gSystem->AccessPathName(path.Data())) { 
908         // File not accessible 
909         Warning("SetupExtras", "File %s not accessible", path.Data());
910         continue;
911       }
912       ret.Append(Form("%s ", gSystem->BaseName(obj->GetName())));
913       gSystem->Exec(Form("ln -s %s .", path.Data()));
914     }
915     ret = ret.Strip();
916     return ret;
917   }
918   //__________________________________________________________________
919   TString SetupSources()
920   {
921     TString nam = EscapedName();
922     TString ret;
923     TIter next(&fListOfSources); 
924     TObject* src;
925     while ((src = next())) {
926       TString path = gSystem->ExpandPathName(src->GetName());
927       if (!path.BeginsWith("/")) 
928         // If not an absolute path, prepend to up-one
929         path = Form("../%s", path.Data());
930       if (gSystem->AccessPathName(path.Data())) { 
931         // File not accessible 
932         Warning("SetupSources", "File %s not accessible", path.Data());
933         continue;
934       }
935       ret.Append(Form("%s ", gSystem->BaseName(src->GetName())));
936       gSystem->Exec(Form("ln -s %s .", path.Data()));
937     }
938     ret = ret.Strip();
939     return ret;
940   }
941   //__________________________________________________________________
942   TString SetupLibraries()
943   {
944     TString ret;
945     TIter next(&fListOfLibraries); 
946     TObject* lib;
947     while ((lib = next())) {
948       ret.Append(lib->GetName());
949       ret.Append(" ");
950     }
951     // Also add extra files to this variable 
952     ret.Append(SetupExtras());
953     ret = ret.Strip();
954     return ret;
955   }
956   //__________________________________________________________________
957   /** 
958    * Scan directory @a dir (possibly recursive) for tree files to add
959    * to the chain.  
960    * 
961    * @param dir        Directory to scan
962    * @param chain      Chain to add to
963    * @param type       Type of tree (ESD or AOD)
964    * @param recursive  Whether to scan recursively 
965    *
966    * @return true if any files where added 
967    */
968   Bool_t ScanDirectory(TSystemDirectory* dir, TChain* chain, 
969                        EType type, bool recursive)
970   {
971     TString fnPattern;
972     switch (type) { 
973     case kESD:  fnPattern = "AliESD"; break;
974     case kAOD:  fnPattern = "AliAOD"; break;
975     }
976     Info("ScanDirectory", "Now investigating %s for %s", 
977          dir->GetName(), fnPattern.Data());
978
979     // Assume failure 
980     Bool_t ret = false;
981
982     // Get list of files, and go back to old working directory
983     TString oldDir(gSystem->WorkingDirectory());
984     TList* files = dir->GetListOfFiles();
985     gSystem->ChangeDirectory(oldDir);
986     if (!files) return false;
987
988     // Sort list of files and check if we should add it 
989     files->Sort();
990     TIter next(files);
991     TSystemFile* file = 0;
992     while ((file = static_cast<TSystemFile*>(next()))) {
993       TString name(file->GetName());
994     
995       // Ignore special links 
996       if (name == "." || name == "..") continue;
997
998       // Check if this is a directory 
999       if (file->IsDirectory()) { 
1000         if (recursive) 
1001           if (ScanDirectory(static_cast<TSystemDirectory*>(file),
1002                             chain,type,recursive))
1003             ret = true;;
1004         continue;
1005       }
1006     
1007       // If this is not a root file, ignore 
1008       if (!name.EndsWith(".root")) continue;
1009
1010       // If this file does not contain AliESDs, ignore 
1011       if (!name.Contains(fnPattern)) continue;
1012     
1013       // Get the path 
1014       TString fn(Form("%s/%s", file->GetTitle(), name.Data()));
1015
1016       // Add 
1017       Info("ScanDirectory", "Adding %s", fn.Data());
1018       chain->Add(fn);
1019       ret = true;
1020     }
1021     return ret;
1022   }
1023   //__________________________________________________________________
1024   /** 
1025    * Create a chain from an XML containing an collection
1026    * 
1027    * @param treeName Name of tree's 
1028    * @param xmlFile  XML collection
1029    * 
1030    * @return Newly allocated chain or null
1031    */
1032   TChain* CreateChainFromXML(const char* treeName, 
1033                              const char* xmlFile) 
1034   {
1035     TGridCollection* collection = TAlienCollection::Open(xmlFile);
1036     if (!collection) { 
1037       Error("CreateChainFromXML", "Cannot create AliEn collection from "
1038             "XML file %s", xmlFile);
1039       return 0;
1040     }
1041
1042     TChain* chain = new TChain(treeName);
1043     collection->Reset();
1044     while (collection->Next()) chain->Add(collection->GetTURL(""));
1045     
1046     return chain;
1047   }
1048   //__________________________________________________________________
1049   /** 
1050    * 
1051    * 
1052    * @param type 
1053    * @param mode 
1054    * @param oper 
1055    * 
1056    * @return 
1057    */    
1058   TChain* CreateChain(EType type, EMode mode, EOper /* oper */)
1059   {
1060     TString treeName;
1061     switch (type) { 
1062     case kESD:  treeName = "esdTree"; break;
1063     case kAOD:  treeName = "aodTree"; break;
1064     }
1065
1066     TChain* chain = 0;
1067     switch (mode) { 
1068     case kProof: 
1069       if (!fDataSet.IsNull()) break; 
1070       // Otherwise fall through
1071     case kLocal:
1072       if (fXML.IsNull()) {
1073         chain = new TChain(treeName.Data());
1074         TString dir(fDataDir);
1075         if (!dir.BeginsWith("/")) dir = Form("../%s", dir.Data());
1076         TSystemDirectory d(dir.Data(), dir.Data());
1077         if (!ScanDirectory(&d, chain, type, true)) { 
1078           delete chain;
1079           chain = 0;
1080         }
1081       }
1082       else 
1083         chain = CreateChainFromXML(treeName.Data(), fXML.Data());
1084       break;
1085     case kGrid:  break; // Do nothing - we use plugin
1086     }
1087     
1088     if (chain && chain->GetNtrees() <= 0) { 
1089       delete chain;
1090       return 0;
1091     }
1092     return chain;
1093   }
1094   //__________________________________________________________________
1095   TString fName;             // Name of analysis
1096   TString fRootVersion;      // ROOT version to use 
1097   TString fAliRootVersion;   // AliROOT version to use 
1098   TString fProofServer;      // Name of proof server
1099   TString fDataDir;          // Grid Input directory 
1100   TString fDataSet;          // Proof data set name 
1101   TString fXML;              // XML collection for local/proof mode
1102   TArrayI fRunNumbers;       // List of run number 
1103   TList   fListOfPARs;       // List of PAR files to use 
1104   TList   fListOfSources;    // List of sources to upload and AcLIC
1105   TList   fListOfLibraries;  // List of libraries to load
1106   TList   fListOfExtras;     // List of extra files to upload
1107   Int_t   fNReplica;         // Storage replication
1108   Int_t   fESDPass;
1109   TString fEscapedName;
1110 };
1111
1112 //====================================================================
1113 class ForwardPass1 : public TrainSetup
1114 {
1115 public:
1116   ForwardPass1(UShort_t sys   = 0, 
1117                UShort_t sNN   = 0, 
1118                Short_t  field = 0, 
1119                UShort_t year  = 0, 
1120                UShort_t month = 0, 
1121                UShort_t day   = 0, 
1122                UShort_t hour  = 0, 
1123                UShort_t min   = 0) 
1124     : TrainSetup("Forward d2Ndetadphi pass1",
1125                  year, month, day, hour, min),
1126       fSys(sys), 
1127       fSNN(sNN), 
1128       fField(field)
1129   {}
1130   void Run(const char* mode, const char* oper, 
1131            Int_t nEvents=-1, Bool_t mc=false)
1132   {
1133     EMode eMode = ParseMode(mode);
1134     EOper eOper = ParseOperation(oper);
1135     
1136     Run(eMode, eOper, nEvents, mc);
1137   }
1138   void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false)
1139   {
1140     Exec(kESD, mode, oper, nEvents, mc, true);
1141   }
1142   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
1143   {
1144     // --- Forward multiplicity ---------------------------------------
1145     AliAnalysisManager::SetCommonFileName("forward.root");
1146     LoadLibrary("PWG2forward2", mode, par, true);
1147     Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
1148     gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/AddTaskFMD.C");
1149     gROOT->ProcessLine(Form("AddTaskFMD(%d,%d,%d,%d)", mc, fSys, fSNN, fField));
1150   }
1151 private:
1152   UShort_t fSys;
1153   UShort_t fSNN;
1154   Short_t  fField;
1155 };
1156 //====================================================================
1157 class ForwardELoss : public TrainSetup
1158 {
1159 public:
1160   ForwardELoss() : TrainSetup("Forward energy loss") {}
1161   void Run(const char* mode, const char* oper, 
1162            Int_t nEvents=-1, Bool_t mc=false)
1163   {
1164     EMode eMode = ParseMode(mode);
1165     EOper eOper = ParseOperation(oper);
1166     
1167     Run(eMode, eOper, nEvents, mc);
1168   }
1169   void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false)
1170   {
1171     Exec(kESD, mode, oper, nEvents, mc, true);
1172   }
1173   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
1174   {
1175     // --- Forward multiplicity ---------------------------------------
1176     AliAnalysisManager::SetCommonFileName("forward_eloss.root");
1177
1178     LoadLibrary("PWG2forward2", mode, par, true);
1179     Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
1180     gROOT->Macro(Form("$ALICE_ROOT/PWG2/FORWARD/analysis2/AddTaskFMDEloss.C(%d)",
1181                       mc));
1182   }
1183 };
1184   
1185 //____________________________________________________________________
1186 //
1187 // EOF
1188 //