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