.so cleanup: no .so ext to GetLibraries()
[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   virtual Bool_t IsLego() const { return false; }
183     /** 
184    * Set the default generator based on the beam type 
185    *
186    * - p-p PYTHIA
187    * - p-A or A-p DPMJet
188    * - A-A Hijing 
189    */
190   static const char* DeduceRunType()
191   {
192     if      (grp->IsPP())                return "pythia";
193     else if (grp->IsPA() || grp->IsAP()) return "dpmjet";
194     else if (grp->IsAA())                return "hijing";
195     return "hijing";
196   }
197
198   static void LoadLibrary(const TString& name,
199                           const TString& cls="")
200   {
201     // If we're looking for a specific class, check that first, and
202     // if available, do nothing;
203     if (!cls.IsNull() && gROOT->GetClass(cls)) return;
204
205     // Now check the list of loaded and linekd libraries 
206     TString libs(gSystem->GetLibraries("", "SD"));
207
208     // IF already in the list, do nothing 
209     if (libs.Contains(name)) return;
210
211     // Otherwise load the library 
212     gSystem->Load(name);
213   }
214   /**
215    * Load the general libraries needed
216    *
217    */
218   static void LoadGen(const TString& runType) {
219     LoadLibrary("liblhapdf","AliStructFuncType"); // Parton density functions
220     LoadLibrary("libEGPythia6","TPythia6");       // TGenerator interface
221     if (!runType.EqualTo("hydjet", TString::kIgnoreCase))
222       LoadPythia(false);
223   }
224
225   /**
226    * Load the pythia libraries
227    *
228    * @param vers Optional version post-fix
229    */
230   static void LoadPythia(Bool_t gen=true, const char* vers="6.4.21")
231   {
232     if (gen) LoadGen("");
233     char m = vers[0];
234     if (gROOT->GetClass(Form("AliPythia6%c", m))) return;
235
236     LoadLibrary("libmicrocern");
237     LoadLibrary(Form("libpythia%s",vers));
238     LoadLibrary(Form("libAliPythia%c", m));
239   }
240   /**
241    * Load HIJING libraries
242    */
243   static void LoadHijing()
244   {
245     LoadPythia();
246     if (gROOT->GetClass("THijing")) return;
247     LoadLibrary("libhijing");
248     LoadLibrary("libTHijing");
249     AliPDG::AddParticlesToPdgDataBase();
250   }
251   /**
252    * Load HydJet libraries
253    */
254   static void LoadHydjet()
255   {
256     LoadLibrary("libTUHKMgen","TUHKMgen");
257   }
258   /**
259    * Load DPMJet libraries
260    */
261   static void LoadDpmjet()
262   {
263     LoadPythia();
264     if (gROOT->GetClass("TDPMjet")) return;
265     LoadLibrary("libdpmjet");
266     LoadLibrary("libTDPMjet");
267   }
268   /**
269    * Load AMPT libraries
270    */
271   static void LoadAmpt()
272   {
273     LoadPythia();
274     if (gROOT->GetClass("TAmpt")) return;
275     LoadLibrary("libampt");
276     LoadLibrary("libTAmpt");
277   }
278   /**
279    * Make the generator
280    *
281    * @param rt    Event generator identifier 
282    * @param b1    Least impact parameter 
283    * @param b2    Largest impact parameter 
284    * @param smear If true, smear interaction per event 
285    *
286    * @return Point to newly allocated generator or null
287    * 
288    */
289   AliGenerator* MakeGenerator(const TString& rt, 
290                               Float_t b1, 
291                               Float_t b2, 
292                               Bool_t smear=true)
293   {
294     if (rt.IsNull()) { 
295       ::Fatal("MakeGenerator", "No EG spec given");
296       return 0;
297     }
298
299     TString runType = rt;
300     runType.ToLower();
301
302     AliGenerator* g = CreateGenerator(runType,b1,b2);
303     if (g && smear) g->SetVertexSmear(AliGenerator::kPerEvent);
304
305     return g;
306   }
307   /**
308    * Make our decayer
309    *
310    * @param rt The EG to use 
311    *
312    * @return Newly allocated decayer or null
313    */
314   TVirtualMCDecayer* MakeDecayer(const TString& rt)
315   {
316     if (rt.IsNull()) { 
317       ::Fatal("MakeGenerator", "No EG spec given");
318       return 0;
319     }
320
321     TString runType = rt;
322     rt.ToLower();
323
324     TVirtualMCDecayer* decayer = CreateDecayer(runType);
325
326     if (decayer) decayer->Init();
327     return decayer;
328   }
329 protected:
330   /** 
331    * Create the generator.  This function must be defined in a derived class. 
332    * 
333    * @param runType The generator ID (all lower case)
334    * @param b1      Least impact parameter 
335    * @param b2      Largest impact parameter 
336    * 
337    * @return Must return a pointer to a new AliGenerator or null
338    */
339   virtual AliGenerator* CreateGenerator(const TString& runType, 
340                                         Float_t b1, 
341                                         Float_t b2) = 0;
342   /** 
343    * Create the decayer.  This function must be defined in a derived class. 
344    * 
345    * @param runType The generator ID (all lower case)
346    * 
347    * @return Must return a pointer to a new TVirtualMCDecayer or null
348    */
349   virtual TVirtualMCDecayer* CreateDecayer(const TString& runType) = 0;
350
351 };
352 /** Global variable */
353 VirtualEGCfg* egCfg = 0;
354
355 //====================================================================
356 /**
357  * Base class for trains 
358  * 
359  */
360 struct VirtualTrain 
361 {
362
363
364   /** 
365    * Run this train 
366    * 
367    * @param run 
368    * @param xmlFile 
369    * @param stage 
370    * @param cdb 
371    * 
372    * @return 
373    */
374   Bool_t Run(UInt_t      run, 
375              const char* xmlFile = "wn.xml", 
376              Int_t       stage   = 0, 
377              const char* cdb     = "raw://")
378   {
379     // --- Load configuration script ---------------------------------
380     LoadConfig();
381     
382     // --- Set-up for CDB access through Grid ------------------------
383     TString cdbString(cdb);
384     if (cdbString.Contains("raw://")) {
385       TGrid::Connect("alien://");
386       if (!gGrid || !gGrid->IsConnected()) {
387         ::Error("Run", "No grid connection");
388         return false;
389       }  
390     }
391     
392     // --- Some environment variables --------------------------------
393     // Temp dir is here, and compilation is here too 
394     gSystem->Setenv("TMPDIR", gSystem->pwd());
395     gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
396
397     // --- Now load common libraries ---------------------------------
398     LoadBaseLibraries();
399     
400     // --- Now create and configure manager --------------------------
401     AliAnalysisManager *mgr  = new AliAnalysisManager(GetName(), 
402                                                       "Production train");
403     mgr->SetRunFromPath(grp->run);
404     
405     // --- Create ESD input handler ------------------------------------
406     AliESDInputHandlerRP *esdHandler = new AliESDInputHandlerRP();
407     mgr->SetInputEventHandler(esdHandler);
408     if (UseFriends()) {
409       esdHandler->SetReadFriends(kTRUE);
410       esdHandler->SetActiveBranches("ESDfriend");
411     }
412
413     // --- Monte Carlo handler -----------------------------------------
414     if (UseMC()) {
415       AliMCEventHandler* mcHandler = new AliMCEventHandler();
416       mgr->SetMCtruthEventHandler(mcHandler);
417       mcHandler->SetPreReadMode(1);
418       mcHandler->SetReadTR(true);
419     }
420     // --- AOD output handler ----------------------------------------
421     if (MakeAOD()) {
422       AliAODHandler* aodHandler   = new AliAODHandler();
423       aodHandler->SetOutputFileName("AliAOD.root");
424       mgr->SetOutputEventHandler(aodHandler);
425     }
426     
427     // --- Call user routine for adding tasks ------------------------
428     if (!AddTasks()) return false;
429     
430     // --- Check if we are to merge ----------------------------------
431     if (stage > 0) 
432       return Merge(xmlfile, stage);
433
434     // --- Otherwise run the train -----------------------------------
435     TChain* chain = CreateChain();
436     if (!chain) return false;
437
438     TStopwatch timer;
439     timer.Start();
440     if (!mgr->InitAnalysis()) {
441       ::Error("Run", "Failed to initialize the train");
442       return false;
443     }
444
445     mgr->PrintStatus();
446     mgr->SetSkipTerminate(kTRUE);
447     mgr->StartAnalysis("local", chain);
448     timer.Print();
449     
450   }
451   /** 
452    * Merge requested files 
453    * 
454    * @param dir    Output directory 
455    * @param stage  Stage 
456    * 
457    * @return true on success 
458    */
459   Bool_t Merge(const char* dir, Int_t stage)
460   {
461
462     TStopwatch    timer;     
463     timer.Start();
464     TString       outputDir     = dir;
465     Bool_t        final         = outputDir.Contains("Stage");
466     TCollection*  outputFiles   = GetFilesToMerge(stage, final);
467     if (!outputFiles) { 
468       ::Warning("Merge", "Nothing to merge");
469       return true;
470     }
471     TIter       iter(outputFiles);
472     TObjString* str           = 0;
473     Bool_t      merged        = kTRUE;
474     while((str = static_cast<TObjString*>(iter()))) {
475       TString& outputFile = str->GetString();
476       // Skip already merged outputs
477       if (!gSystem->AccessPathName(outputFile)) {
478         ::Warning("Merge","Output file <%s> found. Not merging again.",
479                   outputFile.Data());
480         continue;
481       }
482       merged = AliAnalysisAlien::MergeOutput(outputFile, 
483                                              outputDir, 
484                                              10, 
485                                              stage);
486       if (merged) continue; 
487       
488       ::Error("Merge", "Cannot merge %s\n", outputFile.Data());
489     }
490     // --- possible merge file information files ---------------------
491     if (MergeFileInfo()) { 
492       TString infolog = "fileinfo.log";
493       AliAnalysisAlien::MergeInfo(infolog, dir); 
494     }
495
496     // --- If not final stage, get out here --------------------------
497     if (!final) { 
498       ValidateOutput();
499       timer.Print();
500       return true;
501     }
502     
503     // --- set up and run termiante ----------------------------------
504     AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
505     mgr->SetSkipTerminate(kFALSE);
506     if (!mgr->InitAnalysis()) {
507       ::Error("Merge", "Failed to initialize the train");
508       return false;
509     }
510     
511     mgr->PrintStatus();
512     mgr->StartAnalysis("gridterminate", (TTree*)0);
513     ValidateOutput();
514     timer.Print();
515
516     return true;
517   }
518                
519   /** 
520    * Load a library/module 
521    * 
522    * @param module Library/module name 
523    * 
524    * @return true on success
525    */
526   Bool_t LoadLibrary(const char *module)
527   {
528     // Load a module library in a given mode. Reports success.
529     Int_t result = 0;
530     TString mod(module);
531     ::Info("LoadLibrary", "Loading %s", module);
532     gROOT->IncreaseDirLevel();
533
534     if (mod.IsNull()) {
535       ::Error("LoadLibrary", "Empty module name");
536       gROOT->DecreaseDirLevel();
537       return kFALSE;
538     }
539
540     // If a library is specified, just load it
541     if (mod.EndsWith(".so")) {
542       mod.Remove(mod.Index(".so"));
543       ::Info("LoadLibrary", "Loading .so: %s", mod.Data()); 
544       result = gSystem->Load(mod);
545       if (result < 0) {
546         ::Error("oadLibrary", "Could not load library %s", module);
547       }
548       gROOT->DecreaseDirLevel();      
549       return (result >= 0);
550     }
551     // Check if the library is already loaded
552     if (strlen(gSystem->GetLibraries(module, "", kFALSE)) > 0) {
553       ::Info("LoadLibrary", "Module %s.so already loaded", module);
554       gROOT->DecreaseDirLevel();      
555       return kTRUE;
556     }
557
558     ::Info("LoadLibrary", "Trying to load lib%s.so", module);
559     result = gSystem->Load(Form("lib%s", module));
560     if (result < 0)
561       ::Error("LoadLibrary", "Could not load module %s", module);
562     ::Info("LoadLibrary", "Module %s, successfully loaded", module);
563     gROOT->DecreaseDirLevel();      
564     return (result >= 0);
565   }
566   /** 
567    * Load common libraries 
568    * 
569    * @return true on sucess 
570    */
571   virtual Bool_t LoadBaseLibraries()
572   {
573     // Load common analysis libraries.
574     if (!gSystem->Getenv("ALICE_ROOT")) {
575       ::Error("LoadBaseLibraries", 
576               "Analysis trains requires that analysis libraries are "
577               "compiled with a local AliRoot");
578       return false;
579     }
580
581     Bool_t success = true;
582     // Load framework classes. Par option ignored here.
583     success &= LoadLibrary("libSTEERBase.so");
584     success &= LoadLibrary("libESD.so");
585     success &= LoadLibrary("libAOD.so");
586     success &= LoadLibrary("libANALYSIS.so");
587     success &= LoadLibrary("libOADB.so");
588     success &= LoadLibrary("libANALYSISalice.so");
589     success &= LoadLibrary("libESDfilter.so");
590     success &= LoadLibrary("libCORRFW.so");
591     success &= LoadLibrary("libPWGPP.so");
592     gROOT->ProcessLine(".include $ALICE_ROOT/include");
593     if (success) {
594       ::Info("LoadBaseLibraries", 
595              "Load common libraries:    SUCCESS");
596       ::Info("LoadBaseLibraries", 
597              "Include path for Aclic compilation:\n%s",
598              gSystem->GetIncludePath());
599     } else {
600       ::Info("LoadBaseLibraries", 
601              "Load common libraries:    FAILED");
602     }
603     return success;
604   }
605   /** 
606    * Create the input chain
607    * 
608    * @return Pointer to newly allocated train 
609    */
610   TChain* CreateChain()
611   {
612     if (gSystem->AccessPathName("AliESDs.root")) {
613       ::Error("CreateChain", 
614               "File: AliESDs.root not in ./data dir");
615       return 0;
616     }
617     
618     // Create the input chain
619     TChain* chain = new TChain("esdTree");
620     chain->Add("AliESDs.root");
621     if (!chain->GetNtrees()) {
622       delete chain;
623       chain = 0;
624     }
625
626     return chain;
627   }
628   /** 
629    * Helper function to make @c outputs_valid file 
630    * 
631    */
632   void ValidateOutput()
633   {
634     std::ofstream out;
635     out.open("outputs_valid", ios::out);
636     out.close();    
637   }  
638
639   /** 
640    * @{ 
641    * @name Functions to overload 
642    */
643   /** 
644    * Load the configuration script. Override to load specific script.
645    */
646   virtual void LoadConfig() {};
647   /** 
648    * Override to set a name of the analysis manager 
649    * 
650    * @return Name of analysis manager 
651    */
652   virtual const char* GetName() const { return "dummy"; }
653   /** 
654    * Override to return true if friends are needed. 
655    * 
656    * @return false
657    */
658   virtual Bool_t UseFriends() const { return false; }
659   /** 
660    * Override to return true if MC info is needed
661    * 
662    * @return false
663    */
664   virtual Bool_t UseMC() const { return false; }
665   /** 
666    * Override to return true if AODs should be made 
667    * 
668    * @return false
669    */
670   virtual Bool_t MakeAOD() const { return false; }
671   /**
672    * User rountine for adding tasks. Override to add tasks to the
673    * train.
674    *
675    * @return true
676    */
677   virtual Bool_t AddTasks() const { return true; }
678   /** 
679    * Override to return true to merge file information files. 
680    * 
681    * @return false
682    */
683   virtual Bool_t MergeFileInfo() const { return false; }
684   /** 
685    * Return the list of ouput files (TObjString objects)
686    *
687    * @param stage Merge stage 
688    * @param final Final merging (also terminate)
689    *
690    * @return Pointer to TCollection. 
691    */
692   virtual TCollection* GetFilesToMerge(Int_t stage, Bool_t final) const 
693   { 
694     return 0; 
695   }
696 };
697
698
699
700
701 //====================================================================
702 /**
703  * A function so that we can do TROOT::Macro.  Does nothing but print a message.
704  *
705  */
706 void BaseConfig()
707 {
708   Info("", "Defined base classes for configuration");
709 }
710 //
711 // EOF
712 //
713