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