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