Various updates, and prep for Train base class
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / sim / BaseConfig.C
1 /**
2  * @file   BaseConfig.C
3  * @author Christian Holm Christensen <cholm@nbi.dk>
4  * @date   Wed Oct 15 12:52:58 2014
5  * 
6  * @brief  Base classes for configurations shared amoung steps. 
7  * 
8  * 
9  */
10 //====================================================================
11 /** 
12  * Base class for detector configuration. By default, everything is on
13  * except ACORDE.
14  */
15 struct VirtualDetCfg 
16 {
17   virtual Bool_t UseABSO()   const { return true;  }
18   virtual Bool_t UseACORDE() const { return false; }
19   virtual Bool_t UseDIPO()   const { return true;  }
20   virtual Bool_t UseEMCAL()  const { return true;  }
21   virtual Bool_t UseFMD()    const { return true;  }
22   virtual Bool_t UseFRAME()  const { return true;  }
23   virtual Bool_t UseHALL()   const { return true;  }
24   virtual Bool_t UseITS()    const { return true;  }
25   virtual Bool_t UseMAG()    const { return true;  }
26   virtual Bool_t UseMUON()   const { return true;  }
27   virtual Bool_t UsePHOS()   const { return true;  }
28   virtual Bool_t UsePIPE()   const { return true;  }
29   virtual Bool_t UsePMD()    const { return true;  }
30   virtual Bool_t UseHMPID()  const { return true;  }
31   virtual Bool_t UseSHIL()   const { return true;  }
32   virtual Bool_t UseT0()     const { return true;  }
33   virtual Bool_t UseTOF()    const { return true;  }
34   virtual Bool_t UseTPC()    const { return true;  }
35   virtual Bool_t UseTRD()    const { return true;  }
36   virtual Bool_t UseVZERO()  const { return true;  }
37   virtual Bool_t UseZDC()    const { return true;  }
38   virtual void Print() 
39   {
40     Printf("ABSO:   %3s", UseABSO()    ? "yes" : "no");
41     Printf("ACORDE: %3s", UseACORDE()  ? "yes" : "no");
42     Printf("DIPO:   %3s", UseDIPO()    ? "yes" : "no");
43     Printf("EMCAL:  %3s", UseEMCAL()   ? "yes" : "no");
44     Printf("FMD:    %3s", UseFMD()     ? "yes" : "no");
45     Printf("FRAME:  %3s", UseFRAME()   ? "yes" : "no");
46     Printf("HALL:   %3s", UseHALL()    ? "yes" : "no");
47     Printf("ITS:    %3s", UseITS()     ? "yes" : "no");
48     Printf("MAG:    %3s", UseMAG()     ? "yes" : "no");
49     Printf("MUON:   %3s", UseMUON()    ? "yes" : "no");
50     Printf("PHOS:   %3s", UsePHOS()    ? "yes" : "no");
51     Printf("PIPE:   %3s", UsePIPE()    ? "yes" : "no");
52     Printf("PMD:    %3s", UsePMD()     ? "yes" : "no");
53     Printf("HMPID:  %3s", UseHMPID()   ? "yes" : "no");
54     Printf("SHIL:   %3s", UseSHIL()    ? "yes" : "no");
55     Printf("T0:     %3s", UseT0()      ? "yes" : "no");
56     Printf("TOF:    %3s", UseTOF()     ? "yes" : "no");
57     Printf("TPC:    %3s", UseTPC()     ? "yes" : "no");
58     Printf("TRD:    %3s", UseTRD()     ? "yes" : "no");
59     Printf("VZERO:  %3s", UseVZERO()   ? "yes" : "no");
60     Printf("ZDC:    %3s", UseZDC()     ? "yes" : "no");
61   }
62   /** 
63    * Get the string of enabled detectors for local reconstruction.
64    * 
65    * @param enable On return, contains string of enable detectors
66    */
67   void GetRecoString(TString& enable) const
68   {
69     if (UseITS())       Append2Str(enable, "ITS"); 
70     if (UseTPC())       Append2Str(enable, "TPC"); 
71     if (UseTRD())       Append2Str(enable, "TRD"); 
72     if (UseTOF())       Append2Str(enable, "TOF"); 
73     if (UsePHOS())      Append2Str(enable, "PHOS"); 
74     if (UseHMPID())     Append2Str(enable, "HMPID"); 
75     if (UseEMCAL())     Append2Str(enable, "EMCAL"); 
76     if (UseMUON())      Append2Str(enable, "MUON"); 
77     if (UseFMD())       Append2Str(enable, "FMD"); 
78     if (UseZDC())       Append2Str(enable, "ZDC"); 
79     if (UsePMD())       Append2Str(enable, "PMD"); 
80     if (UseT0())        Append2Str(enable, "T0"); 
81     if (UseVZERO())     Append2Str(enable, "VZERO");
82   }
83   /** 
84    * Get the string of detectors for which we should make Summable
85    * Digits
86    * 
87    * @param sDigits On returm contains the string of enable detectors
88    */
89   void GetSDigitString(TString& sDigits) const 
90   {
91     if (UseTRD())       Append2Str(sDigits, "TRD"); 
92     if (UseTOF())       Append2Str(sDigits, "TOF"); 
93     if (UsePHOS())      Append2Str(sDigits, "PHOS"); 
94     if (UseHMPID())     Append2Str(sDigits, "HMPID"); 
95     if (UseEMCAL())     Append2Str(sDigits, "EMCAL"); 
96     if (UseMUON())      Append2Str(sDigits, "MUON"); 
97     if (UseFMD())       Append2Str(sDigits, "FMD"); 
98     if (UseZDC())       Append2Str(sDigits, "ZDC"); 
99     if (UsePMD())       Append2Str(sDigits, "PMD"); 
100     if (UseT0())        Append2Str(sDigits, "T0"); 
101     if (UseVZERO())     Append2Str(sDigits, "VZERO");
102   }
103   /** 
104    * Get the sting of detectors for which we should do the hit to
105    * digit conversion directly.
106    * 
107    * @param fromHits On returm contains the string of enable detectors
108    */
109   void GetHits2DigitsString(TString& fromHits) const
110   {
111     if (UseITS())       Append2Str(fromHits, "ITS");
112     if (UseTPC())       Append2Str(fromHits, "TPC");
113   }
114   /** 
115    * Append a C style string to a string, possibly adding a space before
116    * 
117    * @param str     Where to append
118    * @param append  What to append
119    */
120   static void Append2Str(TString& str, const char* append)
121   {
122     if (!str.IsNull()) str.Append(" ");
123     str.Append(append);
124   }
125   
126 };
127 /** Global variable */
128 VirtualDetCfg* detCfg = 0;
129
130 //====================================================================
131 /**
132  * Base class for the OCDG configration 
133  */
134 struct VirtualOCDBCfg
135 {
136   /** 
137    * This member function must return the default prefix. 
138    * 
139    * @return Prefix of OCDB specific storages
140    */
141   virtual const char* Prefix() const { return ""; }
142   /** 
143    * This member function should define the real setup. 
144    * 
145    * @param forSim Whether we're setting up for simulations or not 
146    */
147   virtual void Init(Bool_t forSim) 
148   {
149     ::Fatal("VirtualOCDBConfig", "Dummy init called - redefine!");
150   }
151   /** 
152    * Set the specific storage for a given key (possibly wild-carded). 
153    * 
154    * @param key    Key 
155    * @param ideal  Whether it is residual or ideal
156    */
157   void AddStore(const char*    key, 
158                 Bool_t         ideal)
159   {
160     AliCDBManager* cdb = AliCDBManager::Instance();
161     const char* prefix = Prefix();
162     TString     path   = Form("alien://Folder=/alice/simulation/%s/%s",
163                               prefix, !ideal ? "Residual" : "Ideal");
164     ::Info("AddStore", "%s -> %s", key, path.Data());
165     cdb->SetSpecificStorage(key, path);
166   }
167 };
168
169 /** Global variable */
170 VirtualOCDBCfg* ocdbCfg = 0;
171
172 //====================================================================
173 /** 
174  * Event generator configuration 
175  * 
176  */
177 struct VirtualEGCfg 
178 {
179   TString runType;
180   VirtualEGCfg() : runType("") {}
181   virtual ~VirtualEGCfg() {}
182   /**
183    * Load the general libraries needed
184    *
185    */
186   static void LoadGen(const TString& runType) {
187     if (!gROOT->GetClass("AliStructFuncType"))
188       gSystem->Load("liblhapdf");      // Parton density functions
189     if (!gROOT->GetClass("TPythia6"))
190       gSystem->Load("libEGPythia6");   // TGenerator interface
191     if (!runType.EqualTo("hydjet", TString::kIgnoreCase))
192       LoadPythia(false);
193   }
194
195   /**
196    * Load the pythia libraries
197    *
198    * @param vers Optional version post-fix
199    */
200   static void LoadPythia(Bool_t gen=true, const char* vers="6.4.21")
201   {
202     if (gen) LoadGen("");
203     char m = vers[0];
204     if (gROOT->GetClass(Form("AliPythia6%c", m))) return;
205     gSystem->Load(Form("libpythia%s", vers));
206     gSystem->Load(Form("libAliPythia%c", m));
207   }
208   /**
209    * Load HIJING libraries
210    */
211   static void LoadHijing()
212   {
213     LoadPythia();
214     if (gROOT->GetClass("THijing")) return;
215     gSystem->Load("libhijing");
216     gSystem->Load("libTHijing");
217     AliPDG::AddParticlesToPdgDataBase();
218   }
219   /**
220    * Load HydJet libraries
221    */
222   static void LoadHydjet()
223   {
224     if (gROOT->GetClass("TUHKMgen")) return;
225     gSystem->Load("libTUHKMgen");
226   }
227   /**
228    * Load DPMJet libraries
229    */
230   static void LoadDpmjet()
231   {
232     LoadPythia();
233     if (gROOT->GetClass("TDPMjet")) return;
234     gSystem->Load("libdpmjet");
235     gSystem->Load("libTDPMjet");
236   }
237   /**
238    * Load AMPT libraries
239    */
240   static void LoadAmpt()
241   {
242     LoadPythia();
243     if (gROOT->GetClass("TAmpt")) return;
244     gSystem->Load("libampt");
245     gSystem->Load("libTAmpt");
246   }
247   /**
248    * Make the generator
249    *
250    * @param rt    Event generator identifier 
251    * @param b1    Least impact parameter 
252    * @param b2    Largest impact parameter 
253    * @param smear If true, smear interaction per event 
254    *
255    * @return Point to newly allocated generator or null
256    * 
257    */
258   AliGenerator* MakeGenerator(const TString& rt, 
259                               Float_t b1, 
260                               Float_t b2, 
261                               Bool_t smear=true)
262   {
263     if (rt.IsNull()) { 
264       ::Fatal("MakeGenerator", "No EG spec given");
265       return 0;
266     }
267
268     TString runType = rt;
269     runType.ToLower();
270
271     AliGenerator* g = CreateGenerator(runType,b1,b2);
272     if (g && smear) g->SetVertexSmear(AliGenerator::kPerEvent);
273
274     return g;
275   }
276   /**
277    * Make our decayer
278    *
279    * @param rt The EG to use 
280    *
281    * @return Newly allocated decayer or null
282    */
283   TVirtualMCDecayer* MakeDecayer(const TString& rt)
284   {
285     if (rt.IsNull()) { 
286       ::Fatal("MakeGenerator", "No EG spec given");
287       return 0;
288     }
289
290     TString runType = rt;
291     rt.ToLower();
292
293     TVirtualMCDecayer* decayer = CreateDecayer(runType);
294
295     if (decayer) decayer->Init();
296     return decayer;
297   }
298 protected:
299   /** 
300    * Create the generator.  This function must be defined in a derived class. 
301    * 
302    * @param runType The generator ID (all lower case)
303    * @param b1      Least impact parameter 
304    * @param b2      Largest impact parameter 
305    * 
306    * @return Must return a pointer to a new AliGenerator or null
307    */
308   virtual AliGenerator* CreateGenerator(const TString& runType, 
309                                         Float_t b1, 
310                                         Float_t b2) = 0;
311   /** 
312    * Create the decayer.  This function must be defined in a derived class. 
313    * 
314    * @param runType The generator ID (all lower case)
315    * 
316    * @return Must return a pointer to a new TVirtualMCDecayer or null
317    */
318   virtual TVirtualMCDecayer* CreateDecayer(const TString& runType) = 0;
319
320 };
321 /** Global variable */
322 VirtualEGCfg* egCfg = 0;
323
324 //====================================================================
325 /**
326  * Base class for trains 
327  * 
328  */
329 struct VirtualTrain 
330 {
331
332
333   /** 
334    * Run this train 
335    * 
336    * @param run 
337    * @param xmlFile 
338    * @param stage 
339    * @param cdb 
340    * 
341    * @return 
342    */
343   Bool_t Run(UInt_t      run, 
344              const char* xmlFile = "wn.xml", 
345              Int_t       stage   = 0, 
346              const char* cdb     = "raw://")
347   {
348     // --- Load configuration script ---------------------------------
349     LoadConfig();
350     
351     // --- Set-up for CDB access through Grid ------------------------
352     TString cdbString(cdb);
353     if (cdbString.Contains("raw://")) {
354       TGrid::Connect("alien://");
355       if (!gGrid || !gGrid->IsConnected()) {
356         ::Error("Run", "No grid connection");
357         return false;
358       }  
359     }
360     
361     // --- Some environment variables --------------------------------
362     // Temp dir is here, and compilation is here too 
363     gSystem->Setenv("TMPDIR", gSystem->pwd());
364     gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
365
366     // --- Now load common libraries ---------------------------------
367     LoadBaseLibraries();
368     
369     // --- Now create and configure manager --------------------------
370     AliAnalysisManager *mgr  = new AliAnalysisManager(GetName(), 
371                                                       "Production train");
372     mgr->SetRunFromPath(grp->run);
373     
374     // --- Create ESD input handler ------------------------------------
375     AliESDInputHandlerRP *esdHandler = new AliESDInputHandlerRP();
376     mgr->SetInputEventHandler(esdHandler);
377     if (UseFriends()) {
378       esdHandler->SetReadFriends(kTRUE);
379       esdHandler->SetActiveBranches("ESDfriend");
380     }
381
382     // --- Monte Carlo handler -----------------------------------------
383     if (UseMC()) {
384       AliMCEventHandler* mcHandler = new AliMCEventHandler();
385       mgr->SetMCtruthEventHandler(mcHandler);
386       mcHandler->SetPreReadMode(1);
387       mcHandler->SetReadTR(true);
388     }
389     // --- AOD output handler ----------------------------------------
390     if (MakeAOD()) {
391       AliAODHandler* aodHandler   = new AliAODHandler();
392       aodHandler->SetOutputFileName("AliAOD.root");
393       mgr->SetOutputEventHandler(aodHandler);
394     }
395     
396     // --- Call user routine for adding tasks ------------------------
397     if (!AddTasks()) return false;
398     
399     // --- Check if we are to merge ----------------------------------
400     if (stage > 0) 
401       return Merge(xmlfile, stage);
402
403     // --- Otherwise run the train -----------------------------------
404     TChain* chain = CreateChain();
405     if (!chain) return false;
406
407     TStopwatch timer;
408     timer.Start();
409     if (!mgr->InitAnalysis()) {
410       ::Error("Run", "Failed to initialize the train");
411       return false;
412     }
413
414     mgr->PrintStatus();
415     mgr->SetSkipTerminate(kTRUE);
416     mgr->StartAnalysis("local", chain);
417     timer.Print();
418     
419   }
420   /** 
421    * Merge requested files 
422    * 
423    * @param dir    Output directory 
424    * @param stage  Stage 
425    * 
426    * @return true on success 
427    */
428   Bool_t Merge(const char* dir, Int_t stage)
429   {
430
431     TStopwatch    timer;     
432     timer.Start();
433     TString       outputDir     = dir;
434     Bool_t        final         = outputDir.Contains("Stage");
435     TCollection*  outputFiles   = GetFilesToMerge(stage, final);
436     if (!outputFiles) { 
437       ::Warning("Merge", "Nothing to merge");
438       return true;
439     }
440     TIter       iter(outputFiles);
441     TObjString* str           = 0;
442     Bool_t      merged        = kTRUE;
443     while((str = static_cast<TObjString*>(iter()))) {
444       TString& outputFile = str->GetString();
445       // Skip already merged outputs
446       if (!gSystem->AccessPathName(outputFile)) {
447         ::Warning("Merge","Output file <%s> found. Not merging again.",
448                   outputFile.Data());
449         continue;
450       }
451       merged = AliAnalysisAlien::MergeOutput(outputFile, 
452                                              outputDir, 
453                                              10, 
454                                              stage);
455       if (merged) continue; 
456       
457       ::Error("Merge", "Cannot merge %s\n", outputFile.Data());
458     }
459     // --- possible merge file information files ---------------------
460     if (MergeFileInfo()) { 
461       TString infolog = "fileinfo.log";
462       AliAnalysisAlien::MergeInfo(infolog, dir); 
463     }
464
465     // --- If not final stage, get out here --------------------------
466     if (!final) { 
467       ValidateOutput();
468       timer.Print();
469       return true;
470     }
471     
472     // --- set up and run termiante ----------------------------------
473     AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
474     mgr->SetSkipTerminate(kFALSE);
475     if (!mgr->InitAnalysis()) {
476       ::Error("Merge", "Failed to initialize the train");
477       return false;
478     }
479     
480     mgr->PrintStatus();
481     mgr->StartAnalysis("gridterminate", (TTree*)0);
482     ValidateOutput();
483     timer.Print();
484
485     return true;
486   }
487                
488   /** 
489    * Load a library/module 
490    * 
491    * @param module Library/module name 
492    * 
493    * @return true on success
494    */
495   Bool_t LoadLibrary(const char *module)
496   {
497     // Load a module library in a given mode. Reports success.
498     Int_t result = 0;
499     TString mod(module);
500     ::Info("LoadLibrary", "Loading %s", module);
501     gROOT->IncreaseDirLevel();
502
503     if (mod.IsNull()) {
504       ::Error("AnalysisTrainNew.C::LoadLibrary", "Empty module name");
505       gROOT->DecreaseDirLevel();
506       return kFALSE;
507     }
508
509     // If a library is specified, just load it
510     if (mod.EndsWith(".so")) {
511       mod.Remove(mod.Index(".so"));
512       ::Info("LoadLibrary", "Loading .so: %s", mod.Data()); 
513       result = gSystem->Load(mod);
514       if (result < 0) {
515         ::Error("AnalysisTrainNew.C::LoadLibrary", 
516                 "Could not load library %s", module);
517       }
518       gROOT->DecreaseDirLevel();      
519       return (result >= 0);
520     }
521     // Check if the library is already loaded
522     if (strlen(gSystem->GetLibraries(Form("%s.so", module), "", kFALSE)) > 0) {
523       ::Info("LoadLibrary", "Module %s.so already loaded", module);
524       gROOT->DecreaseDirLevel();      
525       return kTRUE;
526     }
527
528     ::Info("LoadLibrary", "Trying to load lib%s.so", module);
529     result = gSystem->Load(Form("lib%s.so", module));
530     if (result < 0)
531       ::Error("AnalysisTrainNew.C::LoadLibrary", 
532               "Could not load module %s", module);
533     ::Info("LoadLibrary", "Module %s, successfully loaded", module);
534     gROOT->DecreaseDirLevel();      
535     return (result >= 0);
536   }
537   /** 
538    * Load common libraries 
539    * 
540    * @return true on sucess 
541    */
542   virtual Bool_t LoadBaseLibraries()
543   {
544     // Load common analysis libraries.
545     if (!gSystem->Getenv("ALICE_ROOT")) {
546       ::Error("LoadBaseLibraries", 
547               "Analysis trains requires that analysis libraries are "
548               "compiled with a local AliRoot");
549       return false;
550     }
551
552     Bool_t success = true;
553     // Load framework classes. Par option ignored here.
554     success &= LoadLibrary("libSTEERBase.so");
555     success &= LoadLibrary("libESD.so");
556     success &= LoadLibrary("libAOD.so");
557     success &= LoadLibrary("libANALYSIS.so");
558     success &= LoadLibrary("libOADB.so");
559     success &= LoadLibrary("libANALYSISalice.so");
560     success &= LoadLibrary("libESDfilter.so");
561     success &= LoadLibrary("libCORRFW.so");
562     success &= LoadLibrary("libPWGPP.so");
563     gROOT->ProcessLine(".include $ALICE_ROOT/include");
564     if (success) {
565       ::Info("LoadBaseLibraries", 
566              "Load common libraries:    SUCCESS");
567       ::Info("LoadBaseLibraries", 
568              "Include path for Aclic compilation:\n%s",
569              gSystem->GetIncludePath());
570     } else {
571       ::Info("LoadBaseLibraries", 
572              "Load common libraries:    FAILED");
573     }
574     return success;
575   }
576   /** 
577    * Create the input chain
578    * 
579    * @return Pointer to newly allocated train 
580    */
581   TChain* CreateChain()
582   {
583     if (gSystem->AccessPathName("AliESDs.root")) {
584       ::Error("CreateChain", 
585               "File: AliESDs.root not in ./data dir");
586       return 0;
587     }
588     
589     // Create the input chain
590     TChain* chain = new TChain("esdTree");
591     chain->Add("AliESDs.root");
592     if (!chain->GetNtrees()) {
593       delete chain;
594       chain = 0;
595     }
596
597     return chain;
598   }
599   /** 
600    * Helper function to make @c outputs_valid file 
601    * 
602    */
603   void ValidateOutput()
604   {
605     std::ofstream out;
606     out.open("outputs_valid", ios::out);
607     out.close();    
608   }  
609
610   /** 
611    * @{ 
612    * @name Functions to overload 
613    */
614   /** 
615    * Load the configuration script. Override to load specific script.
616    */
617   virtual void LoadConfig() {};
618   /** 
619    * Override to set a name of the analysis manager 
620    * 
621    * @return Name of analysis manager 
622    */
623   virtual const char* GetName() const { return "dummy"; }
624   /** 
625    * Override to return true if friends are needed. 
626    * 
627    * @return false
628    */
629   virtual Bool_t UseFriends() const { return false; }
630   /** 
631    * Override to return true if MC info is needed
632    * 
633    * @return false
634    */
635   virtual Bool_t UseMC() const { return false; }
636   /** 
637    * Override to return true if AODs should be made 
638    * 
639    * @return false
640    */
641   virtual Bool_t MakeAOD() const { return false; }
642   /**
643    * User rountine for adding tasks. Override to add tasks to the
644    * train.
645    *
646    * @return true
647    */
648   virtual Bool_t AddTasks() const { return true; }
649   /** 
650    * Override to return true to merge file information files. 
651    * 
652    * @return false
653    */
654   virtual Bool_t MergFileInfo() const { return false; }
655   /** 
656    * Return the list of ouput files (TObjString objects)
657    *
658    * @param stage Merge stage 
659    * @param final Final merging (also terminate)
660    *
661    * @return Pointer to TCollection. 
662    */
663   virtual TCollection* GetFilesToMerge(Int_t stage, Bool_t final) const 
664   { 
665     return 0; 
666   }
667 };
668
669
670
671
672 //====================================================================
673 /**
674  * A function so that we can do TROOT::Macro.  Does nothing but print a message.
675  *
676  */
677 void BaseConfig()
678 {
679   Info("", "Defined base classes for configuration");
680 }
681 //
682 // EOF
683 //
684