Check if a macro was already loaded using AliAnalysisManager::IsMacroLoaded()
[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
d3106602 68//______________________________________________________________________________
c52c2132 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
d3106602 283//______________________________________________________________________________
43072535 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
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
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
1569//______________________________________________________________________________
7acc5b9d 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
1611//______________________________________________________________________________
4747b4a7 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
1635//______________________________________________________________________________
d3106602 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
1675//______________________________________________________________________________
d512d8e2 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
1691//______________________________________________________________________________
27734f0e 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
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
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;
d88e4159 1950 TString proofProcessOpt;
d86ed856 1951 SetEventLoop(kTRUE);
1952 // Set the dataset flag
1953 TObject::SetBit(kUseDataSet);
1954 fTree = 0;
3bdcb562 1955 if (fGridHandler) {
1956 // Start proof analysis using the grid handler
1957 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1958 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1959 return -1;
1960 }
1961 // Check if the plugin is in test mode
1962 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
830acc4c 1963 dataset = "test_collection";
3bdcb562 1964 } else {
1965 dataset = fGridHandler->GetProofDataSet();
1966 }
d88e4159 1967
1968 proofProcessOpt = fGridHandler->GetProofProcessOpt();
3bdcb562 1969 }
1970
1971 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1972 Error("StartAnalysis", "No PROOF!!! Exiting.");
1973 return -1;
1974 }
d86ed856 1975
1976 // Initialize locally all tasks
d512d8e2 1977 RunLocalInit();
1978
ea091b97 1979 line = Form("gProof->AddInput((TObject*)%p);", this);
d86ed856 1980 gROOT->ProcessLine(line);
3bdcb562 1981 Long_t retv;
d88e4159 1982 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
1983 dataset,proofProcessOpt.Data(), nentries, firstentry);
ea091b97 1984 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1985 retv = (Long_t)gROOT->ProcessLine(line);
bf574918 1986 return retv;
d86ed856 1987}
1988
1989//______________________________________________________________________________
84fcd93f 1990TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1991{
1992// Opens according the option the file specified by cont->GetFileName() and changes
1993// current directory to cont->GetFolderName(). If the file was already opened, it
1994// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1995// be optionally ignored.
1996 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1997 TString filename = cont->GetFileName();
1998 TFile *f = NULL;
1999 if (filename.IsNull()) {
2000 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2001 return NULL;
2002 }
2003 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2004 && !ignoreProof)
2005 f = mgr->OpenProofFile(cont,option);
2006 else {
2007 // Check first if the file is already opened
0f1b50f3 2008 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 2009 if (f) {
2010 // Check if option "UPDATE" was preserved
2011 TString opt(option);
2012 opt.ToUpper();
2013 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 2014 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 2015 } else {
0f1b50f3 2016 f = TFile::Open(filename, option);
84fcd93f 2017 }
2018 }
2019 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2020 cont->SetFile(f);
2021 // Cd to file
2022 f->cd();
2023 // Check for a folder request
2024 TString dir = cont->GetFolderName();
2025 if (!dir.IsNull()) {
2026 if (!f->GetDirectory(dir)) f->mkdir(dir);
2027 f->cd(dir);
2028 }
2029 return f;
2030 }
2031 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2032 cont->SetFile(NULL);
2033 return NULL;
2034}
2035
2036//______________________________________________________________________________
039e671e 2037TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
8d7d3b59 2038{
2039// Opens a special output file used in PROOF.
84fcd93f 2040 TString line;
2041 TString filename = cont->GetFileName();
23c9468b 2042 if (cont == fCommonOutput) {
039e671e 2043 if (fOutputEventHandler) {
2044 if (strlen(extaod)) filename = extaod;
2045 filename = fOutputEventHandler->GetOutputFileName();
2046 }
61505f8b 2047 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 2048 }
84fcd93f 2049 TFile *f = NULL;
2050 if (fMode!=kProofAnalysis || !fSelector) {
2051 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2052 return NULL;
2053 }
2054 if (fSpecialOutputLocation.Length()) {
2055 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2056 if (f) {
2057 // Check if option "UPDATE" was preserved
2058 TString opt(option);
2059 opt.ToUpper();
23c9468b 2060 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 2061 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 2062 } else {
2063 f = new TFile(filename, option);
2064 }
2065 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2066 cont->SetFile(f);
2067 // Cd to file
2068 f->cd();
2069 // Check for a folder request
2070 TString dir = cont->GetFolderName();
2071 if (dir.Length()) {
2072 if (!f->GetDirectory(dir)) f->mkdir(dir);
2073 f->cd(dir);
2074 }
f5e61abd 2075 return f;
84fcd93f 2076 }
2077 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2078 cont->SetFile(NULL);
2079 return NULL;
2080 }
2081 // Check if there is already a proof output file in the output list
2082 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2083 if (pof) {
2084 // Get the actual file
b3e07543 2085 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
84fcd93f 2086 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 2087 if (fDebug>1) {
2088 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2089 }
84fcd93f 2090 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
ab5d25d8 2091 if (!f) {
2092 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2093 return NULL;
2094 }
84fcd93f 2095 // Check if option "UPDATE" was preserved
2096 TString opt(option);
2097 opt.ToUpper();
2098 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2099 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2100 } else {
90a4b3ee 2101 if (cont->IsRegisterDataset()) {
61505f8b 2102 TString dsetName = filename;
2103 dsetName.ReplaceAll(".root", cont->GetTitle());
2104 dsetName.ReplaceAll(":","_");
2105 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2106 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 2107 } else {
2108 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2109 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2110 }
84fcd93f 2111 if (fDebug > 1) printf("=== %s\n", line.Data());
2112 gROOT->ProcessLine(line);
2113 line = Form("pf->OpenFile(\"%s\");", option);
2114 gROOT->ProcessLine(line);
2115 f = gFile;
2116 if (fDebug > 1) {
8d7d3b59 2117 gROOT->ProcessLine("pf->Print()");
84fcd93f 2118 printf(" == proof file name: %s", f->GetName());
2119 }
2120 // Add to proof output list
b3e07543 2121 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
90a4b3ee 2122 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 2123 gROOT->ProcessLine(line);
2124 }
2125 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2126 cont->SetFile(f);
2127 // Cd to file
2128 f->cd();
2129 // Check for a folder request
2130 TString dir = cont->GetFolderName();
2131 if (!dir.IsNull()) {
2132 if (!f->GetDirectory(dir)) f->mkdir(dir);
2133 f->cd(dir);
2134 }
2135 return f;
2136 }
2137 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2138 cont->SetFile(NULL);
2139 return NULL;
8d7d3b59 2140}
2141
2142//______________________________________________________________________________
d3106602 2143void AliAnalysisManager::ExecAnalysis(Option_t *option)
2144{
2145// Execute analysis.
cd463514 2146 static Long64_t nentries = 0;
1f04b637 2147 static TTree *lastTree = 0;
cd463514 2148 static TStopwatch *timer = new TStopwatch();
20b7268e 2149 // Only the first call to Process will trigger a true Notify. Other Notify
2150 // coming before is ignored.
2151 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2152 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2153 Notify();
2154 }
e9247450 2155 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
cd463514 2156 else {
1f04b637 2157 if (fTree && (fTree != lastTree)) {
2158 nentries += fTree->GetEntries();
2159 lastTree = fTree;
2160 }
e9247450 2161 if (!fNcalls) timer->Start();
f03a8355 2162 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
cd463514 2163 }
ec5acdce 2164 fIOTimer->Start(kTRUE);
57756ec5 2165 gROOT->cd();
cd463514 2166 TDirectory *cdir = gDirectory;
8c0ab8e8 2167 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
e9247450 2168 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
327eaf46 2169 if (!fInitOK) {
57756ec5 2170 Error("ExecAnalysis", "Analysis manager was not initialized !");
2f0e656b 2171 if (cdir) cdir->cd();
327eaf46 2172 return;
57756ec5 2173 }
e9247450 2174 fNcalls++;
d3106602 2175 AliAnalysisTask *task;
327eaf46 2176 // Check if the top tree is active.
2177 if (fTree) {
e9247450 2178 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2179 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
327eaf46 2180 TIter next(fTasks);
2181 // De-activate all tasks
2182 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 2183 AliAnalysisDataContainer *cont = fCommonInput;
2184 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 2185 if (!cont) {
c52c2132 2186 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2f0e656b 2187 if (cdir) cdir->cd();
327eaf46 2188 return;
2189 }
2190 cont->SetData(fTree); // This will notify all consumers
57756ec5 2191 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 2192//
c3701689 2193// Call BeginEvent() for optional input/output and MC services
ed97dc98 2194 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2195 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2196 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 2197 gROOT->cd();
e9247450 2198 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2199 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
6bb2b24f 2200//
2201// Execute the tasks
276941c8 2202// TIter next1(cont->GetConsumers());
ec5acdce 2203 fIOTimer->Stop();
2204 fIOTime += fIOTimer->RealTime();
2205 fCPUTimer->Start(kTRUE);
276941c8 2206 TIter next1(fTopTasks);
096b5a2e 2207 Int_t itask = 0;
327eaf46 2208 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 2209 if (fDebug >1) {
2210 cout << " Executing task " << task->GetName() << endl;
096b5a2e 2211 }
327eaf46 2212 task->ExecuteTask(option);
57756ec5 2213 gROOT->cd();
e9247450 2214 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2215 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
096b5a2e 2216 itask++;
327eaf46 2217 }
ec5acdce 2218 fCPUTimer->Stop();
2219 fCPUTime += fCPUTimer->RealTime();
2220 fIOTimer->Start(kTRUE);
6bb2b24f 2221//
2222// Call FinishEvent() for optional output and MC services
6073f8c9 2223 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 2224 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2225 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 2226 // Gather system information if requested
e9247450 2227 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2228 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2f0e656b 2229 if (cdir) cdir->cd();
ec5acdce 2230 fIOTimer->Stop();
2231 fIOTime += fIOTimer->RealTime();
327eaf46 2232 return;
2233 }
2234 // The event loop is not controlled by TSelector
6bb2b24f 2235//
c3701689 2236// Call BeginEvent() for optional input/output and MC services
ec5acdce 2237 fIOTimer->Start(kTRUE);
ed97dc98 2238 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2239 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2240 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
ec5acdce 2241 fIOTimer->Stop();
2242 fIOTime += fIOTimer->RealTime();
57756ec5 2243 gROOT->cd();
e9247450 2244 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2245 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
ec5acdce 2246 fCPUTimer->Start(kTRUE);
327eaf46 2247 TIter next2(fTopTasks);
2248 while ((task=(AliAnalysisTask*)next2())) {
2249 task->SetActive(kTRUE);
c52c2132 2250 if (fDebug > 1) {
2251 cout << " Executing task " << task->GetName() << endl;
2252 }
d3106602 2253 task->ExecuteTask(option);
57756ec5 2254 gROOT->cd();
327eaf46 2255 }
ec5acdce 2256 fCPUTimer->Stop();
2257 fCPUTime += fCPUTimer->RealTime();
6bb2b24f 2258//
2259// Call FinishEvent() for optional output and MC services
ec5acdce 2260 fIOTimer->Start(kTRUE);
6073f8c9 2261 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2262 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 2263 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
e9247450 2264 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2265 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2f0e656b 2266 if (cdir) cdir->cd();
ec5acdce 2267 fIOTimer->Stop();
2268 fIOTime += fIOTimer->RealTime();
d3106602 2269}
2270
2271//______________________________________________________________________________
8ddad121 2272Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2273{
2274// Check if the stdout is connected to a pipe (C.Holm)
2275 Bool_t ispipe = kFALSE;
2276 out.seekp(0, std::ios_base::cur);
2277 if (out.fail()) {
2278 out.clear();
2279 if (errno == ESPIPE) ispipe = kTRUE;
2280 }
2281 return ispipe;
2282}
2283
2284//______________________________________________________________________________
61505f8b 2285void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 2286{
2287// Set the input event handler and create a container for it.
59e0dcd5 2288 Changed();
60a04972 2289 fInputEventHandler = handler;
523aab8b 2290 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
60a04972 2291}
2292
2293//______________________________________________________________________________
61505f8b 2294void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 2295{
2296// Set the input event handler and create a container for it.
59e0dcd5 2297 Changed();
60a04972 2298 fOutputEventHandler = handler;
523aab8b 2299 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 2300 fCommonOutput->SetSpecialOutput();
60a04972 2301}
c07b9ce2 2302
2303//______________________________________________________________________________
f03a8355 2304void AliAnalysisManager::SetDebugLevel(UInt_t level)
2305{
2306// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2307 if (TObject::TestBit(kUseProgressBar)) {
2308 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2309 return;
2310 }
2311 fDebug = level;
2312}
2313
2314//______________________________________________________________________________
2315void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2316{
2317// Enable a text mode progress bar. Resets debug level to 0.
2318 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2319 TObject::SetBit(kUseProgressBar,flag);
2320 fPBUpdateFreq = freq;
2321 fDebug = 0;
2322}
2323
2324//______________________________________________________________________________
c07b9ce2 2325void AliAnalysisManager::RegisterExtraFile(const char *fname)
2326{
2327// This method is used externally to register output files which are not
2328// connected to any output container, so that the manager can properly register,
2329// retrieve or merge them when running in distributed mode. The file names are
2330// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 2331 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 2332 if (fExtraFiles.Length()) fExtraFiles += " ";
2333 fExtraFiles += fname;
2334}
2335
2336//______________________________________________________________________________
61505f8b 2337Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 2338{
2339// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 2340 char fullPath[512];
2341 char chUrl[512];
b3e07543 2342 char tmp[1024];
c07b9ce2 2343 TObject *pof = source->FindObject(filename);
2344 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2345 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2346 return kFALSE;
2347 }
b3e07543 2348 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2349 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
61505f8b 2350 TString clientUrl(chUrl);
2351 TString fullPath_str(fullPath);
c07b9ce2 2352 if (clientUrl.Contains("localhost")){
61505f8b 2353 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 2354 TObjString *strobj = ( TObjString *)array->At(1);
2355 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2356 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 2357 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2358 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2359 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 2360 delete arrayPort;
2361 delete array;
2362 }
b3e07543 2363 else if (clientUrl.Contains("__lite__")) {
2364 // Special case for ProofLite environement - get file info and copy.
2365 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2366 fullPath_str = Form("%s/%s", tmp, fullPath);
2367 }
c07b9ce2 2368 if (fDebug > 1)
b3e07543 2369 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
61505f8b 2370 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 2371 if (!gotit)
2372 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2373 return gotit;
2374}
d29168d6 2375
2376//______________________________________________________________________________
2377void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2378{
2379// Fill analysis type in the provided string.
2380 switch (fMode) {
2381 case kLocalAnalysis:
2382 type = "local";
2383 return;
2384 case kProofAnalysis:
2385 type = "proof";
2386 return;
2387 case kGridAnalysis:
2388 type = "grid";
2389 return;
2390 case kMixingAnalysis:
2391 type = "mix";
2392 }
2393}
923e2ca5 2394
2395//______________________________________________________________________________
2396Bool_t AliAnalysisManager::ValidateOutputFiles() const
2397{
2398// Validate all output files.
2399 TIter next(fOutputs);
2400 AliAnalysisDataContainer *output;
2401 TDirectory *cdir = gDirectory;
84fcd93f 2402 TString openedFiles;
923e2ca5 2403 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 2404 if (output->IsRegisterDataset()) continue;
923e2ca5 2405 TString filename = output->GetFileName();
2406 if (filename == "default") {
2407 if (!fOutputEventHandler) continue;
2408 filename = fOutputEventHandler->GetOutputFileName();
b3685485 2409 // Main AOD may not be there
2410 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 2411 }
2412 // Check if the file is closed
84fcd93f 2413 if (openedFiles.Contains(filename)) continue;;
923e2ca5 2414 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2415 if (file) {
2416 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 2417 // Clear file list to release object ownership to user.
160e7161 2418// file->Clear();
923e2ca5 2419 file->Close();
2420 }
2421 file = TFile::Open(filename);
2422 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2423 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2f0e656b 2424 if (cdir) cdir->cd();
923e2ca5 2425 return kFALSE;
2426 }
2427 file->Close();
84fcd93f 2428 openedFiles += filename;
2429 openedFiles += " ";
923e2ca5 2430 }
2f0e656b 2431 if (cdir) cdir->cd();
923e2ca5 2432 return kTRUE;
2433}
cd11251e 2434
2435//______________________________________________________________________________
61505f8b 2436void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 2437{
2438// Implements a nice text mode progress bar.
2439 static Long64_t icount = 0;
2440 static TString oname;
2441 static TString nname;
2442 static Long64_t ocurrent = 0;
2443 static Long64_t osize = 0;
2444 static Int_t oseconds = 0;
2445 static TStopwatch *owatch = 0;
2446 static Bool_t oneoftwo = kFALSE;
2447 static Int_t nrefresh = 0;
2448 static Int_t nchecks = 0;
8ddad121 2449 static char lastChar = 0;
f03a8355 2450 const char symbol[4] = {'-','\\','|','/'};
cd11251e 2451
8ddad121 2452 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
cd11251e 2453 if (!refresh) {
2454 nrefresh = 0;
2455 if (!size) return;
2456 owatch = watch;
2457 oname = opname;
2458 ocurrent = TMath::Abs(current);
2459 osize = TMath::Abs(size);
2460 if (ocurrent > osize) ocurrent=osize;
2461 } else {
2462 nrefresh++;
2463 if (!osize) return;
2464 }
f03a8355 2465 if ((current % fPBUpdateFreq) != 0) return;
cd11251e 2466 icount++;
f03a8355 2467 char progress[11] = " ";
2468 Int_t ichar = icount%4;
cd11251e 2469 Double_t time = 0.;
2470 Int_t hours = 0;
2471 Int_t minutes = 0;
2472 Int_t seconds = 0;
2473 if (owatch && !last) {
2474 owatch->Stop();
2475 time = owatch->RealTime();
f03a8355 2476 seconds = int(time) % 60;
2477 minutes = (int(time) / 60) % 60;
2478 hours = (int(time) / 60 / 60);
cd11251e 2479 if (refresh) {
2480 if (oseconds==seconds) {
2481 owatch->Continue();
2482 return;
2483 }
2484 oneoftwo = !oneoftwo;
2485 }
2486 oseconds = seconds;
2487 }
2488 if (refresh && oneoftwo) {
2489 nname = oname;
2490 if (nchecks <= 0) nchecks = nrefresh+1;
2491 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2492 oname = Form(" == %d%% ==", pctdone);
2493 }
2494 Double_t percent = 100.0*ocurrent/osize;
2495 Int_t nchar = Int_t(percent/10);
2496 if (nchar>10) nchar=10;
2497 Int_t i;
2498 for (i=0; i<nchar; i++) progress[i] = '=';
2499 progress[nchar] = symbol[ichar];
2500 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2501 progress[10] = '\0';
2502 oname += " ";
2503 oname.Remove(20);
2504 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2505 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2506 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
f03a8355 2507 if (time>0.) {
2508 Int_t full = Int_t(ocurrent > 0 ?
2509 time * (float(osize)/ocurrent) + .5 :
2510 99*3600+59*60+59);
499b6d5d 2511 Int_t remain = Int_t(full - time);
f03a8355 2512 Int_t rsec = remain % 60;
2513 Int_t rmin = (remain / 60) % 60;
2514 Int_t rhour = (remain / 60 / 60);
8ddad121 2515 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2516 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
f03a8355 2517 }
8ddad121 2518 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
cd11251e 2519 if (refresh && oneoftwo) oname = nname;
2520 if (owatch) owatch->Continue();
2521 if (last) {
2522 icount = 0;
2523 owatch = 0;
2524 ocurrent = 0;
2525 osize = 0;
2526 oseconds = 0;
2527 oneoftwo = kFALSE;
2528 nrefresh = 0;
2529 fprintf(stderr, "\n");
2530 }
2531}
012e169c 2532
2533//______________________________________________________________________________
2534void AliAnalysisManager::DoLoadBranch(const char *name)
2535{
2536 // Get tree and load branch if needed.
c5734a4b 2537 static Long64_t crtEntry = -100;
012e169c 2538
7acc5b9d 2539 if (fAutoBranchHandling || !fTree)
012e169c 2540 return;
2541
2542 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2543 if (!br) {
2544 br = fTree->GetBranch(name);
2545 if (!br) {
979e448a 2546 Error("DoLoadBranch", "Could not find branch %s",name);
012e169c 2547 return;
2548 }
2549 fTable.Add(br);
2550 }
c5734a4b 2551 if (br->GetReadEntry()==fCurrentEntry) return;
9162405c 2552 Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2553 if (readbytes<0) {
f5cbe261 2554 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
c5734a4b 2555 if (crtEntry != fCurrentEntry) {
2556 CountEvent(1,0,1,0);
2557 crtEntry = fCurrentEntry;
2558 }
2559 } else {
2560 if (crtEntry != fCurrentEntry) {
2561 CountEvent(1,1,0,0);
2562 crtEntry = fCurrentEntry;
2563 }
f5cbe261 2564 }
012e169c 2565}
e9247450 2566
2567//______________________________________________________________________________
c3732d79 2568void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
f5cbe261 2569{
2570// Add the statistics task to the manager.
2571 if (fStatistics) {
2572 Info("AddStatisticsTask", "Already added");
2573 return;
c3732d79 2574 }
2575 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2576 gROOT->ProcessLine(line);
f5cbe261 2577}
2578
2579//______________________________________________________________________________
2580void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2581{
2582// Bookkeep current event;
2583 if (!fStatistics) return;
2584 fStatistics->AddInput(ninput);
2585 fStatistics->AddProcessed(nprocessed);
2586 fStatistics->AddFailed(nfailed);
2587 fStatistics->AddAccepted(naccepted);
2588}
2589
2590//______________________________________________________________________________
e9247450 2591void AliAnalysisManager::AddStatisticsMsg(const char *line)
2592{
2593// Add a line in the statistics message. If available, the statistics message is written
2594// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2595// on the client.
2596 if (!strlen(line)) return;
2597 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2598 fStatisticsMsg += line;
2599}
2600
2601//______________________________________________________________________________
a99b2241 2602void AliAnalysisManager::WriteStatisticsMsg(Int_t)
e9247450 2603{
23a74fb4 2604// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
c3732d79 2605 static Bool_t done = kFALSE;
2606 if (done) return;
2607 done = kTRUE;
e296c79c 2608 if (!fStatistics) return;
e9247450 2609 ofstream out;
e296c79c 2610 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2611 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2612 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2613 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2614 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2615 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2616 fStatistics->GetNaccepted()), ios::out);
2617 out << fStatisticsMsg << endl;
e9247450 2618 out.close();
2619}
37196805 2620
2621//______________________________________________________________________________
2622const char* AliAnalysisManager::GetOADBPath()
2623{
2624// returns the path of the OADB
2625// this static function just depends on environment variables
2626
2627 static TString oadbPath;
2628
2629 if (gSystem->Getenv("OADB_PATH"))
2630 oadbPath = gSystem->Getenv("OADB_PATH");
2631 else if (gSystem->Getenv("ALICE_ROOT"))
2632 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2633 else
0a9cc013 2634 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
37196805 2635
2636 return oadbPath;
2637}
77dad4a9 2638
2639//______________________________________________________________________________
2640void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2641{
2642// Define a custom string variable mapped to a global unique name. The variable
2643// can be then retrieved by a given analysis macro via GetGlobalStr(key).
2644 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2645 if (!mgr) {
2646 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2647 return;
2648 }
2649 Bool_t valid = kFALSE;
2650 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2651 if (valid) {
2652 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2653 return;
2654 }
2655 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2656}
2657
2658//______________________________________________________________________________
2659const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2660{
2661// Static method to retrieve a global variable defined via SetGlobalStr.
2662 valid = kFALSE;
2663 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2664 if (!mgr) return 0;
2665 TObject *value = mgr->GetGlobals()->GetValue(key);
2666 if (!value) return 0;
2667 valid = kTRUE;
2668 return value->GetName();
2669}
2670
2671//______________________________________________________________________________
2672void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2673{
2674// Define a custom integer variable mapped to a global unique name. The variable
2675// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2676 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2677 if (!mgr) {
2678 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2679 return;
2680 }
2681 Bool_t valid = kFALSE;
2682 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2683 if (valid) {
2684 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2685 return;
2686 }
2687 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2688}
2689
2690//______________________________________________________________________________
2691Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2692{
2693// Static method to retrieve a global variable defined via SetGlobalInt.
2694 valid = kFALSE;
2695 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2696 if (!mgr) return 0;
2697 TObject *value = mgr->GetGlobals()->GetValue(key);
2698 if (!value) return 0;
2699 valid = kTRUE;
2700 TString s = value->GetName();
2701 return s.Atoi();
2702}
2703
2704//______________________________________________________________________________
2705void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2706{
2707// Define a custom double precision variable mapped to a global unique name. The variable
2708// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2709 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2710 if (!mgr) {
2711 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2712 return;
2713 }
2714 Bool_t valid = kFALSE;
2715 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2716 if (valid) {
2717 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2718 return;
2719 }
2720 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2721}
2722
2723//______________________________________________________________________________
2724Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2725{
2726// Static method to retrieve a global variable defined via SetGlobalDbl.
2727 valid = kFALSE;
2728 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2729 if (!mgr) return 0;
2730 TObject *value = mgr->GetGlobals()->GetValue(key);
2731 if (!value) return 0;
2732 valid = kTRUE;
2733 TString s = value->GetName();
2734 return s.Atof();
2735}
6f3e07d8 2736
2737//______________________________________________________________________________
2738void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2739{
2740// Sets Class debug level
2741
2742 if (!fDebugOptions) {
2743 fDebugOptions = new TObjArray();
2744 fDebugOptions->SetOwner(kTRUE);
2745 }
2746
2747 // substracting DebugOffset, beacuse of AliLog::SetClassDebugLevel()
2748 debugLevel -= AliLog::kDebug-1;
2749
2750 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2751 if (!debugOpt) {
2752 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel+AliLog::kDebug-1,className).Data());
2753 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2754 } else {
2755 TString oldDebugStr = debugOpt->GetTitle();
2756 Int_t oldDebug = oldDebugStr.Atoi();
2757 if (debugLevel > oldDebug) {
2758 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());
2759 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2760 } else {
2761 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());
2762 }
2763 }
2764}
2765
2766//______________________________________________________________________________
2767void AliAnalysisManager::ApplyDebugOptions()
2768{
2769// Apply debug options
2770
2771 if (!fDebugOptions) return;
2772
2773 TIter next(fDebugOptions);
2774 TNamed *debug;
2775 TString debugLevel;
2776 while ((debug=dynamic_cast<TNamed*>(next()))) {
2777 debugLevel = debug->GetTitle();
2778 AliInfo(TString::Format("ApplyDebugOptions : Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()+AliLog::kDebug-1).Data());
2779 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2780 }
2781}
2782
59e0dcd5 2783//______________________________________________________________________________
2784void AliAnalysisManager::Lock()
2785{
2786// Security lock. This is to detect NORMAL user errors and not really to
2787// protect against intentional hacks.
2788 if (fLocked) return;
2789 fLocked = kTRUE;
2790 if (fInputEventHandler) fInputEventHandler->Lock();
2791 if (fOutputEventHandler) fOutputEventHandler->Lock();
2792 if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2793 Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2794}
2795
2796//______________________________________________________________________________
2797void AliAnalysisManager::UnLock()
2798{
2799// Verbose unlocking. Hackers will be punished ;-) ...
2800 if (!fLocked) return;
2801 fLocked = kFALSE;
2802 if (fInputEventHandler) fInputEventHandler->UnLock();
2803 if (fOutputEventHandler) fOutputEventHandler->UnLock();
2804 if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2805 Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2806}
2807
2808//______________________________________________________________________________
2809void AliAnalysisManager::Changed()
2810{
2811// All critical setters pass through the Changed method that throws an exception
2812// in case the lock was set.
2813 if (fLocked) Fatal("Changed","Critical setter called in locked mode");
2814}