Fixed error when copying output files coming from PROOF analysis in GRID
[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();
968 while ((output=(AliAnalysisDataContainer*)next1())) {
969 // Close all files at output
970 TDirectory *opwd = gDirectory;
f5e61abd 971 if (output->GetFile()) {
f3c07fbd 972 // Clear file list to release object ownership to user.
160e7161 973// output->GetFile()->Clear();
f5e61abd 974 output->GetFile()->Close();
975 // Copy merged outputs in alien if requested
976 if (fSpecialOutputLocation.Length() &&
977 fSpecialOutputLocation.BeginsWith("alien://")) {
978 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
77dad4a9 979 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
f5e61abd 980 TFile::Cp(output->GetFile()->GetName(),
981 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
982 }
77dad4a9 983 output->SetFile(NULL);
f5e61abd 984 }
8d7d3b59 985 if (opwd) opwd->cd();
8c0ab8e8 986 }
6cd44ee0 987 delete allOutputs;
e9247450 988 //Write statistics information on the client
e296c79c 989 if (fStatistics) WriteStatisticsMsg(fNcalls);
8c0ab8e8 990 if (getsysInfo) {
b6db1d18 991 TDirectory *crtdir = gDirectory;
8c0ab8e8 992 TFile f("syswatch.root", "RECREATE");
096b5a2e 993 TH1 *hist;
994 TString cut;
8c0ab8e8 995 if (!f.IsZombie()) {
996 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
096b5a2e 997 tree->SetName("syswatch");
8c0ab8e8 998 tree->SetMarkerStyle(kCircle);
999 tree->SetMarkerColor(kBlue);
1000 tree->SetMarkerSize(0.5);
1001 if (!gROOT->IsBatch()) {
1002 tree->SetAlias("event", "id0");
096b5a2e 1003 tree->SetAlias("task", "id1");
1004 tree->SetAlias("stage", "id2");
1005 // Already defined aliases
1006 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1007 // tree->SetAlias("T","stampSec-first");
1008 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1009 // tree->SetAlias("VM","pI.fMemVirtual");
1010 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1011 Int_t npads = 1 /*COO plot for all tasks*/ +
1012 fTopTasks->GetEntries() /*Exec plot per task*/ +
1013 1 /*Terminate plot for all tasks*/ +
1014 1; /*vm plot*/
1015
1016 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1017 if (npads<iopt*(iopt+1))
1018 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1019 else
1020 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1021 Int_t ipad = 1;
1022 // draw the plot of deltaVM for Exec for each task
779e9992 1023 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
096b5a2e 1024 task = (AliAnalysisTask*)fTopTasks->At(itask);
1025 canvas->cd(ipad++);
1026 cut = Form("task==%d && stage==1", itask);
1027 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1028 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1029 if (hist) {
084c84df 1030 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
b3e07543 1031 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1032 }
1033 }
1034 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1035 canvas->cd(ipad++);
1036 tree->SetMarkerStyle(kFullTriangleUp);
1037 tree->SetMarkerColor(kRed);
1038 tree->SetMarkerSize(0.8);
1039 cut = "task>=0 && task<1000 && stage==0";
1040 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1041 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1042 if (hist) {
1043 hist->SetTitle("Memory in CreateOutputObjects()");
b3e07543 1044 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1045 hist->GetXaxis()->SetTitle("task");
1046 }
1047 // draw the plot of deltaVM for Terminate for all tasks
1048 canvas->cd(ipad++);
1049 tree->SetMarkerStyle(kOpenSquare);
1050 tree->SetMarkerColor(kMagenta);
1051 cut = "task>=0 && task<1000 && stage==2";
1052 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1053 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1054 if (hist) {
1055 hist->SetTitle("Memory in Terminate()");
b3e07543 1056 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1057 hist->GetXaxis()->SetTitle("task");
1058 }
1059 // Full VM profile
1060 canvas->cd(ipad++);
1061 tree->SetMarkerStyle(kFullCircle);
1062 tree->SetMarkerColor(kGreen);
1063 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1064 tree->Draw("VM:event",cut,"", 1234567890, 0);
1065 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1066 if (hist) {
1067 hist->SetTitle("Virtual memory");
b3e07543 1068 hist->GetYaxis()->SetTitle("VM [MB]");
096b5a2e 1069 }
1070 canvas->Modified();
8c0ab8e8 1071 }
096b5a2e 1072 tree->SetMarkerStyle(kCircle);
1073 tree->SetMarkerColor(kBlue);
1074 tree->SetMarkerSize(0.5);
8c0ab8e8 1075 tree->Write();
1076 f.Close();
1077 delete tree;
1078 }
b6db1d18 1079 if (crtdir) crtdir->cd();
923e2ca5 1080 }
1081 // Validate the output files
f62a0e4c 1082 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
923e2ca5 1083 ofstream out;
1084 out.open("outputs_valid", ios::out);
1085 out.close();
57756ec5 1086 }
1087 cdir->cd();
cd463514 1088 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 1089}
096b5a2e 1090//______________________________________________________________________________
1091void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1092{
1093// Profiles the task having the itop index in the list of top (first level) tasks.
1094 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1095 if (!task) {
1096 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1097 return;
1098 }
1099 ProfileTask(task->GetName(), option);
1100}
1101
1102//______________________________________________________________________________
1103void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1104{
1105// Profile a managed task after the execution of the analysis in case NSysInfo
1106// was used.
1107 if (gSystem->AccessPathName("syswatch.root")) {
1108 Error("ProfileTask", "No file syswatch.root found in the current directory");
1109 return;
1110 }
1111 if (gROOT->IsBatch()) return;
1112 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1113 if (!task) {
1114 Error("ProfileTask", "No top task named %s known by the manager.", name);
1115 return;
1116 }
1117 Int_t itop = fTopTasks->IndexOf(task);
1118 Int_t itask = fTasks->IndexOf(task);
1119 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1120 TDirectory *cdir = gDirectory;
1121 TFile f("syswatch.root");
1122 TTree *tree = (TTree*)f.Get("syswatch");
1123 if (!tree) {
1124 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1125 return;
1126 }
cd463514 1127 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
096b5a2e 1128 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1129 canvas->Divide(2, 2, 0.01, 0.01);
1130 Int_t ipad = 1;
1131 TString cut;
1132 TH1 *hist;
1133 // VM profile for COO and Terminate methods
1134 canvas->cd(ipad++);
1135 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1136 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1137 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1138 if (hist) {
084c84df 1139 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1140 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1141 hist->GetXaxis()->SetTitle("method");
1142 }
1143 // CPU profile per event
1144 canvas->cd(ipad++);
1145 cut = Form("task==%d && stage==1",itop);
1146 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1147 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1148 if (hist) {
1149 hist->SetTitle("Execution time per event");
1150 hist->GetYaxis()->SetTitle("CPU/event [s]");
1151 }
1152 // VM profile for Exec
1153 canvas->cd(ipad++);
1154 cut = Form("task==%d && stage==1",itop);
1155 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1156 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1157 if (hist) {
084c84df 1158 hist->SetTitle("Alocated VM[MB] per event");
1159 hist->GetYaxis()->SetTitle("deltaVM [MB]");
096b5a2e 1160 }
1161 canvas->Modified();
1162 delete tree;
1163 f.Close();
1164 if (cdir) cdir->cd();
1165}
d3106602 1166
1167//______________________________________________________________________________
1168void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1169{
1170// Adds a user task to the global list of tasks.
21ca8e59 1171 if (fInitOK) {
1172 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1173 return;
1174 }
1175
8d7d3b59 1176 if (fTasks->FindObject(task)) {
1177 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1178 return;
1179 }
d3106602 1180 task->SetActive(kFALSE);
1181 fTasks->Add(task);
1182}
1183
1184//______________________________________________________________________________
1185AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1186{
1187// Retreive task by name.
1188 if (!fTasks) return NULL;
1189 return (AliAnalysisTask*)fTasks->FindObject(name);
1190}
1191
1192//______________________________________________________________________________
1193AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 1194 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 1195{
1196// Create a data container of a certain type. Types can be:
84fcd93f 1197// kExchangeContainer = 0, used to exchange data between tasks
d3106602 1198// kInputContainer = 1, used to store input data
84fcd93f 1199// kOutputContainer = 2, used for writing result to a file
1200// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1201// the output object to a folder inside the output file
b1310ef5 1202 if (fContainers->FindObject(name)) {
923e2ca5 1203 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 1204 return NULL;
1205 }
d3106602 1206 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1207 fContainers->Add(cont);
1208 switch (type) {
1209 case kInputContainer:
1210 fInputs->Add(cont);
1211 break;
1212 case kOutputContainer:
1213 fOutputs->Add(cont);
8c0ab8e8 1214 if (filename && strlen(filename)) {
1215 cont->SetFileName(filename);
6cd44ee0 1216 cont->SetDataOwned(kFALSE); // data owned by the file
1217 }
1218 break;
1219 case kParamContainer:
1220 fParamCont->Add(cont);
1221 if (filename && strlen(filename)) {
1222 cont->SetFileName(filename);
8c0ab8e8 1223 cont->SetDataOwned(kFALSE); // data owned by the file
1224 }
d3106602 1225 break;
c52c2132 1226 case kExchangeContainer:
d3106602 1227 break;
1228 }
1229 return cont;
1230}
1231
1232//______________________________________________________________________________
1233Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1234 AliAnalysisDataContainer *cont)
1235{
1236// Connect input of an existing task to a data container.
60a04972 1237 if (!task) {
1238 Error("ConnectInput", "Task pointer is NULL");
1239 return kFALSE;
1240 }
d3106602 1241 if (!fTasks->FindObject(task)) {
1242 AddTask(task);
8d7d3b59 1243 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 1244 }
1245 Bool_t connected = task->ConnectInput(islot, cont);
1246 return connected;
1247}
1248
1249//______________________________________________________________________________
1250Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1251 AliAnalysisDataContainer *cont)
1252{
1253// Connect output of an existing task to a data container.
60a04972 1254 if (!task) {
1255 Error("ConnectOutput", "Task pointer is NULL");
1256 return kFALSE;
1257 }
d3106602 1258 if (!fTasks->FindObject(task)) {
1259 AddTask(task);
c52c2132 1260 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 1261 }
1262 Bool_t connected = task->ConnectOutput(islot, cont);
1263 return connected;
1264}
1265
1266//______________________________________________________________________________
1267void AliAnalysisManager::CleanContainers()
1268{
1269// Clean data from all containers that have already finished all client tasks.
1270 TIter next(fContainers);
1271 AliAnalysisDataContainer *cont;
1272 while ((cont=(AliAnalysisDataContainer *)next())) {
1273 if (cont->IsOwnedData() &&
1274 cont->IsDataReady() &&
1275 cont->ClientsExecuted()) cont->DeleteData();
1276 }
1277}
1278
1279//______________________________________________________________________________
1280Bool_t AliAnalysisManager::InitAnalysis()
1281{
1282// Initialization of analysis chain of tasks. Should be called after all tasks
1283// and data containers are properly connected
923e2ca5 1284 // Reset flag and remove valid_outputs file if exists
21ca8e59 1285 if (fInitOK) return kTRUE;
923e2ca5 1286 if (!gSystem->AccessPathName("outputs_valid"))
1287 gSystem->Unlink("outputs_valid");
d3106602 1288 // Check for top tasks (depending only on input data containers)
1289 if (!fTasks->First()) {
c52c2132 1290 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 1291 return kFALSE;
1292 }
1293 TIter next(fTasks);
1294 AliAnalysisTask *task;
1295 AliAnalysisDataContainer *cont;
1296 Int_t ntop = 0;
1297 Int_t nzombies = 0;
327eaf46 1298 Bool_t iszombie = kFALSE;
1299 Bool_t istop = kTRUE;
d3106602 1300 Int_t i;
1301 while ((task=(AliAnalysisTask*)next())) {
327eaf46 1302 istop = kTRUE;
1303 iszombie = kFALSE;
d3106602 1304 Int_t ninputs = task->GetNinputs();
d3106602 1305 for (i=0; i<ninputs; i++) {
1306 cont = task->GetInputSlot(i)->GetContainer();
1307 if (!cont) {
327eaf46 1308 if (!iszombie) {
d3106602 1309 task->SetZombie();
1310 fZombies->Add(task);
1311 nzombies++;
327eaf46 1312 iszombie = kTRUE;
d3106602 1313 }
c52c2132 1314 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1315 i, task->GetName());
d3106602 1316 }
327eaf46 1317 if (iszombie) continue;
d3106602 1318 // Check if cont is an input container
327eaf46 1319 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 1320 // Connect to parent task
1321 }
327eaf46 1322 if (istop) {
d3106602 1323 ntop++;
1324 fTopTasks->Add(task);
1325 }
1326 }
1327 if (!ntop) {
c52c2132 1328 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 1329 return kFALSE;
1330 }
1331 // Check now if there are orphan tasks
1332 for (i=0; i<ntop; i++) {
1333 task = (AliAnalysisTask*)fTopTasks->At(i);
1334 task->SetUsed();
1335 }
1336 Int_t norphans = 0;
1337 next.Reset();
1338 while ((task=(AliAnalysisTask*)next())) {
1339 if (!task->IsUsed()) {
1340 norphans++;
c52c2132 1341 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 1342 }
1343 }
1344 // Check the task hierarchy (no parent task should depend on data provided
1345 // by a daughter task)
1346 for (i=0; i<ntop; i++) {
1347 task = (AliAnalysisTask*)fTopTasks->At(i);
1348 if (task->CheckCircularDeps()) {
c52c2132 1349 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 1350 PrintStatus("dep");
1351 return kFALSE;
1352 }
1353 }
b1310ef5 1354 // Check that all containers feeding post-event loop tasks are in the outputs list
1355 TIter nextcont(fContainers); // loop over all containers
1356 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1357 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1358 if (cont->HasConsumers()) {
1359 // Check if one of the consumers is post event loop
1360 TIter nextconsumer(cont->GetConsumers());
1361 while ((task=(AliAnalysisTask*)nextconsumer())) {
1362 if (task->IsPostEventLoop()) {
1363 fOutputs->Add(cont);
1364 break;
1365 }
1366 }
1367 }
1368 }
1369 }
8d7d3b59 1370 // Check if all special output containers have a file name provided
1371 TIter nextout(fOutputs);
1372 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1373 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1374 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1375 return kFALSE;
1376 }
7acc5b9d 1377 }
1378 // Initialize requested branch list if needed
1379 if (!fAutoBranchHandling) {
1380 next.Reset();
1381 while ((task=(AliAnalysisTask*)next())) {
1382 if (!task->HasBranches()) {
1383 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\"",
1384 task->GetName(), task->ClassName());
1385 return kFALSE;
1386 }
1387 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1388 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1389 return kFALSE;
1390 }
1391 TString taskbranches;
1392 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1393 if (taskbranches.IsNull()) {
1394 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1395 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1396 return kFALSE;
1397 }
1398 AddBranches(taskbranches);
1399 }
1400 }
327eaf46 1401 fInitOK = kTRUE;
d3106602 1402 return kTRUE;
1403}
1404
1405//______________________________________________________________________________
7acc5b9d 1406void AliAnalysisManager::AddBranches(const char *branches)
1407{
1408// Add branches to the existing fRequestedBranches.
1409 TString br(branches);
1410 TObjArray *arr = br.Tokenize(",");
1411 TIter next(arr);
1412 TObject *obj;
1413 while ((obj=next())) {
1414 if (!fRequestedBranches.Contains(obj->GetName())) {
1415 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1416 fRequestedBranches += obj->GetName();
1417 }
1418 }
dcc1f876 1419 delete arr;
7acc5b9d 1420}
1421
1422//______________________________________________________________________________
1423void AliAnalysisManager::CheckBranches(Bool_t load)
1424{
1425// The method checks the input branches to be loaded during the analysis.
1426 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1427 TObjArray *arr = fRequestedBranches.Tokenize(",");
1428 TIter next(arr);
1429 TObject *obj;
1430 while ((obj=next())) {
1431 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1432 if (!br) {
1433 br = fTree->GetBranch(obj->GetName());
1434 if (!br) {
1435 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1436 continue;
1437 }
1438 }
1439 fTable.Add(br);
1440 if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry());
1441 }
dcc1f876 1442 delete arr;
7acc5b9d 1443}
1444
1445//______________________________________________________________________________
4747b4a7 1446Bool_t AliAnalysisManager::CheckTasks() const
1447{
1448// Check consistency of tasks.
25c87093 1449 Int_t ntasks = fTasks->GetEntries();
1450 if (!ntasks) {
1451 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1452 return kFALSE;
1453 }
4747b4a7 1454 // Get the pointer to AliAnalysisTaskSE::Class()
1455 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1456 // Loop all tasks to check if their corresponding library was loaded
1457 TIter next(fTasks);
1458 TObject *obj;
1459 while ((obj=next())) {
1460 if (obj->IsA() == badptr) {
1461 Error("CheckTasks", "##################\n \
1462 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1463 return kFALSE;
1464 }
1465 }
1466 return kTRUE;
1467}
1468
1469//______________________________________________________________________________
d3106602 1470void AliAnalysisManager::PrintStatus(Option_t *option) const
1471{
1472// Print task hierarchy.
8c0ab8e8 1473 if (!fInitOK) {
1474 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1475 return;
1476 }
1477 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1478 if (getsysInfo)
1479 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1480 TIter next(fTopTasks);
1481 AliAnalysisTask *task;
1482 while ((task=(AliAnalysisTask*)next()))
1483 task->PrintTask(option);
dcc1f876 1484
7acc5b9d 1485 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1486 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
dcc1f876 1487
1488 TString sopt(option);
1489 sopt.ToUpper();
1490
1491 if (sopt.Contains("ALL"))
1492 {
1493 if ( fOutputEventHandler )
1494 {
1495 cout << TString('_',78) << endl;
1496 cout << "OutputEventHandler:" << endl;
1497 fOutputEventHandler->Print(" ");
1498 }
1499 }
d3106602 1500}
1501
1502//______________________________________________________________________________
1503void AliAnalysisManager::ResetAnalysis()
1504{
1505// Reset all execution flags and clean containers.
1506 CleanContainers();
1507}
1508
1509//______________________________________________________________________________
27734f0e 1510Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1511{
1512// Start analysis having a grid handler.
1513 if (!fGridHandler) {
1514 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1515 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1516 return -1;
1517 }
1518 TTree *tree = NULL;
1519 return StartAnalysis(type, tree, nentries, firstentry);
1520}
1521
1522//______________________________________________________________________________
61505f8b 1523Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1524{
aee5ee44 1525// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1526// MIX. Process nentries starting from firstentry
bf574918 1527 Long64_t retv = 0;
57756ec5 1528 // Backup current directory and make sure gDirectory points to gROOT
1529 TDirectory *cdir = gDirectory;
1530 gROOT->cd();
c52c2132 1531 if (!fInitOK) {
1532 Error("StartAnalysis","Analysis manager was not initialized !");
57756ec5 1533 cdir->cd();
1f87e9fb 1534 return -1;
c52c2132 1535 }
4747b4a7 1536 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
20b7268e 1537 if (fDebug > 1) {
1538 printf("StartAnalysis %s\n",GetName());
1539 AliLog::SetGlobalLogLevel(AliLog::kInfo);
1540 }
f03a8355 1541 fMaxEntries = nentries;
8e1f0465 1542 fIsRemote = kFALSE;
c52c2132 1543 TString anaType = type;
1544 anaType.ToLower();
1545 fMode = kLocalAnalysis;
c57f56b7 1546 Bool_t runlocalinit = kTRUE;
90a4b3ee 1547 if (anaType.Contains("file")) {
1548 runlocalinit = kFALSE;
8e1f0465 1549 fIsRemote = kTRUE;
90a4b3ee 1550 }
4ab472d4 1551 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1552 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1553 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1554
c52c2132 1555 if (fMode == kGridAnalysis) {
8e1f0465 1556 fIsRemote = kTRUE;
f866cba5 1557 if (!anaType.Contains("terminate")) {
1558 if (!fGridHandler) {
1559 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1560 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
57756ec5 1561 cdir->cd();
f866cba5 1562 return -1;
1563 }
1564 // Write analysis manager in the analysis file
1565 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1566 // run local task configuration
1567 TIter nextTask(fTasks);
1568 AliAnalysisTask *task;
1569 while ((task=(AliAnalysisTask*)nextTask())) {
1570 task->LocalInit();
57756ec5 1571 gROOT->cd();
f866cba5 1572 }
1573 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1574 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
57756ec5 1575 cdir->cd();
f866cba5 1576 return -1;
1577 }
c57f56b7 1578
f866cba5 1579 // Terminate grid analysis
57756ec5 1580 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1581 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
f866cba5 1582 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1583 if (!fGridHandler->MergeOutputs()) {
1584 // Return if outputs could not be merged or if it alien handler
1585 // was configured for offline mode or local testing.
57756ec5 1586 cdir->cd();
f866cba5 1587 return 0;
1588 }
1589 }
1590 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
c57f56b7 1591 ImportWrappers(NULL);
1592 Terminate();
57756ec5 1593 cdir->cd();
1f87e9fb 1594 return 0;
981f2614 1595 }
ab5d25d8 1596 TString line;
efd53803 1597 SetEventLoop(kFALSE);
8d7d3b59 1598 // Enable event loop mode if a tree was provided
27734f0e 1599 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1600
8c0ab8e8 1601 TChain *chain = 0;
1602 TString ttype = "TTree";
4ab472d4 1603 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1604 chain = (TChain*)tree;
6b742510 1605 if (!chain || !chain->GetListOfFiles()->First()) {
1606 Error("StartAnalysis", "Cannot process null or empty chain...");
57756ec5 1607 cdir->cd();
1f87e9fb 1608 return -1;
6b742510 1609 }
8c0ab8e8 1610 ttype = "TChain";
1611 }
9b33830a 1612
096b5a2e 1613 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1614 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
aee5ee44 1615 // Initialize locally all tasks (happens for all modes)
9b33830a 1616 TIter next(fTasks);
1617 AliAnalysisTask *task;
c57f56b7 1618 if (runlocalinit) {
1619 while ((task=(AliAnalysisTask*)next())) {
1620 task->LocalInit();
57756ec5 1621 gROOT->cd();
c57f56b7 1622 }
096b5a2e 1623 if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
c57f56b7 1624 }
efd53803 1625
c52c2132 1626 switch (fMode) {
1627 case kLocalAnalysis:
27734f0e 1628 if (!tree && !fGridHandler) {
03a5cc9f 1629 TIter nextT(fTasks);
981f2614 1630 // Call CreateOutputObjects for all tasks
096b5a2e 1631 Int_t itask = 0;
979e448a 1632 Bool_t dirStatus = TH1::AddDirectoryStatus();
03a5cc9f 1633 while ((task=(AliAnalysisTask*)nextT())) {
979e448a 1634 TH1::AddDirectory(kFALSE);
c5a87c56 1635 task->CreateOutputObjects();
4747b4a7 1636 if (!task->CheckPostData()) {
1637 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1638 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1639 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1640 }
096b5a2e 1641 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
57756ec5 1642 gROOT->cd();
096b5a2e 1643 itask++;
c5a87c56 1644 }
979e448a 1645 TH1::AddDirectory(dirStatus);
06a59280 1646 if (IsExternalLoop()) {
1647 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1648 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1f87e9fb 1649 return 0;
57756ec5 1650 }
c52c2132 1651 ExecAnalysis();
981f2614 1652 Terminate();
1f87e9fb 1653 return 0;
c52c2132 1654 }
27734f0e 1655 fSelector = new AliAnalysisSelector(this);
1656 // Check if a plugin handler is used
1657 if (fGridHandler) {
1658 // Get the chain from the plugin
1659 TString dataType = "esdTree";
1660 if (fInputEventHandler) {
1661 dataType = fInputEventHandler->GetDataType();
1662 dataType.ToLower();
1663 dataType += "Tree";
1664 }
1665 chain = fGridHandler->GetChainForTestMode(dataType);
1666 if (!chain) {
1667 Error("StartAnalysis", "No chain for test mode. Aborting.");
1668 return -1;
1669 }
1670 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1671 retv = chain->Process(fSelector, "", nentries, firstentry);
1672 break;
1673 }
c52c2132 1674 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1675 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
bf574918 1676 retv = tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1677 break;
1678 case kProofAnalysis:
8e1f0465 1679 fIsRemote = kTRUE;
3bdcb562 1680 // Check if the plugin is used
1681 if (fGridHandler) {
1682 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1683 }
c52c2132 1684 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1685 Error("StartAnalysis", "No PROOF!!! Exiting.");
57756ec5 1686 cdir->cd();
1f87e9fb 1687 return -1;
c52c2132 1688 }
ea091b97 1689 line = Form("gProof->AddInput((TObject*)%p);", this);
c52c2132 1690 gROOT->ProcessLine(line);
1691 if (chain) {
1692 chain->SetProof();
1693 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
bf574918 1694 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1695 } else {
61505f8b 1696 Error("StartAnalysis", "No chain!!! Exiting.");
57756ec5 1697 cdir->cd();
1f87e9fb 1698 return -1;
c52c2132 1699 }
1700 break;
1701 case kGridAnalysis:
27734f0e 1702 fIsRemote = kTRUE;
1703 if (!anaType.Contains("terminate")) {
1704 if (!fGridHandler) {
1705 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1706 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1707 cdir->cd();
1708 return -1;
1709 }
1710 // Write analysis manager in the analysis file
1711 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1712 // Start the analysis via the handler
1713 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1714 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1715 cdir->cd();
1716 return -1;
1717 }
1718
1719 // Terminate grid analysis
1720 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1721 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1722 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1723 if (!fGridHandler->MergeOutputs()) {
1724 // Return if outputs could not be merged or if it alien handler
1725 // was configured for offline mode or local testing.
1726 cdir->cd();
1727 return 0;
1728 }
1729 }
1730 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1731 ImportWrappers(NULL);
1732 Terminate();
1733 cdir->cd();
1734 return 0;
aee5ee44 1735 case kMixingAnalysis:
1736 // Run event mixing analysis
1737 if (!fEventPool) {
1738 Error("StartAnalysis", "Cannot run event mixing without event pool");
57756ec5 1739 cdir->cd();
1f87e9fb 1740 return -1;
aee5ee44 1741 }
1742 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1743 fSelector = new AliAnalysisSelector(this);
aee5ee44 1744 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1745 next.Reset();
aee5ee44 1746 // Call NotifyBinChange for all tasks
1747 while ((task=(AliAnalysisTask*)next()))
1748 if (!task->IsPostEventLoop()) task->NotifyBinChange();
bf574918 1749 retv = chain->Process(fSelector);
1750 if (retv < 0) {
1751 Error("StartAnalysis", "Mixing analysis failed");
57756ec5 1752 cdir->cd();
bf574918 1753 return retv;
1754 }
aee5ee44 1755 }
1756 PackOutput(fSelector->GetOutputList());
1757 Terminate();
1f87e9fb 1758 }
57756ec5 1759 cdir->cd();
bf574918 1760 return retv;
c52c2132 1761}
1762
1763//______________________________________________________________________________
1f87e9fb 1764Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
d86ed856 1765{
1766// Start analysis for this manager on a given dataset. Analysis task can be:
1767// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1768 if (!fInitOK) {
1769 Error("StartAnalysis","Analysis manager was not initialized !");
1f87e9fb 1770 return -1;
d86ed856 1771 }
8e1f0465 1772 fIsRemote = kTRUE;
cd463514 1773 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
d86ed856 1774 TString anaType = type;
1775 anaType.ToLower();
1776 if (!anaType.Contains("proof")) {
d140f7fb 1777 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1f87e9fb 1778 return -1;
d86ed856 1779 }
1780 fMode = kProofAnalysis;
ab5d25d8 1781 TString line;
d86ed856 1782 SetEventLoop(kTRUE);
1783 // Set the dataset flag
1784 TObject::SetBit(kUseDataSet);
1785 fTree = 0;
3bdcb562 1786 if (fGridHandler) {
1787 // Start proof analysis using the grid handler
1788 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1789 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1790 return -1;
1791 }
1792 // Check if the plugin is in test mode
1793 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
830acc4c 1794 dataset = "test_collection";
3bdcb562 1795 } else {
1796 dataset = fGridHandler->GetProofDataSet();
1797 }
1798 }
1799
1800 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1801 Error("StartAnalysis", "No PROOF!!! Exiting.");
1802 return -1;
1803 }
d86ed856 1804
1805 // Initialize locally all tasks
1806 TIter next(fTasks);
1807 AliAnalysisTask *task;
1808 while ((task=(AliAnalysisTask*)next())) {
1809 task->LocalInit();
1810 }
1811
ea091b97 1812 line = Form("gProof->AddInput((TObject*)%p);", this);
d86ed856 1813 gROOT->ProcessLine(line);
3bdcb562 1814 Long_t retv;
ea091b97 1815 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1816 dataset, nentries, firstentry);
1817 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1818 retv = (Long_t)gROOT->ProcessLine(line);
bf574918 1819 return retv;
d86ed856 1820}
1821
1822//______________________________________________________________________________
84fcd93f 1823TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1824{
1825// Opens according the option the file specified by cont->GetFileName() and changes
1826// current directory to cont->GetFolderName(). If the file was already opened, it
1827// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1828// be optionally ignored.
1829 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1830 TString filename = cont->GetFileName();
1831 TFile *f = NULL;
1832 if (filename.IsNull()) {
1833 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1834 return NULL;
1835 }
1836 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1837 && !ignoreProof)
1838 f = mgr->OpenProofFile(cont,option);
1839 else {
1840 // Check first if the file is already opened
0f1b50f3 1841 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 1842 if (f) {
1843 // Check if option "UPDATE" was preserved
1844 TString opt(option);
1845 opt.ToUpper();
1846 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1847 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1848 } else {
0f1b50f3 1849 f = TFile::Open(filename, option);
84fcd93f 1850 }
1851 }
1852 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1853 cont->SetFile(f);
1854 // Cd to file
1855 f->cd();
1856 // Check for a folder request
1857 TString dir = cont->GetFolderName();
1858 if (!dir.IsNull()) {
1859 if (!f->GetDirectory(dir)) f->mkdir(dir);
1860 f->cd(dir);
1861 }
1862 return f;
1863 }
1864 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1865 cont->SetFile(NULL);
1866 return NULL;
1867}
1868
1869//______________________________________________________________________________
039e671e 1870TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
8d7d3b59 1871{
1872// Opens a special output file used in PROOF.
84fcd93f 1873 TString line;
1874 TString filename = cont->GetFileName();
23c9468b 1875 if (cont == fCommonOutput) {
039e671e 1876 if (fOutputEventHandler) {
1877 if (strlen(extaod)) filename = extaod;
1878 filename = fOutputEventHandler->GetOutputFileName();
1879 }
61505f8b 1880 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 1881 }
84fcd93f 1882 TFile *f = NULL;
1883 if (fMode!=kProofAnalysis || !fSelector) {
1884 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1885 return NULL;
1886 }
1887 if (fSpecialOutputLocation.Length()) {
1888 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1889 if (f) {
1890 // Check if option "UPDATE" was preserved
1891 TString opt(option);
1892 opt.ToUpper();
23c9468b 1893 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1894 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1895 } else {
1896 f = new TFile(filename, option);
1897 }
1898 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1899 cont->SetFile(f);
1900 // Cd to file
1901 f->cd();
1902 // Check for a folder request
1903 TString dir = cont->GetFolderName();
1904 if (dir.Length()) {
1905 if (!f->GetDirectory(dir)) f->mkdir(dir);
1906 f->cd(dir);
1907 }
f5e61abd 1908 return f;
84fcd93f 1909 }
1910 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1911 cont->SetFile(NULL);
1912 return NULL;
1913 }
1914 // Check if there is already a proof output file in the output list
1915 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1916 if (pof) {
1917 // Get the actual file
b3e07543 1918 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
84fcd93f 1919 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 1920 if (fDebug>1) {
1921 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1922 }
84fcd93f 1923 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
ab5d25d8 1924 if (!f) {
1925 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1926 return NULL;
1927 }
84fcd93f 1928 // Check if option "UPDATE" was preserved
1929 TString opt(option);
1930 opt.ToUpper();
1931 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1932 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1933 } else {
90a4b3ee 1934 if (cont->IsRegisterDataset()) {
61505f8b 1935 TString dsetName = filename;
1936 dsetName.ReplaceAll(".root", cont->GetTitle());
1937 dsetName.ReplaceAll(":","_");
1938 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1939 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 1940 } else {
1941 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1942 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1943 }
84fcd93f 1944 if (fDebug > 1) printf("=== %s\n", line.Data());
1945 gROOT->ProcessLine(line);
1946 line = Form("pf->OpenFile(\"%s\");", option);
1947 gROOT->ProcessLine(line);
1948 f = gFile;
1949 if (fDebug > 1) {
8d7d3b59 1950 gROOT->ProcessLine("pf->Print()");
84fcd93f 1951 printf(" == proof file name: %s", f->GetName());
1952 }
1953 // Add to proof output list
b3e07543 1954 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
90a4b3ee 1955 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 1956 gROOT->ProcessLine(line);
1957 }
1958 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1959 cont->SetFile(f);
1960 // Cd to file
1961 f->cd();
1962 // Check for a folder request
1963 TString dir = cont->GetFolderName();
1964 if (!dir.IsNull()) {
1965 if (!f->GetDirectory(dir)) f->mkdir(dir);
1966 f->cd(dir);
1967 }
1968 return f;
1969 }
1970 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1971 cont->SetFile(NULL);
1972 return NULL;
8d7d3b59 1973}
1974
1975//______________________________________________________________________________
d3106602 1976void AliAnalysisManager::ExecAnalysis(Option_t *option)
1977{
1978// Execute analysis.
cd463514 1979 static Long64_t nentries = 0;
1f04b637 1980 static TTree *lastTree = 0;
cd463514 1981 static TStopwatch *timer = new TStopwatch();
20b7268e 1982 // Only the first call to Process will trigger a true Notify. Other Notify
1983 // coming before is ignored.
1984 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
1985 TObject::SetBit(AliAnalysisManager::kTrueNotify);
1986 Notify();
1987 }
e9247450 1988 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
cd463514 1989 else {
1f04b637 1990 if (fTree && (fTree != lastTree)) {
1991 nentries += fTree->GetEntries();
1992 lastTree = fTree;
1993 }
e9247450 1994 if (!fNcalls) timer->Start();
f03a8355 1995 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
cd463514 1996 }
57756ec5 1997 gROOT->cd();
cd463514 1998 TDirectory *cdir = gDirectory;
8c0ab8e8 1999 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
e9247450 2000 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
327eaf46 2001 if (!fInitOK) {
57756ec5 2002 Error("ExecAnalysis", "Analysis manager was not initialized !");
2003 cdir->cd();
327eaf46 2004 return;
57756ec5 2005 }
e9247450 2006 fNcalls++;
d3106602 2007 AliAnalysisTask *task;
327eaf46 2008 // Check if the top tree is active.
2009 if (fTree) {
e9247450 2010 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2011 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
327eaf46 2012 TIter next(fTasks);
2013 // De-activate all tasks
2014 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 2015 AliAnalysisDataContainer *cont = fCommonInput;
2016 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 2017 if (!cont) {
c52c2132 2018 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
57756ec5 2019 cdir->cd();
327eaf46 2020 return;
2021 }
2022 cont->SetData(fTree); // This will notify all consumers
57756ec5 2023 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 2024//
c3701689 2025// Call BeginEvent() for optional input/output and MC services
ed97dc98 2026 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2027 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2028 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 2029 gROOT->cd();
e9247450 2030 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2031 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
6bb2b24f 2032//
2033// Execute the tasks
276941c8 2034// TIter next1(cont->GetConsumers());
2035 TIter next1(fTopTasks);
096b5a2e 2036 Int_t itask = 0;
327eaf46 2037 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 2038 if (fDebug >1) {
2039 cout << " Executing task " << task->GetName() << endl;
096b5a2e 2040 }
327eaf46 2041 task->ExecuteTask(option);
57756ec5 2042 gROOT->cd();
e9247450 2043 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2044 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
096b5a2e 2045 itask++;
327eaf46 2046 }
6bb2b24f 2047//
2048// Call FinishEvent() for optional output and MC services
6073f8c9 2049 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 2050 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2051 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 2052 // Gather system information if requested
e9247450 2053 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2054 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
57756ec5 2055 cdir->cd();
327eaf46 2056 return;
2057 }
2058 // The event loop is not controlled by TSelector
6bb2b24f 2059//
c3701689 2060// Call BeginEvent() for optional input/output and MC services
ed97dc98 2061 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2062 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2063 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
57756ec5 2064 gROOT->cd();
e9247450 2065 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2066 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
327eaf46 2067 TIter next2(fTopTasks);
2068 while ((task=(AliAnalysisTask*)next2())) {
2069 task->SetActive(kTRUE);
c52c2132 2070 if (fDebug > 1) {
2071 cout << " Executing task " << task->GetName() << endl;
2072 }
d3106602 2073 task->ExecuteTask(option);
57756ec5 2074 gROOT->cd();
327eaf46 2075 }
6bb2b24f 2076//
2077// Call FinishEvent() for optional output and MC services
6073f8c9 2078 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2079 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 2080 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
e9247450 2081 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2082 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
57756ec5 2083 cdir->cd();
d3106602 2084}
2085
2086//______________________________________________________________________________
8ddad121 2087Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2088{
2089// Check if the stdout is connected to a pipe (C.Holm)
2090 Bool_t ispipe = kFALSE;
2091 out.seekp(0, std::ios_base::cur);
2092 if (out.fail()) {
2093 out.clear();
2094 if (errno == ESPIPE) ispipe = kTRUE;
2095 }
2096 return ispipe;
2097}
2098
2099//______________________________________________________________________________
61505f8b 2100void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 2101{
2102// Set the input event handler and create a container for it.
2103 fInputEventHandler = handler;
523aab8b 2104 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
60a04972 2105}
2106
2107//______________________________________________________________________________
61505f8b 2108void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 2109{
2110// Set the input event handler and create a container for it.
2111 fOutputEventHandler = handler;
523aab8b 2112 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 2113 fCommonOutput->SetSpecialOutput();
60a04972 2114}
c07b9ce2 2115
2116//______________________________________________________________________________
f03a8355 2117void AliAnalysisManager::SetDebugLevel(UInt_t level)
2118{
2119// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2120 if (TObject::TestBit(kUseProgressBar)) {
2121 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2122 return;
2123 }
2124 fDebug = level;
2125}
2126
2127//______________________________________________________________________________
2128void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2129{
2130// Enable a text mode progress bar. Resets debug level to 0.
2131 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2132 TObject::SetBit(kUseProgressBar,flag);
2133 fPBUpdateFreq = freq;
2134 fDebug = 0;
2135}
2136
2137//______________________________________________________________________________
c07b9ce2 2138void AliAnalysisManager::RegisterExtraFile(const char *fname)
2139{
2140// This method is used externally to register output files which are not
2141// connected to any output container, so that the manager can properly register,
2142// retrieve or merge them when running in distributed mode. The file names are
2143// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 2144 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 2145 if (fExtraFiles.Length()) fExtraFiles += " ";
2146 fExtraFiles += fname;
2147}
2148
2149//______________________________________________________________________________
61505f8b 2150Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 2151{
2152// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 2153 char fullPath[512];
2154 char chUrl[512];
b3e07543 2155 char tmp[1024];
c07b9ce2 2156 TObject *pof = source->FindObject(filename);
2157 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2158 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2159 return kFALSE;
2160 }
b3e07543 2161 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2162 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
61505f8b 2163 TString clientUrl(chUrl);
2164 TString fullPath_str(fullPath);
c07b9ce2 2165 if (clientUrl.Contains("localhost")){
61505f8b 2166 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 2167 TObjString *strobj = ( TObjString *)array->At(1);
2168 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2169 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 2170 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2171 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2172 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 2173 delete arrayPort;
2174 delete array;
2175 }
b3e07543 2176 else if (clientUrl.Contains("__lite__")) {
2177 // Special case for ProofLite environement - get file info and copy.
2178 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2179 fullPath_str = Form("%s/%s", tmp, fullPath);
2180 }
c07b9ce2 2181 if (fDebug > 1)
b3e07543 2182 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
61505f8b 2183 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 2184 if (!gotit)
2185 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2186 return gotit;
2187}
d29168d6 2188
2189//______________________________________________________________________________
2190void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2191{
2192// Fill analysis type in the provided string.
2193 switch (fMode) {
2194 case kLocalAnalysis:
2195 type = "local";
2196 return;
2197 case kProofAnalysis:
2198 type = "proof";
2199 return;
2200 case kGridAnalysis:
2201 type = "grid";
2202 return;
2203 case kMixingAnalysis:
2204 type = "mix";
2205 }
2206}
923e2ca5 2207
2208//______________________________________________________________________________
2209Bool_t AliAnalysisManager::ValidateOutputFiles() const
2210{
2211// Validate all output files.
2212 TIter next(fOutputs);
2213 AliAnalysisDataContainer *output;
2214 TDirectory *cdir = gDirectory;
84fcd93f 2215 TString openedFiles;
923e2ca5 2216 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 2217 if (output->IsRegisterDataset()) continue;
923e2ca5 2218 TString filename = output->GetFileName();
2219 if (filename == "default") {
2220 if (!fOutputEventHandler) continue;
2221 filename = fOutputEventHandler->GetOutputFileName();
b3685485 2222 // Main AOD may not be there
2223 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 2224 }
2225 // Check if the file is closed
84fcd93f 2226 if (openedFiles.Contains(filename)) continue;;
923e2ca5 2227 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2228 if (file) {
2229 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 2230 // Clear file list to release object ownership to user.
160e7161 2231// file->Clear();
923e2ca5 2232 file->Close();
2233 }
2234 file = TFile::Open(filename);
2235 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2236 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2237 cdir->cd();
2238 return kFALSE;
2239 }
2240 file->Close();
84fcd93f 2241 openedFiles += filename;
2242 openedFiles += " ";
923e2ca5 2243 }
2244 cdir->cd();
2245 return kTRUE;
2246}
cd11251e 2247
2248//______________________________________________________________________________
61505f8b 2249void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 2250{
2251// Implements a nice text mode progress bar.
2252 static Long64_t icount = 0;
2253 static TString oname;
2254 static TString nname;
2255 static Long64_t ocurrent = 0;
2256 static Long64_t osize = 0;
2257 static Int_t oseconds = 0;
2258 static TStopwatch *owatch = 0;
2259 static Bool_t oneoftwo = kFALSE;
2260 static Int_t nrefresh = 0;
2261 static Int_t nchecks = 0;
8ddad121 2262 static char lastChar = 0;
f03a8355 2263 const char symbol[4] = {'-','\\','|','/'};
cd11251e 2264
8ddad121 2265 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
cd11251e 2266 if (!refresh) {
2267 nrefresh = 0;
2268 if (!size) return;
2269 owatch = watch;
2270 oname = opname;
2271 ocurrent = TMath::Abs(current);
2272 osize = TMath::Abs(size);
2273 if (ocurrent > osize) ocurrent=osize;
2274 } else {
2275 nrefresh++;
2276 if (!osize) return;
2277 }
f03a8355 2278 if ((current % fPBUpdateFreq) != 0) return;
cd11251e 2279 icount++;
f03a8355 2280 char progress[11] = " ";
2281 Int_t ichar = icount%4;
cd11251e 2282 Double_t time = 0.;
2283 Int_t hours = 0;
2284 Int_t minutes = 0;
2285 Int_t seconds = 0;
2286 if (owatch && !last) {
2287 owatch->Stop();
2288 time = owatch->RealTime();
f03a8355 2289 seconds = int(time) % 60;
2290 minutes = (int(time) / 60) % 60;
2291 hours = (int(time) / 60 / 60);
cd11251e 2292 if (refresh) {
2293 if (oseconds==seconds) {
2294 owatch->Continue();
2295 return;
2296 }
2297 oneoftwo = !oneoftwo;
2298 }
2299 oseconds = seconds;
2300 }
2301 if (refresh && oneoftwo) {
2302 nname = oname;
2303 if (nchecks <= 0) nchecks = nrefresh+1;
2304 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2305 oname = Form(" == %d%% ==", pctdone);
2306 }
2307 Double_t percent = 100.0*ocurrent/osize;
2308 Int_t nchar = Int_t(percent/10);
2309 if (nchar>10) nchar=10;
2310 Int_t i;
2311 for (i=0; i<nchar; i++) progress[i] = '=';
2312 progress[nchar] = symbol[ichar];
2313 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2314 progress[10] = '\0';
2315 oname += " ";
2316 oname.Remove(20);
2317 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2318 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2319 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
f03a8355 2320 if (time>0.) {
2321 Int_t full = Int_t(ocurrent > 0 ?
2322 time * (float(osize)/ocurrent) + .5 :
2323 99*3600+59*60+59);
499b6d5d 2324 Int_t remain = Int_t(full - time);
f03a8355 2325 Int_t rsec = remain % 60;
2326 Int_t rmin = (remain / 60) % 60;
2327 Int_t rhour = (remain / 60 / 60);
8ddad121 2328 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2329 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
f03a8355 2330 }
8ddad121 2331 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
cd11251e 2332 if (refresh && oneoftwo) oname = nname;
2333 if (owatch) owatch->Continue();
2334 if (last) {
2335 icount = 0;
2336 owatch = 0;
2337 ocurrent = 0;
2338 osize = 0;
2339 oseconds = 0;
2340 oneoftwo = kFALSE;
2341 nrefresh = 0;
2342 fprintf(stderr, "\n");
2343 }
2344}
012e169c 2345
2346//______________________________________________________________________________
2347void AliAnalysisManager::DoLoadBranch(const char *name)
2348{
2349 // Get tree and load branch if needed.
c5734a4b 2350 static Long64_t crtEntry = -100;
012e169c 2351
7acc5b9d 2352 if (fAutoBranchHandling || !fTree)
012e169c 2353 return;
2354
2355 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2356 if (!br) {
2357 br = fTree->GetBranch(name);
2358 if (!br) {
979e448a 2359 Error("DoLoadBranch", "Could not find branch %s",name);
012e169c 2360 return;
2361 }
2362 fTable.Add(br);
2363 }
c5734a4b 2364 if (br->GetReadEntry()==fCurrentEntry) return;
f5cbe261 2365 Int_t ret = br->GetEntry(GetCurrentEntry());
2366 if (ret<0) {
2367 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
c5734a4b 2368 if (crtEntry != fCurrentEntry) {
2369 CountEvent(1,0,1,0);
2370 crtEntry = fCurrentEntry;
2371 }
2372 } else {
2373 if (crtEntry != fCurrentEntry) {
2374 CountEvent(1,1,0,0);
2375 crtEntry = fCurrentEntry;
2376 }
f5cbe261 2377 }
012e169c 2378}
e9247450 2379
2380//______________________________________________________________________________
c3732d79 2381void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
f5cbe261 2382{
2383// Add the statistics task to the manager.
2384 if (fStatistics) {
2385 Info("AddStatisticsTask", "Already added");
2386 return;
c3732d79 2387 }
2388 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2389 gROOT->ProcessLine(line);
f5cbe261 2390}
2391
2392//______________________________________________________________________________
2393void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2394{
2395// Bookkeep current event;
2396 if (!fStatistics) return;
2397 fStatistics->AddInput(ninput);
2398 fStatistics->AddProcessed(nprocessed);
2399 fStatistics->AddFailed(nfailed);
2400 fStatistics->AddAccepted(naccepted);
2401}
2402
2403//______________________________________________________________________________
e9247450 2404void AliAnalysisManager::AddStatisticsMsg(const char *line)
2405{
2406// Add a line in the statistics message. If available, the statistics message is written
2407// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2408// on the client.
2409 if (!strlen(line)) return;
2410 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2411 fStatisticsMsg += line;
2412}
2413
2414//______________________________________________________________________________
a99b2241 2415void AliAnalysisManager::WriteStatisticsMsg(Int_t)
e9247450 2416{
23a74fb4 2417// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
c3732d79 2418 static Bool_t done = kFALSE;
2419 if (done) return;
2420 done = kTRUE;
e296c79c 2421 if (!fStatistics) return;
e9247450 2422 ofstream out;
e296c79c 2423 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2424 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2425 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2426 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2427 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2428 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2429 fStatistics->GetNaccepted()), ios::out);
2430 out << fStatisticsMsg << endl;
e9247450 2431 out.close();
2432}
37196805 2433
2434//______________________________________________________________________________
2435const char* AliAnalysisManager::GetOADBPath()
2436{
2437// returns the path of the OADB
2438// this static function just depends on environment variables
2439
2440 static TString oadbPath;
2441
2442 if (gSystem->Getenv("OADB_PATH"))
2443 oadbPath = gSystem->Getenv("OADB_PATH");
2444 else if (gSystem->Getenv("ALICE_ROOT"))
2445 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2446 else
0a9cc013 2447 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
37196805 2448
2449 return oadbPath;
2450}
77dad4a9 2451
2452//______________________________________________________________________________
2453void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2454{
2455// Define a custom string variable mapped to a global unique name. The variable
2456// can be then retrieved by a given analysis macro via GetGlobalStr(key).
2457 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2458 if (!mgr) {
2459 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2460 return;
2461 }
2462 Bool_t valid = kFALSE;
2463 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2464 if (valid) {
2465 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2466 return;
2467 }
2468 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2469}
2470
2471//______________________________________________________________________________
2472const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2473{
2474// Static method to retrieve a global variable defined via SetGlobalStr.
2475 valid = kFALSE;
2476 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2477 if (!mgr) return 0;
2478 TObject *value = mgr->GetGlobals()->GetValue(key);
2479 if (!value) return 0;
2480 valid = kTRUE;
2481 return value->GetName();
2482}
2483
2484//______________________________________________________________________________
2485void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2486{
2487// Define a custom integer variable mapped to a global unique name. The variable
2488// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2489 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2490 if (!mgr) {
2491 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2492 return;
2493 }
2494 Bool_t valid = kFALSE;
2495 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2496 if (valid) {
2497 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2498 return;
2499 }
2500 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2501}
2502
2503//______________________________________________________________________________
2504Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2505{
2506// Static method to retrieve a global variable defined via SetGlobalInt.
2507 valid = kFALSE;
2508 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2509 if (!mgr) return 0;
2510 TObject *value = mgr->GetGlobals()->GetValue(key);
2511 if (!value) return 0;
2512 valid = kTRUE;
2513 TString s = value->GetName();
2514 return s.Atoi();
2515}
2516
2517//______________________________________________________________________________
2518void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2519{
2520// Define a custom double precision variable mapped to a global unique name. The variable
2521// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2522 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2523 if (!mgr) {
2524 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2525 return;
2526 }
2527 Bool_t valid = kFALSE;
2528 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2529 if (valid) {
2530 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2531 return;
2532 }
2533 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2534}
2535
2536//______________________________________________________________________________
2537Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2538{
2539// Static method to retrieve a global variable defined via SetGlobalDbl.
2540 valid = kFALSE;
2541 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2542 if (!mgr) return 0;
2543 TObject *value = mgr->GetGlobals()->GetValue(key);
2544 if (!value) return 0;
2545 valid = kTRUE;
2546 TString s = value->GetName();
2547 return s.Atof();
2548}