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()
69 // Default constructor.
72 //______________________________________________________________________________
73 AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
84 fInputs = new TObjArray(2);
85 fOutputs = new TObjArray(2);
88 //______________________________________________________________________________
89 AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task)
92 fNinputs(task.fNinputs),
93 fNoutputs(task.fNoutputs),
100 fInputs = new TObjArray((fNinputs)?fNinputs:2);
101 fOutputs = new TObjArray((fNoutputs)?fNoutputs:2);
104 for (i=0; i<fNinputs; i++) fInputs->AddAt(task.GetInputSlot(i),i);
105 fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
106 for (i=0; i<fNoutputs; i++) {
107 fOutputReady[i] = IsOutputReady(i);
108 fOutputs->AddAt(task.GetOutputSlot(i),i);
112 //______________________________________________________________________________
113 AliAnalysisTask::~AliAnalysisTask()
116 if (fInputs) {fInputs->Delete(); delete fInputs;}
117 if (fOutputs) {fOutputs->Delete(); delete fOutputs;}
120 //______________________________________________________________________________
121 AliAnalysisTask& AliAnalysisTask::operator=(const AliAnalysisTask& task)
124 if (&task == this) return *this;
125 TTask::operator=(task);
126 fReady = task.IsReady();
127 fNinputs = task.GetNinputs();
128 fNoutputs = task.GetNoutputs();
129 fInputs = new TObjArray((fNinputs)?fNinputs:2);
130 fOutputs = new TObjArray((fNoutputs)?fNoutputs:2);
133 for (i=0; i<fNinputs; i++) fInputs->AddAt(new AliAnalysisDataSlot(*task.GetInputSlot(i)),i);
134 fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
135 for (i=0; i<fNoutputs; i++) {
136 fOutputReady[i] = IsOutputReady(i);
137 fOutputs->AddAt(new AliAnalysisDataSlot(*task.GetOutputSlot(i)),i);
142 //______________________________________________________________________________
143 Bool_t AliAnalysisTask::AreSlotsConnected()
145 // Check if all input/output slots are connected. If this is the case fReady=true
147 if (!fNinputs || !fNoutputs) return kFALSE;
149 AliAnalysisDataSlot *slot;
150 for (i=0; i<fNinputs; i++) {
151 slot = (AliAnalysisDataSlot*)fInputs->At(i);
153 AliError(Form("Input slot %i of task %s not defined !",i,GetName()));
156 if (!slot->IsConnected()) return kFALSE;
158 for (i=0; i<fNoutputs; i++) {
159 slot = (AliAnalysisDataSlot*)fOutputs->At(i);
161 AliError(Form("Output slot %i of task %s not defined !",i,GetName()));
164 if (!slot->IsConnected()) return kFALSE;
170 //______________________________________________________________________________
171 void AliAnalysisTask::CheckNotify()
173 // Check if data is available from all inputs. Change the status of the task
174 // accordingly. This method is called automatically for all tasks connected
175 // to a container where the data was published.
176 for (Int_t islot=0; islot<fNinputs; islot++) {
177 if (!GetInputData(islot)) {
185 //______________________________________________________________________________
186 Bool_t AliAnalysisTask::ConnectInput(Int_t islot, AliAnalysisDataContainer *cont)
188 // Connect an input slot to a data container.
189 AliAnalysisDataSlot *input = GetInputSlot(islot);
191 AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
194 // Check type matching
195 if (!input->GetType()->InheritsFrom(cont->GetType())) {
196 AliError(Form("Data type %s for input %i of task %s not matching container %s of type %s",
197 input->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName()));
200 // Connect the slot to the container as input
201 if (!input->ConnectContainer(cont)) return kFALSE;
202 // Add this to the list of container consumers
203 cont->AddConsumer(this, islot);
208 //______________________________________________________________________________
209 Bool_t AliAnalysisTask::ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont)
211 // Connect an output slot to a data container.
212 AliAnalysisDataSlot *output = GetOutputSlot(islot);
214 AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName()));
217 // Check type matching
218 if (!output->GetType()->InheritsFrom(cont->GetType())) {
219 AliError(Form("Data type %s for output %i of task %s not matching container %s of type %s",
220 output->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName()));
223 // Connect the slot to the container as output
224 if (!output->ConnectContainer(cont)) return kFALSE;
225 // Declare this as the data producer
226 cont->SetProducer(this, islot);
231 //______________________________________________________________________________
232 void AliAnalysisTask::DefineInput(Int_t islot, TClass *type)
234 // Define an input slot and its type.
235 AliAnalysisDataSlot *input = new AliAnalysisDataSlot(type, this);
236 if (fNinputs<islot+1) fNinputs = islot+1;
237 fInputs->AddAt(input, islot);
240 //______________________________________________________________________________
241 void AliAnalysisTask::DefineOutput(Int_t islot, TClass *type)
243 // Define an output slot and its type.
245 AliError(Form("Cannot define negative output slot number for task %s", GetName()));
248 AliAnalysisDataSlot *output = new AliAnalysisDataSlot(type, this);
249 if (fNoutputs<islot+1) {
251 if (fOutputReady) delete [] fOutputReady;
252 fOutputReady = new Bool_t[fNoutputs];
253 memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
255 fOutputs->AddAt(output, islot);
258 //______________________________________________________________________________
259 TClass *AliAnalysisTask::GetInputType(Int_t islot) const
261 // Retreive type of a given input slot.
262 AliAnalysisDataSlot *input = GetInputSlot(islot);
264 AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
267 return (input->GetType());
270 //______________________________________________________________________________
271 TClass *AliAnalysisTask::GetOutputType(Int_t islot) const
273 // Retreive type of a given output slot.
274 AliAnalysisDataSlot *output = GetOutputSlot(islot);
276 AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName()));
279 return (output->GetType());
282 //______________________________________________________________________________
283 TObject *AliAnalysisTask::GetInputData(Int_t islot) const
285 // Retreive input data for a slot if ready. Normally called by Exec() and
286 // the object has to be statically cast to the appropriate type.
287 AliAnalysisDataSlot *input = GetInputSlot(islot);
289 AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName()));
292 return (input->GetData());
295 //______________________________________________________________________________
296 Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option)
298 // Post output data for a given ouput slot in the corresponding data container.
299 // Published data becomes owned by the data container.
300 // If option is specified, the container connected to the output slot must have
301 // an associated file name defined. The option represents the method to open the file.
303 AliAnalysisDataSlot *output = GetOutputSlot(iout);
305 AliError(Form("Output slot %i not defined for analysis task %s", iout, GetName()));
308 if (!output->IsConnected()) {
309 AliError(Form("Output slot %i of analysis task %s not connected to any data container", iout, GetName()));
313 fOutputReady = new Bool_t[fNoutputs];
314 memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
316 fOutputReady[iout] = kTRUE;
317 fPublishedData = data;
318 return (output->GetContainer()->SetData(data, option));
321 //______________________________________________________________________________
322 void AliAnalysisTask::SetUsed(Bool_t flag)
324 // Set 'used' flag recursively to task and all daughter tasks.
325 if (TestBit(kTaskUsed)==flag) return;
326 TObject::SetBit(kTaskUsed,flag);
327 Int_t nd = fTasks->GetSize();
328 AliAnalysisTask *task;
329 for (Int_t i=0; i<nd; i++) {
330 task = (AliAnalysisTask*)fTasks->At(i);
335 //______________________________________________________________________________
336 Bool_t AliAnalysisTask::CheckCircularDeps()
338 // Check for illegal circular dependencies, e.g. a daughter task should not have
339 // a hierarchical parent as subtask.
340 if (IsChecked()) return kTRUE;
342 TList *tasks = GetListOfTasks();
343 Int_t ntasks = tasks->GetSize();
344 AliAnalysisTask *task;
345 for (Int_t i=0; i<ntasks; i++) {
346 task = (AliAnalysisTask*)tasks->At(i);
347 if (task->CheckCircularDeps()) return kTRUE;
353 //______________________________________________________________________________
354 void AliAnalysisTask::PrintTask(Option_t *option, Int_t indent) const
357 AliAnalysisTask *thistask = (AliAnalysisTask*)this;
360 Bool_t dep = (opt.Contains("dep"))?kTRUE:kFALSE;
363 AliAnalysisDataContainer *cont;
364 for (Int_t i=0; i<indent; i++) ind += " ";
365 if (!dep || (dep && IsChecked())) {
366 printf("%s\n", Form("%stask: %s ACTIVE=%i", ind.Data(), GetName(),IsActive()));
367 if (dep) thistask->SetChecked(kFALSE);
369 for (islot=0; islot<fNinputs; islot++) {
370 printf("%s", Form("%s INPUT #%i: %s <- ",ind.Data(),islot, GetInputType(islot)->GetName()));
371 cont = GetInputSlot(islot)->GetContainer();
372 if (cont) printf(" [%s]\n", cont->GetName());
373 else printf(" [NO CONTAINER]\n");
375 for (islot=0; islot<fNoutputs; islot++) {
376 printf("%s", Form("%s OUTPUT #%i: %s -> ",ind.Data(),islot, GetOutputType(islot)->GetName()));
377 cont = GetOutputSlot(islot)->GetContainer();
378 if (cont) printf(" [%s]\n", cont->GetName());
379 else printf(" [NO CONTAINER]\n");
383 PrintContainers(option, indent+3);
386 //______________________________________________________________________________
387 void AliAnalysisTask::PrintContainers(Option_t *option, Int_t indent) const
389 // Print containers info.
390 AliAnalysisDataContainer *cont;
392 for (Int_t i=0; i<indent; i++) ind += " ";
394 for (islot=0; islot<fNoutputs; islot++) {
395 cont = GetOutputSlot(islot)->GetContainer();
396 cont->PrintContainer(option, indent);