]>
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> | |
ddcc1bbd | 30 | # include <TFile.h> |
fdfd93b4 | 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. | |
33438b4c | 71 | * |
72 | * @param verbose Verbosity | |
fdfd93b4 | 73 | * @param url Url describing the job. |
74 | * | |
75 | * - Local mode: | |
76 | * | |
77 | * @code | |
78 | * local://<path>[#<treeName>][?[recursive[&]]] | |
79 | * @endcode | |
80 | * | |
81 | * <path> 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 <path> 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 <host> 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 | |
ddcc1bbd | 126 | * @param copy Copy rather than link |
fdfd93b4 | 127 | * |
128 | * @return true on success | |
129 | */ | |
ddcc1bbd | 130 | virtual Bool_t LoadSource(const TString& name, bool copy=false) |
fdfd93b4 | 131 | { |
ddcc1bbd | 132 | if (!AuxFile(name, copy)) return false; |
fdfd93b4 | 133 | TString base(gSystem->BaseName(name)); |
73b32206 | 134 | gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"a\");"); |
fdfd93b4 | 135 | gROOT->LoadMacro(Form("%s++g", base.Data())); |
73b32206 | 136 | gROOT->ProcessLine("gSystem->RedirectOutput(0);"); |
fdfd93b4 | 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 | |
ddcc1bbd | 144 | * @param copy Copy rather than link |
fdfd93b4 | 145 | * |
146 | * @return true on success | |
147 | */ | |
ddcc1bbd | 148 | virtual Bool_t LoadAux(const TString& name, Bool_t copy=false) |
fdfd93b4 | 149 | { |
ddcc1bbd | 150 | if (!AuxFile(name, copy)) return false; |
fdfd93b4 | 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 | * | |
fdfd93b4 | 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; | |
024ec5ac | 191 | /** |
192 | * Get the mode string used for AliAnalysisManager::StartAnalysis | |
193 | */ | |
194 | virtual const char* ModeString() const { return "unknown"; } | |
fdfd93b4 | 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 | } | |
a54cc77b | 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"); } | |
fdfd93b4 | 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 | * | |
fdfd93b4 | 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; } | |
a80dde0d | 307 | /** |
308 | * Write auxillary ROOT (and possible shell) script for more | |
309 | * (post-)processing e.g., terminate | |
310 | * | |
a80dde0d | 311 | */ |
312 | virtual void AuxSave(const TString& /*escaped*/, | |
313 | Bool_t /*asShellScript*/) {} | |
fdfd93b4 | 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 | { | |
73b32206 | 321 | if (verbose < 3) gSystem->RedirectOutput("/dev/null","w"); |
fdfd93b4 | 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 | } | |
8449e3e0 | 328 | // (Always) recompile and with debug symbols |
329 | gROOT->LoadMacro(Form("%s.C+g",cl.Data())); | |
fdfd93b4 | 330 | Long_t ptr = gROOT->ProcessLine(Form("new %s(\"%s\", %d);", |
331 | cl.Data(), url.GetUrl(), verbose)); | |
73b32206 | 332 | if (verbose < 3) gSystem->RedirectOutput(0); |
fdfd93b4 | 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 | |
33438b4c | 374 | * @param verbose Verbosity level |
fdfd93b4 | 375 | */ |
376 | Helper(const TUrl& url, Int_t verbose) | |
377 | : fUrl(url), fOptions(), fVerbose(verbose) | |
378 | { | |
a54cc77b | 379 | fOptions.Add("mc", "Assume simulation input"); |
fdfd93b4 | 380 | } |
381 | ||
382 | virtual Bool_t ParseOptions() | |
383 | { | |
024ec5ac | 384 | //std::cout << "Url options: \"" << fUrl.GetOptions() << "\"" << std::endl; |
fdfd93b4 | 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 | |
33438b4c | 423 | * @param copy Copy rather than link |
ddcc1bbd | 424 | * |
fdfd93b4 | 425 | * @return true on success |
426 | */ | |
ddcc1bbd | 427 | virtual Bool_t AuxFile(const TString& name, bool copy=false) |
fdfd93b4 | 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 | |
46b25775 | 434 | Warning("Helper::AuxFile", "File %s not accessible", path.Data()); |
fdfd93b4 | 435 | return false; |
436 | } | |
46b25775 | 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 | } | |
ddcc1bbd | 445 | if (copy) |
446 | TFile::Cp(path, base); | |
447 | else | |
448 | gSystem->Exec(Form("ln -s %s .", path.Data())); | |
fdfd93b4 | 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 |