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