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