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