]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisTaskCfg.cxx
Fix for calculation of V0 vertex (Rossella)
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisTaskCfg.cxx
CommitLineData
4579e070 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16#include "AliAnalysisTaskCfg.h"
15f0154e 17#include "AliAnalysisManager.h"
4579e070 18
19#include "Riostream.h"
20#include "TError.h"
21#include "TMacro.h"
5f254645 22#include "TInterpreter.h"
4579e070 23#include "TSystem.h"
24#include "TObjArray.h"
15f0154e 25#include "TObjString.h"
26#include "TList.h"
4579e070 27
28// Author: Andrei Gheata, 12/08/2011
29
30//==============================================================================
31// AliAnalysysTaskCfg - Class embedding the configuration needed to run
32// a given analysis task: libraries to be loaded, location and name of the macro
33// used to add the task to the analysis manager, dependencies.
34//==============================================================================
35
36// This class is used to fully describe how to run a given analysis task. It
37// requires that the user creates an AddTask macro for his task and defines:
38// - The needed libs separated by commas,
39// - The full path to the AddTask macro (starting with $ALICE_ROOT if needed)
40// - The list of arguments to be provided to the AddTask macro. One can use
41// here only constants that can be interpreted.
42// - The list of dependencies (other modules required to run this task). These
43// must be names of other AliAnalysisTaskCfg objects, separated by commas.
44// - Data types supported by the task (e.g. ESD, AOD, MC)
45// The class has normal ROOT IO, but it can also read from and write to text files.
46// An example:
47// Content of file: QAsym.cfg
48/*
49# Lines that do not start with #Module are ignored, except those in embedded
50 macro blocks
51#Module.Begin QAsym
52#Module.Libs PWG1
53#Module.Deps PhysicsSelection
54#Module.DataTypes ESD, AOD, MC
55#Module.MacroName $ALICE_ROOT/PWG1/PilotTrain/AddTaskQAsym.C
56#Module.MacroArgs 0, AliVEvent::kAnyINT, AliVEvent::kHighMult, AliVEvent::kEMC7, AliVEvent::kMUU7
57#Module.StartConfig
58__R_ADDTASK__->SelectCollisionCandidates();
59#Module.EndConfig
60*/
61// The following special variable names can be used:
62// __R_ADDTASK__ = the return value of the AddTask macro included
63// __R_ESDH__ = pointer to ESD handler
64// __R_AODH__ = pointer to AOD handler
65// __R_MCH__ = pointer to MC handler
66// The static method ExtractModulesFrom(const char *filename) allows reading
67// several task configuration modules from the same text file and returning
68// them in a TObjArray.
69//
70// A list of configuration modules representing a train should be injected in
71// the right order in the grid handler to generate train macros.
72
73
74ClassImp(AliAnalysisTaskCfg)
75
76//______________________________________________________________________________
77AliAnalysisTaskCfg::AliAnalysisTaskCfg()
78 :TNamed(),
79 fMacroName(),
80 fMacroArgs(),
81 fLibs(),
82 fDeps(),
83 fDataTypes(),
84 fMacro(0),
15f0154e 85 fConfigDeps(0),
86 fRAddTask(0)
4579e070 87{
88// I/O constructor.
89}
90
91//______________________________________________________________________________
92AliAnalysisTaskCfg::AliAnalysisTaskCfg(const char *name)
93 :TNamed(name,""),
94 fMacroName(),
95 fMacroArgs(),
96 fLibs(),
97 fDeps(),
98 fDataTypes(),
99 fMacro(0),
15f0154e 100 fConfigDeps(0),
101 fRAddTask(0)
4579e070 102{
103// Constructor. All configuration objects need to be named since they are looked
104// for by name.
105}
106
107//______________________________________________________________________________
108AliAnalysisTaskCfg::AliAnalysisTaskCfg(const AliAnalysisTaskCfg &other)
109 :TNamed(other),
110 fMacroName(other.fMacroName),
111 fMacroArgs(other.fMacroArgs),
112 fLibs(other.fLibs),
113 fDeps(other.fDeps),
114 fDataTypes(other.fDataTypes),
115 fMacro(0),
15f0154e 116 fConfigDeps(0),
117 fRAddTask(0)
4579e070 118{
119// Copy constructor.
120 if (other.fMacro) fMacro = new TMacro(*other.fMacro);
121 if (other.fConfigDeps) fConfigDeps = new TMacro(*other.fConfigDeps);
122}
123
124//______________________________________________________________________________
125AliAnalysisTaskCfg::~AliAnalysisTaskCfg()
126{
127// Destructor.
128 delete fMacro;
129 delete fConfigDeps;
130}
131
132//______________________________________________________________________________
133AliAnalysisTaskCfg& AliAnalysisTaskCfg::operator=(const AliAnalysisTaskCfg &other)
134{
135// Assignment operator.
136 if (&other == this) return *this;
137 TNamed::operator=(other);
138 fMacroName = other.fMacroName;
139 fMacroArgs = other.fMacroArgs;
140 fLibs = other.fLibs;
141 fDeps = other.fDeps;
142 fDataTypes = other.fDataTypes;
143 if (other.fMacro) fMacro = new TMacro(*other.fMacro);
144 if (other.fConfigDeps) fConfigDeps = new TMacro(*other.fConfigDeps);
15f0154e 145 fRAddTask = other.fRAddTask;
4579e070 146 return *this;
147}
148
149//______________________________________________________________________________
150TMacro *AliAnalysisTaskCfg::OpenMacro(const char *name)
151{
152// Opens the specified macro if name is not empty. In case of success updates
153// fMacroName, creates the maco object and returns its pointer.
154 // Clean-up previous macro if any
155 if (fMacro) {
156 delete fMacro;
157 fMacro = 0;
158 }
159 TString expname;
160 if (strlen(name)) expname = gSystem->ExpandPathName(name);
3e40fd4c 161 else expname = gSystem->ExpandPathName(fMacroName.Data());
4579e070 162 if (expname.IsNull()) {
163 Error("OpenMacro", "Macro name not provided and not previously set");
164 return 0;
165 }
166 if (gSystem->AccessPathName(expname)) {
167 Error("OpenMacro", "Macro: %s cannot be opened.", expname.Data());
168 return 0;
169 }
170 if (strlen(name)) fMacroName = name;
171 fMacro = new TMacro(expname);
172 return fMacro;
173}
174
175//______________________________________________________________________________
176void AliAnalysisTaskCfg::SetMacro(TMacro *macro)
177{
178// Set the AddTask macro from outside. This will discard the existing macro if
179// any. The provided macro will be owned by this object.
180 if (fMacro) delete fMacro;
181 fMacro = macro;
182}
183
184//______________________________________________________________________________
185Long64_t AliAnalysisTaskCfg::ExecuteMacro(const char *newargs)
186{
187// Execute AddTask macro. Opens first the macro pointed by fMacroName if not yet
188// done. Checks if the requested libraries are loaded, else loads them. Executes
77f34eae 189// with stored fMacroArgs unless new arguments are provided. The flag IsLoaded
190// is set once the macro was successfully executed.
21ca8e59 191 if (IsLoaded()) return kTRUE;
4579e070 192 if (!fMacro && !OpenMacro()) {
193 Error("ExecuteMacro", "Cannot execute this macro");
194 return -1;
195 }
196 if (!CheckLoadLibraries()) {
197 Error("ExecuteMacro", "Cannot load requested libraries: %s", fLibs.Data());
198 return -1;
199 }
200
15f0154e 201 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
202 if (!mgr) {
203 Error("ExecuteMacro", "Analysis manager not defined yet");
204 return -1;
205 }
206 Int_t ntasks0 = mgr->GetTasks()->GetEntriesFast();
4579e070 207 TString args = newargs;
208 if (args.IsNull()) args = fMacroArgs;
5f254645 209 Int_t error = 0;
210 Long64_t retval = fMacro->Exec(args, &error);
211 if (error != TInterpreter::kNoError)
212 {
213 Error("ExecuteMacro", "Macro interpretation failed");
214 return -1;
215 }
5e8c7c22 216 Int_t ntasks = mgr->GetTasks()->GetEntriesFast();
5f254645 217 if (ntasks<=ntasks0)
218 {
219 Error("ExecuteMacro", "The macro did not add any tasks to the manager");
220 return -1;
221 }
222 Long64_t ptrTask = (Long64_t)mgr->GetTasks()->At(ntasks0);
5e8c7c22 223 if (retval >= ptrTask) {
15f0154e 224 TObject::SetBit(AliAnalysisTaskCfg::kLoaded, kTRUE);
225 fRAddTask = reinterpret_cast<TObject*>(retval);
5e8c7c22 226 if (fConfigDeps && dynamic_cast<TObject*>(fRAddTask)) {
15f0154e 227 TString classname = fRAddTask->ClassName();
228 classname += Form("* __R_ADDTASK__ = (%s*)0x%lx;", classname.Data(),(ULong_t)retval);
229 classname.Prepend(" ");
230 TObjString *line = fConfigDeps->GetLineWith("__R_ADDTASK__");
231 if (line) {
232 TList *lines = fConfigDeps->GetListOfLines();
233 lines->AddBefore(line, new TObjString(classname));
234 }
235 }
236 }
15f0154e 237 Info("ExecuteMacro", "Macro %s added %d tasks to the manager", fMacro->GetName(), ntasks-ntasks0);
77f34eae 238 return retval;
4579e070 239}
240
241//______________________________________________________________________________
242Int_t AliAnalysisTaskCfg::GetNlibs() const
243{
244// Returns number of requested libraries.
245 if (fLibs.IsNull()) return 0;
246 Int_t nlibs = fLibs.CountChar(',')+1;
247 return nlibs;
248}
249
250//______________________________________________________________________________
251const char *AliAnalysisTaskCfg::GetLibrary(Int_t i) const
252{
253// Returns library name for the i-th library.
254 Int_t nlibs = GetNlibs();
255 if (i>=nlibs) return 0;
ca1b69aa 256 static TString libname;
4579e070 257 TObjArray *list = fLibs.Tokenize(",");
258 libname = list->At(i)->GetName();
259 libname.ReplaceAll(".so","");
260 libname.ReplaceAll(" ","");
261 if (libname.BeginsWith("lib")) libname.Remove(0, 3);
262 delete list;
263 return libname.Data();
264}
265
266//______________________________________________________________________________
267Bool_t AliAnalysisTaskCfg::CheckLoadLibraries() const
268{
269// Check if all requested libraries were loaded, otherwise load them. If some
270// library cannot be loaded return false.
271 TString library;
272 Int_t nlibs = GetNlibs();
273 for (Int_t i=0; i<nlibs; i++) {
274 library = GetLibrary(i);
275 library.Prepend("lib");
276 Int_t loaded = strlen(gSystem->GetLibraries(library,"",kFALSE));
277 if (!loaded) loaded = gSystem->Load(library);
278 if (loaded < 0) {
279 Error("CheckLoadLibraries", "Cannot load library %s", library.Data());
280 return kFALSE;
281 }
282 }
283 return kTRUE;
284}
285
286//______________________________________________________________________________
287Bool_t AliAnalysisTaskCfg::NeedsLibrary(const char *lib) const
288{
289// Check if a given library is needed by the module.
290 TString libname = lib;
291 libname.ReplaceAll(".so","");
292 if (libname.BeginsWith("lib")) libname.Remove(0, 3);
293 return fLibs.Contains(libname);
294}
295
296//______________________________________________________________________________
297Int_t AliAnalysisTaskCfg::GetNdeps() const
298{
299// Returns number of requested libraries.
300 if (fDeps.IsNull()) return 0;
301 Int_t ndeps = fDeps.CountChar(',')+1;
302 return ndeps;
303}
304
305//______________________________________________________________________________
306const char *AliAnalysisTaskCfg::GetDependency(Int_t i) const
307{
308// Returns library name for the i-th library.
309 Int_t ndeps = GetNdeps();
310 if (i>=ndeps) return 0;
ca1b69aa 311 static TString depname;
4579e070 312 TObjArray *list = fDeps.Tokenize(",");
313 depname = list->At(i)->GetName();
314 depname.ReplaceAll(" ","");
315 delete list;
316 return depname.Data();
317}
318
319//______________________________________________________________________________
320Bool_t AliAnalysisTaskCfg::NeedsDependency(const char *dep) const
321{
322// Check if a given library is needed by the module.
323 return fDeps.Contains(dep);
324}
325
326//______________________________________________________________________________
327TMacro *AliAnalysisTaskCfg::OpenConfigMacro(const char *name)
328{
329// Opens the specified macro if name is not empty.
330 if (fConfigDeps) {
331 delete fConfigDeps;
332 fConfigDeps = 0;
333 }
334
335 TString expname = gSystem->ExpandPathName(name);
336 if (expname.IsNull()) {
337 Error("OpenConfigMacro", "Macro name not provided");
338 return 0;
339 }
340 if (gSystem->AccessPathName(expname)) {
341 Error("OpenMacro", "Macro: %s cannot be opened.", expname.Data());
342 return 0;
343 }
344 fConfigDeps = new TMacro(expname);
345 return fConfigDeps;
346}
347
348//______________________________________________________________________________
349void AliAnalysisTaskCfg::SetConfigMacro(TMacro *macro)
350{
351// Set the macro for configuring deps from outside. This will discard the
352// existing macro if any. The provided macro will be owned by this object.
353 if (fConfigDeps) delete fConfigDeps;
354 fConfigDeps = macro;
355}
356
357//______________________________________________________________________________
358Long64_t AliAnalysisTaskCfg::ExecuteConfigMacro()
359{
360// Execute macro to configure dependencies. No arguments are supported.
361 if (!fConfigDeps) {
362 Error("ExecuteConfigMacro", "Call OpenConfigMacro() first");
363 return -1;
364 }
365 if (!CheckLoadLibraries()) {
366 Error("ExecuteConfigMacro", "Cannot load requested libraries: %s", fLibs.Data());
367 return -1;
368 }
369 return fConfigDeps->Exec();
370}
371
372//______________________________________________________________________________
373void AliAnalysisTaskCfg::SetDataTypes(const char *types)
374{
375// Sets the data types supported by the module. Stored in upper case.
376 fDataTypes = types;
377 fDataTypes.ToUpper();
378}
379
380//______________________________________________________________________________
381Bool_t AliAnalysisTaskCfg::SupportsData(const char *type) const
382{
383// Checks if the given data type is supported.
384 TString stype = type;
385 stype.ToUpper();
386 return fDataTypes.Contains(stype);
387}
388
389//______________________________________________________________________________
390void AliAnalysisTaskCfg::Print(Option_t * option) const
391{
392// Print content of the module.
393 TString opt(option);
394 Bool_t full = (opt.Length())?kTRUE:kFALSE;
395 printf("====================================================================\n");
396 printf("# Analysis task: %s\n", GetName());
397 printf("# Supported data types: %s\n", fDataTypes.Data());
398 printf("# Extra libraries: %s\n", fLibs.Data());
399 printf("# Extra dependencies: %s\n", fDeps.Data());
400 if (fConfigDeps) {
401 printf("# Macro to configure deps: %s\n", fConfigDeps->GetTitle());
402 if (full) fConfigDeps->Print();
403 }
404 printf("# Macro connecting this task: %s\n", fMacroName.Data());
405 printf("# Arguments to run the macro: %s\n", fMacroArgs.Data());
406 if (full) {
407 if (fMacro) fMacro->Print();
408 else {
3e40fd4c 409 TMacro macro(gSystem->ExpandPathName(fMacroName.Data()));
4579e070 410 macro.Print();
411 }
412 }
413}
414
415//______________________________________________________________________________
416void AliAnalysisTaskCfg::SaveAs(const char *filename, Option_t *option) const
417{
418// Save the configuration module as text file in the form key:value. The
419// option can be APPEND, otherwise the file gets overwritten.
420 TString opt(option);
421 opt.ToUpper();
422 ios::openmode mode = ios::out;
423 if (opt == "APPEND") mode = ios::app;
424 ofstream out;
425 out.open(filename, mode);
426 if (out.bad()) {
427 Error("SaveAs", "Bad file name: %s", filename);
428 return;
429 }
430 out << "#Module.Begin " << GetName() << endl;
431 out << "#Module.Libs " << fLibs << endl;
432 out << "#Module.Deps " << fDeps << endl;
433 out << "#Module.DataTypes " << fDataTypes << endl;
434 out << "#Module.MacroName " << fMacroName << endl;
435 out << "#Module.MacroArgs " << fMacroArgs << endl;
436 if (fConfigDeps) {
437 out << "#Config.Deps " << fConfigDeps->GetTitle() << endl;
438 }
439}
440
441
442//______________________________________________________________________________
443const char *AliAnalysisTaskCfg::DecodeValue(TString &line)
444{
445// Decode the value string from the line
ca1b69aa 446 static TString value;
447 value = line(line.Index(' '),line.Length());
4579e070 448 value = value.Strip(TString::kLeading,' ');
449 value = value.Strip(TString::kTrailing,' ');
450 return value.Data();
451}
452
453//______________________________________________________________________________
454TObjArray *AliAnalysisTaskCfg::ExtractModulesFrom(const char *filename)
455{
456// Read all modules from a text file and add them to an object array. The
457// caller must delete the array at the end. Any module must start with a line
458// containing: #Module.Begin
459 TString expname = gSystem->ExpandPathName(filename);
460 if (gSystem->AccessPathName(expname)) {
461 ::Error("ExtractModulesFrom", "Cannot open file %s", filename);
462 return 0;
463 }
464 AliAnalysisTaskCfg *cfg = 0;
465 TObjArray *array = 0;
466 ifstream in;
467 in.open(expname);
468 char cline[1024];
469 TString line;
470 TString decode;
471 TMacro *addMacro = 0;
472 TMacro *addConfig = 0;
473 while (in.good()) {
474 in.getline(cline,1024);
475 line = cline;
476 if (line.BeginsWith("#Module.Begin")) {
477 // New module found, save previous if any
478 if (cfg) {
479 if (addMacro) cfg->SetMacro(addMacro);
480 if (addConfig) cfg->SetConfigMacro(addConfig);
481 if (!array) array = new TObjArray();
482 array->Add(cfg);
483 }
484 // Decode module name from the line
485 decode = AliAnalysisTaskCfg::DecodeValue(line);
486 cfg = new AliAnalysisTaskCfg(decode);
487 addMacro = 0;
488 addConfig = 0;
489 } else if (cfg && line.BeginsWith("#Module.Libs")) {
490 // Libraries section
491 decode = AliAnalysisTaskCfg::DecodeValue(line);
492 cfg->SetLibraries(decode);
493 } else if (cfg && line.BeginsWith("#Module.Deps")) {
494 // Dependencies section
495 decode = AliAnalysisTaskCfg::DecodeValue(line);
496 cfg->SetDependencies(decode);
497 } else if (cfg && line.BeginsWith("#Module.DataTypes")) {
498 // Data types
499 decode = AliAnalysisTaskCfg::DecodeValue(line);
500 cfg->SetDataTypes(decode);
501 } else if (cfg && line.BeginsWith("#Module.MacroName")) {
502 // Name of the add task macro (including path)
503 decode = AliAnalysisTaskCfg::DecodeValue(line);
504 cfg->SetMacroName(decode);
505 } else if (cfg && line.BeginsWith("#Module.MacroArgs")) {
506 // Arguments for the AddTask macro
507 decode = AliAnalysisTaskCfg::DecodeValue(line);
508 cfg->SetMacroArgs(decode);
509 } else if (cfg && line.BeginsWith("#Module.StartMacro")) {
510 // Marker for start of the AddTask macro
511 addMacro = new TMacro();
512 TString shortName = gSystem->BaseName(cfg->GetMacroName());
513 shortName = shortName(0,shortName.Index("."));
514 addMacro->SetName(shortName);
515 addMacro->SetTitle(cfg->GetMacroName());
516 } else if (cfg && line.BeginsWith("#Module.StartConfig")) {
517 // Marker for start of the configuration macro
518 addConfig = new TMacro();
519 TString shortName = gSystem->BaseName(cfg->GetMacroName());
520 shortName = shortName(0,shortName.Index("."));
521 shortName += "Config";
522 addConfig->SetName(shortName);
523 shortName.Prepend("/");
524 shortName.Prepend(gSystem->DirName(cfg->GetMacroName()));
525 shortName += ".C";
526 addConfig->SetTitle(shortName);
527 } else if (cfg && line.BeginsWith("#Module.EndMacro")) {
528 // Marker for the end of the embedded macro. EndMacro block mandatory.
529 if (cfg && addMacro) {
530 cfg->SetMacro(addMacro);
531 addMacro = 0;
532 } else {
533 ::Error("ExtractModulesFrom", "Canot end un-started macro block");
534 }
535 } else if (cfg && line.BeginsWith("#Module.EndConfig")) {
536 // Marker for the end of the config macro. EndConfig block is mandatory
537 if (cfg && addConfig) {
15f0154e 538 addConfig->GetListOfLines()->AddFirst(new TObjString(Form("%s() {",gSystem->BaseName(addConfig->GetName()))));
539 addConfig->GetListOfLines()->AddLast(new TObjString("}"));
4579e070 540 cfg->SetConfigMacro(addConfig);
541 addConfig = 0;
542 } else {
543 ::Error("ExtractModulesFrom", "Canot end un-started config macro block");
544 }
545 } else {
546 // Reading a block line
547 if (addMacro) addMacro->AddLine(line);
548 else if (addConfig) addConfig->AddLine(line);
549 }
550 }
551 // Add last found object to the list
552 if (cfg) {
15f0154e 553 if (addMacro) ::Error("ExtractModulesFrom", "#Module.EndMacro block not found");
554 if (addConfig) ::Error("ExtractModulesFrom", "#Module.EndConfig block not found");
4579e070 555 if (!array) array = new TObjArray();
556 array->Add(cfg);
557 }
558 return array;
559}