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