]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisManager.cxx
Updates in Balance Function Tasks:
[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()));
ed37a9ae 298// if (fAsyncReading) gEnv->SetValue("TFile.AsyncReading",1);
43072535 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());
ed37a9ae 983 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
b1310ef5 984 task->ExecuteTask();
985 }
986 }
ed37a9ae 987 if (fStatistics) fStatistics->StopTimer();
b1310ef5 988 }
c52c2132 989 }
ec5acdce 990 fIOTimer->Stop();
991 fIOTime += fIOTimer->RealTime();
cd463514 992 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 993}
994
995//______________________________________________________________________________
996void AliAnalysisManager::Terminate()
997{
998 // The Terminate() function is the last function to be called during
999 // a query. It always runs on the client, it can be used to present
c52c2132 1000 // the results graphically.
cd463514 1001 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
ec5acdce 1002 fInitTimer->Start(kTRUE);
57756ec5 1003 TDirectory *cdir = gDirectory;
1004 gROOT->cd();
327eaf46 1005 AliAnalysisTask *task;
a0e2e8b1 1006 AliAnalysisDataContainer *output;
c52c2132 1007 TIter next(fTasks);
a0e2e8b1 1008 TStopwatch timer;
096b5a2e 1009 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
327eaf46 1010 // Call Terminate() for tasks
096b5a2e 1011 Int_t itask = 0;
90a4b3ee 1012 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
a0e2e8b1 1013 // Save all the canvases produced by the Terminate
1014 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
a0e2e8b1 1015 task->Terminate();
57756ec5 1016 gROOT->cd();
096b5a2e 1017 if (getsysInfo)
1018 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
1019 itask++;
a0e2e8b1 1020 if (TObject::TestBit(kSaveCanvases)) {
226abfec 1021 if (!gROOT->IsBatch()) {
8e1f0465 1022 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
ec5acdce 1023 timer.Start(kTRUE);
1024 while (timer.RealTime()<5) {
226abfec 1025 timer.Continue();
1026 gSystem->ProcessEvents();
1027 }
1028 }
1029 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
1030 if (iend==0) continue;
a0e2e8b1 1031 TCanvas *canvas;
226abfec 1032 for (Int_t ipict=0; ipict<iend; ipict++) {
1033 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
a0e2e8b1 1034 if (!canvas) continue;
1035 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
226abfec 1036 }
1037 gROOT->GetListOfCanvases()->Delete();
a0e2e8b1 1038 }
1039 }
8c9485b2 1040 //
aa399a26 1041 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
1042 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
1043 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
57756ec5 1044 gROOT->cd();
6cd44ee0 1045 TObjArray *allOutputs = new TObjArray();
1046 Int_t icont;
1047 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
1048 if (!IsSkipTerminate())
1049 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
1050 TIter next1(allOutputs);
f2087b52 1051 TString handlerFile = "";
90d50a8c 1052 TString extraOutputs = "";
f2087b52 1053 if (fOutputEventHandler) {
1054 handlerFile = fOutputEventHandler->GetOutputFileName();
90d50a8c 1055 extraOutputs = fOutputEventHandler->GetExtraOutputs();
f2087b52 1056 }
e16a394c 1057 icont = 0;
ab5d25d8 1058 TList filestmp;
8c0ab8e8 1059 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 1060 // Special outputs or grid files have the files already closed and written.
e16a394c 1061 icont++;
1062 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
90a4b3ee 1063 if (fMode == kProofAnalysis) {
1064 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
1065 }
8c0ab8e8 1066 const char *filename = output->GetFileName();
61505f8b 1067 TString openoption = "RECREATE";
aa399a26 1068 if (!(strcmp(filename, "default"))) continue;
8d7d3b59 1069 if (!strlen(filename)) continue;
1be433fc 1070 if (!output->GetData()) continue;
8d7d3b59 1071 TDirectory *opwd = gDirectory;
84fcd93f 1072 TFile *file = output->GetFile();
1073 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
f2087b52 1074 if (!file) {
61505f8b 1075 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
ab5d25d8 1076 Bool_t firsttime = kTRUE;
90d50a8c 1077 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
ab5d25d8 1078 firsttime = kFALSE;
1079 } else {
1080 filestmp.Add(new TNamed(filename,""));
1081 }
1082 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
cd463514 1083 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
61505f8b 1084 file = new TFile(filename, openoption);
6cd44ee0 1085 } else {
cd463514 1086 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
ff07ec61 1087 openoption = file->GetOption();
1088 if (openoption == "READ") {
cd463514 1089 if (fDebug>1) printf("...reopening in UPDATE mode\n");
ff07ec61 1090 file->ReOpen("UPDATE");
1091 }
6cd44ee0 1092 }
84fcd93f 1093 if (file->IsZombie()) {
1094 Error("Terminate", "Cannot open output file %s", filename);
1095 continue;
1096 }
8e6e6fe8 1097 output->SetFile(file);
1098 file->cd();
84fcd93f 1099 // Check for a folder request
1100 TString dir = output->GetFolderName();
1101 if (!dir.IsNull()) {
1102 if (!file->GetDirectory(dir)) file->mkdir(dir);
1103 file->cd(dir);
1104 }
cd463514 1105 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1be433fc 1106 if (output->GetData()->InheritsFrom(TCollection::Class())) {
1107 // If data is a collection, we set the name of the collection
1108 // as the one of the container and we save as a single key.
1109 TCollection *coll = (TCollection*)output->GetData();
1110 coll->SetName(output->GetName());
1111 coll->Write(output->GetName(), TObject::kSingleKey);
1112 } else {
cbc8747a 1113 if (output->GetData()->InheritsFrom(TTree::Class())) {
1114 TTree *tree = (TTree*)output->GetData();
7a151c06 1115 tree->SetDirectory(gDirectory);
cbc8747a 1116 tree->AutoSave();
1117 } else {
1118 output->GetData()->Write();
1119 }
1be433fc 1120 }
8e6e6fe8 1121 if (opwd) opwd->cd();
57756ec5 1122 }
1123 gROOT->cd();
8e6e6fe8 1124 next1.Reset();
9f2d937f 1125 TString copiedFiles;
8e6e6fe8 1126 while ((output=(AliAnalysisDataContainer*)next1())) {
1127 // Close all files at output
1128 TDirectory *opwd = gDirectory;
f5e61abd 1129 if (output->GetFile()) {
f3c07fbd 1130 // Clear file list to release object ownership to user.
160e7161 1131// output->GetFile()->Clear();
f5e61abd 1132 output->GetFile()->Close();
1133 // Copy merged outputs in alien if requested
9f2d937f 1134 if (fSpecialOutputLocation.BeginsWith("alien://")) {
1135 if (copiedFiles.Contains(output->GetFile()->GetName())) {
1136 if (opwd) opwd->cd();
1137 output->SetFile(NULL);
1138 continue;
1139 }
f5e61abd 1140 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
77dad4a9 1141 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
f5e61abd 1142 TFile::Cp(output->GetFile()->GetName(),
1143 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
9f2d937f 1144 copiedFiles += output->GetFile()->GetName();
f5e61abd 1145 }
77dad4a9 1146 output->SetFile(NULL);
f5e61abd 1147 }
8d7d3b59 1148 if (opwd) opwd->cd();
8c0ab8e8 1149 }
6cd44ee0 1150 delete allOutputs;
e9247450 1151 //Write statistics information on the client
e296c79c 1152 if (fStatistics) WriteStatisticsMsg(fNcalls);
8c0ab8e8 1153 if (getsysInfo) {
b6db1d18 1154 TDirectory *crtdir = gDirectory;
8c0ab8e8 1155 TFile f("syswatch.root", "RECREATE");
096b5a2e 1156 TH1 *hist;
1157 TString cut;
8c0ab8e8 1158 if (!f.IsZombie()) {
1159 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
096b5a2e 1160 tree->SetName("syswatch");
8c0ab8e8 1161 tree->SetMarkerStyle(kCircle);
1162 tree->SetMarkerColor(kBlue);
1163 tree->SetMarkerSize(0.5);
1164 if (!gROOT->IsBatch()) {
1165 tree->SetAlias("event", "id0");
096b5a2e 1166 tree->SetAlias("task", "id1");
1167 tree->SetAlias("stage", "id2");
1168 // Already defined aliases
1169 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1170 // tree->SetAlias("T","stampSec-first");
1171 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1172 // tree->SetAlias("VM","pI.fMemVirtual");
1173 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1174 Int_t npads = 1 /*COO plot for all tasks*/ +
1175 fTopTasks->GetEntries() /*Exec plot per task*/ +
1176 1 /*Terminate plot for all tasks*/ +
1177 1; /*vm plot*/
1178
1179 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1180 if (npads<iopt*(iopt+1))
1181 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1182 else
1183 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1184 Int_t ipad = 1;
1185 // draw the plot of deltaVM for Exec for each task
779e9992 1186 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
096b5a2e 1187 task = (AliAnalysisTask*)fTopTasks->At(itask);
1188 canvas->cd(ipad++);
1189 cut = Form("task==%d && stage==1", itask);
1190 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1191 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1192 if (hist) {
084c84df 1193 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
b3e07543 1194 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1195 }
1196 }
1197 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1198 canvas->cd(ipad++);
1199 tree->SetMarkerStyle(kFullTriangleUp);
1200 tree->SetMarkerColor(kRed);
1201 tree->SetMarkerSize(0.8);
1202 cut = "task>=0 && task<1000 && stage==0";
1203 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1204 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1205 if (hist) {
1206 hist->SetTitle("Memory in CreateOutputObjects()");
b3e07543 1207 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1208 hist->GetXaxis()->SetTitle("task");
1209 }
1210 // draw the plot of deltaVM for Terminate for all tasks
1211 canvas->cd(ipad++);
1212 tree->SetMarkerStyle(kOpenSquare);
1213 tree->SetMarkerColor(kMagenta);
1214 cut = "task>=0 && task<1000 && stage==2";
1215 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1216 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1217 if (hist) {
1218 hist->SetTitle("Memory in Terminate()");
b3e07543 1219 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1220 hist->GetXaxis()->SetTitle("task");
1221 }
1222 // Full VM profile
1223 canvas->cd(ipad++);
1224 tree->SetMarkerStyle(kFullCircle);
1225 tree->SetMarkerColor(kGreen);
1226 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1227 tree->Draw("VM:event",cut,"", 1234567890, 0);
1228 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1229 if (hist) {
1230 hist->SetTitle("Virtual memory");
b3e07543 1231 hist->GetYaxis()->SetTitle("VM [MB]");
096b5a2e 1232 }
1233 canvas->Modified();
8c0ab8e8 1234 }
096b5a2e 1235 tree->SetMarkerStyle(kCircle);
1236 tree->SetMarkerColor(kBlue);
1237 tree->SetMarkerSize(0.5);
8c0ab8e8 1238 tree->Write();
1239 f.Close();
1240 delete tree;
1241 }
b6db1d18 1242 if (crtdir) crtdir->cd();
923e2ca5 1243 }
1244 // Validate the output files
f62a0e4c 1245 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
923e2ca5 1246 ofstream out;
1247 out.open("outputs_valid", ios::out);
1248 out.close();
57756ec5 1249 }
ec5acdce 1250 if (cdir) cdir->cd();
1251 fInitTimer->Stop();
1252 if (fDebug || IsCollectThroughput()) {
1253 printf("=Analysis %s= Terminate time: %g[sec]\n", GetName(), fInitTimer->RealTime());
1254 }
cd463514 1255 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 1256}
096b5a2e 1257//______________________________________________________________________________
1258void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1259{
1260// Profiles the task having the itop index in the list of top (first level) tasks.
1261 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1262 if (!task) {
1263 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1264 return;
1265 }
1266 ProfileTask(task->GetName(), option);
1267}
1268
1269//______________________________________________________________________________
1270void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1271{
1272// Profile a managed task after the execution of the analysis in case NSysInfo
1273// was used.
1274 if (gSystem->AccessPathName("syswatch.root")) {
1275 Error("ProfileTask", "No file syswatch.root found in the current directory");
1276 return;
1277 }
1278 if (gROOT->IsBatch()) return;
1279 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1280 if (!task) {
1281 Error("ProfileTask", "No top task named %s known by the manager.", name);
1282 return;
1283 }
1284 Int_t itop = fTopTasks->IndexOf(task);
1285 Int_t itask = fTasks->IndexOf(task);
1286 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1287 TDirectory *cdir = gDirectory;
1288 TFile f("syswatch.root");
1289 TTree *tree = (TTree*)f.Get("syswatch");
1290 if (!tree) {
1291 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1292 return;
1293 }
cd463514 1294 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
096b5a2e 1295 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1296 canvas->Divide(2, 2, 0.01, 0.01);
1297 Int_t ipad = 1;
1298 TString cut;
1299 TH1 *hist;
1300 // VM profile for COO and Terminate methods
1301 canvas->cd(ipad++);
1302 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1303 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1304 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1305 if (hist) {
084c84df 1306 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1307 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1308 hist->GetXaxis()->SetTitle("method");
1309 }
1310 // CPU profile per event
1311 canvas->cd(ipad++);
1312 cut = Form("task==%d && stage==1",itop);
1313 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1314 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1315 if (hist) {
1316 hist->SetTitle("Execution time per event");
1317 hist->GetYaxis()->SetTitle("CPU/event [s]");
1318 }
1319 // VM profile for Exec
1320 canvas->cd(ipad++);
1321 cut = Form("task==%d && stage==1",itop);
1322 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1323 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1324 if (hist) {
084c84df 1325 hist->SetTitle("Alocated VM[MB] per event");
1326 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1327 }
1328 canvas->Modified();
1329 delete tree;
1330 f.Close();
1331 if (cdir) cdir->cd();
1332}
d3106602 1333
1334//______________________________________________________________________________
1335void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1336{
1337// Adds a user task to the global list of tasks.
21ca8e59 1338 if (fInitOK) {
1339 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1340 return;
1341 }
1342
8d7d3b59 1343 if (fTasks->FindObject(task)) {
1344 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1345 return;
1346 }
d3106602 1347 task->SetActive(kFALSE);
1348 fTasks->Add(task);
1349}
1350
1351//______________________________________________________________________________
1352AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1353{
1354// Retreive task by name.
1355 if (!fTasks) return NULL;
1356 return (AliAnalysisTask*)fTasks->FindObject(name);
1357}
1358
ed37a9ae 1359//______________________________________________________________________________
1360Int_t AliAnalysisManager::GetTaskIndex(const AliAnalysisTask *task) const
1361{
1362// Returns task inded in the manager's list, -1 if not registered.
1363 if (!fTasks) return -1;
1364 return fTasks->IndexOf(task);
1365}
1366
d3106602 1367//______________________________________________________________________________
1368AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 1369 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 1370{
1371// Create a data container of a certain type. Types can be:
84fcd93f 1372// kExchangeContainer = 0, used to exchange data between tasks
d3106602 1373// kInputContainer = 1, used to store input data
84fcd93f 1374// kOutputContainer = 2, used for writing result to a file
1375// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1376// the output object to a folder inside the output file
b1310ef5 1377 if (fContainers->FindObject(name)) {
923e2ca5 1378 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 1379 return NULL;
1380 }
d3106602 1381 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1382 fContainers->Add(cont);
1383 switch (type) {
1384 case kInputContainer:
1385 fInputs->Add(cont);
1386 break;
1387 case kOutputContainer:
1388 fOutputs->Add(cont);
8c0ab8e8 1389 if (filename && strlen(filename)) {
1390 cont->SetFileName(filename);
6cd44ee0 1391 cont->SetDataOwned(kFALSE); // data owned by the file
1392 }
1393 break;
1394 case kParamContainer:
1395 fParamCont->Add(cont);
1396 if (filename && strlen(filename)) {
1397 cont->SetFileName(filename);
8c0ab8e8 1398 cont->SetDataOwned(kFALSE); // data owned by the file
1399 }
d3106602 1400 break;
c52c2132 1401 case kExchangeContainer:
d3106602 1402 break;
1403 }
1404 return cont;
1405}
1406
1407//______________________________________________________________________________
1408Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1409 AliAnalysisDataContainer *cont)
1410{
1411// Connect input of an existing task to a data container.
60a04972 1412 if (!task) {
1413 Error("ConnectInput", "Task pointer is NULL");
1414 return kFALSE;
1415 }
d3106602 1416 if (!fTasks->FindObject(task)) {
1417 AddTask(task);
8d7d3b59 1418 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 1419 }
1420 Bool_t connected = task->ConnectInput(islot, cont);
1421 return connected;
1422}
1423
1424//______________________________________________________________________________
1425Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1426 AliAnalysisDataContainer *cont)
1427{
1428// Connect output of an existing task to a data container.
60a04972 1429 if (!task) {
1430 Error("ConnectOutput", "Task pointer is NULL");
1431 return kFALSE;
1432 }
d3106602 1433 if (!fTasks->FindObject(task)) {
1434 AddTask(task);
c52c2132 1435 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 1436 }
1437 Bool_t connected = task->ConnectOutput(islot, cont);
1438 return connected;
1439}
1440
1441//______________________________________________________________________________
1442void AliAnalysisManager::CleanContainers()
1443{
1444// Clean data from all containers that have already finished all client tasks.
1445 TIter next(fContainers);
1446 AliAnalysisDataContainer *cont;
1447 while ((cont=(AliAnalysisDataContainer *)next())) {
1448 if (cont->IsOwnedData() &&
1449 cont->IsDataReady() &&
1450 cont->ClientsExecuted()) cont->DeleteData();
1451 }
1452}
1453
1454//______________________________________________________________________________
1455Bool_t AliAnalysisManager::InitAnalysis()
1456{
1457// Initialization of analysis chain of tasks. Should be called after all tasks
1458// and data containers are properly connected
923e2ca5 1459 // Reset flag and remove valid_outputs file if exists
21ca8e59 1460 if (fInitOK) return kTRUE;
923e2ca5 1461 if (!gSystem->AccessPathName("outputs_valid"))
1462 gSystem->Unlink("outputs_valid");
d3106602 1463 // Check for top tasks (depending only on input data containers)
1464 if (!fTasks->First()) {
c52c2132 1465 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 1466 return kFALSE;
1467 }
1468 TIter next(fTasks);
1469 AliAnalysisTask *task;
1470 AliAnalysisDataContainer *cont;
1471 Int_t ntop = 0;
1472 Int_t nzombies = 0;
327eaf46 1473 Bool_t iszombie = kFALSE;
1474 Bool_t istop = kTRUE;
d3106602 1475 Int_t i;
1476 while ((task=(AliAnalysisTask*)next())) {
327eaf46 1477 istop = kTRUE;
1478 iszombie = kFALSE;
d3106602 1479 Int_t ninputs = task->GetNinputs();
d3106602 1480 for (i=0; i<ninputs; i++) {
1481 cont = task->GetInputSlot(i)->GetContainer();
1482 if (!cont) {
327eaf46 1483 if (!iszombie) {
d3106602 1484 task->SetZombie();
1485 fZombies->Add(task);
1486 nzombies++;
327eaf46 1487 iszombie = kTRUE;
d3106602 1488 }
c52c2132 1489 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1490 i, task->GetName());
d3106602 1491 }
327eaf46 1492 if (iszombie) continue;
d3106602 1493 // Check if cont is an input container
327eaf46 1494 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 1495 // Connect to parent task
1496 }
327eaf46 1497 if (istop) {
d3106602 1498 ntop++;
1499 fTopTasks->Add(task);
1500 }
1501 }
1502 if (!ntop) {
c52c2132 1503 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 1504 return kFALSE;
1505 }
1506 // Check now if there are orphan tasks
1507 for (i=0; i<ntop; i++) {
1508 task = (AliAnalysisTask*)fTopTasks->At(i);
1509 task->SetUsed();
1510 }
1511 Int_t norphans = 0;
1512 next.Reset();
1513 while ((task=(AliAnalysisTask*)next())) {
1514 if (!task->IsUsed()) {
1515 norphans++;
c52c2132 1516 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 1517 }
1518 }
1519 // Check the task hierarchy (no parent task should depend on data provided
1520 // by a daughter task)
1521 for (i=0; i<ntop; i++) {
1522 task = (AliAnalysisTask*)fTopTasks->At(i);
1523 if (task->CheckCircularDeps()) {
c52c2132 1524 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 1525 PrintStatus("dep");
1526 return kFALSE;
1527 }
1528 }
b1310ef5 1529 // Check that all containers feeding post-event loop tasks are in the outputs list
1530 TIter nextcont(fContainers); // loop over all containers
1531 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1532 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1533 if (cont->HasConsumers()) {
1534 // Check if one of the consumers is post event loop
1535 TIter nextconsumer(cont->GetConsumers());
1536 while ((task=(AliAnalysisTask*)nextconsumer())) {
1537 if (task->IsPostEventLoop()) {
1538 fOutputs->Add(cont);
1539 break;
1540 }
1541 }
1542 }
1543 }
1544 }
8d7d3b59 1545 // Check if all special output containers have a file name provided
1546 TIter nextout(fOutputs);
1547 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1548 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1549 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1550 return kFALSE;
1551 }
7acc5b9d 1552 }
1553 // Initialize requested branch list if needed
1554 if (!fAutoBranchHandling) {
1555 next.Reset();
1556 while ((task=(AliAnalysisTask*)next())) {
1557 if (!task->HasBranches()) {
1558 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\"",
1559 task->GetName(), task->ClassName());
1560 return kFALSE;
1561 }
1562 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1563 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1564 return kFALSE;
1565 }
1566 TString taskbranches;
1567 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1568 if (taskbranches.IsNull()) {
1569 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1570 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1571 return kFALSE;
1572 }
1573 AddBranches(taskbranches);
1574 }
1575 }
327eaf46 1576 fInitOK = kTRUE;
d3106602 1577 return kTRUE;
1578}
1579
7acc5b9d 1580//______________________________________________________________________________
1581void AliAnalysisManager::AddBranches(const char *branches)
1582{
1583// Add branches to the existing fRequestedBranches.
1584 TString br(branches);
1585 TObjArray *arr = br.Tokenize(",");
1586 TIter next(arr);
1587 TObject *obj;
1588 while ((obj=next())) {
1589 if (!fRequestedBranches.Contains(obj->GetName())) {
1590 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1591 fRequestedBranches += obj->GetName();
1592 }
1593 }
dcc1f876 1594 delete arr;
7acc5b9d 1595}
1596
1597//______________________________________________________________________________
1598void AliAnalysisManager::CheckBranches(Bool_t load)
1599{
1600// The method checks the input branches to be loaded during the analysis.
1601 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1602 TObjArray *arr = fRequestedBranches.Tokenize(",");
1603 TIter next(arr);
1604 TObject *obj;
1605 while ((obj=next())) {
1606 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1607 if (!br) {
1608 br = fTree->GetBranch(obj->GetName());
1609 if (!br) {
1610 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1611 continue;
1612 }
1613 }
1614 fTable.Add(br);
9162405c 1615 if (load && br->GetReadEntry()!=GetCurrentEntry()) {
1616 br->GetEntry(GetCurrentEntry());
1617 }
7acc5b9d 1618 }
dcc1f876 1619 delete arr;
7acc5b9d 1620}
1621
4747b4a7 1622//______________________________________________________________________________
1623Bool_t AliAnalysisManager::CheckTasks() const
1624{
1625// Check consistency of tasks.
25c87093 1626 Int_t ntasks = fTasks->GetEntries();
1627 if (!ntasks) {
1628 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1629 return kFALSE;
1630 }
4747b4a7 1631 // Get the pointer to AliAnalysisTaskSE::Class()
1632 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1633 // Loop all tasks to check if their corresponding library was loaded
1634 TIter next(fTasks);
1635 TObject *obj;
1636 while ((obj=next())) {
1637 if (obj->IsA() == badptr) {
1638 Error("CheckTasks", "##################\n \
1639 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1640 return kFALSE;
1641 }
1642 }
1643 return kTRUE;
1644}
1645
d3106602 1646//______________________________________________________________________________
1647void AliAnalysisManager::PrintStatus(Option_t *option) const
1648{
1649// Print task hierarchy.
8c0ab8e8 1650 if (!fInitOK) {
1651 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1652 return;
1653 }
1654 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1655 if (getsysInfo)
1656 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1657 TIter next(fTopTasks);
1658 AliAnalysisTask *task;
1659 while ((task=(AliAnalysisTask*)next()))
1660 task->PrintTask(option);
dcc1f876 1661
7acc5b9d 1662 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1663 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
dcc1f876 1664
1665 TString sopt(option);
1666 sopt.ToUpper();
1667
1668 if (sopt.Contains("ALL"))
1669 {
1670 if ( fOutputEventHandler )
1671 {
1672 cout << TString('_',78) << endl;
1673 cout << "OutputEventHandler:" << endl;
1674 fOutputEventHandler->Print(" ");
1675 }
1676 }
d3106602 1677}
1678
1679//______________________________________________________________________________
1680void AliAnalysisManager::ResetAnalysis()
1681{
1682// Reset all execution flags and clean containers.
1683 CleanContainers();
1684}
1685
d512d8e2 1686//______________________________________________________________________________
1687void AliAnalysisManager::RunLocalInit()
1688{
1689// Run LocalInit method for all tasks.
1690 TDirectory *cdir = gDirectory;
1691 if (IsTrainInitialized()) return;
1692 TIter nextTask(fTasks);
1693 AliAnalysisTask *task;
1694 while ((task=(AliAnalysisTask*)nextTask())) {
1695 gROOT->cd();
1696 task->LocalInit();
1697 }
2f0e656b 1698 if (cdir) cdir->cd();
d512d8e2 1699 TObject::SetBit(kTasksInitialized, kTRUE);
1700}
1701
fdbaa4ce 1702//______________________________________________________________________________
1703void AliAnalysisManager::InputFileFromTree(TTree * const tree, TString &fname)
1704{
1705// Retrieves name of the file from tree
1706 fname = "";
1707 if (!tree) return;
1708 TFile *file = tree->GetCurrentFile();
1709 TString basename;
1710 if (!file) {
1711 TChain *chain = dynamic_cast<TChain*>(tree);
1712 if (!chain || !chain->GetNtrees()) return;
1713 basename = gSystem->BaseName(chain->GetListOfFiles()->First()->GetTitle());
1714 } else {
1715 basename = gSystem->BaseName(file->GetName());
1716 }
1717 Int_t index = basename.Index("#");
1718 fname = basename(index+1, basename.Length());
1719}
1720
27734f0e 1721//______________________________________________________________________________
1722Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1723{
1724// Start analysis having a grid handler.
1725 if (!fGridHandler) {
1726 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1727 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1728 return -1;
1729 }
1730 TTree *tree = NULL;
1731 return StartAnalysis(type, tree, nentries, firstentry);
1732}
1733
c52c2132 1734//______________________________________________________________________________
61505f8b 1735Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1736{
aee5ee44 1737// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1738// MIX. Process nentries starting from firstentry
bf574918 1739 Long64_t retv = 0;
57756ec5 1740 // Backup current directory and make sure gDirectory points to gROOT
1741 TDirectory *cdir = gDirectory;
1742 gROOT->cd();
c52c2132 1743 if (!fInitOK) {
1744 Error("StartAnalysis","Analysis manager was not initialized !");
2f0e656b 1745 if (cdir) cdir->cd();
1f87e9fb 1746 return -1;
c52c2132 1747 }
4747b4a7 1748 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
20b7268e 1749 if (fDebug > 1) {
1750 printf("StartAnalysis %s\n",GetName());
1751 AliLog::SetGlobalLogLevel(AliLog::kInfo);
59e0dcd5 1752 }
f03a8355 1753 fMaxEntries = nentries;
8e1f0465 1754 fIsRemote = kFALSE;
c52c2132 1755 TString anaType = type;
1756 anaType.ToLower();
1757 fMode = kLocalAnalysis;
d512d8e2 1758 if (anaType.Contains("file")) fIsRemote = kTRUE;
4ab472d4 1759 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1760 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1761 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
fdbaa4ce 1762 if (fInputEventHandler) {
1763 TString fname;
1764 InputFileFromTree(tree, fname);
1765 if (fname.Length()) fInputEventHandler->SetInputFileName(fname);
1766 }
4ab472d4 1767
c52c2132 1768 if (fMode == kGridAnalysis) {
8e1f0465 1769 fIsRemote = kTRUE;
f866cba5 1770 if (!anaType.Contains("terminate")) {
1771 if (!fGridHandler) {
1772 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1773 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
2f0e656b 1774 if (cdir) cdir->cd();
f866cba5 1775 return -1;
1776 }
1777 // Write analysis manager in the analysis file
1778 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1779 // run local task configuration
d512d8e2 1780 RunLocalInit();
f866cba5 1781 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1782 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
2f0e656b 1783 if (cdir) cdir->cd();
f866cba5 1784 return -1;
1785 }
c57f56b7 1786
f866cba5 1787 // Terminate grid analysis
2f0e656b 1788 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1789 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
f866cba5 1790 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1791 if (!fGridHandler->MergeOutputs()) {
1792 // Return if outputs could not be merged or if it alien handler
1793 // was configured for offline mode or local testing.
2f0e656b 1794 if (cdir) cdir->cd();
f866cba5 1795 return 0;
1796 }
1797 }
1798 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
0309b722 1799 if (cdir) cdir->cd();
c57f56b7 1800 ImportWrappers(NULL);
1801 Terminate();
2f0e656b 1802 if (cdir) cdir->cd();
1f87e9fb 1803 return 0;
981f2614 1804 }
ab5d25d8 1805 TString line;
efd53803 1806 SetEventLoop(kFALSE);
8d7d3b59 1807 // Enable event loop mode if a tree was provided
27734f0e 1808 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1809
8c0ab8e8 1810 TChain *chain = 0;
1811 TString ttype = "TTree";
4ab472d4 1812 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1813 chain = (TChain*)tree;
6b742510 1814 if (!chain || !chain->GetListOfFiles()->First()) {
1815 Error("StartAnalysis", "Cannot process null or empty chain...");
2f0e656b 1816 if (cdir) cdir->cd();
1f87e9fb 1817 return -1;
6b742510 1818 }
8c0ab8e8 1819 ttype = "TChain";
1820 }
9b33830a 1821
096b5a2e 1822 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1823 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
aee5ee44 1824 // Initialize locally all tasks (happens for all modes)
9b33830a 1825 TIter next(fTasks);
1826 AliAnalysisTask *task;
d512d8e2 1827 RunLocalInit();
efd53803 1828
c52c2132 1829 switch (fMode) {
1830 case kLocalAnalysis:
27734f0e 1831 if (!tree && !fGridHandler) {
03a5cc9f 1832 TIter nextT(fTasks);
981f2614 1833 // Call CreateOutputObjects for all tasks
096b5a2e 1834 Int_t itask = 0;
979e448a 1835 Bool_t dirStatus = TH1::AddDirectoryStatus();
03a5cc9f 1836 while ((task=(AliAnalysisTask*)nextT())) {
979e448a 1837 TH1::AddDirectory(kFALSE);
c5a87c56 1838 task->CreateOutputObjects();
4747b4a7 1839 if (!task->CheckPostData()) {
1840 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1841 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1842 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1843 }
096b5a2e 1844 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
57756ec5 1845 gROOT->cd();
096b5a2e 1846 itask++;
c5a87c56 1847 }
979e448a 1848 TH1::AddDirectory(dirStatus);
06a59280 1849 if (IsExternalLoop()) {
1850 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1851 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1f87e9fb 1852 return 0;
57756ec5 1853 }
c52c2132 1854 ExecAnalysis();
981f2614 1855 Terminate();
1f87e9fb 1856 return 0;
c52c2132 1857 }
27734f0e 1858 fSelector = new AliAnalysisSelector(this);
1859 // Check if a plugin handler is used
1860 if (fGridHandler) {
1861 // Get the chain from the plugin
1862 TString dataType = "esdTree";
1863 if (fInputEventHandler) {
1864 dataType = fInputEventHandler->GetDataType();
1865 dataType.ToLower();
1866 dataType += "Tree";
1867 }
1868 chain = fGridHandler->GetChainForTestMode(dataType);
1869 if (!chain) {
1870 Error("StartAnalysis", "No chain for test mode. Aborting.");
1871 return -1;
1872 }
1873 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1874 retv = chain->Process(fSelector, "", nentries, firstentry);
1875 break;
1876 }
c52c2132 1877 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1878 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
bf574918 1879 retv = tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1880 break;
1881 case kProofAnalysis:
8e1f0465 1882 fIsRemote = kTRUE;
3bdcb562 1883 // Check if the plugin is used
1884 if (fGridHandler) {
1885 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1886 }
c52c2132 1887 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1888 Error("StartAnalysis", "No PROOF!!! Exiting.");
2f0e656b 1889 if (cdir) cdir->cd();
1f87e9fb 1890 return -1;
c52c2132 1891 }
ea091b97 1892 line = Form("gProof->AddInput((TObject*)%p);", this);
c52c2132 1893 gROOT->ProcessLine(line);
1894 if (chain) {
1895 chain->SetProof();
1896 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
bf574918 1897 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1898 } else {
61505f8b 1899 Error("StartAnalysis", "No chain!!! Exiting.");
2f0e656b 1900 if (cdir) cdir->cd();
1f87e9fb 1901 return -1;
c52c2132 1902 }
1903 break;
1904 case kGridAnalysis:
27734f0e 1905 fIsRemote = kTRUE;
1906 if (!anaType.Contains("terminate")) {
1907 if (!fGridHandler) {
1908 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1909 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
2f0e656b 1910 if (cdir) cdir->cd();
27734f0e 1911 return -1;
1912 }
1913 // Write analysis manager in the analysis file
1914 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1915 // Start the analysis via the handler
1916 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1917 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
2f0e656b 1918 if (cdir) cdir->cd();
27734f0e 1919 return -1;
1920 }
1921
1922 // Terminate grid analysis
2f0e656b 1923 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1924 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
27734f0e 1925 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1926 if (!fGridHandler->MergeOutputs()) {
1927 // Return if outputs could not be merged or if it alien handler
1928 // was configured for offline mode or local testing.
2f0e656b 1929 if (cdir) cdir->cd();
27734f0e 1930 return 0;
1931 }
1932 }
1933 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1934 ImportWrappers(NULL);
1935 Terminate();
2f0e656b 1936 if (cdir) cdir->cd();
27734f0e 1937 return 0;
aee5ee44 1938 case kMixingAnalysis:
1939 // Run event mixing analysis
1940 if (!fEventPool) {
1941 Error("StartAnalysis", "Cannot run event mixing without event pool");
2f0e656b 1942 if (cdir) cdir->cd();
1f87e9fb 1943 return -1;
aee5ee44 1944 }
1945 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1946 fSelector = new AliAnalysisSelector(this);
aee5ee44 1947 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1948 next.Reset();
aee5ee44 1949 // Call NotifyBinChange for all tasks
1950 while ((task=(AliAnalysisTask*)next()))
1951 if (!task->IsPostEventLoop()) task->NotifyBinChange();
bf574918 1952 retv = chain->Process(fSelector);
1953 if (retv < 0) {
1954 Error("StartAnalysis", "Mixing analysis failed");
2f0e656b 1955 if (cdir) cdir->cd();
bf574918 1956 return retv;
1957 }
aee5ee44 1958 }
1959 PackOutput(fSelector->GetOutputList());
1960 Terminate();
1f87e9fb 1961 }
2f0e656b 1962 if (cdir) cdir->cd();
bf574918 1963 return retv;
c52c2132 1964}
1965
d86ed856 1966//______________________________________________________________________________
1f87e9fb 1967Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
d86ed856 1968{
1969// Start analysis for this manager on a given dataset. Analysis task can be:
1970// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1971 if (!fInitOK) {
1972 Error("StartAnalysis","Analysis manager was not initialized !");
1f87e9fb 1973 return -1;
d86ed856 1974 }
8e1f0465 1975 fIsRemote = kTRUE;
cd463514 1976 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
d86ed856 1977 TString anaType = type;
1978 anaType.ToLower();
1979 if (!anaType.Contains("proof")) {
d140f7fb 1980 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1f87e9fb 1981 return -1;
d86ed856 1982 }
1983 fMode = kProofAnalysis;
ab5d25d8 1984 TString line;
d88e4159 1985 TString proofProcessOpt;
d86ed856 1986 SetEventLoop(kTRUE);
1987 // Set the dataset flag
1988 TObject::SetBit(kUseDataSet);
1989 fTree = 0;
3bdcb562 1990 if (fGridHandler) {
1991 // Start proof analysis using the grid handler
1992 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1993 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1994 return -1;
1995 }
1996 // Check if the plugin is in test mode
1997 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
830acc4c 1998 dataset = "test_collection";
3bdcb562 1999 } else {
2000 dataset = fGridHandler->GetProofDataSet();
2001 }
d88e4159 2002
2003 proofProcessOpt = fGridHandler->GetProofProcessOpt();
3bdcb562 2004 }
2005
2006 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
2007 Error("StartAnalysis", "No PROOF!!! Exiting.");
2008 return -1;
2009 }
d86ed856 2010
2011 // Initialize locally all tasks
d512d8e2 2012 RunLocalInit();
2013
ea091b97 2014 line = Form("gProof->AddInput((TObject*)%p);", this);
d86ed856 2015 gROOT->ProcessLine(line);
3bdcb562 2016 Long_t retv;
d88e4159 2017 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
2018 dataset,proofProcessOpt.Data(), nentries, firstentry);
ea091b97 2019 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
2020 retv = (Long_t)gROOT->ProcessLine(line);
bf574918 2021 return retv;
d86ed856 2022}
2023
d3106602 2024//______________________________________________________________________________
84fcd93f 2025TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
2026{
2027// Opens according the option the file specified by cont->GetFileName() and changes
2028// current directory to cont->GetFolderName(). If the file was already opened, it
2029// checks if the option UPDATE was preserved. File open via TProofOutputFile can
2030// be optionally ignored.
2031 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2032 TString filename = cont->GetFileName();
2033 TFile *f = NULL;
2034 if (filename.IsNull()) {
2035 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2036 return NULL;
2037 }
2038 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2039 && !ignoreProof)
2040 f = mgr->OpenProofFile(cont,option);
2041 else {
2042 // Check first if the file is already opened
0f1b50f3 2043 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 2044 if (f) {
2045 // Check if option "UPDATE" was preserved
2046 TString opt(option);
2047 opt.ToUpper();
2048 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 2049 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 2050 } else {
0f1b50f3 2051 f = TFile::Open(filename, option);
84fcd93f 2052 }
2053 }
2054 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2055 cont->SetFile(f);
2056 // Cd to file
2057 f->cd();
2058 // Check for a folder request
2059 TString dir = cont->GetFolderName();
2060 if (!dir.IsNull()) {
2061 if (!f->GetDirectory(dir)) f->mkdir(dir);
2062 f->cd(dir);
2063 }
2064 return f;
2065 }
2066 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2067 cont->SetFile(NULL);
2068 return NULL;
2069}
2070
2071//______________________________________________________________________________
039e671e 2072TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
8d7d3b59 2073{
2074// Opens a special output file used in PROOF.
84fcd93f 2075 TString line;
2076 TString filename = cont->GetFileName();
23c9468b 2077 if (cont == fCommonOutput) {
039e671e 2078 if (fOutputEventHandler) {
2079 if (strlen(extaod)) filename = extaod;
2080 filename = fOutputEventHandler->GetOutputFileName();
2081 }
61505f8b 2082 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 2083 }
84fcd93f 2084 TFile *f = NULL;
2085 if (fMode!=kProofAnalysis || !fSelector) {
2086 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2087 return NULL;
2088 }
2089 if (fSpecialOutputLocation.Length()) {
2090 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2091 if (f) {
2092 // Check if option "UPDATE" was preserved
2093 TString opt(option);
2094 opt.ToUpper();
23c9468b 2095 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 2096 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 2097 } else {
2098 f = new TFile(filename, option);
2099 }
2100 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2101 cont->SetFile(f);
2102 // Cd to file
2103 f->cd();
2104 // Check for a folder request
2105 TString dir = cont->GetFolderName();
2106 if (dir.Length()) {
2107 if (!f->GetDirectory(dir)) f->mkdir(dir);
2108 f->cd(dir);
2109 }
f5e61abd 2110 return f;
84fcd93f 2111 }
2112 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2113 cont->SetFile(NULL);
2114 return NULL;
2115 }
2116 // Check if there is already a proof output file in the output list
2117 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2118 if (pof) {
2119 // Get the actual file
b3e07543 2120 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
84fcd93f 2121 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 2122 if (fDebug>1) {
2123 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2124 }
84fcd93f 2125 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
ab5d25d8 2126 if (!f) {
2127 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2128 return NULL;
2129 }
84fcd93f 2130 // Check if option "UPDATE" was preserved
2131 TString opt(option);
2132 opt.ToUpper();
2133 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2134 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2135 } else {
90a4b3ee 2136 if (cont->IsRegisterDataset()) {
61505f8b 2137 TString dsetName = filename;
2138 dsetName.ReplaceAll(".root", cont->GetTitle());
2139 dsetName.ReplaceAll(":","_");
2140 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2141 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 2142 } else {
2143 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2144 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2145 }
84fcd93f 2146 if (fDebug > 1) printf("=== %s\n", line.Data());
2147 gROOT->ProcessLine(line);
2148 line = Form("pf->OpenFile(\"%s\");", option);
2149 gROOT->ProcessLine(line);
2150 f = gFile;
2151 if (fDebug > 1) {
8d7d3b59 2152 gROOT->ProcessLine("pf->Print()");
84fcd93f 2153 printf(" == proof file name: %s", f->GetName());
2154 }
2155 // Add to proof output list
b3e07543 2156 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
90a4b3ee 2157 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 2158 gROOT->ProcessLine(line);
2159 }
2160 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2161 cont->SetFile(f);
2162 // Cd to file
2163 f->cd();
2164 // Check for a folder request
2165 TString dir = cont->GetFolderName();
2166 if (!dir.IsNull()) {
2167 if (!f->GetDirectory(dir)) f->mkdir(dir);
2168 f->cd(dir);
2169 }
2170 return f;
2171 }
2172 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2173 cont->SetFile(NULL);
2174 return NULL;
8d7d3b59 2175}
2176
2177//______________________________________________________________________________
d3106602 2178void AliAnalysisManager::ExecAnalysis(Option_t *option)
2179{
2180// Execute analysis.
cd463514 2181 static Long64_t nentries = 0;
1f04b637 2182 static TTree *lastTree = 0;
cd463514 2183 static TStopwatch *timer = new TStopwatch();
20b7268e 2184 // Only the first call to Process will trigger a true Notify. Other Notify
2185 // coming before is ignored.
2186 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2187 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2188 Notify();
2189 }
e9247450 2190 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
cd463514 2191 else {
1f04b637 2192 if (fTree && (fTree != lastTree)) {
2193 nentries += fTree->GetEntries();
2194 lastTree = fTree;
2195 }
e9247450 2196 if (!fNcalls) timer->Start();
f03a8355 2197 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
cd463514 2198 }
ec5acdce 2199 fIOTimer->Start(kTRUE);
57756ec5 2200 gROOT->cd();
cd463514 2201 TDirectory *cdir = gDirectory;
8c0ab8e8 2202 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
e9247450 2203 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
327eaf46 2204 if (!fInitOK) {
57756ec5 2205 Error("ExecAnalysis", "Analysis manager was not initialized !");
2f0e656b 2206 if (cdir) cdir->cd();
327eaf46 2207 return;
57756ec5 2208 }
e9247450 2209 fNcalls++;
d3106602 2210 AliAnalysisTask *task;
327eaf46 2211 // Check if the top tree is active.
2212 if (fTree) {
e9247450 2213 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2214 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
327eaf46 2215 TIter next(fTasks);
2216 // De-activate all tasks
2217 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 2218 AliAnalysisDataContainer *cont = fCommonInput;
2219 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 2220 if (!cont) {
c52c2132 2221 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2f0e656b 2222 if (cdir) cdir->cd();
327eaf46 2223 return;
2224 }
2225 cont->SetData(fTree); // This will notify all consumers
57756ec5 2226 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 2227//
c3701689 2228// Call BeginEvent() for optional input/output and MC services
ed97dc98 2229 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2230 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2231 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 2232 gROOT->cd();
e9247450 2233 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2234 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
6bb2b24f 2235//
2236// Execute the tasks
276941c8 2237// TIter next1(cont->GetConsumers());
ec5acdce 2238 fIOTimer->Stop();
2239 fIOTime += fIOTimer->RealTime();
2240 fCPUTimer->Start(kTRUE);
276941c8 2241 TIter next1(fTopTasks);
096b5a2e 2242 Int_t itask = 0;
327eaf46 2243 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 2244 if (fDebug >1) {
2245 cout << " Executing task " << task->GetName() << endl;
ed37a9ae 2246 }
2247 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
327eaf46 2248 task->ExecuteTask(option);
ed37a9ae 2249 if (fStatistics) fStatistics->StopTimer();
57756ec5 2250 gROOT->cd();
e9247450 2251 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2252 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
096b5a2e 2253 itask++;
327eaf46 2254 }
ec5acdce 2255 fCPUTimer->Stop();
2256 fCPUTime += fCPUTimer->RealTime();
2257 fIOTimer->Start(kTRUE);
6bb2b24f 2258//
2259// Call FinishEvent() for optional output and MC services
6073f8c9 2260 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 2261 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2262 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 2263 // Gather system information if requested
e9247450 2264 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2265 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2f0e656b 2266 if (cdir) cdir->cd();
ec5acdce 2267 fIOTimer->Stop();
2268 fIOTime += fIOTimer->RealTime();
327eaf46 2269 return;
2270 }
2271 // The event loop is not controlled by TSelector
6bb2b24f 2272//
c3701689 2273// Call BeginEvent() for optional input/output and MC services
ec5acdce 2274 fIOTimer->Start(kTRUE);
ed97dc98 2275 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2276 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2277 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
ec5acdce 2278 fIOTimer->Stop();
2279 fIOTime += fIOTimer->RealTime();
57756ec5 2280 gROOT->cd();
e9247450 2281 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2282 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
ec5acdce 2283 fCPUTimer->Start(kTRUE);
327eaf46 2284 TIter next2(fTopTasks);
2285 while ((task=(AliAnalysisTask*)next2())) {
2286 task->SetActive(kTRUE);
c52c2132 2287 if (fDebug > 1) {
2288 cout << " Executing task " << task->GetName() << endl;
2289 }
ed37a9ae 2290 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
d3106602 2291 task->ExecuteTask(option);
ed37a9ae 2292 if (fStatistics) fStatistics->StopTimer();
57756ec5 2293 gROOT->cd();
327eaf46 2294 }
ec5acdce 2295 fCPUTimer->Stop();
2296 fCPUTime += fCPUTimer->RealTime();
6bb2b24f 2297//
2298// Call FinishEvent() for optional output and MC services
ec5acdce 2299 fIOTimer->Start(kTRUE);
6073f8c9 2300 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2301 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 2302 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
e9247450 2303 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2304 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2f0e656b 2305 if (cdir) cdir->cd();
ec5acdce 2306 fIOTimer->Stop();
2307 fIOTime += fIOTimer->RealTime();
d3106602 2308}
2309
8ddad121 2310//______________________________________________________________________________
2311Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2312{
2313// Check if the stdout is connected to a pipe (C.Holm)
2314 Bool_t ispipe = kFALSE;
2315 out.seekp(0, std::ios_base::cur);
2316 if (out.fail()) {
2317 out.clear();
2318 if (errno == ESPIPE) ispipe = kTRUE;
2319 }
2320 return ispipe;
2321}
2322
d3106602 2323//______________________________________________________________________________
61505f8b 2324void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 2325{
2326// Set the input event handler and create a container for it.
59e0dcd5 2327 Changed();
60a04972 2328 fInputEventHandler = handler;
523aab8b 2329 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
60a04972 2330}
2331
2332//______________________________________________________________________________
61505f8b 2333void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 2334{
2335// Set the input event handler and create a container for it.
59e0dcd5 2336 Changed();
60a04972 2337 fOutputEventHandler = handler;
523aab8b 2338 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 2339 fCommonOutput->SetSpecialOutput();
60a04972 2340}
c07b9ce2 2341
f03a8355 2342//______________________________________________________________________________
2343void AliAnalysisManager::SetDebugLevel(UInt_t level)
2344{
2345// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2346 if (TObject::TestBit(kUseProgressBar)) {
2347 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2348 return;
2349 }
2350 fDebug = level;
2351}
2352
2353//______________________________________________________________________________
2354void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2355{
2356// Enable a text mode progress bar. Resets debug level to 0.
2357 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2358 TObject::SetBit(kUseProgressBar,flag);
2359 fPBUpdateFreq = freq;
2360 fDebug = 0;
2361}
2362
c07b9ce2 2363//______________________________________________________________________________
2364void AliAnalysisManager::RegisterExtraFile(const char *fname)
2365{
2366// This method is used externally to register output files which are not
2367// connected to any output container, so that the manager can properly register,
2368// retrieve or merge them when running in distributed mode. The file names are
2369// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 2370 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 2371 if (fExtraFiles.Length()) fExtraFiles += " ";
2372 fExtraFiles += fname;
2373}
2374
2375//______________________________________________________________________________
61505f8b 2376Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 2377{
2378// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 2379 char fullPath[512];
2380 char chUrl[512];
b3e07543 2381 char tmp[1024];
c07b9ce2 2382 TObject *pof = source->FindObject(filename);
2383 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2384 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2385 return kFALSE;
2386 }
b3e07543 2387 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2388 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
61505f8b 2389 TString clientUrl(chUrl);
2390 TString fullPath_str(fullPath);
c07b9ce2 2391 if (clientUrl.Contains("localhost")){
61505f8b 2392 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 2393 TObjString *strobj = ( TObjString *)array->At(1);
2394 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2395 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 2396 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2397 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2398 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 2399 delete arrayPort;
2400 delete array;
2401 }
b3e07543 2402 else if (clientUrl.Contains("__lite__")) {
2403 // Special case for ProofLite environement - get file info and copy.
2404 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2405 fullPath_str = Form("%s/%s", tmp, fullPath);
2406 }
c07b9ce2 2407 if (fDebug > 1)
b3e07543 2408 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
61505f8b 2409 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 2410 if (!gotit)
2411 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2412 return gotit;
2413}
d29168d6 2414
2415//______________________________________________________________________________
2416void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2417{
2418// Fill analysis type in the provided string.
2419 switch (fMode) {
2420 case kLocalAnalysis:
2421 type = "local";
2422 return;
2423 case kProofAnalysis:
2424 type = "proof";
2425 return;
2426 case kGridAnalysis:
2427 type = "grid";
2428 return;
2429 case kMixingAnalysis:
2430 type = "mix";
2431 }
2432}
923e2ca5 2433
2434//______________________________________________________________________________
2435Bool_t AliAnalysisManager::ValidateOutputFiles() const
2436{
2437// Validate all output files.
2438 TIter next(fOutputs);
2439 AliAnalysisDataContainer *output;
2440 TDirectory *cdir = gDirectory;
84fcd93f 2441 TString openedFiles;
923e2ca5 2442 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 2443 if (output->IsRegisterDataset()) continue;
923e2ca5 2444 TString filename = output->GetFileName();
2445 if (filename == "default") {
2446 if (!fOutputEventHandler) continue;
2447 filename = fOutputEventHandler->GetOutputFileName();
b3685485 2448 // Main AOD may not be there
2449 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 2450 }
2451 // Check if the file is closed
84fcd93f 2452 if (openedFiles.Contains(filename)) continue;;
923e2ca5 2453 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2454 if (file) {
2455 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 2456 // Clear file list to release object ownership to user.
160e7161 2457// file->Clear();
923e2ca5 2458 file->Close();
2459 }
2460 file = TFile::Open(filename);
2461 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2462 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2f0e656b 2463 if (cdir) cdir->cd();
923e2ca5 2464 return kFALSE;
2465 }
2466 file->Close();
84fcd93f 2467 openedFiles += filename;
2468 openedFiles += " ";
923e2ca5 2469 }
2f0e656b 2470 if (cdir) cdir->cd();
923e2ca5 2471 return kTRUE;
2472}
cd11251e 2473
2474//______________________________________________________________________________
61505f8b 2475void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 2476{
2477// Implements a nice text mode progress bar.
2478 static Long64_t icount = 0;
2479 static TString oname;
2480 static TString nname;
2481 static Long64_t ocurrent = 0;
2482 static Long64_t osize = 0;
2483 static Int_t oseconds = 0;
2484 static TStopwatch *owatch = 0;
2485 static Bool_t oneoftwo = kFALSE;
2486 static Int_t nrefresh = 0;
2487 static Int_t nchecks = 0;
8ddad121 2488 static char lastChar = 0;
f03a8355 2489 const char symbol[4] = {'-','\\','|','/'};
cd11251e 2490
8ddad121 2491 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
cd11251e 2492 if (!refresh) {
2493 nrefresh = 0;
2494 if (!size) return;
2495 owatch = watch;
2496 oname = opname;
2497 ocurrent = TMath::Abs(current);
2498 osize = TMath::Abs(size);
2499 if (ocurrent > osize) ocurrent=osize;
2500 } else {
2501 nrefresh++;
2502 if (!osize) return;
2503 }
f03a8355 2504 if ((current % fPBUpdateFreq) != 0) return;
cd11251e 2505 icount++;
f03a8355 2506 char progress[11] = " ";
2507 Int_t ichar = icount%4;
cd11251e 2508 Double_t time = 0.;
2509 Int_t hours = 0;
2510 Int_t minutes = 0;
2511 Int_t seconds = 0;
2512 if (owatch && !last) {
2513 owatch->Stop();
2514 time = owatch->RealTime();
f03a8355 2515 seconds = int(time) % 60;
2516 minutes = (int(time) / 60) % 60;
2517 hours = (int(time) / 60 / 60);
cd11251e 2518 if (refresh) {
2519 if (oseconds==seconds) {
2520 owatch->Continue();
2521 return;
2522 }
2523 oneoftwo = !oneoftwo;
2524 }
2525 oseconds = seconds;
2526 }
2527 if (refresh && oneoftwo) {
2528 nname = oname;
2529 if (nchecks <= 0) nchecks = nrefresh+1;
2530 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2531 oname = Form(" == %d%% ==", pctdone);
2532 }
2533 Double_t percent = 100.0*ocurrent/osize;
2534 Int_t nchar = Int_t(percent/10);
2535 if (nchar>10) nchar=10;
2536 Int_t i;
2537 for (i=0; i<nchar; i++) progress[i] = '=';
2538 progress[nchar] = symbol[ichar];
2539 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2540 progress[10] = '\0';
2541 oname += " ";
2542 oname.Remove(20);
2543 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2544 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2545 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
f03a8355 2546 if (time>0.) {
2547 Int_t full = Int_t(ocurrent > 0 ?
2548 time * (float(osize)/ocurrent) + .5 :
2549 99*3600+59*60+59);
499b6d5d 2550 Int_t remain = Int_t(full - time);
f03a8355 2551 Int_t rsec = remain % 60;
2552 Int_t rmin = (remain / 60) % 60;
2553 Int_t rhour = (remain / 60 / 60);
8ddad121 2554 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2555 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
f03a8355 2556 }
8ddad121 2557 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
cd11251e 2558 if (refresh && oneoftwo) oname = nname;
2559 if (owatch) owatch->Continue();
2560 if (last) {
2561 icount = 0;
2562 owatch = 0;
2563 ocurrent = 0;
2564 osize = 0;
2565 oseconds = 0;
2566 oneoftwo = kFALSE;
2567 nrefresh = 0;
2568 fprintf(stderr, "\n");
2569 }
2570}
012e169c 2571
2572//______________________________________________________________________________
2573void AliAnalysisManager::DoLoadBranch(const char *name)
2574{
2575 // Get tree and load branch if needed.
c5734a4b 2576 static Long64_t crtEntry = -100;
012e169c 2577
7acc5b9d 2578 if (fAutoBranchHandling || !fTree)
012e169c 2579 return;
2580
2581 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2582 if (!br) {
2583 br = fTree->GetBranch(name);
2584 if (!br) {
979e448a 2585 Error("DoLoadBranch", "Could not find branch %s",name);
012e169c 2586 return;
2587 }
2588 fTable.Add(br);
2589 }
c5734a4b 2590 if (br->GetReadEntry()==fCurrentEntry) return;
9162405c 2591 Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2592 if (readbytes<0) {
f5cbe261 2593 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
c5734a4b 2594 if (crtEntry != fCurrentEntry) {
2595 CountEvent(1,0,1,0);
2596 crtEntry = fCurrentEntry;
2597 }
2598 } else {
2599 if (crtEntry != fCurrentEntry) {
2600 CountEvent(1,1,0,0);
2601 crtEntry = fCurrentEntry;
2602 }
f5cbe261 2603 }
012e169c 2604}
e9247450 2605
f5cbe261 2606//______________________________________________________________________________
c3732d79 2607void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
f5cbe261 2608{
2609// Add the statistics task to the manager.
2610 if (fStatistics) {
2611 Info("AddStatisticsTask", "Already added");
2612 return;
c3732d79 2613 }
2614 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2615 gROOT->ProcessLine(line);
f5cbe261 2616}
2617
2618//______________________________________________________________________________
2619void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2620{
2621// Bookkeep current event;
2622 if (!fStatistics) return;
2623 fStatistics->AddInput(ninput);
2624 fStatistics->AddProcessed(nprocessed);
2625 fStatistics->AddFailed(nfailed);
2626 fStatistics->AddAccepted(naccepted);
2627}
2628
e9247450 2629//______________________________________________________________________________
2630void AliAnalysisManager::AddStatisticsMsg(const char *line)
2631{
2632// Add a line in the statistics message. If available, the statistics message is written
2633// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2634// on the client.
2635 if (!strlen(line)) return;
2636 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2637 fStatisticsMsg += line;
2638}
2639
2640//______________________________________________________________________________
a99b2241 2641void AliAnalysisManager::WriteStatisticsMsg(Int_t)
e9247450 2642{
23a74fb4 2643// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
c3732d79 2644 static Bool_t done = kFALSE;
2645 if (done) return;
2646 done = kTRUE;
e296c79c 2647 if (!fStatistics) return;
e9247450 2648 ofstream out;
e296c79c 2649 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2650 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2651 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2652 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2653 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2654 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2655 fStatistics->GetNaccepted()), ios::out);
2656 out << fStatisticsMsg << endl;
e9247450 2657 out.close();
2658}
37196805 2659
2660//______________________________________________________________________________
2661const char* AliAnalysisManager::GetOADBPath()
2662{
2663// returns the path of the OADB
2664// this static function just depends on environment variables
2665
2666 static TString oadbPath;
2667
2668 if (gSystem->Getenv("OADB_PATH"))
2669 oadbPath = gSystem->Getenv("OADB_PATH");
2670 else if (gSystem->Getenv("ALICE_ROOT"))
2671 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2672 else
0a9cc013 2673 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
37196805 2674
2675 return oadbPath;
2676}
77dad4a9 2677
2678//______________________________________________________________________________
2679void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2680{
2681// Define a custom string variable mapped to a global unique name. The variable
2682// can be then retrieved by a given analysis macro via GetGlobalStr(key).
2683 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2684 if (!mgr) {
2685 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2686 return;
2687 }
2688 Bool_t valid = kFALSE;
2689 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2690 if (valid) {
2691 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2692 return;
2693 }
2694 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2695}
2696
2697//______________________________________________________________________________
2698const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2699{
2700// Static method to retrieve a global variable defined via SetGlobalStr.
2701 valid = kFALSE;
2702 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2703 if (!mgr) return 0;
2704 TObject *value = mgr->GetGlobals()->GetValue(key);
2705 if (!value) return 0;
2706 valid = kTRUE;
2707 return value->GetName();
2708}
2709
2710//______________________________________________________________________________
2711void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2712{
2713// Define a custom integer variable mapped to a global unique name. The variable
2714// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2715 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2716 if (!mgr) {
2717 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2718 return;
2719 }
2720 Bool_t valid = kFALSE;
2721 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2722 if (valid) {
2723 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2724 return;
2725 }
2726 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2727}
2728
2729//______________________________________________________________________________
2730Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2731{
2732// Static method to retrieve a global variable defined via SetGlobalInt.
2733 valid = kFALSE;
2734 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2735 if (!mgr) return 0;
2736 TObject *value = mgr->GetGlobals()->GetValue(key);
2737 if (!value) return 0;
2738 valid = kTRUE;
2739 TString s = value->GetName();
2740 return s.Atoi();
2741}
2742
2743//______________________________________________________________________________
2744void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2745{
2746// Define a custom double precision variable mapped to a global unique name. The variable
2747// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2748 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2749 if (!mgr) {
2750 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2751 return;
2752 }
2753 Bool_t valid = kFALSE;
2754 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2755 if (valid) {
2756 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2757 return;
2758 }
2759 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2760}
2761
2762//______________________________________________________________________________
2763Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2764{
2765// Static method to retrieve a global variable defined via SetGlobalDbl.
2766 valid = kFALSE;
2767 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2768 if (!mgr) return 0;
2769 TObject *value = mgr->GetGlobals()->GetValue(key);
2770 if (!value) return 0;
2771 valid = kTRUE;
2772 TString s = value->GetName();
2773 return s.Atof();
2774}
6f3e07d8 2775
2776//______________________________________________________________________________
2777void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2778{
2779// Sets Class debug level
2780
2781 if (!fDebugOptions) {
2782 fDebugOptions = new TObjArray();
2783 fDebugOptions->SetOwner(kTRUE);
2784 }
2785
6f3e07d8 2786 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2787 if (!debugOpt) {
e8b43383 2788 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel,className).Data());
6f3e07d8 2789 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2790 } else {
2791 TString oldDebugStr = debugOpt->GetTitle();
2792 Int_t oldDebug = oldDebugStr.Atoi();
2793 if (debugLevel > oldDebug) {
e8b43383 2794 AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel,className,oldDebug).Data());
6f3e07d8 2795 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2796 } else {
e8b43383 2797 AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel,className,oldDebug).Data());
6f3e07d8 2798 }
2799 }
2800}
2801
2802//______________________________________________________________________________
2803void AliAnalysisManager::ApplyDebugOptions()
2804{
2805// Apply debug options
2806
2807 if (!fDebugOptions) return;
2808
2809 TIter next(fDebugOptions);
2810 TNamed *debug;
2811 TString debugLevel;
2812 while ((debug=dynamic_cast<TNamed*>(next()))) {
2813 debugLevel = debug->GetTitle();
e8b43383 2814 AliInfo(TString::Format("Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()).Data());
6f3e07d8 2815 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2816 }
2817}
2818
c1b9ddb5 2819//______________________________________________________________________________
2820Bool_t AliAnalysisManager::IsMacroLoaded(const char filename)
2821{
2822// Check if a macro was loaded.
2823 return fgMacroNames.Contains(filename);
2824}
2825
2826//______________________________________________________________________________
2827Int_t AliAnalysisManager::LoadMacro(const char *filename, Int_t *error, Bool_t check)
2828{
2829// Redirection of gROOT->LoadMacro which makes sure the same macro is not loaded
2830// twice
2831 TString macroName = gSystem->BaseName(filename);
2832 // Strip appended +, ++, +g, +O
2833 Int_t index = macroName.Index("+");
2834 if (index>0) macroName.Remove(index);
2835 if (fgMacroNames.Contains(macroName)) {
2836 // Macro with the same name loaded already in this root session, do
2837 // nothing
2838 error = 0;
2839 return 0;
2840 }
2841 Int_t ret = gROOT->LoadMacro(filename,error,check);
2842 // In case of error return the error code
2843 if (ret) return ret;
2844 // Append the macro name to the loaded macros list
2845 fgMacroNames += macroName;
2846 fgMacroNames += " ";
2847 return ret;
2848}
2849
59e0dcd5 2850//______________________________________________________________________________
2851void AliAnalysisManager::Lock()
2852{
2853// Security lock. This is to detect NORMAL user errors and not really to
2854// protect against intentional hacks.
2855 if (fLocked) return;
2856 fLocked = kTRUE;
2857 if (fInputEventHandler) fInputEventHandler->Lock();
2858 if (fOutputEventHandler) fOutputEventHandler->Lock();
2859 if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2860 Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2861}
2862
2863//______________________________________________________________________________
2864void AliAnalysisManager::UnLock()
2865{
2866// Verbose unlocking. Hackers will be punished ;-) ...
2867 if (!fLocked) return;
2868 fLocked = kFALSE;
2869 if (fInputEventHandler) fInputEventHandler->UnLock();
2870 if (fOutputEventHandler) fOutputEventHandler->UnLock();
2871 if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2872 Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2873}
2874
2875//______________________________________________________________________________
2876void AliAnalysisManager::Changed()
2877{
2878// All critical setters pass through the Changed method that throws an exception
2879// in case the lock was set.
2880 if (fLocked) Fatal("Changed","Critical setter called in locked mode");
2881}