disable doxygen latex output
[u/mrichter/AliRoot.git] / RALICE / AliJob.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 ///////////////////////////////////////////////////////////////////////////
19 // Class AliJob
20 // Base class for the top level processor class in a task based procedure.
21 // It allows stepwise invokation of various sub-tasks by the derived
22 // (user defined) top level processor, based on looping over a certain
23 // main object structure (e.g. AliEvent for event-by-event processing).
24 // The main object structure (if needed) may be specified by the derived
25 // top level processor class and will be stored automatically in the
26 // working environment (see below).
27 //
28 // However, being designed as a base class for a user defined top level
29 // processor, this class can also be used as a "hook" to specify
30 // various sub-tasks in an (interactive) user environment.
31 // Usage of the memberfunction ProcessObject() allows an (interactive)
32 // event-by-event processing of the various specified subtasks.  
33 //
34 // This base class provides a working environment for the derived
35 // (user defined) processor class and all of its subtasks.
36 //
37 // The default working environment consists of :
38 //
39 // * An array containing pointers to the objects which are stored
40 //   via the AddObject() facility of this AliJob class.
41 //   From this storage the objects can be directly accessed via the
42 //   GetObject() and GetObjects() memberfunctions.
43 // * A pointer to the main object structure during job processing.
44 //   This pointer can be initiated/updated only by the derived top level
45 //   processor via the SetMainObject() facility but all sub-tasks can access
46 //   it via the above array facilities or the GetMainObject() memberfunction.
47 //   The latter provides faster access to the main object structure than
48 //   the GetObject (search) based procedures.
49 //
50 // Optionally one may invoke the MakeFolder() memberfunction or use the
51 // "mode" argument of ExecuteJob (see below) to provide in addition to the above
52 // the following job-specific folder structure :
53 //
54 // * A folder which may serve as a whiteboard for transferring pointers to
55 //   objects which are posted there by the top level processor or any
56 //   of its subtasks.
57 //   Objects can be posted in the job folder via the AddObject() facility
58 //   of this AliJob class.
59 //   Access to the job folder is obtained via the GetFolder() memberfunction
60 //   and from this the various objects can be accessed via the usual TFolder
61 //   FindObject and/or iterator facilities.
62 //
63 // Notes :
64 // -------
65 // 1) This AliJob class is derived from TTask, which implies that every
66 //    (user defined) top level processor class is itself also a TTask.
67 //    This allows sub-tasks to be introduced to the top level processor
68 //    using the standard TTask facilities.
69 //
70 // 2) Only references to the various introduced objects are stored.
71 //    It is the user's responsibility to delete all introduced objects,
72 //    either in the Exec() or destructor of the derived top level processor class
73 //    or via Clear() facility as provided by the TTask machinery.
74 //
75 // 3) The top level processor instance is entered into the standard ROOT
76 //    ListOfTasks under the name which was provided by the user in the
77 //    constructor of the top level processor.
78 //    The name of the top level processor is passed automatically as the
79 //    opt argument to the Exec(Option_t* opt) memberfunctions of the 
80 //    various sub-tasks by the ExecuteJob() memberfunction (see below).
81 //    This allows all sub-tasks to obtain the pointer to the top level
82 //    processor instance from its name via the statement :
83 //
84 //      AliJob* parent=(AliJob*)gROOT->GetListOfTasks()->FindObject(opt)
85 //
86 // 4) If selected, the job-specific folder will be created in the generic folder
87 //    called "AliJob-folders" as a sub-folder under the same name as the one
88 //    introduced in the constructor of the derived top level processor class.
89 //    The folder will only be created if the MakeFolder() member function has been
90 //    invoked or when selected explicitly by the "mode" argument of ExecuteJob().
91 //    Actual creation of the folder environment (and internal array storage as well)
92 //    only takes place when the first object is posted via the AddObject()
93 //    or SetMainObject() facilities.
94 //
95 // Execution of the (user defined) top level processor has to be invoked via
96 // the memberfunction ExecuteJob() of this AliJob base class.
97 // This will set the default gROOT as the global working directory and then
98 // invoke the (user written) Exec() memberfunction of the top level
99 // processor class with as argument the name of the top level processor instance
100 // as specified by the user in the top level processor constructor.
101 // This will allow stepwise (e.g. event-by-event) execution of the various sub-tasks.
102 // In addition the "mode" argument of ExecuteJob() may be used to select/overrule
103 // creation of the folder environment for the complete job.
104 // See the docs of ExecuteJob() for further details.
105 //
106 // It is the user's responsibility to invoke the sub-tasks via the
107 // ExecuteTasks() statement at the appropriate location in the top level
108 // processor class if auto-execution was not explicitly selected via the
109 // "mode" argument of the ExecuteJob() memberfunction.
110 //
111 //--- Author: Nick van Eijndhoven 07-may-2005 Utrecht University
112 //- Modified: NvE $Date$ Utrecht University
113 ///////////////////////////////////////////////////////////////////////////
114  
115 #include "AliJob.h"
116 #include "Riostream.h"
117
118 ClassImp(AliJob) // Class implementation to enable ROOT I/O
119
120 AliJob::AliJob(const char* name,const char* title) : TTask(name,title)
121 {
122 // Default constructor.
123 // Initialise the working environment for general data access
124 // by the derived task and its subtasks.
125
126  fMakefolder=0;
127  fMainObject=0;
128  fFolder=0;
129  fObjects=0;
130  fSelect=0;
131
132  // Introduce this AliJob based instance into the ROOT task list
133  TSeqCollection* tasks=gROOT->GetListOfTasks();
134  if (tasks) tasks->Add(this);
135 }
136 ///////////////////////////////////////////////////////////////////////////
137 AliJob::~AliJob()
138 {
139 // Default destructor.
140 // The internal array and job specific folder (if any) holding the various
141 // references are deleted.
142 // Note : The objects belonging to the various pointers in the array/folder
143 //        and the main processing object are NOT deleted by this base class.
144
145  // Remove this AliJob based instance into the ROOT task list
146  TSeqCollection* tasks=gROOT->GetListOfTasks();
147  if (tasks) tasks->Remove(this);
148
149  if (fObjects)
150  {
151   delete fObjects;
152   fObjects=0;
153  }
154  if (fFolder)
155  {
156   TList* list=gROOT->GetListOfBrowsables();
157   if (list)
158   {
159    TFolder* top=(TFolder*)list->FindObject("AliJob-folders");
160    if (top) RecursiveRemove(fFolder);
161   }
162   delete fFolder;
163   fFolder=0;
164  }
165  if (fSelect)
166  {
167   delete fSelect;
168   fSelect=0;
169  }
170 }
171 ///////////////////////////////////////////////////////////////////////////
172 void AliJob::ListEnvironment()
173 {
174 // Provide listing of the job environment. 
175
176  cout << " ***" << endl;
177  cout << " *** Environment of job " << GetName() << " ***" << endl;
178  cout << " ***" << endl;
179  cout << " === Available (sub)tasks : " << endl;
180  ls();
181  if (fFolder)
182  {
183   cout << " === Current job-folder contents : " << endl;
184   fFolder->ls();
185  }
186  cout << endl;
187 }
188 ///////////////////////////////////////////////////////////////////////////
189 void AliJob::ExecuteJob(Int_t mode)
190 {
191 // Invokation of the top level processor via its Exec() memberfunction.
192 // The input argument "mode" can be used to explicitly specify the
193 // (de)selection of the folder environment creation and automatic
194 // invokation of all subtasks after execution of the top level
195 // Exec() memberfunction.
196 // The latter is convenient if an AliJob instance is used directly
197 // by the user (e.g. in a ROOT macro) in order to provide a hook
198 // for event-by-event processing of various subtasks.
199 // An even more convenient alternative to achieve this is invokation of the
200 // memberfunction ProcessObject().  
201 //
202 // mode = -1 : Explicitly prohibit folder creation for the complete job
203 //         0 : Folder creation selection steered by MakeFolder()
204 //         1 : Explicitly select creation of the folder environment
205 //             for the complete job.
206 //       -11 : Same as mode=-1 but also auto-execution of subtasks after Exec()
207 //        10 : Same as mode=0 but also auto-execution of subtasks after Exec()
208 //        11 : Same as mode=1 but also auto-execution of subtasks after Exec()
209 //
210 // The default is mode=0.
211 //
212 // Note : Before execution gROOT is set as the global working directory.
213
214  if (mode<0) fMakefolder=-1;
215  if (mode==1 || mode==11) fMakefolder=1;
216
217  gROOT->cd(); 
218  Exec(GetName());
219
220  if (abs(mode)>9)
221  {
222   CleanTasks();
223   ExecuteTasks(GetName());
224  }
225 }
226 ///////////////////////////////////////////////////////////////////////////
227 void AliJob::MakeFolder()
228 {
229 // Select creation of the folder structure in addition to the internal
230 // array storage of objects.
231 // Creation of the folder structure is only activated if it was not
232 // explicitly forbidden by the specified "mode" on invokation of the
233 // ExecuteJob() memberfunction.
234
235  if (!fMakefolder) fMakefolder=1;
236 }
237 ///////////////////////////////////////////////////////////////////////////
238 TFolder* AliJob::GetFolder() const
239 {
240 // Provide pointer to the whiteboard folder.
241  return fFolder;
242 }
243 ///////////////////////////////////////////////////////////////////////////
244 TObject* AliJob::GetMainObject() const
245 {
246 // Provide pointer to the main object structure.
247  return fMainObject;
248 }
249 ///////////////////////////////////////////////////////////////////////////
250 void AliJob::SetMainObject(TObject* obj)
251 {
252 // Store pointer to the main object structure.
253  if (obj)
254  {
255   fMainObject=obj;
256   AddObject(obj);
257  }
258 }
259 ///////////////////////////////////////////////////////////////////////////
260 void AliJob::AddObject(TObject* obj)
261 {
262 // Store pointer of specified object in the working environment.
263
264  if (!obj) return;
265
266  if (!fObjects) fObjects=new TObjArray();
267
268  if (fMakefolder>0 && !fFolder)
269  {
270   // Create the top level environment folder for all AliJobs if needed 
271   TList* list=gROOT->GetListOfBrowsables();
272   if (list)
273   {
274    TFolder* top=(TFolder*)list->FindObject("AliJob-folders");
275    if (!top)
276    {
277     top=new TFolder("AliJob-folders","Environment for all AliJob derived tasks");
278     list->Add(top,"AliJob-folders");
279    }
280    // Create the task-specific folder as a sub-folder in the top folder 
281    fFolder=top->AddFolder(GetName(),GetTitle());
282   }
283  }
284
285  // Add object pointer to array and folder if it doesn't already exist 
286  Int_t exist=0;
287  for (Int_t i=0; i<fObjects->GetEntries(); i++)
288  {
289   if (obj==fObjects->At(i))
290   {
291    exist=1;
292    break;
293   }
294  }
295  if (!exist)
296  {
297   fObjects->Add(obj);
298   if (fFolder) fFolder->Add(obj);
299  }
300 }
301 ///////////////////////////////////////////////////////////////////////////
302 void AliJob::AddObjects(TObjArray* arr)
303 {
304 // Store pointers of all the array objects individually in the working environment.
305
306  if (!arr) return;
307
308  TObject* obj=0;
309  for (Int_t i=0; i<arr->GetSize(); i++)
310  {
311   obj=arr->At(i);
312   if (obj) AddObject(obj);
313  }
314 }
315 ///////////////////////////////////////////////////////////////////////////
316 void AliJob::RemoveObject(TObject* obj)
317 {
318 // Remove pointer of specified object from the working environment.
319 // In case the specified object is also the main object, the main object
320 // pointer will be set to 0 as well.
321
322  if (!obj) return;
323
324  if (fObjects)
325  {
326   TObject* test=fObjects->Remove(obj);
327   if (test)
328   {
329    fObjects->Compress();
330    if (test==fMainObject) fMainObject=0;
331   }
332  }
333
334  if (fFolder) fFolder->Remove(obj);
335 }
336 ///////////////////////////////////////////////////////////////////////////
337 void AliJob::RemoveObjects(const char* classname)
338 {
339 // Remove all stored objects inheriting from classname.
340 // In case one of the removed objects is also the main object, the main object
341 // pointer will be set to 0 as well.
342
343  if (!fObjects) return;
344
345  Int_t remove=0;
346  for (Int_t i=0; i<fObjects->GetEntries(); i++)
347  {
348   TObject* obj=fObjects->At(i);
349   if (obj->InheritsFrom(classname))
350   {
351    TObject* test=fObjects->Remove(obj);
352    if (test)
353    {
354     remove=1;
355     if (test==fMainObject) fMainObject=0;
356    }
357    if (fFolder) fFolder->Remove(obj);
358   }
359  }
360  if (remove) fObjects->Compress();
361 }
362 ///////////////////////////////////////////////////////////////////////////
363 TObject* AliJob::GetObject(Int_t j) const
364 {
365 // Provide pointer to j-th stored object.
366 // Note : j=1 indicates the first object.
367
368  if (!fObjects || j<1) return 0;
369
370  TObject* obj=0;
371
372  if (j<=fObjects->GetEntries()) obj=fObjects->At(j-1);
373  return obj;
374 }
375 ///////////////////////////////////////////////////////////////////////////
376 TObject* AliJob::GetObject(const char* classname) const
377 {
378 // Provide pointer to the first stored object which inherits from classname.
379
380  if (!fObjects) return 0;
381
382  TObject* obj=0;
383  for (Int_t i=0; i<fObjects->GetEntries(); i++)
384  {
385   TObject* obx=fObjects->At(i);
386   if (obx->InheritsFrom(classname))
387   {
388    obj=obx;
389    break;
390   }
391  }
392  return obj;
393 }
394 ///////////////////////////////////////////////////////////////////////////
395 TObjArray* AliJob::GetObjects() const
396 {
397 // Provide pointers of all the stored objects.
398  return fObjects;
399 }
400 ///////////////////////////////////////////////////////////////////////////
401 TObjArray* AliJob::GetObjects(const char* classname)
402 {
403 // Provide pointers to all stored objects inheriting from classname.
404
405  if (!fObjects) return 0;
406
407  if (fSelect)
408  {
409   fSelect->Clear();
410  }
411  else
412  {
413   fSelect=new TObjArray();
414  }
415
416  for (Int_t i=0; i<fObjects->GetEntries(); i++)
417  {
418   TObject* obj=fObjects->At(i);
419   if (obj->InheritsFrom(classname)) fSelect->Add(obj);
420  }
421  return fSelect;
422 }
423 ///////////////////////////////////////////////////////////////////////////
424 void AliJob::ProcessObject(TObject* obj)
425 {
426 // Invokation of all user defined sub-tasks for the specified object.
427 // This facility is very convenient when performing a task based
428 // event-by-event analysis in an (interactive) user application.
429 //
430 // Note :
431 // ------
432 // Before processing gROOT is set as the global working directory.
433 // The specified object will be added to the job's object list
434 // as main object before the processing starts.
435 // This will allow the various sub-tasks to access the object in the
436 // usual way.
437 // After the processing of this object has been performed, the object
438 // will be removed from the object list and the main object pointer will
439 // be set to zero.
440
441  if (!obj) return;
442
443  SetMainObject(obj);
444
445  gROOT->cd(); 
446  CleanTasks();
447  ExecuteTasks(GetName());
448
449  RemoveObject(obj);
450 }
451 ///////////////////////////////////////////////////////////////////////////