]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGHF/correlationHF/macros/run-single-task.C
modified 2 colliding tasks
[u/mrichter/AliRoot.git] / PWGHF / correlationHF / macros / run-single-task.C
CommitLineData
04a0c008 1//-*- Mode: C++ -*-
2// $Id$
3
4/// @file run-single-task.C
5/// @author Matthias.Richter@ift.uib.no
6/// @date 2012-04-06
7/// @brief Run a single task
8///
9/// Helper macro to run a single task either locally or on Grid
10/// Usage:
c98603ea 11/// aliroot -b -q -l run-single-task.C'("mode", "input", "tasks", "name", "options", events, "path", "pattern", "friendPattern", "outputDir", "user")'
04a0c008 12/// arguments
13/// mode: local, full, test
c98603ea 14/// input: In grid mode a list of run numbers.
15/// In local mode:
16/// - ESD file AliESDs.root
17/// - a list of ESD files in a text file <choose-file-name>.txt
18/// - AOD file AliAOD.root
19/// - AODs with predefined list/AODs in same folder, specifiy as "AOD"
20///
21/// tasks: list of class names/source or header files of task, or AddTask-Macro
04a0c008 22///
23/// optional arguments
24/// name: analysis name (default 'myanalysis')
c98603ea 25/// options: optional arguments passed onto the task, e.g. 'mc', 'event-mixing'
26/// options of run-single-task:
27/// 'mcData' -> the run numbers indicate MC Data, no '000' prepended
04a0c008 28/// events: number of events to be processed (default -1 -> all)
29/// path: data search path for grid analysis (default from configuration file)
30/// pattern: data search pattern (default from configuration file)
39341c1f 31/// friend pattern: friend file search pattern (default from configuration file)
32/// output dir: output directory in Grid home (default gridwork/yyyy-mm-dd_hh-mm)
33/// user: default NULL, using user of active token
04a0c008 34///
35/// Examples:
36/// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "myanalysis_LHC11a")'
37///
38/// aliroot -b -q -l run-single-task.C'("local", "$ALICE_ROOT/test/ppbench/AliESDs.root", "AliAnalysisTaskSample")'
39///
39341c1f 40/// aliroot -b -q -l run-single-task.C'("local", "AOD", "AddTaskSample.C")'
9a3d923b 41///
39341c1f 42/// aliroot -b -q -l run-single-task.C'("full", "146860", "AliAnalysisTaskSample", "correlation3p_LHC11a", 0, -1, "/alice/data/2011/LHC11a", "*/pass2_without_SDD/AOD*/*/AliAOD.root")'
04a0c008 43///
44/// Data input:
45/// depending on the format of the search pattern either the ESD or AOD input handler is used.
46///
47/// Source files:
48/// If the task and classes used by the task are not in an AliRoot library available, e.g.
49/// for the purpose of development, all header and source files need to be in the local
50/// directory. The macro searches automatically for dependencies, compiles those and
51/// copies files to the Grid working directory. In order to make the files accessible in
52/// the local directory, the files can be just linked.
53/// <pre>
54/// for f in <search path>; do ln -s $f; done
55/// </pre>
c98603ea 56/// If there are dependencies (include headers) which are not available in the working
57/// directory, the macro searches for the aliroot libraries implementing them, and adds
58/// the libraries if found to the setup.
04a0c008 59///
60/// Local analysis:
61/// requires only the path to the input file and the task class name. If the specified file is
39341c1f 62/// a text file (.txt) each line can contain an input ESD file path, all files are chained.
63/// Analysis on local AOD files needs to be setup prior to this macro. gDirectory must contain
64/// a TChain object of name 'aodTree'. This is for example created by macros like
65/// $ALICE_ROOT/PWGHF/vertexingHF/MakeAODInputChain.C
66/// Set $ALICE_ROOT/PWGHF/correlationHF/macros/setupDxHFE.C for an example.
04a0c008 67///
68/// Grid analysis:
69/// All modes provided by the AliAnalysisAlien plugin can be used, e.g. full, test, offline
70/// A couple of settings need to be defined in a configuration file 'grid-config.C' which can be
39341c1f 71/// either in the local directory or home directory. The file can look like
04a0c008 72/// <pre>
73/// const char* alienAPIVersion="V1.1x";
39341c1f 74/// const char* alienROOTVersion="v5-34-01";
75/// const char* alienAliROOTVersion="v5-03-61-AN";
04a0c008 76/// const char* defaultGridDataDir="/alice/data/2011/LHC11a";
77/// const char* defaultDataPattern="*/pass2_without_SDD/*/AliESDs.root";
39341c1f 78/// const char* defaultFriendDataPattern="";
04a0c008 79/// {} // note this empty body
80/// </pre>
81/// Data path and pattern can also be specified as command line arguments.
82/// The working directory in the grid home directory of the user is set to
39341c1f 83/// gridwork/<date>_<time> (gridwork/yyyy-mm-dd_hh-mm), can be overridden by command line
84/// parameter.
04a0c008 85///
a354ea1a 86/// Options:
87/// Options to the macro can be propagated via the parameter 'arguments', the known options
88/// are parsed and filtered out from the arguments, which are than further propagated to
89/// AdTask macros and task.
90/// --mcData switch indicates that the input data is mc data, the run numbers have
91/// a different format in real data
92/// --nTestFiles= number of test files to be used in test mode (default 10)
93/// --merge= merging mode 'local', 'grid', 'collect' (default Grid)
94///
95/// Merging of output:
96/// The output files can be merged locally by using the argument '--merge=local'. In that
97/// case all files are downloaded to the local machine and merged. The merging on grid
98/// requires to launch the analysis with argument '--merge=grid'. After the jobs are done
99/// further steps are required,
100/// 1) run in mode "terminate" with argument '--merge=grid' and working directory on grid,
101/// 2) run in mode "terminate" with argument '--merge=collect' and working directory on grid.
102/// Step 1) can be repeated multiple times, the AnalysisManager will in each stage merge
103/// several files of the previous stage, it will notify you when the final result has
104/// already been merged.
04a0c008 105///
c98603ea 106/// Suggestions:
107/// Feedback appreciated: Matthias.Richter@cern.ch
108/// If you find this macro useful but not applicable without patching it, let me know
109/// your changes and use cases.
110
04a0c008 111
f6f9bc4b 112#if defined(__CINT__) && !defined(__MAKECINT__)
04a0c008 113///////////////////////////////////////////////////////////////////////////////////////////////////
114//
115// environment
116//
9a3d923b 117int macroVerbosity=0;
118const char* defaultAnalysisName="myanalysis";
04a0c008 119const char* includePath="-I. -I$ROOTSYS/include -I$ALICE_ROOT/include";
120const char* libraryDependencies=
9a3d923b 121 "libSTEERBase.so "
122 "libESD.so "
123 "libAOD.so "
124 "libANALYSIS.so "
125 "libANALYSISalice.so "
04a0c008 126 ;
127
128TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass=true);
a354ea1a 129TObject* BuildCodeTree(const char* filename, TObject* pTree);
f6f9bc4b 130int ProcessCodeTree(TObject* tree, TString& sources, TString& headers, TString& libs);
04a0c008 131void ErrorConfigurationFile(const char* fileName);
132
133void run_single_task(const char* mode,
134 const char* input,
685fea75 135 const char* tasknames,
9a3d923b 136 const char* analysisName=defaultAnalysisName,
c98603ea 137 const char* arguments="",
04a0c008 138 int nevents=-1,
139 const char* gridDataDir=NULL,
140 const char* dataPattern=NULL,
9a3d923b 141 const char* friendDataPattern=NULL,
142 TString odir="",
04a0c008 143 const char* user=NULL
144 )
145{
146 ///////////////////////////////////////////////////////////////////////////////////////////////////
147 ///////////////////////////////////////////////////////////////////////////////////////////////////
148 ///////////////////////////////////////////////////////////////////////////////////////////////////
149 //
150 // defaults
151 //
9a3d923b 152 if (analysisName==defaultAnalysisName && gDirectory!=NULL) {
153 // NOTE: the direct pointer comparison is on purpose
154 // string comparison not necessary in this special case
155
156 // fetch the analysis name from the setup file
157 const char* confObjectName="analysis_name";
158 TObject* confObject=gDirectory->FindObject(confObjectName);
159 if (confObject) {
160 analysisName=confObject->GetTitle();
161 }
162 }
163
04a0c008 164 bool bRunLocal=strcmp(mode, "local")==0;
165 const char* gridConfigFile="grid-config.C";
166 TString strGridConfigFile=gridConfigFile;
167 if (gSystem->AccessPathName(strGridConfigFile)!=0) {
168 strGridConfigFile.Prepend("/");
169 strGridConfigFile.Prepend(gSystem->Getenv("HOME"));
170 if (gSystem->AccessPathName(strGridConfigFile)!=0) {
171 if (!bRunLocal) {
172 ErrorConfigurationFile(gridConfigFile);
173 return;
174 }
175 strGridConfigFile="";
176 }
177 }
178
179 if (strGridConfigFile.IsNull()==0 && !bRunLocal) {
180 cout << "loading grid configuration from file '" << strGridConfigFile << "':" << endl;
181 gROOT->LoadMacro(strGridConfigFile);
9a3d923b 182 cout << " alienAPIVersion =" << alienAPIVersion << endl;
183 cout << " alienROOTVersion =" << alienROOTVersion << endl;
184 cout << " alienAliROOTVersion =" << alienAliROOTVersion << endl;
185 cout << " defaultGridDataDir =" << defaultGridDataDir << endl;
186 cout << " defaultDataPattern =" << defaultDataPattern << endl;
187 cout << " defaultFriendDataPattern =" << defaultFriendDataPattern << endl;
04a0c008 188
189 if (gridDataDir==NULL) gridDataDir=defaultGridDataDir;
190 if (dataPattern==NULL) dataPattern=defaultDataPattern;
9a3d923b 191 if (friendDataPattern==NULL) friendDataPattern=defaultFriendDataPattern;
04a0c008 192 } else if (bRunLocal) {
193 if (dataPattern==NULL) {
c98603ea 194 // thats a very crude logic, I guess it can fail in some special cases
9a3d923b 195 TString strin=input;
c98603ea 196 if (strin.Contains("AOD"))
9a3d923b 197 dataPattern="AOD";
c98603ea 198 else if (strin.Contains("ESD"))
9a3d923b 199 dataPattern="ESD";
04a0c008 200 }
201 }
202
9a3d923b 203 if(!bRunLocal) {
204 // Connect to AliEn
205 TGrid::Connect("alien://");
206 }
c98603ea 207 ///////////////////////////////////////////////////////////////////////////////////////////////////
208 ///////////////////////////////////////////////////////////////////////////////////////////////////
209 ///////////////////////////////////////////////////////////////////////////////////////////////////
210 //
211 // argument settings
212 //
7162a4fd 213 bool bRunAnalysis=true;
214 bool bDefaultOutput=true;
a354ea1a 215 bool bMergeOnGrid=true;
c98603ea 216 bool mcData=false;
a354ea1a 217 int nTestFiles=10;
c98603ea 218 TString strArguments(arguments);
219 TObjArray* tokens=strArguments.Tokenize(" ");
220 if (tokens) {
221 for (int iToken=0; iToken<tokens->GetEntriesFast(); iToken++) {
222 TObject* token=tokens->At(iToken);
223 if (!token) continue;
224 TString arg=token->GetName();
225 const char* key=NULL;
226
a354ea1a 227 key="--mcData";
c98603ea 228 if (arg.CompareTo(key)==0) {
a354ea1a 229 // this is an argument to the macro, don't propagate it further to tasks
230 // switch indicates that the input data is mc data, the run numbers have
231 // a different format in real data
232 // NOTE: not to be confused with option 'mc' which is propagated to tasks
233 // and switches processing and output modes inside tasks
c98603ea 234 mcData=true;
235 }
a354ea1a 236 key="--merge=";
237 if (arg.BeginsWith(key)) {
238 // this is an argument to the macro, don't propagate it further to tasks
239 strArguments.ReplaceAll(arg, "");
240 arg.ReplaceAll(key, "");
241 if (arg.CompareTo("local")==0) {
242 // download all files and merge locally
243 bMergeOnGrid=false;
244 } else if (arg.CompareTo("collect")==0) {
245 // download the output of merging on Grid
246 // macro must have been called in mode "terminate" with option
247 // --merge=grid and the correct grid working directory
248 bMergeOnGrid=false;
249 } else if (arg.CompareTo("grid")==0) {
250 // merge output on grid, the correct grid working directory
251 // must be provided
252 bMergeOnGrid=true;
253 }
254 }
255 key="--nTestFiles=";
256 if (arg.BeginsWith(key)) {
257 // this is an argument to the macro, don't propagate it further to tasks
258 strArguments.ReplaceAll(arg, "");
259 arg.ReplaceAll(key, "");
260 nTestFiles=arg.Atoi();
261 }
7162a4fd 262 key="--noDefaultOutput";
263 if (arg.CompareTo(key)==0) {
264 // this is an argument to the macro, don't propagate it further to tasks
265 strArguments.ReplaceAll(arg, "");
266 bDefaultOutput=false;
267 }
268 key="--stopBeforeRunning";
269 if (arg.CompareTo(key)==0) {
270 // this is an argument to the macro, don't propagate it further to tasks
271 strArguments.ReplaceAll(arg, "");
272 bRunAnalysis=false;
273 }
c98603ea 274 }
275 delete tokens;
276 }
277
04a0c008 278 ///////////////////////////////////////////////////////////////////////////////////////////////////
279 ///////////////////////////////////////////////////////////////////////////////////////////////////
280 ///////////////////////////////////////////////////////////////////////////////////////////////////
281 //
282 // make the analysis manager
283 //
284 AliAnalysisManager *pManager = new AliAnalysisManager("AnalysisManager");
285 if (!pManager) {
286 cerr << "failed to created AnalysisManager" << endl;
287 return;
288 }
289 AliInputEventHandler *pInputHandler = NULL;
290 TString strDataPattern(dataPattern);
9a3d923b 291 if (strDataPattern.Contains("AOD")) pInputHandler=new AliAODInputHandler;
292 else if (strDataPattern.Contains("ESD")) pInputHandler=new AliESDInputHandler;
04a0c008 293 else {
294 cerr << "can not determine input type from data pattern '" << dataPattern << "'" << endl;
295 return;
296 }
297 if (!pInputHandler) {
298 cerr << "failed to created input handler" << endl;
299 return;
300 }
301 //pInputHandler->SetReadFriends(kFALSE);
302 pManager->SetInputEventHandler(pInputHandler);
303 pManager->SetNSysInfo(1000);
304
305 TString ofile=Form("%s.root", analysisName);
306
307 ///////////////////////////////////////////////////////////////////////////////////////////////////
308 ///////////////////////////////////////////////////////////////////////////////////////////////////
309 ///////////////////////////////////////////////////////////////////////////////////////////////////
310 //
311 // load task classes and find and load all dependencies
312 //
313 gSystem->AddIncludePath(includePath);
314 TString libraries=libraryDependencies;
9a3d923b 315 if (gDirectory!=NULL) {
316 // fetch the analysis libraries from the setup file
317 const char* confObjectName="analysis_libraries";
318 TObject* confObject=gDirectory->FindObject(confObjectName);
319 if (confObject) {
320 TString analysisLibraries(confObject->GetTitle());
321 TObjArray* pTokens=analysisLibraries.Tokenize(" ");
322 if (pTokens) {
323 for (int i=0; i<pTokens->GetEntriesFast(); i++) {
324 if (libraries.Contains(pTokens->At(i)->GetName())==0) {
325 libraries+=" ";
326 libraries+=pTokens->At(i)->GetName();
d8f45894 327 TString library=pTokens->At(i)->GetName();
328 if (!library.EndsWith(".so")) libraries+=".so";
9a3d923b 329 }
330 }
331 delete pTokens;
332 }
333 }
334 }
04a0c008 335 TObjArray* pTokens=libraries.Tokenize(" ");
336 if (pTokens) {
337 for (int i=0; i<pTokens->GetEntriesFast(); i++) {
d8f45894 338 TString library=pTokens->At(i)->GetName();
339 if (!library.EndsWith(".so")) {
340 cerr << "libraries need to have ending '.so' in order to be correctly processed by alien plugin, please correct library name '" << library << "'" << endl;
341 }
9a3d923b 342 if (gSystem->Load(pTokens->At(i)->GetName())==0) {
343 cout << "loading " << pTokens->At(i)->GetName() << endl;
344 }
04a0c008 345 }
346 delete pTokens;
347 }
04a0c008 348
685fea75 349 TString taskNames=tasknames;
350 TString taskClasses="";
351 TString taskSources="";
352 TString taskHeaders="";
353 TString addTaskMacros="";
f6f9bc4b 354 TString dependencyHeader;
355 TString dependencySource;
685fea75 356 TString parPackages="";
f6f9bc4b 357 TString delimiter(" ");
358 TStringToken taskNameTokens(taskNames, delimiter);
359 TObject* pCodeTree=NULL;
360 {
361 while (taskNameTokens.NextToken()) {
362 TString taskSource(taskNameTokens);
363 TString taskHeader(taskNameTokens);
685fea75 364 bool bIsAddTask=false;
39341c1f 365 if (taskSource.EndsWith(".C")) {
366 // suppose that's an 'AddTask' macro
367 taskHeader="";
368 bIsAddTask=true;
369 } else if (taskSource.EndsWith(".par")) {
370 // par file
371 if (gSystem->AccessPathName(taskSource)!=0) {
372 ::Error("run_single_task", Form("par file '%s' not found in current directory, you might want to set a symbolic link", taskSource.Data()));
373 return;
374 }
375 parPackages+=" ";
376 parPackages+=taskSource;
377 continue;
378 } else if (taskSource.EndsWith(".h")) {
379 taskSource.ReplaceAll(".h", "");
380 taskClasses+=" ";
381 taskClasses+=taskSource;
382 taskSource+=".cxx";
383 } else if (taskSource.EndsWith(".cxx")) {
384 taskHeader.ReplaceAll(".cxx", "");
385 taskClasses+=" ";
386 taskClasses+=taskHeader;
387 taskHeader+=".h";
388 } else {
389 taskClasses+=" ";
390 taskClasses+=taskSource;
391 taskSource+=".cxx";
392 taskHeader+=".h";
393 }
39341c1f 394 if (gSystem->AccessPathName(taskSource)==0) {
f6f9bc4b 395 pCodeTree=BuildCodeTree(taskSource, pCodeTree);
39341c1f 396 if (!bIsAddTask) {taskSources+=" "; taskSources+=taskSource;}
397 else {addTaskMacros+=" "; addTaskMacros+=taskSource;}
398 }
f6f9bc4b 399 if (gSystem->AccessPathName(taskHeader)==0) {
400 pCodeTree=BuildCodeTree(taskHeader, pCodeTree);
401 taskHeaders+=" "; taskHeaders+=taskHeader;
39341c1f 402 }
685fea75 403 }
685fea75 404 }
f6f9bc4b 405 ProcessCodeTree(pCodeTree, dependencySource, dependencyHeader, libraries);
406
685fea75 407 cout << "Tasks: " << taskClasses << endl;
408 cout << "Task files: " << taskSources << addTaskMacros << taskHeaders << endl;
04a0c008 409 cout << "Dependency classes: " << dependencySource << endl;
410 cout << "Dependency headers: " << dependencyHeader << endl;
411 cout << "Dependency libraries: " << libraries << endl;
685fea75 412 cout << "Packages: " << parPackages << endl;
04a0c008 413
414 ///////////////////////////////////////////////////////////////////////////////////////////////////
415 ///////////////////////////////////////////////////////////////////////////////////////////////////
416 ///////////////////////////////////////////////////////////////////////////////////////////////////
417 //
418 // init for local or GRID analysis
419 //
9a3d923b 420 AliAnalysisAlien *alienHandler = NULL; // for grid analysis
04a0c008 421 TChain *chain=NULL; // for local analysis
422 TString strInput=input;
423 if (bRunLocal) {
424 ///////////////////////////////////////////////////////////////////////////////////////////////////
425 //
426 // local analysis
427 //
c98603ea 428 if (strInput.BeginsWith("alien://")) {
429 // file on Grid -> connect to AliEn
430 TGrid::Connect("alien://");
431 }
04a0c008 432 if(strInput.EndsWith("AliESDs.root")){
433 // suppose it's a single ESD file
434 chain = new TChain("esdTree");
435 chain->Add(strInput);
436 } else if(strInput.EndsWith(".txt")) {
437 // Constructs chain from filenames in *.txt
438 // in the form $DIR/AliESDs.root
439 gROOT->LoadMacro("$ALICE_ROOT/PWG0/CreateESDChain.C");
440 // chain can contain up to 200 files, value can be modified to
441 // include a subset of what the *txt file contains
c98603ea 442 chain = CreateESDChain(strInput.Data(),200);
04a0c008 443
444 // check if the files are on grid
445 TIter next(chain->GetListOfFiles());
446 TChainElement *chEl = 0;
447 while(( chEl = (TChainElement*)next() )){
448 TString tmp = chEl->GetTitle();
449 if(tmp.BeginsWith("alien://")) {
450 TGrid::Connect("alien://");
451 break;
452 }
453 }
c98603ea 454 } else if(strInput.EndsWith("ESD")){
455 // fetch esd tree from the setup macro
a354ea1a 456 const char* esdTreeName="esdTree";
c98603ea 457 if (gDirectory!=NULL) {
c98603ea 458 TObject* chainObject=gDirectory->FindObject(esdTreeName);
459 if (chainObject) {
460 chain=dynamic_cast<TChain*>(chainObject);
461 }
462 }
463 if (!chain) {
464 ::Error("run_single_task", Form("failed to fetch esd tree object from setup; the chain with name '%s' has to be created before calling this macro", esdTreeName));
465 return;
466 }
467 } else if(strInput.EndsWith("AliAOD.root")){
468 // single local AOD file
469 chain = new TChain("aodTree");
470 chain->Add(strInput);
9a3d923b 471 } else if(strInput.EndsWith("AOD")){
472 // fetch aod tree from the setup macro
a354ea1a 473 const char* aodTreeName="aodTree";
9a3d923b 474 if (gDirectory!=NULL) {
39341c1f 475 TObject* chainObject=gDirectory->FindObject(aodTreeName);
9a3d923b 476 if (chainObject) {
477 chain=dynamic_cast<TChain*>(chainObject);
478 }
479 }
480 if (!chain) {
39341c1f 481 ::Error("run_single_task", Form("failed to fetch aod tree object from setup; the chain with name '%s' has to be created before calling this macro", aodTreeName));
482 return;
9a3d923b 483 }
04a0c008 484 } else {
39341c1f 485 ::Error("run_single_task", Form("invalid input"));
486 return;
04a0c008 487 }
488 } else {
489 ///////////////////////////////////////////////////////////////////////////////////////////////////
490 //
491 // grid analysis
492 //
39341c1f 493 bool bSetRun=true;
39341c1f 494 if (!strInput.IsDigit()) {
495 // support for external macros specifying the the runs to be
496 // analyzed
497 // the input is expected to be an external plugin with name 'input'
498 // and all run numbers being set
499 TObject* pObj=gDirectory->FindObject(input);
500 if (pObj) alienHandler=dynamic_cast<AliAnalysisAlien*>(pObj);
501 if (!alienHandler) {
502 ::Error("run_single_task", Form("can not find plugin of name '%s', please setup alien handler with name and run numbers before calling this macro", input));
503 return;
504 }
505 bSetRun=false;
506 } else {
507 alienHandler=new AliAnalysisAlien();
508 }
04a0c008 509 if (!alienHandler) {
39341c1f 510 ::Error("run_single_task", Form("failed to create alien handler"));
04a0c008 511 return;
512 }
513
514 // do not check for copying to grid (CLOSE_SE)
515 alienHandler->SetCheckCopy(kFALSE);
516
517 // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
518 alienHandler->SetRunMode(mode);
a354ea1a 519
520 // number of files in test mode configurable via argument '--nTestFiles='
521 if(mode=="test") alienHandler->SetNtestFiles(nTestFiles);
04a0c008 522
523 // check the versions available on alien with the command 'packages'
524 alienHandler->SetAPIVersion(alienAPIVersion);
525 alienHandler->SetROOTVersion(alienROOTVersion);
526 alienHandler->SetAliROOTVersion(alienAliROOTVersion);
527
7162a4fd 528 // using only default output
529 // the alien plugin automatically recognizes all output files associated to output
530 // containers, all files are treated in the standard output and added to the
531 // root-archieve.root, which also seems to be needed for merging on Grid
532 // see further down for using non-default output
533 alienHandler->SetDefaultOutputs(bDefaultOutput);
a354ea1a 534
04a0c008 535 if (user && user[0]!=0) alienHandler->SetUser(user);
536
537 // data alien directory
538 alienHandler->SetGridDataDir(gridDataDir);
539
540 // Set data search pattern
541 alienHandler->SetDataPattern(dataPattern);
9a3d923b 542 alienHandler->SetFriendChainName(friendDataPattern);
04a0c008 543
685fea75 544 TObjArray* packageTokens=parPackages.Tokenize(" " );
545 if (packageTokens) {
546 for (int iPackageToken=0; iPackageToken<packageTokens->GetEntriesFast(); iPackageToken++) {
547 alienHandler->EnablePackage(packageTokens->At(iPackageToken)->GetName());
548 }
549 delete packageTokens;
550 }
551
39341c1f 552 if (bSetRun) {
553 // only set if input is a run number
c98603ea 554 if (!mcData && !strInput.BeginsWith("000"))
39341c1f 555 alienHandler->SetRunPrefix("000"); // real data
04a0c008 556
39341c1f 557 alienHandler->AddRunNumber(input);
558 }
04a0c008 559
560 // define working and output directories
561 TDatime dt;
9a3d923b 562 if(odir.IsNull())
563 odir=(Form("gridwork/%04d-%02d-%02d_%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute()));
564 cout << odir << endl;
04a0c008 565 alienHandler->SetGridWorkingDir(odir); // relative to $HOME
566 alienHandler->SetGridOutputDir("output"); // relative to working dir
9a3d923b 567 //alienHandler->SetOverwriteMode(); // overwrites the contents of the working and output directory
04a0c008 568
9a3d923b 569 // workaround for a Root feature: GetIncludePath() appends always
570 // the current Root include path including escaped quotes. Those
571 // quotes make it difficult to pass the output directly. Search for the
572 // last appended include path and truncate
573 TString strIncludePath(gSystem->GetIncludePath());
574 Int_t pos=strIncludePath.Index(includePath);
575 if (pos>=0) {
576 Int_t cut=0;
577 do {
578 cut=pos+strlen(includePath);
579 } while ((pos=strIncludePath.Index(includePath, cut))>cut);
580 strIncludePath.Resize(cut);
581 }
582 alienHandler->AddIncludePath(strIncludePath);
04a0c008 583
584 // Note: there is no extra source or header file to be transferred if 'AddTask' macros are used
685fea75 585 alienHandler->SetAnalysisSource(Form("%s %s %s %s", dependencySource.Data(), dependencyHeader.Data(), taskSources.Data(), taskHeaders.Data()));
a354ea1a 586 alienHandler->SetAdditionalLibs(Form("%s %s %s %s %s", libraries.Data(), dependencySource.Data(), dependencyHeader.Data(), taskSources.Data(), taskHeaders.Data()));
04a0c008 587
04a0c008 588 // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
589 TString macroName; macroName.Form("run_%s.C",analysisName); macroName.ReplaceAll("-","_");
590 alienHandler->SetAnalysisMacro(macroName);
591
592 //alienHandler->SetExecutable("comparison.sh");
593 alienHandler->SetExecutable(Form("run_%s.sh",analysisName));
594
595 alienHandler->SetSplitMaxInputFileNumber(100);
596
597 // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
598 alienHandler->SetMaxInitFailed(10);
599
600 // Optionally resubmit threshold.
601 alienHandler->SetMasterResubmitThreshold(90); // in %
602
39341c1f 603 alienHandler->SetTTL(86400);// in sec
04a0c008 604
605 // Optionally set input format (default xml-single)
606 alienHandler->SetInputFormat("xml-single");
607
608 // Optionally modify the name of the generated JDL (default analysis.jdl)
609 alienHandler->SetJDLName(Form("run_%s.jdl",analysisName));
610
611 // Optionally modify job price (default 1)
612 alienHandler->SetPrice(1);
613
614 // Optionally modify split mode (default 'se')
615 alienHandler->SetSplitMode("se");
616
a354ea1a 617 // configure merging on grid,
618 // argument '--merge=collect' sets 'false' for fetching the merged output
619 alienHandler->SetMergeViaJDL(bMergeOnGrid);
04a0c008 620
9a3d923b 621 alienHandler->SetOneStageMerging(kFALSE);
622 alienHandler->SetMaxMergeStages(2);
04a0c008 623 }
624
625 // Connect plugin to the analysis manager
626 if (alienHandler) {
627 pManager->SetGridHandler(alienHandler);
628 }
629
630 ///////////////////////////////////////////////////////////////////////////////////////////////////
631 ///////////////////////////////////////////////////////////////////////////////////////////////////
632 ///////////////////////////////////////////////////////////////////////////////////////////////////
633 //
634 // create task from the name, create output container, connect slots
635 //
685fea75 636 TObjArray* taskClassTokens=taskClasses.Tokenize(" ");
637 if (taskClassTokens) {
638 for (int iTaskClassToken=0; iTaskClassToken<taskClassTokens->GetEntriesFast(); iTaskClassToken++) {
39341c1f 639 AliAnalysisTaskSE *pTask=NULL;
640 TString taskName=taskClassTokens->At(iTaskClassToken)->GetName();
641 taskName.ReplaceAll(".cxx", "");
642 TClass* pCl=TClass::GetClass(taskName);
643 if (!pCl) {
644 cerr << "can not load class " << taskName << endl;
645 return;
646 }
a354ea1a 647 void* p=pCl->New();
39341c1f 648 if (!p) {
649 cerr << "failed to instantiate class " << taskName << endl;
650 return;
651 }
652 pTask=reinterpret_cast<AliAnalysisTaskSE*>(p);
653 pManager->AddTask(pTask);
654 AliAnalysisDataContainer *pContainer=pManager->CreateContainer(analysisName ,TObject::Class(), AliAnalysisManager::kOutputContainer, ofile);
655 pManager->ConnectInput(pTask,0,pManager->GetCommonInputContainer());
656 pManager->ConnectOutput(pTask,1,pContainer);
685fea75 657 }
658 delete taskClassTokens;
659 }
660 TObjArray* taskMacroTokens=addTaskMacros.Tokenize(" ");
661 if (taskMacroTokens) {
662 for (int iTaskMacroToken=0; iTaskMacroToken<taskMacroTokens->GetEntriesFast(); iTaskMacroToken++) {
a354ea1a 663 TString taskSource= taskMacroTokens->At(iTaskMacroToken)->GetName();
664
39341c1f 665 taskSource+="+g";
666 TString configuration;
a354ea1a 667 if(!strArguments.Contains("file=")) configuration+=Form(" file=%s",ofile.Data());
668 if(!strArguments.Contains("name=")) configuration+=Form(" name=%s",analysisName);
669 configuration+=" "; configuration+=strArguments.Data();
39341c1f 670 if (gDirectory) gDirectory->Add(new TNamed("run_single_task_configuration", configuration.Data()));
671 gROOT->Macro(taskMacroTokens->At(iTaskMacroToken)->GetName());
685fea75 672 }
673 delete taskMacroTokens;
04a0c008 674 }
675
7162a4fd 676 if (!bDefaultOutput) {
677 // fetch all output files from the output containers
678 TString ofiles;
679 TIter nextcontainer(pManager->GetContainers());
680 TObject* objContainer=NULL;
681 while ((objContainer=nextcontainer())!=NULL) {
682 AliAnalysisDataContainer* container=dynamic_cast<AliAnalysisDataContainer*>(objContainer);
683 if (!container) continue;
684 ofiles+=container->GetFileName();
685 ofiles+=" ";
686 }
687
688 alienHandler->SetOutputFiles(ofiles);
689 // Optionally define the files to be archived.
690 alienHandler->SetOutputArchive("log_archive.zip:stdout,stderr");
691 }
692
04a0c008 693 ///////////////////////////////////////////////////////////////////////////////////////////////////
694 ///////////////////////////////////////////////////////////////////////////////////////////////////
695 ///////////////////////////////////////////////////////////////////////////////////////////////////
696 //
697 // run
698 //
a354ea1a 699
04a0c008 700 if (!pManager->InitAnalysis()) {
701 cerr << "failed to initialize analysis" << endl;
702 return;
703 }
704 if (nevents<0) nevents=1000000000;
705 pManager->PrintStatus();
7162a4fd 706 if (!bRunAnalysis) return;
04a0c008 707 if (bRunLocal) {
708 pManager->StartAnalysis("local", chain, nevents);
709 } else {
710 pManager->StartAnalysis("grid", nevents);
711 }
712}
713
c98603ea 714// method for backward compatibility
715void run_single_task(const char* mode,
716 const char* input,
717 const char* tasknames,
718 const char* analysisName,
719 Bool_t useMC,
720 int nevents=-1,
721 const char* gridDataDir=NULL,
722 const char* dataPattern=NULL,
723 const char* friendDataPattern=NULL,
724 TString odir="",
725 const char* user=NULL
726 )
727{
728 run_single_task(mode,
729 input,
a354ea1a 730 tasknames,
c98603ea 731 analysisName,
a354ea1a 732 (useMC?"mc":""),
c98603ea 733 nevents,
734 gridDataDir,
735 dataPattern,
736 friendDataPattern,
737 odir,
738 user
739 );
740}
741
a354ea1a 742// method for calling with a fixed working directory, e.g. in mode terminate
743void run_single_task(const char* mode,
744 const char* input,
745 const char* tasknames,
746 const char* analysisName,
747 const char* arguments,
748 const char* workdir
749 )
750{
751 TString odir(workdir);
752 run_single_task(mode,
753 input,
754 tasknames,
755 analysisName,
756 arguments,
757 -1,
758 NULL,
759 NULL,
760 NULL,
761 odir,
762 NULL
763 );
764}
765
04a0c008 766TString GetIncludeHeaders(const char* filename, TString& headers, TString& libs, bool loadClass)
767{
768 // scan the file and add all include headers found by path
769 // to the parameter headers
770 ifstream input(filename);
04a0c008 771 if (input.bad()) {
772 cerr << "failed to open file " << filename << endl;
773 return headers;
774 }
775 TString line;
776 while (!line.ReadLine(input).eof()) {
777 if (!line.Contains("#include") || !line.Contains(".h")) continue;
778 line=line(0, line.Index(".h"));line+=".h";
779 line.Replace(0, line.Index("#include"), "");
780 line.ReplaceAll("#include", "");
781 line.ReplaceAll(" ", "");
782 line.ReplaceAll("\"", "");
783 if (!line.BeginsWith("Ali") && !line.BeginsWith("T")) continue;
784 if (gSystem->AccessPathName(line)!=0) {
785 // not an include file in the current directory, check if class
786 // is available or find library
787 line.ReplaceAll(".h","");
788 //cout << "checking class " << line << endl;
789 if (TClass::GetClass(line)==NULL) {
790 TString command;
791 TString resfilename(gSystem->TempDirectory()); resfilename+="/findlib.txt";
792 command.Form("for lib in $ALICE_ROOT/lib/*/lib*.so; do (nm $lib | grep %s | grep ' T ' | grep Class_Name > /dev/null) && echo $lib > %s; done", line.Data(), resfilename.Data());
793 gSystem->Exec(command);
794 ifstream resfile(resfilename.Data());
795 if (resfile.good()) {
796 TString result;
797 if (!result.ReadLine(resfile).eof()) {
798 Ssiz_t haveSlash=-1;
799 while ((haveSlash=result.First('/'))>=0) result.Replace(0, haveSlash+1, "");
800 if (!libs.Contains(result)) {
801 cout << "loading dependency library '" << result << "' for class '" << line << "'" << endl;
802 gSystem->Load(result);
803 if (!libs.IsNull()) libs+=" ";
804 libs+=result;
805 }
806 }
807 command="rm "; command+=resfilename;
808 gSystem->Exec(command);
809 }
810 }
811 } else {
812 if (headers.Contains(line)) {
813 if (!headers.BeginsWith(line)) {
814 headers.ReplaceAll(line, "");
815 if (!headers.IsNull()) headers.Insert(0, " ");
9a3d923b 816 if (macroVerbosity>0) cout << "moving " << line << endl;
04a0c008 817 headers.Insert(0, line);
818 }
819 continue;
820 }
821 if (!headers.IsNull()) headers.Insert(0, " ");
9a3d923b 822 if (macroVerbosity>0) cout << "inserting " << line << endl;
04a0c008 823 headers.Insert(0, line);
824 TString source=line; source.ReplaceAll(".h", ".cxx");
825 if (gSystem->AccessPathName(source)==0) {
826 GetIncludeHeaders(source, headers, libs);
827 }
828 GetIncludeHeaders(line, headers, libs);
829 if (loadClass && gSystem->AccessPathName(source)==0) {
830 line.ReplaceAll(".h", "");
831 if (TClass::GetClass(line)==NULL) {
832 source+="+g";
833 gROOT->LoadMacro(source);
834 }
835 }
836 }
837 }
9a3d923b 838
04a0c008 839 return headers;
840}
841
842void ErrorConfigurationFile(const char* fileName) {
843 cout << endl;
844 cout << "/// -------------------------------------------------------------------" << endl;
845 cout << "/// Warning: can not find configuration file '" << fileName << "'" << endl;
846 cout << "/// please create a configuration file in either local or HOME directory, or in" << endl;
847 cout << "/// specified location. Below is an example, fill in your preferred defaults." << endl;
848 cout << "/// -------------------------------------------------------------------" << endl;
849 cout << endl;
850 cout << "const char* alienAPIVersion=\"V1.1x\";" << endl;
851 cout << "const char* alienROOTVersion=\"v5-33-02a\";" << endl;
852 cout << "const char* alienAliROOTVersion=\"v5-01-Rev-29\";" << endl;
853 cout << "const char* defaultGridDataDir=\"/alice/data/2011/LHC11f\";" << endl;
854 cout << "const char* defaultDataPattern=\"*ESDs.root\";" << endl;
9a3d923b 855 cout << "const char* defaultFriendDataPattern=\"\";" << endl;
04a0c008 856 cout << "{} // note this empty body";
857 cout << endl;
858}
f6f9bc4b 859
860class AliCodeNode : public TNamed
861{
862public:
863 AliCodeNode();
864 AliCodeNode(const char* filename);
865 ~AliCodeNode();
866
867 enum {
868 kTypeInvalid = 0,
869 kTypeSource = 1,
870 kTypeHeader,
871 kTypeMacro,
872 kNofTypes
873 };
874
875 const TList& GetParents() const {return fParents;}
876 const TList& GetChilds() const {return fChilds;}
877 int AddParent(AliCodeNode* pParent);
878 int InsertChild(AliCodeNode* pChild);
879 bool HasChilds() const {return (GetChilds().GetEntries()-fProcessedChilds.GetEntries())>0;}
880 int MarkProcessed();
881 int MarkChildProcessed(AliCodeNode* pChild);
882 bool HasSourceParent();
883 //int DisconnectParents();
884
885 bool IsHeader() const {return fType==kTypeHeader;}
886 bool IsSource() const {return fType==kTypeSource;}
a354ea1a 887 void HaveFile(bool haveFile) {fHaveFile=haveFile;}
888 bool HaveFile() const {return fHaveFile;}
f6f9bc4b 889 void Print(Option_t *option="") const;
890
891protected:
892 //int DisconnectChild(const AliCodeNode& child);
893
894private:
895 TList fParents; // list of parents
896 TList fChilds; // list of childs
897 TList fProcessedChilds; // list of processed childs
898 int fType; // source of header
a354ea1a 899 bool fHaveFile;// file is existing in pwd
f6f9bc4b 900
901 ClassDef(AliCodeNode, 1)
902};
903
904class AliCodeTree : public TObject
905{
906public:
907 AliCodeTree(short verbosity=0) : fNodes(), fIndentCount(0), fVerbosity(verbosity) {fNodes.SetOwner(kTRUE);}
908 ~AliCodeTree() {}
909
910 AliCodeNode* Build(const char* topfile, AliCodeNode* parent=NULL);
911 AliCodeNode* FindNode(const char* name);
912 int Sort();
913 int LoadClasses(TString& libs);
914 int LoadClasses() {TString dummy; return LoadClasses(dummy);}
915 int GetHeaders(TString& headers);
916 int GetSources(TString& sources);
917
918 void Print(Option_t *option="") const;
919
920private:
921 TObjArray fNodes; // list of nodes
922 short fIndentCount;
923 short fVerbosity;
924
925 ClassDef(AliCodeTree, 1)
926};
927
928ClassImp(AliCodeNode)
929
930AliCodeNode::AliCodeNode()
931 : TNamed()
932 , fParents()
933 , fChilds()
934 , fProcessedChilds()
935 , fType(AliCodeNode::kTypeInvalid)
a354ea1a 936 , fHaveFile(false)
f6f9bc4b 937{
938}
939
940AliCodeNode::AliCodeNode(const char* filename)
941 : TNamed(filename, filename)
942 , fParents()
943 , fChilds()
944 , fProcessedChilds()
945 , fType(AliCodeNode::kTypeInvalid)
a354ea1a 946 , fHaveFile(false)
f6f9bc4b 947{
948 TString s(filename);
949 if (s.EndsWith(".cxx")) fType=kTypeSource;
950 else if (s.EndsWith(".h")) fType=kTypeHeader;
951 else if (s.EndsWith(".C")) fType=kTypeMacro;
952}
953
954AliCodeNode::~AliCodeNode()
955{
956}
957
958int AliCodeNode::AddParent(AliCodeNode* pParent)
959{
960 if (!pParent) return -1;
961 if (fParents.FindObject(pParent)) return 0;
962 if (GetChilds().FindObject(pParent)) {
963 cerr << "error: circular dependency: can not add " << pParent->GetName() << " as parent to " << this->GetName() << endl;
964 return -2;
965 }
966 fParents.Add(pParent);
967 return 0;
968}
969
970int AliCodeNode::InsertChild(AliCodeNode* pChild)
971{
972 if (!pChild) return -1;
973 if (fChilds.FindObject(pChild)) return 0;
974 if (pChild->GetChilds().FindObject(this)) {
975 cerr << "error: circular dependency: can not add " << pChild->GetName() << " as child to " << this->GetName() << endl;
976 return -2;
977 }
978 fChilds.Add(pChild);
979 return 0;
980}
981
982int AliCodeNode::MarkProcessed()
983{
984 TIter parents(&fParents);
985 TObject* obj=NULL;
986 while ((obj=parents())) {
987 AliCodeNode* parent=dynamic_cast<AliCodeNode*>(obj);
988 parent->MarkChildProcessed(this);
989 }
990
991 return 0;
992}
993
994bool AliCodeNode::HasSourceParent()
995{
996 if (fType!=kTypeHeader) return false;
997 TString name(GetName());
998 name.ReplaceAll(".h", ".cxx");
999 TIter parents(&fParents);
1000 TObject* obj=NULL;
1001 while ((obj=parents())) {
1002 if (name.CompareTo(obj->GetName())==0)
1003 return true;
1004 }
1005 return false;
1006}
1007
1008int AliCodeNode::MarkChildProcessed(AliCodeNode* pChild)
1009{
1010 if (!pChild) return -1;
1011 if (fChilds.FindObject(pChild)==NULL) {
1012 cerr << "node " << GetName() << ": failed to find child node " << pChild->GetName() << endl;
1013 return -1;
1014 }
1015 if (fProcessedChilds.FindObject(pChild)!=NULL) {
1016 cerr << "node " << GetName() << ": child node " << pChild->GetName() << " already processed" << endl;
1017 return 0;
1018 }
1019 fProcessedChilds.Add(pChild);
1020 return 0;
1021}
1022
1023void AliCodeNode::Print(Option_t */*option*/) const
1024{
1025 cout << "-- " << GetName() << endl;
1026 TObject* obj=NULL;
1027 cout << " - parents" << endl;
1028 TIter parents(&fParents);
1029 while ((obj=parents())) {
1030 cout << " |- " << obj->GetName() << endl;
1031 }
1032 cout << " - childs" << endl;
1033 TIter childs(&fChilds);
1034 while ((obj=childs())) {
1035 cout << " |- " << obj->GetName() << endl;
1036 }
1037}
1038
1039ClassImp(AliCodeTree)
1040
1041AliCodeNode* AliCodeTree::Build(const char* topfile, AliCodeNode* parent)
1042{
1043 // scan the file and recursively add all include headers found by path
1044 int iResult=0;
f6f9bc4b 1045 AliCodeNode* node=FindNode(topfile);
1046 if (!node) {
1047 if (fVerbosity>0) cout << setw(2*fIndentCount) << " " << "new node " << topfile << endl;
1048 fIndentCount++;
1049 node=new AliCodeNode(topfile);
1050 fNodes.Add(node);
a354ea1a 1051 ifstream input(topfile);
1052 if (input.good()) {
1053 node->HaveFile(true);
1054 TString line;
1055 while (!line.ReadLine(input).eof()) {
1056 if (!line.Contains("#include") || !line.Contains(".h")) continue;
1057 line=line(0, line.Index(".h"));line+=".h";
1058 line.Replace(0, line.Index("#include"), "");
1059 line.ReplaceAll("#include", "");
1060 line.ReplaceAll(" ", "");
1061 line.ReplaceAll("\"", "");
1062 if (!line.BeginsWith("Ali") && !line.BeginsWith("T")) continue;
1063 AliCodeNode* child=NULL;
f6f9bc4b 1064 TString source=line; source.ReplaceAll(".h", ".cxx");
1065 if (source.CompareTo(topfile)!=0 && gSystem->AccessPathName(source)==0) {
a354ea1a 1066 child=Build(source, node);
f6f9bc4b 1067 node->InsertChild(child);
1068 }
a354ea1a 1069 child=Build(line, node);
1070 node->InsertChild(child);
f6f9bc4b 1071 }
1072 }
1073 fIndentCount--;
1074 }
1075 if (parent) {
1076 if ((iResult=node->AddParent(parent))<0)
1077 return NULL;
1078 }
1079 if (fVerbosity>0) cout << setw(2*fIndentCount) << " " << "finished " << topfile << endl;
1080 return node;
1081}
1082
1083int AliCodeTree::Sort()
1084{
1085 TObjArray sortedNodes;
1086 int nNodes=fNodes.GetEntriesFast();
1087 int nCount=0;
1088 while (sortedNodes.GetEntriesFast()<nNodes && nCount<nNodes) {
1089 for (int i=0; i<nNodes; i++) {
1090 if (fNodes[i]==NULL) continue;
1091 AliCodeNode* node=dynamic_cast<AliCodeNode*>(fNodes[i]);
1092 if (node->HasChilds()) {
1093 continue;
1094 }
1095 fNodes[i]=NULL;
1096 sortedNodes.Add(node);
1097 node->MarkProcessed();
1098 }
1099 nCount++;
1100 }
1101
1102 for (int i=0; i<nNodes; i++) {
1103 fNodes[i]=sortedNodes[i];
1104 }
1105
1106 return 0;
1107}
1108
1109int AliCodeTree::LoadClasses(TString& libs)
1110{
1111 TIter next(&fNodes);
1112 TObject* obj=NULL;
1113 while ((obj=next())!=NULL) {
1114 AliCodeNode* node=dynamic_cast<AliCodeNode*>(obj);
1115 TString name(node->GetName());
1116 if (node->IsHeader()) {
1117 if (node->HasSourceParent()) {
1118 // nothing to do, class going to be compiled from source
1119 continue;
1120 }
1121 name.ReplaceAll(".h", "");
1122 if (TClass::GetClass(name)!=NULL) {
1123 // class available in the system
1124 continue;
1125 }
1126
1127 TString command;
1128 TString resfilename(gSystem->TempDirectory()); resfilename+="/findlib.txt";
1129 command.Form("for lib in $ALICE_ROOT/lib/*/lib*.so; do (nm $lib | grep %s | grep ' T ' | grep Class_Name > /dev/null) && echo $lib > %s; done", name.Data(), resfilename.Data());
1130 gSystem->Exec(command);
1131 ifstream resfile(resfilename.Data());
1132 if (resfile.good()) {
1133 TString result;
1134 if (!result.ReadLine(resfile).eof()) {
1135 Ssiz_t haveSlash=-1;
1136 while ((haveSlash=result.First('/'))>=0) result.Replace(0, haveSlash+1, "");
1137 if (!libs.Contains(result)) {
1138 cout << "loading dependency library '" << result << "' for class '" << name << "'" << endl;
1139 gSystem->Load(result);
1140 if (!libs.IsNull()) libs+=" ";
1141 libs+=result;
1142 }
1143 }
1144 command="rm "; command+=resfilename;
1145 gSystem->Exec(command);
1146 }
1147 continue;
1148 }
1149 if (node->IsSource()) {
1150 TString classname(name);
1151 classname.ReplaceAll(".cxx", "");
1152 if (TClass::GetClass(classname)!=NULL) {
1153 // class available in the system
1154 continue;
1155 }
1156 name+="+g";
1157 gROOT->LoadMacro(name);
1158 }
1159 }
1160 return 0;
1161}
1162
1163int AliCodeTree::GetHeaders(TString& headers)
1164{
1165 TIter next(&fNodes);
1166 TObject* obj=NULL;
1167 while ((obj=next())!=NULL) {
1168 AliCodeNode* node=dynamic_cast<AliCodeNode*>(obj);
a354ea1a 1169 if (!node->IsHeader() || !node->HaveFile()) continue;
f6f9bc4b 1170 if (!headers.IsNull()) headers+=" ";
1171 headers+=node->GetName();
1172 }
1173 return 0;
1174}
1175
1176int AliCodeTree::GetSources(TString& sources)
1177{
1178 TIter next(&fNodes);
1179 TObject* obj=NULL;
1180 while ((obj=next())!=NULL) {
1181 AliCodeNode* node=dynamic_cast<AliCodeNode*>(obj);
a354ea1a 1182 if (!node->IsSource() || !node->HaveFile()) continue;
f6f9bc4b 1183 if (!sources.IsNull()) sources+=" ";
1184 sources+=node->GetName();
1185 }
1186 return 0;
1187}
1188
1189AliCodeNode* AliCodeTree::FindNode(const char* name)
1190{
1191 TObject* node=fNodes.FindObject(name);
1192 if (!node) return NULL;
1193 return dynamic_cast<AliCodeNode*>(node);
1194}
1195
1196void AliCodeTree::Print(Option_t *option) const
1197{
1198 const char* key=NULL;
1199 int indent=0;
1200 TString childOptions;
1201 const TString delimiter(" ");
1202 TStringToken options(option, delimiter);
1203 while (options.NextToken()) {
1204 key="indent=";
1205 if (options.BeginsWith(key)) {
1206 TString arg(options);
1207 arg.ReplaceAll(key, "");
1208 indent=arg.Atoi();
1209 continue;
1210 }
1211 childOptions+=" ";
1212 childOptions+=options;
1213 }
1214 childOptions+=Form("indent=%d", indent+1);
1215 TIter next(&fNodes);
1216 TObject* obj=NULL;
1217 while ((obj=next())!=NULL) {
1218 obj->Print(childOptions);
1219 }
1220}
1221
1222TObject* BuildCodeTree(const char* filename, TObject* useObject)
1223{
1224 AliCodeTree* pTree=NULL;
1225 if (useObject) pTree=dynamic_cast<AliCodeTree*>(useObject);
1226 if (!pTree) pTree=new AliCodeTree;
1227 if (!pTree) return NULL;
1228
1229 pTree->Build(filename);
1230 return pTree;
1231}
1232
1233int ProcessCodeTree(TObject* tree, TString& sources, TString& headers, TString& libs)
1234{
1235 if (!tree) return -1;
1236 AliCodeTree* pTree=dynamic_cast<AliCodeTree*>(tree);
1237 pTree->Sort();
1238 pTree->LoadClasses(libs);
1239 pTree->GetHeaders(headers);
1240 pTree->GetSources(sources);
1241 return 0;
1242}
1243
1244#else
1245#include "TObject.h"
1246#include "TNamed.h"
1247#include "TList.h"
1248#include "TObjArray.h"
1249#include "TString.h"
1250#include "TPRegexp.h"
1251#include "TSystem.h"
1252#include "TROOT.h"
a354ea1a 1253#include "TGrid.h"
1254#include "TChain.h"
1255#include "TChainElement.h"
1256// #include "AliAnalysisManager.h"
1257// #include "AliAnalysisAlien.h"
1258// #include "AliAnalysisTaskSE.h"
1259// #include "AliInputEventHandler.h"
1260// #include "AliAODInputHandler.h"
1261// #include "AliESDInputHandler.h"
f6f9bc4b 1262#include <iostream>
1263#include <fstream>
1264#include <iomanip>
1265using namespace std;
1266
1267#endif