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