get rid of compilation warning
[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.
1be433fc 401 if (output->GetData()->InheritsFrom(TCollection::Class())) {
402 // If data is a collection, we set the name of the collection
403 // as the one of the container and we save as a single key.
404 TCollection *coll = (TCollection*)output->GetData();
405 coll->SetName(output->GetName());
406 coll->Write(output->GetName(), TObject::kSingleKey);
407 } else {
408 output->GetData()->Write();
409 }
8d7d3b59 410 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
411 if (fDebug > 2) {
412 printf(" file %s listing content:\n", filename);
413 file->ls();
414 }
ca78991b 415 file->Close();
ca78991b 416 // Restore current directory
417 if (opwd) opwd->cd();
8d7d3b59 418 } else {
419 // Memory-resident outputs
420 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", output->GetName());
ca78991b 421 }
8167b1d0 422 AliAnalysisDataWrapper *wrap = output->ExportData();
423 // Output wrappers must delete data after merging (AG 13/11/07)
424 wrap->SetDeleteData(kTRUE);
8167b1d0 425 target->Add(wrap);
426 }
8d7d3b59 427 // Special outputs
428 if (output->IsSpecialOutput()) {
d0864eb4 429 TDirectory *opwd = gDirectory;
8d7d3b59 430 TFile *file = output->GetFile();
431 if (!file) {
432 AliAnalysisTask *producer = output->GetProducer();
433 Error("PackOutput",
434 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
435 output->GetFileName(), output->GetName(), producer->ClassName());
436 continue;
437 }
ef788aee 438 file->cd();
8d7d3b59 439 // Release object ownership to users after writing data to file
1be433fc 440 if (output->GetData()->InheritsFrom(TCollection::Class())) {
441 // If data is a collection, we set the name of the collection
442 // as the one of the container and we save as a single key.
443 TCollection *coll = (TCollection*)output->GetData();
444 coll->SetName(output->GetName());
445 coll->Write(output->GetName(), TObject::kSingleKey);
446 } else {
447 output->GetData()->Write();
448 }
8d7d3b59 449 file->Clear();
450 if (fDebug > 2) {
451 printf(" file %s listing content:\n", output->GetFileName());
452 file->ls();
453 }
13ef3bb0 454 file->Close();
8d7d3b59 455 // Restore current directory
d0864eb4 456 if (opwd) opwd->cd();
8d7d3b59 457 // Check if a special output location was provided or the output files have to be merged
13ef3bb0 458 if (strlen(fSpecialOutputLocation.Data())) {
459 TString remote = fSpecialOutputLocation;
460 remote += "/";
ef788aee 461 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
d0864eb4 462 remote += Form("%s_%d_", gSystem->HostName(), gid);
13ef3bb0 463 remote += output->GetFileName();
464 TFile::Cp(output->GetFileName(), remote.Data());
ca78991b 465 } else {
8d7d3b59 466 // No special location specified-> use TProofOutputFile as merging utility
467 // The file at this output slot must be opened in CreateOutputObjects
468 if (fDebug > 1) printf(" File %s to be merged...\n", output->GetFileName());
13ef3bb0 469 }
470 }
c52c2132 471 }
472 }
8d7d3b59 473 if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
c52c2132 474}
475
476//______________________________________________________________________________
981f2614 477void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 478{
981f2614 479// Import data in output containers from wrappers coming in source.
8d7d3b59 480 if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
327eaf46 481 TIter next(fOutputs);
981f2614 482 AliAnalysisDataContainer *cont;
483 AliAnalysisDataWrapper *wrap;
484 Int_t icont = 0;
c52c2132 485 while ((cont=(AliAnalysisDataContainer*)next())) {
8d7d3b59 486 if (cont->GetProducer()->IsPostEventLoop()) continue;
487 if (cont->IsSpecialOutput()) {
488 if (strlen(fSpecialOutputLocation.Data())) continue;
489 // Copy merged file from PROOF scratch space
490 if (fDebug > 1)
491 printf(" Copying file %s from PROOF scratch space\n", cont->GetFileName());
492 Bool_t gotit = TFile::Cp(Form("root://lxb6045.cern.ch:11094//pool/scratch/%s",cont->GetFileName()),
493 cont->GetFileName());
494 if (!gotit) {
495 Error("ImportWrappers", "Could not get file %s from proof scratch space", cont->GetFileName());
496 }
497 // Normally we should connect data from the copied file to the
498 // corresponding output container, but it is not obvious how to do this
499 // automatically if several objects in file...
500 continue;
501 }
981f2614 502 wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 503 if (!wrap) {
504 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 505 continue;
506 }
981f2614 507 icont++;
8d7d3b59 508 if (fDebug > 1) {
509 printf(" Importing data for container %s", cont->GetName());
510 if (strlen(cont->GetFileName())) printf(" -> file %s\n", cont->GetFileName());
511 else printf("\n");
512 }
981f2614 513 cont->ImportData(wrap);
c52c2132 514 }
8d7d3b59 515 if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 516}
517
518//______________________________________________________________________________
519void AliAnalysisManager::UnpackOutput(TList *source)
520{
ca78991b 521 // Called by AliAnalysisSelector::Terminate only on the client.
8d7d3b59 522 if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 523 if (!source) {
981f2614 524 Error("UnpackOutput", "No target. Aborting.");
c52c2132 525 return;
526 }
8d7d3b59 527 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
c52c2132 528
981f2614 529 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 530
981f2614 531 TIter next(fOutputs);
c52c2132 532 AliAnalysisDataContainer *output;
533 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 534 if (!output->GetData()) continue;
b1310ef5 535 // Check if there are client tasks that run post event loop
536 if (output->HasConsumers()) {
537 // Disable event loop semaphore
538 output->SetPostEventLoop(kTRUE);
539 TObjArray *list = output->GetConsumers();
540 Int_t ncons = list->GetEntriesFast();
541 for (Int_t i=0; i<ncons; i++) {
542 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
543 task->CheckNotify(kTRUE);
544 // If task is active, execute it
545 if (task->IsPostEventLoop() && task->IsActive()) {
8d7d3b59 546 if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 547 task->ExecuteTask();
548 }
549 }
550 }
c52c2132 551 }
8d7d3b59 552 if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 553}
554
555//______________________________________________________________________________
556void AliAnalysisManager::Terminate()
557{
558 // The Terminate() function is the last function to be called during
559 // a query. It always runs on the client, it can be used to present
c52c2132 560 // the results graphically.
8d7d3b59 561 if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
327eaf46 562 AliAnalysisTask *task;
c52c2132 563 TIter next(fTasks);
327eaf46 564 // Call Terminate() for tasks
c52c2132 565 while ((task=(AliAnalysisTask*)next())) task->Terminate();
8c9485b2 566 //
8c0ab8e8 567 TIter next1(fOutputs);
568 AliAnalysisDataContainer *output;
569 while ((output=(AliAnalysisDataContainer*)next1())) {
570 // Close all files at output
1be433fc 571 // Special outputs have the files already closed and written.
572 if (output->IsSpecialOutput()) continue;
8c0ab8e8 573 const char *filename = output->GetFileName();
574 if (!(strcmp(filename, "default"))) {
575 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1be433fc 576 TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
577 if (aodfile) {
578 if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
579 aodfile->Write();
580 continue;
581 }
8d7d3b59 582 }
583 if (!strlen(filename)) continue;
1be433fc 584 if (!output->GetData()) continue;
8d7d3b59 585 TFile *file = output->GetFile();
586 TDirectory *opwd = gDirectory;
587 if (file) {
588 file->cd();
589 } else {
590 file = new TFile(filename, "RECREATE");
591 if (file->IsZombie()) continue;
592 output->SetFile(file);
593 }
594 if (fDebug > 1) printf(" writing output data %s to file %s\n", output->GetData()->GetName(), file->GetName());
1be433fc 595 if (output->GetData()->InheritsFrom(TCollection::Class())) {
596 // If data is a collection, we set the name of the collection
597 // as the one of the container and we save as a single key.
598 TCollection *coll = (TCollection*)output->GetData();
599 coll->SetName(output->GetName());
600 coll->Write(output->GetName(), TObject::kSingleKey);
601 } else {
602 output->GetData()->Write();
603 }
8c0ab8e8 604 file->Close();
8d7d3b59 605 if (opwd) opwd->cd();
8c0ab8e8 606 }
607
1be433fc 608 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
609 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
610 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
611
8c0ab8e8 612 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
613 if (getsysInfo) {
614 TDirectory *cdir = gDirectory;
615 TFile f("syswatch.root", "RECREATE");
616 if (!f.IsZombie()) {
617 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
618 tree->SetMarkerStyle(kCircle);
619 tree->SetMarkerColor(kBlue);
620 tree->SetMarkerSize(0.5);
621 if (!gROOT->IsBatch()) {
622 tree->SetAlias("event", "id0");
29cbcef8 623 tree->SetAlias("memUSED", "pI.fMemVirtual");
8c0ab8e8 624 tree->SetAlias("userCPU", "pI.fCpuUser");
625 TCanvas *c = new TCanvas("SysInfo","SysInfo",10,10,800,600);
626 c->Divide(2,1,0.01,0.01);
627 c->cd(1);
628 tree->Draw("memUSED:event","","", 1234567890, 0);
629 c->cd(2);
630 tree->Draw("userCPU:event","","", 1234567890, 0);
631 }
632 tree->Write();
633 f.Close();
634 delete tree;
635 }
636 if (cdir) cdir->cd();
637 }
8d7d3b59 638 if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 639}
640
641//______________________________________________________________________________
642void AliAnalysisManager::AddTask(AliAnalysisTask *task)
643{
644// Adds a user task to the global list of tasks.
8d7d3b59 645 if (fTasks->FindObject(task)) {
646 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
647 return;
648 }
d3106602 649 task->SetActive(kFALSE);
650 fTasks->Add(task);
651}
652
653//______________________________________________________________________________
654AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
655{
656// Retreive task by name.
657 if (!fTasks) return NULL;
658 return (AliAnalysisTask*)fTasks->FindObject(name);
659}
660
661//______________________________________________________________________________
662AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 663 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 664{
665// Create a data container of a certain type. Types can be:
c52c2132 666// kExchangeContainer = 0, used to exchange date between tasks
d3106602 667// kInputContainer = 1, used to store input data
668// kOutputContainer = 2, used for posting results
b1310ef5 669 if (fContainers->FindObject(name)) {
670 Error("CreateContainer","A container named %s already defined !\n",name);
671 return NULL;
672 }
d3106602 673 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
674 fContainers->Add(cont);
675 switch (type) {
676 case kInputContainer:
677 fInputs->Add(cont);
678 break;
679 case kOutputContainer:
680 fOutputs->Add(cont);
8c0ab8e8 681 if (filename && strlen(filename)) {
682 cont->SetFileName(filename);
683 cont->SetDataOwned(kFALSE); // data owned by the file
684 }
d3106602 685 break;
c52c2132 686 case kExchangeContainer:
d3106602 687 break;
688 }
689 return cont;
690}
691
692//______________________________________________________________________________
693Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
694 AliAnalysisDataContainer *cont)
695{
696// Connect input of an existing task to a data container.
697 if (!fTasks->FindObject(task)) {
698 AddTask(task);
8d7d3b59 699 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 700 }
701 Bool_t connected = task->ConnectInput(islot, cont);
702 return connected;
703}
704
705//______________________________________________________________________________
706Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
707 AliAnalysisDataContainer *cont)
708{
709// Connect output of an existing task to a data container.
710 if (!fTasks->FindObject(task)) {
711 AddTask(task);
c52c2132 712 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 713 }
714 Bool_t connected = task->ConnectOutput(islot, cont);
715 return connected;
716}
717
718//______________________________________________________________________________
719void AliAnalysisManager::CleanContainers()
720{
721// Clean data from all containers that have already finished all client tasks.
722 TIter next(fContainers);
723 AliAnalysisDataContainer *cont;
724 while ((cont=(AliAnalysisDataContainer *)next())) {
725 if (cont->IsOwnedData() &&
726 cont->IsDataReady() &&
727 cont->ClientsExecuted()) cont->DeleteData();
728 }
729}
730
731//______________________________________________________________________________
732Bool_t AliAnalysisManager::InitAnalysis()
733{
734// Initialization of analysis chain of tasks. Should be called after all tasks
735// and data containers are properly connected
736 // Check for input/output containers
737 fInitOK = kFALSE;
d3106602 738 // Check for top tasks (depending only on input data containers)
739 if (!fTasks->First()) {
c52c2132 740 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 741 return kFALSE;
742 }
743 TIter next(fTasks);
744 AliAnalysisTask *task;
745 AliAnalysisDataContainer *cont;
746 Int_t ntop = 0;
747 Int_t nzombies = 0;
327eaf46 748 Bool_t iszombie = kFALSE;
749 Bool_t istop = kTRUE;
d3106602 750 Int_t i;
751 while ((task=(AliAnalysisTask*)next())) {
327eaf46 752 istop = kTRUE;
753 iszombie = kFALSE;
d3106602 754 Int_t ninputs = task->GetNinputs();
d3106602 755 for (i=0; i<ninputs; i++) {
756 cont = task->GetInputSlot(i)->GetContainer();
757 if (!cont) {
327eaf46 758 if (!iszombie) {
d3106602 759 task->SetZombie();
760 fZombies->Add(task);
761 nzombies++;
327eaf46 762 iszombie = kTRUE;
d3106602 763 }
c52c2132 764 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
765 i, task->GetName());
d3106602 766 }
327eaf46 767 if (iszombie) continue;
d3106602 768 // Check if cont is an input container
327eaf46 769 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 770 // Connect to parent task
771 }
327eaf46 772 if (istop) {
d3106602 773 ntop++;
774 fTopTasks->Add(task);
775 }
776 }
777 if (!ntop) {
c52c2132 778 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 779 return kFALSE;
780 }
781 // Check now if there are orphan tasks
782 for (i=0; i<ntop; i++) {
783 task = (AliAnalysisTask*)fTopTasks->At(i);
784 task->SetUsed();
785 }
786 Int_t norphans = 0;
787 next.Reset();
788 while ((task=(AliAnalysisTask*)next())) {
789 if (!task->IsUsed()) {
790 norphans++;
c52c2132 791 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 792 }
793 }
794 // Check the task hierarchy (no parent task should depend on data provided
795 // by a daughter task)
796 for (i=0; i<ntop; i++) {
797 task = (AliAnalysisTask*)fTopTasks->At(i);
798 if (task->CheckCircularDeps()) {
c52c2132 799 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 800 PrintStatus("dep");
801 return kFALSE;
802 }
803 }
b1310ef5 804 // Check that all containers feeding post-event loop tasks are in the outputs list
805 TIter nextcont(fContainers); // loop over all containers
806 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
807 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
808 if (cont->HasConsumers()) {
809 // Check if one of the consumers is post event loop
810 TIter nextconsumer(cont->GetConsumers());
811 while ((task=(AliAnalysisTask*)nextconsumer())) {
812 if (task->IsPostEventLoop()) {
813 fOutputs->Add(cont);
814 break;
815 }
816 }
817 }
818 }
819 }
8d7d3b59 820 // Check if all special output containers have a file name provided
821 TIter nextout(fOutputs);
822 while ((cont=(AliAnalysisDataContainer*)nextout())) {
823 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
824 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
825 return kFALSE;
826 }
827 }
327eaf46 828 fInitOK = kTRUE;
d3106602 829 return kTRUE;
830}
831
832//______________________________________________________________________________
833void AliAnalysisManager::PrintStatus(Option_t *option) const
834{
835// Print task hierarchy.
8c0ab8e8 836 if (!fInitOK) {
837 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
838 return;
839 }
840 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
841 if (getsysInfo)
842 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 843 TIter next(fTopTasks);
844 AliAnalysisTask *task;
845 while ((task=(AliAnalysisTask*)next()))
846 task->PrintTask(option);
847}
848
849//______________________________________________________________________________
850void AliAnalysisManager::ResetAnalysis()
851{
852// Reset all execution flags and clean containers.
853 CleanContainers();
854}
855
856//______________________________________________________________________________
8c0ab8e8 857void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
c52c2132 858{
859// Start analysis for this manager. Analysis task can be: LOCAL, PROOF or GRID.
8c0ab8e8 860// Process nentries starting from firstentry
c52c2132 861 if (!fInitOK) {
862 Error("StartAnalysis","Analysis manager was not initialized !");
863 return;
864 }
8d7d3b59 865 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
c52c2132 866 TString anaType = type;
867 anaType.ToLower();
868 fMode = kLocalAnalysis;
869 if (tree) {
870 if (anaType.Contains("proof")) fMode = kProofAnalysis;
871 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
872 }
873 if (fMode == kGridAnalysis) {
874 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
981f2614 875 fMode = kLocalAnalysis;
876 }
d86ed856 877 char line[256];
efd53803 878 SetEventLoop(kFALSE);
8d7d3b59 879 // Enable event loop mode if a tree was provided
880 if (tree) SetEventLoop(kTRUE);
efd53803 881
8c0ab8e8 882 TChain *chain = 0;
883 TString ttype = "TTree";
884 if (tree->IsA() == TChain::Class()) {
885 chain = (TChain*)tree;
6b742510 886 if (!chain || !chain->GetListOfFiles()->First()) {
887 Error("StartAnalysis", "Cannot process null or empty chain...");
888 return;
889 }
8c0ab8e8 890 ttype = "TChain";
891 }
9b33830a 892
893 // Initialize locally all tasks
894 TIter next(fTasks);
895 AliAnalysisTask *task;
efd53803 896 while ((task=(AliAnalysisTask*)next())) {
efd53803 897 task->LocalInit();
898 }
899
c52c2132 900 switch (fMode) {
901 case kLocalAnalysis:
902 if (!tree) {
03a5cc9f 903 TIter nextT(fTasks);
981f2614 904 // Call CreateOutputObjects for all tasks
03a5cc9f 905 while ((task=(AliAnalysisTask*)nextT())) {
c5a87c56 906 TDirectory *curdir = gDirectory;
907 task->CreateOutputObjects();
908 if (curdir) curdir->cd();
909 }
c52c2132 910 ExecAnalysis();
981f2614 911 Terminate();
c52c2132 912 return;
913 }
914 // Run tree-based analysis via AliAnalysisSelector
c52c2132 915 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
916 sprintf(line, "AliAnalysisSelector *selector = new AliAnalysisSelector((AliAnalysisManager*)0x%lx);",(ULong_t)this);
917 gROOT->ProcessLine(line);
8c0ab8e8 918 sprintf(line, "((%s*)0x%lx)->Process(selector, \"\",%lld, %lld);",ttype.Data(),(ULong_t)tree, nentries, firstentry);
c52c2132 919 gROOT->ProcessLine(line);
920 break;
921 case kProofAnalysis:
922 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
923 printf("StartAnalysis: no PROOF!!!\n");
924 return;
925 }
926 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
927 gROOT->ProcessLine(line);
928 if (chain) {
929 chain->SetProof();
930 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
8c0ab8e8 931 chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 932 } else {
933 printf("StartAnalysis: no chain\n");
934 return;
935 }
936 break;
937 case kGridAnalysis:
938 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
939 }
940}
941
942//______________________________________________________________________________
d86ed856 943void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
944{
945// Start analysis for this manager on a given dataset. Analysis task can be:
946// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
947 if (!fInitOK) {
948 Error("StartAnalysis","Analysis manager was not initialized !");
949 return;
950 }
8d7d3b59 951 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
d86ed856 952 TString anaType = type;
953 anaType.ToLower();
954 if (!anaType.Contains("proof")) {
955 Error("Cannot process datasets in %s mode. Try PROOF.", type);
956 return;
957 }
958 fMode = kProofAnalysis;
959 char line[256];
960 SetEventLoop(kTRUE);
961 // Set the dataset flag
962 TObject::SetBit(kUseDataSet);
963 fTree = 0;
964
965 // Initialize locally all tasks
966 TIter next(fTasks);
967 AliAnalysisTask *task;
968 while ((task=(AliAnalysisTask*)next())) {
969 task->LocalInit();
970 }
971
972 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
973 printf("StartAnalysis: no PROOF!!!\n");
974 return;
975 }
976 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
977 gROOT->ProcessLine(line);
978 sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
979 if (!gROOT->ProcessLine(line)) {
980 Error("StartAnalysis", "Dataset %s not found", dataset);
981 return;
982 }
983 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
984 dataset, nentries, firstentry);
985 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
986 gROOT->ProcessLine(line);
987}
988
989//______________________________________________________________________________
8d7d3b59 990TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
991{
992// Opens a special output file used in PROOF.
993 char line[256];
994 if (fMode!=kProofAnalysis || !fSelector) {
995 Error("OpenProofFile","Cannot open PROOF file %s",filename);
996 return NULL;
997 }
998 sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
999 if (fDebug > 1) printf("=== %s\n", line);
1000 gROOT->ProcessLine(line);
1001 sprintf(line, "pf->OpenFile(\"%s\");", option);
1002 gROOT->ProcessLine(line);
1003 if (fDebug > 1) {
1004 gROOT->ProcessLine("pf->Print()");
1005 printf(" == proof file name: %s\n", gFile->GetName());
1006 }
1007 sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1008 if (fDebug > 1) printf("=== %s\n", line);
1009 gROOT->ProcessLine(line);
1010 return gFile;
1011}
1012
1013//______________________________________________________________________________
d3106602 1014void AliAnalysisManager::ExecAnalysis(Option_t *option)
1015{
1016// Execute analysis.
8c0ab8e8 1017 static Long64_t ncalls = 0;
1018 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1019 if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1020 ncalls++;
327eaf46 1021 if (!fInitOK) {
c52c2132 1022 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 1023 return;
1024 }
d3106602 1025 AliAnalysisTask *task;
327eaf46 1026 // Check if the top tree is active.
1027 if (fTree) {
1028 TIter next(fTasks);
1029 // De-activate all tasks
1030 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1031 AliAnalysisDataContainer *cont = (AliAnalysisDataContainer*)fInputs->At(0);
1032 if (!cont) {
c52c2132 1033 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 1034 return;
1035 }
1036 cont->SetData(fTree); // This will notify all consumers
ed97dc98 1037 Long64_t entry = fTree->GetTree()->GetReadEntry();
1038
6bb2b24f 1039//
c3701689 1040// Call BeginEvent() for optional input/output and MC services
ed97dc98 1041 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1042 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1043 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 1044//
1045// Execute the tasks
276941c8 1046// TIter next1(cont->GetConsumers());
1047 TIter next1(fTopTasks);
327eaf46 1048 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1049 if (fDebug >1) {
1050 cout << " Executing task " << task->GetName() << endl;
1051 }
6bb2b24f 1052
327eaf46 1053 task->ExecuteTask(option);
1054 }
6bb2b24f 1055//
1056// Call FinishEvent() for optional output and MC services
6073f8c9 1057 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1058 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1059 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1060 // Gather system information if requested
1061 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1062 AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
327eaf46 1063 return;
1064 }
1065 // The event loop is not controlled by TSelector
6bb2b24f 1066//
c3701689 1067// Call BeginEvent() for optional input/output and MC services
ed97dc98 1068 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1069 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1070 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
327eaf46 1071 TIter next2(fTopTasks);
1072 while ((task=(AliAnalysisTask*)next2())) {
1073 task->SetActive(kTRUE);
c52c2132 1074 if (fDebug > 1) {
1075 cout << " Executing task " << task->GetName() << endl;
1076 }
d3106602 1077 task->ExecuteTask(option);
327eaf46 1078 }
6bb2b24f 1079//
1080// Call FinishEvent() for optional output and MC services
6073f8c9 1081 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1082 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1083 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 1084}
1085
1086//______________________________________________________________________________
1087void AliAnalysisManager::FinishAnalysis()
1088{
1089// Finish analysis.
1090}