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>
42 class AliVEventHandler;
43 class AliAnalysisManager;
44 class AliInputEventHandler;
47 //====================================================================
49 * Generic set-up of an analysis train using the grid-handler (AliEn plugin).
51 * See also @ref train_setup_doc
53 * @ingroup pwglf_forward_trains
61 * @param name Name of the train
63 TrainSetup(const TString& name)
69 fOptions.Add("help", "Show help");
70 fOptions.Add("date", "YYYY-MM-DD HH:MM", "Set date", "now");
71 fOptions.Add("mc", "Assume MC input");
72 fOptions.Add("bare-ps", "Use bare physics selection w/o task");
73 fOptions.Add("verbose", "LEVEL", "Set verbosity level", "0");
74 fOptions.Add("url", "URL", "Job location & input URL", "");
75 fOptions.Add("overwrite", "Allow overwrite");
76 fOptions.Add("events", "N", "Number of events to analyse", "-1");
77 fOptions.Add("type", "ESD|AOD|USER", "Input data stype", "");
78 fEscapedName = EscapeName(fName, "");
80 TrainSetup(const TrainSetup& o)
82 fEscapedName(o.fEscapedName),
86 TrainSetup& operator=(const TrainSetup& o)
88 if (&o == this) return *this;
90 fEscapedName = o.fEscapedName;
91 fOptions = o.fOptions;
99 virtual ~TrainSetup() {}
101 //__________________________________________________________________
109 * @return true on success
113 // --- Create the helper -----------------------------------------
114 TString url = fOptions.Get("url");
115 Int_t verbose = fOptions.AsInt("verbose");
116 Bool_t mc = fOptions.AsBool("mc");
118 fHelper = Helper::Create(url.Data(), verbose);
120 Error("Init", "Failed to make the worker for URL %s", url.Data());
124 // --- Check the type, if possible -------------------------------
125 UShort_t type = fHelper->InputType();
126 if (fOptions.Has("type")) {
127 const TString& it = fOptions.Get("type");
128 if (it.EqualTo("ESD",TString::kIgnoreCase)) type = Helper::kESD;
129 else if (it.EqualTo("AOD",TString::kIgnoreCase)) type = Helper::kAOD;
130 else if (it.EqualTo("user",TString::kIgnoreCase))
131 type = Helper::kUser;
134 // --- Rewrite the escpaed name ----------------------------------
135 if (fOptions.Has("date")) {
136 TString date = fOptions.Get("date");
137 fEscapedName = EscapeName(fName, date);
140 // --- Get current directory and set-up sub-directory ------------
141 TString cwd = gSystem->WorkingDirectory();
142 if (!SetupWorkingDirectory()) return false;
144 // --- Do initial helper setup -----------------------------------
145 if (!fHelper->PreSetup()) return false;
147 // --- Load ROOT libraries ---------------------------------------
148 if (!fHelper->LoadROOT()) return false;
150 // --- Load AliROOT libraries ------------------------------------
151 if (!fHelper->LoadAliROOT()) return false;
153 // --- Create analysis manager -----------------------------------
154 AliAnalysisManager *mgr = CreateAnalysisManager(fName);
156 // In test mode, collect system information on every event
157 // if (oper == kTest) mgr->SetNSysInfo(1);
158 if (verbose > 0) mgr->SetDebugLevel(verbose);
159 if (fHelper->Mode() == Helper::kLocal)
160 mgr->SetUseProgressBar(kTRUE, 100);
162 // --- ESD input handler ------------------------------------------
163 AliVEventHandler* inputHandler = CreateInputHandler(type);
164 if (inputHandler) mgr->SetInputEventHandler(inputHandler);
166 // --- Monte-Carlo ------------------------------------------------
167 AliVEventHandler* mcHandler = CreateMCHandler(type,mc);
168 if (mcHandler) mgr->SetMCtruthEventHandler(mcHandler);
170 // --- AOD output handler -----------------------------------------
171 AliVEventHandler* outputHandler = CreateOutputHandler(type);
172 if (outputHandler) mgr->SetOutputEventHandler(outputHandler);
174 // --- Include analysis macro path in search path ----------------
175 gROOT->SetMacroPath(Form("%s:%s:$ALICE_ROOT/ANALYSIS/macros",
176 cwd.Data(), gROOT->GetMacroPath()));
178 // --- Physics selction - only for ESD ---------------------------
179 if (type == Helper::kESD) CreatePhysicsSelection(mc, mgr);
181 // --- Create centrality task ------------------------------------
182 CreateCentralitySelection(mc, mgr);
184 // --- Create tasks ----------------------------------------------
187 // --- Post set-up initialization of helper ----------------------
188 if (!fHelper->PostSetup()) return false;
190 // --- Set debug level on defined tasks --------------------------
192 TIter next(mgr->GetTasks());
193 AliAnalysisTask* sub = 0;
194 while ((sub = static_cast<AliAnalysisTask*>(next()))) {
195 AliAnalysisTaskSE* se = dynamic_cast<AliAnalysisTaskSE*>(sub);
197 se->SetDebugLevel(verbose);
201 // --- Print this setup ------------------------------------------
204 // --- Initialise the train --------------------------------------
205 if (!mgr->InitAnalysis()) {
206 gSystem->ChangeDirectory(cwd.Data());
207 Error("Init","Failed to initialise train");
211 // --- Enable progress bar ---------------------------------------
212 if (fHelper->Mode() != Helper::kGrid)
213 mgr->SetUseProgressBar(true, 100);
215 // --- Save setup to disk ----------------------------------------
223 Bool_t Run(Bool_t doExit=false)
225 TString cwd = gSystem->WorkingDirectory();
226 Bool_t status = false;
228 if (!Init()) throw TString("Failed to intialize the train");
230 // if (r) SaveSetup(*r, nEvents, asShell);
232 Long64_t nEvents = fOptions.AsLong("events", -1);
233 Long64_t ret = fHelper->Run(nEvents);
235 // Make sure we go back
236 gSystem->ChangeDirectory(cwd.Data());
239 if (ret < 0) throw TString("Analysis failed");
247 if (gApplication && doExit) {
249 gApplication->Terminate(status ? 0 : 1);
257 * @return Reference ot the options
259 OptionList& Options() { return fOptions; }
261 * Print information to standard output
264 void Print(Option_t* ="") const
266 std::cout << "Train: " << fName << " (" << fEscapedName << ")"
268 fOptions.Show(std::cout);
269 if (fHelper) fHelper->Print();
278 Bool_t Help(std::ostream& o=std::cout, bool asProg=false)
280 if (!fOptions.Has("help")) return true;
283 o << "Usage: runTrain --name=NAME --class=CLASS [OPTIONS]";
285 o << "Usage: RunTrain(NAME, CLASS, OPTIONS)";
287 o << "\n\nOptions:\n\n";
289 OptionList tmp(fOptions);
290 tmp.Add("name", "STRING", "Name of train", fName);
291 tmp.Add("class", "NAME", "Name of setup class", "");
295 fOptions.Help(o, " ");
299 if (!fHelper && fOptions.Has("url")) {
300 TString url = fOptions.Get("url");
301 fHelper = Helper::Create(url.Data());
304 o << fHelper->Desc() << " URL form:\n\n"
305 << " " << fHelper->UrlHelp() << "\n\n"
307 fHelper->Options().Help(o, " ");
311 o << "Possible URL forms:\n\n";
312 Helper::ShowUrlHelp("LocalHelper");
313 Helper::ShowUrlHelp("ProofHelper");
314 Helper::ShowUrlHelp("LiteHelper");
315 Helper::ShowUrlHelp("AAFHelper");
316 Helper::ShowUrlHelp("AAFPluginHelper");
317 Helper::ShowUrlHelp("GridHelper");
323 * Run train. This will AcLic compile the setup script, create
324 * an object of that type with the given name, and then pass the
325 * options to it. Then, it will run the setup.
327 * @param name Train name
328 * @param cls Class name
329 * @param opts Comma seperated list of options
331 * @return true on success
333 static Bool_t Main(const TString& name, const TString& cls,
334 const TCollection* opts,
338 Error("Main", "No class name specified");
342 Error("Main", "No train name specified");
346 Int_t r1 = gROOT->LoadMacro(Form("%s.C++g", cls.Data()), &error);
347 if (r1 < 0 || error) {
348 Error("Main", "Failed to load setup %s: %d", cls.Data(), error);
352 // Make our object using the interpreter
353 TString create = TString::Format("new %s(\"%s\")",
354 cls.Data(), name.Data());
355 gROOT->ProcessLine("gSystem->RedirectOutput(\"/dev/null\",\"w\");");
356 Long_t ret = gROOT->ProcessLine(create, &error);
357 gROOT->ProcessLine("gSystem->RedirectOutput(0);");
359 Error("Main", "Failed to make object of class %s: 0x%08lx/%d\n\t%s",
360 cls.Data(), ret, error, create.Data());
363 TrainSetup* train = reinterpret_cast<TrainSetup*>(ret);
365 // Now parse the options
366 if (!train->Options().Parse(opts)) {
367 Error("Main", "Failed to parse options");
371 // Check if we got a help request
372 if (train->Options().Has("help")) {
373 train->Help(std::cout, asProg);
376 // return train->Init();
377 return train->Run(asProg);
380 //__________________________________________________________________
383 * @Name Overloadable behaviour
385 //------------------------------------------------------------------
387 * Create the analysis manager
389 * @param name Name of the analysis
391 * @return Created analysis manager
393 virtual AliAnalysisManager* CreateAnalysisManager(const char* name)
395 return new AliAnalysisManager(name,"Analysis Train");
397 //------------------------------------------------------------------
399 * Create input handler
405 virtual AliVEventHandler* CreateInputHandler(UShort_t type)
408 case Helper::kESD: return new AliESDInputHandler();
409 case Helper::kAOD: return new AliAODInputHandler();
410 case Helper::kUser: return 0;
414 //------------------------------------------------------------------
416 * Create MC input handler
418 * @param type Run type (ESD or AOD)
419 * @param mc Assume monte-carlo input
423 virtual AliVEventHandler* CreateMCHandler(UShort_t /*type*/, bool mc)
426 AliMCEventHandler* mcHandler = new AliMCEventHandler();
427 mcHandler->SetReadTR(true);
430 //------------------------------------------------------------------
432 * Create output event handler
438 virtual AliVEventHandler* CreateOutputHandler(UShort_t type)
440 AliAODHandler* ret = new AliAODHandler();
443 ret->SetOutputFileName("AliAOD.root");
446 ret->SetOutputFileName("AliAOD.pass2.root");
454 //------------------------------------------------------------------
456 * Create physics selection, and add to manager
458 * @param mc Whether this is for MC
461 virtual void CreatePhysicsSelection(Bool_t mc, AliAnalysisManager* mgr)
463 if (fOptions.Has("bare-ps")) {
464 AliInputEventHandler* input =
465 dynamic_cast<AliInputEventHandler*> (mgr->GetInputEventHandler());
468 AliPhysicsSelection* ps = new AliPhysicsSelection();
469 if (mc) ps->SetAnalyzeMC();
471 input->SetEventSelection(ps);
475 gROOT->Macro(Form("AddTaskPhysicsSelection.C(%d)", mc));
476 mgr->RegisterExtraFile("event_stat.root");
478 //------------------------------------------------------------------
480 * Create centrality selection, and add to manager
482 * @param mc Whether this is for MC
485 virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
487 gROOT->Macro("AddTaskCentrality.C");
488 const char* name = "CentralitySelection";
489 AliCentralitySelectionTask* ctask =
490 dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask(name));
492 if (mc) ctask->SetMCInput();
494 //------------------------------------------------------------------
496 * Create analysis tasks. Must be overloaded by sub-class
500 virtual void CreateTasks(AliAnalysisManager* mgr)=0;
501 virtual const Char_t* ClassName() const = 0;
503 //__________________________________________________________________
506 * @name Utility functions
509 * Escape bad elements of the name
511 * @param name Name to escape
512 * @param datime Date and Time
514 * @return escaped name
516 static TString EscapeName(const char* name, const TString& datimeStr)
518 TString escaped = name;
519 char c[] = { ' ', '/', '@', 0 };
522 char tmp[] = { *p, '\0' };
523 escaped.ReplaceAll(tmp, "_");
526 if (!datimeStr.IsNull()) {
528 if (datimeStr.EqualTo("now", TString::kIgnoreCase))
531 // Try various formats
533 const char* formats[] = { "%Ec", // Locale
537 "%F %R", // ISO standard, no seconds
539 const char** f = formats;
540 Bool_t found = false;
541 while (*f && !found) {
542 // Reset needed fields
548 // Stop processing on first match
549 if (strptime(datimeStr.Data(), *f, &t) != 0) found = true;
553 datime.Set(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, 0);
555 if (datime.GetYear() <= 1995 ||
556 datime.GetMonth() == 0 ||
557 datime.GetDay() == 0) return escaped;
558 escaped.Append(Form("_%04d%02d%02d_%02d%02d",
563 datime.GetMinute()));
568 * Make our working directory if so requested
570 * @return true on success
572 Bool_t SetupWorkingDirectory()
574 // Get the name of the target directory
575 TString& nam = fEscapedName;
577 // Check if the directory exists already
578 Bool_t exists = gSystem->AccessPathName(nam.Data()) == 0;
579 if (fHelper->Operation() == Helper::kTerminate && !exists) {
580 Error("SetupWorkingDirectory", "File/directory %s does not exists",
585 Bool_t overwrite = fOptions.Has("overwrite");
586 // If we're not allowed to overwrite, then complain
587 if (!overwrite && exists) {
588 Error("SetupWorkingDirectory", "File/directory %s already exists",
593 // Make the target directory if it doesn't exists
595 if (gSystem->MakeDirectory(nam.Data())) {
596 Error("SetupWorkingDirectory", "Failed to make directory '%s'",
602 // Change directory to target directory
603 if (!gSystem->ChangeDirectory(nam.Data())) {
604 Error("SetupWorkingDirectory", "Failed to change directory to %s",
608 Info("SetupWorkingDirectory", "Made subdirectory %s, and cd'ed there",
613 * Save the setup as a ROOT script and possibly also a shell script
615 * @param asShellScript If true, also save as shell script
617 virtual void SaveSetup(Bool_t asShellScript)
619 OptionList tmp(fOptions);
620 if (tmp.Find("overwrite")) tmp.Set("overwrite");
622 SaveSetupShell("rerun", ClassName(), fName, tmp);
623 SaveSetupROOT("ReRun", ClassName(), fName, tmp);
626 * Save a setup as a shell script
628 * @param out Output name of shell script
629 * @param cls Class of the train
630 * @param name Name of the train
631 * @param opts Option list
633 static void SaveSetupShell(const TString& out, const TString& cls,
634 const TString& name, const OptionList& opts)
636 std::ofstream o(Form("%s.sh", out.Data()));
637 o << "#!/bin/bash\n\n"
638 << "class=\"" << cls << "\"\n"
639 << "name=\"" << name << "\"\n\n"
640 << "# Available options\n"
642 opts.Help(o, "# --");
644 << "opts=(--class=$class \\\n"
646 opts.Store(o, " \\\n --", "", true);
648 << "echo \"Running runTrain ${opts[@]} $@\"\n"
649 << "runTrain \"${opts[@]}\" $@\n\n"
650 << "# EOF" << std::endl;
652 gSystem->Exec(Form("chmod a+x %s.sh", out.Data()));
655 * Save a setup as a ROOT script
657 * @param out Output name of shell script
658 * @param cls Class of the train
659 * @param name Name of the train
660 * @param opts Option list
662 static void SaveSetupROOT(const TString& out, const TString& cls,
663 const TString& name, const OptionList& opts)
665 OptionList tmp(opts);
667 std::ofstream o(Form("%s.C", out.Data()));
668 o << "/* Available options:\n"
672 << "Bool_t " << out << "()\n"
674 << " TString name(\"" << name << "\");\n"
675 << " TString cls(\"" << cls << "\");\n"
676 << " TString uri(\"" << opts.Get("url") << "\");\n"
678 tmp.Store(o, "\"", ",\"\n ", false);
681 TString path(gROOT->GetMacroPath());
682 TObjArray* elements = path.Tokenize(":");
683 TObjString* element = 0;
684 TIter next(elements);
685 while ((element = static_cast<TObjString*>(next()))) {
686 if (element->String().IsNull()) continue;
687 o << "\n \"" << element->GetName() << ":\"";
691 << " path.Append(\"$ALICE_ROOT/PWGLF/FORWARD/trains\");\n"
692 << " gROOT->SetMacroPath(path);\n\n"
693 << " gROOT->LoadMacro(\"RunTrain.C\");\n\n"
694 << " return RunTrain(name, cls, uri, opts);\n"
698 << "//" << std::endl;
703 TString fEscapedName;