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