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