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