Add new abstract base classes (Markus)
[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
37153431 21// analysis tasks and data containers storing their input/output. Allows
d3106602 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
c52c2132 28#include <Riostream.h>
11026a80 29
c52c2132 30#include <TClass.h>
31#include <TFile.h>
32#include <TMethodCall.h>
33#include <TChain.h>
34#include <TSystem.h>
35#include <TROOT.h>
d3106602 36
d3106602 37#include "AliAnalysisTask.h"
38#include "AliAnalysisDataContainer.h"
39#include "AliAnalysisDataSlot.h"
8c9485b2 40#include "AliVirtualEventHandler.h"
c52c2132 41#include "AliAnalysisManager.h"
d3106602 42
43ClassImp(AliAnalysisManager)
44
c52c2132 45AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
46
d3106602 47//______________________________________________________________________________
c52c2132 48AliAnalysisManager::AliAnalysisManager()
49 :TNamed(),
327eaf46 50 fTree(NULL),
6bb2b24f 51 fOutputEventHandler(NULL),
52 fMCtruthEventHandler(NULL),
c52c2132 53 fCurrentEntry(-1),
54 fMode(kLocalAnalysis),
37a26056 55 fInitOK(kFALSE),
6bb2b24f 56 fDebug(0),
c52c2132 57 fTasks(NULL),
58 fTopTasks(NULL),
59 fZombies(NULL),
37a26056 60 fContainers(NULL),
61 fInputs(NULL),
c52c2132 62 fOutputs(NULL)
63{
64// Dummy constructor.
65 fgAnalysisManager = this;
b1310ef5 66 SetEventLoop(kTRUE);
c52c2132 67}
68
69//______________________________________________________________________________
70AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
71 :TNamed(name,title),
72 fTree(NULL),
6bb2b24f 73 fOutputEventHandler(NULL),
74 fMCtruthEventHandler(NULL),
c52c2132 75 fCurrentEntry(-1),
76 fMode(kLocalAnalysis),
77 fInitOK(kFALSE),
78 fDebug(0),
37a26056 79 fTasks(NULL),
80 fTopTasks(NULL),
c52c2132 81 fZombies(NULL),
82 fContainers(NULL),
83 fInputs(NULL),
84 fOutputs(NULL)
d3106602 85{
86// Default constructor.
c52c2132 87 fgAnalysisManager = this;
88 fTasks = new TObjArray();
89 fTopTasks = new TObjArray();
90 fZombies = new TObjArray();
91 fContainers = new TObjArray();
92 fInputs = new TObjArray();
37153431 93 fOutputs = new TObjArray();
b1310ef5 94 SetEventLoop(kTRUE);
d3106602 95}
96
97//______________________________________________________________________________
98AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
c52c2132 99 :TNamed(other),
327eaf46 100 fTree(NULL),
6bb2b24f 101 fOutputEventHandler(NULL),
102 fMCtruthEventHandler(NULL),
c52c2132 103 fCurrentEntry(-1),
104 fMode(other.fMode),
105 fInitOK(other.fInitOK),
106 fDebug(other.fDebug),
37a26056 107 fTasks(NULL),
108 fTopTasks(NULL),
c52c2132 109 fZombies(NULL),
110 fContainers(NULL),
111 fInputs(NULL),
112 fOutputs(NULL)
d3106602 113{
114// Copy constructor.
37a26056 115 fTasks = new TObjArray(*other.fTasks);
116 fTopTasks = new TObjArray(*other.fTopTasks);
117 fZombies = new TObjArray(*other.fZombies);
c52c2132 118 fContainers = new TObjArray(*other.fContainers);
119 fInputs = new TObjArray(*other.fInputs);
120 fOutputs = new TObjArray(*other.fOutputs);
121 fgAnalysisManager = this;
d3106602 122}
123
124//______________________________________________________________________________
125AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
126{
127// Assignment
128 if (&other != this) {
c52c2132 129 TNamed::operator=(other);
6bb2b24f 130 fOutputEventHandler = other.fOutputEventHandler;
131 fMCtruthEventHandler = other.fMCtruthEventHandler;
c52c2132 132 fTree = NULL;
133 fCurrentEntry = -1;
134 fMode = other.fMode;
37a26056 135 fInitOK = other.fInitOK;
c52c2132 136 fDebug = other.fDebug;
37a26056 137 fTasks = new TObjArray(*other.fTasks);
138 fTopTasks = new TObjArray(*other.fTopTasks);
139 fZombies = new TObjArray(*other.fZombies);
c52c2132 140 fContainers = new TObjArray(*other.fContainers);
141 fInputs = new TObjArray(*other.fInputs);
142 fOutputs = new TObjArray(*other.fOutputs);
143 fgAnalysisManager = this;
d3106602 144 }
145 return *this;
146}
147
148//______________________________________________________________________________
149AliAnalysisManager::~AliAnalysisManager()
150{
151// Destructor.
d3106602 152 if (fTasks) {fTasks->Delete(); delete fTasks;}
153 if (fTopTasks) delete fTopTasks;
154 if (fZombies) delete fZombies;
c52c2132 155 if (fContainers) {fContainers->Delete(); delete fContainers;}
156 if (fInputs) delete fInputs;
157 if (fOutputs) delete fOutputs;
158 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
d3106602 159}
c52c2132 160
d3106602 161//______________________________________________________________________________
327eaf46 162Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
163{
164// Read one entry of the tree or a whole branch.
c52c2132 165 if (fDebug > 1) {
166 cout << "== AliAnalysisManager::GetEntry()" << endl;
167 }
168 fCurrentEntry = entry;
327eaf46 169 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
170}
171
172//______________________________________________________________________________
173void AliAnalysisManager::Init(TTree *tree)
d3106602 174{
175 // The Init() function is called when the selector needs to initialize
176 // a new tree or chain. Typically here the branch addresses of the tree
177 // will be set. It is normaly not necessary to make changes to the
178 // generated code, but the routine can be extended by the user if needed.
179 // Init() will be called many times when running with PROOF.
327eaf46 180 if (!tree) return;
c52c2132 181 if (fDebug > 1) {
981f2614 182 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
c52c2132 183 }
184 if (!fInitOK) InitAnalysis();
185 if (!fInitOK) return;
327eaf46 186 fTree = tree;
187 AliAnalysisDataContainer *top = (AliAnalysisDataContainer*)fInputs->At(0);
c52c2132 188 if (!top) {
189 cout<<"Error: No top input container !" <<endl;
190 return;
37153431 191 }
327eaf46 192 top->SetData(tree);
981f2614 193 if (fDebug > 1) {
194 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
195 }
d3106602 196}
197
198//______________________________________________________________________________
327eaf46 199void AliAnalysisManager::Begin(TTree *tree)
d3106602 200{
201 // The Begin() function is called at the start of the query.
202 // When running with PROOF Begin() is only called on the client.
203 // The tree argument is deprecated (on PROOF 0 is passed).
c52c2132 204 if (fDebug > 1) {
205 cout << "AliAnalysisManager::Begin()" << endl;
206 }
327eaf46 207 Init(tree);
d3106602 208}
209
210//______________________________________________________________________________
327eaf46 211void AliAnalysisManager::SlaveBegin(TTree *tree)
d3106602 212{
213 // The SlaveBegin() function is called after the Begin() function.
214 // When running with PROOF SlaveBegin() is called on each slave server.
215 // The tree argument is deprecated (on PROOF 0 is passed).
c52c2132 216 if (fDebug > 1) {
981f2614 217 cout << "->AliAnalysisManager::SlaveBegin()" << endl;
37153431 218 }
8c9485b2 219 // Call InitIO of EventHandler
6bb2b24f 220 if (fOutputEventHandler) {
8ca08916 221 if (fMode == kProofAnalysis) {
6bb2b24f 222 fOutputEventHandler->InitIO("proof");
8ca08916 223 } else {
6bb2b24f 224 fOutputEventHandler->InitIO("local");
8ca08916 225 }
bcce695f 226 }
8c9485b2 227 //
c52c2132 228 TIter next(fTasks);
229 AliAnalysisTask *task;
230 // Call CreateOutputObjects for all tasks
c5a87c56 231 while ((task=(AliAnalysisTask*)next())) {
232 TDirectory *curdir = gDirectory;
c52c2132 233 task->CreateOutputObjects();
c5a87c56 234 if (curdir) curdir->cd();
235 }
c52c2132 236 if (fMode == kLocalAnalysis) Init(tree);
981f2614 237 if (fDebug > 1) {
238 cout << "<-AliAnalysisManager::SlaveBegin()" << endl;
239 }
d3106602 240}
241
242//______________________________________________________________________________
327eaf46 243Bool_t AliAnalysisManager::Notify()
244{
245 // The Notify() function is called when a new file is opened. This
246 // can be either for a new TTree in a TChain or when when a new TTree
247 // is started when using PROOF. It is normaly not necessary to make changes
248 // to the generated code, but the routine can be extended by the
249 // user if needed. The return value is currently not used.
250 if (fTree) {
251 TFile *curfile = fTree->GetCurrentFile();
c52c2132 252 if (curfile && fDebug>1) printf("AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
981f2614 253 TIter next(fTasks);
254 AliAnalysisTask *task;
255 // Call Notify for all tasks
256 while ((task=(AliAnalysisTask*)next()))
6bb2b24f 257 task->Notify();
890126ab 258
6bb2b24f 259 // Call Notify of the MC truth handler
890126ab 260 if (fMCtruthEventHandler) {
261 TString fileName(curfile->GetName());
262 fileName.ReplaceAll("AliESDs.root", "");
263 fMCtruthEventHandler->Notify(fileName.Data());
264 }
327eaf46 265 }
266 return kTRUE;
267}
268
269//______________________________________________________________________________
270Bool_t AliAnalysisManager::Process(Long64_t entry)
d3106602 271{
272 // The Process() function is called for each entry in the tree (or possibly
273 // keyed object in the case of PROOF) to be processed. The entry argument
274 // specifies which entry in the currently loaded tree is to be processed.
275 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
276 // to read either all or the required parts of the data. When processing
277 // keyed objects with PROOF, the object is already loaded and is available
278 // via the fObject pointer.
279 //
280 // This function should contain the "body" of the analysis. It can contain
281 // simple or elaborate selection criteria, run algorithms on the data
282 // of the event and typically fill histograms.
283
284 // WARNING when a selector is used with a TChain, you must use
285 // the pointer to the current TTree to call GetEntry(entry).
286 // The entry is always the local entry number in the current tree.
287 // Assuming that fChain is the pointer to the TChain being processed,
288 // use fChain->GetTree()->GetEntry(entry).
c52c2132 289 if (fDebug > 1) {
981f2614 290 cout << "->AliAnalysisManager::Process()" << endl;
37153431 291 }
6bb2b24f 292
293 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent();
294 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent();
295
327eaf46 296 GetEntry(entry);
297 ExecAnalysis();
981f2614 298 if (fDebug > 1) {
299 cout << "<-AliAnalysisManager::Process()" << endl;
300 }
327eaf46 301 return kTRUE;
d3106602 302}
303
304//______________________________________________________________________________
c52c2132 305void AliAnalysisManager::PackOutput(TList *target)
d3106602 306{
981f2614 307 // Pack all output data containers in the output list. Called at SlaveTerminate
308 // stage in PROOF case for each slave.
c52c2132 309 if (fDebug > 1) {
981f2614 310 cout << "->AliAnalysisManager::PackOutput()" << endl;
c52c2132 311 }
312 if (!target) {
313 Error("PackOutput", "No target. Aborting.");
314 return;
37153431 315 }
c52c2132 316
6bb2b24f 317 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
318 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
8c9485b2 319
c52c2132 320 if (fMode == kProofAnalysis) {
321 TIter next(fOutputs);
322 AliAnalysisDataContainer *output;
323 while ((output=(AliAnalysisDataContainer*)next())) {
981f2614 324 if (fDebug > 1) printf(" Packing container %s...\n", output->GetName());
325 if (output->GetData()) target->Add(output->ExportData());
c52c2132 326 }
327 }
c52c2132 328 if (fDebug > 1) {
981f2614 329 printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
37153431 330 }
c52c2132 331}
332
333//______________________________________________________________________________
981f2614 334void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 335{
981f2614 336// Import data in output containers from wrappers coming in source.
337 if (fDebug > 1) {
338 cout << "->AliAnalysisManager::ImportWrappers()" << endl;
339 }
327eaf46 340 TIter next(fOutputs);
981f2614 341 AliAnalysisDataContainer *cont;
342 AliAnalysisDataWrapper *wrap;
343 Int_t icont = 0;
c52c2132 344 while ((cont=(AliAnalysisDataContainer*)next())) {
981f2614 345 wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
346 if (!wrap && fDebug>1) {
347 printf("(WW) ImportWrappers: container %s not found in analysis output !\n", cont->GetName());
c52c2132 348 continue;
349 }
981f2614 350 icont++;
351 if (fDebug > 1) printf(" Importing data for container %s\n", wrap->GetName());
352 if (cont->GetFileName()) printf(" -> %s\n", cont->GetFileName());
353 cont->ImportData(wrap);
c52c2132 354 }
981f2614 355 if (fDebug > 1) {
356 cout << "<-AliAnalysisManager::ImportWrappers(): "<< icont << " containers imported" << endl;
357 }
c52c2132 358}
359
360//______________________________________________________________________________
361void AliAnalysisManager::UnpackOutput(TList *source)
362{
363 // Called by AliAnalysisSelector::Terminate. Output containers should
364 // be in source in the same order as in fOutputs.
981f2614 365 if (fDebug > 1) {
366 cout << "->AliAnalysisManager::UnpackOutput()" << endl;
367 }
c52c2132 368 if (!source) {
981f2614 369 Error("UnpackOutput", "No target. Aborting.");
c52c2132 370 return;
371 }
372 if (fDebug > 1) {
c52c2132 373 printf(" Source list contains %d containers\n", source->GetSize());
327eaf46 374 }
c52c2132 375
981f2614 376 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 377
981f2614 378 TIter next(fOutputs);
c52c2132 379 AliAnalysisDataContainer *output;
380 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 381 if (!output->GetData()) continue;
b1310ef5 382 // Check if there are client tasks that run post event loop
383 if (output->HasConsumers()) {
384 // Disable event loop semaphore
385 output->SetPostEventLoop(kTRUE);
386 TObjArray *list = output->GetConsumers();
387 Int_t ncons = list->GetEntriesFast();
388 for (Int_t i=0; i<ncons; i++) {
389 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
390 task->CheckNotify(kTRUE);
391 // If task is active, execute it
392 if (task->IsPostEventLoop() && task->IsActive()) {
393 if (fDebug > 1) {
394 cout << "== Executing post event loop task " << task->GetName() << endl;
395 }
396 task->ExecuteTask();
397 }
398 }
399 }
c52c2132 400 // Check if the output need to be written to a file.
401 const char *filename = output->GetFileName();
8ca08916 402 if (!(strcmp(filename, "default"))) {
6bb2b24f 403 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
8ca08916 404 }
405
c52c2132 406 if (!filename || !strlen(filename)) continue;
407 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
408 if (file) file->cd();
409 else file = new TFile(filename, "RECREATE");
410 if (file->IsZombie()) continue;
411 // Reparent data to this file
412 TMethodCall callEnv;
413 if (output->GetData()->IsA())
414 callEnv.InitWithPrototype(output->GetData()->IsA(), "SetDirectory", "TDirectory*");
415 if (callEnv.IsValid()) {
416 callEnv.SetParam((Long_t) file);
417 callEnv.Execute(output->GetData());
418 }
b1109411 419 output->GetData()->Write();
c52c2132 420 }
981f2614 421 if (fDebug > 1) {
422 cout << "<-AliAnalysisManager::UnpackOutput()" << endl;
423 }
d3106602 424}
425
426//______________________________________________________________________________
427void AliAnalysisManager::Terminate()
428{
429 // The Terminate() function is the last function to be called during
430 // a query. It always runs on the client, it can be used to present
c52c2132 431 // the results graphically.
432 if (fDebug > 1) {
981f2614 433 cout << "->AliAnalysisManager::Terminate()" << endl;
c52c2132 434 }
327eaf46 435 AliAnalysisTask *task;
c52c2132 436 TIter next(fTasks);
327eaf46 437 // Call Terminate() for tasks
c52c2132 438 while ((task=(AliAnalysisTask*)next())) task->Terminate();
981f2614 439 if (fDebug > 1) {
440 cout << "<-AliAnalysisManager::Terminate()" << endl;
441 }
8c9485b2 442 //
6bb2b24f 443 if (fOutputEventHandler) fOutputEventHandler->TerminateIO();
d3106602 444}
445
446//______________________________________________________________________________
447void AliAnalysisManager::AddTask(AliAnalysisTask *task)
448{
449// Adds a user task to the global list of tasks.
450 task->SetActive(kFALSE);
451 fTasks->Add(task);
452}
453
454//______________________________________________________________________________
455AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
456{
457// Retreive task by name.
458 if (!fTasks) return NULL;
459 return (AliAnalysisTask*)fTasks->FindObject(name);
460}
461
462//______________________________________________________________________________
463AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 464 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 465{
466// Create a data container of a certain type. Types can be:
c52c2132 467// kExchangeContainer = 0, used to exchange date between tasks
d3106602 468// kInputContainer = 1, used to store input data
469// kOutputContainer = 2, used for posting results
b1310ef5 470 if (fContainers->FindObject(name)) {
471 Error("CreateContainer","A container named %s already defined !\n",name);
472 return NULL;
473 }
d3106602 474 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
475 fContainers->Add(cont);
476 switch (type) {
477 case kInputContainer:
478 fInputs->Add(cont);
479 break;
480 case kOutputContainer:
481 fOutputs->Add(cont);
c52c2132 482 if (filename && strlen(filename)) cont->SetFileName(filename);
d3106602 483 break;
c52c2132 484 case kExchangeContainer:
d3106602 485 break;
486 }
487 return cont;
488}
489
490//______________________________________________________________________________
491Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
492 AliAnalysisDataContainer *cont)
493{
494// Connect input of an existing task to a data container.
495 if (!fTasks->FindObject(task)) {
496 AddTask(task);
c52c2132 497 Warning("ConnectInput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 498 }
499 Bool_t connected = task->ConnectInput(islot, cont);
500 return connected;
501}
502
503//______________________________________________________________________________
504Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
505 AliAnalysisDataContainer *cont)
506{
507// Connect output of an existing task to a data container.
508 if (!fTasks->FindObject(task)) {
509 AddTask(task);
c52c2132 510 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 511 }
512 Bool_t connected = task->ConnectOutput(islot, cont);
513 return connected;
514}
515
516//______________________________________________________________________________
517void AliAnalysisManager::CleanContainers()
518{
519// Clean data from all containers that have already finished all client tasks.
520 TIter next(fContainers);
521 AliAnalysisDataContainer *cont;
522 while ((cont=(AliAnalysisDataContainer *)next())) {
523 if (cont->IsOwnedData() &&
524 cont->IsDataReady() &&
525 cont->ClientsExecuted()) cont->DeleteData();
526 }
527}
528
529//______________________________________________________________________________
530Bool_t AliAnalysisManager::InitAnalysis()
531{
532// Initialization of analysis chain of tasks. Should be called after all tasks
533// and data containers are properly connected
534 // Check for input/output containers
535 fInitOK = kFALSE;
d3106602 536 // Check for top tasks (depending only on input data containers)
537 if (!fTasks->First()) {
c52c2132 538 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 539 return kFALSE;
540 }
541 TIter next(fTasks);
542 AliAnalysisTask *task;
543 AliAnalysisDataContainer *cont;
544 Int_t ntop = 0;
545 Int_t nzombies = 0;
327eaf46 546 Bool_t iszombie = kFALSE;
547 Bool_t istop = kTRUE;
d3106602 548 Int_t i;
549 while ((task=(AliAnalysisTask*)next())) {
327eaf46 550 istop = kTRUE;
551 iszombie = kFALSE;
d3106602 552 Int_t ninputs = task->GetNinputs();
d3106602 553 for (i=0; i<ninputs; i++) {
554 cont = task->GetInputSlot(i)->GetContainer();
555 if (!cont) {
327eaf46 556 if (!iszombie) {
d3106602 557 task->SetZombie();
558 fZombies->Add(task);
559 nzombies++;
327eaf46 560 iszombie = kTRUE;
d3106602 561 }
c52c2132 562 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
563 i, task->GetName());
d3106602 564 }
327eaf46 565 if (iszombie) continue;
d3106602 566 // Check if cont is an input container
327eaf46 567 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 568 // Connect to parent task
569 }
327eaf46 570 if (istop) {
d3106602 571 ntop++;
572 fTopTasks->Add(task);
573 }
574 }
575 if (!ntop) {
c52c2132 576 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 577 return kFALSE;
578 }
579 // Check now if there are orphan tasks
580 for (i=0; i<ntop; i++) {
581 task = (AliAnalysisTask*)fTopTasks->At(i);
582 task->SetUsed();
583 }
584 Int_t norphans = 0;
585 next.Reset();
586 while ((task=(AliAnalysisTask*)next())) {
587 if (!task->IsUsed()) {
588 norphans++;
c52c2132 589 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 590 }
591 }
592 // Check the task hierarchy (no parent task should depend on data provided
593 // by a daughter task)
594 for (i=0; i<ntop; i++) {
595 task = (AliAnalysisTask*)fTopTasks->At(i);
596 if (task->CheckCircularDeps()) {
c52c2132 597 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 598 PrintStatus("dep");
599 return kFALSE;
600 }
601 }
b1310ef5 602 // Check that all containers feeding post-event loop tasks are in the outputs list
603 TIter nextcont(fContainers); // loop over all containers
604 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
605 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
606 if (cont->HasConsumers()) {
607 // Check if one of the consumers is post event loop
608 TIter nextconsumer(cont->GetConsumers());
609 while ((task=(AliAnalysisTask*)nextconsumer())) {
610 if (task->IsPostEventLoop()) {
611 fOutputs->Add(cont);
612 break;
613 }
614 }
615 }
616 }
617 }
327eaf46 618 fInitOK = kTRUE;
d3106602 619 return kTRUE;
620}
621
622//______________________________________________________________________________
623void AliAnalysisManager::PrintStatus(Option_t *option) const
624{
625// Print task hierarchy.
626 TIter next(fTopTasks);
627 AliAnalysisTask *task;
628 while ((task=(AliAnalysisTask*)next()))
629 task->PrintTask(option);
630}
631
632//______________________________________________________________________________
633void AliAnalysisManager::ResetAnalysis()
634{
635// Reset all execution flags and clean containers.
636 CleanContainers();
637}
638
639//______________________________________________________________________________
c52c2132 640void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree)
641{
642// Start analysis for this manager. Analysis task can be: LOCAL, PROOF or GRID.
643 if (!fInitOK) {
644 Error("StartAnalysis","Analysis manager was not initialized !");
645 return;
646 }
647 if (fDebug>1) {
648 cout << "StartAnalysis: " << GetName() << endl;
649 }
650 TString anaType = type;
651 anaType.ToLower();
652 fMode = kLocalAnalysis;
653 if (tree) {
654 if (anaType.Contains("proof")) fMode = kProofAnalysis;
655 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
656 }
657 if (fMode == kGridAnalysis) {
658 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
981f2614 659 fMode = kLocalAnalysis;
660 }
efd53803 661 char line[128];
662 SetEventLoop(kFALSE);
b1310ef5 663 // Disable all branches if requested and set event loop mode
efd53803 664 if (tree) {
b1310ef5 665 if (TestBit(kDisableBranches)) {
666 printf("Disabling all branches...\n");
667// tree->SetBranchStatus("*",0); // not yet working
668 }
efd53803 669 SetEventLoop(kTRUE);
670 }
efd53803 671
c52c2132 672 TChain *chain = dynamic_cast<TChain*>(tree);
9b33830a 673
674 // Initialize locally all tasks
675 TIter next(fTasks);
676 AliAnalysisTask *task;
efd53803 677 while ((task=(AliAnalysisTask*)next())) {
efd53803 678 task->LocalInit();
679 }
680
c52c2132 681 switch (fMode) {
682 case kLocalAnalysis:
683 if (!tree) {
981f2614 684 TIter next(fTasks);
685 AliAnalysisTask *task;
686 // Call CreateOutputObjects for all tasks
c5a87c56 687 while ((task=(AliAnalysisTask*)next())) {
688 TDirectory *curdir = gDirectory;
689 task->CreateOutputObjects();
690 if (curdir) curdir->cd();
691 }
c52c2132 692 ExecAnalysis();
981f2614 693 Terminate();
c52c2132 694 return;
695 }
696 // Run tree-based analysis via AliAnalysisSelector
8eedd442 697// gROOT->ProcessLine(".L $ALICE_ROOT/ANALYSIS/AliAnalysisSelector.cxx+");
c52c2132 698 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
699 sprintf(line, "AliAnalysisSelector *selector = new AliAnalysisSelector((AliAnalysisManager*)0x%lx);",(ULong_t)this);
700 gROOT->ProcessLine(line);
701 sprintf(line, "((TTree*)0x%lx)->Process(selector);",(ULong_t)tree);
702 gROOT->ProcessLine(line);
703 break;
704 case kProofAnalysis:
705 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
706 printf("StartAnalysis: no PROOF!!!\n");
707 return;
708 }
709 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
710 gROOT->ProcessLine(line);
711 if (chain) {
712 chain->SetProof();
713 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
8eedd442 714 chain->Process("AliAnalysisSelector");
c52c2132 715 } else {
716 printf("StartAnalysis: no chain\n");
717 return;
718 }
719 break;
720 case kGridAnalysis:
721 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
722 }
723}
724
725//______________________________________________________________________________
d3106602 726void AliAnalysisManager::ExecAnalysis(Option_t *option)
727{
728// Execute analysis.
327eaf46 729 if (!fInitOK) {
c52c2132 730 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 731 return;
732 }
d3106602 733 AliAnalysisTask *task;
327eaf46 734 // Check if the top tree is active.
735 if (fTree) {
c52c2132 736 if (fDebug>1) {
737 printf("AliAnalysisManager::ExecAnalysis\n");
738 }
327eaf46 739 TIter next(fTasks);
740 // De-activate all tasks
741 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
742 AliAnalysisDataContainer *cont = (AliAnalysisDataContainer*)fInputs->At(0);
743 if (!cont) {
c52c2132 744 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 745 return;
746 }
747 cont->SetData(fTree); // This will notify all consumers
6bb2b24f 748//
749// Call BeginEvent() for optional output and MC services
750 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent();
751 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent();
752//
753// Execute the tasks
327eaf46 754 TIter next1(cont->GetConsumers());
755 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 756 if (fDebug >1) {
757 cout << " Executing task " << task->GetName() << endl;
758 }
6bb2b24f 759
327eaf46 760 task->ExecuteTask(option);
761 }
6bb2b24f 762//
763// Call FinishEvent() for optional output and MC services
764 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
765 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
766//
327eaf46 767 return;
768 }
769 // The event loop is not controlled by TSelector
6bb2b24f 770//
771// Call BeginEvent() for optional output and MC services
772 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent();
773 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent();
327eaf46 774 TIter next2(fTopTasks);
775 while ((task=(AliAnalysisTask*)next2())) {
776 task->SetActive(kTRUE);
c52c2132 777 if (fDebug > 1) {
778 cout << " Executing task " << task->GetName() << endl;
779 }
d3106602 780 task->ExecuteTask(option);
327eaf46 781 }
6bb2b24f 782//
783// Call FinishEvent() for optional output and MC services
784 if (fOutputEventHandler) fOutputEventHandler->FinishEvent();
785 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 786}
787
788//______________________________________________________________________________
789void AliAnalysisManager::FinishAnalysis()
790{
791// Finish analysis.
792}