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