Change in the cocktail to avoid interference with Pythia MB (Andreas)
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisManager.cxx
CommitLineData
d3106602 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// AliAnalysysManager - Manager analysis class. Allows creation of several
21// analysis tasks and data containers storing their input/output. Allows
22// connecting/chaining tasks via shared data containers. Serializes the current
23// event for all tasks depending only on initial input data.
24//==============================================================================
25//
26//==============================================================================
27
28#include "TClass.h"
327eaf46 29#include "TFile.h"
30#include "TTree.h"
d3106602 31#include "AliLog.h"
32
33#include "AliAnalysisManager.h"
34#include "AliAnalysisTask.h"
35#include "AliAnalysisDataContainer.h"
36#include "AliAnalysisDataSlot.h"
37
38ClassImp(AliAnalysisManager)
39
40//______________________________________________________________________________
37a26056 41AliAnalysisManager::AliAnalysisManager() : TSelector(),
327eaf46 42 fTree(NULL),
37a26056 43 fInitOK(kFALSE),
44 fContainers(NULL),
45 fInputs(NULL),
46 fOutputs(NULL),
47 fTasks(NULL),
48 fTopTasks(NULL),
49 fZombies(NULL)
d3106602 50{
51// Default constructor.
37a26056 52 if (TClass::IsCallingNew() != TClass::kDummyNew) {
d3106602 53 fContainers = new TObjArray();
54 fInputs = new TObjArray();
55 fOutputs = new TObjArray();
56 fTasks = new TObjArray();
57 fTopTasks = new TObjArray();
58 fZombies = new TObjArray();
59// fStatus = new AliAnalysisInfo(this);
60 }
61}
62
5daf9fd2 63#ifdef NEVER
d3106602 64//______________________________________________________________________________
65AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
37a26056 66 :TSelector(other),
327eaf46 67 fTree(NULL),
37a26056 68 fInitOK(kFALSE),
69 fContainers(NULL),
70 fInputs(NULL),
71 fOutputs(NULL),
72 fTasks(NULL),
73 fTopTasks(NULL),
74 fZombies(NULL)
d3106602 75{
76// Copy constructor.
37a26056 77 fInitOK = other.fInitOK;
78 fContainers = new TObjArray(*other.fContainers);
79 fInputs = new TObjArray(*other.fInputs);
80 fOutputs = new TObjArray(*other.fOutputs);
81 fTasks = new TObjArray(*other.fTasks);
82 fTopTasks = new TObjArray(*other.fTopTasks);
83 fZombies = new TObjArray(*other.fZombies);
d3106602 84// fStatus = new AliAnalysisInfo(this);
85}
86
87//______________________________________________________________________________
88AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
89{
90// Assignment
91 if (&other != this) {
92 TSelector::operator=(other);
327eaf46 93 fTree = other.fTree;
37a26056 94 fInitOK = other.fInitOK;
95 fContainers = new TObjArray(*other.fContainers);
96 fInputs = new TObjArray(*other.fInputs);
97 fOutputs = new TObjArray(*other.fOutputs);
98 fTasks = new TObjArray(*other.fTasks);
99 fTopTasks = new TObjArray(*other.fTopTasks);
100 fZombies = new TObjArray(*other.fZombies);
d3106602 101// fStatus = new AliAnalysisInfo(this);
102 }
103 return *this;
104}
5daf9fd2 105#endif
d3106602 106
107//______________________________________________________________________________
108AliAnalysisManager::~AliAnalysisManager()
109{
110// Destructor.
111 if (fContainers) {fContainers->Delete(); delete fContainers;}
112 if (fInputs) delete fInputs;
113 if (fOutputs) delete fOutputs;
114 if (fTasks) {fTasks->Delete(); delete fTasks;}
115 if (fTopTasks) delete fTopTasks;
116 if (fZombies) delete fZombies;
117}
d3106602 118//______________________________________________________________________________
327eaf46 119Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
120{
121// Read one entry of the tree or a whole branch.
122 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
123}
124
125//______________________________________________________________________________
126void AliAnalysisManager::Init(TTree *tree)
d3106602 127{
128 // The Init() function is called when the selector needs to initialize
129 // a new tree or chain. Typically here the branch addresses of the tree
130 // will be set. It is normaly not necessary to make changes to the
131 // generated code, but the routine can be extended by the user if needed.
132 // Init() will be called many times when running with PROOF.
327eaf46 133 printf("AliAnalysisManager::Init(%s)\n", tree->GetName());
134 if (!fInitOK) {
135 AliError("You have to call InitAnalysis first");
136 return;
137 }
138 if (!tree) return;
139 fTree = tree;
140 AliAnalysisDataContainer *top = (AliAnalysisDataContainer*)fInputs->At(0);
141 top->SetData(tree);
d3106602 142}
143
144//______________________________________________________________________________
327eaf46 145void AliAnalysisManager::Begin(TTree *tree)
d3106602 146{
147 // The Begin() function is called at the start of the query.
148 // When running with PROOF Begin() is only called on the client.
149 // The tree argument is deprecated (on PROOF 0 is passed).
327eaf46 150 printf("AliAnalysisManager::Begin(%s)\n", tree->GetName());
151 Init(tree);
d3106602 152}
153
154//______________________________________________________________________________
327eaf46 155void AliAnalysisManager::SlaveBegin(TTree *tree)
d3106602 156{
157 // The SlaveBegin() function is called after the Begin() function.
158 // When running with PROOF SlaveBegin() is called on each slave server.
159 // The tree argument is deprecated (on PROOF 0 is passed).
327eaf46 160 printf("AliAnalysisManager::SlaveBegin(%s)\n", tree->GetName());
161 Init(tree);
d3106602 162}
163
164//______________________________________________________________________________
327eaf46 165Bool_t AliAnalysisManager::Notify()
166{
167 // The Notify() function is called when a new file is opened. This
168 // can be either for a new TTree in a TChain or when when a new TTree
169 // is started when using PROOF. It is normaly not necessary to make changes
170 // to the generated code, but the routine can be extended by the
171 // user if needed. The return value is currently not used.
172 if (fTree) {
173 TFile *curfile = fTree->GetCurrentFile();
174 if (curfile) printf("AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
175 }
176 return kTRUE;
177}
178
179//______________________________________________________________________________
180Bool_t AliAnalysisManager::Process(Long64_t entry)
d3106602 181{
182 // The Process() function is called for each entry in the tree (or possibly
183 // keyed object in the case of PROOF) to be processed. The entry argument
184 // specifies which entry in the currently loaded tree is to be processed.
185 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
186 // to read either all or the required parts of the data. When processing
187 // keyed objects with PROOF, the object is already loaded and is available
188 // via the fObject pointer.
189 //
190 // This function should contain the "body" of the analysis. It can contain
191 // simple or elaborate selection criteria, run algorithms on the data
192 // of the event and typically fill histograms.
193
194 // WARNING when a selector is used with a TChain, you must use
195 // the pointer to the current TTree to call GetEntry(entry).
196 // The entry is always the local entry number in the current tree.
197 // Assuming that fChain is the pointer to the TChain being processed,
198 // use fChain->GetTree()->GetEntry(entry).
327eaf46 199
200// printf("AliAnalysisManager::Process(%lld)\n", entry);
201 GetEntry(entry);
202 ExecAnalysis();
203 return kTRUE;
d3106602 204}
205
206//______________________________________________________________________________
207void AliAnalysisManager::SlaveTerminate()
208{
209 // The SlaveTerminate() function is called after all entries or objects
210 // have been processed. When running with PROOF SlaveTerminate() is called
211 // on each slave server.
327eaf46 212
213 printf("AliAnalysisManager::SlaveTerminate()\n");
214 if (!fOutput)
215 {
216 AliError("ERROR: Output list not initialized.");
217 return;
218 }
219 TIter next(fOutputs);
220 AliAnalysisDataContainer *output;
221 while ((output=(AliAnalysisDataContainer *)next())) {
222 output->SetDataOwned(kFALSE);
223 fOutput->Add(output->GetData());
224 }
d3106602 225}
226
227//______________________________________________________________________________
228void AliAnalysisManager::Terminate()
229{
230 // The Terminate() function is the last function to be called during
231 // a query. It always runs on the client, it can be used to present
232 // the results graphically or save the results to file.
327eaf46 233 printf("AliAnalysisManager::Terminate()\n");
234 AliAnalysisDataContainer *output;
235 AliAnalysisTask *task;
236 TIter next(fOutputs);
237 while ((output=(AliAnalysisDataContainer *)next())) output->WriteData();
238 TIter next1(fTasks);
239 // Call Terminate() for tasks
240 while ((task=(AliAnalysisTask*)next1())) task->Terminate();
d3106602 241}
242
243//______________________________________________________________________________
244void AliAnalysisManager::AddTask(AliAnalysisTask *task)
245{
246// Adds a user task to the global list of tasks.
247 task->SetActive(kFALSE);
248 fTasks->Add(task);
249}
250
251//______________________________________________________________________________
252AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
253{
254// Retreive task by name.
255 if (!fTasks) return NULL;
256 return (AliAnalysisTask*)fTasks->FindObject(name);
257}
258
259//______________________________________________________________________________
260AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
261 TClass *datatype, EAliAnalysisContType type)
262{
263// Create a data container of a certain type. Types can be:
264// kNormalContainer = 0, used to exchange date between tasks
265// kInputContainer = 1, used to store input data
266// kOutputContainer = 2, used for posting results
267 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
268 fContainers->Add(cont);
269 switch (type) {
270 case kInputContainer:
271 fInputs->Add(cont);
272 break;
273 case kOutputContainer:
274 fOutputs->Add(cont);
275 break;
276 case kNormalContainer:
277 break;
278 }
279 return cont;
280}
281
282//______________________________________________________________________________
283Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
284 AliAnalysisDataContainer *cont)
285{
286// Connect input of an existing task to a data container.
287 if (!fTasks->FindObject(task)) {
288 AddTask(task);
289 AliInfo(Form("Task %s not registered. Now owned by analysis manager", task->GetName()));
290 }
291 Bool_t connected = task->ConnectInput(islot, cont);
292 return connected;
293}
294
295//______________________________________________________________________________
296Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
297 AliAnalysisDataContainer *cont)
298{
299// Connect output of an existing task to a data container.
300 if (!fTasks->FindObject(task)) {
301 AddTask(task);
302 AliInfo(Form("Task %s not registered. Now owned by analysis manager", task->GetName()));
303 }
304 Bool_t connected = task->ConnectOutput(islot, cont);
305 return connected;
306}
307
308//______________________________________________________________________________
309void AliAnalysisManager::CleanContainers()
310{
311// Clean data from all containers that have already finished all client tasks.
312 TIter next(fContainers);
313 AliAnalysisDataContainer *cont;
314 while ((cont=(AliAnalysisDataContainer *)next())) {
315 if (cont->IsOwnedData() &&
316 cont->IsDataReady() &&
317 cont->ClientsExecuted()) cont->DeleteData();
318 }
319}
320
321//______________________________________________________________________________
322Bool_t AliAnalysisManager::InitAnalysis()
323{
324// Initialization of analysis chain of tasks. Should be called after all tasks
325// and data containers are properly connected
326 // Check for input/output containers
327 fInitOK = kFALSE;
327eaf46 328// if (!fInputs->GetEntriesFast()) {
329// AliError("No input container defined. At least one container should store input data");
330// return kFALSE;
331// }
332// if (!fOutputs->GetEntriesFast()) {
333// AliError("No output container defined. At least one container should store output data");
334// return kFALSE;
335// }
d3106602 336 // Check for top tasks (depending only on input data containers)
337 if (!fTasks->First()) {
338 AliError("Analysis have no tasks !");
339 return kFALSE;
340 }
341 TIter next(fTasks);
342 AliAnalysisTask *task;
343 AliAnalysisDataContainer *cont;
344 Int_t ntop = 0;
345 Int_t nzombies = 0;
327eaf46 346 Bool_t iszombie = kFALSE;
347 Bool_t istop = kTRUE;
d3106602 348 Int_t i;
349 while ((task=(AliAnalysisTask*)next())) {
327eaf46 350 istop = kTRUE;
351 iszombie = kFALSE;
d3106602 352 Int_t ninputs = task->GetNinputs();
327eaf46 353// if (!ninputs) {
354// task->SetZombie();
355// fZombies->Add(task);
356// nzombies++;
357// AliWarning(Form("Task %s has no input slots defined ! Declared zombie...",task->GetName()));
358// continue;
359// }
d3106602 360 for (i=0; i<ninputs; i++) {
361 cont = task->GetInputSlot(i)->GetContainer();
362 if (!cont) {
327eaf46 363 if (!iszombie) {
d3106602 364 task->SetZombie();
365 fZombies->Add(task);
366 nzombies++;
327eaf46 367 iszombie = kTRUE;
d3106602 368 }
369 AliWarning(Form("Input slot %i of task %s has no container connected ! Declared zombie...",
370 i,task->GetName()));
371 }
327eaf46 372 if (iszombie) continue;
d3106602 373 // Check if cont is an input container
327eaf46 374 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 375 // Connect to parent task
376 }
327eaf46 377 if (istop) {
d3106602 378 ntop++;
379 fTopTasks->Add(task);
380 }
381 }
382 if (!ntop) {
383 AliError("No top task defined. At least one task should be connected only to input containers");
384 return kFALSE;
385 }
386 // Check now if there are orphan tasks
387 for (i=0; i<ntop; i++) {
388 task = (AliAnalysisTask*)fTopTasks->At(i);
389 task->SetUsed();
390 }
391 Int_t norphans = 0;
392 next.Reset();
393 while ((task=(AliAnalysisTask*)next())) {
394 if (!task->IsUsed()) {
395 norphans++;
396 AliWarning(Form("Task %s is orphan",task->GetName()));
397 }
398 }
399 // Check the task hierarchy (no parent task should depend on data provided
400 // by a daughter task)
401 for (i=0; i<ntop; i++) {
402 task = (AliAnalysisTask*)fTopTasks->At(i);
403 if (task->CheckCircularDeps()) {
404 AliError("Found illegal circular dependencies between following tasks:");
405 PrintStatus("dep");
406 return kFALSE;
407 }
408 }
327eaf46 409 fInitOK = kTRUE;
d3106602 410 return kTRUE;
411}
412
413//______________________________________________________________________________
414void AliAnalysisManager::PrintStatus(Option_t *option) const
415{
416// Print task hierarchy.
417 TIter next(fTopTasks);
418 AliAnalysisTask *task;
419 while ((task=(AliAnalysisTask*)next()))
420 task->PrintTask(option);
421}
422
423//______________________________________________________________________________
424void AliAnalysisManager::ResetAnalysis()
425{
426// Reset all execution flags and clean containers.
427 CleanContainers();
428}
429
430//______________________________________________________________________________
431void AliAnalysisManager::ExecAnalysis(Option_t *option)
432{
433// Execute analysis.
327eaf46 434 if (!fInitOK) {
435 AliError("Analysis manager was not initialized !");
436 return;
437 }
d3106602 438 AliAnalysisTask *task;
327eaf46 439 // Check if the top tree is active.
440 if (fTree) {
441 TIter next(fTasks);
442 // De-activate all tasks
443 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
444 AliAnalysisDataContainer *cont = (AliAnalysisDataContainer*)fInputs->At(0);
445 if (!cont) {
446 AliError("Cannot execute analysis in TSelector mode without at least one top container");
447 return;
448 }
449 cont->SetData(fTree); // This will notify all consumers
450 TIter next1(cont->GetConsumers());
451 while ((task=(AliAnalysisTask*)next1())) {
452// task->SetActive(kTRUE);
453 task->ExecuteTask(option);
454 }
455 return;
456 }
457 // The event loop is not controlled by TSelector
458 TIter next2(fTopTasks);
459 while ((task=(AliAnalysisTask*)next2())) {
460 task->SetActive(kTRUE);
461 printf("executing %s\n", task->GetName());
d3106602 462 task->ExecuteTask(option);
327eaf46 463 }
d3106602 464}
465
466//______________________________________________________________________________
467void AliAnalysisManager::FinishAnalysis()
468{
469// Finish analysis.
470}