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