]>
Commit | Line | Data |
---|---|---|
fdfd93b4 | 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 | * <path> 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 <path> 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 <host> 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 | } | |
46b25775 | 309 | // Always recompile and with debug symbols |
310 | gROOT->LoadMacro(Form("%s.C++g",cl.Data())); | |
fdfd93b4 | 311 | Long_t ptr = gROOT->ProcessLine(Form("new %s(\"%s\", %d);", |
312 | cl.Data(), url.GetUrl(), verbose)); | |
313 | if (verbose > 3) gSystem->RedirectOutput(0); | |
314 | if (!ptr) { | |
315 | Warning("Helper::CreateObject", "Failed to instantize a %s", cl.Data()); | |
316 | return 0; | |
317 | } | |
318 | Helper* h = reinterpret_cast<Helper*>(ptr); | |
319 | return h; | |
320 | } | |
321 | /** | |
322 | * Show help on URL using the interpreter | |
323 | * | |
324 | * @param cl Helper class | |
325 | */ | |
326 | static void ShowUrlHelp(const TString& cl) | |
327 | { | |
328 | Helper* h = CreateObject(cl, "", true); | |
329 | if (!h) return; | |
330 | ||
331 | std::cout << " " << h->UrlHelp() << std::endl; | |
332 | } | |
333 | /** | |
334 | * Show help on URL and options using the interpreter | |
335 | * | |
336 | * @param cl Helper class | |
337 | */ | |
338 | static void ShowFullHelp(const TString& cl) | |
339 | { | |
340 | Helper* h = CreateObject(cl, "", true); | |
341 | if (!h) return; | |
342 | ||
343 | std::cout << h->Desc() << ":\n" | |
344 | << "==============\n" | |
345 | << " " << h->UrlHelp() << "\n\n" | |
346 | << "Options: " << std::endl; | |
347 | h->Options().Help(std::cout); | |
348 | std::cout << std::endl; | |
349 | } | |
350 | protected: | |
351 | /** | |
352 | * Constructor | |
353 | * | |
354 | * @param url Set-up URL | |
355 | * @param opts Pre-parsed options | |
356 | */ | |
357 | Helper(const TUrl& url, Int_t verbose) | |
358 | : fUrl(url), fOptions(), fVerbose(verbose) | |
359 | { | |
360 | } | |
361 | ||
362 | virtual Bool_t ParseOptions() | |
363 | { | |
364 | return fOptions.Parse(fUrl.GetOptions(), "&"); | |
365 | } | |
366 | /** | |
367 | * Destructor | |
368 | */ | |
369 | virtual ~Helper() | |
370 | { | |
371 | } | |
372 | /** | |
373 | * Normalize a library name | |
374 | * | |
375 | * @param name | |
376 | * | |
377 | * @return | |
378 | */ | |
379 | const TString& MakeLibraryName(const TString& name) | |
380 | { | |
381 | static TString libName; | |
382 | ||
383 | libName = name; | |
384 | ||
385 | if (!libName.BeginsWith("lib")) { | |
386 | // Check if the library corresponds to a compiled macro | |
387 | if (!gSystem->AccessPathName(Form("%s_C.so", libName.Data()))) | |
388 | libName.Append("_C"); | |
389 | else if (!gSystem->AccessPathName(Form("../%s_C.so", libName.Data()))) | |
390 | libName = Form("../%s_C", libName.Data()); | |
391 | else | |
392 | libName = Form("lib%s", libName.Data()); | |
393 | } | |
394 | if (!libName.EndsWith(".so")) libName.Append(".so"); | |
395 | ||
396 | return libName; | |
397 | } | |
398 | /** | |
399 | * Link an auxilary file to working directory | |
400 | * | |
401 | * @param name Name of the file | |
402 | * | |
403 | * @return true on success | |
404 | */ | |
405 | virtual Bool_t AuxFile(const TString& name) | |
406 | { | |
407 | TString path(gSystem->ExpandPathName(name.Data())); | |
408 | // If not absolute, prepend up-one | |
409 | if (!path.BeginsWith("/")) path.Prepend("../"); | |
410 | if (gSystem->AccessPathName(path.Data())) { | |
411 | // File not accessible | |
46b25775 | 412 | Warning("Helper::AuxFile", "File %s not accessible", path.Data()); |
fdfd93b4 | 413 | return false; |
414 | } | |
46b25775 | 415 | TString base(gSystem->BaseName(path.Data())); |
416 | if (gSystem->AccessPathName(base.Data()) == 0) { | |
417 | // File or link exists - remove it | |
418 | if (gSystem->Unlink(base) != 0) { | |
419 | Error("Helper::AuxFile", "Failed to remove old %s", base.Data()); | |
420 | return false; | |
421 | } | |
422 | } | |
fdfd93b4 | 423 | gSystem->Exec(Form("ln -s %s .", path.Data())); |
424 | return true; | |
425 | } | |
426 | /** | |
427 | * Deduce the top of job from a string | |
428 | * | |
429 | * @param str String | |
430 | * | |
431 | * @return Job type | |
432 | */ | |
433 | static UShort_t DeduceType(const TString& str) | |
434 | { | |
435 | if (str.IsNull()) return kUser; | |
436 | if (str.Contains("aod", TString::kIgnoreCase)) return kAOD; | |
437 | if (str.Contains("esd", TString::kIgnoreCase)) return kESD; | |
438 | return kUser; | |
439 | } | |
440 | // --- Data members ------------------------------------------------ | |
441 | TUrl fUrl; // The URI | |
442 | OptionList fOptions; | |
443 | Int_t fVerbose; | |
444 | }; | |
445 | ||
446 | ||
447 | ||
448 | ||
449 | // =================================================================== | |
450 | Helper* | |
451 | Helper::Create(const TUrl& url, Int_t verbose) | |
452 | { | |
453 | if (!url.IsValid()) { | |
454 | Warning("Helper::Create", "URL is invalid"); | |
455 | return 0; | |
456 | } | |
457 | ||
458 | TString prot(url.GetProtocol()); | |
459 | prot.ToLower(); | |
460 | ||
461 | TUrl tmp(url); | |
462 | TString opts(tmp.GetOptions()); | |
463 | TString host(url.GetHost()); | |
464 | TString cl = ""; | |
465 | if (prot.EqualTo("alien")) { | |
466 | // Create an AliEn helper | |
467 | cl = "GridHelper"; | |
468 | } | |
469 | else if (prot.EqualTo("local")) { | |
470 | // Create Lite helper | |
471 | cl = "LocalHelper"; | |
472 | } | |
473 | else if (prot.EqualTo("proof")) { | |
474 | // Create a Proof helper | |
475 | if (host.IsNull()) | |
476 | cl = "LiteHelper"; | |
477 | else if (host.BeginsWith("alice-caf")) { | |
478 | // AAF | |
479 | cl = opts.Contains("plugin") ? "AAFPluginHelper" : "AAFHelper"; | |
480 | } | |
481 | else | |
482 | cl = "ProofHelper"; | |
483 | } | |
484 | else if (prot.EqualTo("lite")) { | |
485 | // Create a Proof helper | |
486 | cl = "LiteHelper"; | |
487 | } | |
488 | else if (prot.EqualTo("help")) { | |
489 | // Special HELP protocol | |
490 | if (host.Contains("options")) { | |
491 | std::cout << "Possible URL types and options are:" << std::endl; | |
492 | ShowFullHelp("LocalHelper"); | |
493 | ShowFullHelp("ProofHelper"); | |
494 | ShowFullHelp("LiteHelper"); | |
495 | ShowFullHelp("AAFHelper"); | |
496 | ShowFullHelp("AAFPluginHelper"); | |
497 | ShowFullHelp("GridHelper"); | |
498 | return 0; | |
499 | } | |
500 | std::cout << "Possible URL types are:" << std::endl; | |
501 | ShowUrlHelp("LocalHelper"); | |
502 | ShowUrlHelp("ProofHelper"); | |
503 | ShowUrlHelp("LiteHelper"); | |
504 | ShowUrlHelp("AAFHelper"); | |
505 | ShowUrlHelp("AAFPluginHelper"); | |
506 | ShowUrlHelp("GridHelper"); | |
507 | return 0; | |
508 | } | |
509 | // --- Check if we got a scheme ------------------------------------ | |
510 | if (cl.IsNull()) { | |
511 | Error("Helper::Create", "Unknown scheme: %s", prot.Data()); | |
512 | return 0; | |
513 | } | |
514 | ||
515 | // --- Use interpreter to make our object -------------------------- | |
516 | Helper* helper = CreateObject(cl, url, verbose); | |
517 | if (!helper) { | |
518 | Error("Helper::Create", "Failed to make object of class %s", cl.Data()); | |
519 | return 0; | |
520 | } | |
521 | ||
522 | // --- Parse options ----------------------------------------------- | |
523 | if (!helper->ParseOptions()) { | |
524 | delete helper; | |
525 | helper = 0; | |
526 | } | |
527 | ||
528 | return helper; | |
529 | } | |
530 | ||
531 | #endif |