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