]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisManager.cxx
- Small fix in data ownership by containers
[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>
8c0ab8e8 36#include <TCanvas.h>
d3106602 37
8d7d3b59 38#include "AliAnalysisSelector.h"
d3106602 39#include "AliAnalysisTask.h"
40#include "AliAnalysisDataContainer.h"
41#include "AliAnalysisDataSlot.h"
d2f1d9ef 42#include "AliVEventHandler.h"
c2922515 43#include "AliVEventPool.h"
8c0ab8e8 44#include "AliSysInfo.h"
c52c2132 45#include "AliAnalysisManager.h"
d3106602 46
47ClassImp(AliAnalysisManager)
48
c52c2132 49AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
50
c52c2132 51//______________________________________________________________________________
52AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
53 :TNamed(name,title),
54 fTree(NULL),
8c0ab8e8 55 fInputEventHandler(NULL),
56 fOutputEventHandler(NULL),
57 fMCtruthEventHandler(NULL),
c2922515 58 fEventPool(NULL),
c52c2132 59 fCurrentEntry(-1),
8c0ab8e8 60 fNSysInfo(0),
c52c2132 61 fMode(kLocalAnalysis),
62 fInitOK(kFALSE),
63 fDebug(0),
26f071d8 64 fSpecialOutputLocation(""),
37a26056 65 fTasks(NULL),
66 fTopTasks(NULL),
c52c2132 67 fZombies(NULL),
68 fContainers(NULL),
69 fInputs(NULL),
8d7d3b59 70 fOutputs(NULL),
71 fSelector(NULL)
d3106602 72{
73// Default constructor.
c52c2132 74 fgAnalysisManager = this;
75 fTasks = new TObjArray();
76 fTopTasks = new TObjArray();
77 fZombies = new TObjArray();
78 fContainers = new TObjArray();
79 fInputs = new TObjArray();
37153431 80 fOutputs = new TObjArray();
b1310ef5 81 SetEventLoop(kTRUE);
d3106602 82}
83
84//______________________________________________________________________________
85AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
c52c2132 86 :TNamed(other),
327eaf46 87 fTree(NULL),
8c0ab8e8 88 fInputEventHandler(NULL),
89 fOutputEventHandler(NULL),
90 fMCtruthEventHandler(NULL),
c2922515 91 fEventPool(NULL),
c52c2132 92 fCurrentEntry(-1),
8c0ab8e8 93 fNSysInfo(0),
c52c2132 94 fMode(other.fMode),
95 fInitOK(other.fInitOK),
96 fDebug(other.fDebug),
26f071d8 97 fSpecialOutputLocation(""),
37a26056 98 fTasks(NULL),
99 fTopTasks(NULL),
c52c2132 100 fZombies(NULL),
101 fContainers(NULL),
102 fInputs(NULL),
8d7d3b59 103 fOutputs(NULL),
104 fSelector(NULL)
d3106602 105{
106// Copy constructor.
37a26056 107 fTasks = new TObjArray(*other.fTasks);
108 fTopTasks = new TObjArray(*other.fTopTasks);
109 fZombies = new TObjArray(*other.fZombies);
c52c2132 110 fContainers = new TObjArray(*other.fContainers);
111 fInputs = new TObjArray(*other.fInputs);
112 fOutputs = new TObjArray(*other.fOutputs);
113 fgAnalysisManager = this;
d3106602 114}
115
116//______________________________________________________________________________
117AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
118{
119// Assignment
120 if (&other != this) {
c52c2132 121 TNamed::operator=(other);
54cff064 122 fInputEventHandler = other.fInputEventHandler;
6bb2b24f 123 fOutputEventHandler = other.fOutputEventHandler;
124 fMCtruthEventHandler = other.fMCtruthEventHandler;
c2922515 125 fEventPool = other.fEventPool;
c52c2132 126 fTree = NULL;
127 fCurrentEntry = -1;
8c0ab8e8 128 fNSysInfo = other.fNSysInfo;
c52c2132 129 fMode = other.fMode;
37a26056 130 fInitOK = other.fInitOK;
c52c2132 131 fDebug = other.fDebug;
37a26056 132 fTasks = new TObjArray(*other.fTasks);
133 fTopTasks = new TObjArray(*other.fTopTasks);
134 fZombies = new TObjArray(*other.fZombies);
c52c2132 135 fContainers = new TObjArray(*other.fContainers);
136 fInputs = new TObjArray(*other.fInputs);
137 fOutputs = new TObjArray(*other.fOutputs);
8d7d3b59 138 fSelector = NULL;
c52c2132 139 fgAnalysisManager = this;
d3106602 140 }
141 return *this;
142}
143
144//______________________________________________________________________________
145AliAnalysisManager::~AliAnalysisManager()
146{
147// Destructor.
d3106602 148 if (fTasks) {fTasks->Delete(); delete fTasks;}
149 if (fTopTasks) delete fTopTasks;
150 if (fZombies) delete fZombies;
c52c2132 151 if (fContainers) {fContainers->Delete(); delete fContainers;}
152 if (fInputs) delete fInputs;
153 if (fOutputs) delete fOutputs;
154 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
d3106602 155}
c52c2132 156
d3106602 157//______________________________________________________________________________
327eaf46 158Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
159{
160// Read one entry of the tree or a whole branch.
8d7d3b59 161 if (fDebug > 0) printf("== AliAnalysisManager::GetEntry(%lld)\n", entry);
c52c2132 162 fCurrentEntry = entry;
327eaf46 163 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
164}
165
166//______________________________________________________________________________
167void AliAnalysisManager::Init(TTree *tree)
d3106602 168{
169 // The Init() function is called when the selector needs to initialize
170 // a new tree or chain. Typically here the branch addresses of the tree
171 // will be set. It is normaly not necessary to make changes to the
172 // generated code, but the routine can be extended by the user if needed.
173 // Init() will be called many times when running with PROOF.
327eaf46 174 if (!tree) return;
8d7d3b59 175 if (fDebug > 0) {
176 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
c52c2132 177 }
fdb458ec 178
f3d59a0d 179 // Call InitTree of EventHandler
36e82a52 180 if (fOutputEventHandler) {
181 if (fMode == kProofAnalysis) {
f3d59a0d 182 fOutputEventHandler->Init(0x0, "proof");
36e82a52 183 } else {
f3d59a0d 184 fOutputEventHandler->Init(0x0, "local");
36e82a52 185 }
186 }
187
fdb458ec 188 if (fInputEventHandler) {
36e82a52 189 if (fMode == kProofAnalysis) {
f3d59a0d 190 fInputEventHandler->Init(tree, "proof");
36e82a52 191 } else {
f3d59a0d 192 fInputEventHandler->Init(tree, "local");
36e82a52 193 }
e7ae3836 194 } else {
195 // If no input event handler we need to get the tree once
196 // for the chain
197 if(!tree->GetTree()) tree->LoadTree(0);
36e82a52 198 }
e7ae3836 199
36e82a52 200
201 if (fMCtruthEventHandler) {
202 if (fMode == kProofAnalysis) {
f3d59a0d 203 fMCtruthEventHandler->Init(0x0, "proof");
36e82a52 204 } else {
f3d59a0d 205 fMCtruthEventHandler->Init(0x0, "local");
36e82a52 206 }
fdb458ec 207 }
208
c52c2132 209 if (!fInitOK) InitAnalysis();
210 if (!fInitOK) return;
327eaf46 211 fTree = tree;
212 AliAnalysisDataContainer *top = (AliAnalysisDataContainer*)fInputs->At(0);
c52c2132 213 if (!top) {
8d7d3b59 214 Error("Init","No top input container !");
c52c2132 215 return;
37153431 216 }
327eaf46 217 top->SetData(tree);
8d7d3b59 218 if (fDebug > 0) {
981f2614 219 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
220 }
d3106602 221}
222
d3106602 223//______________________________________________________________________________
327eaf46 224void AliAnalysisManager::SlaveBegin(TTree *tree)
d3106602 225{
226 // The SlaveBegin() function is called after the Begin() function.
227 // When running with PROOF SlaveBegin() is called on each slave server.
228 // The tree argument is deprecated (on PROOF 0 is passed).
8d7d3b59 229 if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
aee5ee44 230 static Bool_t isCalled = kFALSE;
231 // Call SlaveBegin only once in case of mixing
232 if (isCalled && fMode==kMixingAnalysis) return;
f3d59a0d 233 // Call Init of EventHandler
234 if (fOutputEventHandler) {
235 if (fMode == kProofAnalysis) {
236 fOutputEventHandler->Init("proof");
237 } else {
238 fOutputEventHandler->Init("local");
239 }
240 }
241
242 if (fInputEventHandler) {
243 fInputEventHandler->SetInputTree(tree);
244 if (fMode == kProofAnalysis) {
245 fInputEventHandler->Init("proof");
246 } else {
247 fInputEventHandler->Init("local");
248 }
249 }
250
251 if (fMCtruthEventHandler) {
252 if (fMode == kProofAnalysis) {
253 fMCtruthEventHandler->Init("proof");
254 } else {
255 fMCtruthEventHandler->Init("local");
256 }
257 }
258
c52c2132 259 TIter next(fTasks);
260 AliAnalysisTask *task;
261 // Call CreateOutputObjects for all tasks
c5a87c56 262 while ((task=(AliAnalysisTask*)next())) {
263 TDirectory *curdir = gDirectory;
c52c2132 264 task->CreateOutputObjects();
c5a87c56 265 if (curdir) curdir->cd();
36e82a52 266 }
aee5ee44 267 isCalled = kTRUE;
36e82a52 268
8d7d3b59 269 if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
d3106602 270}
271
272//______________________________________________________________________________
327eaf46 273Bool_t AliAnalysisManager::Notify()
274{
275 // The Notify() function is called when a new file is opened. This
276 // can be either for a new TTree in a TChain or when when a new TTree
277 // is started when using PROOF. It is normaly not necessary to make changes
278 // to the generated code, but the routine can be extended by the
279 // user if needed. The return value is currently not used.
8d7d3b59 280 if (!fTree) {
281 Error("Notify","No current tree.");
282 return kFALSE;
283 }
284 TFile *curfile = fTree->GetCurrentFile();
285 if (!curfile) {
286 Error("Notify","No current file");
287 return kFALSE;
288 }
289
290 if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
291 TIter next(fTasks);
292 AliAnalysisTask *task;
293 // Call Notify for all tasks
294 while ((task=(AliAnalysisTask*)next()))
295 task->Notify();
fdb458ec 296
8d7d3b59 297 // Call Notify of the event handlers
298 if (fInputEventHandler) {
299 fInputEventHandler->Notify(curfile->GetName());
300 }
6073f8c9 301
8d7d3b59 302 if (fOutputEventHandler) {
303 fOutputEventHandler->Notify(curfile->GetName());
304 }
890126ab 305
8d7d3b59 306 if (fMCtruthEventHandler) {
307 fMCtruthEventHandler->Notify(curfile->GetName());
308 }
309 if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
310 return kTRUE;
327eaf46 311}
312
313//______________________________________________________________________________
314Bool_t AliAnalysisManager::Process(Long64_t entry)
d3106602 315{
316 // The Process() function is called for each entry in the tree (or possibly
317 // keyed object in the case of PROOF) to be processed. The entry argument
318 // specifies which entry in the currently loaded tree is to be processed.
319 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
320 // to read either all or the required parts of the data. When processing
321 // keyed objects with PROOF, the object is already loaded and is available
322 // via the fObject pointer.
323 //
324 // This function should contain the "body" of the analysis. It can contain
325 // simple or elaborate selection criteria, run algorithms on the data
326 // of the event and typically fill histograms.
327
328 // WARNING when a selector is used with a TChain, you must use
329 // the pointer to the current TTree to call GetEntry(entry).
330 // The entry is always the local entry number in the current tree.
331 // Assuming that fChain is the pointer to the TChain being processed,
332 // use fChain->GetTree()->GetEntry(entry).
8d7d3b59 333 if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
334
ed97dc98 335 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
336 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
337 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 338
327eaf46 339 GetEntry(entry);
340 ExecAnalysis();
8d7d3b59 341 if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
327eaf46 342 return kTRUE;
d3106602 343}
344
345//______________________________________________________________________________
c52c2132 346void AliAnalysisManager::PackOutput(TList *target)
d3106602 347{
981f2614 348 // Pack all output data containers in the output list. Called at SlaveTerminate
349 // stage in PROOF case for each slave.
8d7d3b59 350 if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
c52c2132 351 if (!target) {
352 Error("PackOutput", "No target. Aborting.");
353 return;
37153431 354 }
6073f8c9 355 if (fInputEventHandler) fInputEventHandler ->Terminate();
6bb2b24f 356 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
357 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
8d7d3b59 358
359 // Call FinishTaskOutput() for each event loop task (not called for
360 // post-event loop tasks - use Terminate() fo those)
361 TIter nexttask(fTasks);
362 AliAnalysisTask *task;
363 while ((task=(AliAnalysisTask*)nexttask())) {
364 if (!task->IsPostEventLoop()) {
365 if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
366 task->FinishTaskOutput();
367 if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
368 }
369 }
8c9485b2 370
c52c2132 371 if (fMode == kProofAnalysis) {
372 TIter next(fOutputs);
373 AliAnalysisDataContainer *output;
374 while ((output=(AliAnalysisDataContainer*)next())) {
8d7d3b59 375 // Do not consider outputs of post event loop tasks
376 if (output->GetProducer()->IsPostEventLoop()) continue;
377 // Check if data was posted to this container. If not, issue an error.
378 if (!output->GetData() ) {
379 Error("PackOutput", "No data for output container %s. Forgot to PostData ?\n", output->GetName());
380 continue;
381 }
382 if (!output->IsSpecialOutput()) {
383 // Normal outputs
ca78991b 384 const char *filename = output->GetFileName();
385 if (!(strcmp(filename, "default"))) {
386 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
387 }
388 if (strlen(filename)) {
8d7d3b59 389 // File resident outputs
390 TFile *file = output->GetFile();
391 // Backup current folder
ca78991b 392 TDirectory *opwd = gDirectory;
8d7d3b59 393 // Create file if not existing and register to container.
ca78991b 394 if (file) file->cd();
8d7d3b59 395 else file = new TFile(filename, "RECREATE");
396 if (file->IsZombie()) {
397 Fatal("PackOutput", "Could not recreate file %s\n", filename);
398 return;
399 }
400 output->SetFile(file);
ca78991b 401 // Clear file list to release object ownership to user.
ca78991b 402 file->Clear();
8d7d3b59 403 // Save data to file, then close.
1be433fc 404 if (output->GetData()->InheritsFrom(TCollection::Class())) {
405 // If data is a collection, we set the name of the collection
406 // as the one of the container and we save as a single key.
407 TCollection *coll = (TCollection*)output->GetData();
408 coll->SetName(output->GetName());
409 coll->Write(output->GetName(), TObject::kSingleKey);
410 } else {
411 output->GetData()->Write();
412 }
8d7d3b59 413 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
414 if (fDebug > 2) {
415 printf(" file %s listing content:\n", filename);
416 file->ls();
417 }
ca78991b 418 file->Close();
ca78991b 419 // Restore current directory
420 if (opwd) opwd->cd();
8d7d3b59 421 } else {
422 // Memory-resident outputs
423 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", output->GetName());
ca78991b 424 }
8167b1d0 425 AliAnalysisDataWrapper *wrap = output->ExportData();
426 // Output wrappers must delete data after merging (AG 13/11/07)
427 wrap->SetDeleteData(kTRUE);
8167b1d0 428 target->Add(wrap);
429 }
8d7d3b59 430 // Special outputs
431 if (output->IsSpecialOutput()) {
d0864eb4 432 TDirectory *opwd = gDirectory;
8d7d3b59 433 TFile *file = output->GetFile();
434 if (!file) {
435 AliAnalysisTask *producer = output->GetProducer();
436 Error("PackOutput",
437 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
438 output->GetFileName(), output->GetName(), producer->ClassName());
439 continue;
440 }
ef788aee 441 file->cd();
8d7d3b59 442 // Release object ownership to users after writing data to file
1be433fc 443 if (output->GetData()->InheritsFrom(TCollection::Class())) {
444 // If data is a collection, we set the name of the collection
445 // as the one of the container and we save as a single key.
446 TCollection *coll = (TCollection*)output->GetData();
447 coll->SetName(output->GetName());
448 coll->Write(output->GetName(), TObject::kSingleKey);
449 } else {
450 output->GetData()->Write();
451 }
8d7d3b59 452 file->Clear();
453 if (fDebug > 2) {
454 printf(" file %s listing content:\n", output->GetFileName());
455 file->ls();
456 }
13ef3bb0 457 file->Close();
8d7d3b59 458 // Restore current directory
d0864eb4 459 if (opwd) opwd->cd();
8d7d3b59 460 // Check if a special output location was provided or the output files have to be merged
13ef3bb0 461 if (strlen(fSpecialOutputLocation.Data())) {
462 TString remote = fSpecialOutputLocation;
463 remote += "/";
ef788aee 464 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
d0864eb4 465 remote += Form("%s_%d_", gSystem->HostName(), gid);
13ef3bb0 466 remote += output->GetFileName();
467 TFile::Cp(output->GetFileName(), remote.Data());
ca78991b 468 } else {
8d7d3b59 469 // No special location specified-> use TProofOutputFile as merging utility
470 // The file at this output slot must be opened in CreateOutputObjects
471 if (fDebug > 1) printf(" File %s to be merged...\n", output->GetFileName());
13ef3bb0 472 }
473 }
c52c2132 474 }
475 }
8d7d3b59 476 if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
c52c2132 477}
478
479//______________________________________________________________________________
981f2614 480void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 481{
981f2614 482// Import data in output containers from wrappers coming in source.
8d7d3b59 483 if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
327eaf46 484 TIter next(fOutputs);
981f2614 485 AliAnalysisDataContainer *cont;
486 AliAnalysisDataWrapper *wrap;
487 Int_t icont = 0;
c52c2132 488 while ((cont=(AliAnalysisDataContainer*)next())) {
0355fc48 489 wrap = 0;
8d7d3b59 490 if (cont->GetProducer()->IsPostEventLoop()) continue;
491 if (cont->IsSpecialOutput()) {
492 if (strlen(fSpecialOutputLocation.Data())) continue;
493 // Copy merged file from PROOF scratch space
494 if (fDebug > 1)
495 printf(" Copying file %s from PROOF scratch space\n", cont->GetFileName());
496 Bool_t gotit = TFile::Cp(Form("root://lxb6045.cern.ch:11094//pool/scratch/%s",cont->GetFileName()),
497 cont->GetFileName());
498 if (!gotit) {
499 Error("ImportWrappers", "Could not get file %s from proof scratch space", cont->GetFileName());
500 }
501 // Normally we should connect data from the copied file to the
502 // corresponding output container, but it is not obvious how to do this
503 // automatically if several objects in file...
0355fc48 504 TFile *f = new TFile(cont->GetFileName(), "READ");
505 TObject *obj = f->Get(cont->GetName());
506 if (!obj) {
507 Error("ImportWrappers", "Could not find object %s in file %s", cont->GetName(), cont->GetFileName());
508 continue;
509 }
510 wrap = new AliAnalysisDataWrapper(obj);
511 wrap->SetDeleteData(kFALSE);
8d7d3b59 512 }
0355fc48 513 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 514 if (!wrap) {
515 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 516 continue;
517 }
981f2614 518 icont++;
8d7d3b59 519 if (fDebug > 1) {
520 printf(" Importing data for container %s", cont->GetName());
521 if (strlen(cont->GetFileName())) printf(" -> file %s\n", cont->GetFileName());
522 else printf("\n");
523 }
981f2614 524 cont->ImportData(wrap);
c52c2132 525 }
8d7d3b59 526 if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 527}
528
529//______________________________________________________________________________
530void AliAnalysisManager::UnpackOutput(TList *source)
531{
ca78991b 532 // Called by AliAnalysisSelector::Terminate only on the client.
8d7d3b59 533 if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 534 if (!source) {
981f2614 535 Error("UnpackOutput", "No target. Aborting.");
c52c2132 536 return;
537 }
8d7d3b59 538 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
c52c2132 539
981f2614 540 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 541
981f2614 542 TIter next(fOutputs);
c52c2132 543 AliAnalysisDataContainer *output;
544 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 545 if (!output->GetData()) continue;
b1310ef5 546 // Check if there are client tasks that run post event loop
547 if (output->HasConsumers()) {
548 // Disable event loop semaphore
549 output->SetPostEventLoop(kTRUE);
550 TObjArray *list = output->GetConsumers();
551 Int_t ncons = list->GetEntriesFast();
552 for (Int_t i=0; i<ncons; i++) {
553 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
554 task->CheckNotify(kTRUE);
555 // If task is active, execute it
556 if (task->IsPostEventLoop() && task->IsActive()) {
8d7d3b59 557 if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 558 task->ExecuteTask();
559 }
560 }
561 }
c52c2132 562 }
8d7d3b59 563 if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 564}
565
566//______________________________________________________________________________
567void AliAnalysisManager::Terminate()
568{
569 // The Terminate() function is the last function to be called during
570 // a query. It always runs on the client, it can be used to present
c52c2132 571 // the results graphically.
8d7d3b59 572 if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
327eaf46 573 AliAnalysisTask *task;
c52c2132 574 TIter next(fTasks);
327eaf46 575 // Call Terminate() for tasks
c52c2132 576 while ((task=(AliAnalysisTask*)next())) task->Terminate();
8c9485b2 577 //
8c0ab8e8 578 TIter next1(fOutputs);
579 AliAnalysisDataContainer *output;
580 while ((output=(AliAnalysisDataContainer*)next1())) {
581 // Close all files at output
1be433fc 582 // Special outputs have the files already closed and written.
583 if (output->IsSpecialOutput()) continue;
8c0ab8e8 584 const char *filename = output->GetFileName();
585 if (!(strcmp(filename, "default"))) {
586 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1be433fc 587 TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
588 if (aodfile) {
589 if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
590 aodfile->Write();
591 continue;
592 }
8d7d3b59 593 }
594 if (!strlen(filename)) continue;
1be433fc 595 if (!output->GetData()) continue;
8d7d3b59 596 TFile *file = output->GetFile();
597 TDirectory *opwd = gDirectory;
598 if (file) {
599 file->cd();
600 } else {
601 file = new TFile(filename, "RECREATE");
602 if (file->IsZombie()) continue;
603 output->SetFile(file);
604 }
605 if (fDebug > 1) printf(" writing output data %s to file %s\n", output->GetData()->GetName(), file->GetName());
1be433fc 606 if (output->GetData()->InheritsFrom(TCollection::Class())) {
607 // If data is a collection, we set the name of the collection
608 // as the one of the container and we save as a single key.
609 TCollection *coll = (TCollection*)output->GetData();
610 coll->SetName(output->GetName());
611 coll->Write(output->GetName(), TObject::kSingleKey);
612 } else {
613 output->GetData()->Write();
614 }
8c0ab8e8 615 file->Close();
8d7d3b59 616 if (opwd) opwd->cd();
8c0ab8e8 617 }
618
1be433fc 619 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
620 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
621 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
622
8c0ab8e8 623 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
624 if (getsysInfo) {
625 TDirectory *cdir = gDirectory;
626 TFile f("syswatch.root", "RECREATE");
627 if (!f.IsZombie()) {
628 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
629 tree->SetMarkerStyle(kCircle);
630 tree->SetMarkerColor(kBlue);
631 tree->SetMarkerSize(0.5);
632 if (!gROOT->IsBatch()) {
633 tree->SetAlias("event", "id0");
29cbcef8 634 tree->SetAlias("memUSED", "pI.fMemVirtual");
8c0ab8e8 635 tree->SetAlias("userCPU", "pI.fCpuUser");
636 TCanvas *c = new TCanvas("SysInfo","SysInfo",10,10,800,600);
637 c->Divide(2,1,0.01,0.01);
638 c->cd(1);
639 tree->Draw("memUSED:event","","", 1234567890, 0);
640 c->cd(2);
641 tree->Draw("userCPU:event","","", 1234567890, 0);
642 }
643 tree->Write();
644 f.Close();
645 delete tree;
646 }
647 if (cdir) cdir->cd();
648 }
8d7d3b59 649 if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 650}
651
652//______________________________________________________________________________
653void AliAnalysisManager::AddTask(AliAnalysisTask *task)
654{
655// Adds a user task to the global list of tasks.
8d7d3b59 656 if (fTasks->FindObject(task)) {
657 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
658 return;
659 }
d3106602 660 task->SetActive(kFALSE);
661 fTasks->Add(task);
662}
663
664//______________________________________________________________________________
665AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
666{
667// Retreive task by name.
668 if (!fTasks) return NULL;
669 return (AliAnalysisTask*)fTasks->FindObject(name);
670}
671
672//______________________________________________________________________________
673AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 674 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 675{
676// Create a data container of a certain type. Types can be:
c52c2132 677// kExchangeContainer = 0, used to exchange date between tasks
d3106602 678// kInputContainer = 1, used to store input data
679// kOutputContainer = 2, used for posting results
b1310ef5 680 if (fContainers->FindObject(name)) {
681 Error("CreateContainer","A container named %s already defined !\n",name);
682 return NULL;
683 }
d3106602 684 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
685 fContainers->Add(cont);
686 switch (type) {
687 case kInputContainer:
688 fInputs->Add(cont);
689 break;
690 case kOutputContainer:
691 fOutputs->Add(cont);
8c0ab8e8 692 if (filename && strlen(filename)) {
693 cont->SetFileName(filename);
694 cont->SetDataOwned(kFALSE); // data owned by the file
695 }
d3106602 696 break;
c52c2132 697 case kExchangeContainer:
d3106602 698 break;
699 }
700 return cont;
701}
702
703//______________________________________________________________________________
704Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
705 AliAnalysisDataContainer *cont)
706{
707// Connect input of an existing task to a data container.
708 if (!fTasks->FindObject(task)) {
709 AddTask(task);
8d7d3b59 710 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 711 }
712 Bool_t connected = task->ConnectInput(islot, cont);
713 return connected;
714}
715
716//______________________________________________________________________________
717Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
718 AliAnalysisDataContainer *cont)
719{
720// Connect output of an existing task to a data container.
721 if (!fTasks->FindObject(task)) {
722 AddTask(task);
c52c2132 723 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 724 }
725 Bool_t connected = task->ConnectOutput(islot, cont);
726 return connected;
727}
728
729//______________________________________________________________________________
730void AliAnalysisManager::CleanContainers()
731{
732// Clean data from all containers that have already finished all client tasks.
733 TIter next(fContainers);
734 AliAnalysisDataContainer *cont;
735 while ((cont=(AliAnalysisDataContainer *)next())) {
736 if (cont->IsOwnedData() &&
737 cont->IsDataReady() &&
738 cont->ClientsExecuted()) cont->DeleteData();
739 }
740}
741
742//______________________________________________________________________________
743Bool_t AliAnalysisManager::InitAnalysis()
744{
745// Initialization of analysis chain of tasks. Should be called after all tasks
746// and data containers are properly connected
747 // Check for input/output containers
748 fInitOK = kFALSE;
d3106602 749 // Check for top tasks (depending only on input data containers)
750 if (!fTasks->First()) {
c52c2132 751 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 752 return kFALSE;
753 }
754 TIter next(fTasks);
755 AliAnalysisTask *task;
756 AliAnalysisDataContainer *cont;
757 Int_t ntop = 0;
758 Int_t nzombies = 0;
327eaf46 759 Bool_t iszombie = kFALSE;
760 Bool_t istop = kTRUE;
d3106602 761 Int_t i;
762 while ((task=(AliAnalysisTask*)next())) {
327eaf46 763 istop = kTRUE;
764 iszombie = kFALSE;
d3106602 765 Int_t ninputs = task->GetNinputs();
d3106602 766 for (i=0; i<ninputs; i++) {
767 cont = task->GetInputSlot(i)->GetContainer();
768 if (!cont) {
327eaf46 769 if (!iszombie) {
d3106602 770 task->SetZombie();
771 fZombies->Add(task);
772 nzombies++;
327eaf46 773 iszombie = kTRUE;
d3106602 774 }
c52c2132 775 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
776 i, task->GetName());
d3106602 777 }
327eaf46 778 if (iszombie) continue;
d3106602 779 // Check if cont is an input container
327eaf46 780 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 781 // Connect to parent task
782 }
327eaf46 783 if (istop) {
d3106602 784 ntop++;
785 fTopTasks->Add(task);
786 }
787 }
788 if (!ntop) {
c52c2132 789 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 790 return kFALSE;
791 }
792 // Check now if there are orphan tasks
793 for (i=0; i<ntop; i++) {
794 task = (AliAnalysisTask*)fTopTasks->At(i);
795 task->SetUsed();
796 }
797 Int_t norphans = 0;
798 next.Reset();
799 while ((task=(AliAnalysisTask*)next())) {
800 if (!task->IsUsed()) {
801 norphans++;
c52c2132 802 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 803 }
804 }
805 // Check the task hierarchy (no parent task should depend on data provided
806 // by a daughter task)
807 for (i=0; i<ntop; i++) {
808 task = (AliAnalysisTask*)fTopTasks->At(i);
809 if (task->CheckCircularDeps()) {
c52c2132 810 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 811 PrintStatus("dep");
812 return kFALSE;
813 }
814 }
b1310ef5 815 // Check that all containers feeding post-event loop tasks are in the outputs list
816 TIter nextcont(fContainers); // loop over all containers
817 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
818 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
819 if (cont->HasConsumers()) {
820 // Check if one of the consumers is post event loop
821 TIter nextconsumer(cont->GetConsumers());
822 while ((task=(AliAnalysisTask*)nextconsumer())) {
823 if (task->IsPostEventLoop()) {
824 fOutputs->Add(cont);
825 break;
826 }
827 }
828 }
829 }
830 }
8d7d3b59 831 // Check if all special output containers have a file name provided
832 TIter nextout(fOutputs);
833 while ((cont=(AliAnalysisDataContainer*)nextout())) {
834 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
835 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
836 return kFALSE;
837 }
838 }
327eaf46 839 fInitOK = kTRUE;
d3106602 840 return kTRUE;
841}
842
843//______________________________________________________________________________
844void AliAnalysisManager::PrintStatus(Option_t *option) const
845{
846// Print task hierarchy.
8c0ab8e8 847 if (!fInitOK) {
848 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
849 return;
850 }
851 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
852 if (getsysInfo)
853 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 854 TIter next(fTopTasks);
855 AliAnalysisTask *task;
856 while ((task=(AliAnalysisTask*)next()))
857 task->PrintTask(option);
858}
859
860//______________________________________________________________________________
861void AliAnalysisManager::ResetAnalysis()
862{
863// Reset all execution flags and clean containers.
864 CleanContainers();
865}
866
c52c2132 867//______________________________________________________________________________
8c0ab8e8 868void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
c52c2132 869{
aee5ee44 870// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
871// MIX. Process nentries starting from firstentry
c52c2132 872 if (!fInitOK) {
873 Error("StartAnalysis","Analysis manager was not initialized !");
874 return;
875 }
8d7d3b59 876 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
c52c2132 877 TString anaType = type;
878 anaType.ToLower();
879 fMode = kLocalAnalysis;
880 if (tree) {
881 if (anaType.Contains("proof")) fMode = kProofAnalysis;
882 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
aee5ee44 883 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
c52c2132 884 }
885 if (fMode == kGridAnalysis) {
886 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
981f2614 887 fMode = kLocalAnalysis;
888 }
d86ed856 889 char line[256];
efd53803 890 SetEventLoop(kFALSE);
8d7d3b59 891 // Enable event loop mode if a tree was provided
aee5ee44 892 if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 893
8c0ab8e8 894 TChain *chain = 0;
895 TString ttype = "TTree";
896 if (tree->IsA() == TChain::Class()) {
897 chain = (TChain*)tree;
6b742510 898 if (!chain || !chain->GetListOfFiles()->First()) {
899 Error("StartAnalysis", "Cannot process null or empty chain...");
900 return;
901 }
8c0ab8e8 902 ttype = "TChain";
903 }
9b33830a 904
aee5ee44 905 // Initialize locally all tasks (happens for all modes)
9b33830a 906 TIter next(fTasks);
907 AliAnalysisTask *task;
efd53803 908 while ((task=(AliAnalysisTask*)next())) {
efd53803 909 task->LocalInit();
910 }
911
c52c2132 912 switch (fMode) {
913 case kLocalAnalysis:
914 if (!tree) {
03a5cc9f 915 TIter nextT(fTasks);
981f2614 916 // Call CreateOutputObjects for all tasks
03a5cc9f 917 while ((task=(AliAnalysisTask*)nextT())) {
c5a87c56 918 TDirectory *curdir = gDirectory;
919 task->CreateOutputObjects();
920 if (curdir) curdir->cd();
921 }
c52c2132 922 ExecAnalysis();
981f2614 923 Terminate();
c52c2132 924 return;
925 }
926 // Run tree-based analysis via AliAnalysisSelector
c52c2132 927 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
aee5ee44 928 fSelector = new AliAnalysisSelector(this);
929 tree->Process(fSelector, "", nentries, firstentry);
c52c2132 930 break;
931 case kProofAnalysis:
932 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
933 printf("StartAnalysis: no PROOF!!!\n");
934 return;
935 }
936 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
937 gROOT->ProcessLine(line);
938 if (chain) {
939 chain->SetProof();
940 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
8c0ab8e8 941 chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 942 } else {
943 printf("StartAnalysis: no chain\n");
944 return;
945 }
946 break;
947 case kGridAnalysis:
948 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
aee5ee44 949 break;
950 case kMixingAnalysis:
951 // Run event mixing analysis
952 if (!fEventPool) {
953 Error("StartAnalysis", "Cannot run event mixing without event pool");
954 return;
955 }
956 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
957 fSelector = new AliAnalysisSelector(this);
958 TChain *chain;
959 while ((chain=fEventPool->GetNextChain())) {
960 TIter next(fTasks);
961 AliAnalysisTask *task;
962 // Call NotifyBinChange for all tasks
963 while ((task=(AliAnalysisTask*)next()))
964 if (!task->IsPostEventLoop()) task->NotifyBinChange();
965 chain->Process(fSelector);
966 }
967 PackOutput(fSelector->GetOutputList());
968 Terminate();
c52c2132 969 }
970}
971
d86ed856 972//______________________________________________________________________________
973void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
974{
975// Start analysis for this manager on a given dataset. Analysis task can be:
976// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
977 if (!fInitOK) {
978 Error("StartAnalysis","Analysis manager was not initialized !");
979 return;
980 }
8d7d3b59 981 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
d86ed856 982 TString anaType = type;
983 anaType.ToLower();
984 if (!anaType.Contains("proof")) {
985 Error("Cannot process datasets in %s mode. Try PROOF.", type);
986 return;
987 }
988 fMode = kProofAnalysis;
989 char line[256];
990 SetEventLoop(kTRUE);
991 // Set the dataset flag
992 TObject::SetBit(kUseDataSet);
993 fTree = 0;
994
995 // Initialize locally all tasks
996 TIter next(fTasks);
997 AliAnalysisTask *task;
998 while ((task=(AliAnalysisTask*)next())) {
999 task->LocalInit();
1000 }
1001
1002 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1003 printf("StartAnalysis: no PROOF!!!\n");
1004 return;
1005 }
1006 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1007 gROOT->ProcessLine(line);
1008 sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1009 if (!gROOT->ProcessLine(line)) {
1010 Error("StartAnalysis", "Dataset %s not found", dataset);
1011 return;
1012 }
1013 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1014 dataset, nentries, firstentry);
1015 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1016 gROOT->ProcessLine(line);
1017}
1018
d3106602 1019//______________________________________________________________________________
8d7d3b59 1020TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1021{
1022// Opens a special output file used in PROOF.
1023 char line[256];
1024 if (fMode!=kProofAnalysis || !fSelector) {
1025 Error("OpenProofFile","Cannot open PROOF file %s",filename);
1026 return NULL;
1027 }
1028 sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
1029 if (fDebug > 1) printf("=== %s\n", line);
1030 gROOT->ProcessLine(line);
1031 sprintf(line, "pf->OpenFile(\"%s\");", option);
1032 gROOT->ProcessLine(line);
1033 if (fDebug > 1) {
1034 gROOT->ProcessLine("pf->Print()");
1035 printf(" == proof file name: %s\n", gFile->GetName());
1036 }
1037 sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1038 if (fDebug > 1) printf("=== %s\n", line);
1039 gROOT->ProcessLine(line);
1040 return gFile;
1041}
1042
1043//______________________________________________________________________________
d3106602 1044void AliAnalysisManager::ExecAnalysis(Option_t *option)
1045{
1046// Execute analysis.
8c0ab8e8 1047 static Long64_t ncalls = 0;
1048 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1049 if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1050 ncalls++;
327eaf46 1051 if (!fInitOK) {
c52c2132 1052 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 1053 return;
1054 }
d3106602 1055 AliAnalysisTask *task;
327eaf46 1056 // Check if the top tree is active.
1057 if (fTree) {
1058 TIter next(fTasks);
1059 // De-activate all tasks
1060 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1061 AliAnalysisDataContainer *cont = (AliAnalysisDataContainer*)fInputs->At(0);
1062 if (!cont) {
c52c2132 1063 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 1064 return;
1065 }
1066 cont->SetData(fTree); // This will notify all consumers
ed97dc98 1067 Long64_t entry = fTree->GetTree()->GetReadEntry();
1068
6bb2b24f 1069//
c3701689 1070// Call BeginEvent() for optional input/output and MC services
ed97dc98 1071 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1072 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1073 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 1074//
1075// Execute the tasks
276941c8 1076// TIter next1(cont->GetConsumers());
1077 TIter next1(fTopTasks);
327eaf46 1078 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1079 if (fDebug >1) {
1080 cout << " Executing task " << task->GetName() << endl;
1081 }
6bb2b24f 1082
327eaf46 1083 task->ExecuteTask(option);
1084 }
6bb2b24f 1085//
1086// Call FinishEvent() for optional output and MC services
6073f8c9 1087 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1088 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1089 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1090 // Gather system information if requested
1091 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1092 AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
327eaf46 1093 return;
1094 }
1095 // The event loop is not controlled by TSelector
6bb2b24f 1096//
c3701689 1097// Call BeginEvent() for optional input/output and MC services
ed97dc98 1098 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1099 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1100 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
327eaf46 1101 TIter next2(fTopTasks);
1102 while ((task=(AliAnalysisTask*)next2())) {
1103 task->SetActive(kTRUE);
c52c2132 1104 if (fDebug > 1) {
1105 cout << " Executing task " << task->GetName() << endl;
1106 }
d3106602 1107 task->ExecuteTask(option);
327eaf46 1108 }
6bb2b24f 1109//
1110// Call FinishEvent() for optional output and MC services
6073f8c9 1111 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1112 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1113 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 1114}
1115
1116//______________________________________________________________________________
1117void AliAnalysisManager::FinishAnalysis()
1118{
1119// Finish analysis.
1120}