2 * @defgroup pwglf_forward_trains Trains
6 * @ingroup pwglf_forward
10 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
11 * @date Tue Oct 16 17:56:57 2012
13 * @brief Base classs for train specifications
15 * @ingroup pwglf_forward_trains
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>
41 class AliVEventHandler;
42 class AliAnalysisManager;
43 class AliInputEventHandler;
46 //====================================================================
48 * Generic set-up of an analysis train using the grid-handler (AliEn plugin).
50 * See also @ref train_setup_doc
52 * @ingroup pwglf_forward_trains
60 * @param name Name of the train
62 TrainSetup(const TString& name)
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, "");
81 virtual ~TrainSetup() {}
83 //__________________________________________________________________
91 * @return true on success
95 // --- Create the helper -----------------------------------------
96 TString url = fOptions.Get("url");
97 Int_t verbose = fOptions.AsInt("verbose");
98 Bool_t mc = fOptions.AsBool("mc");
100 fHelper = Helper::Create(url.Data(), verbose);
102 Error("Init", "Failed to make the worker for URL %s", url.Data());
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;
115 // --- Get current directory and set-up sub-directory ------------
116 TString cwd = gSystem->WorkingDirectory();
117 if (!SetupWorkingDirectory()) return false;
119 // --- Do initial helper setup -----------------------------------
120 if (!fHelper->PreSetup()) return false;
122 // --- Load ROOT libraries ---------------------------------------
123 if (!fHelper->LoadROOT()) return false;
125 // --- Load AliROOT libraries ------------------------------------
126 if (!fHelper->LoadAliROOT()) return false;
128 // --- Create analysis manager -----------------------------------
129 AliAnalysisManager *mgr = CreateAnalysisManager(fName);
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);
137 // --- ESD input handler ------------------------------------------
138 AliVEventHandler* inputHandler = CreateInputHandler(type);
139 if (inputHandler) mgr->SetInputEventHandler(inputHandler);
141 // --- Monte-Carlo ------------------------------------------------
142 AliVEventHandler* mcHandler = CreateMCHandler(type,mc);
143 if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
145 // --- AOD output handler -----------------------------------------
146 AliVEventHandler* outputHandler = CreateOutputHandler(type);
147 if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
149 // --- Include analysis macro path in search path ----------------
150 gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
151 cwd.Data(), gROOT->GetMacroPath()));
153 // --- Physics selction - only for ESD ---------------------------
154 if (type == Helper::kESD) CreatePhysicsSelection(mc, mgr);
156 // --- Create centrality task ------------------------------------
157 CreateCentralitySelection(mc, mgr);
159 // --- Create tasks ----------------------------------------------
162 // --- Post set-up initialization of helper ----------------------
163 if (!fHelper->PostSetup()) return false;
165 // --- Set debug level on defined tasks --------------------------
167 TIter next(mgr->GetTasks());
168 AliAnalysisTask* sub = 0;
169 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
170 AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
172 se->SetDebugLevel(verbose);
176 // --- Print this setup ------------------------------------------
179 // --- Initialise the train --------------------------------------
180 if (!mgr->InitAnalysis()) {
181 gSystem->ChangeDirectory(cwd.Data());
182 Error("Init","Failed to initialise train");
186 // --- Enable progress bar ---------------------------------------
187 if (fHelper->Mode() != Helper::kGrid)
188 mgr->SetUseProgressBar(true, 100);
190 // --- Save setup to disk ----------------------------------------
198 Bool_t Run(Bool_t doExit=false)
200 TString cwd = gSystem->WorkingDirectory();
201 Bool_t status = false;
203 if (!Init()) throw TString("Failed to intialize the train");
205 // if (r) SaveSetup(*r, nEvents, asShell);
207 Long64_t nEvents = fOptions.AsLong("events", -1);
208 Long64_t ret = fHelper->Run(nEvents);
210 // Make sure we go back
211 gSystem->ChangeDirectory(cwd.Data());
214 if (ret < 0) throw TString("Analysis failed");
222 if (gApplication && doExit) {
224 gApplication->Terminate(status ? 0 : 1);
232 * @return Reference ot the options
234 OptionList& Options() { return fOptions; }
236 * Print information to standard output
239 void Print(Option_t* ="") const
241 std::cout << "Train: " << fName << " (" << fEscapedName << ")"
243 fOptions.Show(std::cout);
244 if (fHelper) fHelper->Print();
253 Bool_t Help(std::ostream& o=std::cout, bool asProg=false)
255 if (!fOptions.Has("help")) return true;
258 o << "Usage: runTrain --name=NAME --class=CLASS [OPTIONS]";
260 o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
262 o << "\n\nOptions:\n\n";
264 OptionList tmp(fOptions);
265 tmp.Add("name", "STRING", "Name of train", fName);
266 tmp.Add("class", "NAME", "Name of setup class", "");
270 fOptions.Help(o, " ");
274 if (!fHelper && fOptions.Has("url")) {
275 TString url = fOptions.Get("url");
276 fHelper = Helper::Create(url.Data());
279 o << fHelper->Desc() << " URL form:\n\n"
280 << " " << fHelper->UrlHelp() << "\n\n"
282 fHelper->Options().Help(o, " ");
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");
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.
302 * @param name Train name
303 * @param cls Class name
304 * @param opts Comma seperated list of options
306 * @return true on success
308 static Bool_t Main(const TString& name, const TString& cls,
309 const TCollection* opts,
313 Error("Main", "No class name specified");
317 Error("Main", "No train name specified");
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);
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);");
334 Error("Main", "Failed to make object of class %s: 0x%08lx/%d\n\t%s",
335 cls.Data(), ret, error, create.Data());
338 TrainSetup* train = reinterpret_cast<TrainSetup*>(ret);
340 // Now parse the options
341 if (!train->Options().Parse(opts)) {
342 Error("Main", "Failed to parse options");
346 // Check if we got a help request
347 if (train->Options().Has("help")) {
348 train->Help(std::cout, asProg);
351 // return train->Init();
352 return train->Run(asProg);
355 //__________________________________________________________________
358 * @Name Overloadable behaviour
360 //------------------------------------------------------------------
362 * Create the analysis manager
364 * @param name Name of the analysis
366 * @return Created analysis manager
368 virtual AliAnalysisManager* CreateAnalysisManager(const char* name)
370 return new AliAnalysisManager(name,"Analysis Train");
372 //------------------------------------------------------------------
374 * Create input handler
380 virtual AliVEventHandler* CreateInputHandler(UShort_t type)
383 case Helper::kESD: return new AliESDInputHandler();
384 case Helper::kAOD: return new AliAODInputHandler();
385 case Helper::kUser: return 0;
389 //------------------------------------------------------------------
391 * Create MC input handler
393 * @param type Run type (ESD or AOD)
394 * @param mc Assume monte-carlo input
398 virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc)
401 AliMCEventHandler* mcHandler = new AliMCEventHandler();
402 mcHandler->SetReadTR(true);
405 //------------------------------------------------------------------
407 * Create output event handler
413 virtual AliVEventHandler* CreateOutputHandler(UShort_t type)
415 AliAODHandler* ret = new AliAODHandler();
418 ret->SetOutputFileName("AliAOD.root");
421 ret->SetOutputFileName("AliAOD.pass2.root");
429 //------------------------------------------------------------------
431 * Create physics selection, and add to manager
433 * @param mc Whether this is for MC
436 virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
438 if (fOptions.Has("bare-ps")) {
439 AliInputEventHandler* input =
440 dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler());
443 AliPhysicsSelection* ps = new AliPhysicsSelection();
444 if (mc) ps->SetAnalyzeMC();
446 input->SetEventSelection(ps);
450 gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
451 mgr->RegisterExtraFile("event_stat.root");
453 //------------------------------------------------------------------
455 * Create centrality selection, and add to manager
457 * @param mc Whether this is for MC
460 virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
462 gROOT->Macro("AddTaskCentrality.C");
463 const char* name = "CentralitySelection";
464 AliCentralitySelectionTask* ctask =
465 dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
467 if (mc) ctask->SetMCInput();
469 //------------------------------------------------------------------
471 * Create analysis tasks. Must be overloaded by sub-class
475 virtual void CreateTasks(AliAnalysisManager* mgr)=0;
476 virtual const Char_t* ClassName() const = 0;
478 //__________________________________________________________________
481 * @name Utility functions
484 * Escape bad elements of the name
486 * @param name Name to escape
487 * @param datime Date and Time
489 * @return escaped name
491 static TString EscapeName(const char* name, const TString& datimeStr)
493 TString escaped = name;
494 char c[] = { ' ', '/', '@', 0 };
497 escaped.ReplaceAll(Form("%c", *p), "_");
500 if (!datimeStr.IsNull()) {
502 if (datimeStr.EqualTo("now", TString::kIgnoreCase))
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",
514 datime.GetMinute()));
519 * Make our working directory if so requested
521 * @return true on success
523 Bool_t SetupWorkingDirectory()
525 // Get the name of the target directory
526 TString& nam = fEscapedName;
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",
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",
544 // Make the target directory if it doesn't exists
546 if (gSystem->MakeDirectory(nam.Data())) {
547 Error("SetupWorkingDirectory", "Failed to make directory '%s'",
553 // Change directory to target directory
554 if (!gSystem->ChangeDirectory(nam.Data())) {
555 Error("SetupWorkingDirectory", "Failed to change directory to %s",
559 Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there",
564 * Save the setup as a ROOT script and possibly also a shell script
566 * @param asShellScript If true, also save as shell script
568 virtual void SaveSetup(Bool_t asShellScript)
571 SaveSetupShell("rerun", ClassName(), fName, fOptions);
572 SaveSetupROOT("ReRun", ClassName(), fName, fOptions);
575 * Save a setup as a shell script
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
582 static void SaveSetupShell(const TString& out, const TString& cls,
583 const TString& name, const OptionList& opts)
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"
591 opts.Help(o, "# --");
593 << "opts=(--class=$class \\\n"
595 opts.Store(o, " \\\n --", "", true);
597 << "echo \"Running runTrain ${opts[@]} $@\"\n"
598 << "runTrain \"${opts[@]}\" $@\n\n"
599 << "# EOF" << std::endl;
601 gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
604 * Save a setup as a ROOT script
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
611 static void SaveSetupROOT(const TString& out, const TString& cls,
612 const TString& name, const OptionList& opts)
614 OptionList tmp(opts);
616 std::ofstream o(Form("%s.C", out.Data()));
617 o << "/* Available options:\n"
621 << "Bool_t " << out << "()\n"
623 << " TString name(\"" << name << "\");\n"
624 << " TString cls(\"" << cls << "\");\n"
625 << " TString uri(\"" << opts.Get("url") << "\");\n"
627 tmp.Store(o, "\"", ",\"\n ", false);
629 << " gROOT->LoadMacro(\"RunTrain.C\");\n\n"
630 << " return RunTrain(name, cls, uri, opts);\n"
634 << "//" << std::endl;
639 TString fEscapedName;