Removed the AliHLTPHOSValidCellDataStruct.h from Makefile.am
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisTask.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 // Author: Andrei Gheata, 31/05/2006
18
19 //==============================================================================
20 //   AliAnalysysTask - Class representing a basic analysis task. Any
21 // user-defined task should derive from it and implement the Exec() virtual
22 // method.
23 //==============================================================================
24 //
25 // A specific user analysis task have to derive from this class. The list of
26 // specific input and output slots have to be defined in the derived class ctor:
27 //
28 //   UserTask::UserTask(name, title)
29 //   {
30 //      DefineInput(0, TTree::Class());
31 //      DefineInput(1, TH1::Class());
32 //      ...
33 //      DefineOutput(0, TTree::Class());
34 //      DefineOutput(1, MyObject::Class());
35 //      ...
36 //   }
37 //
38 // An existing data contaner (AliAnalysisDataContainer) can be connected to the
39 // input/output slots of an analysis task. Containers should not be defined and
40 // connected by the derived analysis task, but from the level of AliAnalysisManager:
41 //
42 //   AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
43 //                                   AliAnalysisDataContainer *cont)
44 //   AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
45 //                                    AliAnalysisDataContainer *cont)
46 // To connect a slot to a data container, the data types declared by both must
47 // match.
48 //
49 // The method Init will be called once per session at the moment when the data is
50 // available at all input slots. 
51 // The method Init() has to be overloaded by the derived class in order to:
52 // 1. Define objects that should be created only once per session (e.g. output
53 //    histograms)
54 // 2. Set the branch address or connect to a branch address in case the input
55 //    slots are connected to trees.
56 //
57 // Example:
58 // MyAnalysisTask::Init(Option_t *)
59 // {
60 //    if (!fHist1) fHist1 = new TH1F("h1", ....);
61 //    if (!fHist2) fHist2 = new TH1F("h2", ....);
62 //    fESD = GetBranchAddress(islot=0, "ESD");
63 //    if (!fESD) SetBranchAddress(islot=0, "ESD", &fESD);
64 // }
65 //
66 // The method Terminate() will be called by the framework once at the end of
67 // data processing. Overload this if needed.
68 //
69 //==============================================================================
70
71 #include "Riostream.h"
72
73 #include "TClass.h"
74
75 //#include "AliLog.h"
76 #include "AliAnalysisTask.h"
77 #include "AliAnalysisDataSlot.h"
78 #include "AliAnalysisDataContainer.h"
79
80 ClassImp(AliAnalysisTask)
81
82 //______________________________________________________________________________
83 AliAnalysisTask::AliAnalysisTask()
84                 :fReady(kFALSE),
85                  fInitialized(kFALSE),
86                  fNinputs(0),
87                  fNoutputs(0),
88                  fOutputReady(NULL),
89                  fPublishedData(NULL),
90                  fInputs(NULL),
91                  fOutputs(NULL)
92 {
93 // Default constructor.
94 }
95
96 //______________________________________________________________________________
97 AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
98                 :TTask(name,title),
99                  fReady(kFALSE),
100                  fInitialized(kFALSE),
101                  fNinputs(0),
102                  fNoutputs(0),
103                  fOutputReady(NULL),
104                  fPublishedData(NULL),
105                  fInputs(NULL),
106                  fOutputs(NULL)                 
107 {
108 // Constructor.
109    fInputs      = new TObjArray(2);
110    fOutputs     = new TObjArray(2);
111 }
112
113 //______________________________________________________________________________
114 AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task)
115                 :TTask(task),
116                  fReady(task.fReady),
117                  fInitialized(task.fInitialized),
118                  fNinputs(task.fNinputs),
119                  fNoutputs(task.fNoutputs),                 
120                  fOutputReady(NULL),
121                  fPublishedData(NULL),
122                  fInputs(NULL),
123                  fOutputs(NULL)                 
124 {
125 // Copy ctor.
126    fInputs      = new TObjArray((fNinputs)?fNinputs:2);
127    fOutputs     = new TObjArray((fNoutputs)?fNoutputs:2);
128    fPublishedData = 0;
129    Int_t i;
130    for (i=0; i<fNinputs; i++) fInputs->AddAt(task.GetInputSlot(i),i);
131    fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
132    for (i=0; i<fNoutputs; i++) {
133       fOutputReady[i] = IsOutputReady(i);
134       fOutputs->AddAt(task.GetOutputSlot(i),i);
135    }   
136 }
137
138 //______________________________________________________________________________
139 AliAnalysisTask::~AliAnalysisTask()
140 {
141 // Dtor.
142    if (fInputs)  {fInputs->Delete(); delete fInputs;}
143    if (fOutputs) {fOutputs->Delete(); delete fOutputs;}
144 }   
145   
146 //______________________________________________________________________________
147 AliAnalysisTask& AliAnalysisTask::operator=(const AliAnalysisTask& task)
148 {
149 // Assignment
150    if (&task == this) return *this;
151    TTask::operator=(task);
152    fReady       = task.IsReady();
153    fInitialized = task.IsInitialized();
154    fNinputs     = task.GetNinputs();
155    fNoutputs    = task.GetNoutputs();
156    fInputs      = new TObjArray((fNinputs)?fNinputs:2);
157    fOutputs     = new TObjArray((fNoutputs)?fNoutputs:2);
158    fPublishedData = 0;
159    Int_t i;
160    for (i=0; i<fNinputs; i++) fInputs->AddAt(new AliAnalysisDataSlot(*task.GetInputSlot(i)),i);
161    fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
162    for (i=0; i<fNoutputs; i++) {
163       fOutputReady[i] = IsOutputReady(i);
164       fOutputs->AddAt(new AliAnalysisDataSlot(*task.GetOutputSlot(i)),i);
165    }         
166    return *this;
167 }
168
169 //______________________________________________________________________________
170 Bool_t AliAnalysisTask::AreSlotsConnected()
171 {
172 // Check if all input/output slots are connected. If this is the case fReady=true
173    fReady = kFALSE;
174    if (!fNinputs || !fNoutputs) return kFALSE;
175    Int_t i;
176    AliAnalysisDataSlot *slot;
177    for (i=0; i<fNinputs; i++) {
178       slot = (AliAnalysisDataSlot*)fInputs->At(i);
179       if (!slot) {
180         cout<<"Input slot "<<i<<" of task "<<GetName()<<" not defined !"<<endl;
181         //AliError(Form("Input slot %i of task %s not defined !",i,GetName()));
182          return kFALSE;
183       }   
184       if (!slot->IsConnected()) return kFALSE;
185    }   
186    for (i=0; i<fNoutputs; i++) {
187       slot = (AliAnalysisDataSlot*)fOutputs->At(i);
188       if (!slot) {
189         cout<<"Output slot "<<i<<" of task "<<GetName()<<" not defined !"<<endl;
190         //AliError(Form("Output slot %i of task %s not defined !",i,GetName()));
191          return kFALSE;
192       }   
193       if (!slot->IsConnected()) return kFALSE;
194    } 
195    fReady = kTRUE;  
196    return kTRUE;
197 }
198
199 //______________________________________________________________________________
200 void AliAnalysisTask::CheckNotify(Bool_t init)
201 {
202 // Check if data is available from all inputs. Change the status of the task
203 // accordingly. This method is called automatically for all tasks connected
204 // to a container where the data was published.
205    if (init) fInitialized = kFALSE;
206    for (Int_t islot=0; islot<fNinputs; islot++) {
207       if (!GetInputData(islot)) {
208          SetActive(kFALSE);
209          return;
210       }   
211    }   
212    SetActive(kTRUE);
213    if (fInitialized) return;
214    TDirectory *cursav = gDirectory;
215    Init();
216    if (cursav) cursav->cd();
217    fInitialized = kTRUE;
218 }
219
220 //______________________________________________________________________________
221 Bool_t AliAnalysisTask::ConnectInput(Int_t islot, AliAnalysisDataContainer *cont)
222 {
223 // Connect an input slot to a data container.
224    AliAnalysisDataSlot *input = GetInputSlot(islot);
225    if (!input) {
226      cout<<"Input slot "<<islot<<" not defined for analysis task "<<GetName()<<endl;
227      //AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
228       return kFALSE;
229    }
230    // Check type matching          
231    if (!input->GetType()->InheritsFrom(cont->GetType())) {
232      cout<<"Data type "<<input->GetType()->GetName()<<" for input "<<islot<<" of task "<<GetName()<<" not matching container "<<cont->GetName()<<" of type "<<cont->GetType()->GetName()<<endl;
233      //AliError(Form("Data type %s for input %i of task %s not matching container %s of type %s",input->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName()));
234       return kFALSE;
235    }  
236    // Connect the slot to the container as input          
237    if (!input->ConnectContainer(cont)) return kFALSE;
238    // Add this to the list of container consumers
239    cont->AddConsumer(this, islot);
240    AreSlotsConnected();
241    return kTRUE;
242 }   
243
244 //______________________________________________________________________________
245 Bool_t AliAnalysisTask::ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont)
246 {
247 // Connect an output slot to a data container.
248    AliAnalysisDataSlot *output = GetOutputSlot(islot);
249    if (!output) {
250      cout<<"Output slot "<<islot<<" not defined for analysis task "<<GetName()<<endl;
251      //AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName()));
252       return kFALSE;
253    }
254    // Check type matching          
255    if (!output->GetType()->InheritsFrom(cont->GetType())) {
256      cout<<"Data type "<<output->GetType()->GetName()<<" for output "<<islot<<" of task "<<GetName()<<" not matching container "<<cont->GetName()<<" of type "<<cont->GetType()->GetName()<<endl;
257      //AliError(Form("Data type %s for output %i of task %s not matching container %s of type %s",output->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName()));
258       return kFALSE;
259    }            
260    // Connect the slot to the container as output         
261    if (!output->ConnectContainer(cont)) return kFALSE;
262    // Declare this as the data producer
263    cont->SetProducer(this, islot);
264    AreSlotsConnected();
265    return kTRUE;
266 }   
267
268 //______________________________________________________________________________
269 void AliAnalysisTask::DefineInput(Int_t islot, TClass *type)
270 {
271 // Define an input slot and its type.
272    AliAnalysisDataSlot *input = new AliAnalysisDataSlot(type, this);
273    if (fNinputs<islot+1) fNinputs = islot+1;
274    fInputs->AddAtAndExpand(input, islot);
275 }
276
277 //______________________________________________________________________________
278 void AliAnalysisTask::DefineOutput(Int_t islot, TClass *type)
279 {
280 // Define an output slot and its type.
281    if (islot<0) {
282      cout<<"Cannot define negative output slot number for task "<<GetName()<<endl;
283      //AliError(Form("Cannot define negative output slot number for task %s", GetName()));
284       return;
285    }   
286    AliAnalysisDataSlot *output = new AliAnalysisDataSlot(type, this);
287    if (fNoutputs<islot+1) {
288       fNoutputs = islot+1;
289       if (fOutputReady) delete [] fOutputReady;
290       fOutputReady = new Bool_t[fNoutputs];
291       memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
292    } 
293    fOutputs->AddAtAndExpand(output, islot);
294 }
295
296 //______________________________________________________________________________
297 TClass *AliAnalysisTask::GetInputType(Int_t islot) const
298 {
299 // Retreive type of a given input slot.
300    AliAnalysisDataSlot *input = GetInputSlot(islot);
301    if (!input) {
302      cout<<"Input slot "<<islot<<" not defined for analysis task "<<GetName()<<endl;
303      //AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
304       return NULL;
305    }
306    return (input->GetType());
307 }
308
309 //______________________________________________________________________________
310 TClass *AliAnalysisTask::GetOutputType(Int_t islot) const
311 {
312 // Retreive type of a given output slot.
313    AliAnalysisDataSlot *output = GetOutputSlot(islot);
314    if (!output) {
315      cout<<"Output slot "<<islot<<" not defined for analysis task "<<GetName()<<endl;
316      //AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName()));
317       return NULL;
318    }
319    return (output->GetType());
320 }
321
322 //______________________________________________________________________________
323 TObject *AliAnalysisTask::GetInputData(Int_t islot) const
324 {
325 // Retreive input data for a slot if ready. Normally called by Exec() and
326 // the object has to be statically cast to the appropriate type.
327    AliAnalysisDataSlot *input = GetInputSlot(islot);
328    if (!input) {
329      cout<<"Input slot "<<islot<<" not defined for analysis task "<<GetName()<<endl;
330      //AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
331       return NULL;
332    }
333    return (input->GetData()); 
334 }
335
336 //______________________________________________________________________________
337 char *AliAnalysisTask::GetBranchAddress(Int_t islot, const char *branch) const
338 {
339 // Check if a branch with a given name from the specified input is connected
340 // to some address. Call this in Init() before trying to call SetBranchAddress()
341 // since the adress may be set by other task.
342    return (char *)GetInputSlot(islot)->GetBranchAddress(branch);
343 }
344
345 //______________________________________________________________________________
346 Bool_t AliAnalysisTask::SetBranchAddress(Int_t islot, const char *branch, void *address) const
347 {
348 // Connect an object address to a branch of the specified input.
349    return GetInputSlot(islot)->SetBranchAddress(branch, address);
350 }   
351
352 //______________________________________________________________________________
353 void AliAnalysisTask::Init(Option_t *)
354 {
355 // Branch address initialization.
356 }
357
358 //______________________________________________________________________________
359 void AliAnalysisTask::Terminate(Option_t *)
360 {
361 // Method called by the framework at the end of data processing.
362 }
363
364 //______________________________________________________________________________
365 void AliAnalysisTask::OpenFile(Int_t iout, const char *name, Option_t *option) const
366 {
367 // Set data at output iout to be written in the specified file.
368    GetOutputSlot(iout)->GetContainer()->OpenFile(name, option);
369 }   
370
371 //______________________________________________________________________________
372 Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option)
373 {
374 // Post output data for a given ouput slot in the corresponding data container.
375 // Published data becomes owned by the data container.
376 // If option is specified, the container connected to the output slot must have
377 // an associated file name defined. The option represents the method to open the file.
378    fPublishedData = 0;
379    AliAnalysisDataSlot *output = GetOutputSlot(iout);
380    if (!output) {
381      cout<<"Output slot "<<iout<<" not defined for analysis task "<<GetName()<<endl;
382      //AliError(Form("Output slot %i not defined for analysis task %s", iout, GetName()));
383       return kFALSE;
384    }
385    if (!output->IsConnected()) {
386      cout<<"Output slot "<<iout<<" of analysis task "<<GetName()<<" not connected to any data container"<<endl;
387      //AliError(Form("Output slot %i of analysis task %s not connected to any data container", iout, GetName()));
388       return kFALSE;
389    }
390    if (!fOutputReady) {
391       fOutputReady = new Bool_t[fNoutputs];
392       memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
393    }   
394    fOutputReady[iout] = kTRUE;
395    fPublishedData = data;
396    return (output->GetContainer()->SetData(data, option));
397 }
398
399 //______________________________________________________________________________
400 void AliAnalysisTask::SetUsed(Bool_t flag)
401 {
402 // Set 'used' flag recursively to task and all daughter tasks.
403    if (TestBit(kTaskUsed)==flag) return;
404    TObject::SetBit(kTaskUsed,flag);
405    Int_t nd = fTasks->GetSize();
406    AliAnalysisTask *task;
407    for (Int_t i=0; i<nd; i++) {
408       task = (AliAnalysisTask*)fTasks->At(i);
409       task->SetUsed(flag);
410    }
411 }   
412
413 //______________________________________________________________________________
414 Bool_t AliAnalysisTask::CheckCircularDeps()
415 {
416 // Check for illegal circular dependencies, e.g. a daughter task should not have
417 // a hierarchical parent as subtask.
418    if (IsChecked()) return kTRUE;
419    SetChecked();
420    TList *tasks = GetListOfTasks();
421    Int_t ntasks = tasks->GetSize();
422    AliAnalysisTask *task;
423    for (Int_t i=0; i<ntasks; i++) {
424       task = (AliAnalysisTask*)tasks->At(i);
425       if (task->CheckCircularDeps()) return kTRUE;
426    }
427    SetChecked(kFALSE);
428    return kFALSE;
429 }   
430    
431 //______________________________________________________________________________
432 void AliAnalysisTask::PrintTask(Option_t *option, Int_t indent) const
433 {
434 // Print task info.
435    AliAnalysisTask *thistask = (AliAnalysisTask*)this;
436    TString opt(option);
437    opt.ToLower();
438    Bool_t dep = (opt.Contains("dep"))?kTRUE:kFALSE;
439    TString ind;
440    Int_t islot;
441    AliAnalysisDataContainer *cont;
442    for (Int_t i=0; i<indent; i++) ind += " ";
443    if (!dep || (dep && IsChecked())) {
444       printf("%s\n", Form("%stask: %s  ACTIVE=%i", ind.Data(), GetName(),IsActive()));
445       if (dep) thistask->SetChecked(kFALSE);
446       else {
447          for (islot=0; islot<fNinputs; islot++) {
448             printf("%s", Form("%s   INPUT #%i: %s <- ",ind.Data(),islot, GetInputType(islot)->GetName()));
449             cont = GetInputSlot(islot)->GetContainer();
450             if (cont) printf(" [%s]\n", cont->GetName());
451             else printf(" [NO CONTAINER]\n");
452          }
453          for (islot=0; islot<fNoutputs; islot++) {
454             printf("%s", Form("%s   OUTPUT #%i: %s -> ",ind.Data(),islot, GetOutputType(islot)->GetName()));
455             cont = GetOutputSlot(islot)->GetContainer();
456             if (cont) printf(" [%s]\n", cont->GetName());
457             else printf(" [NO CONTAINER]\n");
458          }            
459       }
460    }
461    PrintContainers(option, indent+3);
462 }      
463
464 //______________________________________________________________________________
465 void AliAnalysisTask::PrintContainers(Option_t *option, Int_t indent) const
466 {
467 // Print containers info.
468    AliAnalysisDataContainer *cont;
469    TString ind;
470    for (Int_t i=0; i<indent; i++) ind += " ";
471    Int_t islot;
472    for (islot=0; islot<fNoutputs; islot++) {
473       cont = GetOutputSlot(islot)->GetContainer();
474       cont->PrintContainer(option, indent);
475    }   
476 }