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