]>
Commit | Line | Data |
---|---|---|
fdfd93b4 | 1 | /** |
2 | * @defgroup pwglf_forward_trains Trains | |
3 | * | |
4 | * Train specifications | |
5 | * | |
6 | * @ingroup pwglf_forward | |
7 | */ | |
8 | /** | |
9 | * @file TrainSetup.C | |
10 | * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk> | |
11 | * @date Tue Oct 16 17:56:57 2012 | |
12 | * | |
13 | * @brief Base classs for train specifications | |
14 | * | |
15 | * @ingroup pwglf_forward_trains | |
16 | */ | |
17 | #ifndef TRAINSETUP_C | |
18 | #define TRAINSETUP_C | |
19 | #ifndef __CINT__ | |
20 | # include "Helper.C" | |
21 | # include "Option.C" | |
22 | # include <TDatime.h> | |
23 | # include <TUrl.h> | |
24 | # include <TString.h> | |
25 | # include <TApplication.h> | |
ddcc1bbd | 26 | # include <TStopwatch.h> |
fdfd93b4 | 27 | # include <AliAnalysisManager.h> |
28 | # include <AliVEventHandler.h> | |
29 | # include <AliPhysicsSelection.h> | |
30 | # include <AliPhysicsSelectionTask.h> | |
31 | # include <AliCentralitySelectionTask.h> | |
32 | # include <AliESDInputHandler.h> | |
33 | # include <AliAODInputHandler.h> | |
34 | # include <AliAODHandler.h> | |
35 | # include <AliMCEventHandler.h> | |
46b25775 | 36 | # include <ctime> |
fdfd93b4 | 37 | #else |
38 | struct Helper; | |
39 | struct OptionList; | |
40 | class TDatime; | |
41 | class TUrl; | |
42 | class TString; | |
ddcc1bbd | 43 | class TStopwatch; |
fdfd93b4 | 44 | class AliVEventHandler; |
45 | class AliAnalysisManager; | |
46 | class AliInputEventHandler; | |
47 | #endif | |
48 | ||
49 | //==================================================================== | |
50 | /** | |
ddcc1bbd | 51 | * Generic set-up of an analysis train |
fdfd93b4 | 52 | * |
53 | * See also @ref train_setup_doc | |
54 | * | |
55 | * @ingroup pwglf_forward_trains | |
56 | * | |
57 | */ | |
58 | struct TrainSetup | |
59 | { | |
60 | /** | |
61 | * Constructor | |
62 | * | |
63 | * @param name Name of the train | |
64 | */ | |
65 | TrainSetup(const TString& name) | |
66 | : fName(name), | |
67 | fEscapedName(name), | |
46b25775 | 68 | fOptions(), |
fdfd93b4 | 69 | fHelper(0) |
70 | { | |
71 | fOptions.Add("help", "Show help"); | |
72 | fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now"); | |
fdfd93b4 | 73 | fOptions.Add("bare-ps", "Use bare physics selection w/o task"); |
a80dde0d | 74 | fOptions.Add("verbose", "LEVEL", "Set verbosity level", 0); |
75 | fOptions.Add("url", "URL", "Job location & input URL"); | |
fdfd93b4 | 76 | fOptions.Add("overwrite", "Allow overwrite"); |
a80dde0d | 77 | fOptions.Add("events", "N", "Number of events to analyse", -1); |
78 | fOptions.Add("type", "ESD|AOD|USER", "Input data stype"); | |
79 | fOptions.Add("setup", "Only do the setup"); | |
a54cc77b | 80 | fOptions.Add("branches", "Load only requested branches"); |
fdfd93b4 | 81 | fEscapedName = EscapeName(fName, ""); |
82 | } | |
46b25775 | 83 | TrainSetup(const TrainSetup& o) |
84 | : fName(o.fName), | |
85 | fEscapedName(o.fEscapedName), | |
86 | fOptions(o.fOptions), | |
87 | fHelper(o.fHelper) | |
88 | {} | |
89 | TrainSetup& operator=(const TrainSetup& o) | |
90 | { | |
91 | if (&o == this) return *this; | |
92 | fName = o.fName; | |
93 | fEscapedName = o.fEscapedName; | |
94 | fOptions = o.fOptions; | |
95 | fHelper = o.fHelper; | |
96 | return *this; | |
97 | } | |
98 | ||
fdfd93b4 | 99 | /** |
100 | * Destructor | |
101 | */ | |
102 | virtual ~TrainSetup() {} | |
103 | /* @} */ | |
104 | //__________________________________________________________________ | |
105 | /** | |
106 | * @{ | |
107 | * @name Execution | |
108 | */ | |
109 | /** | |
110 | * Initialize | |
111 | * | |
112 | * @return true on success | |
113 | */ | |
114 | Bool_t Init() | |
115 | { | |
116 | // --- Create the helper ----------------------------------------- | |
117 | TString url = fOptions.Get("url"); | |
118 | Int_t verbose = fOptions.AsInt("verbose"); | |
fdfd93b4 | 119 | |
120 | fHelper = Helper::Create(url.Data(), verbose); | |
121 | if (!fHelper) { | |
122 | Error("Init", "Failed to make the worker for URL %s", url.Data()); | |
123 | return false; | |
124 | } | |
125 | ||
46b25775 | 126 | // --- Check the type, if possible ------------------------------- |
fdfd93b4 | 127 | UShort_t type = fHelper->InputType(); |
a54cc77b | 128 | Bool_t mc = fHelper->IsMC(); |
fdfd93b4 | 129 | if (fOptions.Has("type")) { |
130 | const TString& it = fOptions.Get("type"); | |
131 | if (it.EqualTo("ESD",TString::kIgnoreCase)) type = Helper::kESD; | |
132 | else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Helper::kAOD; | |
133 | else if (it.EqualTo("user",TString::kIgnoreCase)) | |
134 | type = Helper::kUser; | |
135 | } | |
136 | ||
46b25775 | 137 | // --- Rewrite the escpaed name ---------------------------------- |
138 | if (fOptions.Has("date")) { | |
139 | TString date = fOptions.Get("date"); | |
140 | fEscapedName = EscapeName(fName, date); | |
141 | } | |
142 | ||
fdfd93b4 | 143 | // --- Get current directory and set-up sub-directory ------------ |
144 | TString cwd = gSystem->WorkingDirectory(); | |
145 | if (!SetupWorkingDirectory()) return false; | |
146 | ||
147 | // --- Do initial helper setup ----------------------------------- | |
148 | if (!fHelper->PreSetup()) return false; | |
149 | ||
150 | // --- Load ROOT libraries --------------------------------------- | |
151 | if (!fHelper->LoadROOT()) return false; | |
152 | ||
153 | // --- Load AliROOT libraries ------------------------------------ | |
154 | if (!fHelper->LoadAliROOT()) return false; | |
155 | ||
156 | // --- Create analysis manager ----------------------------------- | |
a80dde0d | 157 | AliAnalysisManager *mgr = CreateAnalysisManager(fEscapedName); |
fdfd93b4 | 158 | |
159 | // In test mode, collect system information on every event | |
160 | // if (oper == kTest) mgr->SetNSysInfo(1); | |
161 | if (verbose > 0) mgr->SetDebugLevel(verbose); | |
a54cc77b | 162 | mgr->SetAutoBranchLoading(!fOptions.Has("branches")); |
fdfd93b4 | 163 | if (fHelper->Mode() == Helper::kLocal) |
164 | mgr->SetUseProgressBar(kTRUE, 100); | |
165 | ||
166 | // --- ESD input handler ------------------------------------------ | |
167 | AliVEventHandler* inputHandler = CreateInputHandler(type); | |
168 | if (inputHandler) mgr->SetInputEventHandler(inputHandler); | |
169 | ||
170 | // --- Monte-Carlo ------------------------------------------------ | |
171 | AliVEventHandler* mcHandler = CreateMCHandler(type,mc); | |
172 | if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler); | |
173 | ||
174 | // --- AOD output handler ----------------------------------------- | |
175 | AliVEventHandler* outputHandler = CreateOutputHandler(type); | |
176 | if (outputHandler) mgr->SetOutputEventHandler(outputHandler); | |
177 | ||
178 | // --- Include analysis macro path in search path ---------------- | |
179 | gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros", | |
180 | cwd.Data(), gROOT->GetMacroPath())); | |
181 | ||
182 | // --- Physics selction - only for ESD --------------------------- | |
183 | if (type == Helper::kESD) CreatePhysicsSelection(mc, mgr); | |
184 | ||
185 | // --- Create centrality task ------------------------------------ | |
186 | CreateCentralitySelection(mc, mgr); | |
187 | ||
188 | // --- Create tasks ---------------------------------------------- | |
189 | CreateTasks(mgr); | |
190 | ||
191 | // --- Post set-up initialization of helper ---------------------- | |
192 | if (!fHelper->PostSetup()) return false; | |
193 | ||
194 | // --- Set debug level on defined tasks -------------------------- | |
195 | if (verbose > 0) { | |
196 | TIter next(mgr->GetTasks()); | |
197 | AliAnalysisTask* sub = 0; | |
198 | while ((sub = static_cast<AliAnalysisTask*>(next()))) { | |
199 | AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub); | |
200 | if (!se) continue; | |
201 | se->SetDebugLevel(verbose); | |
202 | } | |
203 | } | |
204 | ||
205 | // --- Print this setup ------------------------------------------ | |
206 | Print(); | |
207 | ||
208 | // --- Initialise the train -------------------------------------- | |
209 | if (!mgr->InitAnalysis()) { | |
210 | gSystem->ChangeDirectory(cwd.Data()); | |
211 | Error("Init","Failed to initialise train"); | |
212 | return false; | |
213 | } | |
214 | ||
215 | // --- Enable progress bar --------------------------------------- | |
216 | if (fHelper->Mode() != Helper::kGrid) | |
217 | mgr->SetUseProgressBar(true, 100); | |
218 | ||
219 | // --- Save setup to disk ---------------------------------------- | |
220 | SaveSetup(true); | |
221 | ||
ddcc1bbd | 222 | // --- Some information ------------------------------------------ |
fdfd93b4 | 223 | mgr->PrintStatus(); |
ddcc1bbd | 224 | if (fHelper->Mode() != Helper::kLocal) { |
225 | TIter next(mgr->GetTasks()); | |
226 | AliAnalysisTask* sub = 0; | |
227 | while ((sub = static_cast<AliAnalysisTask*>(next()))) { | |
228 | sub->Print(); | |
229 | } | |
230 | } | |
fdfd93b4 | 231 | return true; |
232 | } | |
ddcc1bbd | 233 | void PrintTimer(TStopwatch& timer, const char* where) |
234 | { | |
235 | timer.Stop(); | |
236 | Double_t t = timer.RealTime(); | |
237 | Int_t h = Int_t(t / 3600); t -= h * 3600; | |
238 | Int_t m = Int_t(t / 60); t -= m * 60; | |
239 | if (t < 0) t = 0; | |
240 | Info(where, "took %4d:%02d:%06.3f", h, m, t); | |
241 | } | |
242 | ||
a80dde0d | 243 | Bool_t Run() |
fdfd93b4 | 244 | { |
245 | TString cwd = gSystem->WorkingDirectory(); | |
246 | Bool_t status = false; | |
ddcc1bbd | 247 | TStopwatch timer; |
248 | timer.Start(); | |
fdfd93b4 | 249 | try { |
250 | if (!Init()) throw TString("Failed to intialize the train"); | |
ddcc1bbd | 251 | PrintTimer(timer, "Initialization"); |
252 | timer.Continue(); | |
253 | ||
a80dde0d | 254 | // Check if we're asked to only do the setup |
255 | if (fOptions.Has("setup")) { | |
256 | status = true; | |
257 | throw TString("Only did setup, no running"); | |
258 | } | |
259 | ||
fdfd93b4 | 260 | // if (r) SaveSetup(*r, nEvents, asShell); |
261 | ||
262 | Long64_t nEvents = fOptions.AsLong("events", -1); | |
263 | Long64_t ret = fHelper->Run(nEvents); | |
ddcc1bbd | 264 | PrintTimer(timer, "Processing"); |
265 | timer.Continue(); | |
fdfd93b4 | 266 | |
267 | // Make sure we go back | |
268 | gSystem->ChangeDirectory(cwd.Data()); | |
269 | ||
270 | // Return. | |
271 | if (ret < 0) throw TString("Analysis failed"); | |
272 | ||
273 | status = true; | |
274 | } | |
275 | catch (TString& e) { | |
a54cc77b | 276 | if (status) Warning("Run", "%s", e.Data()); |
277 | else Error("Run", "%s", e.Data()); | |
ddcc1bbd | 278 | } |
279 | if (fOptions.Has("date")) { | |
280 | TString escaped = EscapeName(fName, ""); | |
281 | gSystem->Exec(Form("rm -f last_%s", escaped.Data())); | |
282 | gSystem->Exec(Form("ln -sf %s last_%s", | |
283 | fEscapedName.Data(), escaped.Data())); | |
fdfd93b4 | 284 | } |
ddcc1bbd | 285 | PrintTimer(timer, "Finish"); |
286 | timer.Continue(); | |
a80dde0d | 287 | return status; |
fdfd93b4 | 288 | } |
289 | /** | |
290 | * Get the options | |
291 | * | |
292 | * | |
293 | * @return Reference ot the options | |
294 | */ | |
295 | OptionList& Options() { return fOptions; } | |
296 | /** | |
297 | * Print information to standard output | |
298 | * | |
299 | */ | |
300 | void Print(Option_t* ="") const | |
301 | { | |
302 | std::cout << "Train: " << fName << " (" << fEscapedName << ")" | |
303 | << std::endl; | |
304 | fOptions.Show(std::cout); | |
305 | if (fHelper) fHelper->Print(); | |
306 | } | |
307 | /** | |
308 | * Show the help | |
309 | * | |
310 | * @param o | |
311 | * | |
312 | * @return | |
313 | */ | |
314 | Bool_t Help(std::ostream& o=std::cout, bool asProg=false) | |
315 | { | |
316 | if (!fOptions.Has("help")) return true; | |
317 | ||
318 | if (asProg) | |
a80dde0d | 319 | o << "Usage: runTrain2 --name=NAME --class=CLASS [OPTIONS]"; |
fdfd93b4 | 320 | else |
321 | o << "Usage: RunTrain(NAME, CLASS, OPTIONS)"; | |
322 | ||
323 | o << "\n\nOptions:\n\n"; | |
324 | if (asProg) { | |
325 | OptionList tmp(fOptions); | |
326 | tmp.Add("name", "STRING", "Name of train", fName); | |
327 | tmp.Add("class", "NAME", "Name of setup class", ""); | |
328 | tmp.Help(o," --"); | |
329 | } | |
330 | else | |
331 | fOptions.Help(o, " "); | |
332 | ||
333 | o << "\n"; | |
334 | ||
335 | if (!fHelper && fOptions.Has("url")) { | |
336 | TString url = fOptions.Get("url"); | |
337 | fHelper = Helper::Create(url.Data()); | |
338 | } | |
339 | if (fHelper) { | |
340 | o << fHelper->Desc() << " URL form:\n\n" | |
341 | << " " << fHelper->UrlHelp() << "\n\n" | |
342 | << "Options:\n"; | |
343 | fHelper->Options().Help(o, " "); | |
344 | o << "\n"; | |
345 | } | |
346 | else { | |
347 | o << "Possible URL forms:\n\n"; | |
348 | Helper::ShowUrlHelp("LocalHelper"); | |
349 | Helper::ShowUrlHelp("ProofHelper"); | |
350 | Helper::ShowUrlHelp("LiteHelper"); | |
351 | Helper::ShowUrlHelp("AAFHelper"); | |
352 | Helper::ShowUrlHelp("AAFPluginHelper"); | |
353 | Helper::ShowUrlHelp("GridHelper"); | |
354 | o << "\n"; | |
355 | } | |
356 | return false; | |
357 | } | |
358 | /** | |
359 | * Run train. This will AcLic compile the setup script, create | |
360 | * an object of that type with the given name, and then pass the | |
361 | * options to it. Then, it will run the setup. | |
362 | * | |
363 | * @param name Train name | |
364 | * @param cls Class name | |
365 | * @param opts Comma seperated list of options | |
366 | * | |
367 | * @return true on success | |
368 | */ | |
369 | static Bool_t Main(const TString& name, const TString& cls, | |
370 | const TCollection* opts, | |
371 | Bool_t asProg=true) | |
372 | { | |
a80dde0d | 373 | Bool_t ret = false; |
374 | try { | |
375 | if (cls.IsNull()) | |
376 | throw TString("No class name specified"); | |
377 | if (name.IsNull()) | |
378 | throw TString("No train name specified"); | |
fdfd93b4 | 379 | |
a80dde0d | 380 | Int_t error = 0; |
381 | Int_t r1 = gROOT->LoadMacro(Form("%s.C++g", cls.Data()), &error); | |
382 | if (r1 < 0 || error) | |
383 | throw TString::Format("Failed to load setup %s: %d", cls.Data(), error); | |
384 | ||
385 | // Make our object using the interpreter | |
386 | TString create = TString::Format("new %s(\"%s\")", | |
387 | cls.Data(), name.Data()); | |
388 | gROOT->ProcessLine("gSystem->RedirectOutput(\"/dev/null\",\"w\");"); | |
389 | Long_t retP = gROOT->ProcessLine(create, &error); | |
390 | gROOT->ProcessLine("gSystem->RedirectOutput(0);"); | |
391 | if (!retP || error) | |
392 | throw TString::Format("Failed to make object of class %s: " | |
393 | "0x%08lx/%d\n\t%s", | |
394 | cls.Data(), retP, error, create.Data()); | |
395 | ||
396 | TrainSetup* train = reinterpret_cast<TrainSetup*>(retP); | |
fdfd93b4 | 397 | |
a80dde0d | 398 | // Now parse the options |
399 | if (!train->Options().Parse(opts)) | |
400 | throw TString("Failed to parse options"); | |
fdfd93b4 | 401 | |
a80dde0d | 402 | // Check if we got a help request |
403 | if (train->Options().Has("help")) { | |
404 | train->Help(std::cout, asProg); | |
405 | ret = true; | |
406 | throw TString(""); | |
407 | } | |
408 | ||
409 | // return train->Init(); | |
410 | ret = train->Run(); | |
411 | } | |
412 | catch (TString& e) { | |
a54cc77b | 413 | if (!e.IsNull()) Error("Main", "%s", e.Data()); |
a80dde0d | 414 | } |
415 | if (gApplication && asProg) { | |
416 | gSystem->Sleep(3); | |
417 | gApplication->Terminate(ret ? 0 : 1); | |
fdfd93b4 | 418 | } |
a80dde0d | 419 | return ret; |
fdfd93b4 | 420 | } |
421 | protected: | |
422 | //__________________________________________________________________ | |
423 | /** | |
424 | * @{ | |
425 | * @Name Overloadable behaviour | |
426 | */ | |
427 | //------------------------------------------------------------------ | |
428 | /** | |
429 | * Create the analysis manager | |
430 | * | |
431 | * @param name Name of the analysis | |
432 | * | |
433 | * @return Created analysis manager | |
434 | */ | |
435 | virtual AliAnalysisManager* CreateAnalysisManager(const char* name) | |
436 | { | |
437 | return new AliAnalysisManager(name,"Analysis Train"); | |
438 | } | |
439 | //------------------------------------------------------------------ | |
440 | /** | |
441 | * Create input handler | |
442 | * | |
443 | * @param type | |
444 | * | |
445 | * @return | |
446 | */ | |
447 | virtual AliVEventHandler* CreateInputHandler(UShort_t type) | |
448 | { | |
449 | switch (type) { | |
450 | case Helper::kESD: return new AliESDInputHandler(); | |
451 | case Helper::kAOD: return new AliAODInputHandler(); | |
452 | case Helper::kUser: return 0; | |
453 | } | |
454 | return 0; | |
455 | } | |
456 | //------------------------------------------------------------------ | |
457 | /** | |
458 | * Create MC input handler | |
459 | * | |
460 | * @param type Run type (ESD or AOD) | |
461 | * @param mc Assume monte-carlo input | |
462 | * | |
463 | * @return | |
464 | */ | |
465 | virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc) | |
466 | { | |
467 | if (!mc) return 0; | |
468 | AliMCEventHandler* mcHandler = new AliMCEventHandler(); | |
469 | mcHandler->SetReadTR(true); | |
470 | return mcHandler; | |
471 | } | |
472 | //------------------------------------------------------------------ | |
473 | /** | |
474 | * Create output event handler | |
475 | * | |
476 | * @param type | |
477 | * | |
478 | * @return | |
479 | */ | |
480 | virtual AliVEventHandler* CreateOutputHandler(UShort_t type) | |
481 | { | |
482 | AliAODHandler* ret = new AliAODHandler(); | |
483 | switch (type) { | |
484 | case Helper::kESD: | |
485 | ret->SetOutputFileName("AliAOD.root"); | |
486 | break; | |
487 | case Helper::kAOD: | |
488 | ret->SetOutputFileName("AliAOD.pass2.root"); | |
489 | break; | |
490 | case Helper::kUser: | |
491 | break; | |
492 | } | |
493 | ||
494 | return ret; | |
495 | } | |
496 | //------------------------------------------------------------------ | |
497 | /** | |
498 | * Create physics selection, and add to manager | |
499 | * | |
500 | * @param mc Whether this is for MC | |
501 | * @param mgr Manager | |
502 | */ | |
503 | virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr) | |
504 | { | |
505 | if (fOptions.Has("bare-ps")) { | |
506 | AliInputEventHandler* input = | |
507 | dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler()); | |
508 | if (!input) return; | |
509 | ||
510 | AliPhysicsSelection* ps = new AliPhysicsSelection(); | |
511 | if (mc) ps->SetAnalyzeMC(); | |
512 | ||
513 | input->SetEventSelection(ps); | |
514 | ||
515 | return; | |
516 | } | |
517 | gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc)); | |
518 | mgr->RegisterExtraFile("event_stat.root"); | |
519 | } | |
520 | //------------------------------------------------------------------ | |
521 | /** | |
522 | * Create centrality selection, and add to manager | |
523 | * | |
524 | * @param mc Whether this is for MC | |
525 | * @param mgr Manager | |
526 | */ | |
527 | virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr) | |
528 | { | |
529 | gROOT->Macro("AddTaskCentrality.C"); | |
530 | const char* name = "CentralitySelection"; | |
531 | AliCentralitySelectionTask* ctask = | |
532 | dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name)); | |
533 | if (!ctask) return; | |
534 | if (mc) ctask->SetMCInput(); | |
535 | } | |
536 | //------------------------------------------------------------------ | |
537 | /** | |
538 | * Create analysis tasks. Must be overloaded by sub-class | |
539 | * | |
540 | * @param mgr Manager | |
541 | */ | |
542 | virtual void CreateTasks(AliAnalysisManager* mgr)=0; | |
543 | virtual const Char_t* ClassName() const = 0; | |
544 | /* @} */ | |
545 | //__________________________________________________________________ | |
546 | /** | |
547 | * @{ | |
548 | * @name Utility functions | |
549 | */ | |
550 | /** | |
551 | * Escape bad elements of the name | |
552 | * | |
553 | * @param name Name to escape | |
554 | * @param datime Date and Time | |
555 | * | |
556 | * @return escaped name | |
557 | */ | |
558 | static TString EscapeName(const char* name, const TString& datimeStr) | |
559 | { | |
560 | TString escaped = name; | |
561 | char c[] = { ' ', '/', '@', 0 }; | |
562 | char* p = c; | |
563 | while (*p) { | |
46b25775 | 564 | char tmp[] = { *p, '\0' }; |
565 | escaped.ReplaceAll(tmp, "_"); | |
fdfd93b4 | 566 | p++; |
567 | } | |
568 | if (!datimeStr.IsNull()) { | |
569 | TDatime datime; | |
570 | if (datimeStr.EqualTo("now", TString::kIgnoreCase)) | |
571 | datime.Set(); | |
46b25775 | 572 | else { |
573 | // Try various formats | |
574 | struct tm t; | |
575 | const char* formats[] = { "%Ec", // Locale | |
576 | "%c", // Locale | |
577 | "%Ex EX", // Locale | |
578 | "%x %X", // Locale | |
a80dde0d | 579 | "%Y%m%d_%H%M", // YYYYMMDD_HHMM |
46b25775 | 580 | "%F %R", // ISO standard, no seconds |
581 | 0 }; | |
582 | const char** f = formats; | |
583 | Bool_t found = false; | |
584 | while (*f && !found) { | |
585 | // Reset needed fields | |
586 | t.tm_year = 0; | |
587 | t.tm_mon = 0; | |
588 | t.tm_mday = 0; | |
589 | t.tm_hour = 0; | |
590 | t.tm_min = 0; | |
591 | // Stop processing on first match | |
592 | if (strptime(datimeStr.Data(), *f, &t) != 0) found = true; | |
593 | f++; | |
594 | } | |
a80dde0d | 595 | if (found) { |
596 | t.tm_mon += 1; // Return 0-based month | |
46b25775 | 597 | datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0); |
a80dde0d | 598 | } |
46b25775 | 599 | } |
fdfd93b4 | 600 | if (datime.GetYear() <= 1995 || |
601 | datime.GetMonth() == 0 || | |
602 | datime.GetDay() == 0) return escaped; | |
603 | escaped.Append(Form("_%04d%02d%02d_%02d%02d", | |
604 | datime.GetYear(), | |
605 | datime.GetMonth(), | |
606 | datime.GetDay(), | |
607 | datime.GetHour(), | |
608 | datime.GetMinute())); | |
609 | } | |
610 | return escaped; | |
611 | } | |
612 | /** | |
613 | * Make our working directory if so requested | |
614 | * | |
615 | * @return true on success | |
616 | */ | |
617 | Bool_t SetupWorkingDirectory() | |
618 | { | |
619 | // Get the name of the target directory | |
620 | TString& nam = fEscapedName; | |
621 | ||
622 | // Check if the directory exists already | |
623 | Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0; | |
624 | if (fHelper->Operation() == Helper::kTerminate && !exists) { | |
625 | Error("SetupWorkingDirectory", "File/directory %s does not exists", | |
626 | nam.Data()); | |
627 | return false; | |
628 | } | |
629 | ||
630 | Bool_t overwrite = fOptions.Has("overwrite"); | |
631 | // If we're not allowed to overwrite, then complain | |
632 | if (!overwrite && exists) { | |
633 | Error("SetupWorkingDirectory", "File/directory %s already exists", | |
634 | nam.Data()); | |
635 | return false; | |
636 | } | |
637 | ||
638 | // Make the target directory if it doesn't exists | |
639 | if (!exists) { | |
640 | if (gSystem->MakeDirectory(nam.Data())) { | |
641 | Error("SetupWorkingDirectory", "Failed to make directory '%s'", | |
642 | nam.Data()); | |
643 | return false; | |
644 | } | |
645 | } | |
646 | ||
647 | // Change directory to target directory | |
648 | if (!gSystem->ChangeDirectory(nam.Data())) { | |
649 | Error("SetupWorkingDirectory", "Failed to change directory to %s", | |
650 | nam.Data()); | |
651 | return false; | |
652 | } | |
653 | Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there", | |
654 | nam.Data()); | |
655 | return true; | |
656 | } | |
657 | /** | |
658 | * Save the setup as a ROOT script and possibly also a shell script | |
659 | * | |
660 | * @param asShellScript If true, also save as shell script | |
661 | */ | |
662 | virtual void SaveSetup(Bool_t asShellScript) | |
663 | { | |
46b25775 | 664 | OptionList tmp(fOptions); |
a80dde0d | 665 | const OptionList* uopts = (fHelper ? &fHelper->Options() : 0); |
46b25775 | 666 | if (tmp.Find("overwrite")) tmp.Set("overwrite"); |
a80dde0d | 667 | if (tmp.Find("date") && fEscapedName.Length() > fName.Length()+1) { |
668 | Int_t n = fName.Length()+1; | |
669 | tmp.Set("date", fEscapedName(n, fEscapedName.Length()-n)); | |
670 | } | |
fdfd93b4 | 671 | if (asShellScript) |
a80dde0d | 672 | SaveSetupShell("rerun", ClassName(), fName, tmp, uopts); |
673 | SaveSetupROOT("ReRun", ClassName(), fName, tmp, uopts); | |
674 | if (fHelper) fHelper->AuxSave(fEscapedName, asShellScript); | |
fdfd93b4 | 675 | } |
676 | /** | |
677 | * Save a setup as a shell script | |
678 | * | |
679 | * @param out Output name of shell script | |
680 | * @param cls Class of the train | |
681 | * @param name Name of the train | |
682 | * @param opts Option list | |
683 | */ | |
684 | static void SaveSetupShell(const TString& out, const TString& cls, | |
a80dde0d | 685 | const TString& name, const OptionList& opts, |
686 | const OptionList* uopts) | |
fdfd93b4 | 687 | { |
688 | std::ofstream o(Form("%s.sh", out.Data())); | |
689 | o << "#!/bin/bash\n\n" | |
690 | << "class=\"" << cls << "\"\n" | |
691 | << "name=\"" << name << "\"\n\n" | |
692 | << "# Available options\n" | |
693 | << "# \n"; | |
694 | opts.Help(o, "# --"); | |
a80dde0d | 695 | if (uopts) { |
696 | o << "#\n" | |
697 | << "# Available URI options\n" | |
698 | << "# \n"; | |
699 | uopts->Help(o, "# "); | |
700 | } | |
fdfd93b4 | 701 | o << "#\n" |
702 | << "opts=(--class=$class \\\n" | |
703 | << " --name=$name"; | |
704 | opts.Store(o, " \\\n --", "", true); | |
705 | o << ")\n\n" | |
92f304b1 | 706 | << "echo \"Running runTrain ${opts[@]} $@\"\n" |
707 | << "runTrain \"${opts[@]}\" $@\n\n" | |
fdfd93b4 | 708 | << "# EOF" << std::endl; |
709 | o.close(); | |
710 | gSystem->Exec(Form("chmod a+x %s.sh", out.Data())); | |
711 | } | |
712 | /** | |
713 | * Save a setup as a ROOT script | |
714 | * | |
715 | * @param out Output name of shell script | |
716 | * @param cls Class of the train | |
717 | * @param name Name of the train | |
718 | * @param opts Option list | |
719 | */ | |
720 | static void SaveSetupROOT(const TString& out, const TString& cls, | |
a80dde0d | 721 | const TString& name, const OptionList& opts, |
722 | const OptionList* uopts) | |
fdfd93b4 | 723 | { |
724 | OptionList tmp(opts); | |
725 | tmp.Remove("url"); | |
a80dde0d | 726 | |
fdfd93b4 | 727 | std::ofstream o(Form("%s.C", out.Data())); |
a80dde0d | 728 | o << "// Available options:\n" |
729 | << "// \n"; | |
730 | tmp.Help(o, "// "); | |
731 | if (uopts) { | |
732 | o << "// \n" | |
733 | << "// Available URI options\n"; | |
734 | uopts->Help(o, "// "); | |
735 | } | |
736 | o << "//\n" | |
737 | << "Bool_t " << out << "()\n" | |
fdfd93b4 | 738 | << "{\n" |
739 | << " TString name(\"" << name << "\");\n" | |
740 | << " TString cls(\"" << cls << "\");\n" | |
a80dde0d | 741 | << " TUrl uri(\"" << opts.Get("url") << "\");\n" |
742 | << " \n" | |
fdfd93b4 | 743 | << " TString opts("; |
744 | tmp.Store(o, "\"", ",\"\n ", false); | |
745 | o << ");\n\n" | |
46b25775 | 746 | << " TString path("; |
747 | TString path(gROOT->GetMacroPath()); | |
748 | TObjArray* elements = path.Tokenize(":"); | |
749 | TObjString* element = 0; | |
750 | TIter next(elements); | |
751 | while ((element = static_cast<TObjString*>(next()))) { | |
752 | if (element->String().IsNull()) continue; | |
753 | o << "\n \"" << element->GetName() << ":\""; | |
754 | } | |
755 | elements->Delete(); | |
756 | o << ");\n" | |
757 | << " path.Append(\"$ALICE_ROOT/PWGLF/FORWARD/trains\");\n" | |
758 | << " gROOT->SetMacroPath(path);\n\n" | |
fdfd93b4 | 759 | << " gROOT->LoadMacro(\"RunTrain.C\");\n\n" |
760 | << " return RunTrain(name, cls, uri, opts);\n" | |
761 | << "}\n" | |
762 | << "//\n" | |
763 | << "// EOF\n" | |
764 | << "//" << std::endl; | |
765 | o.close(); | |
766 | } | |
767 | /* @} */ | |
768 | TString fName; | |
769 | TString fEscapedName; | |
770 | OptionList fOptions; | |
771 | Helper* fHelper; | |
772 | }; | |
773 | #endif |