Fixes
[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 (oper != kTerminate) { 
367       if (!gSystem->AccessPathName(nam.Data())) {
368         Error("Exec", "File/directory %s already exists", nam.Data());
369         return;
370       }
371       if (gSystem->MakeDirectory(nam.Data())) {
372         Error("Exec", "Failed to make directory %s", nam.Data());
373         return;
374       }
375     }
376     else {
377       if (gSystem->AccessPathName(nam.Data())) {
378         Error("Exec", "File/directory %s does not exists", nam.Data());
379         return;
380       }
381     }
382       
383     if (!gSystem->ChangeDirectory(nam.Data())) { 
384       Error("Exec", "Failed to change directory to %s", nam.Data());
385       return;
386     }
387     Info("Exec", "Made subdirectory %s, and cd'ed there", nam.Data());
388       
389     if (!LoadCommonLibraries(mode, usePar)) return;
390     
391     // --- Create analysis manager -----------------------------------
392     AliAnalysisManager *mgr  = new AliAnalysisManager(fName,"Analysis Train");
393
394     // In test mode, collect system information on every event 
395     // if (oper == kTest)  mgr->SetNSysInfo(1); 
396     if (dbg  >  0)      mgr->SetDebugLevel(dbg);
397     if (mode == kLocal) mgr->SetUseProgressBar(kTRUE, 100);
398    
399     // --- ESD input handler ------------------------------------------
400     mgr->SetInputEventHandler(CreateInputHandler(type));
401     
402    // --- Monte-Carlo ------------------------------------------------
403     mgr->SetMCtruthEventHandler(CreateMCHandler(type,mc));
404     
405    // --- AOD output handler -----------------------------------------
406     mgr->SetOutputEventHandler(CreateOutputHandler(type));
407     
408     // --- Physics selction ------------------------------------------
409     gROOT->Macro(Form("$ALICE_ROOT/ANALYSIS/macros/"
410                       "AddTaskPhysicsSelection.C(%d)", mc));
411     mgr->RegisterExtraFile("event_stat.root");
412     
413     // --- Create tasks ----------------------------------------------
414     CreateTasks(mode, usePar, mgr);
415
416     // --- Create Grid handler ----------------------------------------
417     // _must_ be done after all tasks has been added
418     mgr->SetGridHandler(CreateGridHandler(mode, oper));
419     
420     
421     // --- Create the chain ------------------------------------------
422     TChain* chain = CreateChain(type, mode, oper);
423
424     // --- Print setup -----------------------------------------------
425     Print();
426
427     // --- Initialise the train --------------------------------------
428     if (!mgr->InitAnalysis())  {
429       gSystem->ChangeDirectory(cwd.Data());
430       Fatal("Run","Failed initialise train");
431     }
432
433     // --- Show status -----------------------------------------------
434     mgr->PrintStatus();
435
436     StartAnalysis(mgr, mode, chain, nEvents);
437
438     gSystem->ChangeDirectory(cwd.Data());
439   }
440
441   void StartAnalysis(AliAnalysisManager* mgr, 
442                      EMode mode, 
443                      TChain* chain,
444                      Int_t nEvents)
445   {
446     // --- Run the analysis ------------------------------------------
447     switch (mode) { 
448     case kLocal: 
449       if (!chain) Fatal("Run", "No chain defined");
450       if (nEvents < 0) nEvents = chain->GetEntries();
451       mgr->StartAnalysis(ModeString(mode), chain, nEvents);
452       break;
453     case kProof: 
454       if (fDataSet.IsNull()) {
455         if (!chain) Fatal("Run", "No chain defined");
456         if (nEvents < 0) nEvents = chain->GetEntries();
457         mgr->StartAnalysis(ModeString(mode), chain, nEvents);
458       }
459       else 
460         mgr->StartAnalysis(ModeString(mode), fDataSet);
461       break;
462     case kGrid: 
463       mgr->StartAnalysis(ModeString(mode));
464     }
465   }
466   //__________________________________________________________________
467   const TString& EscapedName() const 
468   {
469     return fEscapedName;
470   }
471   //__________________________________________________________________
472   /** 
473    * Create a grid handler 
474    * 
475    * @param oper Operation 
476    * 
477    * @return Grid handler 
478    */
479   AliAnalysisAlien* CreateGridHandler(EMode mode, EOper oper)
480   {
481     if (mode != kGrid) return 0;
482
483     TString name = EscapedName();
484
485     // Create the plug-in object, and set run mode 
486     AliAnalysisAlien* plugin = new AliAnalysisAlien();
487     plugin->SetRunMode(OperString(oper));
488     
489     // Production mode - not used here 
490     // plugin->SetProductionMode();
491     
492     // Set output to be per run 
493     plugin->SetOutputToRunNo();
494
495     // Set the job tag 
496     plugin->SetJobTag(fName);
497
498     // Set number of test files - used in test mode only 
499     plugin->SetNtestFiles(1);
500     
501     // Set required version of software 
502     plugin->SetAPIVersion("V1.1x");
503     plugin->SetROOTVersion(fRootVersion);
504     plugin->SetAliROOTVersion(fAliRootVersion);
505
506     // Keep log files 
507     plugin->SetKeepLogs();
508
509     // Declare root of input data directory 
510     plugin->SetGridDataDir(fDataDir);
511
512     // Data search patterns 
513     plugin->SetRunPrefix("000");
514     plugin->SetDataPattern(Form("*ESDs/pass%d/*/*ESDs.root", fESDPass));
515
516     // Add the run numbers 
517     for (Int_t i = 0; i < fRunNumbers.fN; i++) {
518       if (fRunNumbers[i] < 0) continue; 
519       plugin->AddRunNumber(fRunNumbers[i]);
520     }
521     
522     // Set the working directory to be the trains name (with special
523     // characters replaced by '_' and the date appended), and also set
524     // the output directory (relative to working directory)
525     plugin->SetGridWorkingDir(name.Data());
526     plugin->SetGridOutputDir("output");
527
528     // Enable configured PARs 
529     TIter nextPar(&fListOfPARs);
530     TObject* parName;
531     while ((parName = nextPar()))
532       plugin->EnablePackage(parName->GetName());
533     
534     // Add sources that need to be compiled on the workers using
535     // AcLIC. 
536     TString addSources = SetupSources();
537     if (!addSources.IsNull()) plugin->SetAnalysisSource(addSources.Data());
538
539     // Add binary libraries that should be uploaded to the workers 
540     TString addLibs = SetupLibraries();
541     if (!addLibs.IsNull()) plugin->SetAdditionalLibs(addLibs.Data());
542     
543     // Disable default outputs 
544     plugin->SetDefaultOutputs(true);
545
546     // Merge parameters 
547     plugin->SetMaxMergeFiles(20);
548     plugin->SetMergeExcludes("AliAOD.root "
549                             "EventStat_temp.root "
550                             "*event_stat*.root");
551
552     // Set number of runs per master - set to one to per run
553     plugin->SetNrunsPerMaster(1);
554
555     // Loop over defined containers in the analysis manager, 
556     // and declare these as outputs 
557     TString listOfAODs  = "";
558     TString listOfHists = "";
559     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
560     AliAnalysisDataContainer* cont = 0;
561     TIter nextCont(mgr->GetOutputs());
562     while ((cont = static_cast<AliAnalysisDataContainer*>(nextCont()))) {
563       TString outName(cont->GetFileName());
564       TString& list = (outName == "default" ? listOfAODs : listOfHists);
565       if (outName == "default") { 
566         if (!mgr->GetOutputEventHandler()) continue; 
567
568         outName = mgr->GetOutputEventHandler()->GetOutputFileName();
569       }
570       if (list.Contains(outName)) continue;
571       if (!list.IsNull()) list.Append(",");
572       list.Append(outName);
573     }
574     if (!mgr->GetExtraFiles().IsNull()) { 
575       if (!listOfAODs.IsNull()) listOfAODs.Append("+");
576       TString extra = mgr->GetExtraFiles();
577       extra.ReplaceAll(" ", ",");
578       listOfAODs.Append(extra);
579     }
580     TString outArchive = Form("stderr, stdout@disk=%d", fNReplica);
581     if (!listOfHists.IsNull()) 
582       outArchive.Append(Form(" hist_archive.zip:%s@disk=%d", 
583                              listOfHists.Data(), fNReplica));
584     if (!listOfAODs.IsNull()) 
585       outArchive.Append(Form(" aod_archive.zip:%s@disk=%d", 
586                              listOfAODs.Data(), fNReplica));
587     if (listOfAODs.IsNull() && listOfHists.IsNull()) 
588       Fatal("CreateGridHandler", "No outputs defined");
589     // Disabled for now 
590     // plugin->SetOutputArchive(outArchive);
591     
592     // Set name of generated analysis macro 
593     plugin->SetAnalysisMacro(Form("%s.C", name.Data()));
594     
595     // Maximum number of sub-jobs 
596     plugin->SetSplitMaxInputFileNumber(25);
597     
598     // Set the Time-To-Live 
599     plugin->SetTTL(70000);
600     
601     // Re-submit failed jobs as long as the ratio of failed jobs is
602     // below this percentage. 
603     plugin->SetMasterResubmitThreshold(95);
604
605     // Set the input format
606     plugin->SetInputFormat("xml-single");
607
608     // Set the name of the generated jdl 
609     plugin->SetJDLName(Form("%s.jdl", name.Data()));
610
611     // Set the name of the generated executable 
612     plugin->SetExecutable(Form("%s.sh", name.Data()));
613     
614     // Set the job price !?
615     plugin->SetPrice(1);
616
617     // Set whether to merge via JDL 
618     plugin->SetMergeViaJDL(true);
619     
620     // Fast read otion 
621     plugin->SetFastReadOption(false);
622
623     // Whether to overwrite existing output 
624     plugin->SetOverwriteMode(true);
625
626     // Set the executable binary name and options 
627     plugin->SetExecutableCommand("aliroot -b -q -x");
628     
629     // Split by storage element - must be lower case!
630     plugin->SetSplitMode("se");
631
632     return plugin;
633   }
634   //__________________________________________________________________
635   /** 
636    * Create input handler 
637    * 
638    * @param type 
639    * 
640    * @return 
641    */
642   AliVEventHandler* CreateInputHandler(EType type)
643   {
644     switch (type) {
645     case kESD: return new AliESDInputHandler(); 
646     case kAOD: return new AliAODInputHandler(); 
647     }
648     return 0;
649   }
650   //__________________________________________________________________
651   /** 
652    * Create input handler 
653    * 
654    * @param type 
655    * 
656    * @return 
657    */
658   AliVEventHandler* CreateMCHandler(EType type, bool mc)
659   {
660     if (!mc || type != kESD) return 0;
661     AliMCEventHandler* mcHandler = new AliMCEventHandler();
662     mcHandler->SetReadTR(true); 
663     return mcHandler;
664   }
665   //__________________________________________________________________
666   /** 
667    * Create output event handler 
668    * 
669    * @param type 
670    * 
671    * @return 
672    */
673   AliVEventHandler* CreateOutputHandler(EType type)
674   {
675     switch (type) { 
676     case kESD: // Fall through 
677     case kAOD: { 
678       AliAODHandler* ret = new AliAODHandler();
679       ret->SetOutputFileName("AliAOD.root");
680       return ret;
681     }
682     }
683     return 0;
684   }
685   //__________________________________________________________________
686   /** 
687    * Create analysis tasks 
688    * 
689    * @param mgr Manager
690    * @param par Whether to use pars 
691    */
692   virtual void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)=0;
693   //__________________________________________________________________
694   /** 
695    * Connect to external services (Proof and/or grid)
696    * 
697    * @param mode Running mode 
698    * 
699    * @return true on success 
700    */
701   virtual Bool_t Connect(EMode mode)
702   {
703     if (mode == kLocal) return true;
704                           
705     // --- Set-up connections to Proof cluster and alien -------------
706     if (mode == kProof) { 
707       // --- Find user name ------------------------------------------
708       TString userName(gSystem->Getenv("alien_API_USER"));
709       if (userName.IsNull()) {
710         userName = gSystem->GetUserInfo()->fUser;
711         Warning("Connect", 
712                 "environment variable 'alien_API_USER' not set, using %s", 
713                 userName.Data());
714       }
715
716       // --- Set prefered GSI method ---------------------------------
717       gEnv->SetValue("XSec.GSI.DelegProxy", "2");
718       
719       // --- Now open connection to PROOF cluster --------------------
720       TProof::Open(Form("%s@%s", userName.Data(), fProofServer.Data()));
721       if (!gProof) { 
722         Error("Connect", "Failed to connect to Proof cluster %s as %s",
723               fProofServer.Data(), userName.Data());
724         return false;
725       }
726     }
727
728     // --- Open a connection to the grid -----------------------------
729     TGrid::Connect("alien://");
730     if (!gGrid || !gGrid->IsConnected()) { 
731       // This is only fatal in grid mode 
732       Error("Connect", "Failed to connect to AliEN");
733       if (mode == kGrid) return false; 
734     }
735     if (mode == kGrid) return true;
736
737     
738     // --- Set and make output directory -----------------------------
739     TString name = EscapedName();
740     TString homeDir(gGrid->GetHomeDirectory());
741     TString workDir(homeDir);
742     workDir.Append("/");
743     workDir.Append(name);
744     
745     // Make working directory 
746     if (!gGrid->Cd(workDir)) { 
747       gGrid->Cd(homeDir);
748       if (gGrid->Mkdir(workDir)) {
749         gGrid->Cd(name);
750         Info("Connect", "Directory %s created", workDir.Data());
751       }
752     }
753     // Make output directory 
754     gGrid->Mkdir("proof_output");
755     gGrid->Cd("proof_output");
756
757     return true;
758   }       
759   //__________________________________________________________________
760   /** 
761    * Load common libraries 
762    * 
763    * @param mode Running mode 
764    * 
765    * @return true on success 
766    */
767   Bool_t LoadCommonLibraries(EMode mode, Bool_t par) 
768   {
769     if (!gSystem->Getenv("ALICE_ROOT")) { 
770       Error("LoadCommonLibraries", "Local AliROOT not available");
771       return false;
772     }
773     gSystem->Load("libTree.so");
774     gSystem->Load("libGeom.so");
775     gSystem->Load("libVMC.so");
776     gSystem->Load("libPhysics.so");
777     gSystem->Load("libMinuit.so");
778
779     Bool_t ret   = true;
780     Bool_t basic = mode == kGrid ? false : par;
781     
782     ret &= LoadLibrary("STEERBase",     mode, basic, false);
783     ret &= LoadLibrary("ESD",           mode, basic, false);
784     ret &= LoadLibrary("AOD",           mode, basic, false);
785     ret &= LoadLibrary("ANALYSIS",      mode, basic, true);
786     ret &= LoadLibrary("ANALYSISalice", mode, basic, true);
787
788     return ret;
789   }
790   //__________________________________________________________________
791   /** 
792    * Load a library 
793    * 
794    * @param what What library to load
795    * @param mode Mode (local, proof, grid)
796    * @param rec  If true, also load on slaves
797    * 
798    * @return true on success 
799    */
800   Bool_t LoadLibrary(const char* what, EMode mode, Bool_t par, Bool_t rec=false)
801   {
802     if (!what || what[0] == '\0') return true;
803     
804     TString module(what);
805     TString libName(what);
806     if (!libName.BeginsWith("lib")) libName = Form("lib%s", libName.Data());
807     if (!libName.EndsWith(".so"))   libName.Append(".so");
808
809     Int_t ret = 0;
810
811     switch (mode) { 
812     case kLocal: // Just load and exit 
813       gSystem->Load(libName.Data());
814       break;
815     case kGrid: 
816       if (par) { 
817         ret = SetupPAR(what) ? 0 : -1;
818         if (rec) fListOfPARs.Add(new TObjString(what));
819       } else  {
820         ret = gSystem->Load(libName.Data());
821         if (rec) fListOfLibraries.Add(new TObjString(libName));
822       }
823       break;
824     case kProof: 
825       ret = gProof->UploadPackage(what);
826       if (ret < 0)  {   
827           ret = gProof->UploadPackage(gSystem->ExpandPathName(Form("../%s.par",
828                                                                    what)));
829         if (ret < 0) {  
830           ret = 
831             gProof->UploadPackage(gSystem
832                                   ->ExpandPathName(Form("$ALICE_ROOT/%s.par", 
833                                                         what)));
834           if (ret < 0) {
835             Error("LoadLibrary", 
836                   "Could not find module %s.par in current directory nor "
837                   "in $ALICE_ROOT", module.Data());
838             return false;
839           }
840         }
841       }
842       ret = gProof->EnablePackage(what);
843       break;
844     }
845     if (ret < 0) { 
846       Error("LoadLibrary", "Couldn't load %s", what);
847       return false;
848     }
849     return true;
850   }
851           
852   //__________________________________________________________________
853   Bool_t SetupPAR(const char* what)
854   {
855     if (!what || what[0] == '\0') return -1;
856     
857     TString parFile(Form("%s.par", what));
858     if (gSystem->AccessPathName(parFile.Data())) { 
859       if (gSystem->AccessPathName(Form("../%s.par", what))) { 
860         // If not found 
861         TString aliParFile = 
862           gSystem->ExpandPathName(Form("$(ALICE_ROOT)/%s.par", what));
863         if (gSystem->AccessPathName(aliParFile.Data())) { 
864           Error("SetupPAR", "PAR file %s not found in current directory or "
865                 "$(ALICE_ROOT)", what);
866           return false;
867         }
868         // Copy to current directory 
869         TFile::Cp(aliParFile, parFile);
870       }
871       else 
872         gSystem->Exec(Form("ln -s ../%s.par .", what));
873     }
874     
875     // Extract archive 
876     gSystem->Exec(Form("tar xvzf %s", parFile.Data()));
877     
878     // Change directory into par archive
879     TString cwd = gSystem->WorkingDirectory();
880     
881     if (!gSystem->ChangeDirectory(what)) { 
882       Error("SetupPAR", "Failed to change directory to %s", what);
883       return false;
884     }
885     
886     // Test the build 
887     if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
888       Info("SetupPar", "Building in PAR archive %s", what);
889       if (gSystem->Exec("PROOF-INF/BUILD.sh")) { 
890         Error("SetupPar", "Failed to build in PAR directory %s", what);
891         gSystem->ChangeDirectory(cwd.Data());
892         return false;
893       }
894     }
895     
896     // Check for setup script
897     if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
898       Info("SetupPAR", "Setting up for PAR %s", what);
899       gROOT->Macro("PROOF-INF/SETUP.C");
900     }
901     if (!gSystem->ChangeDirectory(cwd.Data())) return false;
902
903     return true;
904   }
905   //__________________________________________________________________
906   TString SetupExtras()
907   {
908     TString ret;
909     TIter next(&fListOfExtras);
910     TObjString* obj = 0;
911     while ((obj = static_cast<TObjString*>(next()))) {
912       TString path = gSystem->ExpandPathName(obj->GetName());
913       if (!path.BeginsWith("/")) 
914         // If not an absolute path, prepend to up-one
915         path = Form("../%s", path.Data());
916       if (gSystem->AccessPathName(path.Data())) { 
917         // File not accessible 
918         Warning("SetupExtras", "File %s not accessible", path.Data());
919         continue;
920       }
921       ret.Append(Form("%s ", gSystem->BaseName(obj->GetName())));
922       gSystem->Exec(Form("ln -s %s .", path.Data()));
923     }
924     ret = ret.Strip();
925     return ret;
926   }
927   //__________________________________________________________________
928   TString SetupSources()
929   {
930     TString nam = EscapedName();
931     TString ret;
932     TIter next(&fListOfSources); 
933     TObject* src;
934     while ((src = next())) {
935       TString path = gSystem->ExpandPathName(src->GetName());
936       if (!path.BeginsWith("/")) 
937         // If not an absolute path, prepend to up-one
938         path = Form("../%s", path.Data());
939       if (gSystem->AccessPathName(path.Data())) { 
940         // File not accessible 
941         Warning("SetupSources", "File %s not accessible", path.Data());
942         continue;
943       }
944       ret.Append(Form("%s ", gSystem->BaseName(src->GetName())));
945       gSystem->Exec(Form("ln -s %s .", path.Data()));
946     }
947     ret = ret.Strip();
948     return ret;
949   }
950   //__________________________________________________________________
951   TString SetupLibraries()
952   {
953     TString ret;
954     TIter next(&fListOfLibraries); 
955     TObject* lib;
956     while ((lib = next())) {
957       ret.Append(lib->GetName());
958       ret.Append(" ");
959     }
960     // Also add extra files to this variable 
961     ret.Append(SetupExtras());
962     ret = ret.Strip();
963     return ret;
964   }
965   //__________________________________________________________________
966   /** 
967    * Scan directory @a dir (possibly recursive) for tree files to add
968    * to the chain.  
969    * 
970    * @param dir        Directory to scan
971    * @param chain      Chain to add to
972    * @param type       Type of tree (ESD or AOD)
973    * @param recursive  Whether to scan recursively 
974    *
975    * @return true if any files where added 
976    */
977   Bool_t ScanDirectory(TSystemDirectory* dir, TChain* chain, 
978                        EType type, bool recursive)
979   {
980     TString fnPattern;
981     switch (type) { 
982     case kESD:  fnPattern = "AliESD"; break;
983     case kAOD:  fnPattern = "AliAOD"; break;
984     }
985     Info("ScanDirectory", "Now investigating %s for %s", 
986          dir->GetName(), fnPattern.Data());
987
988     // Assume failure 
989     Bool_t ret = false;
990
991     // Get list of files, and go back to old working directory
992     TString oldDir(gSystem->WorkingDirectory());
993     TList* files = dir->GetListOfFiles();
994     gSystem->ChangeDirectory(oldDir);
995     if (!files) return false;
996
997     // Sort list of files and check if we should add it 
998     files->Sort();
999     TIter next(files);
1000     TSystemFile* file = 0;
1001     while ((file = static_cast<TSystemFile*>(next()))) {
1002       TString name(file->GetName());
1003     
1004       // Ignore special links 
1005       if (name == "." || name == "..") continue;
1006
1007       // Check if this is a directory 
1008       if (file->IsDirectory()) { 
1009         if (recursive) 
1010           if (ScanDirectory(static_cast<TSystemDirectory*>(file),
1011                             chain,type,recursive))
1012             ret = true;;
1013         continue;
1014       }
1015     
1016       // If this is not a root file, ignore 
1017       if (!name.EndsWith(".root")) continue;
1018
1019       // If this file does not contain AliESDs, ignore 
1020       if (!name.Contains(fnPattern)) continue;
1021     
1022       // Get the path 
1023       TString fn(Form("%s/%s", file->GetTitle(), name.Data()));
1024
1025       // Add 
1026       Info("ScanDirectory", "Adding %s", fn.Data());
1027       chain->Add(fn);
1028       ret = true;
1029     }
1030     return ret;
1031   }
1032   //__________________________________________________________________
1033   /** 
1034    * Create a chain from an XML containing an collection
1035    * 
1036    * @param treeName Name of tree's 
1037    * @param xmlFile  XML collection
1038    * 
1039    * @return Newly allocated chain or null
1040    */
1041   TChain* CreateChainFromXML(const char* treeName, 
1042                              const char* xmlFile) 
1043   {
1044     TGridCollection* collection = TAlienCollection::Open(xmlFile);
1045     if (!collection) { 
1046       Error("CreateChainFromXML", "Cannot create AliEn collection from "
1047             "XML file %s", xmlFile);
1048       return 0;
1049     }
1050
1051     TChain* chain = new TChain(treeName);
1052     collection->Reset();
1053     while (collection->Next()) chain->Add(collection->GetTURL(""));
1054     
1055     return chain;
1056   }
1057   //__________________________________________________________________
1058   /** 
1059    * 
1060    * 
1061    * @param type 
1062    * @param mode 
1063    * @param oper 
1064    * 
1065    * @return 
1066    */    
1067   TChain* CreateChain(EType type, EMode mode, EOper /* oper */)
1068   {
1069     TString treeName;
1070     switch (type) { 
1071     case kESD:  treeName = "esdTree"; break;
1072     case kAOD:  treeName = "aodTree"; break;
1073     }
1074
1075     TChain* chain = 0;
1076     switch (mode) { 
1077     case kProof: 
1078       if (!fDataSet.IsNull()) break; 
1079       // Otherwise fall through
1080     case kLocal:
1081       if (fXML.IsNull()) {
1082         chain = new TChain(treeName.Data());
1083         TString dir(fDataDir);
1084         if (!dir.BeginsWith("/")) dir = Form("../%s", dir.Data());
1085         TSystemDirectory d(dir.Data(), dir.Data());
1086         if (!ScanDirectory(&d, chain, type, true)) { 
1087           delete chain;
1088           chain = 0;
1089         }
1090       }
1091       else 
1092         chain = CreateChainFromXML(treeName.Data(), fXML.Data());
1093       break;
1094     case kGrid:  break; // Do nothing - we use plugin
1095     }
1096     
1097     if (chain && chain->GetNtrees() <= 0) { 
1098       delete chain;
1099       return 0;
1100     }
1101     return chain;
1102   }
1103   //__________________________________________________________________
1104   TString fName;             // Name of analysis
1105   TString fRootVersion;      // ROOT version to use 
1106   TString fAliRootVersion;   // AliROOT version to use 
1107   TString fProofServer;      // Name of proof server
1108   TString fDataDir;          // Grid Input directory 
1109   TString fDataSet;          // Proof data set name 
1110   TString fXML;              // XML collection for local/proof mode
1111   TArrayI fRunNumbers;       // List of run number 
1112   TList   fListOfPARs;       // List of PAR files to use 
1113   TList   fListOfSources;    // List of sources to upload and AcLIC
1114   TList   fListOfLibraries;  // List of libraries to load
1115   TList   fListOfExtras;     // List of extra files to upload
1116   Int_t   fNReplica;         // Storage replication
1117   Int_t   fESDPass;
1118   TString fEscapedName;
1119 };
1120
1121 //====================================================================
1122 class ForwardPass1 : public TrainSetup
1123 {
1124 public:
1125   ForwardPass1(UShort_t sys   = 0, 
1126                UShort_t sNN   = 0, 
1127                Short_t  field = 0, 
1128                UShort_t year  = 0, 
1129                UShort_t month = 0, 
1130                UShort_t day   = 0, 
1131                UShort_t hour  = 0, 
1132                UShort_t min   = 0) 
1133     : TrainSetup("Forward d2Ndetadphi pass1",
1134                  year, month, day, hour, min),
1135       fSys(sys), 
1136       fSNN(sNN), 
1137       fField(field)
1138   {}
1139   void Run(const char* mode, const char* oper, 
1140            Int_t nEvents=-1, Bool_t mc=false)
1141   {
1142     EMode eMode = ParseMode(mode);
1143     EOper eOper = ParseOperation(oper);
1144     
1145     Run(eMode, eOper, nEvents, mc);
1146   }
1147   void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false)
1148   {
1149     Exec(kESD, mode, oper, nEvents, mc, true);
1150   }
1151   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
1152   {
1153     AliAnalysisManager::SetCommonFileName("forward.root");
1154     LoadLibrary("PWG2forward2", mode, par, true);
1155     Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
1156     gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/AddTaskFMD.C");
1157     gROOT->ProcessLine(Form("AddTaskFMD(%d,%d,%d,%d)", mc, fSys, fSNN, fField));
1158   }
1159 private:
1160   UShort_t fSys;
1161   UShort_t fSNN;
1162   Short_t  fField;
1163 };
1164 //====================================================================
1165 class ForwardPass2 : public TrainSetup
1166 {
1167 public:
1168   ForwardPass2(const char* trig="INEL", 
1169                Double_t    vzMin=-10, 
1170                Double_t    vzMax=10, 
1171                UShort_t    year  = 0, 
1172                UShort_t    month = 0, 
1173                UShort_t    day   = 0, 
1174                UShort_t    hour  = 0, 
1175                UShort_t    min   = 0) 
1176     : TrainSetup("Forward d2Ndetadphi pass2",
1177                  year, month, day, hour, min),
1178       fTrig(trig), 
1179       fVzMin(vzMin), 
1180       fVzMax(vzMax)
1181   {}
1182   void Run(const char* mode, const char* oper, 
1183            Int_t nEvents=-1, Bool_t mc=false)
1184   {
1185     EMode eMode = ParseMode(mode);
1186     EOper eOper = ParseOperation(oper);
1187     
1188     Run(eMode, eOper, nEvents, mc);
1189   }
1190   void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false)
1191   {
1192     Exec(kESD, mode, oper, nEvents, mc, true);
1193   }
1194   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
1195   {
1196     AliAnalysisManager::SetCommonFileName("forward_dndeta.root");
1197     LoadLibrary("PWG2forward2", mode, par, true);
1198     gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/AddTaskForwarddNdeta.C");
1199     gROOT->ProcessLine(Form("AddTaskForwarddNdeta(\"%s\",%f,%f)",
1200                             fTrig.Data(), fVzMin, fVzMax));
1201   }
1202 private:
1203   TString fTrig;
1204   Double_t fVzMin;
1205   Double_t fVzMax;
1206 };
1207 //====================================================================
1208 class ForwardELoss : public TrainSetup
1209 {
1210 public:
1211   ForwardELoss(UShort_t year  = 0, 
1212                UShort_t month = 0, 
1213                UShort_t day   = 0, 
1214                UShort_t hour  = 0, 
1215                UShort_t min   = 0) 
1216     : TrainSetup("Forward energy loss",
1217                  year, month, day, hour, min) 
1218   {}
1219   void Run(const char* mode, const char* oper, 
1220            Int_t nEvents=-1, Bool_t mc=false)
1221   {
1222     EMode eMode = ParseMode(mode);
1223     EOper eOper = ParseOperation(oper);
1224     
1225     Run(eMode, eOper, nEvents, mc);
1226   }
1227   void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false)
1228   {
1229     Exec(kESD, mode, oper, nEvents, mc, true);
1230   }
1231   void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
1232   {
1233     // --- Forward multiplicity ---------------------------------------
1234     AliAnalysisManager::SetCommonFileName("forward_eloss.root");
1235
1236     LoadLibrary("PWG2forward2", mode, par, true);
1237     Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
1238     gROOT->Macro(Form("$ALICE_ROOT/PWG2/FORWARD/analysis2/AddTaskFMDEloss.C(%d)",
1239                       mc));
1240   }
1241 };
1242   
1243 //____________________________________________________________________
1244 //
1245 // EOF
1246 //