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