]>
Commit | Line | Data |
---|---|---|
fdfd93b4 | 1 | /** |
67a4bb96 | 2 | * @defgroup pwglf_forward_trains Trains. |
fdfd93b4 | 3 | * |
67a4bb96 CHC |
4 | * Train specifications. |
5 | * See also @ref train_setup_doc | |
fdfd93b4 | 6 | */ |
7 | /** | |
8 | * @file TrainSetup.C | |
9 | * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk> | |
10 | * @date Tue Oct 16 17:56:57 2012 | |
11 | * | |
12 | * @brief Base classs for train specifications | |
13 | * | |
14 | * @ingroup pwglf_forward_trains | |
15 | */ | |
16 | #ifndef TRAINSETUP_C | |
17 | #define TRAINSETUP_C | |
18 | #ifndef __CINT__ | |
19 | # include "Helper.C" | |
20 | # include "Option.C" | |
21 | # include <TDatime.h> | |
22 | # include <TUrl.h> | |
23 | # include <TString.h> | |
24 | # include <TApplication.h> | |
ddcc1bbd | 25 | # include <TStopwatch.h> |
fdfd93b4 | 26 | # include <AliAnalysisManager.h> |
27 | # include <AliVEventHandler.h> | |
28 | # include <AliPhysicsSelection.h> | |
29 | # include <AliPhysicsSelectionTask.h> | |
30 | # include <AliCentralitySelectionTask.h> | |
31 | # include <AliESDInputHandler.h> | |
32 | # include <AliAODInputHandler.h> | |
33 | # include <AliAODHandler.h> | |
34 | # include <AliMCEventHandler.h> | |
46b25775 | 35 | # include <ctime> |
fdfd93b4 | 36 | #else |
37 | struct Helper; | |
38 | struct OptionList; | |
39 | class TDatime; | |
40 | class TUrl; | |
41 | class TString; | |
ddcc1bbd | 42 | class TStopwatch; |
fdfd93b4 | 43 | class AliVEventHandler; |
44 | class AliAnalysisManager; | |
45 | class AliInputEventHandler; | |
46 | #endif | |
47 | ||
48 | //==================================================================== | |
49 | /** | |
ddcc1bbd | 50 | * Generic set-up of an analysis train |
fdfd93b4 | 51 | * |
52 | * See also @ref train_setup_doc | |
53 | * | |
54 | * @ingroup pwglf_forward_trains | |
55 | * | |
56 | */ | |
57 | struct TrainSetup | |
58 | { | |
59 | /** | |
60 | * Constructor | |
61 | * | |
62 | * @param name Name of the train | |
63 | */ | |
64 | TrainSetup(const TString& name) | |
65 | : fName(name), | |
66 | fEscapedName(name), | |
bfab35d9 | 67 | fDatimeString(""), |
46b25775 | 68 | fOptions(), |
6ee074b7 | 69 | fHelper(0), |
70 | fMonitored("") | |
fdfd93b4 | 71 | { |
33438b4c | 72 | fOptions.Add("help", "Show help", false); |
fdfd93b4 | 73 | fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now"); |
33438b4c | 74 | fOptions.Add("bare-ps", "Use bare physics selection w/o task", false); |
a80dde0d | 75 | fOptions.Add("verbose", "LEVEL", "Set verbosity level", 0); |
33438b4c | 76 | fOptions.Add("url", "URL", "Job location & input URL", ""); |
77 | fOptions.Add("overwrite", "Allow overwrite", false); | |
a80dde0d | 78 | fOptions.Add("events", "N", "Number of events to analyse", -1); |
33438b4c | 79 | fOptions.Add("type", "ESD|AOD|USER", "Input data stype", ""); |
80 | fOptions.Add("setup", "Only do the setup", false); | |
81 | fOptions.Add("branches", "Load only requested branches", false); | |
bfab35d9 | 82 | fDatimeString = ""; |
83 | fEscapedName = EscapeName(fName, fDatimeString); | |
fdfd93b4 | 84 | } |
8449e3e0 | 85 | /** |
86 | * Copy constructor | |
87 | * | |
88 | * @param o Object to copy from | |
89 | */ | |
46b25775 | 90 | TrainSetup(const TrainSetup& o) |
91 | : fName(o.fName), | |
92 | fEscapedName(o.fEscapedName), | |
bfab35d9 | 93 | fDatimeString(o.fDatimeString), |
46b25775 | 94 | fOptions(o.fOptions), |
6ee074b7 | 95 | fHelper(o.fHelper), |
96 | fMonitored(o.fMonitored) | |
46b25775 | 97 | {} |
8449e3e0 | 98 | /** |
99 | * Assignment operator | |
100 | * | |
101 | * @param o Object to assign from | |
102 | * | |
103 | * @return Reference to this object | |
104 | */ | |
46b25775 | 105 | TrainSetup& operator=(const TrainSetup& o) |
106 | { | |
107 | if (&o == this) return *this; | |
bfab35d9 | 108 | fName = o.fName; |
109 | fEscapedName = o.fEscapedName; | |
110 | fDatimeString = o.fDatimeString; | |
111 | fOptions = o.fOptions; | |
112 | fHelper = o.fHelper; | |
6ee074b7 | 113 | fMonitored = o.fMonitored; |
46b25775 | 114 | return *this; |
115 | } | |
116 | ||
fdfd93b4 | 117 | /** |
118 | * Destructor | |
119 | */ | |
120 | virtual ~TrainSetup() {} | |
121 | /* @} */ | |
122 | //__________________________________________________________________ | |
123 | /** | |
124 | * @{ | |
125 | * @name Execution | |
126 | */ | |
127 | /** | |
128 | * Initialize | |
129 | * | |
130 | * @return true on success | |
131 | */ | |
132 | Bool_t Init() | |
133 | { | |
134 | // --- Create the helper ----------------------------------------- | |
135 | TString url = fOptions.Get("url"); | |
136 | Int_t verbose = fOptions.AsInt("verbose"); | |
fdfd93b4 | 137 | |
138 | fHelper = Helper::Create(url.Data(), verbose); | |
139 | if (!fHelper) { | |
140 | Error("Init", "Failed to make the worker for URL %s", url.Data()); | |
141 | return false; | |
142 | } | |
143 | ||
46b25775 | 144 | // --- Check the type, if possible ------------------------------- |
fdfd93b4 | 145 | UShort_t type = fHelper->InputType(); |
a54cc77b | 146 | Bool_t mc = fHelper->IsMC(); |
fdfd93b4 | 147 | if (fOptions.Has("type")) { |
148 | const TString& it = fOptions.Get("type"); | |
149 | if (it.EqualTo("ESD",TString::kIgnoreCase)) type = Helper::kESD; | |
150 | else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Helper::kAOD; | |
151 | else if (it.EqualTo("user",TString::kIgnoreCase)) | |
152 | type = Helper::kUser; | |
153 | } | |
154 | ||
46b25775 | 155 | // --- Rewrite the escpaed name ---------------------------------- |
156 | if (fOptions.Has("date")) { | |
bfab35d9 | 157 | fDatimeString = fOptions.Get("date"); |
158 | fEscapedName = EscapeName(fName, fDatimeString); | |
46b25775 | 159 | } |
160 | ||
fdfd93b4 | 161 | // --- Get current directory and set-up sub-directory ------------ |
162 | TString cwd = gSystem->WorkingDirectory(); | |
163 | if (!SetupWorkingDirectory()) return false; | |
164 | ||
165 | // --- Do initial helper setup ----------------------------------- | |
166 | if (!fHelper->PreSetup()) return false; | |
167 | ||
168 | // --- Load ROOT libraries --------------------------------------- | |
169 | if (!fHelper->LoadROOT()) return false; | |
170 | ||
171 | // --- Load AliROOT libraries ------------------------------------ | |
172 | if (!fHelper->LoadAliROOT()) return false; | |
173 | ||
174 | // --- Create analysis manager ----------------------------------- | |
a80dde0d | 175 | AliAnalysisManager *mgr = CreateAnalysisManager(fEscapedName); |
fdfd93b4 | 176 | |
177 | // In test mode, collect system information on every event | |
178 | // if (oper == kTest) mgr->SetNSysInfo(1); | |
179 | if (verbose > 0) mgr->SetDebugLevel(verbose); | |
a54cc77b | 180 | mgr->SetAutoBranchLoading(!fOptions.Has("branches")); |
fdfd93b4 | 181 | if (fHelper->Mode() == Helper::kLocal) |
182 | mgr->SetUseProgressBar(kTRUE, 100); | |
183 | ||
184 | // --- ESD input handler ------------------------------------------ | |
185 | AliVEventHandler* inputHandler = CreateInputHandler(type); | |
186 | if (inputHandler) mgr->SetInputEventHandler(inputHandler); | |
187 | ||
188 | // --- Monte-Carlo ------------------------------------------------ | |
189 | AliVEventHandler* mcHandler = CreateMCHandler(type,mc); | |
190 | if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler); | |
191 | ||
192 | // --- AOD output handler ----------------------------------------- | |
193 | AliVEventHandler* outputHandler = CreateOutputHandler(type); | |
194 | if (outputHandler) mgr->SetOutputEventHandler(outputHandler); | |
195 | ||
196 | // --- Include analysis macro path in search path ---------------- | |
197 | gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros", | |
198 | cwd.Data(), gROOT->GetMacroPath())); | |
199 | ||
200 | // --- Physics selction - only for ESD --------------------------- | |
201 | if (type == Helper::kESD) CreatePhysicsSelection(mc, mgr); | |
202 | ||
203 | // --- Create centrality task ------------------------------------ | |
204 | CreateCentralitySelection(mc, mgr); | |
205 | ||
206 | // --- Create tasks ---------------------------------------------- | |
207 | CreateTasks(mgr); | |
208 | ||
6ee074b7 | 209 | // --- Create monitor objects ------------------------------------ |
210 | CreateMonitors(); | |
211 | ||
fdfd93b4 | 212 | // --- Post set-up initialization of helper ---------------------- |
213 | if (!fHelper->PostSetup()) return false; | |
214 | ||
215 | // --- Set debug level on defined tasks -------------------------- | |
216 | if (verbose > 0) { | |
217 | TIter next(mgr->GetTasks()); | |
218 | AliAnalysisTask* sub = 0; | |
219 | while ((sub = static_cast<AliAnalysisTask*>(next()))) { | |
220 | AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub); | |
221 | if (!se) continue; | |
222 | se->SetDebugLevel(verbose); | |
223 | } | |
224 | } | |
225 | ||
226 | // --- Print this setup ------------------------------------------ | |
227 | Print(); | |
228 | ||
229 | // --- Initialise the train -------------------------------------- | |
230 | if (!mgr->InitAnalysis()) { | |
231 | gSystem->ChangeDirectory(cwd.Data()); | |
232 | Error("Init","Failed to initialise train"); | |
233 | return false; | |
234 | } | |
235 | ||
236 | // --- Enable progress bar --------------------------------------- | |
237 | if (fHelper->Mode() != Helper::kGrid) | |
238 | mgr->SetUseProgressBar(true, 100); | |
239 | ||
240 | // --- Save setup to disk ---------------------------------------- | |
241 | SaveSetup(true); | |
242 | ||
ddcc1bbd | 243 | // --- Some information ------------------------------------------ |
fdfd93b4 | 244 | mgr->PrintStatus(); |
ddcc1bbd | 245 | if (fHelper->Mode() != Helper::kLocal) { |
246 | TIter next(mgr->GetTasks()); | |
247 | AliAnalysisTask* sub = 0; | |
248 | while ((sub = static_cast<AliAnalysisTask*>(next()))) { | |
249 | sub->Print(); | |
250 | } | |
251 | } | |
fdfd93b4 | 252 | return true; |
253 | } | |
8449e3e0 | 254 | /** |
255 | * Print timer information | |
256 | * | |
257 | * @param timer The timer | |
258 | * @param where Where this was called from | |
259 | */ | |
ddcc1bbd | 260 | void PrintTimer(TStopwatch& timer, const char* where) |
261 | { | |
262 | timer.Stop(); | |
263 | Double_t t = timer.RealTime(); | |
264 | Int_t h = Int_t(t / 3600); t -= h * 3600; | |
265 | Int_t m = Int_t(t / 60); t -= m * 60; | |
266 | if (t < 0) t = 0; | |
267 | Info(where, "took %4d:%02d:%06.3f", h, m, t); | |
268 | } | |
8449e3e0 | 269 | /** |
270 | * Run this train | |
271 | * | |
272 | * @return true on success | |
273 | */ | |
a80dde0d | 274 | Bool_t Run() |
fdfd93b4 | 275 | { |
276 | TString cwd = gSystem->WorkingDirectory(); | |
277 | Bool_t status = false; | |
ddcc1bbd | 278 | TStopwatch timer; |
279 | timer.Start(); | |
fdfd93b4 | 280 | try { |
281 | if (!Init()) throw TString("Failed to intialize the train"); | |
ddcc1bbd | 282 | PrintTimer(timer, "Initialization"); |
283 | timer.Continue(); | |
284 | ||
a80dde0d | 285 | // Check if we're asked to only do the setup |
286 | if (fOptions.Has("setup")) { | |
287 | status = true; | |
288 | throw TString("Only did setup, no running"); | |
289 | } | |
290 | ||
fdfd93b4 | 291 | // if (r) SaveSetup(*r, nEvents, asShell); |
292 | ||
293 | Long64_t nEvents = fOptions.AsLong("events", -1); | |
294 | Long64_t ret = fHelper->Run(nEvents); | |
ddcc1bbd | 295 | PrintTimer(timer, "Processing"); |
296 | timer.Continue(); | |
fdfd93b4 | 297 | |
298 | // Make sure we go back | |
299 | gSystem->ChangeDirectory(cwd.Data()); | |
300 | ||
301 | // Return. | |
302 | if (ret < 0) throw TString("Analysis failed"); | |
303 | ||
304 | status = true; | |
305 | } | |
306 | catch (TString& e) { | |
a54cc77b | 307 | if (status) Warning("Run", "%s", e.Data()); |
308 | else Error("Run", "%s", e.Data()); | |
ddcc1bbd | 309 | } |
310 | if (fOptions.Has("date")) { | |
bfab35d9 | 311 | TString tmp = ""; |
312 | TString escaped = EscapeName(fName, tmp); | |
ddcc1bbd | 313 | gSystem->Exec(Form("rm -f last_%s", escaped.Data())); |
314 | gSystem->Exec(Form("ln -sf %s last_%s", | |
315 | fEscapedName.Data(), escaped.Data())); | |
fdfd93b4 | 316 | } |
ddcc1bbd | 317 | PrintTimer(timer, "Finish"); |
318 | timer.Continue(); | |
a80dde0d | 319 | return status; |
fdfd93b4 | 320 | } |
321 | /** | |
322 | * Get the options | |
323 | * | |
324 | * | |
325 | * @return Reference ot the options | |
326 | */ | |
327 | OptionList& Options() { return fOptions; } | |
328 | /** | |
329 | * Print information to standard output | |
330 | * | |
331 | */ | |
332 | void Print(Option_t* ="") const | |
333 | { | |
334 | std::cout << "Train: " << fName << " (" << fEscapedName << ")" | |
335 | << std::endl; | |
336 | fOptions.Show(std::cout); | |
337 | if (fHelper) fHelper->Print(); | |
338 | } | |
339 | /** | |
340 | * Show the help | |
341 | * | |
33438b4c | 342 | * @param o Output stream |
343 | * @param asProg If true, output as program options | |
fdfd93b4 | 344 | * |
345 | * @return | |
346 | */ | |
347 | Bool_t Help(std::ostream& o=std::cout, bool asProg=false) | |
348 | { | |
349 | if (!fOptions.Has("help")) return true; | |
350 | ||
73b32206 | 351 | if (!asProg) |
fdfd93b4 | 352 | o << "Usage: RunTrain(NAME, CLASS, OPTIONS)"; |
353 | ||
73b32206 | 354 | o << "\n\nTrain Options:\n"; |
355 | fOptions.Help(o, asProg ? " --" : " "); | |
fdfd93b4 | 356 | o << "\n"; |
357 | ||
358 | if (!fHelper && fOptions.Has("url")) { | |
359 | TString url = fOptions.Get("url"); | |
360 | fHelper = Helper::Create(url.Data()); | |
361 | } | |
362 | if (fHelper) { | |
363 | o << fHelper->Desc() << " URL form:\n\n" | |
364 | << " " << fHelper->UrlHelp() << "\n\n" | |
365 | << "Options:\n"; | |
366 | fHelper->Options().Help(o, " "); | |
367 | o << "\n"; | |
368 | } | |
369 | else { | |
370 | o << "Possible URL forms:\n\n"; | |
371 | Helper::ShowUrlHelp("LocalHelper"); | |
372 | Helper::ShowUrlHelp("ProofHelper"); | |
373 | Helper::ShowUrlHelp("LiteHelper"); | |
374 | Helper::ShowUrlHelp("AAFHelper"); | |
375 | Helper::ShowUrlHelp("AAFPluginHelper"); | |
376 | Helper::ShowUrlHelp("GridHelper"); | |
377 | o << "\n"; | |
378 | } | |
379 | return false; | |
380 | } | |
381 | /** | |
382 | * Run train. This will AcLic compile the setup script, create | |
383 | * an object of that type with the given name, and then pass the | |
384 | * options to it. Then, it will run the setup. | |
385 | * | |
33438b4c | 386 | * @param name Train name |
387 | * @param cls Class name | |
388 | * @param opts Comma seperated list of options | |
389 | * @param asProg Run as program | |
390 | * @param spawn Spawn ROOT shell after execution | |
fdfd93b4 | 391 | * |
392 | * @return true on success | |
393 | */ | |
394 | static Bool_t Main(const TString& name, const TString& cls, | |
395 | const TCollection* opts, | |
73b32206 | 396 | Bool_t asProg=true, |
397 | Bool_t spawn=false) | |
fdfd93b4 | 398 | { |
a80dde0d | 399 | Bool_t ret = false; |
400 | try { | |
401 | if (cls.IsNull()) | |
402 | throw TString("No class name specified"); | |
403 | if (name.IsNull()) | |
404 | throw TString("No train name specified"); | |
fdfd93b4 | 405 | |
73b32206 | 406 | gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"w\");"); |
a80dde0d | 407 | Int_t error = 0; |
8449e3e0 | 408 | Int_t r1 = gROOT->LoadMacro(Form("%s.C+g", cls.Data()), &error); |
73b32206 | 409 | gROOT->ProcessLine("gSystem->RedirectOutput(0);"); |
a80dde0d | 410 | if (r1 < 0 || error) |
73b32206 | 411 | throw TString::Format("Failed to load setup %s: %d - see build.log", |
412 | cls.Data(), error); | |
a80dde0d | 413 | |
414 | // Make our object using the interpreter | |
415 | TString create = TString::Format("new %s(\"%s\")", | |
416 | cls.Data(), name.Data()); | |
85f21ab4 | 417 | gROOT->ProcessLine("gSystem->RedirectOutput(\"build.log\",\"a\");"); |
a80dde0d | 418 | Long_t retP = gROOT->ProcessLine(create, &error); |
419 | gROOT->ProcessLine("gSystem->RedirectOutput(0);"); | |
420 | if (!retP || error) | |
85f21ab4 | 421 | throw TString::Format("Failed to make object of class %s " |
422 | "(see build.log): 0x%08lx/%d\n\t%s", | |
a80dde0d | 423 | cls.Data(), retP, error, create.Data()); |
424 | ||
425 | TrainSetup* train = reinterpret_cast<TrainSetup*>(retP); | |
fdfd93b4 | 426 | |
a80dde0d | 427 | // Now parse the options |
428 | if (!train->Options().Parse(opts)) | |
429 | throw TString("Failed to parse options"); | |
fdfd93b4 | 430 | |
024ec5ac | 431 | // Info("", "URL=%s", train->Options().Get("url").Data()); |
33438b4c | 432 | |
a80dde0d | 433 | // Check if we got a help request |
434 | if (train->Options().Has("help")) { | |
435 | train->Help(std::cout, asProg); | |
436 | ret = true; | |
437 | throw TString(""); | |
438 | } | |
439 | ||
440 | // return train->Init(); | |
441 | ret = train->Run(); | |
442 | } | |
443 | catch (TString& e) { | |
a54cc77b | 444 | if (!e.IsNull()) Error("Main", "%s", e.Data()); |
a80dde0d | 445 | } |
85f21ab4 | 446 | // Info("Main", "End of main loop (app=%p, asProg=%s, spawn=%s)", |
447 | // gApplication, asProg ? "true" : "false", spawn ? "true" : "false"); | |
a80dde0d | 448 | if (gApplication && asProg) { |
73b32206 | 449 | if (!spawn) { |
450 | gSystem->Sleep(3); | |
451 | gApplication->Terminate(ret ? 0 : 1); | |
452 | } | |
fdfd93b4 | 453 | } |
a80dde0d | 454 | return ret; |
fdfd93b4 | 455 | } |
456 | protected: | |
457 | //__________________________________________________________________ | |
458 | /** | |
459 | * @{ | |
33438b4c | 460 | * @name Overloadable behaviour |
fdfd93b4 | 461 | */ |
462 | //------------------------------------------------------------------ | |
463 | /** | |
464 | * Create the analysis manager | |
465 | * | |
466 | * @param name Name of the analysis | |
467 | * | |
468 | * @return Created analysis manager | |
469 | */ | |
470 | virtual AliAnalysisManager* CreateAnalysisManager(const char* name) | |
471 | { | |
472 | return new AliAnalysisManager(name,"Analysis Train"); | |
473 | } | |
474 | //------------------------------------------------------------------ | |
475 | /** | |
476 | * Create input handler | |
477 | * | |
478 | * @param type | |
479 | * | |
480 | * @return | |
481 | */ | |
482 | virtual AliVEventHandler* CreateInputHandler(UShort_t type) | |
483 | { | |
484 | switch (type) { | |
485 | case Helper::kESD: return new AliESDInputHandler(); | |
486 | case Helper::kAOD: return new AliAODInputHandler(); | |
487 | case Helper::kUser: return 0; | |
488 | } | |
489 | return 0; | |
490 | } | |
491 | //------------------------------------------------------------------ | |
492 | /** | |
493 | * Create MC input handler | |
494 | * | |
fdfd93b4 | 495 | * @param mc Assume monte-carlo input |
496 | * | |
497 | * @return | |
498 | */ | |
499 | virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc) | |
500 | { | |
501 | if (!mc) return 0; | |
502 | AliMCEventHandler* mcHandler = new AliMCEventHandler(); | |
503 | mcHandler->SetReadTR(true); | |
504 | return mcHandler; | |
505 | } | |
506 | //------------------------------------------------------------------ | |
507 | /** | |
508 | * Create output event handler | |
509 | * | |
510 | * @param type | |
511 | * | |
512 | * @return | |
513 | */ | |
514 | virtual AliVEventHandler* CreateOutputHandler(UShort_t type) | |
515 | { | |
516 | AliAODHandler* ret = new AliAODHandler(); | |
517 | switch (type) { | |
518 | case Helper::kESD: | |
519 | ret->SetOutputFileName("AliAOD.root"); | |
520 | break; | |
521 | case Helper::kAOD: | |
522 | ret->SetOutputFileName("AliAOD.pass2.root"); | |
523 | break; | |
524 | case Helper::kUser: | |
525 | break; | |
526 | } | |
527 | ||
528 | return ret; | |
529 | } | |
530 | //------------------------------------------------------------------ | |
531 | /** | |
532 | * Create physics selection, and add to manager | |
533 | * | |
534 | * @param mc Whether this is for MC | |
535 | * @param mgr Manager | |
536 | */ | |
537 | virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr) | |
538 | { | |
539 | if (fOptions.Has("bare-ps")) { | |
540 | AliInputEventHandler* input = | |
541 | dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler()); | |
542 | if (!input) return; | |
543 | ||
544 | AliPhysicsSelection* ps = new AliPhysicsSelection(); | |
545 | if (mc) ps->SetAnalyzeMC(); | |
546 | ||
547 | input->SetEventSelection(ps); | |
548 | ||
549 | return; | |
550 | } | |
551 | gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc)); | |
552 | mgr->RegisterExtraFile("event_stat.root"); | |
33438b4c | 553 | mgr->AddStatisticsTask(AliVEvent::kAny); |
fdfd93b4 | 554 | } |
555 | //------------------------------------------------------------------ | |
556 | /** | |
557 | * Create centrality selection, and add to manager | |
558 | * | |
559 | * @param mc Whether this is for MC | |
560 | * @param mgr Manager | |
561 | */ | |
562 | virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr) | |
563 | { | |
73b32206 | 564 | gROOT->Macro("AddTaskCentrality.C(true)"); |
fdfd93b4 | 565 | const char* name = "CentralitySelection"; |
566 | AliCentralitySelectionTask* ctask = | |
567 | dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name)); | |
568 | if (!ctask) return; | |
569 | if (mc) ctask->SetMCInput(); | |
570 | } | |
571 | //------------------------------------------------------------------ | |
572 | /** | |
573 | * Create analysis tasks. Must be overloaded by sub-class | |
574 | * | |
575 | * @param mgr Manager | |
576 | */ | |
577 | virtual void CreateTasks(AliAnalysisManager* mgr)=0; | |
33438b4c | 578 | /** |
579 | * Add a task using a script and possibly some arguments | |
580 | * | |
581 | * @param macro Script to execute | |
582 | * @param args Optional arguments to the script | |
583 | * | |
584 | * @return Created task or null | |
585 | */ | |
586 | virtual AliAnalysisTask* AddTask(const TString& macro, | |
587 | const TString& args) | |
588 | { | |
589 | TString p = gSystem->Which(gROOT->GetMacroPath(), macro.Data()); | |
590 | if (p.IsNull()) { | |
591 | Error("AddTask", "Macro %s not found", macro.Data()); | |
592 | return 0; | |
593 | } | |
594 | TString cmd(p); | |
595 | if (!args.IsNull()) | |
596 | cmd.Append(TString::Format("(%s)", args.Data())); | |
597 | ||
598 | Int_t err; | |
599 | Long_t ret = gROOT->Macro(cmd.Data(), &err, false); | |
600 | if (!ret) { | |
66ee9f2f | 601 | Error("AddTask", "Failed to execute %s (%ld)", cmd.Data(), ret); |
33438b4c | 602 | return 0; |
603 | } | |
604 | return reinterpret_cast<AliAnalysisTask*>(ret); | |
605 | } | |
606 | /** | |
607 | * Add a task to the train with no arguments passed to the script | |
608 | * | |
609 | * @param macro The <b>AddTask</b> macro. | |
610 | * | |
611 | * @return The added task, if any | |
612 | */ | |
613 | virtual AliAnalysisTask* AddTask(const TString& macro) | |
614 | { | |
615 | TString args; | |
616 | return AddTask(macro, args); | |
617 | } | |
618 | /** | |
619 | * Add a single event analysis task to the train, passing the | |
620 | * specified arguments to the macro. | |
621 | * | |
622 | * @param macro The <b>AddTask</b> macro | |
623 | * @param args Arguments to pass the macro | |
624 | * | |
625 | * @return The added task, if any | |
626 | */ | |
627 | virtual AliAnalysisTaskSE* AddSETask(const TString& macro, | |
628 | const TString& args) | |
629 | { | |
630 | return dynamic_cast<AliAnalysisTaskSE*>(AddTask(macro, args)); | |
631 | } | |
632 | /** | |
633 | * Add a single event task to the train with no arguments passed to | |
634 | * the script | |
635 | * | |
636 | * @param macro The <b>AddTask</b> macro. | |
637 | * | |
638 | * @return The added task, if any | |
639 | */ | |
640 | virtual AliAnalysisTaskSE* AddSETask(const TString& macro) | |
641 | { | |
642 | TString args; | |
643 | return AddSETask(macro, args); | |
644 | } | |
56039ab4 | 645 | /** |
646 | * Find an already added task | |
647 | * | |
648 | * @param name Name of the task | |
649 | * @param verbose If true, | |
650 | * | |
651 | * @return | |
652 | */ | |
653 | virtual AliAnalysisTask* FindTask(const TString& name, | |
654 | Bool_t verbose=true) const | |
655 | { | |
656 | AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager(); | |
657 | if (!mgr) { | |
658 | ::Warning("FindTask", "No manager defined"); | |
659 | return 0; | |
660 | } | |
661 | AliAnalysisTask* task = mgr->GetTask(name); | |
662 | if (!task && verbose) | |
663 | ::Warning("FindTask", "Task \"%s\" not found in train", | |
664 | name.Data()); | |
665 | return task; | |
666 | } | |
340c93ea | 667 | /** |
668 | * Check if we have an MC handler attached | |
669 | * | |
670 | * @return True if MC handler is found in a valid manager. False if | |
671 | * manager is not defined, or has no MC handler. | |
672 | */ | |
673 | virtual Bool_t HasMCHandler() const | |
674 | { | |
675 | AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager(); | |
676 | if (!mgr) return false; | |
677 | return mgr->GetMCtruthEventHandler() != 0; | |
678 | } | |
73b32206 | 679 | /** |
680 | * Set the name of the train - should be name of the class. Must be | |
681 | * overloaded. | |
682 | * | |
683 | * @return Class name as a constant C string | |
684 | */ | |
fdfd93b4 | 685 | virtual const Char_t* ClassName() const = 0; |
686 | /* @} */ | |
687 | //__________________________________________________________________ | |
6ee074b7 | 688 | virtual void AddMonitor(const TString& name) |
689 | { | |
690 | if (!fMonitored.IsNull()) fMonitored.Append(":"); | |
691 | fMonitored.Append(name); | |
692 | } | |
693 | virtual void CreateMonitors() | |
694 | { | |
695 | if (fMonitored.IsNull()) return; | |
696 | if (fHelper->Mode() != Helper::kProof) return; | |
697 | ||
698 | TObjArray* tokens = fMonitored.Tokenize(":"); | |
699 | TObject* token = 0; | |
700 | TIter next(tokens); | |
701 | while ((token = next())) { | |
702 | gROOT->ProcessLine(Form("gProof->AddFeedback(\"%s\");", | |
703 | token->GetName())); | |
704 | ||
705 | } | |
706 | tokens->Delete(); | |
707 | } | |
708 | //__________________________________________________________________ | |
fdfd93b4 | 709 | /** |
710 | * @{ | |
711 | * @name Utility functions | |
712 | */ | |
713 | /** | |
714 | * Escape bad elements of the name | |
715 | * | |
33438b4c | 716 | * @param name Name to escape |
717 | * @param datimeStr Date and Time string | |
fdfd93b4 | 718 | * |
719 | * @return escaped name | |
720 | */ | |
bfab35d9 | 721 | static TString EscapeName(const char* name, TString& datimeStr) |
fdfd93b4 | 722 | { |
723 | TString escaped = name; | |
724 | char c[] = { ' ', '/', '@', 0 }; | |
725 | char* p = c; | |
726 | while (*p) { | |
46b25775 | 727 | char tmp[] = { *p, '\0' }; |
728 | escaped.ReplaceAll(tmp, "_"); | |
fdfd93b4 | 729 | p++; |
730 | } | |
7095962e CHC |
731 | if (!datimeStr.IsNull() && |
732 | !datimeStr.EqualTo("none", TString::kIgnoreCase)) { | |
fdfd93b4 | 733 | TDatime datime; |
734 | if (datimeStr.EqualTo("now", TString::kIgnoreCase)) | |
735 | datime.Set(); | |
46b25775 | 736 | else { |
737 | // Try various formats | |
738 | struct tm t; | |
739 | const char* formats[] = { "%Ec", // Locale | |
740 | "%c", // Locale | |
741 | "%Ex EX", // Locale | |
742 | "%x %X", // Locale | |
a80dde0d | 743 | "%Y%m%d_%H%M", // YYYYMMDD_HHMM |
46b25775 | 744 | "%F %R", // ISO standard, no seconds |
745 | 0 }; | |
746 | const char** f = formats; | |
747 | Bool_t found = false; | |
748 | while (*f && !found) { | |
749 | // Reset needed fields | |
750 | t.tm_year = 0; | |
751 | t.tm_mon = 0; | |
752 | t.tm_mday = 0; | |
753 | t.tm_hour = 0; | |
754 | t.tm_min = 0; | |
755 | // Stop processing on first match | |
756 | if (strptime(datimeStr.Data(), *f, &t) != 0) found = true; | |
757 | f++; | |
758 | } | |
a80dde0d | 759 | if (found) { |
760 | t.tm_mon += 1; // Return 0-based month | |
46b25775 | 761 | datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0); |
a80dde0d | 762 | } |
46b25775 | 763 | } |
fdfd93b4 | 764 | if (datime.GetYear() <= 1995 || |
765 | datime.GetMonth() == 0 || | |
766 | datime.GetDay() == 0) return escaped; | |
bfab35d9 | 767 | datimeStr = Form("%04d%02d%02d_%02d%02d", |
768 | datime.GetYear(), | |
769 | datime.GetMonth(), | |
770 | datime.GetDay(), | |
771 | datime.GetHour(), | |
772 | datime.GetMinute()); | |
773 | escaped.Append(Form("_%s", datimeStr.Data())); | |
fdfd93b4 | 774 | } |
775 | return escaped; | |
776 | } | |
777 | /** | |
778 | * Make our working directory if so requested | |
779 | * | |
780 | * @return true on success | |
781 | */ | |
782 | Bool_t SetupWorkingDirectory() | |
783 | { | |
784 | // Get the name of the target directory | |
785 | TString& nam = fEscapedName; | |
786 | ||
787 | // Check if the directory exists already | |
788 | Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0; | |
789 | if (fHelper->Operation() == Helper::kTerminate && !exists) { | |
790 | Error("SetupWorkingDirectory", "File/directory %s does not exists", | |
791 | nam.Data()); | |
792 | return false; | |
793 | } | |
794 | ||
795 | Bool_t overwrite = fOptions.Has("overwrite"); | |
796 | // If we're not allowed to overwrite, then complain | |
797 | if (!overwrite && exists) { | |
798 | Error("SetupWorkingDirectory", "File/directory %s already exists", | |
799 | nam.Data()); | |
800 | return false; | |
801 | } | |
802 | ||
803 | // Make the target directory if it doesn't exists | |
804 | if (!exists) { | |
805 | if (gSystem->MakeDirectory(nam.Data())) { | |
806 | Error("SetupWorkingDirectory", "Failed to make directory '%s'", | |
807 | nam.Data()); | |
808 | return false; | |
809 | } | |
810 | } | |
811 | ||
812 | // Change directory to target directory | |
813 | if (!gSystem->ChangeDirectory(nam.Data())) { | |
814 | Error("SetupWorkingDirectory", "Failed to change directory to %s", | |
815 | nam.Data()); | |
816 | return false; | |
817 | } | |
85f21ab4 | 818 | // Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there", |
819 | // nam.Data()); | |
fdfd93b4 | 820 | return true; |
821 | } | |
822 | /** | |
823 | * Save the setup as a ROOT script and possibly also a shell script | |
824 | * | |
825 | * @param asShellScript If true, also save as shell script | |
826 | */ | |
827 | virtual void SaveSetup(Bool_t asShellScript) | |
828 | { | |
46b25775 | 829 | OptionList tmp(fOptions); |
a80dde0d | 830 | const OptionList* uopts = (fHelper ? &fHelper->Options() : 0); |
46b25775 | 831 | if (tmp.Find("overwrite")) tmp.Set("overwrite"); |
a80dde0d | 832 | if (tmp.Find("date") && fEscapedName.Length() > fName.Length()+1) { |
833 | Int_t n = fName.Length()+1; | |
834 | tmp.Set("date", fEscapedName(n, fEscapedName.Length()-n)); | |
835 | } | |
fdfd93b4 | 836 | if (asShellScript) |
a80dde0d | 837 | SaveSetupShell("rerun", ClassName(), fName, tmp, uopts); |
838 | SaveSetupROOT("ReRun", ClassName(), fName, tmp, uopts); | |
839 | if (fHelper) fHelper->AuxSave(fEscapedName, asShellScript); | |
aeab3a4e | 840 | SavePostShellScript(); |
fdfd93b4 | 841 | } |
842 | /** | |
843 | * Save a setup as a shell script | |
844 | * | |
845 | * @param out Output name of shell script | |
846 | * @param cls Class of the train | |
847 | * @param name Name of the train | |
848 | * @param opts Option list | |
33438b4c | 849 | * @param uopts Url options |
fdfd93b4 | 850 | */ |
851 | static void SaveSetupShell(const TString& out, const TString& cls, | |
a80dde0d | 852 | const TString& name, const OptionList& opts, |
853 | const OptionList* uopts) | |
fdfd93b4 | 854 | { |
855 | std::ofstream o(Form("%s.sh", out.Data())); | |
856 | o << "#!/bin/bash\n\n" | |
857 | << "class=\"" << cls << "\"\n" | |
858 | << "name=\"" << name << "\"\n\n" | |
859 | << "# Available options\n" | |
860 | << "# \n"; | |
861 | opts.Help(o, "# --"); | |
a80dde0d | 862 | if (uopts) { |
863 | o << "#\n" | |
864 | << "# Available URI options\n" | |
865 | << "# \n"; | |
866 | uopts->Help(o, "# "); | |
867 | } | |
fdfd93b4 | 868 | o << "#\n" |
869 | << "opts=(--class=$class \\\n" | |
870 | << " --name=$name"; | |
871 | opts.Store(o, " \\\n --", "", true); | |
872 | o << ")\n\n" | |
92f304b1 | 873 | << "echo \"Running runTrain ${opts[@]} $@\"\n" |
874 | << "runTrain \"${opts[@]}\" $@\n\n" | |
fdfd93b4 | 875 | << "# EOF" << std::endl; |
876 | o.close(); | |
877 | gSystem->Exec(Form("chmod a+x %s.sh", out.Data())); | |
878 | } | |
879 | /** | |
880 | * Save a setup as a ROOT script | |
881 | * | |
882 | * @param out Output name of shell script | |
883 | * @param cls Class of the train | |
884 | * @param name Name of the train | |
885 | * @param opts Option list | |
33438b4c | 886 | * @param uopts Url options |
fdfd93b4 | 887 | */ |
888 | static void SaveSetupROOT(const TString& out, const TString& cls, | |
a80dde0d | 889 | const TString& name, const OptionList& opts, |
890 | const OptionList* uopts) | |
fdfd93b4 | 891 | { |
892 | OptionList tmp(opts); | |
893 | tmp.Remove("url"); | |
a80dde0d | 894 | |
fdfd93b4 | 895 | std::ofstream o(Form("%s.C", out.Data())); |
a80dde0d | 896 | o << "// Available options:\n" |
897 | << "// \n"; | |
898 | tmp.Help(o, "// "); | |
899 | if (uopts) { | |
900 | o << "// \n" | |
901 | << "// Available URI options\n"; | |
902 | uopts->Help(o, "// "); | |
903 | } | |
904 | o << "//\n" | |
905 | << "Bool_t " << out << "()\n" | |
fdfd93b4 | 906 | << "{\n" |
907 | << " TString name(\"" << name << "\");\n" | |
908 | << " TString cls(\"" << cls << "\");\n" | |
a80dde0d | 909 | << " TUrl uri(\"" << opts.Get("url") << "\");\n" |
910 | << " \n" | |
fdfd93b4 | 911 | << " TString opts("; |
912 | tmp.Store(o, "\"", ",\"\n ", false); | |
913 | o << ");\n\n" | |
46b25775 | 914 | << " TString path("; |
915 | TString path(gROOT->GetMacroPath()); | |
916 | TObjArray* elements = path.Tokenize(":"); | |
917 | TObjString* element = 0; | |
918 | TIter next(elements); | |
919 | while ((element = static_cast<TObjString*>(next()))) { | |
920 | if (element->String().IsNull()) continue; | |
921 | o << "\n \"" << element->GetName() << ":\""; | |
922 | } | |
923 | elements->Delete(); | |
924 | o << ");\n" | |
925 | << " path.Append(\"$ALICE_ROOT/PWGLF/FORWARD/trains\");\n" | |
926 | << " gROOT->SetMacroPath(path);\n\n" | |
fdfd93b4 | 927 | << " gROOT->LoadMacro(\"RunTrain.C\");\n\n" |
928 | << " return RunTrain(name, cls, uri, opts);\n" | |
929 | << "}\n" | |
930 | << "//\n" | |
931 | << "// EOF\n" | |
932 | << "//" << std::endl; | |
933 | o.close(); | |
934 | } | |
aeab3a4e | 935 | /** |
936 | * Write shell code to do post processing after terminate. This | |
937 | * code should deal with a single run (or run range). The following | |
938 | * shell variables are available to the code: | |
939 | * | |
940 | * - @c $prefix Relative path to job directory or empty | |
941 | * - @c $dest Destination for output to be stored | |
942 | * | |
943 | * Note, the code is injected into a shell function, and should | |
944 | * therefor not define new functions or the like. | |
945 | * | |
946 | * @param o The output stream. | |
947 | */ | |
948 | virtual void PostShellCode(std::ostream& o) | |
949 | { | |
950 | o << " echo \"Nothing to do for " << ClassName() | |
951 | << " train\"" << std::endl; | |
952 | } | |
953 | /** | |
954 | * Save a script to do post processing after terminate on each run | |
955 | * or run-range. | |
956 | * | |
957 | * The shell script will execute the train defined code (in | |
958 | * PostShellCode) for each run or run-range. The train defined code | |
959 | * and call drawing and summarizing macros or the like. | |
960 | * | |
961 | * In case of Grid analysis, this script will download and extract | |
962 | * the appropriate ZIP files to separate directories, and then | |
963 | * change directory to these directories and execute the train | |
964 | * defined shell code there. In this case, the script defines the | |
965 | * shell variable @c $prefix as the relative path to the job | |
966 | * directory. | |
967 | * | |
968 | */ | |
969 | void SavePostShellScript() | |
970 | { | |
971 | std::ofstream f("post.sh"); | |
972 | if (!f) { | |
973 | Error("SavePostAll", "Failed to open post.sh script"); | |
974 | return; | |
975 | } | |
976 | f << "#!/bin/bash\n" | |
977 | << "# Generated by " << ClassName() << "\n" | |
978 | << "set -e\n" | |
979 | << "\n" | |
980 | << "dest=$1\n" | |
981 | << "prefix=\n" | |
982 | << "\n" | |
983 | << "doall() {" | |
984 | << std::endl; | |
985 | PostShellCode(f); | |
986 | f << "}\n" | |
987 | << "\n" | |
988 | << "if test ! -f Download.C ;then\n" | |
989 | << " doall\n" | |
990 | << " exit\n" | |
991 | << "fi\n" | |
992 | << "\n" | |
993 | << "if test ! -f .download ; then\n" | |
994 | << " aliroot -l -b -q Download.C\\(1\\)\n" | |
995 | << " touch .download\n" | |
996 | << "fi\n" | |
997 | << "prefix=../\n" | |
998 | << "\n" | |
999 | << "for i in root_archive_*.zip ; do\n" | |
1000 | << " d=`basename $i .zip` \n" | |
1001 | << " if test ! -d $d ; then\n" | |
1002 | << " echo \"Directory $d missing\"\n" | |
1003 | << " continue\n" | |
1004 | << " fi\n" | |
1005 | << " \n" | |
1006 | << " (cd $d && doall)\n" | |
1007 | << "done\n" | |
1008 | << "# EOF" | |
1009 | << std::endl; | |
1010 | f.close(); | |
1011 | gSystem->Exec("chmod a+x post.sh"); | |
1012 | } | |
1013 | ||
fdfd93b4 | 1014 | /* @} */ |
1015 | TString fName; | |
1016 | TString fEscapedName; | |
bfab35d9 | 1017 | TString fDatimeString; |
fdfd93b4 | 1018 | OptionList fOptions; |
1019 | Helper* fHelper; | |
6ee074b7 | 1020 | TString fMonitored; |
fdfd93b4 | 1021 | }; |
1022 | #endif |