]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisManager.cxx
Added method mgr->AddStatisticsTask(offlineMask) that allows to configure the statist...
[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//==============================================================================
c7597be6 20// AliAnalysisManager - 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
f5cbe261 28#include "AliAnalysisManager.h"
11026a80 29
f5cbe261 30#include <Riostream.h>
84fcd93f 31#include <TError.h>
c52c2132 32#include <TClass.h>
33#include <TFile.h>
096b5a2e 34#include <TMath.h>
35#include <TH1.h>
c52c2132 36#include <TMethodCall.h>
37#include <TChain.h>
38#include <TSystem.h>
39#include <TROOT.h>
8c0ab8e8 40#include <TCanvas.h>
a0e2e8b1 41#include <TStopwatch.h>
d3106602 42
8d7d3b59 43#include "AliAnalysisSelector.h"
c57f56b7 44#include "AliAnalysisGrid.h"
d3106602 45#include "AliAnalysisTask.h"
46#include "AliAnalysisDataContainer.h"
47#include "AliAnalysisDataSlot.h"
d2f1d9ef 48#include "AliVEventHandler.h"
c2922515 49#include "AliVEventPool.h"
8c0ab8e8 50#include "AliSysInfo.h"
f5cbe261 51#include "AliAnalysisStatistics.h"
d3106602 52
53ClassImp(AliAnalysisManager)
54
c52c2132 55AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
84fcd93f 56TString AliAnalysisManager::fgCommonFileName = "";
c52c2132 57
c52c2132 58//______________________________________________________________________________
59AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
60 :TNamed(name,title),
61 fTree(NULL),
8c0ab8e8 62 fInputEventHandler(NULL),
63 fOutputEventHandler(NULL),
64 fMCtruthEventHandler(NULL),
c57f56b7 65 fEventPool(NULL),
c52c2132 66 fCurrentEntry(-1),
8c0ab8e8 67 fNSysInfo(0),
c52c2132 68 fMode(kLocalAnalysis),
69 fInitOK(kFALSE),
8e1f0465 70 fIsRemote(kFALSE),
c52c2132 71 fDebug(0),
26f071d8 72 fSpecialOutputLocation(""),
37a26056 73 fTasks(NULL),
74 fTopTasks(NULL),
c52c2132 75 fZombies(NULL),
76 fContainers(NULL),
77 fInputs(NULL),
8d7d3b59 78 fOutputs(NULL),
6cd44ee0 79 fParamCont(NULL),
60a04972 80 fCommonInput(NULL),
81 fCommonOutput(NULL),
c57f56b7 82 fSelector(NULL),
c07b9ce2 83 fGridHandler(NULL),
012e169c 84 fExtraFiles(""),
85 fAutoBranchHandling(kTRUE),
242accb2 86 fTable(),
e9247450 87 fRunFromPath(0),
88 fNcalls(0),
7acc5b9d 89 fStatisticsMsg(),
f5cbe261 90 fRequestedBranches(),
91 fStatistics(0)
d3106602 92{
93// Default constructor.
c52c2132 94 fgAnalysisManager = this;
84fcd93f 95 fgCommonFileName = "AnalysisResults.root";
c52c2132 96 fTasks = new TObjArray();
97 fTopTasks = new TObjArray();
98 fZombies = new TObjArray();
99 fContainers = new TObjArray();
100 fInputs = new TObjArray();
37153431 101 fOutputs = new TObjArray();
6cd44ee0 102 fParamCont = new TObjArray();
b1310ef5 103 SetEventLoop(kTRUE);
48f1c230 104 TObject::SetObjectStat(kFALSE);
d3106602 105}
106
107//______________________________________________________________________________
108AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
c52c2132 109 :TNamed(other),
327eaf46 110 fTree(NULL),
8c0ab8e8 111 fInputEventHandler(NULL),
112 fOutputEventHandler(NULL),
113 fMCtruthEventHandler(NULL),
84fcd93f 114 fEventPool(NULL),
c52c2132 115 fCurrentEntry(-1),
8c0ab8e8 116 fNSysInfo(0),
c52c2132 117 fMode(other.fMode),
118 fInitOK(other.fInitOK),
8e1f0465 119 fIsRemote(other.fIsRemote),
c52c2132 120 fDebug(other.fDebug),
26f071d8 121 fSpecialOutputLocation(""),
37a26056 122 fTasks(NULL),
123 fTopTasks(NULL),
c52c2132 124 fZombies(NULL),
125 fContainers(NULL),
126 fInputs(NULL),
8d7d3b59 127 fOutputs(NULL),
6cd44ee0 128 fParamCont(NULL),
60a04972 129 fCommonInput(NULL),
130 fCommonOutput(NULL),
c57f56b7 131 fSelector(NULL),
c07b9ce2 132 fGridHandler(NULL),
012e169c 133 fExtraFiles(),
134 fAutoBranchHandling(other.fAutoBranchHandling),
242accb2 135 fTable(),
e9247450 136 fRunFromPath(0),
137 fNcalls(other.fNcalls),
7acc5b9d 138 fStatisticsMsg(other.fStatisticsMsg),
f5cbe261 139 fRequestedBranches(other.fRequestedBranches),
140 fStatistics(other.fStatistics)
d3106602 141{
142// Copy constructor.
37a26056 143 fTasks = new TObjArray(*other.fTasks);
144 fTopTasks = new TObjArray(*other.fTopTasks);
145 fZombies = new TObjArray(*other.fZombies);
c52c2132 146 fContainers = new TObjArray(*other.fContainers);
147 fInputs = new TObjArray(*other.fInputs);
148 fOutputs = new TObjArray(*other.fOutputs);
6cd44ee0 149 fParamCont = new TObjArray(*other.fParamCont);
84fcd93f 150 fgCommonFileName = "AnalysisResults.root";
c52c2132 151 fgAnalysisManager = this;
48f1c230 152 TObject::SetObjectStat(kFALSE);
d3106602 153}
154
155//______________________________________________________________________________
156AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
157{
158// Assignment
159 if (&other != this) {
c52c2132 160 TNamed::operator=(other);
54cff064 161 fInputEventHandler = other.fInputEventHandler;
6bb2b24f 162 fOutputEventHandler = other.fOutputEventHandler;
163 fMCtruthEventHandler = other.fMCtruthEventHandler;
c2922515 164 fEventPool = other.fEventPool;
c52c2132 165 fTree = NULL;
166 fCurrentEntry = -1;
8c0ab8e8 167 fNSysInfo = other.fNSysInfo;
c52c2132 168 fMode = other.fMode;
37a26056 169 fInitOK = other.fInitOK;
8e1f0465 170 fIsRemote = other.fIsRemote;
c52c2132 171 fDebug = other.fDebug;
37a26056 172 fTasks = new TObjArray(*other.fTasks);
173 fTopTasks = new TObjArray(*other.fTopTasks);
174 fZombies = new TObjArray(*other.fZombies);
c52c2132 175 fContainers = new TObjArray(*other.fContainers);
176 fInputs = new TObjArray(*other.fInputs);
177 fOutputs = new TObjArray(*other.fOutputs);
6cd44ee0 178 fParamCont = new TObjArray(*other.fParamCont);
60a04972 179 fCommonInput = NULL;
180 fCommonOutput = NULL;
8d7d3b59 181 fSelector = NULL;
c57f56b7 182 fGridHandler = NULL;
c07b9ce2 183 fExtraFiles = other.fExtraFiles;
84fcd93f 184 fgCommonFileName = "AnalysisResults.root";
c52c2132 185 fgAnalysisManager = this;
012e169c 186 fAutoBranchHandling = other.fAutoBranchHandling;
242accb2 187 fTable.Clear("nodelete");
188 fRunFromPath = other.fRunFromPath;
e9247450 189 fNcalls = other. fNcalls;
190 fStatisticsMsg = other.fStatisticsMsg;
7acc5b9d 191 fRequestedBranches = other.fRequestedBranches;
f5cbe261 192 fStatistics = other.fStatistics;
d3106602 193 }
194 return *this;
195}
196
197//______________________________________________________________________________
198AliAnalysisManager::~AliAnalysisManager()
199{
200// Destructor.
d3106602 201 if (fTasks) {fTasks->Delete(); delete fTasks;}
202 if (fTopTasks) delete fTopTasks;
203 if (fZombies) delete fZombies;
c52c2132 204 if (fContainers) {fContainers->Delete(); delete fContainers;}
205 if (fInputs) delete fInputs;
206 if (fOutputs) delete fOutputs;
6cd44ee0 207 if (fParamCont) delete fParamCont;
c57f56b7 208 if (fGridHandler) delete fGridHandler;
f3c07fbd 209 if (fInputEventHandler) delete fInputEventHandler;
210 if (fOutputEventHandler) delete fOutputEventHandler;
211 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
212 if (fEventPool) delete fEventPool;
c52c2132 213 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
48f1c230 214 TObject::SetObjectStat(kTRUE);
d3106602 215}
c52c2132 216
d3106602 217//______________________________________________________________________________
327eaf46 218Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
219{
220// Read one entry of the tree or a whole branch.
c52c2132 221 fCurrentEntry = entry;
012e169c 222 if (!fAutoBranchHandling)
f5cbe261 223 return 123456789;
224 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : -1;
327eaf46 225}
242accb2 226
227//______________________________________________________________________________
228Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
229{
230// Attempt to extract run number from input data path. Works only for paths to
231// alice data in alien.
232// sim: /alice/sim/<production>/run_no/...
233// data: /alice/data/year/period/000run_no/... (ESD or AOD)
234 TString s(path);
235 TString srun;
236 Int_t run = 0;
237 Int_t index = s.Index("/alice/sim");
238 if (index >= 0) {
239 for (Int_t i=0; i<3; i++) {
240 index = s.Index("/", index+1);
241 if (index<0) return 0;
242 }
243 srun = s(index+1,6);
244 run = atoi(srun);
245 }
246 index = s.Index("/alice/data");
247 if (index >= 0) {
248 for (Int_t i=0; i<4; i++) {
249 index = s.Index("/", index+1);
250 if (index<0) return 0;
251 }
252 srun = s(index+1,9);
253 run = atoi(srun);
254 }
255 return run;
256}
257
327eaf46 258//______________________________________________________________________________
2d626244 259Bool_t AliAnalysisManager::Init(TTree *tree)
d3106602 260{
261 // The Init() function is called when the selector needs to initialize
262 // a new tree or chain. Typically here the branch addresses of the tree
263 // will be set. It is normaly not necessary to make changes to the
264 // generated code, but the routine can be extended by the user if needed.
265 // Init() will be called many times when running with PROOF.
2d626244 266 Bool_t init = kFALSE;
267 if (!tree) return kFALSE; // Should not happen - protected in selector caller
cd463514 268 if (fDebug > 1) {
84fcd93f 269 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
c52c2132 270 }
f3d59a0d 271 // Call InitTree of EventHandler
36e82a52 272 if (fOutputEventHandler) {
273 if (fMode == kProofAnalysis) {
2d626244 274 init = fOutputEventHandler->Init(0x0, "proof");
36e82a52 275 } else {
2d626244 276 init = fOutputEventHandler->Init(0x0, "local");
36e82a52 277 }
2d626244 278 if (!init) {
279 Error("Init", "Output event handler failed to initialize");
280 return kFALSE;
281 }
36e82a52 282 }
2d626244 283
fdb458ec 284 if (fInputEventHandler) {
36e82a52 285 if (fMode == kProofAnalysis) {
2d626244 286 init = fInputEventHandler->Init(tree, "proof");
36e82a52 287 } else {
2d626244 288 init = fInputEventHandler->Init(tree, "local");
36e82a52 289 }
2d626244 290 if (!init) {
291 Error("Init", "Input event handler failed to initialize tree");
292 return kFALSE;
293 }
e7ae3836 294 } else {
295 // If no input event handler we need to get the tree once
296 // for the chain
2d626244 297 if(!tree->GetTree()) {
298 Long64_t readEntry = tree->LoadTree(0);
299 if (readEntry == -2) {
61505f8b 300 Error("Init", "Input tree has no entry. Exiting");
2d626244 301 return kFALSE;
302 }
303 }
36e82a52 304 }
305
306 if (fMCtruthEventHandler) {
307 if (fMode == kProofAnalysis) {
2d626244 308 init = fMCtruthEventHandler->Init(0x0, "proof");
36e82a52 309 } else {
2d626244 310 init = fMCtruthEventHandler->Init(0x0, "local");
36e82a52 311 }
2d626244 312 if (!init) {
313 Error("Init", "MC event handler failed to initialize");
314 return kFALSE;
315 }
fdb458ec 316 }
317
c52c2132 318 if (!fInitOK) InitAnalysis();
2d626244 319 if (!fInitOK) return kFALSE;
327eaf46 320 fTree = tree;
012e169c 321 fTable.Rehash(100);
ce46ecc1 322 AliAnalysisDataContainer *top = fCommonInput;
323 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
c52c2132 324 if (!top) {
8d7d3b59 325 Error("Init","No top input container !");
2d626244 326 return kFALSE;
37153431 327 }
327eaf46 328 top->SetData(tree);
7acc5b9d 329 CheckBranches(kFALSE);
cd463514 330 if (fDebug > 1) {
84fcd93f 331 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
981f2614 332 }
2d626244 333 return kTRUE;
d3106602 334}
335
d3106602 336//______________________________________________________________________________
327eaf46 337void AliAnalysisManager::SlaveBegin(TTree *tree)
d3106602 338{
339 // The SlaveBegin() function is called after the Begin() function.
340 // When running with PROOF SlaveBegin() is called on each slave server.
341 // The tree argument is deprecated (on PROOF 0 is passed).
cd463514 342 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
aee5ee44 343 static Bool_t isCalled = kFALSE;
2d626244 344 Bool_t init = kFALSE;
345 Bool_t initOK = kTRUE;
346 TString msg;
4ab472d4 347 TDirectory *curdir = gDirectory;
aee5ee44 348 // Call SlaveBegin only once in case of mixing
349 if (isCalled && fMode==kMixingAnalysis) return;
979e448a 350 gROOT->cd();
f3d59a0d 351 // Call Init of EventHandler
352 if (fOutputEventHandler) {
353 if (fMode == kProofAnalysis) {
673f68ff 354 // Merging AOD's in PROOF via TProofOutputFile
84fcd93f 355 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
673f68ff 356 init = fOutputEventHandler->Init("proof");
357 if (!init) msg = "Failed to initialize output handler on worker";
f3d59a0d 358 } else {
2d626244 359 init = fOutputEventHandler->Init("local");
673f68ff 360 if (!init) msg = "Failed to initialize output handler";
f3d59a0d 361 }
2d626244 362 initOK &= init;
363 if (!fSelector) Error("SlaveBegin", "Selector not set");
364 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 365 }
979e448a 366 gROOT->cd();
f3d59a0d 367 if (fInputEventHandler) {
368 fInputEventHandler->SetInputTree(tree);
369 if (fMode == kProofAnalysis) {
2d626244 370 init = fInputEventHandler->Init("proof");
371 if (!init) msg = "Failed to initialize input handler on worker";
f3d59a0d 372 } else {
2d626244 373 init = fInputEventHandler->Init("local");
374 if (!init) msg = "Failed to initialize input handler";
f3d59a0d 375 }
2d626244 376 initOK &= init;
377 if (!fSelector) Error("SlaveBegin", "Selector not set");
378 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 379 }
979e448a 380 gROOT->cd();
f3d59a0d 381 if (fMCtruthEventHandler) {
382 if (fMode == kProofAnalysis) {
2d626244 383 init = fMCtruthEventHandler->Init("proof");
384 if (!init) msg = "Failed to initialize MC handler on worker";
f3d59a0d 385 } else {
2d626244 386 init = fMCtruthEventHandler->Init("local");
387 if (!init) msg = "Failed to initialize MC handler";
f3d59a0d 388 }
2d626244 389 initOK &= init;
390 if (!fSelector) Error("SlaveBegin", "Selector not set");
391 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 392 }
4ab472d4 393 if (curdir) curdir->cd();
2d626244 394 isCalled = kTRUE;
395 if (!initOK) return;
c52c2132 396 TIter next(fTasks);
397 AliAnalysisTask *task;
398 // Call CreateOutputObjects for all tasks
096b5a2e 399 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
979e448a 400 Bool_t dirStatus = TH1::AddDirectoryStatus();
096b5a2e 401 Int_t itask = 0;
c5a87c56 402 while ((task=(AliAnalysisTask*)next())) {
979e448a 403 gROOT->cd();
404 // Start with memory as current dir and make sure by default histograms do not get attached to files.
405 TH1::AddDirectory(kFALSE);
c52c2132 406 task->CreateOutputObjects();
096b5a2e 407 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
408 itask++;
36e82a52 409 }
979e448a 410 TH1::AddDirectory(dirStatus);
411 if (curdir) curdir->cd();
cd463514 412 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
d3106602 413}
414
415//______________________________________________________________________________
327eaf46 416Bool_t AliAnalysisManager::Notify()
417{
418 // The Notify() function is called when a new file is opened. This
419 // can be either for a new TTree in a TChain or when when a new TTree
420 // is started when using PROOF. It is normaly not necessary to make changes
421 // to the generated code, but the routine can be extended by the
422 // user if needed. The return value is currently not used.
2d626244 423 if (!fTree) return kFALSE;
012e169c 424
425 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
8e1f0465 426 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
2d626244 427
8d7d3b59 428 TFile *curfile = fTree->GetCurrentFile();
429 if (!curfile) {
430 Error("Notify","No current file");
431 return kFALSE;
432 }
433
cd463514 434 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
242accb2 435 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
436 if (run) SetRunFromPath(run);
437 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
8d7d3b59 438 TIter next(fTasks);
439 AliAnalysisTask *task;
fdb458ec 440
8d7d3b59 441 // Call Notify of the event handlers
442 if (fInputEventHandler) {
443 fInputEventHandler->Notify(curfile->GetName());
444 }
6073f8c9 445
8d7d3b59 446 if (fOutputEventHandler) {
447 fOutputEventHandler->Notify(curfile->GetName());
448 }
890126ab 449
8d7d3b59 450 if (fMCtruthEventHandler) {
451 fMCtruthEventHandler->Notify(curfile->GetName());
452 }
012e169c 453
242accb2 454 // Call Notify for all tasks
455 while ((task=(AliAnalysisTask*)next()))
456 task->Notify();
457
cd463514 458 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
8d7d3b59 459 return kTRUE;
327eaf46 460}
461
462//______________________________________________________________________________
463Bool_t AliAnalysisManager::Process(Long64_t entry)
d3106602 464{
465 // The Process() function is called for each entry in the tree (or possibly
466 // keyed object in the case of PROOF) to be processed. The entry argument
467 // specifies which entry in the currently loaded tree is to be processed.
468 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
469 // to read either all or the required parts of the data. When processing
470 // keyed objects with PROOF, the object is already loaded and is available
471 // via the fObject pointer.
472 //
473 // This function should contain the "body" of the analysis. It can contain
474 // simple or elaborate selection criteria, run algorithms on the data
475 // of the event and typically fill histograms.
476
477 // WARNING when a selector is used with a TChain, you must use
478 // the pointer to the current TTree to call GetEntry(entry).
479 // The entry is always the local entry number in the current tree.
480 // Assuming that fChain is the pointer to the TChain being processed,
481 // use fChain->GetTree()->GetEntry(entry).
cd463514 482 if (fDebug > 1) printf("->AliAnalysisManager::Process(%lld)\n", entry);
8d7d3b59 483
ed97dc98 484 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
485 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
486 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 487
327eaf46 488 GetEntry(entry);
0d6a82a5 489
490 if (fInputEventHandler) fInputEventHandler ->GetEntry();
491
327eaf46 492 ExecAnalysis();
cd463514 493 if (fDebug > 1) printf("<-AliAnalysisManager::Process()\n");
327eaf46 494 return kTRUE;
d3106602 495}
496
497//______________________________________________________________________________
c52c2132 498void AliAnalysisManager::PackOutput(TList *target)
d3106602 499{
981f2614 500 // Pack all output data containers in the output list. Called at SlaveTerminate
501 // stage in PROOF case for each slave.
cd463514 502 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
c52c2132 503 if (!target) {
61505f8b 504 Error("PackOutput", "No target. Exiting.");
c52c2132 505 return;
37153431 506 }
57756ec5 507 TDirectory *cdir = gDirectory;
508 gROOT->cd();
6073f8c9 509 if (fInputEventHandler) fInputEventHandler ->Terminate();
6bb2b24f 510 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
511 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
57756ec5 512 gROOT->cd();
8d7d3b59 513
514 // Call FinishTaskOutput() for each event loop task (not called for
515 // post-event loop tasks - use Terminate() fo those)
516 TIter nexttask(fTasks);
517 AliAnalysisTask *task;
518 while ((task=(AliAnalysisTask*)nexttask())) {
519 if (!task->IsPostEventLoop()) {
cd463514 520 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
8d7d3b59 521 task->FinishTaskOutput();
57756ec5 522 gROOT->cd();
cd463514 523 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
8d7d3b59 524 }
e9247450 525 }
526 // Write statistics message on the workers.
527 WriteStatisticsMsg(fNcalls);
8c9485b2 528
c52c2132 529 if (fMode == kProofAnalysis) {
530 TIter next(fOutputs);
531 AliAnalysisDataContainer *output;
4ab472d4 532 Bool_t isManagedByHandler = kFALSE;
ab5d25d8 533 TList filestmp;
534 filestmp.SetOwner();
c52c2132 535 while ((output=(AliAnalysisDataContainer*)next())) {
8d7d3b59 536 // Do not consider outputs of post event loop tasks
2b83ca27 537 isManagedByHandler = kFALSE;
1c5dff85 538 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
4ab472d4 539 const char *filename = output->GetFileName();
540 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
541 isManagedByHandler = kTRUE;
84fcd93f 542 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
4ab472d4 543 filename = fOutputEventHandler->GetOutputFileName();
544 }
8d7d3b59 545 // Check if data was posted to this container. If not, issue an error.
4ab472d4 546 if (!output->GetData() && !isManagedByHandler) {
923e2ca5 547 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
8d7d3b59 548 continue;
549 }
550 if (!output->IsSpecialOutput()) {
551 // Normal outputs
4ab472d4 552 if (strlen(filename) && !isManagedByHandler) {
8d7d3b59 553 // Backup current folder
ca78991b 554 TDirectory *opwd = gDirectory;
f2087b52 555 // File resident outputs.
556 // Check first if the file exists.
61505f8b 557 TString openoption = "RECREATE";
ab5d25d8 558 Bool_t firsttime = kTRUE;
559 if (filestmp.FindObject(output->GetFileName())) {
560 firsttime = kFALSE;
561 } else {
562 filestmp.Add(new TNamed(output->GetFileName(),""));
563 }
564 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
565// TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
8d7d3b59 566 // Save data to file, then close.
1be433fc 567 if (output->GetData()->InheritsFrom(TCollection::Class())) {
568 // If data is a collection, we set the name of the collection
569 // as the one of the container and we save as a single key.
570 TCollection *coll = (TCollection*)output->GetData();
571 coll->SetName(output->GetName());
ab5d25d8 572// coll->Write(output->GetName(), TObject::kSingleKey);
1be433fc 573 } else {
cbc8747a 574 if (output->GetData()->InheritsFrom(TTree::Class())) {
ab5d25d8 575 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
576 // Save data to file, then close.
cbc8747a 577 TTree *tree = (TTree*)output->GetData();
57756ec5 578 // Check if tree is in memory
579 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
cbc8747a 580 tree->AutoSave();
ab5d25d8 581 file->Close();
cbc8747a 582 } else {
ab5d25d8 583// output->GetData()->Write();
cbc8747a 584 }
1be433fc 585 }
84fcd93f 586 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
ab5d25d8 587// if (fDebug > 2) {
588// printf(" file %s listing content:\n", filename);
589// file->ls();
590// }
f3c07fbd 591 // Clear file list to release object ownership to user.
160e7161 592// file->Clear();
ab5d25d8 593// file->Close();
84fcd93f 594 output->SetFile(NULL);
ca78991b 595 // Restore current directory
596 if (opwd) opwd->cd();
8d7d3b59 597 } else {
598 // Memory-resident outputs
84fcd93f 599 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
4ab472d4 600 }
601 AliAnalysisDataWrapper *wrap = 0;
602 if (isManagedByHandler) {
603 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
604 wrap->SetName(output->GetName());
ca78991b 605 }
4ab472d4 606 else wrap =output->ExportData();
cbc8747a 607 // Output wrappers must NOT delete data after merging - the user owns them
608 wrap->SetDeleteData(kFALSE);
8167b1d0 609 target->Add(wrap);
4ab472d4 610 } else {
f5e61abd 611 // Special outputs. The file must be opened and connected to the container.
d0864eb4 612 TDirectory *opwd = gDirectory;
8d7d3b59 613 TFile *file = output->GetFile();
f5e61abd 614 if (!file) {
615 AliAnalysisTask *producer = output->GetProducer();
84fcd93f 616 Fatal("PackOutput",
f5e61abd 617 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
618 output->GetFileName(), output->GetName(), producer->ClassName());
619 continue;
620 }
621 TString outFilename = file->GetName();
84fcd93f 622 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
4ab472d4 623 if (isManagedByHandler) {
624 // Terminate IO for files managed by the output handler
aa399a26 625 // file->Write() moved to AOD handler (A.G. 11.01.10)
626// if (file) file->Write();
802f90ef 627 if (file && fDebug > 2) {
84fcd93f 628 printf(" handled file %s listing content:\n", file->GetName());
802f90ef 629 file->ls();
630 }
4ab472d4 631 fOutputEventHandler->TerminateIO();
f5e61abd 632 } else {
633 file->cd();
634 // Release object ownership to users after writing data to file
635 if (output->GetData()->InheritsFrom(TCollection::Class())) {
636 // If data is a collection, we set the name of the collection
637 // as the one of the container and we save as a single key.
638 TCollection *coll = (TCollection*)output->GetData();
639 coll->SetName(output->GetName());
640 coll->Write(output->GetName(), TObject::kSingleKey);
cbc8747a 641 } else {
f5e61abd 642 if (output->GetData()->InheritsFrom(TTree::Class())) {
643 TTree *tree = (TTree*)output->GetData();
644 tree->SetDirectory(file);
645 tree->AutoSave();
646 } else {
647 output->GetData()->Write();
648 }
649 }
f5e61abd 650 if (fDebug > 2) {
84fcd93f 651 printf(" file %s listing content:\n", output->GetFileName());
f5e61abd 652 file->ls();
653 }
f3c07fbd 654 // Clear file list to release object ownership to user.
160e7161 655// file->Clear();
f5e61abd 656 file->Close();
84fcd93f 657 output->SetFile(NULL);
ef73322e 658 }
8d7d3b59 659 // Restore current directory
d0864eb4 660 if (opwd) opwd->cd();
8d7d3b59 661 // Check if a special output location was provided or the output files have to be merged
13ef3bb0 662 if (strlen(fSpecialOutputLocation.Data())) {
663 TString remote = fSpecialOutputLocation;
664 remote += "/";
ef788aee 665 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
3bdcb562 666 if (remote.BeginsWith("alien:")) {
667 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
f5e61abd 668 remote += outFilename;
669 remote.ReplaceAll(".root", Form("_%d.root", gid));
670 } else {
671 remote += Form("%s_%d_", gSystem->HostName(), gid);
672 remote += outFilename;
673 }
674 if (fDebug > 1)
675 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
676 output->GetName(), remote.Data());
ef73322e 677 TFile::Cp ( outFilename.Data(), remote.Data() );
c9e39043 678 // Copy extra outputs
679 if (fExtraFiles.Length() && isManagedByHandler) {
680 TObjArray *arr = fExtraFiles.Tokenize(" ");
681 TObjString *os;
682 TIter nextfilename(arr);
683 while ((os=(TObjString*)nextfilename())) {
684 outFilename = os->GetString();
685 remote = fSpecialOutputLocation;
686 remote += "/";
687 if (remote.BeginsWith("alien://")) {
688 remote += outFilename;
689 remote.ReplaceAll(".root", Form("_%d.root", gid));
690 } else {
691 remote += Form("%s_%d_", gSystem->HostName(), gid);
692 remote += outFilename;
693 }
694 if (fDebug > 1)
695 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
696 outFilename.Data(), remote.Data());
697 TFile::Cp ( outFilename.Data(), remote.Data() );
698 }
699 delete arr;
700 }
ca78991b 701 } else {
8d7d3b59 702 // No special location specified-> use TProofOutputFile as merging utility
703 // The file at this output slot must be opened in CreateOutputObjects
84fcd93f 704 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
13ef3bb0 705 }
706 }
c52c2132 707 }
708 }
57756ec5 709 cdir->cd();
cd463514 710 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
c52c2132 711}
712
713//______________________________________________________________________________
981f2614 714void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 715{
981f2614 716// Import data in output containers from wrappers coming in source.
cd463514 717 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
327eaf46 718 TIter next(fOutputs);
981f2614 719 AliAnalysisDataContainer *cont;
720 AliAnalysisDataWrapper *wrap;
721 Int_t icont = 0;
c57f56b7 722 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
84fcd93f 723 TDirectory *cdir = gDirectory;
c52c2132 724 while ((cont=(AliAnalysisDataContainer*)next())) {
0355fc48 725 wrap = 0;
f3c07fbd 726 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
90a4b3ee 727 if (cont->IsRegisterDataset()) continue;
4ab472d4 728 const char *filename = cont->GetFileName();
729 Bool_t isManagedByHandler = kFALSE;
730 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
731 isManagedByHandler = kTRUE;
732 filename = fOutputEventHandler->GetOutputFileName();
733 }
c57f56b7 734 if (cont->IsSpecialOutput() || inGrid) {
f5e61abd 735 if (strlen(fSpecialOutputLocation.Data())) continue;
c57f56b7 736 // Copy merged file from PROOF scratch space.
737 // In case of grid the files are already in the current directory.
738 if (!inGrid) {
c07b9ce2 739 if (isManagedByHandler && fExtraFiles.Length()) {
740 // Copy extra registered dAOD files.
741 TObjArray *arr = fExtraFiles.Tokenize(" ");
742 TObjString *os;
743 TIter nextfilename(arr);
744 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
745 delete arr;
c57f56b7 746 }
c07b9ce2 747 if (!GetFileFromWrapper(filename, source)) continue;
c57f56b7 748 }
8d7d3b59 749 // Normally we should connect data from the copied file to the
750 // corresponding output container, but it is not obvious how to do this
751 // automatically if several objects in file...
84fcd93f 752 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
753 if (!f) f = TFile::Open(filename, "READ");
dd197a68 754 if (!f) {
755 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
0355fc48 756 continue;
dd197a68 757 }
758 TObject *obj = 0;
84fcd93f 759 // Cd to the directory pointed by the container
760 TString folder = cont->GetFolderName();
761 if (!folder.IsNull()) f->cd(folder);
762 // Try to fetch first an object having the container name.
763 obj = gDirectory->Get(cont->GetName());
dd197a68 764 if (!obj) {
c7597be6 765 Warning("ImportWrappers", "Could not import object of type:%s for container %s in file %s:%s.\n Object will not be available in Terminate(). Try if possible to name the output object as the container (%s) or to embed it in a TList",
766 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
dd197a68 767 continue;
768 }
0355fc48 769 wrap = new AliAnalysisDataWrapper(obj);
770 wrap->SetDeleteData(kFALSE);
8d7d3b59 771 }
0355fc48 772 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 773 if (!wrap) {
774 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 775 continue;
776 }
981f2614 777 icont++;
8d7d3b59 778 if (fDebug > 1) {
84fcd93f 779 printf(" Importing data for container %s\n", cont->GetName());
780 if (strlen(filename)) printf(" -> file %s\n", filename);
781 else printf("\n");
8d7d3b59 782 }
981f2614 783 cont->ImportData(wrap);
84fcd93f 784 }
785 if (cdir) cdir->cd();
cd463514 786 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 787}
788
789//______________________________________________________________________________
790void AliAnalysisManager::UnpackOutput(TList *source)
791{
ca78991b 792 // Called by AliAnalysisSelector::Terminate only on the client.
cd463514 793 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 794 if (!source) {
61505f8b 795 Error("UnpackOutput", "No target. Exiting.");
c52c2132 796 return;
797 }
84fcd93f 798 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
c52c2132 799
981f2614 800 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 801
981f2614 802 TIter next(fOutputs);
c52c2132 803 AliAnalysisDataContainer *output;
804 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 805 if (!output->GetData()) continue;
b1310ef5 806 // Check if there are client tasks that run post event loop
807 if (output->HasConsumers()) {
808 // Disable event loop semaphore
809 output->SetPostEventLoop(kTRUE);
810 TObjArray *list = output->GetConsumers();
811 Int_t ncons = list->GetEntriesFast();
812 for (Int_t i=0; i<ncons; i++) {
813 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
814 task->CheckNotify(kTRUE);
815 // If task is active, execute it
816 if (task->IsPostEventLoop() && task->IsActive()) {
cd463514 817 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 818 task->ExecuteTask();
819 }
820 }
821 }
c52c2132 822 }
cd463514 823 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 824}
825
826//______________________________________________________________________________
827void AliAnalysisManager::Terminate()
828{
829 // The Terminate() function is the last function to be called during
830 // a query. It always runs on the client, it can be used to present
c52c2132 831 // the results graphically.
cd463514 832 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
57756ec5 833 TDirectory *cdir = gDirectory;
834 gROOT->cd();
327eaf46 835 AliAnalysisTask *task;
a0e2e8b1 836 AliAnalysisDataContainer *output;
c52c2132 837 TIter next(fTasks);
a0e2e8b1 838 TStopwatch timer;
096b5a2e 839 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
327eaf46 840 // Call Terminate() for tasks
096b5a2e 841 Int_t itask = 0;
90a4b3ee 842 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
a0e2e8b1 843 // Save all the canvases produced by the Terminate
844 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
a0e2e8b1 845 task->Terminate();
57756ec5 846 gROOT->cd();
096b5a2e 847 if (getsysInfo)
848 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
849 itask++;
a0e2e8b1 850 if (TObject::TestBit(kSaveCanvases)) {
226abfec 851 if (!gROOT->IsBatch()) {
8e1f0465 852 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
226abfec 853 timer.Start();
854 while (timer.CpuTime()<5) {
855 timer.Continue();
856 gSystem->ProcessEvents();
857 }
858 }
859 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
860 if (iend==0) continue;
a0e2e8b1 861 TCanvas *canvas;
226abfec 862 for (Int_t ipict=0; ipict<iend; ipict++) {
863 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
a0e2e8b1 864 if (!canvas) continue;
865 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
226abfec 866 }
867 gROOT->GetListOfCanvases()->Delete();
a0e2e8b1 868 }
869 }
8c9485b2 870 //
aa399a26 871 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
872 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
873 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
57756ec5 874 gROOT->cd();
6cd44ee0 875 TObjArray *allOutputs = new TObjArray();
876 Int_t icont;
877 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
878 if (!IsSkipTerminate())
879 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
880 TIter next1(allOutputs);
f2087b52 881 TString handlerFile = "";
90d50a8c 882 TString extraOutputs = "";
f2087b52 883 if (fOutputEventHandler) {
884 handlerFile = fOutputEventHandler->GetOutputFileName();
90d50a8c 885 extraOutputs = fOutputEventHandler->GetExtraOutputs();
f2087b52 886 }
e16a394c 887 icont = 0;
ab5d25d8 888 TList filestmp;
8c0ab8e8 889 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 890 // Special outputs or grid files have the files already closed and written.
e16a394c 891 icont++;
892 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
90a4b3ee 893 if (fMode == kProofAnalysis) {
894 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
895 }
8c0ab8e8 896 const char *filename = output->GetFileName();
61505f8b 897 TString openoption = "RECREATE";
aa399a26 898 if (!(strcmp(filename, "default"))) continue;
8d7d3b59 899 if (!strlen(filename)) continue;
1be433fc 900 if (!output->GetData()) continue;
8d7d3b59 901 TDirectory *opwd = gDirectory;
84fcd93f 902 TFile *file = output->GetFile();
903 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
f2087b52 904 if (!file) {
61505f8b 905 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
ab5d25d8 906 Bool_t firsttime = kTRUE;
90d50a8c 907 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
ab5d25d8 908 firsttime = kFALSE;
909 } else {
910 filestmp.Add(new TNamed(filename,""));
911 }
912 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
cd463514 913 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
61505f8b 914 file = new TFile(filename, openoption);
6cd44ee0 915 } else {
cd463514 916 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
ff07ec61 917 openoption = file->GetOption();
918 if (openoption == "READ") {
cd463514 919 if (fDebug>1) printf("...reopening in UPDATE mode\n");
ff07ec61 920 file->ReOpen("UPDATE");
921 }
6cd44ee0 922 }
84fcd93f 923 if (file->IsZombie()) {
924 Error("Terminate", "Cannot open output file %s", filename);
925 continue;
926 }
8e6e6fe8 927 output->SetFile(file);
928 file->cd();
84fcd93f 929 // Check for a folder request
930 TString dir = output->GetFolderName();
931 if (!dir.IsNull()) {
932 if (!file->GetDirectory(dir)) file->mkdir(dir);
933 file->cd(dir);
934 }
cd463514 935 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1be433fc 936 if (output->GetData()->InheritsFrom(TCollection::Class())) {
937 // If data is a collection, we set the name of the collection
938 // as the one of the container and we save as a single key.
939 TCollection *coll = (TCollection*)output->GetData();
940 coll->SetName(output->GetName());
941 coll->Write(output->GetName(), TObject::kSingleKey);
942 } else {
cbc8747a 943 if (output->GetData()->InheritsFrom(TTree::Class())) {
944 TTree *tree = (TTree*)output->GetData();
7a151c06 945 tree->SetDirectory(gDirectory);
cbc8747a 946 tree->AutoSave();
947 } else {
948 output->GetData()->Write();
949 }
1be433fc 950 }
8e6e6fe8 951 if (opwd) opwd->cd();
57756ec5 952 }
953 gROOT->cd();
8e6e6fe8 954 next1.Reset();
955 while ((output=(AliAnalysisDataContainer*)next1())) {
956 // Close all files at output
957 TDirectory *opwd = gDirectory;
f5e61abd 958 if (output->GetFile()) {
f3c07fbd 959 // Clear file list to release object ownership to user.
160e7161 960// output->GetFile()->Clear();
f5e61abd 961 output->GetFile()->Close();
84fcd93f 962 output->SetFile(NULL);
f5e61abd 963 // Copy merged outputs in alien if requested
964 if (fSpecialOutputLocation.Length() &&
965 fSpecialOutputLocation.BeginsWith("alien://")) {
966 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
967 TFile::Cp(output->GetFile()->GetName(),
968 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
969 }
970 }
8d7d3b59 971 if (opwd) opwd->cd();
8c0ab8e8 972 }
6cd44ee0 973 delete allOutputs;
e9247450 974 //Write statistics information on the client
975 WriteStatisticsMsg(fNcalls);
8c0ab8e8 976 if (getsysInfo) {
b6db1d18 977 TDirectory *crtdir = gDirectory;
8c0ab8e8 978 TFile f("syswatch.root", "RECREATE");
096b5a2e 979 TH1 *hist;
980 TString cut;
8c0ab8e8 981 if (!f.IsZombie()) {
982 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
096b5a2e 983 tree->SetName("syswatch");
8c0ab8e8 984 tree->SetMarkerStyle(kCircle);
985 tree->SetMarkerColor(kBlue);
986 tree->SetMarkerSize(0.5);
987 if (!gROOT->IsBatch()) {
988 tree->SetAlias("event", "id0");
096b5a2e 989 tree->SetAlias("task", "id1");
990 tree->SetAlias("stage", "id2");
991 // Already defined aliases
992 // tree->SetAlias("deltaT","stampSec-stampOldSec");
993 // tree->SetAlias("T","stampSec-first");
994 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
995 // tree->SetAlias("VM","pI.fMemVirtual");
996 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
997 Int_t npads = 1 /*COO plot for all tasks*/ +
998 fTopTasks->GetEntries() /*Exec plot per task*/ +
999 1 /*Terminate plot for all tasks*/ +
1000 1; /*vm plot*/
1001
1002 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1003 if (npads<iopt*(iopt+1))
1004 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1005 else
1006 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1007 Int_t ipad = 1;
1008 // draw the plot of deltaVM for Exec for each task
779e9992 1009 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
096b5a2e 1010 task = (AliAnalysisTask*)fTopTasks->At(itask);
1011 canvas->cd(ipad++);
1012 cut = Form("task==%d && stage==1", itask);
1013 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1014 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1015 if (hist) {
1016 hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
b3e07543 1017 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1018 }
1019 }
1020 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1021 canvas->cd(ipad++);
1022 tree->SetMarkerStyle(kFullTriangleUp);
1023 tree->SetMarkerColor(kRed);
1024 tree->SetMarkerSize(0.8);
1025 cut = "task>=0 && task<1000 && stage==0";
1026 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1027 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1028 if (hist) {
1029 hist->SetTitle("Memory in CreateOutputObjects()");
b3e07543 1030 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1031 hist->GetXaxis()->SetTitle("task");
1032 }
1033 // draw the plot of deltaVM for Terminate for all tasks
1034 canvas->cd(ipad++);
1035 tree->SetMarkerStyle(kOpenSquare);
1036 tree->SetMarkerColor(kMagenta);
1037 cut = "task>=0 && task<1000 && stage==2";
1038 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1039 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1040 if (hist) {
1041 hist->SetTitle("Memory in Terminate()");
b3e07543 1042 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1043 hist->GetXaxis()->SetTitle("task");
1044 }
1045 // Full VM profile
1046 canvas->cd(ipad++);
1047 tree->SetMarkerStyle(kFullCircle);
1048 tree->SetMarkerColor(kGreen);
1049 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1050 tree->Draw("VM:event",cut,"", 1234567890, 0);
1051 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1052 if (hist) {
1053 hist->SetTitle("Virtual memory");
b3e07543 1054 hist->GetYaxis()->SetTitle("VM [MB]");
096b5a2e 1055 }
1056 canvas->Modified();
8c0ab8e8 1057 }
096b5a2e 1058 tree->SetMarkerStyle(kCircle);
1059 tree->SetMarkerColor(kBlue);
1060 tree->SetMarkerSize(0.5);
8c0ab8e8 1061 tree->Write();
1062 f.Close();
1063 delete tree;
1064 }
b6db1d18 1065 if (crtdir) crtdir->cd();
923e2ca5 1066 }
1067 // Validate the output files
1068 if (ValidateOutputFiles()) {
1069 ofstream out;
1070 out.open("outputs_valid", ios::out);
1071 out.close();
57756ec5 1072 }
1073 cdir->cd();
cd463514 1074 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 1075}
096b5a2e 1076//______________________________________________________________________________
1077void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1078{
1079// Profiles the task having the itop index in the list of top (first level) tasks.
1080 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1081 if (!task) {
1082 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1083 return;
1084 }
1085 ProfileTask(task->GetName(), option);
1086}
1087
1088//______________________________________________________________________________
1089void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1090{
1091// Profile a managed task after the execution of the analysis in case NSysInfo
1092// was used.
1093 if (gSystem->AccessPathName("syswatch.root")) {
1094 Error("ProfileTask", "No file syswatch.root found in the current directory");
1095 return;
1096 }
1097 if (gROOT->IsBatch()) return;
1098 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1099 if (!task) {
1100 Error("ProfileTask", "No top task named %s known by the manager.", name);
1101 return;
1102 }
1103 Int_t itop = fTopTasks->IndexOf(task);
1104 Int_t itask = fTasks->IndexOf(task);
1105 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1106 TDirectory *cdir = gDirectory;
1107 TFile f("syswatch.root");
1108 TTree *tree = (TTree*)f.Get("syswatch");
1109 if (!tree) {
1110 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1111 return;
1112 }
cd463514 1113 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
096b5a2e 1114 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1115 canvas->Divide(2, 2, 0.01, 0.01);
1116 Int_t ipad = 1;
1117 TString cut;
1118 TH1 *hist;
1119 // VM profile for COO and Terminate methods
1120 canvas->cd(ipad++);
1121 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1122 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1123 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1124 if (hist) {
1125 hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1126 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1127 hist->GetXaxis()->SetTitle("method");
1128 }
1129 // CPU profile per event
1130 canvas->cd(ipad++);
1131 cut = Form("task==%d && stage==1",itop);
1132 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1133 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1134 if (hist) {
1135 hist->SetTitle("Execution time per event");
1136 hist->GetYaxis()->SetTitle("CPU/event [s]");
1137 }
1138 // VM profile for Exec
1139 canvas->cd(ipad++);
1140 cut = Form("task==%d && stage==1",itop);
1141 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1142 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1143 if (hist) {
1144 hist->SetTitle("Alocated VM[kB] per event");
1145 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1146 }
1147 canvas->Modified();
1148 delete tree;
1149 f.Close();
1150 if (cdir) cdir->cd();
1151}
d3106602 1152
1153//______________________________________________________________________________
1154void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1155{
1156// Adds a user task to the global list of tasks.
8d7d3b59 1157 if (fTasks->FindObject(task)) {
1158 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1159 return;
1160 }
d3106602 1161 task->SetActive(kFALSE);
1162 fTasks->Add(task);
1163}
1164
1165//______________________________________________________________________________
1166AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1167{
1168// Retreive task by name.
1169 if (!fTasks) return NULL;
1170 return (AliAnalysisTask*)fTasks->FindObject(name);
1171}
1172
1173//______________________________________________________________________________
1174AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 1175 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 1176{
1177// Create a data container of a certain type. Types can be:
84fcd93f 1178// kExchangeContainer = 0, used to exchange data between tasks
d3106602 1179// kInputContainer = 1, used to store input data
84fcd93f 1180// kOutputContainer = 2, used for writing result to a file
1181// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1182// the output object to a folder inside the output file
b1310ef5 1183 if (fContainers->FindObject(name)) {
923e2ca5 1184 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 1185 return NULL;
1186 }
d3106602 1187 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1188 fContainers->Add(cont);
1189 switch (type) {
1190 case kInputContainer:
1191 fInputs->Add(cont);
1192 break;
1193 case kOutputContainer:
1194 fOutputs->Add(cont);
8c0ab8e8 1195 if (filename && strlen(filename)) {
1196 cont->SetFileName(filename);
6cd44ee0 1197 cont->SetDataOwned(kFALSE); // data owned by the file
1198 }
1199 break;
1200 case kParamContainer:
1201 fParamCont->Add(cont);
1202 if (filename && strlen(filename)) {
1203 cont->SetFileName(filename);
8c0ab8e8 1204 cont->SetDataOwned(kFALSE); // data owned by the file
1205 }
d3106602 1206 break;
c52c2132 1207 case kExchangeContainer:
d3106602 1208 break;
1209 }
1210 return cont;
1211}
1212
1213//______________________________________________________________________________
1214Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1215 AliAnalysisDataContainer *cont)
1216{
1217// Connect input of an existing task to a data container.
60a04972 1218 if (!task) {
1219 Error("ConnectInput", "Task pointer is NULL");
1220 return kFALSE;
1221 }
d3106602 1222 if (!fTasks->FindObject(task)) {
1223 AddTask(task);
8d7d3b59 1224 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 1225 }
1226 Bool_t connected = task->ConnectInput(islot, cont);
1227 return connected;
1228}
1229
1230//______________________________________________________________________________
1231Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1232 AliAnalysisDataContainer *cont)
1233{
1234// Connect output of an existing task to a data container.
60a04972 1235 if (!task) {
1236 Error("ConnectOutput", "Task pointer is NULL");
1237 return kFALSE;
1238 }
d3106602 1239 if (!fTasks->FindObject(task)) {
1240 AddTask(task);
c52c2132 1241 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 1242 }
1243 Bool_t connected = task->ConnectOutput(islot, cont);
1244 return connected;
1245}
1246
1247//______________________________________________________________________________
1248void AliAnalysisManager::CleanContainers()
1249{
1250// Clean data from all containers that have already finished all client tasks.
1251 TIter next(fContainers);
1252 AliAnalysisDataContainer *cont;
1253 while ((cont=(AliAnalysisDataContainer *)next())) {
1254 if (cont->IsOwnedData() &&
1255 cont->IsDataReady() &&
1256 cont->ClientsExecuted()) cont->DeleteData();
1257 }
1258}
1259
1260//______________________________________________________________________________
1261Bool_t AliAnalysisManager::InitAnalysis()
1262{
1263// Initialization of analysis chain of tasks. Should be called after all tasks
1264// and data containers are properly connected
923e2ca5 1265 // Reset flag and remove valid_outputs file if exists
d3106602 1266 fInitOK = kFALSE;
923e2ca5 1267 if (!gSystem->AccessPathName("outputs_valid"))
1268 gSystem->Unlink("outputs_valid");
d3106602 1269 // Check for top tasks (depending only on input data containers)
1270 if (!fTasks->First()) {
c52c2132 1271 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 1272 return kFALSE;
1273 }
1274 TIter next(fTasks);
1275 AliAnalysisTask *task;
1276 AliAnalysisDataContainer *cont;
1277 Int_t ntop = 0;
1278 Int_t nzombies = 0;
327eaf46 1279 Bool_t iszombie = kFALSE;
1280 Bool_t istop = kTRUE;
d3106602 1281 Int_t i;
1282 while ((task=(AliAnalysisTask*)next())) {
327eaf46 1283 istop = kTRUE;
1284 iszombie = kFALSE;
d3106602 1285 Int_t ninputs = task->GetNinputs();
d3106602 1286 for (i=0; i<ninputs; i++) {
1287 cont = task->GetInputSlot(i)->GetContainer();
1288 if (!cont) {
327eaf46 1289 if (!iszombie) {
d3106602 1290 task->SetZombie();
1291 fZombies->Add(task);
1292 nzombies++;
327eaf46 1293 iszombie = kTRUE;
d3106602 1294 }
c52c2132 1295 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1296 i, task->GetName());
d3106602 1297 }
327eaf46 1298 if (iszombie) continue;
d3106602 1299 // Check if cont is an input container
327eaf46 1300 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 1301 // Connect to parent task
1302 }
327eaf46 1303 if (istop) {
d3106602 1304 ntop++;
1305 fTopTasks->Add(task);
1306 }
1307 }
1308 if (!ntop) {
c52c2132 1309 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 1310 return kFALSE;
1311 }
1312 // Check now if there are orphan tasks
1313 for (i=0; i<ntop; i++) {
1314 task = (AliAnalysisTask*)fTopTasks->At(i);
1315 task->SetUsed();
1316 }
1317 Int_t norphans = 0;
1318 next.Reset();
1319 while ((task=(AliAnalysisTask*)next())) {
1320 if (!task->IsUsed()) {
1321 norphans++;
c52c2132 1322 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 1323 }
1324 }
1325 // Check the task hierarchy (no parent task should depend on data provided
1326 // by a daughter task)
1327 for (i=0; i<ntop; i++) {
1328 task = (AliAnalysisTask*)fTopTasks->At(i);
1329 if (task->CheckCircularDeps()) {
c52c2132 1330 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 1331 PrintStatus("dep");
1332 return kFALSE;
1333 }
1334 }
b1310ef5 1335 // Check that all containers feeding post-event loop tasks are in the outputs list
1336 TIter nextcont(fContainers); // loop over all containers
1337 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1338 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1339 if (cont->HasConsumers()) {
1340 // Check if one of the consumers is post event loop
1341 TIter nextconsumer(cont->GetConsumers());
1342 while ((task=(AliAnalysisTask*)nextconsumer())) {
1343 if (task->IsPostEventLoop()) {
1344 fOutputs->Add(cont);
1345 break;
1346 }
1347 }
1348 }
1349 }
1350 }
8d7d3b59 1351 // Check if all special output containers have a file name provided
1352 TIter nextout(fOutputs);
1353 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1354 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1355 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1356 return kFALSE;
1357 }
7acc5b9d 1358 }
1359 // Initialize requested branch list if needed
1360 if (!fAutoBranchHandling) {
1361 next.Reset();
1362 while ((task=(AliAnalysisTask*)next())) {
1363 if (!task->HasBranches()) {
1364 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches.\nUse: fBranchNames = \"ESD:br1,br2,...,brN AOD:bra1,bra2,...,braM\"",
1365 task->GetName(), task->ClassName());
1366 return kFALSE;
1367 }
1368 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1369 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1370 return kFALSE;
1371 }
1372 TString taskbranches;
1373 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1374 if (taskbranches.IsNull()) {
1375 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1376 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1377 return kFALSE;
1378 }
1379 AddBranches(taskbranches);
1380 }
1381 }
327eaf46 1382 fInitOK = kTRUE;
d3106602 1383 return kTRUE;
1384}
1385
7acc5b9d 1386//______________________________________________________________________________
1387void AliAnalysisManager::AddBranches(const char *branches)
1388{
1389// Add branches to the existing fRequestedBranches.
1390 TString br(branches);
1391 TObjArray *arr = br.Tokenize(",");
1392 TIter next(arr);
1393 TObject *obj;
1394 while ((obj=next())) {
1395 if (!fRequestedBranches.Contains(obj->GetName())) {
1396 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1397 fRequestedBranches += obj->GetName();
1398 }
1399 }
1400 if (arr) delete arr;
1401}
1402
1403//______________________________________________________________________________
1404void AliAnalysisManager::CheckBranches(Bool_t load)
1405{
1406// The method checks the input branches to be loaded during the analysis.
1407 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1408 TObjArray *arr = fRequestedBranches.Tokenize(",");
1409 TIter next(arr);
1410 TObject *obj;
1411 while ((obj=next())) {
1412 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1413 if (!br) {
1414 br = fTree->GetBranch(obj->GetName());
1415 if (!br) {
1416 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1417 continue;
1418 }
1419 }
1420 fTable.Add(br);
1421 if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry());
1422 }
1423}
1424
d3106602 1425//______________________________________________________________________________
1426void AliAnalysisManager::PrintStatus(Option_t *option) const
1427{
1428// Print task hierarchy.
8c0ab8e8 1429 if (!fInitOK) {
1430 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1431 return;
1432 }
1433 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1434 if (getsysInfo)
1435 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1436 TIter next(fTopTasks);
1437 AliAnalysisTask *task;
1438 while ((task=(AliAnalysisTask*)next()))
1439 task->PrintTask(option);
7acc5b9d 1440 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1441 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
d3106602 1442}
1443
1444//______________________________________________________________________________
1445void AliAnalysisManager::ResetAnalysis()
1446{
1447// Reset all execution flags and clean containers.
1448 CleanContainers();
1449}
1450
27734f0e 1451//______________________________________________________________________________
1452Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1453{
1454// Start analysis having a grid handler.
1455 if (!fGridHandler) {
1456 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1457 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1458 return -1;
1459 }
1460 TTree *tree = NULL;
1461 return StartAnalysis(type, tree, nentries, firstentry);
1462}
1463
c52c2132 1464//______________________________________________________________________________
61505f8b 1465Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1466{
aee5ee44 1467// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1468// MIX. Process nentries starting from firstentry
bf574918 1469 Long64_t retv = 0;
57756ec5 1470 // Backup current directory and make sure gDirectory points to gROOT
1471 TDirectory *cdir = gDirectory;
1472 gROOT->cd();
c52c2132 1473 if (!fInitOK) {
1474 Error("StartAnalysis","Analysis manager was not initialized !");
57756ec5 1475 cdir->cd();
1f87e9fb 1476 return -1;
c52c2132 1477 }
cd463514 1478 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
8e1f0465 1479 fIsRemote = kFALSE;
c52c2132 1480 TString anaType = type;
1481 anaType.ToLower();
1482 fMode = kLocalAnalysis;
c57f56b7 1483 Bool_t runlocalinit = kTRUE;
90a4b3ee 1484 if (anaType.Contains("file")) {
1485 runlocalinit = kFALSE;
8e1f0465 1486 fIsRemote = kTRUE;
90a4b3ee 1487 }
4ab472d4 1488 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1489 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1490 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1491
c52c2132 1492 if (fMode == kGridAnalysis) {
8e1f0465 1493 fIsRemote = kTRUE;
f866cba5 1494 if (!anaType.Contains("terminate")) {
1495 if (!fGridHandler) {
1496 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1497 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
57756ec5 1498 cdir->cd();
f866cba5 1499 return -1;
1500 }
1501 // Write analysis manager in the analysis file
1502 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1503 // run local task configuration
1504 TIter nextTask(fTasks);
1505 AliAnalysisTask *task;
1506 while ((task=(AliAnalysisTask*)nextTask())) {
1507 task->LocalInit();
57756ec5 1508 gROOT->cd();
f866cba5 1509 }
1510 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1511 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
57756ec5 1512 cdir->cd();
f866cba5 1513 return -1;
1514 }
c57f56b7 1515
f866cba5 1516 // Terminate grid analysis
57756ec5 1517 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1518 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
f866cba5 1519 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1520 if (!fGridHandler->MergeOutputs()) {
1521 // Return if outputs could not be merged or if it alien handler
1522 // was configured for offline mode or local testing.
57756ec5 1523 cdir->cd();
f866cba5 1524 return 0;
1525 }
1526 }
1527 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
c57f56b7 1528 ImportWrappers(NULL);
1529 Terminate();
57756ec5 1530 cdir->cd();
1f87e9fb 1531 return 0;
981f2614 1532 }
ab5d25d8 1533 TString line;
efd53803 1534 SetEventLoop(kFALSE);
8d7d3b59 1535 // Enable event loop mode if a tree was provided
27734f0e 1536 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1537
8c0ab8e8 1538 TChain *chain = 0;
1539 TString ttype = "TTree";
4ab472d4 1540 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1541 chain = (TChain*)tree;
6b742510 1542 if (!chain || !chain->GetListOfFiles()->First()) {
1543 Error("StartAnalysis", "Cannot process null or empty chain...");
57756ec5 1544 cdir->cd();
1f87e9fb 1545 return -1;
6b742510 1546 }
8c0ab8e8 1547 ttype = "TChain";
1548 }
9b33830a 1549
096b5a2e 1550 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1551 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
aee5ee44 1552 // Initialize locally all tasks (happens for all modes)
9b33830a 1553 TIter next(fTasks);
1554 AliAnalysisTask *task;
c57f56b7 1555 if (runlocalinit) {
1556 while ((task=(AliAnalysisTask*)next())) {
1557 task->LocalInit();
57756ec5 1558 gROOT->cd();
c57f56b7 1559 }
096b5a2e 1560 if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
c57f56b7 1561 }
efd53803 1562
c52c2132 1563 switch (fMode) {
1564 case kLocalAnalysis:
27734f0e 1565 if (!tree && !fGridHandler) {
03a5cc9f 1566 TIter nextT(fTasks);
981f2614 1567 // Call CreateOutputObjects for all tasks
096b5a2e 1568 Int_t itask = 0;
979e448a 1569 Bool_t dirStatus = TH1::AddDirectoryStatus();
03a5cc9f 1570 while ((task=(AliAnalysisTask*)nextT())) {
979e448a 1571 TH1::AddDirectory(kFALSE);
c5a87c56 1572 task->CreateOutputObjects();
096b5a2e 1573 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
57756ec5 1574 gROOT->cd();
096b5a2e 1575 itask++;
c5a87c56 1576 }
979e448a 1577 TH1::AddDirectory(dirStatus);
06a59280 1578 if (IsExternalLoop()) {
1579 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1580 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1f87e9fb 1581 return 0;
57756ec5 1582 }
c52c2132 1583 ExecAnalysis();
981f2614 1584 Terminate();
1f87e9fb 1585 return 0;
c52c2132 1586 }
27734f0e 1587 fSelector = new AliAnalysisSelector(this);
1588 // Check if a plugin handler is used
1589 if (fGridHandler) {
1590 // Get the chain from the plugin
1591 TString dataType = "esdTree";
1592 if (fInputEventHandler) {
1593 dataType = fInputEventHandler->GetDataType();
1594 dataType.ToLower();
1595 dataType += "Tree";
1596 }
1597 chain = fGridHandler->GetChainForTestMode(dataType);
1598 if (!chain) {
1599 Error("StartAnalysis", "No chain for test mode. Aborting.");
1600 return -1;
1601 }
1602 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1603 retv = chain->Process(fSelector, "", nentries, firstentry);
1604 break;
1605 }
c52c2132 1606 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1607 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
bf574918 1608 retv = tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1609 break;
1610 case kProofAnalysis:
8e1f0465 1611 fIsRemote = kTRUE;
3bdcb562 1612 // Check if the plugin is used
1613 if (fGridHandler) {
1614 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1615 }
c52c2132 1616 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1617 Error("StartAnalysis", "No PROOF!!! Exiting.");
57756ec5 1618 cdir->cd();
1f87e9fb 1619 return -1;
c52c2132 1620 }
ab5d25d8 1621 line = Form("gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
c52c2132 1622 gROOT->ProcessLine(line);
1623 if (chain) {
1624 chain->SetProof();
1625 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
bf574918 1626 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1627 } else {
61505f8b 1628 Error("StartAnalysis", "No chain!!! Exiting.");
57756ec5 1629 cdir->cd();
1f87e9fb 1630 return -1;
c52c2132 1631 }
1632 break;
1633 case kGridAnalysis:
27734f0e 1634 fIsRemote = kTRUE;
1635 if (!anaType.Contains("terminate")) {
1636 if (!fGridHandler) {
1637 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1638 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1639 cdir->cd();
1640 return -1;
1641 }
1642 // Write analysis manager in the analysis file
1643 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1644 // Start the analysis via the handler
1645 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1646 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1647 cdir->cd();
1648 return -1;
1649 }
1650
1651 // Terminate grid analysis
1652 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1653 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1654 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1655 if (!fGridHandler->MergeOutputs()) {
1656 // Return if outputs could not be merged or if it alien handler
1657 // was configured for offline mode or local testing.
1658 cdir->cd();
1659 return 0;
1660 }
1661 }
1662 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1663 ImportWrappers(NULL);
1664 Terminate();
1665 cdir->cd();
1666 return 0;
aee5ee44 1667 case kMixingAnalysis:
1668 // Run event mixing analysis
1669 if (!fEventPool) {
1670 Error("StartAnalysis", "Cannot run event mixing without event pool");
57756ec5 1671 cdir->cd();
1f87e9fb 1672 return -1;
aee5ee44 1673 }
1674 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1675 fSelector = new AliAnalysisSelector(this);
aee5ee44 1676 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1677 next.Reset();
aee5ee44 1678 // Call NotifyBinChange for all tasks
1679 while ((task=(AliAnalysisTask*)next()))
1680 if (!task->IsPostEventLoop()) task->NotifyBinChange();
bf574918 1681 retv = chain->Process(fSelector);
1682 if (retv < 0) {
1683 Error("StartAnalysis", "Mixing analysis failed");
57756ec5 1684 cdir->cd();
bf574918 1685 return retv;
1686 }
aee5ee44 1687 }
1688 PackOutput(fSelector->GetOutputList());
1689 Terminate();
1f87e9fb 1690 }
57756ec5 1691 cdir->cd();
bf574918 1692 return retv;
c52c2132 1693}
1694
d86ed856 1695//______________________________________________________________________________
1f87e9fb 1696Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
d86ed856 1697{
1698// Start analysis for this manager on a given dataset. Analysis task can be:
1699// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1700 if (!fInitOK) {
1701 Error("StartAnalysis","Analysis manager was not initialized !");
1f87e9fb 1702 return -1;
d86ed856 1703 }
8e1f0465 1704 fIsRemote = kTRUE;
cd463514 1705 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
d86ed856 1706 TString anaType = type;
1707 anaType.ToLower();
1708 if (!anaType.Contains("proof")) {
d140f7fb 1709 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1f87e9fb 1710 return -1;
d86ed856 1711 }
1712 fMode = kProofAnalysis;
ab5d25d8 1713 TString line;
d86ed856 1714 SetEventLoop(kTRUE);
1715 // Set the dataset flag
1716 TObject::SetBit(kUseDataSet);
1717 fTree = 0;
3bdcb562 1718 TChain *chain = 0;
1719 if (fGridHandler) {
1720 // Start proof analysis using the grid handler
1721 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1722 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1723 return -1;
1724 }
1725 // Check if the plugin is in test mode
1726 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
830acc4c 1727 dataset = "test_collection";
3bdcb562 1728 } else {
1729 dataset = fGridHandler->GetProofDataSet();
1730 }
1731 }
1732
1733 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1734 Error("StartAnalysis", "No PROOF!!! Exiting.");
1735 return -1;
1736 }
d86ed856 1737
1738 // Initialize locally all tasks
1739 TIter next(fTasks);
1740 AliAnalysisTask *task;
1741 while ((task=(AliAnalysisTask*)next())) {
1742 task->LocalInit();
1743 }
1744
ab5d25d8 1745 line = Form("gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
d86ed856 1746 gROOT->ProcessLine(line);
3bdcb562 1747 Long_t retv;
1748 if (chain) {
1749// chain->SetProof();
1750 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON TEST CHAIN " << chain->GetName() << endl;
1751 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1752 } else {
1753 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1754 dataset, nentries, firstentry);
1755 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1756 retv = (Long_t)gROOT->ProcessLine(line);
1757 }
bf574918 1758 return retv;
d86ed856 1759}
1760
d3106602 1761//______________________________________________________________________________
84fcd93f 1762TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1763{
1764// Opens according the option the file specified by cont->GetFileName() and changes
1765// current directory to cont->GetFolderName(). If the file was already opened, it
1766// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1767// be optionally ignored.
1768 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1769 TString filename = cont->GetFileName();
1770 TFile *f = NULL;
1771 if (filename.IsNull()) {
1772 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1773 return NULL;
1774 }
1775 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1776 && !ignoreProof)
1777 f = mgr->OpenProofFile(cont,option);
1778 else {
1779 // Check first if the file is already opened
0f1b50f3 1780 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 1781 if (f) {
1782 // Check if option "UPDATE" was preserved
1783 TString opt(option);
1784 opt.ToUpper();
1785 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1786 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1787 } else {
0f1b50f3 1788 f = TFile::Open(filename, option);
84fcd93f 1789 }
1790 }
1791 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1792 cont->SetFile(f);
1793 // Cd to file
1794 f->cd();
1795 // Check for a folder request
1796 TString dir = cont->GetFolderName();
1797 if (!dir.IsNull()) {
1798 if (!f->GetDirectory(dir)) f->mkdir(dir);
1799 f->cd(dir);
1800 }
1801 return f;
1802 }
1803 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1804 cont->SetFile(NULL);
1805 return NULL;
1806}
1807
1808//______________________________________________________________________________
039e671e 1809TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
8d7d3b59 1810{
1811// Opens a special output file used in PROOF.
84fcd93f 1812 TString line;
1813 TString filename = cont->GetFileName();
23c9468b 1814 if (cont == fCommonOutput) {
039e671e 1815 if (fOutputEventHandler) {
1816 if (strlen(extaod)) filename = extaod;
1817 filename = fOutputEventHandler->GetOutputFileName();
1818 }
61505f8b 1819 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 1820 }
84fcd93f 1821 TFile *f = NULL;
1822 if (fMode!=kProofAnalysis || !fSelector) {
1823 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1824 return NULL;
1825 }
1826 if (fSpecialOutputLocation.Length()) {
1827 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1828 if (f) {
1829 // Check if option "UPDATE" was preserved
1830 TString opt(option);
1831 opt.ToUpper();
23c9468b 1832 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1833 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1834 } else {
1835 f = new TFile(filename, option);
1836 }
1837 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1838 cont->SetFile(f);
1839 // Cd to file
1840 f->cd();
1841 // Check for a folder request
1842 TString dir = cont->GetFolderName();
1843 if (dir.Length()) {
1844 if (!f->GetDirectory(dir)) f->mkdir(dir);
1845 f->cd(dir);
1846 }
f5e61abd 1847 return f;
84fcd93f 1848 }
1849 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1850 cont->SetFile(NULL);
1851 return NULL;
1852 }
1853 // Check if there is already a proof output file in the output list
1854 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1855 if (pof) {
1856 // Get the actual file
b3e07543 1857 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
84fcd93f 1858 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 1859 if (fDebug>1) {
1860 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1861 }
84fcd93f 1862 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
ab5d25d8 1863 if (!f) {
1864 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1865 return NULL;
1866 }
84fcd93f 1867 // Check if option "UPDATE" was preserved
1868 TString opt(option);
1869 opt.ToUpper();
1870 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1871 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1872 } else {
90a4b3ee 1873 if (cont->IsRegisterDataset()) {
61505f8b 1874 TString dsetName = filename;
1875 dsetName.ReplaceAll(".root", cont->GetTitle());
1876 dsetName.ReplaceAll(":","_");
1877 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1878 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 1879 } else {
1880 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1881 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1882 }
84fcd93f 1883 if (fDebug > 1) printf("=== %s\n", line.Data());
1884 gROOT->ProcessLine(line);
1885 line = Form("pf->OpenFile(\"%s\");", option);
1886 gROOT->ProcessLine(line);
1887 f = gFile;
1888 if (fDebug > 1) {
8d7d3b59 1889 gROOT->ProcessLine("pf->Print()");
84fcd93f 1890 printf(" == proof file name: %s", f->GetName());
1891 }
1892 // Add to proof output list
b3e07543 1893 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
90a4b3ee 1894 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 1895 gROOT->ProcessLine(line);
1896 }
1897 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1898 cont->SetFile(f);
1899 // Cd to file
1900 f->cd();
1901 // Check for a folder request
1902 TString dir = cont->GetFolderName();
1903 if (!dir.IsNull()) {
1904 if (!f->GetDirectory(dir)) f->mkdir(dir);
1905 f->cd(dir);
1906 }
1907 return f;
1908 }
1909 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1910 cont->SetFile(NULL);
1911 return NULL;
8d7d3b59 1912}
1913
1914//______________________________________________________________________________
d3106602 1915void AliAnalysisManager::ExecAnalysis(Option_t *option)
1916{
1917// Execute analysis.
cd463514 1918 static Long64_t nentries = 0;
1f04b637 1919 static TTree *lastTree = 0;
cd463514 1920 static TStopwatch *timer = new TStopwatch();
e9247450 1921 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
cd463514 1922 else {
1f04b637 1923 if (fTree && (fTree != lastTree)) {
1924 nentries += fTree->GetEntries();
1925 lastTree = fTree;
1926 }
e9247450 1927 if (!fNcalls) timer->Start();
1928 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, nentries, timer, kFALSE);
cd463514 1929 }
57756ec5 1930 gROOT->cd();
cd463514 1931 TDirectory *cdir = gDirectory;
8c0ab8e8 1932 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
e9247450 1933 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
327eaf46 1934 if (!fInitOK) {
57756ec5 1935 Error("ExecAnalysis", "Analysis manager was not initialized !");
1936 cdir->cd();
327eaf46 1937 return;
57756ec5 1938 }
e9247450 1939 fNcalls++;
d3106602 1940 AliAnalysisTask *task;
327eaf46 1941 // Check if the top tree is active.
1942 if (fTree) {
e9247450 1943 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1944 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
327eaf46 1945 TIter next(fTasks);
1946 // De-activate all tasks
1947 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1948 AliAnalysisDataContainer *cont = fCommonInput;
1949 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1950 if (!cont) {
c52c2132 1951 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
57756ec5 1952 cdir->cd();
327eaf46 1953 return;
1954 }
1955 cont->SetData(fTree); // This will notify all consumers
57756ec5 1956 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 1957//
c3701689 1958// Call BeginEvent() for optional input/output and MC services
ed97dc98 1959 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1960 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1961 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 1962 gROOT->cd();
e9247450 1963 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1964 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
6bb2b24f 1965//
1966// Execute the tasks
276941c8 1967// TIter next1(cont->GetConsumers());
1968 TIter next1(fTopTasks);
096b5a2e 1969 Int_t itask = 0;
327eaf46 1970 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1971 if (fDebug >1) {
1972 cout << " Executing task " << task->GetName() << endl;
096b5a2e 1973 }
327eaf46 1974 task->ExecuteTask(option);
57756ec5 1975 gROOT->cd();
e9247450 1976 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1977 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
096b5a2e 1978 itask++;
327eaf46 1979 }
6bb2b24f 1980//
1981// Call FinishEvent() for optional output and MC services
6073f8c9 1982 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1983 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1984 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1985 // Gather system information if requested
e9247450 1986 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1987 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
57756ec5 1988 cdir->cd();
327eaf46 1989 return;
1990 }
1991 // The event loop is not controlled by TSelector
6bb2b24f 1992//
c3701689 1993// Call BeginEvent() for optional input/output and MC services
ed97dc98 1994 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1995 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1996 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
57756ec5 1997 gROOT->cd();
e9247450 1998 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1999 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
327eaf46 2000 TIter next2(fTopTasks);
2001 while ((task=(AliAnalysisTask*)next2())) {
2002 task->SetActive(kTRUE);
c52c2132 2003 if (fDebug > 1) {
2004 cout << " Executing task " << task->GetName() << endl;
2005 }
d3106602 2006 task->ExecuteTask(option);
57756ec5 2007 gROOT->cd();
327eaf46 2008 }
6bb2b24f 2009//
2010// Call FinishEvent() for optional output and MC services
6073f8c9 2011 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2012 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 2013 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
e9247450 2014 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2015 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
57756ec5 2016 cdir->cd();
d3106602 2017}
2018
2019//______________________________________________________________________________
61505f8b 2020void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 2021{
2022// Set the input event handler and create a container for it.
2023 fInputEventHandler = handler;
d958c3ea 2024 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ff92d2b1 2025// Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 2026}
2027
2028//______________________________________________________________________________
61505f8b 2029void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 2030{
2031// Set the input event handler and create a container for it.
2032 fOutputEventHandler = handler;
d958c3ea 2033 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 2034 fCommonOutput->SetSpecialOutput();
ff92d2b1 2035// Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 2036}
c07b9ce2 2037
2038//______________________________________________________________________________
2039void AliAnalysisManager::RegisterExtraFile(const char *fname)
2040{
2041// This method is used externally to register output files which are not
2042// connected to any output container, so that the manager can properly register,
2043// retrieve or merge them when running in distributed mode. The file names are
2044// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 2045 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 2046 if (fExtraFiles.Length()) fExtraFiles += " ";
2047 fExtraFiles += fname;
2048}
2049
2050//______________________________________________________________________________
61505f8b 2051Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 2052{
2053// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 2054 char fullPath[512];
2055 char chUrl[512];
b3e07543 2056 char tmp[1024];
c07b9ce2 2057 TObject *pof = source->FindObject(filename);
2058 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2059 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2060 return kFALSE;
2061 }
b3e07543 2062 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2063 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
61505f8b 2064 TString clientUrl(chUrl);
2065 TString fullPath_str(fullPath);
c07b9ce2 2066 if (clientUrl.Contains("localhost")){
61505f8b 2067 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 2068 TObjString *strobj = ( TObjString *)array->At(1);
2069 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2070 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 2071 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2072 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2073 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 2074 delete arrayPort;
2075 delete array;
2076 }
b3e07543 2077 else if (clientUrl.Contains("__lite__")) {
2078 // Special case for ProofLite environement - get file info and copy.
2079 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2080 fullPath_str = Form("%s/%s", tmp, fullPath);
2081 }
c07b9ce2 2082 if (fDebug > 1)
b3e07543 2083 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
61505f8b 2084 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 2085 if (!gotit)
2086 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2087 return gotit;
2088}
d29168d6 2089
2090//______________________________________________________________________________
2091void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2092{
2093// Fill analysis type in the provided string.
2094 switch (fMode) {
2095 case kLocalAnalysis:
2096 type = "local";
2097 return;
2098 case kProofAnalysis:
2099 type = "proof";
2100 return;
2101 case kGridAnalysis:
2102 type = "grid";
2103 return;
2104 case kMixingAnalysis:
2105 type = "mix";
2106 }
2107}
923e2ca5 2108
2109//______________________________________________________________________________
2110Bool_t AliAnalysisManager::ValidateOutputFiles() const
2111{
2112// Validate all output files.
2113 TIter next(fOutputs);
2114 AliAnalysisDataContainer *output;
2115 TDirectory *cdir = gDirectory;
84fcd93f 2116 TString openedFiles;
923e2ca5 2117 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 2118 if (output->IsRegisterDataset()) continue;
923e2ca5 2119 TString filename = output->GetFileName();
2120 if (filename == "default") {
2121 if (!fOutputEventHandler) continue;
2122 filename = fOutputEventHandler->GetOutputFileName();
b3685485 2123 // Main AOD may not be there
2124 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 2125 }
2126 // Check if the file is closed
84fcd93f 2127 if (openedFiles.Contains(filename)) continue;;
923e2ca5 2128 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2129 if (file) {
2130 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 2131 // Clear file list to release object ownership to user.
160e7161 2132// file->Clear();
923e2ca5 2133 file->Close();
2134 }
2135 file = TFile::Open(filename);
2136 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2137 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2138 cdir->cd();
2139 return kFALSE;
2140 }
2141 file->Close();
84fcd93f 2142 openedFiles += filename;
2143 openedFiles += " ";
923e2ca5 2144 }
2145 cdir->cd();
2146 return kTRUE;
2147}
cd11251e 2148
2149//______________________________________________________________________________
61505f8b 2150void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 2151{
2152// Implements a nice text mode progress bar.
2153 static Long64_t icount = 0;
2154 static TString oname;
2155 static TString nname;
2156 static Long64_t ocurrent = 0;
2157 static Long64_t osize = 0;
2158 static Int_t oseconds = 0;
2159 static TStopwatch *owatch = 0;
2160 static Bool_t oneoftwo = kFALSE;
2161 static Int_t nrefresh = 0;
2162 static Int_t nchecks = 0;
2163 const char symbol[4] = {'=','\\','|','/'};
2164 char progress[11] = " ";
2165 Int_t ichar = icount%4;
2166
2167 if (!refresh) {
2168 nrefresh = 0;
2169 if (!size) return;
2170 owatch = watch;
2171 oname = opname;
2172 ocurrent = TMath::Abs(current);
2173 osize = TMath::Abs(size);
2174 if (ocurrent > osize) ocurrent=osize;
2175 } else {
2176 nrefresh++;
2177 if (!osize) return;
2178 }
2179 icount++;
2180 Double_t time = 0.;
2181 Int_t hours = 0;
2182 Int_t minutes = 0;
2183 Int_t seconds = 0;
2184 if (owatch && !last) {
2185 owatch->Stop();
2186 time = owatch->RealTime();
2187 hours = (Int_t)(time/3600.);
2188 time -= 3600*hours;
2189 minutes = (Int_t)(time/60.);
2190 time -= 60*minutes;
2191 seconds = (Int_t)time;
2192 if (refresh) {
2193 if (oseconds==seconds) {
2194 owatch->Continue();
2195 return;
2196 }
2197 oneoftwo = !oneoftwo;
2198 }
2199 oseconds = seconds;
2200 }
2201 if (refresh && oneoftwo) {
2202 nname = oname;
2203 if (nchecks <= 0) nchecks = nrefresh+1;
2204 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2205 oname = Form(" == %d%% ==", pctdone);
2206 }
2207 Double_t percent = 100.0*ocurrent/osize;
2208 Int_t nchar = Int_t(percent/10);
2209 if (nchar>10) nchar=10;
2210 Int_t i;
2211 for (i=0; i<nchar; i++) progress[i] = '=';
2212 progress[nchar] = symbol[ichar];
2213 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2214 progress[10] = '\0';
2215 oname += " ";
2216 oname.Remove(20);
2217 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2218 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2219 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2220 if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d \r", percent, hours, minutes, seconds);
2221 else fprintf(stderr, "[%6.2f %%]\r", percent);
2222 if (refresh && oneoftwo) oname = nname;
2223 if (owatch) owatch->Continue();
2224 if (last) {
2225 icount = 0;
2226 owatch = 0;
2227 ocurrent = 0;
2228 osize = 0;
2229 oseconds = 0;
2230 oneoftwo = kFALSE;
2231 nrefresh = 0;
2232 fprintf(stderr, "\n");
2233 }
2234}
012e169c 2235
2236//______________________________________________________________________________
2237void AliAnalysisManager::DoLoadBranch(const char *name)
2238{
2239 // Get tree and load branch if needed.
c5734a4b 2240 static Long64_t crtEntry = -100;
012e169c 2241
7acc5b9d 2242 if (fAutoBranchHandling || !fTree)
012e169c 2243 return;
2244
2245 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2246 if (!br) {
2247 br = fTree->GetBranch(name);
2248 if (!br) {
979e448a 2249 Error("DoLoadBranch", "Could not find branch %s",name);
012e169c 2250 return;
2251 }
2252 fTable.Add(br);
2253 }
c5734a4b 2254 if (br->GetReadEntry()==fCurrentEntry) return;
f5cbe261 2255 Int_t ret = br->GetEntry(GetCurrentEntry());
2256 if (ret<0) {
2257 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
c5734a4b 2258 if (crtEntry != fCurrentEntry) {
2259 CountEvent(1,0,1,0);
2260 crtEntry = fCurrentEntry;
2261 }
2262 } else {
2263 if (crtEntry != fCurrentEntry) {
2264 CountEvent(1,1,0,0);
2265 crtEntry = fCurrentEntry;
2266 }
f5cbe261 2267 }
012e169c 2268}
e9247450 2269
f5cbe261 2270//______________________________________________________________________________
c3732d79 2271void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
f5cbe261 2272{
2273// Add the statistics task to the manager.
2274 if (fStatistics) {
2275 Info("AddStatisticsTask", "Already added");
2276 return;
c3732d79 2277 }
2278 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2279 gROOT->ProcessLine(line);
f5cbe261 2280}
2281
2282//______________________________________________________________________________
2283void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2284{
2285// Bookkeep current event;
2286 if (!fStatistics) return;
2287 fStatistics->AddInput(ninput);
2288 fStatistics->AddProcessed(nprocessed);
2289 fStatistics->AddFailed(nfailed);
2290 fStatistics->AddAccepted(naccepted);
2291}
2292
e9247450 2293//______________________________________________________________________________
2294void AliAnalysisManager::AddStatisticsMsg(const char *line)
2295{
2296// Add a line in the statistics message. If available, the statistics message is written
2297// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2298// on the client.
2299 if (!strlen(line)) return;
2300 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2301 fStatisticsMsg += line;
2302}
2303
2304//______________________________________________________________________________
2305void AliAnalysisManager::WriteStatisticsMsg(Int_t nevents)
2306{
23a74fb4 2307// Write the statistics message in a file named <nevents.stat>.
2308// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
c3732d79 2309 static Bool_t done = kFALSE;
2310 if (done) return;
2311 done = kTRUE;
e9247450 2312 ofstream out;
23a74fb4 2313 if (fStatistics) {
2314 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2315 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2316 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
c3732d79 2317 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
23a74fb4 2318 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2319 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2320 fStatistics->GetNaccepted()), ios::out);
2321 out << fStatisticsMsg << endl;
2322 } else {
2323 if (!nevents) return;
2324 out.open(Form("%09d.stat", nevents), ios::out);
2325 if (!fStatisticsMsg.IsNull()) out << fStatisticsMsg << endl;
2326 }
e9247450 2327 out.close();
2328}