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