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