]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/trains/TrainSetup.C
Updates to address coverity issues.
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / TrainSetup.C
CommitLineData
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>
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>
35#else
36struct Helper;
37struct OptionList;
38class TDatime;
39class TUrl;
40class TString;
41class AliVEventHandler;
42class AliAnalysisManager;
43class AliInputEventHandler;
44#endif
45
46//====================================================================
47/**
48 * Generic set-up of an analysis train using the grid-handler (AliEn plugin).
49 *
50 * See also @ref train_setup_doc
51 *
52 * @ingroup pwglf_forward_trains
53 *
54 */
55struct TrainSetup
56{
57 /**
58 * Constructor
59 *
60 * @param name Name of the train
61 */
62 TrainSetup(const TString& name)
63 : fName(name),
64 fEscapedName(name),
65 fHelper(0)
66 {
67 fOptions.Add("help", "Show help");
68 fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now");
69 fOptions.Add("mc", "Assume MC input");
70 fOptions.Add("bare-ps", "Use bare physics selection w/o task");
71 fOptions.Add("verbose", "LEVEL", "Set verbosity level", "0");
72 fOptions.Add("url", "URL", "Job location & input URL", "");
73 fOptions.Add("overwrite", "Allow overwrite");
74 fOptions.Add("events", "N", "Number of events to analyse", "-1");
75 fOptions.Add("type", "ESD|AOD|USER", "Input data stype", "");
76 fEscapedName = EscapeName(fName, "");
77 }
78 /**
79 * Destructor
80 */
81 virtual ~TrainSetup() {}
82 /* @} */
83 //__________________________________________________________________
84 /**
85 * @{
86 * @name Execution
87 */
88 /**
89 * Initialize
90 *
91 * @return true on success
92 */
93 Bool_t Init()
94 {
95 // --- Create the helper -----------------------------------------
96 TString url = fOptions.Get("url");
97 Int_t verbose = fOptions.AsInt("verbose");
98 Bool_t mc = fOptions.AsBool("mc");
99
100 fHelper = Helper::Create(url.Data(), verbose);
101 if (!fHelper) {
102 Error("Init", "Failed to make the worker for URL %s", url.Data());
103 return false;
104 }
105
106 UShort_t type = fHelper->InputType();
107 if (fOptions.Has("type")) {
108 const TString& it = fOptions.Get("type");
109 if (it.EqualTo("ESD",TString::kIgnoreCase)) type = Helper::kESD;
110 else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Helper::kAOD;
111 else if (it.EqualTo("user",TString::kIgnoreCase))
112 type = Helper::kUser;
113 }
114
115 // --- Get current directory and set-up sub-directory ------------
116 TString cwd = gSystem->WorkingDirectory();
117 if (!SetupWorkingDirectory()) return false;
118
119 // --- Do initial helper setup -----------------------------------
120 if (!fHelper->PreSetup()) return false;
121
122 // --- Load ROOT libraries ---------------------------------------
123 if (!fHelper->LoadROOT()) return false;
124
125 // --- Load AliROOT libraries ------------------------------------
126 if (!fHelper->LoadAliROOT()) return false;
127
128 // --- Create analysis manager -----------------------------------
129 AliAnalysisManager *mgr = CreateAnalysisManager(fName);
130
131 // In test mode, collect system information on every event
132 // if (oper == kTest) mgr->SetNSysInfo(1);
133 if (verbose > 0) mgr->SetDebugLevel(verbose);
134 if (fHelper->Mode() == Helper::kLocal)
135 mgr->SetUseProgressBar(kTRUE, 100);
136
137 // --- ESD input handler ------------------------------------------
138 AliVEventHandler* inputHandler = CreateInputHandler(type);
139 if (inputHandler) mgr->SetInputEventHandler(inputHandler);
140
141 // --- Monte-Carlo ------------------------------------------------
142 AliVEventHandler* mcHandler = CreateMCHandler(type,mc);
143 if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
144
145 // --- AOD output handler -----------------------------------------
146 AliVEventHandler* outputHandler = CreateOutputHandler(type);
147 if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
148
149 // --- Include analysis macro path in search path ----------------
150 gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
151 cwd.Data(), gROOT->GetMacroPath()));
152
153 // --- Physics selction - only for ESD ---------------------------
154 if (type == Helper::kESD) CreatePhysicsSelection(mc, mgr);
155
156 // --- Create centrality task ------------------------------------
157 CreateCentralitySelection(mc, mgr);
158
159 // --- Create tasks ----------------------------------------------
160 CreateTasks(mgr);
161
162 // --- Post set-up initialization of helper ----------------------
163 if (!fHelper->PostSetup()) return false;
164
165 // --- Set debug level on defined tasks --------------------------
166 if (verbose > 0) {
167 TIter next(mgr->GetTasks());
168 AliAnalysisTask* sub = 0;
169 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
170 AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
171 if (!se) continue;
172 se->SetDebugLevel(verbose);
173 }
174 }
175
176 // --- Print this setup ------------------------------------------
177 Print();
178
179 // --- Initialise the train --------------------------------------
180 if (!mgr->InitAnalysis()) {
181 gSystem->ChangeDirectory(cwd.Data());
182 Error("Init","Failed to initialise train");
183 return false;
184 }
185
186 // --- Enable progress bar ---------------------------------------
187 if (fHelper->Mode() != Helper::kGrid)
188 mgr->SetUseProgressBar(true, 100);
189
190 // --- Save setup to disk ----------------------------------------
191 SaveSetup(true);
192
193 // Some information
194 mgr->PrintStatus();
195
196 return true;
197 }
198 Bool_t Run(Bool_t doExit=false)
199 {
200 TString cwd = gSystem->WorkingDirectory();
201 Bool_t status = false;
202 try {
203 if (!Init()) throw TString("Failed to intialize the train");
204
205 // if (r) SaveSetup(*r, nEvents, asShell);
206
207 Long64_t nEvents = fOptions.AsLong("events", -1);
208 Long64_t ret = fHelper->Run(nEvents);
209
210 // Make sure we go back
211 gSystem->ChangeDirectory(cwd.Data());
212
213 // Return.
214 if (ret < 0) throw TString("Analysis failed");
215
216 status = true;
217 }
218 catch (TString& e) {
219 Error("Main", e);
220 status = false;
221 }
222 if (gApplication && doExit) {
223 gSystem->Sleep(3);
224 gApplication->Terminate(status ? 0 : 1);
225 }
226 return true;
227 }
228 /**
229 * Get the options
230 *
231 *
232 * @return Reference ot the options
233 */
234 OptionList& Options() { return fOptions; }
235 /**
236 * Print information to standard output
237 *
238 */
239 void Print(Option_t* ="") const
240 {
241 std::cout << "Train: " << fName << " (" << fEscapedName << ")"
242 << std::endl;
243 fOptions.Show(std::cout);
244 if (fHelper) fHelper->Print();
245 }
246 /**
247 * Show the help
248 *
249 * @param o
250 *
251 * @return
252 */
253 Bool_t Help(std::ostream& o=std::cout, bool asProg=false)
254 {
255 if (!fOptions.Has("help")) return true;
256
257 if (asProg)
258 o << "Usage: runTrain --name=NAME --class=CLASS [OPTIONS]";
259 else
260 o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
261
262 o << "\n\nOptions:\n\n";
263 if (asProg) {
264 OptionList tmp(fOptions);
265 tmp.Add("name", "STRING", "Name of train", fName);
266 tmp.Add("class", "NAME", "Name of setup class", "");
267 tmp.Help(o," --");
268 }
269 else
270 fOptions.Help(o, " ");
271
272 o << "\n";
273
274 if (!fHelper && fOptions.Has("url")) {
275 TString url = fOptions.Get("url");
276 fHelper = Helper::Create(url.Data());
277 }
278 if (fHelper) {
279 o << fHelper->Desc() << " URL form:\n\n"
280 << " " << fHelper->UrlHelp() << "\n\n"
281 << "Options:\n";
282 fHelper->Options().Help(o, " ");
283 o << "\n";
284 }
285 else {
286 o << "Possible URL forms:\n\n";
287 Helper::ShowUrlHelp("LocalHelper");
288 Helper::ShowUrlHelp("ProofHelper");
289 Helper::ShowUrlHelp("LiteHelper");
290 Helper::ShowUrlHelp("AAFHelper");
291 Helper::ShowUrlHelp("AAFPluginHelper");
292 Helper::ShowUrlHelp("GridHelper");
293 o << "\n";
294 }
295 return false;
296 }
297 /**
298 * Run train. This will AcLic compile the setup script, create
299 * an object of that type with the given name, and then pass the
300 * options to it. Then, it will run the setup.
301 *
302 * @param name Train name
303 * @param cls Class name
304 * @param opts Comma seperated list of options
305 *
306 * @return true on success
307 */
308 static Bool_t Main(const TString& name, const TString& cls,
309 const TCollection* opts,
310 Bool_t asProg=true)
311 {
312 if (cls.IsNull()) {
313 Error("Main", "No class name specified");
314 return false;
315 }
316 if (name.IsNull()) {
317 Error("Main", "No train name specified");
318 return false;
319 }
320 Int_t error = 0;
321 Int_t r1 = gROOT->LoadMacro(Form("%s.C++g", cls.Data()), &error);
322 if (r1 < 0 || error) {
323 Error("Main", "Failed to load setup %s: %d", cls.Data(), error);
324 return false;
325 }
326
327 // Make our object using the interpreter
328 TString create = TString::Format("new %s(\"%s\")",
329 cls.Data(), name.Data());
330 gROOT->ProcessLine("gSystem->RedirectOutput(\"/dev/null\",\"w\");");
331 Long_t ret = gROOT->ProcessLine(create, &error);
332 gROOT->ProcessLine("gSystem->RedirectOutput(0);");
333 if (!ret || error) {
334 Error("Main", "Failed to make object of class %s: 0x%08lx/%d\n\t%s",
335 cls.Data(), ret, error, create.Data());
336 return false;
337 }
338 TrainSetup* train = reinterpret_cast<TrainSetup*>(ret);
339
340 // Now parse the options
341 if (!train->Options().Parse(opts)) {
342 Error("Main", "Failed to parse options");
343 return false;
344 }
345
346 // Check if we got a help request
347 if (train->Options().Has("help")) {
348 train->Help(std::cout, asProg);
349 return true;
350 }
351 // return train->Init();
352 return train->Run(asProg);
353 }
354protected:
355 //__________________________________________________________________
356 /**
357 * @{
358 * @Name Overloadable behaviour
359 */
360 //------------------------------------------------------------------
361 /**
362 * Create the analysis manager
363 *
364 * @param name Name of the analysis
365 *
366 * @return Created analysis manager
367 */
368 virtual AliAnalysisManager* CreateAnalysisManager(const char* name)
369 {
370 return new AliAnalysisManager(name,"Analysis Train");
371 }
372 //------------------------------------------------------------------
373 /**
374 * Create input handler
375 *
376 * @param type
377 *
378 * @return
379 */
380 virtual AliVEventHandler* CreateInputHandler(UShort_t type)
381 {
382 switch (type) {
383 case Helper::kESD: return new AliESDInputHandler();
384 case Helper::kAOD: return new AliAODInputHandler();
385 case Helper::kUser: return 0;
386 }
387 return 0;
388 }
389 //------------------------------------------------------------------
390 /**
391 * Create MC input handler
392 *
393 * @param type Run type (ESD or AOD)
394 * @param mc Assume monte-carlo input
395 *
396 * @return
397 */
398 virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc)
399 {
400 if (!mc) return 0;
401 AliMCEventHandler* mcHandler = new AliMCEventHandler();
402 mcHandler->SetReadTR(true);
403 return mcHandler;
404 }
405 //------------------------------------------------------------------
406 /**
407 * Create output event handler
408 *
409 * @param type
410 *
411 * @return
412 */
413 virtual AliVEventHandler* CreateOutputHandler(UShort_t type)
414 {
415 AliAODHandler* ret = new AliAODHandler();
416 switch (type) {
417 case Helper::kESD:
418 ret->SetOutputFileName("AliAOD.root");
419 break;
420 case Helper::kAOD:
421 ret->SetOutputFileName("AliAOD.pass2.root");
422 break;
423 case Helper::kUser:
424 break;
425 }
426
427 return ret;
428 }
429 //------------------------------------------------------------------
430 /**
431 * Create physics selection, and add to manager
432 *
433 * @param mc Whether this is for MC
434 * @param mgr Manager
435 */
436 virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
437 {
438 if (fOptions.Has("bare-ps")) {
439 AliInputEventHandler* input =
440 dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler());
441 if (!input) return;
442
443 AliPhysicsSelection* ps = new AliPhysicsSelection();
444 if (mc) ps->SetAnalyzeMC();
445
446 input->SetEventSelection(ps);
447
448 return;
449 }
450 gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
451 mgr->RegisterExtraFile("event_stat.root");
452 }
453 //------------------------------------------------------------------
454 /**
455 * Create centrality selection, and add to manager
456 *
457 * @param mc Whether this is for MC
458 * @param mgr Manager
459 */
460 virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
461 {
462 gROOT->Macro("AddTaskCentrality.C");
463 const char* name = "CentralitySelection";
464 AliCentralitySelectionTask* ctask =
465 dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
466 if (!ctask) return;
467 if (mc) ctask->SetMCInput();
468 }
469 //------------------------------------------------------------------
470 /**
471 * Create analysis tasks. Must be overloaded by sub-class
472 *
473 * @param mgr Manager
474 */
475 virtual void CreateTasks(AliAnalysisManager* mgr)=0;
476 virtual const Char_t* ClassName() const = 0;
477 /* @} */
478 //__________________________________________________________________
479 /**
480 * @{
481 * @name Utility functions
482 */
483 /**
484 * Escape bad elements of the name
485 *
486 * @param name Name to escape
487 * @param datime Date and Time
488 *
489 * @return escaped name
490 */
491 static TString EscapeName(const char* name, const TString& datimeStr)
492 {
493 TString escaped = name;
494 char c[] = { ' ', '/', '@', 0 };
495 char* p = c;
496 while (*p) {
497 escaped.ReplaceAll(Form("%c", *p), "_");
498 p++;
499 }
500 if (!datimeStr.IsNull()) {
501 TDatime datime;
502 if (datimeStr.EqualTo("now", TString::kIgnoreCase))
503 datime.Set();
504 else
505 datime.Set(datimeStr.Data());
506 if (datime.GetYear() <= 1995 ||
507 datime.GetMonth() == 0 ||
508 datime.GetDay() == 0) return escaped;
509 escaped.Append(Form("_%04d%02d%02d_%02d%02d",
510 datime.GetYear(),
511 datime.GetMonth(),
512 datime.GetDay(),
513 datime.GetHour(),
514 datime.GetMinute()));
515 }
516 return escaped;
517 }
518 /**
519 * Make our working directory if so requested
520 *
521 * @return true on success
522 */
523 Bool_t SetupWorkingDirectory()
524 {
525 // Get the name of the target directory
526 TString& nam = fEscapedName;
527
528 // Check if the directory exists already
529 Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
530 if (fHelper->Operation() == Helper::kTerminate && !exists) {
531 Error("SetupWorkingDirectory", "File/directory %s does not exists",
532 nam.Data());
533 return false;
534 }
535
536 Bool_t overwrite = fOptions.Has("overwrite");
537 // If we're not allowed to overwrite, then complain
538 if (!overwrite && exists) {
539 Error("SetupWorkingDirectory", "File/directory %s already exists",
540 nam.Data());
541 return false;
542 }
543
544 // Make the target directory if it doesn't exists
545 if (!exists) {
546 if (gSystem->MakeDirectory(nam.Data())) {
547 Error("SetupWorkingDirectory", "Failed to make directory '%s'",
548 nam.Data());
549 return false;
550 }
551 }
552
553 // Change directory to target directory
554 if (!gSystem->ChangeDirectory(nam.Data())) {
555 Error("SetupWorkingDirectory", "Failed to change directory to %s",
556 nam.Data());
557 return false;
558 }
559 Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there",
560 nam.Data());
561 return true;
562 }
563 /**
564 * Save the setup as a ROOT script and possibly also a shell script
565 *
566 * @param asShellScript If true, also save as shell script
567 */
568 virtual void SaveSetup(Bool_t asShellScript)
569 {
570 if (asShellScript)
571 SaveSetupShell("rerun", ClassName(), fName, fOptions);
572 SaveSetupROOT("ReRun", ClassName(), fName, fOptions);
573 }
574 /**
575 * Save a setup as a shell script
576 *
577 * @param out Output name of shell script
578 * @param cls Class of the train
579 * @param name Name of the train
580 * @param opts Option list
581 */
582 static void SaveSetupShell(const TString& out, const TString& cls,
583 const TString& name, const OptionList& opts)
584 {
585 std::ofstream o(Form("%s.sh", out.Data()));
586 o << "#!/bin/bash\n\n"
587 << "class=\"" << cls << "\"\n"
588 << "name=\"" << name << "\"\n\n"
589 << "# Available options\n"
590 << "# \n";
591 opts.Help(o, "# --");
592 o << "#\n"
593 << "opts=(--class=$class \\\n"
594 << " --name=$name";
595 opts.Store(o, " \\\n --", "", true);
596 o << ")\n\n"
597 << "echo \"Running runTrain ${opts[@]} $@\"\n"
598 << "runTrain \"${opts[@]}\" $@\n\n"
599 << "# EOF" << std::endl;
600 o.close();
601 gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
602 }
603 /**
604 * Save a setup as a ROOT script
605 *
606 * @param out Output name of shell script
607 * @param cls Class of the train
608 * @param name Name of the train
609 * @param opts Option list
610 */
611 static void SaveSetupROOT(const TString& out, const TString& cls,
612 const TString& name, const OptionList& opts)
613 {
614 OptionList tmp(opts);
615 tmp.Remove("url");
616 std::ofstream o(Form("%s.C", out.Data()));
617 o << "/* Available options:\n"
618 << " *\n";
619 tmp.Help(o, " * ");
620 o << " */\n"
621 << "Bool_t " << out << "()\n"
622 << "{\n"
623 << " TString name(\"" << name << "\");\n"
624 << " TString cls(\"" << cls << "\");\n"
625 << " TString uri(\"" << opts.Get("url") << "\");\n"
626 << " TString opts(";
627 tmp.Store(o, "\"", ",\"\n ", false);
628 o << ");\n\n"
629 << " gROOT->LoadMacro(\"RunTrain.C\");\n\n"
630 << " return RunTrain(name, cls, uri, opts);\n"
631 << "}\n"
632 << "//\n"
633 << "// EOF\n"
634 << "//" << std::endl;
635 o.close();
636 }
637 /* @} */
638 TString fName;
639 TString fEscapedName;
640 OptionList fOptions;
641 Helper* fHelper;
642};
643#endif