AliRoot Core  3dc7879 (3dc7879)
AliAnalysisTask.cxx
Go to the documentation of this file.
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 
17 #include <Riostream.h>
18 #include <TFile.h>
19 #include <TClass.h>
20 #include <TCollection.h>
21 #include <TTree.h>
22 #include <TROOT.h>
23 #include <TClonesArray.h>
24 
25 #include "AliAnalysisTask.h"
26 #include "AliAnalysisDataSlot.h"
28 #include "AliAnalysisManager.h"
29 
30 static bool showInfo = !(getenv("HLT_ONLINE_MODE") && strcmp(getenv("HLT_ONLINE_MODE"), "on") == 0);
31 
32 ClassImp(AliAnalysisTask)
33 
34 //______________________________________________________________________________
36  :fReady(kFALSE),
37  fInitialized(kFALSE),
38  fNinputs(0),
39  fNoutputs(0),
40  fOutputReady(NULL),
41  fPublishedData(NULL),
42  fInputs(NULL),
43  fOutputs(NULL),
44  fBranchNames()
45 {
46 // Default constructor.
47 }
48 
49 //______________________________________________________________________________
50 AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
51  :TTask(name,title),
52  fReady(kFALSE),
53  fInitialized(kFALSE),
54  fNinputs(0),
55  fNoutputs(0),
56  fOutputReady(NULL),
57  fPublishedData(NULL),
58  fInputs(NULL),
59  fOutputs(NULL),
60  fBranchNames()
61 {
63 
64  fInputs = new TObjArray(2);
65  fOutputs = new TObjArray(2);
66 }
67 
68 //______________________________________________________________________________
70  :TTask(task),
71  fReady(task.fReady),
73  fNinputs(task.fNinputs),
74  fNoutputs(task.fNoutputs),
75  fOutputReady(NULL),
76  fPublishedData(NULL),
77  fInputs(NULL),
78  fOutputs(NULL),
80 {
82 
85  fPublishedData = 0;
86  Int_t i;
87  for (i=0; i<fNinputs; i++) fInputs->AddAt(task.GetInputSlot(i),i);
88  fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
89  for (i=0; i<fNoutputs; i++) {
91  fOutputs->AddAt(task.GetOutputSlot(i),i);
92  }
93 }
94 
95 //______________________________________________________________________________
97 {
99 
100  if (fTasks) fTasks->Clear();
101  if (fInputs) {
102  //make sure the container knows it does not own the input data (why is it even there?)
103  TIter i(fInputs);
104  while (AliAnalysisDataSlot* dataSlot = static_cast<AliAnalysisDataSlot*>(i())) {
105  AliAnalysisDataContainer* cont = dataSlot->GetContainer();
106  if (cont) {
107  cont->SetDataOwned(kFALSE);
108  }
109  }
110  fInputs->Delete();
111  delete fInputs;
112  }
113  if (fOutputs) {
114  //By convention(design?) the user task deletes the output objects,
115  //make sure the container knows it does not own them
116  TIter i(fOutputs);
117  while (AliAnalysisDataSlot* dataSlot = static_cast<AliAnalysisDataSlot*>(i())) {
118  AliAnalysisDataContainer* cont = dataSlot->GetContainer();
119  if (cont) {
120  cont->SetDataOwned(kFALSE);
121  }
122  }
123  fOutputs->Delete();
124  delete fOutputs;
125  }
126 }
127 
128 //______________________________________________________________________________
130 {
132 
133  if (&task == this) return *this;
134  TTask::operator=(task);
135  fReady = task.IsReady();
136  fInitialized = task.IsInitialized();
137  fNinputs = task.GetNinputs();
138  fNoutputs = task.GetNoutputs();
139  fInputs = new TObjArray((fNinputs)?fNinputs:2);
141  fPublishedData = 0;
142  Int_t i;
143  for (i=0; i<fNinputs; i++) fInputs->AddAt(new AliAnalysisDataSlot(*task.GetInputSlot(i)),i);
144  fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
145  for (i=0; i<fNoutputs; i++) {
146  fOutputReady[i] = IsOutputReady(i);
147  fOutputs->AddAt(new AliAnalysisDataSlot(*task.GetOutputSlot(i)),i);
148  }
149  fBranchNames = task.fBranchNames;
150  return *this;
151 }
152 
153 //______________________________________________________________________________
155 {
157 
158  fReady = kFALSE;
159  if (!fNinputs || !fNoutputs) return kFALSE;
160  Int_t i;
161  AliAnalysisDataSlot *slot;
162  for (i=0; i<fNinputs; i++) {
163  slot = (AliAnalysisDataSlot*)fInputs->At(i);
164  if (!slot) {
165  Error("AreSlotsConnected", "Input slot %d of task %s not defined !",i,GetName());
166  return kFALSE;
167  }
168  if (!slot->IsConnected()) return kFALSE;
169  }
170  for (i=0; i<fNoutputs; i++) {
171  slot = (AliAnalysisDataSlot*)fOutputs->At(i);
172  if (!slot) {
173  Error("AreSlotsConnected", "Output slot %d of task %s not defined !",i,GetName());
174  return kFALSE;
175  }
176  if (!slot->IsConnected()) return kFALSE;
177  }
178  fReady = kTRUE;
179  return kTRUE;
180 }
181 
182 //______________________________________________________________________________
184 {
188 
189  if (init) fInitialized = kFALSE;
190  Bool_t single_shot = IsPostEventLoop();
191  AliAnalysisDataContainer *cinput;
192  for (Int_t islot=0; islot<fNinputs; islot++) {
193  cinput = GetInputSlot(islot)->GetContainer();
194  if (!cinput->GetData() || (single_shot && !cinput->IsPostEventLoop())) {
195  SetActive(kFALSE);
196  return;
197  }
198  }
199  SetActive(kTRUE);
200  if (fInitialized) return;
201  TDirectory *cursav = gDirectory;
203  if (cursav) cursav->cd();
204  fInitialized = kTRUE;
205 }
206 
207 //______________________________________________________________________________
209 {
212 
213  Bool_t dataPosted = kTRUE;
214  AliAnalysisDataContainer *coutput;
216  for (Int_t islot=0; islot<fNoutputs; islot++) {
217  coutput = GetOutputSlot(islot)->GetContainer();
218  if (!coutput) continue;
219  if (coutput->IsExchange() || !mgr->GetOutputs()->FindObject(coutput) || coutput==mgr->GetCommonOutputContainer()) continue;
220  if (!coutput->GetData()) {
221  Error("CheckPostData", "Data not posted for slot #%d of task %s (%s)",
222  islot, GetName(), ClassName());
223  dataPosted = kFALSE;
224  }
225  }
226  CheckOwnership();
227  return dataPosted;
228 }
229 
230 //______________________________________________________________________________
232 {
234 
235  TObject *outdata;
236  for (Int_t islot=0; islot<fNoutputs; islot++) {
237  outdata = GetOutputData(islot);
238  if (outdata && outdata->InheritsFrom(TCollection::Class()) && !outdata->InheritsFrom(TClonesArray::Class())) {
239  TCollection *coll = (TCollection*)outdata;
240  if (!coll->IsOwner()) {
241  Error("CheckOwnership","####### IMPORTANT! ####### \n\n\n\
242  Task %s (%s) posts a container that is not owner at output #%d. This may apply for other embedded containers. \n\n\
243  ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", GetName(), ClassName(), islot);
244  return kFALSE;
245  }
246  }
247  }
248  return kTRUE;
249 }
250 
251 //______________________________________________________________________________
253 {
255 
256  AliAnalysisDataSlot *input = GetInputSlot(islot);
257  if (!input) {
258  if (showInfo) Error("ConnectInput","Input slot %i not defined for analysis task %s", islot, GetName());
259  return kFALSE;
260  }
261  // Check type matching
262  if (!input->GetType()->InheritsFrom(cont->GetType())) {
263  Error("ConnectInput","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());
264  return kFALSE;
265  }
266  // Connect the slot to the container as input
267  if (!input->ConnectContainer(cont)) return kFALSE;
268  // Add this to the list of container consumers
269  cont->AddConsumer(this, islot);
271  return kTRUE;
272 }
273 
274 //______________________________________________________________________________
276 {
278 
279  AliAnalysisDataSlot *output = GetOutputSlot(islot);
280  if (!output) {
281  if (showInfo) Error("ConnectOutput","Output slot %i not defined for analysis task %s", islot, GetName());
282  return kFALSE;
283  }
284  // Check type matching
285  if (!output->GetType()->InheritsFrom(cont->GetType())) {
286  Error("ConnectOutput","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());
287  return kFALSE;
288  }
289  // Connect the slot to the container as output
290  if (!output->ConnectContainer(cont)) return kFALSE;
291  // Set event loop type the same as for the task
293  // Declare this as the data producer
294  cont->SetProducer(this, islot);
296  return kTRUE;
297 }
298 
299 //______________________________________________________________________________
300 void AliAnalysisTask::DefineInput(Int_t islot, TClass *type)
301 {
303 
304  AliAnalysisDataSlot *input = new AliAnalysisDataSlot(type, this);
305  if (fNinputs<islot+1) fNinputs = islot+1;
306  fInputs->AddAtAndExpand(input, islot);
307 }
308 
309 //______________________________________________________________________________
310 void AliAnalysisTask::DefineOutput(Int_t islot, TClass *type)
311 {
313 
314  AliAnalysisDataSlot *output = new AliAnalysisDataSlot(type, this);
315  if (fNoutputs<islot+1) {
316  fNoutputs = islot+1;
317  if (fOutputReady) delete [] fOutputReady;
318  fOutputReady = new Bool_t[fNoutputs];
319  memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
320  }
321  fOutputs->AddAtAndExpand(output, islot);
322 }
323 
324 //______________________________________________________________________________
325 TClass *AliAnalysisTask::GetInputType(Int_t islot) const
326 {
328 
329  AliAnalysisDataSlot *input = GetInputSlot(islot);
330  if (!input) {
331  if (showInfo) Error("GetInputType","Input slot %d not defined for analysis task %s", islot, GetName());
332  return NULL;
333  }
334  return (input->GetType());
335 }
336 
337 //______________________________________________________________________________
338 TClass *AliAnalysisTask::GetOutputType(Int_t islot) const
339 {
341 
342  AliAnalysisDataSlot *output = GetOutputSlot(islot);
343  if (!output) {
344  if (showInfo) Error("GetOutputType","Output slot %d not defined for analysis task %s", islot, GetName());
345  return NULL;
346  }
347  return (output->GetType());
348 }
349 
350 //______________________________________________________________________________
351 TObject *AliAnalysisTask::GetInputData(Int_t islot) const
352 {
355 
356  AliAnalysisDataSlot *input = GetInputSlot(islot);
357  if (!input) {
358  if (showInfo) Error("GetInputData","Input slot %d not defined for analysis task %s", islot, GetName());
359  return NULL;
360  }
361  return (input->GetData());
362 }
363 
364 //______________________________________________________________________________
365 TObject *AliAnalysisTask::GetOutputData(Int_t islot) const
366 {
369 
370  AliAnalysisDataSlot *output = GetOutputSlot(islot);
371  if (!output) {
372  if (showInfo) Error("GetOutputData","Input slot %d not defined for analysis task %s", islot, GetName());
373  return NULL;
374  }
375  return (output->GetData());
376 }
377 
378 //______________________________________________________________________________
379 char *AliAnalysisTask::GetBranchAddress(Int_t islot, const char *branch) const
380 {
384 
385  return (char *)GetInputSlot(islot)->GetBranchAddress(branch);
386 }
387 
388 //______________________________________________________________________________
389 Bool_t AliAnalysisTask::SetBranchAddress(Int_t islot, const char *branch, void *address) const
390 {
392 
393  return GetInputSlot(islot)->SetBranchAddress(branch, address);
394 }
395 
396 //______________________________________________________________________________
397 void AliAnalysisTask::EnableBranch(Int_t islot, const char *bname) const
398 {
401 
402  AliAnalysisDataSlot *input = GetInputSlot(islot);
403  if (!input || !input->GetType()->InheritsFrom(TTree::Class())) {
404  Error("EnableBranch", "Wrong slot type #%d for task %s: not TTree-derived type", islot, GetName());
405  return;
406  }
407  TTree *tree = (TTree*)input->GetData();
408  if (!strcmp(bname, "*")) {
409  tree->SetBranchStatus("*",1);
410  return;
411  }
413 }
414 
415 //______________________________________________________________________________
417 {
423 
424 }
425 
426 //______________________________________________________________________________
428 {
430 
431 }
432 
433 //______________________________________________________________________________
435 {
441 
442 }
443 
444 //______________________________________________________________________________
446 {
449 
450 }
451 
452 //______________________________________________________________________________
453 TFile *AliAnalysisTask::OpenFile(Int_t iout, Option_t *option) const
454 {
473 
474  if (iout<0 || iout>=fNoutputs) {
475  Error("OpenFile", "No output slot for task %s with index %d", GetName(), iout);
476  return NULL;
477  }
478  // Method delegated to the analysis manager (A.G. 02/11/09)
480  return AliAnalysisManager::OpenFile(cont, option);
481 }
482 
483 //______________________________________________________________________________
485 {
487 
488  return kTRUE;
489 }
490 
491 //______________________________________________________________________________
493 {
495 
496  return kTRUE;
497 }
498 
499 //______________________________________________________________________________
501 {
503 
504 }
505 
506 //______________________________________________________________________________
507 Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option)
508 {
513 
514  fPublishedData = 0;
515  AliAnalysisDataSlot *output = GetOutputSlot(iout);
516  if (!output) {
517  if (showInfo) Error("PostData","Output slot %i not defined for analysis task %s", iout, GetName());
518  return kFALSE;
519  }
520  if (!output->IsConnected()) {
521  if (showInfo) Error("PostData","Output slot %i of analysis task %s not connected to any data container", iout, GetName());
522  return kFALSE;
523  }
524  if (!fOutputReady) {
525  fOutputReady = new Bool_t[fNoutputs];
526  memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
527  }
528  fOutputReady[iout] = kTRUE;
529  fPublishedData = data;
530  return (output->GetContainer()->SetData(data, option));
531 }
532 
533 //______________________________________________________________________________
534 void AliAnalysisTask::SetUsed(Bool_t flag)
535 {
537 
538  if (TestBit(kTaskUsed)==flag) return;
539  TObject::SetBit(kTaskUsed,flag);
540  Int_t nd = fTasks->GetSize();
541  AliAnalysisTask *task;
542  for (Int_t i=0; i<nd; i++) {
543  task = (AliAnalysisTask*)fTasks->At(i);
544  task->SetUsed(flag);
545  }
546 }
547 
548 //______________________________________________________________________________
550 {
552 
553  fActive = kFALSE;
554  fHasExecuted = kFALSE;
555  // Call PostData(islot, 0) for all slots connected to exchange containers
556  Int_t islot;
558  for (islot=0; islot<fNinputs; islot++) {
559  cont = GetInputSlot(islot)->GetContainer();
560  if (cont && cont->IsExchange()) cont->Reset();
561  }
562 }
563 
564 //______________________________________________________________________________
566 {
569 
570  if (IsChecked()) return kTRUE;
571  SetChecked();
572  TList *tasks = GetListOfTasks();
573  Int_t ntasks = tasks->GetSize();
574  AliAnalysisTask *task;
575  for (Int_t i=0; i<ntasks; i++) {
576  task = (AliAnalysisTask*)tasks->At(i);
577  if (task->CheckCircularDeps()) return kTRUE;
578  }
579  SetChecked(kFALSE);
580  return kFALSE;
581 }
582 
583 //______________________________________________________________________________
585 {
587 
588  Int_t islot;
590  for (islot=0; islot<fNinputs; islot++) {
591  cont = GetInputSlot(islot)->GetContainer();
592  // Simulate the data flow so the tasks are printed only when all inputs
593  // are touched
594  if (cont && !cont->IsTouched()) return kFALSE;
595  }
596  return kTRUE;
597 }
598 
599 //______________________________________________________________________________
600 void AliAnalysisTask::PrintTask(Option_t *option, Int_t indent) const
601 {
603 
604  Int_t islot;
606  if (fActive) return;
607  if (!ProducersTouched()) return;
608  TString opt(option);
609  opt.ToLower();
610  Bool_t dep = (opt.Contains("dep"))?kTRUE:kFALSE;
611  TString ind;
612  for (Int_t i=0; i<indent; i++) ind += " ";
613  if (!dep || (dep && IsChecked())) {
614  printf("______________________________________________________________________________\n");
615  printf("%s\n", Form("%stask: %s ACTIVE=%i POST_LOOP=%i", ind.Data(), GetName(),IsActive(),IsPostEventLoop()));
616  if (dep) const_cast<AliAnalysisTask*>(this)->SetChecked(kFALSE);
617  else {
618  for (islot=0; islot<fNinputs; islot++) {
619  printf("%s", Form("%s INPUT #%i: %s <- ",ind.Data(),islot, GetInputType(islot)->GetName()));
620  cont = GetInputSlot(islot)->GetContainer();
621  if (cont) printf(" [%s]\n", cont->GetName());
622  else printf(" [NO CONTAINER]\n");
623  }
624  for (islot=0; islot<fNoutputs; islot++) {
625  printf("%s", Form("%s OUTPUT #%i: %s -> ",ind.Data(),islot, GetOutputType(islot)->GetName()));
626  cont = GetOutputSlot(islot)->GetContainer();
627  if (cont) printf(" [%s]\n", cont->GetName());
628  else printf(" [NO CONTAINER]\n");
629  }
630  }
631  }
632  ((AliAnalysisTask*)this)->SetActive(kTRUE);
633  PrintContainers(option, indent+3);
634  if (!fBranchNames.IsNull()) printf("%sRequested branches: %s\n", ind.Data(), fBranchNames.Data());
635 }
636 
637 //______________________________________________________________________________
638 void AliAnalysisTask::PrintContainers(Option_t *option, Int_t indent) const
639 {
641 
643  TString ind;
644  for (Int_t i=0; i<indent; i++) ind += " ";
645  Int_t islot;
646  for (islot=0; islot<fNoutputs; islot++) {
647  cont = GetOutputSlot(islot)->GetContainer();
648  if (cont) cont->PrintContainer(option, indent);
649  }
650 }
651 
652 //______________________________________________________________________________
654 {
657 
658  TObject::SetBit(kTaskPostEventLoop,flag);
660  Int_t islot;
661  for (islot=0; islot<fNoutputs; islot++) {
662  cont = GetOutputSlot(islot)->GetContainer();
663  if (cont) cont->SetPostEventLoop(flag);
664  }
665 }
666 
667 //______________________________________________________________________________
668 void AliAnalysisTask::GetBranches(const char *type, TString &result) const
669 {
673 
674  result = "";
675  if (fBranchNames.IsNull()) return;
676  Int_t index1 = fBranchNames.Index(type);
677  if (index1<0) return;
678  index1 += 1+strlen(type);
679  Int_t index2 = fBranchNames.Index(" ", index1);
680  if (index2<0) index2 = fBranchNames.Length();
681  result = fBranchNames(index1, index2-index1);
682 }
AliAnalysysTask - Class representing a basic analysis task. Any user-defined task should derive from...
Bool_t fReady
Flag if the task is ready.
Bool_t fInitialized
True if Init() was called.
AliAnalysisDataContainer * GetCommonOutputContainer() const
virtual void Terminate(Option_t *option="")
printf("Chi2/npoints = %f\n", TMath::Sqrt(chi2/npoints))
void CheckNotify(Bool_t init=kFALSE)
Bool_t ConnectContainer(AliAnalysisDataContainer *cont)
TClass * GetInputType(Int_t islot) const
Bool_t SetBranchAddress(const char *branch, void *address)
Bool_t CheckCircularDeps()
virtual void FinishTaskOutput()
static TFile * OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof=kFALSE)
static bool showInfo
#define TObjArray
virtual void PrintTask(Option_t *option="all", Int_t indent=0) const
static AliAnalysisManager * GetAnalysisManager()
Bool_t IsConnected() const
TObject * GetData() const
Getters.
AliAnalysysManager Manager analysis class. Allows creation of several analysis tasks and data contain...
virtual Bool_t CheckOwnership() const
TClass * GetOutputType(Int_t islot) const
void * GetBranchAddress(const char *branch) const
void PrintContainer(Option_t *option="all", Int_t indent=0) const
Print connected tasks/status.
Bool_t PostData(Int_t iout, TObject *data, Option_t *option="")
void SetPostEventLoop(Bool_t flag=kTRUE)
Int_t fNinputs
Number of inputs.
virtual Bool_t NotifyBinChange()
void DefineInput(Int_t islot, TClass *type)
AliAnalysisTask & operator=(const AliAnalysisTask &task)
Bool_t IsOutputReady(Int_t islot) const
char * GetBranchAddress(Int_t islot, const char *branch) const
AliAnalysysDataContainer AliAnalysysDataContainer - Container of data of arbitrary type deriving from...
Int_t GetNinputs() const
virtual Bool_t Notify()
static Int_t EnableBranch(const char *bname, TTree *tree)
TString fBranchNames
List of input branches that need to be loaded for this task.
void SetChecked(Bool_t flag=kTRUE)
bool init
Definition: XSection.C:263
virtual void CreateOutputObjects()
Bool_t ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont)
TObject * GetInputData(Int_t islot) const
TObject * GetData() const
TTree * tree
virtual ~AliAnalysisTask()
TFile * OpenFile(Int_t iout, Option_t *option="RECREATE") const
virtual void ConnectInputData(Option_t *option="")
Bool_t ProducersTouched() const
AliAnalysysDataSlot Class representing a data slot of an analysis task. An analysis slot enforces a c...
virtual void Reset()
void PrintContainers(Option_t *option="all", Int_t indent=0) const
TObjArray * GetOutputs() const
Bool_t IsInitialized() const
AliAnalysisDataSlot * GetOutputSlot(Int_t islot) const
virtual void LocalInit()
Bool_t ConnectInput(Int_t islot, AliAnalysisDataContainer *cont)
TObject * GetOutputData(Int_t islot) const
Bool_t SetBranchAddress(Int_t islot, const char *branch, void *address) const
Bool_t IsPostEventLoop() const
TClass * GetType() const
AliAnalysisDataSlot * GetInputSlot(Int_t islot) const
void GetBranches(const char *type, TString &result) const
mgr
Definition: runKineProof.C:24
Bool_t * fOutputReady
Flags for output readyness.
void SetPostEventLoop(Bool_t flag=kTRUE)
void SetUsed(Bool_t flag=kTRUE)
virtual Bool_t CheckPostData() const
Int_t GetNoutputs() const
AliAnalysisDataContainer * GetContainer() const
Bool_t IsChecked() const
virtual Bool_t SetData(TObject *data, Option_t *option="")
void AddConsumer(AliAnalysisTask *cons, Int_t islot)
void DefineOutput(Int_t islot, TClass *type)
Bool_t IsReady() const
TObject * fPublishedData
! published data
void SetProducer(AliAnalysisTask *prod, Int_t islot)
TObjArray * fInputs
Array of input slots.
void EnableBranch(Int_t islot, const char *bname) const
TObjArray * fOutputs
Array of output slots.
Bool_t AreSlotsConnected()