use AliLog message scheme
[u/mrichter/AliRoot.git] / STEER / AliConfig.cxx
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 /* $Id$ */
17
18 //  Description:
19 //  This class is responsible for creating folder structure
20 //  All stuff of aliroot sits in one folder with name defined by
21 //  fgkTopFolderName data wich do not very trough event to event are
22 //  sitting in directly in "top folder" all data which changes from
23 //  event to event are sitting in one folder (which has more subfolders)
24 //  Idea is to have more than one event in folder structure which allows
25 //  usage of standard procedures in merging
26 //  Add(AliDetector*) calls Add(AliModule*) as AliDetector is a AliModule
27 //  as well and should be listed in module list
28
29 #include <TDatabasePDG.h>
30 #include <TFolder.h>
31 #include <TInterpreter.h>
32 #include <TObjString.h>
33 #include <TROOT.h>
34 #include <TString.h>
35 #include <TSystem.h>
36 #include <TTask.h>
37 #include <TVirtualMC.h>
38
39 #include "AliConfig.h"
40 #include "AliDetector.h"
41 #include "AliGenerator.h" 
42 #include "AliLoader.h"
43 #include "AliLog.h"
44
45 enum 
46  {
47   kDetTaskQA = 0,
48   kDetTaskSDigitizer,
49   kDetTaskDigitizer,
50   kDetTaskRecontructioner,
51   kDetTaskTracker,
52   kDetTaskPID,
53   kDetTaskLast
54  };
55
56 enum
57  {
58    kDetFolderData = 0,
59    kDetFolderCalibration,
60    kDetFolderAligmnet,
61    kDetFolderQA,
62    kDetFolderLast
63  };
64 ClassImp(AliConfig)
65
66 AliConfig* AliConfig::fgInstance = 0;
67
68 //0 level folder
69 const TString AliConfig::fgkTopFolderName("Folders");
70
71 //1st level folder
72 const TString AliConfig::fgkTasksFolderName("Tasks"); //task folder, commn
73 const TString AliConfig::fgkConstantsFolderName("Constants");
74 const TString AliConfig::fgkDefaultEventFolderName("Event");  //default folder for event, always used except merging
75
76 //2st level folder
77 //subfolder of event folder
78 const TString AliConfig::fgkDataFolderName("Data");//folder for data (hits, digits, points, tracks) grouped by detectors
79 const TString AliConfig::fgkModuleFolderName("Modules");//folder with modules objects
80 const TString AliConfig::fgkConditionsFolderName("Conditions");//folder with conditions (mag. field etc.)
81 const TString AliConfig::fgkConfigurationFolderName("Configuration");//folder with configuration (setup) of the detector
82 const TString AliConfig::fgkHeaderFolderName("Header");//folder with header and other MC information
83
84 //Tasks names, goes into fgkTasksFolderName folder
85 const TString AliConfig::fgkDigitizerTaskName("Digitizer");
86 const TString AliConfig::fgkSDigitizerTaskName("SDigitizer");
87 const TString AliConfig::fgkReconstructionerTaskName("Reconstructioner");
88 const TString AliConfig::fgkTrackerTaskName("Tracker");
89 const TString AliConfig::fgkPIDTaskName("PIDTask");//;=) PIDer???
90 const TString AliConfig::fgkQATaskName("QAtask");
91
92 //3rd level folder
93 //fgkConditionsFolderName subfolders
94 const TString AliConfig::fgkCalibrationFolderName("Calibration");
95 const TString AliConfig::fgkAligmentFolderName("Aligment");
96 const TString AliConfig::fgkQAFolderName("QAout");
97   
98 //3rd level folder
99 //fgkConfigurationFolderName subfolders
100 const TString AliConfig::fgkFieldFolderName("Field");
101 const TString AliConfig::fgkGeneratorsFolderName("Generators");
102 const TString AliConfig::fgkVirtualMCFolderName("VirtualMC");
103
104
105 const TString AliConfig::fgkPDGFolderName("Constants/DatabasePDG");//folder with PDG Database
106 const TString AliConfig::fgkGeneratorFolderName("Configuration/Generators");//folder with generators
107 const TString AliConfig::fgkMCFolderName("Configuration/VirtualMC");
108
109 //____________________________________________________________________________
110 AliConfig* AliConfig::Instance ()
111 {
112   //
113   // Instance method for singleton class
114   //
115    if(fgInstance == 0) 
116     {
117      fgInstance = new AliConfig (fgkTopFolderName,"Alice data exchange board");
118     }
119    return fgInstance;
120 }
121
122 //____________________________________________________________________________
123 AliConfig::AliConfig():
124   fTopFolder(0x0),
125   fTaskFolder(0x0),
126   fConstFolder(0x0),
127   fDetectorTask(0x0),
128   fDetectorFolder(0x0)
129 {
130   //
131   // Default constructor, mainly to keep coding conventions
132   //
133   fgInstance=0;//never mind, its going to exit in next step
134   AliFatal("Constructor should not be called for a singleton");
135 }
136 //____________________________________________________________________________
137
138 AliConfig::AliConfig(const AliConfig& conf):
139   TNamed(conf),
140   fTopFolder(0x0),
141   fTaskFolder(0x0),
142   fConstFolder(0x0),
143   fDetectorTask(0x0),
144   fDetectorFolder(0x0)
145 {
146   //
147   // Copy constructor, mainly to keep coding conventions
148   //
149   fgInstance=0;
150     
151   AliFatal("Copy constructor should not be called for a singleton");
152 }
153 //____________________________________________________________________________
154
155 AliConfig& AliConfig::operator=(const AliConfig& /*conf*/)
156 {
157   //
158   // Assignment, mainly to keep coding conventions
159   //
160   fgInstance=0;
161     
162   AliFatal("Assignment operator should not be called for a singleton");
163   return *this;
164 }
165 //____________________________________________________________________________
166
167 AliConfig::AliConfig(const char *name, const char *title): 
168   TNamed(name,title), 
169   fTopFolder(gROOT->GetRootFolder()->AddFolder(name,title)),
170   fTaskFolder(fTopFolder->AddFolder(fgkTasksFolderName, "ALICE Tasks")),
171   fConstFolder(0x0),
172   fDetectorTask(0x0),
173   fDetectorFolder(new TString[kDetFolderLast+1])
174 {
175 // Constructor
176
177   //Main AliRoot Folder
178   if (fTopFolder == 0x0)
179    {
180      AliFatal("Can not create Top Alice Folder.");
181      return;//never reached
182    }
183   fTopFolder->SetOwner();
184   
185   fDetectorFolder[kDetFolderData] = fgkDataFolderName;
186   fDetectorFolder[kDetFolderCalibration] = fgkConditionsFolderName+"/"+fgkCalibrationFolderName;
187   fDetectorFolder[kDetFolderAligmnet] = fgkConditionsFolderName+"/"+fgkAligmentFolderName;
188   fDetectorFolder[kDetFolderQA] = fgkConditionsFolderName+"/"+fgkQAFolderName;
189   fDetectorFolder[kDetFolderLast] = "";
190   
191   gROOT->GetListOfBrowsables()->Add(fTopFolder, name);
192
193   //Constants folder
194   fConstFolder = fTopFolder->AddFolder (fgkConstantsFolderName, "Constant parameters");
195   fConstFolder->AddFolder("DatabasePDG", "PDG database");
196   
197   // Add the tasks to //Folders
198   
199   TTask * qa = new TTask(fgkQATaskName, "Alice QA tasks");
200   fTaskFolder->Add(qa); 
201   TTask * sd = new TTask(fgkSDigitizerTaskName, "Alice SDigitizer") ;
202   fTaskFolder->Add(sd); 
203   TTask * di = new TTask(fgkDigitizerTaskName, "Alice Digitizer") ;
204   fTaskFolder->Add(di); 
205   TTask * re = new TTask(fgkReconstructionerTaskName, "Alice Reconstructioner") ;
206   fTaskFolder->Add(re); 
207   TTask * tr = new TTask(fgkTrackerTaskName,"Alice Tracker");
208   fTaskFolder->Add(tr);
209   TTask * pid = new TTask(fgkPIDTaskName,"Alice Particle Identification Task");
210   fTaskFolder->Add(pid);
211   fDetectorTask    =  new TString[kDetTaskLast+1];
212   
213   fDetectorTask[kDetTaskQA] = fgkQATaskName;
214   fDetectorTask[kDetTaskSDigitizer] = fgkSDigitizerTaskName;
215   fDetectorTask[kDetTaskDigitizer] =  fgkDigitizerTaskName;
216   fDetectorTask[kDetTaskRecontructioner] = fgkReconstructionerTaskName;
217   fDetectorTask[kDetTaskTracker] = fgkTrackerTaskName;
218   fDetectorTask[kDetTaskPID] = fgkPIDTaskName;
219   fDetectorTask[kDetTaskLast] = "";
220
221   fgInstance=this;
222 }
223
224 //____________________________________________________________________________
225 AliConfig::~AliConfig()
226
227   // destructor
228   delete [] fDetectorFolder ;  
229   delete [] fDetectorTask;
230   if (fTopFolder)
231    {
232     fTopFolder->SetOwner();
233     delete fTopFolder; 
234    }
235 }
236 //____________________________________________________________________________
237
238 void AliConfig::AddInFolder (const char *dir, TObject *obj)
239 {
240   // Adds object "obj" to folder "dir"
241   TFolder *folder = dynamic_cast<TFolder *>(fTopFolder->FindObject(dir));
242   if (folder)
243     folder->Add (static_cast<TObject *>(obj));
244 }
245 //____________________________________________________________________________
246
247 Int_t AliConfig::AddSubTask(const char *taskname, const char* name,const char* title)
248 {
249 //Create new task named 'name' and titled 'title' 
250 //as a subtask of the task named 'taskname'
251
252    AliDebug(1, Form("Try to get folder named %s",taskname));
253    TObject* obj = fTopFolder->FindObject(taskname);
254    TTask * task = (obj)?dynamic_cast<TTask*>(obj):0x0;
255    if (task)
256      {
257       AliDebug(1, "          Got");
258       TTask * subtask = static_cast<TTask*>(task->GetListOfTasks()->FindObject(name));
259       if (!subtask) 
260         {
261           subtask = new TTask(name,title);
262           task->Add(subtask);
263         }
264       else
265        {
266          AliWarning(Form("Task named \"%s\" already exists in Task %s",name,taskname));
267        }
268      }
269    else
270      {
271        AliError(Form("Can not find task %s to put a new task in.",taskname));
272        return 1;
273      }
274   return 0;
275 }
276
277 //____________________________________________________________________________
278 TObject* AliConfig::FindInFolder (const char *dir, const char *name)
279 {
280   // Finds object with name "name" in folder "dir"
281   if(!name) return(fTopFolder->FindObject(name));
282   TFolder * folder = dynamic_cast<TFolder *>(fTopFolder->FindObject(dir));
283   if (!folder) return (NULL);
284   return(folder->FindObject(name));
285 }
286
287 //____________________________________________________________________________
288 void    AliConfig::Add (AliGenerator * obj,const char* eventfolder)
289 {
290   // Adds generator "obj" to the event folder "eventfolder"
291   TString path(eventfolder);
292   path = path + "/" + fgkGeneratorsFolderName;
293   AddInFolder(path,obj);
294 }
295
296 //____________________________________________________________________________
297 void AliConfig::Add (TVirtualMC * obj,const char* eventfolder)
298 {
299   // Adds TVirtualMC object to the event folder
300   TString path(eventfolder);
301   path = path + "/" + fgkMCFolderName;
302   AddInFolder(path, obj);
303 }
304
305 //____________________________________________________________________________
306 void  AliConfig::Add (TDatabasePDG * obj)
307 {
308   // Adds TDataBase object
309   AddInFolder(fgkPDGFolderName, obj);
310 }
311
312 //____________________________________________________________________________
313 void AliConfig::Add(AliModule* obj,const char* eventfolder)
314 {
315   // Adds module to the event folder
316   TString path(eventfolder);
317   path = path + "/" + fgkModuleFolderName;
318   AliDebug(1, Form("module name = %s, Ev. Fold. Name is %s.",
319                    obj->GetName(),eventfolder));
320   AddInFolder(path, obj);
321 }
322 //____________________________________________________________________________
323
324 Int_t AliConfig::AddDetector(TFolder* evntfolder, const char *name, const char* title)
325 {
326 //creates folders and tasks for the detector 'name'
327  Int_t retval;//returned value
328  retval = CreateDetectorFolders(evntfolder,name,title);
329  if (retval)
330   {
331     AliError(Form("CreateDetectorFolders returned error for detector %s",name));
332     return retval;
333   }
334  return 0; 
335 }
336 //____________________________________________________________________________
337
338 Int_t AliConfig::AddDetector(const char* evntfoldername,const char *name, const char* title)
339 {
340 //creates folders and tasks for the detector 'name'
341  Int_t retval;//returned value
342  retval = CreateDetectorFolders(evntfoldername,name,title);
343  if (retval)
344   {
345     AliError(Form("CreateDetectorFolders returned error for detector %s",name));
346     return retval;
347   }
348 // retval = CreateDetectorTasks(name,title);
349 // if (retval)
350 //  {
351 //    Error("AddDetector","CreateDetectorTasks returned error for detector %s",name);
352 //    return retval;
353 //  }
354  return 0; 
355 }
356 //____________________________________________________________________________
357
358 void  AliConfig::Add(AliDetector * obj,const char* eventfolder)
359 {
360   // Adds new AliDetector objest to the correspondent event folder
361   AliDebug(1, Form("detector name = %s, Ev. Fold. Name is %s.",
362                    obj->GetName(),eventfolder));
363
364   TObject* foundobj = GetTopFolder()->FindObject(eventfolder);
365   TFolder* evfolder = (foundobj)?dynamic_cast<TFolder*>(foundobj):0x0;
366   if (evfolder == 0x0)
367    {
368      AliFatal(Form("Can not find folder %s while adding detector %s",eventfolder,obj->GetName()));
369      return;
370    } 
371   CreateDetectorFolders(evfolder, obj->GetName(), obj->GetTitle());
372   
373 //  CreateDetectorTasks(obj->GetName(),obj->GetTitle());
374
375 }
376 //____________________________________________________________________________
377
378 Int_t  AliConfig::CreateDetectorFolders(const char* evntfoldername,const char *name, const char* title)
379 {
380 //creates a folders for detector named 'name' and titled 'title'
381 //in a event folder named 'evntfoldername'
382 //list of folder names where new folders are created is defined in fDetectorFolder array 
383 //detector folders are named 'name' and titled 'title' as well
384
385  TFolder* evfolder = dynamic_cast<TFolder*>(GetTopFolder()->FindObject(evntfoldername));
386  if (evfolder == 0x0)
387   {
388    AliError(Form("Can not find folder %s while adding detector %s",evntfoldername,name));
389    return 1;
390   }
391  return CreateDetectorFolders(evfolder,name,title);
392 }
393 //____________________________________________________________________________
394 Int_t  AliConfig::CreateDetectorFolders(TFolder* evntfolder,const char *name, const char* title)
395 {
396 //creates a folders for detector named 'name' and titled 'title'
397 //in a event folder 'evntfolder'
398 //list of folder names where new folders are created is defined in fDetectorFolder array 
399 //detector folders are named 'name' and titled 'title' as well
400 //Here we add only detector not an modules
401  
402  Int_t tmp;
403  Int_t i = 0;//iterator
404  while(!fDetectorFolder[i].IsNull())
405   {
406     tmp = AddSubFolder(evntfolder,fDetectorFolder[i],name,title);
407     if (tmp)
408      {
409       AliError(Form("Failed to create subfolder of %s for detector %s",fDetectorFolder[i].Data(),name));
410       return 1;
411      }
412     i++;
413   }
414  return 0;
415 }
416 //____________________________________________________________________________
417 Int_t AliConfig::CreateDetectorTasks(const char *name, const char* title)
418 {
419   // Creates new detector's task "name"
420    Int_t i = 0;
421    Int_t tmp;
422    while (i < kDetTaskLast)
423     {
424       tmp = AddSubTask(fgkTasksFolderName+"/"+fDetectorTask[i],
425                        name+fDetectorTask[i],(fDetectorTask[i]+" for ")+title);
426       if (tmp)
427        {
428          AliError(Form("Error occured while creating task for %s in %s.",
429                        name,fDetectorTask[i-1].Data()));
430          return 1;
431        }
432       i++;
433     }
434    return 0;
435 }
436
437 //____________________________________________________________________________
438 void    AliConfig::Add (char *list)
439 {
440   // Adds space separated list of objects to the
441   // configuration macro (?)
442   char *path;
443   
444   const char   *confPath = gSystem->Getenv ("ALICE_CONFIG_PATH");
445   if  (confPath) {
446     path = new char[strlen (confPath)];
447     strcpy (path, confPath);
448   } else {
449     const char   *alice = gSystem->Getenv ("ALICE_ROOT");
450     path = new char[strlen (alice) + 32];
451     
452     strcpy (path, ".:");
453     if (alice) {
454       strcat (path, alice);
455     }
456     strcat (path, "/macros/config");
457   }
458   
459   char   *token = strtok (path, ":");
460   
461   TList  *dirlist = new TList;
462   
463   while (token != NULL) 
464     {
465       dirlist->Add (new TObjString(token));
466       token = strtok (NULL, ":");
467     }
468   
469   token = strtok (list, " ");
470   
471   while (token != NULL)
472     { 
473       AliInfo(Form("Configuring token=%s",token));
474       
475       TObject *obj;
476       TIter   next (dirlist);
477       TString found = "\0";
478       
479       while ((obj = next ()))
480         {
481           TString dir(obj->GetName());
482           TString path  = dir + "/" + token;
483           TString macro = path + ".C";
484           if (!gSystem->AccessPathName (macro.Data()))  
485            {
486             gInterpreter->ExecuteMacro (macro.Data());                             
487             found = "(" + macro + ")";
488             if (macro.Contains("/")) 
489              {
490                TString dirname = gSystem->DirName(macro.Data());
491                TString macroConfigure = dirname + "/Configure.C";
492                if (!gSystem->AccessPathName (macroConfigure.Data()))
493                 {
494                   gInterpreter->ExecuteMacro (macroConfigure.Data());                               
495                   found += " => Configured";
496                 }                             
497              }
498             break;
499            } 
500           else 
501            {
502             TString macroDefault = path + "/Default.C";
503             if (!gSystem->AccessPathName (macroDefault.Data()))
504               {
505                 gInterpreter->ExecuteMacro (macroDefault.Data());
506                 found = "(" + macro + ")";
507                 TString macroConfigure = path + "/Configure.C";
508                 if (!gSystem->AccessPathName (macroConfigure.Data()))   
509                   {
510                     gInterpreter->ExecuteMacro (macroConfigure.Data());                             
511                     found += " => Configured";
512                   }
513                 break;                              
514               }
515            }
516         }
517       
518       if (strlen(found.Data())) 
519         {
520           AliInfo(Form("found=%s  => OK",found.Data()));
521         } 
522       else 
523         {
524           AliError(" => FAILED.");
525           exit(1); 
526         }           
527       
528       token = strtok (NULL," ");
529     }
530   
531   if (dirlist) delete dirlist;
532   
533 }
534
535 /*****************************************************************************/
536
537 TFolder* AliConfig::BuildEventFolder(const char* name,const char* title)
538 {
539 /*
540  creates the folder structure for one event
541  TopFolder_
542          | \
543          |  Tasks
544          |_
545          | \
546          |  Constants
547          |_
548          | \
549          |  Event_
550          |      | \
551          |      |  Modules(detector objects)
552          |      |_
553          |      | \              
554          |      |  Header
555          |      |_
556          |      | \              
557          |      |  Data_
558          |      |     | \ 
559          |      |     |  TPC_
560          |      |     |    | \
561          |      |     |    |  Hits(object;e.g. tree)
562          |      |     |    |_  
563          |      |     |    | \ 
564          |      |     |    |  SDigits(object)
565          |      |     |    |_
566          |      |     |    | \ 
567          |      |     |    |  Digits(object)
568          |      |     |    |_
569          |      |     |    | \ 
570          |      |     |    |  RecPoints(object)
571          |      |     |    |_
572          |      |     |      \ 
573          |      |     |       Tracks(object)
574          |      |     |_ 
575          |      |       \
576          |      |        ITS_
577          |      |          | \
578          |      |          |  Hits(object;e.g. tree)
579          |      |          |_  
580          |      |          | \ 
581          |      |          |  SDigits(object)
582          |      |          |_
583          |      |          | \ 
584          |      |          |  Digits(object)
585          |      |          |_
586          |      |          | \ 
587          |      |          |  RecPoints(object)
588          |      |          |_
589          |      |            \ 
590          |      |             Tracks(object)
591          |      |_         
592          |        \       
593          |         Configuration
594          |               
595          |_
596            \
597             Event2_  (to be merged with event)
598                 |  \
599                 |   Modules(detector objects)
600                 |_
601                 | \              
602                 |  Header
603                 |_
604                 | \              
605                 |  Data_
606                 |     | \ 
607                 |     |  TPC_
608                 |     |    | \
609                 |     |    |  Hits(object;e.g. tree)
610                 |     |    |_  
611                 |     |    | \ 
612                 |     |    |  SDigits(object)
613                 |     |    |_
614                 |     |    | \ 
615                 |     |    |  Digits(object)
616                 |     |    |_
617                 |     |    | \ 
618                 |     |    |  RecPoints(object)
619                 |     |    |_
620                 |     |      \ 
621                 |     |       Tracks(object)
622                 |     |_ 
623                 |       \
624                 |        ITS_
625                 |          | \
626                 |          |  Hits(object;e.g. tree)
627                 |          |_  
628                 |          | \ 
629                 |          |  SDigits(object)
630                 |          |_
631                 |          | \ 
632                 |          |  Digits(object)
633                 |          |_
634                 |          | \ 
635                 |          |  RecPoints(object)
636                 |          |_
637                 |            \ 
638                 |             Tracks(object)
639                 |_         
640                   \       
641                    Configuration
642                          
643 */
644   TFolder* eventfolder = fTopFolder->AddFolder(name,title); 
645    
646   //modules
647   eventfolder->AddFolder(fgkModuleFolderName, "Detector objects");
648   //event data
649   eventfolder->AddFolder(fgkDataFolderName, "Detector data");
650   
651     //Conditions
652   TFolder *conditions = eventfolder->AddFolder(fgkConditionsFolderName, "Run conditions");
653   conditions->AddFolder(fgkCalibrationFolderName,"Detector calibration data");
654   conditions->AddFolder(fgkAligmentFolderName,"Detector aligment");
655   conditions->AddFolder(fgkQAFolderName,"Quality Asurance Output"); //Folder with output of the QA task(s)
656   //Configuration
657   TFolder *configuration = eventfolder->AddFolder(fgkConfigurationFolderName, "Run configuration");
658   configuration->AddFolder(fgkFieldFolderName, "Magnetic field maps");
659   configuration->AddFolder(fgkGeneratorsFolderName,"list of generator objects");
660   configuration->AddFolder(fgkVirtualMCFolderName,"the Virtual MC");
661
662   eventfolder->AddFolder(fgkHeaderFolderName,"MonteCarlo event header");
663
664   eventfolder->SetOwner();
665
666   return eventfolder;
667 }
668
669 /*****************************************************************************/
670
671 TString AliConfig::GetQATaskName() const
672  {
673  //returns task name
674   return fDetectorTask[kDetTaskQA];
675  }
676 /*****************************************************************************/
677  
678 TString AliConfig::GetDigitizerTaskName() const
679  {
680  //returns task name
681   return fDetectorTask[kDetTaskDigitizer];
682  }
683 /*****************************************************************************/
684  
685 TString AliConfig::GetSDigitizerTaskName() const
686  {
687  //returns task name
688   return fDetectorTask[kDetTaskSDigitizer];
689  }
690 /*****************************************************************************/
691
692 TString AliConfig::GetReconstructionerTaskName() const
693  {
694  //returns task name
695   return fDetectorTask[kDetTaskRecontructioner];
696  }
697 /*****************************************************************************/
698
699 TString AliConfig::GetTrackerTaskName() const
700  {
701  //returns task name
702   return fDetectorTask[kDetTaskTracker];
703  }
704 /*****************************************************************************/
705
706 TString AliConfig::GetPIDTaskName() const
707  {
708  //returns task name
709   return fDetectorTask[kDetTaskPID];
710  }
711 /*****************************************************************************/
712
713 const TString& AliConfig::GetQAFolderName() const
714 {
715 //returns pathname of folder with QA output relative to Top Alice Folder
716   return fDetectorFolder[kDetFolderQA];
717 }
718 /*****************************************************************************/
719
720 const TString& AliConfig::GetDataFolderName() const
721 {
722 //returns name of data folder path relative to event folder
723  return fgkDataFolderName;
724 }
725 /*****************************************************************************/
726
727 Int_t AliConfig::AddSubFolder(TFolder* topfolder, const char* infoler, 
728                      const char* newfoldname, const char* newfoldtitle)
729 {
730 //helper method
731 //in topfolder looks for folder named 'infolder'
732 //and if it exist it creates inside a new folder named 'newfoldname' and titled 'newfoldtitle'
733
734  if (topfolder == 0x0)//check if exists top folder
735   {
736    AliError("Parameter TFolder* points to NULL.");
737    return 1;
738   }
739  
740  TObject *obj;
741  TFolder* folder;
742  
743  folder = dynamic_cast<TFolder*>(topfolder->FindObject(infoler));
744  if (folder == 0x0) //check if we got inolder
745   {
746    AliError(Form("Can not find folder %s in folder %s.",infoler,topfolder->GetName()));
747    return 1;
748   }
749  obj = folder->FindObject(newfoldname); //see if such a subfolder already exists
750  if (obj == 0x0) //nope
751   {
752    TFolder *newfolder = folder->AddFolder(newfoldname,newfoldtitle);//add the desired subfolder
753    if (newfolder == 0x0) //check if we managed
754     {
755      AliError(Form("Can not create folder %s in folder %s",newfoldname,infoler));
756      return 2;
757     }
758    else return 0;//success
759   }
760  //such an object already exists
761  TFolder* fol = dynamic_cast<TFolder*>(obj);
762  if (fol == 0x0)
763    {
764      AliError(Form("Object named %s already exists in folder %s AND IT IS NOT A FOLDER",newfoldname,infoler));
765      return 3;
766    }
767  AliWarning(Form("Folder named %s already exists in folder %s",newfoldname,infoler));
768  return 0;
769 }