b46b7a285dc7503eb88a3d5e4efa96ac5a7f40d3
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / Helper.C
1 /**
2  * @defgroup pwglf_forward_trains_helper Analysis helpers
3  *
4  * @ingroup pwglf_forward_trains
5  * 
6  * 
7  */
8 /**
9  * @file   Helper.C
10  * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
11  * @date   Tue Oct 16 19:00:17 2012
12  * 
13  * @brief  Base class for analysis helpers
14  * 
15  * @ingroup pwglf_forward_trains_helper
16  * 
17  */
18 #ifndef TRAIN_HELPER_C
19 #define TRAIN_HELPER_C
20 #ifndef __CINT__
21 # include "Option.C"
22 # include <TUrl.h>
23 # include <TString.h>
24 # include <TMap.h>
25 # include <TObjString.h>
26 # include <TSystem.h>
27 # include <TROOT.h>
28 # include <TError.h>
29 # include <TObjArray.h>
30 # include <AliAnalysisManager.h>
31 # include <iostream>
32 #else 
33 class TString;
34 class TUrl;
35 class TMap;
36 class Option;
37 class OptionList;
38 #endif
39
40 /**
41  * Helper class to set-up an analysis using a train 
42  *
43  * @ingroup pwglf_forward_trains_helper
44  */
45 struct Helper 
46 {
47   enum EMode { 
48     kLocal, 
49     kProof, 
50     kGrid
51   };
52   enum EOperation { 
53     kTest,
54     kOffline,
55     kSubmit,
56     kTerminate, 
57     kFull
58   };
59   enum EInput { 
60     kESD, 
61     kAOD, 
62     kUser
63   };
64   Helper(const Helper& o) 
65     : fUrl(o.fUrl), fOptions(o.fOptions), fVerbose(o.fVerbose)
66   {}
67   Helper& operator=(const Helper&) { return *this; }
68   /** 
69    * Create a helper object. 
70    * 
71    * @param url Url describing the job. 
72    *
73    * - Local mode: 
74    *
75    * @code
76    * local://<path>[#<treeName>][?[recursive[&]]]
77    * @endcode 
78    *
79    * &lt;path&gt; can be a single ROOT file, a text file with one
80    * entry per file to add to the chain, or a directory containing the
81    * files. If &lt;path&gt; does not start with a '/' then it is
82    * interpreted as a relative path.
83    *
84    * - Grid mode: 
85    *
86    * @code 
87    * alien:///<path>#<pattern>
88    * @endcode
89    *
90    * - PROOF mode: 
91    * 
92    * Several options 
93    *
94    * @code 
95    * lite:///<path>[?[recursive[&]][workers=<n>]][#treeName]
96    * proof:///<path>[?[recursive[&]][workers=<n>]][#treeName]
97    * @endcode 
98    *
99    * @code 
100    * proof://<host>/<dsname>[?[workers=<n>[&]][dsname[=<outname>]]][#treeName]
101    * @endcode 
102    *
103    * Note, if &lt;host&gt; is recognised as an Alice Analysis
104    * Facility, then the Grid handler (AliAnalysisAlien) is used unless
105    * the option <tt>plain</tt> was given. 
106    * 
107    * @return Newly allocated helper or null 
108    */
109   static Helper* Create(const TUrl& url, Int_t verbose=0);
110   /** 
111    * Load a library 
112    * 
113    * @param name   Name of library 
114    * @param slave  If true also load on slaves
115    * 
116    * @return true on success, false otherwise 
117    */
118   virtual Bool_t LoadLibrary(const TString& name, 
119                              Bool_t slave=true) = 0;
120   /** 
121    * Load a source file, and compile it 
122    * 
123    * @param name Name of the source file 
124    * 
125    * @return true on success
126    */
127   virtual Bool_t LoadSource(const TString& name)
128   {
129     if (!AuxFile(name)) return false;
130     TString base(gSystem->BaseName(name));
131     gROOT->LoadMacro(Form("%s++g", base.Data()));
132     return true;
133   }
134   /** 
135    * Load auxillary file - not compiled or sourced.  Just copied to
136    * working directory
137    * 
138    * @param name Extra file name 
139    *
140    * @return true on success 
141    */
142   virtual Bool_t LoadAux(const TString& name)
143   {
144     if (!AuxFile(name)) return false;
145     return true;
146   }
147
148   /** 
149    * Load needed ROOT libaries 
150    */
151   virtual Bool_t LoadROOT()
152   {
153     if (gSystem->Load("libTree.so")    < 0) return false;
154     if (gSystem->Load("libGeom.so")    < 0) return false;
155     if (gSystem->Load("libVMC.so")     < 0) return false;
156     if (gSystem->Load("libPhysics.so") < 0) return false;
157     if (gSystem->Load("libMinuit.so")  < 0) return false;
158     return true;
159   }
160   /** 
161    * Set-up to load the AliROOT libraries 
162    * 
163    * @param par Whether to use PAR files 
164    * 
165    * @return true on success
166    */
167   virtual Bool_t LoadAliROOT()
168   {
169     if (!gSystem->Getenv("ALICE_ROOT")) { 
170       Error("Helper::LoadAliROOT", "Local AliROOT not available");
171       return false;
172     }
173     if (!LoadLibrary("STEERBase"))     return false;
174     if (!LoadLibrary("ESD"))           return false;
175     if (!LoadLibrary("AOD"))           return false;
176     if (!LoadLibrary("ANALYSIS"))      return false;
177     if (!LoadLibrary("OADB"))          return false;
178     if (!LoadLibrary("ANALYSISalice")) return false;
179     return true;
180   }
181   /** 
182    * Get the execution mode 
183    * 
184    * @return Execution mode set in set-up URL
185    */
186   virtual UShort_t Mode() const = 0;
187   /** 
188    * Get the operation - this only makes sense for Grid jobs
189    * 
190    * @return Operation type
191    */
192   virtual UShort_t Operation() const { return kFull; }
193   /** 
194    * Get the input data type 
195    *
196    * @return Input data type 
197    */
198   virtual Short_t InputType() const
199   {
200     UShort_t ret = DeduceType(fUrl.GetAnchor());
201     if (ret != kUser) return ret;
202
203     if (fOptions.Has("pattern")) ret = DeduceType(fOptions.Get("pattern"));
204     if (ret != kUser) return ret;
205     
206     ret = DeduceType(fUrl.GetFile());
207     return ret;
208   }
209   /** 
210    * The file part of tehe output URL - overwritten by derived classes. 
211    * 
212    * 
213    * @return File part of output URL
214    */
215   virtual TString OutputPath() const { return ""; }
216   /** 
217    * Get the location of the output data.  Use ful to define second pass 
218    * scripts, etc. 
219    * 
220    * 
221    * @return Url string 
222    */
223   virtual TString OutputLocation() const 
224   {
225     AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
226     if (!mgr || !mgr->GetOutputEventHandler()) return "";
227
228     TString path(OutputPath());
229     if (path.IsNull()) {
230       path = gSystem->WorkingDirectory(); 
231       // mgr->GetName();
232     }
233
234     TUrl u(fUrl);
235     u.SetFile(path);
236     u.SetAnchor("aodTree");
237     TString opt(u.GetOptions());
238     opt.ReplaceAll("AliESDs", "AliAOD");
239     u.SetOptions(opt);
240
241     return u.GetUrl();
242   }
243   /** 
244    * Set-up done before task setup 
245    * 
246    * @return true on success
247    */
248   virtual Bool_t PreSetup() = 0;
249   /** 
250    * Set-up done after task setup 
251    * 
252    * @return true on success
253    */
254   virtual Bool_t PostSetup() = 0;
255   /** 
256    * Run the analysis
257    * 
258    * @param nEvents Number of events to analyse 
259    * 
260    * @return The return value of AliAnalysisManager::StartAnalysis
261    */
262   virtual Long64_t Run(Long64_t nEvents=-1) = 0;
263   /** 
264    * Print information to standard output 
265    * 
266    * @param option 
267    * 
268    * @return 
269    */
270   virtual void Print(Option_t* ="") const
271   {
272     std::cout << "Url: " << fUrl.GetUrl() << std::endl;
273     fOptions.Show(std::cout);
274   }
275   /** 
276    * @return URL help string 
277    */
278   virtual const Char_t* UrlHelp() const  = 0;
279   /** 
280    * @return Short description string 
281    */
282   virtual const char* Desc() const = 0;
283   /** 
284    * Get the input URL 
285    * 
286    * @return Input URL 
287    */
288   const TUrl& Url() const { return fUrl; }
289   /** 
290    * Get the list of options 
291    * 
292    * @return Reference to list of options 
293    */
294   const OptionList& Options() const { return fOptions; }
295   /** 
296    * Create an instance of a helper class 
297    */
298   static Helper* CreateObject(const TString& cl, 
299                               const TUrl&    url, 
300                               Int_t verbose=0)
301   {
302     if (verbose > 3) gSystem->RedirectOutput("/dev/null","w");
303     if (cl.Contains("proof", TString::kIgnoreCase) || 
304         cl.Contains("lite",  TString::kIgnoreCase) || 
305         cl.Contains("aaf",   TString::kIgnoreCase)) {
306       gSystem->Load("libProof");
307       gSystem->Load("libProofPlayer");
308     }
309     gROOT->LoadMacro(Form("%s.C+",cl.Data()));
310     Long_t ptr = gROOT->ProcessLine(Form("new %s(\"%s\", %d);", 
311                                          cl.Data(), url.GetUrl(), verbose));
312     if (verbose > 3) gSystem->RedirectOutput(0);
313     if (!ptr) { 
314       Warning("Helper::CreateObject", "Failed to instantize a %s", cl.Data());
315       return 0;
316     }
317     Helper* h = reinterpret_cast<Helper*>(ptr);
318     return h;
319   }
320   /** 
321    * Show help on URL using the interpreter 
322    * 
323    * @param cl Helper class 
324    */
325   static void ShowUrlHelp(const TString& cl)
326   {
327     Helper* h = CreateObject(cl, "", true);
328     if (!h) return;
329
330     std::cout << "   " << h->UrlHelp() << std::endl;
331   }
332   /** 
333    * Show help on URL and options using the interpreter 
334    * 
335    * @param cl Helper class 
336    */
337   static void ShowFullHelp(const TString& cl) 
338   {
339     Helper* h = CreateObject(cl, "", true);
340     if (!h) return;
341     
342     std::cout << h->Desc() << ":\n" 
343               << "==============\n"
344               << "  " << h->UrlHelp() << "\n\n"
345               << "Options: " << std::endl;
346     h->Options().Help(std::cout);
347     std::cout << std::endl;
348   }
349 protected:
350   /** 
351    * Constructor 
352    * 
353    * @param url Set-up URL
354    * @param opts Pre-parsed options 
355    */
356   Helper(const TUrl& url, Int_t verbose) 
357     : fUrl(url), fOptions(), fVerbose(verbose)
358   {
359   }
360
361   virtual Bool_t ParseOptions()
362   {
363     return fOptions.Parse(fUrl.GetOptions(), "&");
364   }
365   /** 
366    * Destructor 
367    */
368   virtual ~Helper()
369   {
370   }
371   /** 
372    * Normalize a library name
373    * 
374    * @param name 
375    * 
376    * @return 
377    */
378   const TString& MakeLibraryName(const TString& name)
379   {
380     static TString libName;
381
382     libName = name;
383
384     if (!libName.BeginsWith("lib")) { 
385       // Check if the library corresponds to a compiled macro 
386       if (!gSystem->AccessPathName(Form("%s_C.so", libName.Data()))) 
387         libName.Append("_C");
388       else if (!gSystem->AccessPathName(Form("../%s_C.so", libName.Data()))) 
389         libName = Form("../%s_C", libName.Data());
390       else 
391         libName = Form("lib%s", libName.Data());
392     }
393     if (!libName.EndsWith(".so"))   libName.Append(".so");
394
395     return libName;
396   }
397   /** 
398    * Link an auxilary file to working directory 
399    * 
400    * @param name Name of the file
401    * 
402    * @return true on success
403    */
404   virtual Bool_t AuxFile(const TString& name)
405   {
406     TString path(gSystem->ExpandPathName(name.Data()));
407     // If not absolute, prepend up-one
408     if (!path.BeginsWith("/")) path.Prepend("../");
409     if (gSystem->AccessPathName(path.Data())) { 
410       // File not accessible
411       Warning("Helper::LoadSource", "File %s not accessible", path.Data());
412       return false;
413     }
414     gSystem->Exec(Form("ln -s %s .", path.Data()));
415     return true;
416   }
417   /** 
418    * Deduce the top of job from a string 
419    * 
420    * @param str String 
421    * 
422    * @return Job type
423    */
424   static UShort_t DeduceType(const TString& str)
425   {
426     if (str.IsNull()) return kUser;
427     if (str.Contains("aod", TString::kIgnoreCase)) return kAOD;
428     if (str.Contains("esd", TString::kIgnoreCase)) return kESD;
429     return kUser;
430   }
431   // --- Data members ------------------------------------------------
432   TUrl        fUrl;     // The URI
433   OptionList  fOptions; 
434   Int_t       fVerbose;
435 };
436
437
438
439
440 // ===================================================================
441 Helper* 
442 Helper::Create(const TUrl& url, Int_t verbose)
443 {
444   if (!url.IsValid()) { 
445     Warning("Helper::Create", "URL is invalid");
446     return 0;
447   }
448
449   TString prot(url.GetProtocol());
450   prot.ToLower();
451
452   TUrl tmp(url);
453   TString opts(tmp.GetOptions());
454   TString host(url.GetHost());
455   TString cl = "";
456   if (prot.EqualTo("alien")) { 
457     // Create an AliEn helper 
458     cl = "GridHelper";
459   }
460   else if (prot.EqualTo("local")) { 
461     // Create Lite helper 
462     cl = "LocalHelper";
463   }
464   else if (prot.EqualTo("proof")) { 
465     // Create a Proof helper 
466     if (host.IsNull()) 
467       cl = "LiteHelper";
468     else if (host.BeginsWith("alice-caf")) { 
469       // AAF 
470       cl = opts.Contains("plugin") ? "AAFPluginHelper" : "AAFHelper";
471     }
472     else 
473       cl = "ProofHelper";
474   }
475   else if (prot.EqualTo("lite")) { 
476     // Create a Proof helper 
477     cl = "LiteHelper";
478   }
479   else if (prot.EqualTo("help")) {
480     // Special HELP protocol
481     if (host.Contains("options")) {
482       std::cout << "Possible URL types and options are:" << std::endl;
483       ShowFullHelp("LocalHelper");
484       ShowFullHelp("ProofHelper");
485       ShowFullHelp("LiteHelper");
486       ShowFullHelp("AAFHelper");
487       ShowFullHelp("AAFPluginHelper");
488       ShowFullHelp("GridHelper");
489       return 0;
490     }
491     std::cout << "Possible URL types are:" << std::endl;
492     ShowUrlHelp("LocalHelper");
493     ShowUrlHelp("ProofHelper");
494     ShowUrlHelp("LiteHelper");
495     ShowUrlHelp("AAFHelper");
496     ShowUrlHelp("AAFPluginHelper");
497     ShowUrlHelp("GridHelper");
498     return 0;
499   }
500   // --- Check if we got a scheme ------------------------------------
501   if (cl.IsNull()) {
502     Error("Helper::Create", "Unknown scheme: %s", prot.Data());
503     return 0;
504   }
505
506   // --- Use interpreter to make our object --------------------------
507   Helper* helper = CreateObject(cl, url, verbose);
508   if (!helper) {
509     Error("Helper::Create", "Failed to make object of class %s", cl.Data());
510     return 0;
511   }
512
513   // --- Parse options -----------------------------------------------
514   if (!helper->ParseOptions()) {
515     delete helper;
516     helper = 0;
517   }
518
519   return helper;
520 }
521
522 #endif