1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 // Author: Andrei Gheata, 31/05/2006
19 //==============================================================================
20 // AliAnalysysTask - Class representing a basic analysis task. Any
21 // user-defined task should derive from it and implement the Exec() virtual
23 //==============================================================================
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:
28 // UserTask::UserTask(name, title)
30 // DefineInput(0, TTree::Class());
31 // DefineInput(1, TH1::Class());
33 // DefineOutput(0, TTree::Class());
34 // DefineOutput(1, MyObject::Class());
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:
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
48 //==============================================================================
53 #include "AliAnalysisTask.h"
54 #include "AliAnalysisDataSlot.h"
55 #include "AliAnalysisDataContainer.h"
57 ClassImp(AliAnalysisTask)
59 //______________________________________________________________________________
60 AliAnalysisTask::AliAnalysisTask()
62 // Default constructor.
72 //______________________________________________________________________________
73 AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
82 fInputs = new TObjArray(2);
83 fOutputs = new TObjArray(2);
86 //______________________________________________________________________________
87 AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task)
91 fReady = task.IsReady();
92 fNinputs = task.GetNinputs();
93 fNoutputs = task.GetNoutputs();
94 fInputs = new TObjArray((fNinputs)?fNinputs:2);
95 fOutputs = new TObjArray((fNoutputs)?fNoutputs:2);
98 for (i=0; i<fNinputs; i++) fInputs->AddAt(task.GetInputSlot(i),i);
99 fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
100 for (i=0; i<fNoutputs; i++) {
101 fOutputReady[i] = IsOutputReady(i);
102 fOutputs->AddAt(task.GetOutputSlot(i),i);
106 //______________________________________________________________________________
107 AliAnalysisTask::~AliAnalysisTask()
110 if (fInputs) {fInputs->Delete(); delete fInputs;}
111 if (fOutputs) {fOutputs->Delete(); delete fOutputs;}
114 //______________________________________________________________________________
115 AliAnalysisTask& AliAnalysisTask::operator=(const AliAnalysisTask& task)
119 TTask::operator=(task);
120 fReady = task.IsReady();
121 fNinputs = task.GetNinputs();
122 fNoutputs = task.GetNoutputs();
123 fInputs = new TObjArray((fNinputs)?fNinputs:2);
124 fOutputs = new TObjArray((fNoutputs)?fNoutputs:2);
127 for (i=0; i<fNinputs; i++) fInputs->AddAt(task.GetInputSlot(i),i);
128 fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
129 for (i=0; i<fNoutputs; i++) {
130 fOutputReady[i] = IsOutputReady(i);
131 fOutputs->AddAt(task.GetOutputSlot(i),i);
137 //______________________________________________________________________________
138 Bool_t AliAnalysisTask::AreSlotsConnected()
140 // Check if all input/output slots are connected. If this is the case fReady=true
142 if (!fNinputs || !fNoutputs) return kFALSE;
144 AliAnalysisDataSlot *slot;
145 for (i=0; i<fNinputs; i++) {
146 slot = (AliAnalysisDataSlot*)fInputs->At(i);
148 AliError(Form("Input slot %i of task %s not defined !",i,GetName()));
151 if (!slot->IsConnected()) return kFALSE;
153 for (i=0; i<fNoutputs; i++) {
154 slot = (AliAnalysisDataSlot*)fOutputs->At(i);
156 AliError(Form("Output slot %i of task %s not defined !",i,GetName()));
159 if (!slot->IsConnected()) return kFALSE;
165 //______________________________________________________________________________
166 void AliAnalysisTask::CheckNotify()
168 // Check if data is available from all inputs. Change the status of the task
169 // accordingly. This method is called automatically for all tasks connected
170 // to a container where the data was published.
171 for (Int_t islot=0; islot<fNinputs; islot++) {
172 if (!GetInputData(islot)) {
180 //______________________________________________________________________________
181 Bool_t AliAnalysisTask::ConnectInput(Int_t islot, AliAnalysisDataContainer *cont)
183 // Connect an input slot to a data container.
184 AliAnalysisDataSlot *input = GetInputSlot(islot);
186 AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
189 // Check type matching
190 if (!input->GetType()->InheritsFrom(cont->GetType())) {
191 AliError(Form("Data type %s for input %i of task %s not matching container %s of type %s",
192 input->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName()));
195 // Connect the slot to the container as input
196 if (!input->ConnectContainer(cont)) return kFALSE;
197 // Add this to the list of container consumers
198 cont->AddConsumer(this, islot);
203 //______________________________________________________________________________
204 Bool_t AliAnalysisTask::ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont)
206 // Connect an output slot to a data container.
207 AliAnalysisDataSlot *output = GetOutputSlot(islot);
209 AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName()));
212 // Check type matching
213 if (!output->GetType()->InheritsFrom(cont->GetType())) {
214 AliError(Form("Data type %s for output %i of task %s not matching container %s of type %s",
215 output->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName()));
218 // Connect the slot to the container as output
219 if (!output->ConnectContainer(cont)) return kFALSE;
220 // Declare this as the data producer
221 cont->SetProducer(this, islot);
226 //______________________________________________________________________________
227 void AliAnalysisTask::DefineInput(Int_t islot, TClass *type)
229 // Define an input slot and its type.
230 AliAnalysisDataSlot *input = new AliAnalysisDataSlot(type, this);
231 if (fNinputs<islot+1) fNinputs = islot+1;
232 fInputs->AddAt(input, islot);
235 //______________________________________________________________________________
236 void AliAnalysisTask::DefineOutput(Int_t islot, TClass *type)
238 // Define an output slot and its type.
240 AliError(Form("Cannot define negative output slot number for task %s", GetName()));
243 AliAnalysisDataSlot *output = new AliAnalysisDataSlot(type, this);
244 if (fNoutputs<islot+1) {
246 if (fOutputReady) delete [] fOutputReady;
247 fOutputReady = new Bool_t[fNoutputs];
248 memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
250 fOutputs->AddAt(output, islot);
253 //______________________________________________________________________________
254 TClass *AliAnalysisTask::GetInputType(Int_t islot) const
256 // Retreive type of a given input slot.
257 AliAnalysisDataSlot *input = GetInputSlot(islot);
259 AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
262 return (input->GetType());
265 //______________________________________________________________________________
266 TClass *AliAnalysisTask::GetOutputType(Int_t islot) const
268 // Retreive type of a given output slot.
269 AliAnalysisDataSlot *output = GetOutputSlot(islot);
271 AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName()));
274 return (output->GetType());
277 //______________________________________________________________________________
278 TObject *AliAnalysisTask::GetInputData(Int_t islot) const
280 // Retreive input data for a slot if ready. Normally called by Exec() and
281 // the object has to be statically cast to the appropriate type.
282 AliAnalysisDataSlot *input = GetInputSlot(islot);
284 AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
287 return (input->GetData());
290 //______________________________________________________________________________
291 Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option)
293 // Post output data for a given ouput slot in the corresponding data container.
294 // Published data becomes owned by the data container.
295 // If option is specified, the container connected to the output slot must have
296 // an associated file name defined. The option represents the method to open the file.
298 AliAnalysisDataSlot *output = GetOutputSlot(iout);
300 AliError(Form("Output slot %i not defined for analysis task %s", iout, GetName()));
303 if (!output->IsConnected()) {
304 AliError(Form("Output slot %i of analysis task %s not connected to any data container", iout, GetName()));
308 fOutputReady = new Bool_t[fNoutputs];
309 memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
311 fOutputReady[iout] = kTRUE;
312 fPublishedData = data;
313 return (output->GetContainer()->SetData(data, option));
316 //______________________________________________________________________________
317 void AliAnalysisTask::SetUsed(Bool_t flag)
319 // Set 'used' flag recursively to task and all daughter tasks.
320 if (TestBit(kTaskUsed)==flag) return;
321 TObject::SetBit(kTaskUsed,flag);
322 Int_t nd = fTasks->GetSize();
323 AliAnalysisTask *task;
324 for (Int_t i=0; i<nd; i++) {
325 task = (AliAnalysisTask*)fTasks->At(i);
330 //______________________________________________________________________________
331 Bool_t AliAnalysisTask::CheckCircularDeps()
333 // Check for illegal circular dependencies, e.g. a daughter task should not have
334 // a hierarchical parent as subtask.
335 if (IsChecked()) return kTRUE;
337 TList *tasks = GetListOfTasks();
338 Int_t ntasks = tasks->GetSize();
339 AliAnalysisTask *task;
340 for (Int_t i=0; i<ntasks; i++) {
341 task = (AliAnalysisTask*)tasks->At(i);
342 if (task->CheckCircularDeps()) return kTRUE;
348 //______________________________________________________________________________
349 void AliAnalysisTask::PrintTask(Option_t *option, Int_t indent) const
352 AliAnalysisTask *thistask = (AliAnalysisTask*)this;
355 Bool_t dep = (opt.Contains("dep"))?kTRUE:kFALSE;
358 AliAnalysisDataContainer *cont;
359 for (Int_t i=0; i<indent; i++) ind += " ";
360 if (!dep || (dep && IsChecked())) {
361 printf("%s\n", Form("%stask: %s ACTIVE=%i", ind.Data(), GetName(),IsActive()));
362 if (dep) thistask->SetChecked(kFALSE);
364 for (islot=0; islot<fNinputs; islot++) {
365 printf("%s", Form("%s INPUT #%i: %s <- ",ind.Data(),islot, GetInputType(islot)->GetName()));
366 cont = GetInputSlot(islot)->GetContainer();
367 if (cont) printf(" [%s]\n", cont->GetName());
368 else printf(" [NO CONTAINER]\n");
370 for (islot=0; islot<fNoutputs; islot++) {
371 printf("%s", Form("%s OUTPUT #%i: %s -> ",ind.Data(),islot, GetOutputType(islot)->GetName()));
372 cont = GetOutputSlot(islot)->GetContainer();
373 if (cont) printf(" [%s]\n", cont->GetName());
374 else printf(" [NO CONTAINER]\n");
378 PrintContainers(option, indent+3);
381 //______________________________________________________________________________
382 void AliAnalysisTask::PrintContainers(Option_t *option, Int_t indent) const
384 // Print containers info.
385 AliAnalysisDataContainer *cont;
387 for (Int_t i=0; i<indent; i++) ind += " ";
389 for (islot=0; islot<fNoutputs; islot++) {
390 cont = GetOutputSlot(islot)->GetContainer();
391 cont->PrintContainer(option, indent);