Updated histos
[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 }
57756ec5 731 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 }
1103 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 }
1537 cdir->cd();
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 !");
57756ec5 1565 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.");
57756ec5 1589 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");
57756ec5 1598 cdir->cd();
f866cba5 1599 return -1;
1600 }
c57f56b7 1601
f866cba5 1602 // Terminate grid analysis
57756ec5 1603 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1604 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {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.
57756ec5 1609 cdir->cd();
f866cba5 1610 return 0;
1611 }
1612 }
1613 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
c57f56b7 1614 ImportWrappers(NULL);
1615 Terminate();
57756ec5 1616 cdir->cd();
1f87e9fb 1617 return 0;
981f2614 1618 }
ab5d25d8 1619 TString line;
efd53803 1620 SetEventLoop(kFALSE);
8d7d3b59 1621 // Enable event loop mode if a tree was provided
27734f0e 1622 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1623
8c0ab8e8 1624 TChain *chain = 0;
1625 TString ttype = "TTree";
4ab472d4 1626 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1627 chain = (TChain*)tree;
6b742510 1628 if (!chain || !chain->GetListOfFiles()->First()) {
1629 Error("StartAnalysis", "Cannot process null or empty chain...");
57756ec5 1630 cdir->cd();
1f87e9fb 1631 return -1;
6b742510 1632 }
8c0ab8e8 1633 ttype = "TChain";
1634 }
9b33830a 1635
096b5a2e 1636 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1637 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
aee5ee44 1638 // Initialize locally all tasks (happens for all modes)
9b33830a 1639 TIter next(fTasks);
1640 AliAnalysisTask *task;
d512d8e2 1641 RunLocalInit();
efd53803 1642
c52c2132 1643 switch (fMode) {
1644 case kLocalAnalysis:
27734f0e 1645 if (!tree && !fGridHandler) {
03a5cc9f 1646 TIter nextT(fTasks);
981f2614 1647 // Call CreateOutputObjects for all tasks
096b5a2e 1648 Int_t itask = 0;
979e448a 1649 Bool_t dirStatus = TH1::AddDirectoryStatus();
03a5cc9f 1650 while ((task=(AliAnalysisTask*)nextT())) {
979e448a 1651 TH1::AddDirectory(kFALSE);
c5a87c56 1652 task->CreateOutputObjects();
4747b4a7 1653 if (!task->CheckPostData()) {
1654 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1655 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1656 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1657 }
096b5a2e 1658 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
57756ec5 1659 gROOT->cd();
096b5a2e 1660 itask++;
c5a87c56 1661 }
979e448a 1662 TH1::AddDirectory(dirStatus);
06a59280 1663 if (IsExternalLoop()) {
1664 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1665 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1f87e9fb 1666 return 0;
57756ec5 1667 }
c52c2132 1668 ExecAnalysis();
981f2614 1669 Terminate();
1f87e9fb 1670 return 0;
c52c2132 1671 }
27734f0e 1672 fSelector = new AliAnalysisSelector(this);
1673 // Check if a plugin handler is used
1674 if (fGridHandler) {
1675 // Get the chain from the plugin
1676 TString dataType = "esdTree";
1677 if (fInputEventHandler) {
1678 dataType = fInputEventHandler->GetDataType();
1679 dataType.ToLower();
1680 dataType += "Tree";
1681 }
1682 chain = fGridHandler->GetChainForTestMode(dataType);
1683 if (!chain) {
1684 Error("StartAnalysis", "No chain for test mode. Aborting.");
1685 return -1;
1686 }
1687 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1688 retv = chain->Process(fSelector, "", nentries, firstentry);
1689 break;
1690 }
c52c2132 1691 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1692 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
bf574918 1693 retv = tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1694 break;
1695 case kProofAnalysis:
8e1f0465 1696 fIsRemote = kTRUE;
3bdcb562 1697 // Check if the plugin is used
1698 if (fGridHandler) {
1699 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1700 }
c52c2132 1701 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1702 Error("StartAnalysis", "No PROOF!!! Exiting.");
57756ec5 1703 cdir->cd();
1f87e9fb 1704 return -1;
c52c2132 1705 }
ea091b97 1706 line = Form("gProof->AddInput((TObject*)%p);", this);
c52c2132 1707 gROOT->ProcessLine(line);
1708 if (chain) {
1709 chain->SetProof();
1710 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
bf574918 1711 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1712 } else {
61505f8b 1713 Error("StartAnalysis", "No chain!!! Exiting.");
57756ec5 1714 cdir->cd();
1f87e9fb 1715 return -1;
c52c2132 1716 }
1717 break;
1718 case kGridAnalysis:
27734f0e 1719 fIsRemote = kTRUE;
1720 if (!anaType.Contains("terminate")) {
1721 if (!fGridHandler) {
1722 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1723 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1724 cdir->cd();
1725 return -1;
1726 }
1727 // Write analysis manager in the analysis file
1728 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1729 // Start the analysis via the handler
1730 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1731 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1732 cdir->cd();
1733 return -1;
1734 }
1735
1736 // Terminate grid analysis
1737 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1738 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1739 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1740 if (!fGridHandler->MergeOutputs()) {
1741 // Return if outputs could not be merged or if it alien handler
1742 // was configured for offline mode or local testing.
1743 cdir->cd();
1744 return 0;
1745 }
1746 }
1747 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1748 ImportWrappers(NULL);
1749 Terminate();
1750 cdir->cd();
1751 return 0;
aee5ee44 1752 case kMixingAnalysis:
1753 // Run event mixing analysis
1754 if (!fEventPool) {
1755 Error("StartAnalysis", "Cannot run event mixing without event pool");
57756ec5 1756 cdir->cd();
1f87e9fb 1757 return -1;
aee5ee44 1758 }
1759 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1760 fSelector = new AliAnalysisSelector(this);
aee5ee44 1761 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1762 next.Reset();
aee5ee44 1763 // Call NotifyBinChange for all tasks
1764 while ((task=(AliAnalysisTask*)next()))
1765 if (!task->IsPostEventLoop()) task->NotifyBinChange();
bf574918 1766 retv = chain->Process(fSelector);
1767 if (retv < 0) {
1768 Error("StartAnalysis", "Mixing analysis failed");
57756ec5 1769 cdir->cd();
bf574918 1770 return retv;
1771 }
aee5ee44 1772 }
1773 PackOutput(fSelector->GetOutputList());
1774 Terminate();
1f87e9fb 1775 }
57756ec5 1776 cdir->cd();
bf574918 1777 return retv;
c52c2132 1778}
1779
1780//______________________________________________________________________________
1f87e9fb 1781Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
d86ed856 1782{
1783// Start analysis for this manager on a given dataset. Analysis task can be:
1784// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1785 if (!fInitOK) {
1786 Error("StartAnalysis","Analysis manager was not initialized !");
1f87e9fb 1787 return -1;
d86ed856 1788 }
8e1f0465 1789 fIsRemote = kTRUE;
cd463514 1790 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
d86ed856 1791 TString anaType = type;
1792 anaType.ToLower();
1793 if (!anaType.Contains("proof")) {
d140f7fb 1794 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1f87e9fb 1795 return -1;
d86ed856 1796 }
1797 fMode = kProofAnalysis;
ab5d25d8 1798 TString line;
d86ed856 1799 SetEventLoop(kTRUE);
1800 // Set the dataset flag
1801 TObject::SetBit(kUseDataSet);
1802 fTree = 0;
3bdcb562 1803 if (fGridHandler) {
1804 // Start proof analysis using the grid handler
1805 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1806 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1807 return -1;
1808 }
1809 // Check if the plugin is in test mode
1810 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
830acc4c 1811 dataset = "test_collection";
3bdcb562 1812 } else {
1813 dataset = fGridHandler->GetProofDataSet();
1814 }
1815 }
1816
1817 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1818 Error("StartAnalysis", "No PROOF!!! Exiting.");
1819 return -1;
1820 }
d86ed856 1821
1822 // Initialize locally all tasks
d512d8e2 1823 RunLocalInit();
1824
ea091b97 1825 line = Form("gProof->AddInput((TObject*)%p);", this);
d86ed856 1826 gROOT->ProcessLine(line);
3bdcb562 1827 Long_t retv;
ea091b97 1828 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1829 dataset, nentries, firstentry);
1830 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1831 retv = (Long_t)gROOT->ProcessLine(line);
bf574918 1832 return retv;
d86ed856 1833}
1834
1835//______________________________________________________________________________
84fcd93f 1836TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1837{
1838// Opens according the option the file specified by cont->GetFileName() and changes
1839// current directory to cont->GetFolderName(). If the file was already opened, it
1840// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1841// be optionally ignored.
1842 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1843 TString filename = cont->GetFileName();
1844 TFile *f = NULL;
1845 if (filename.IsNull()) {
1846 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1847 return NULL;
1848 }
1849 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1850 && !ignoreProof)
1851 f = mgr->OpenProofFile(cont,option);
1852 else {
1853 // Check first if the file is already opened
0f1b50f3 1854 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 1855 if (f) {
1856 // Check if option "UPDATE" was preserved
1857 TString opt(option);
1858 opt.ToUpper();
1859 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1860 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1861 } else {
0f1b50f3 1862 f = TFile::Open(filename, option);
84fcd93f 1863 }
1864 }
1865 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1866 cont->SetFile(f);
1867 // Cd to file
1868 f->cd();
1869 // Check for a folder request
1870 TString dir = cont->GetFolderName();
1871 if (!dir.IsNull()) {
1872 if (!f->GetDirectory(dir)) f->mkdir(dir);
1873 f->cd(dir);
1874 }
1875 return f;
1876 }
1877 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1878 cont->SetFile(NULL);
1879 return NULL;
1880}
1881
1882//______________________________________________________________________________
039e671e 1883TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
8d7d3b59 1884{
1885// Opens a special output file used in PROOF.
84fcd93f 1886 TString line;
1887 TString filename = cont->GetFileName();
23c9468b 1888 if (cont == fCommonOutput) {
039e671e 1889 if (fOutputEventHandler) {
1890 if (strlen(extaod)) filename = extaod;
1891 filename = fOutputEventHandler->GetOutputFileName();
1892 }
61505f8b 1893 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 1894 }
84fcd93f 1895 TFile *f = NULL;
1896 if (fMode!=kProofAnalysis || !fSelector) {
1897 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1898 return NULL;
1899 }
1900 if (fSpecialOutputLocation.Length()) {
1901 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1902 if (f) {
1903 // Check if option "UPDATE" was preserved
1904 TString opt(option);
1905 opt.ToUpper();
23c9468b 1906 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1907 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1908 } else {
1909 f = new TFile(filename, option);
1910 }
1911 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1912 cont->SetFile(f);
1913 // Cd to file
1914 f->cd();
1915 // Check for a folder request
1916 TString dir = cont->GetFolderName();
1917 if (dir.Length()) {
1918 if (!f->GetDirectory(dir)) f->mkdir(dir);
1919 f->cd(dir);
1920 }
f5e61abd 1921 return f;
84fcd93f 1922 }
1923 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1924 cont->SetFile(NULL);
1925 return NULL;
1926 }
1927 // Check if there is already a proof output file in the output list
1928 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1929 if (pof) {
1930 // Get the actual file
b3e07543 1931 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
84fcd93f 1932 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 1933 if (fDebug>1) {
1934 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1935 }
84fcd93f 1936 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
ab5d25d8 1937 if (!f) {
1938 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1939 return NULL;
1940 }
84fcd93f 1941 // Check if option "UPDATE" was preserved
1942 TString opt(option);
1943 opt.ToUpper();
1944 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1945 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1946 } else {
90a4b3ee 1947 if (cont->IsRegisterDataset()) {
61505f8b 1948 TString dsetName = filename;
1949 dsetName.ReplaceAll(".root", cont->GetTitle());
1950 dsetName.ReplaceAll(":","_");
1951 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1952 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 1953 } else {
1954 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1955 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1956 }
84fcd93f 1957 if (fDebug > 1) printf("=== %s\n", line.Data());
1958 gROOT->ProcessLine(line);
1959 line = Form("pf->OpenFile(\"%s\");", option);
1960 gROOT->ProcessLine(line);
1961 f = gFile;
1962 if (fDebug > 1) {
8d7d3b59 1963 gROOT->ProcessLine("pf->Print()");
84fcd93f 1964 printf(" == proof file name: %s", f->GetName());
1965 }
1966 // Add to proof output list
b3e07543 1967 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
90a4b3ee 1968 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 1969 gROOT->ProcessLine(line);
1970 }
1971 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1972 cont->SetFile(f);
1973 // Cd to file
1974 f->cd();
1975 // Check for a folder request
1976 TString dir = cont->GetFolderName();
1977 if (!dir.IsNull()) {
1978 if (!f->GetDirectory(dir)) f->mkdir(dir);
1979 f->cd(dir);
1980 }
1981 return f;
1982 }
1983 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1984 cont->SetFile(NULL);
1985 return NULL;
8d7d3b59 1986}
1987
1988//______________________________________________________________________________
d3106602 1989void AliAnalysisManager::ExecAnalysis(Option_t *option)
1990{
1991// Execute analysis.
cd463514 1992 static Long64_t nentries = 0;
1f04b637 1993 static TTree *lastTree = 0;
cd463514 1994 static TStopwatch *timer = new TStopwatch();
20b7268e 1995 // Only the first call to Process will trigger a true Notify. Other Notify
1996 // coming before is ignored.
1997 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
1998 TObject::SetBit(AliAnalysisManager::kTrueNotify);
1999 Notify();
2000 }
e9247450 2001 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
cd463514 2002 else {
1f04b637 2003 if (fTree && (fTree != lastTree)) {
2004 nentries += fTree->GetEntries();
2005 lastTree = fTree;
2006 }
e9247450 2007 if (!fNcalls) timer->Start();
f03a8355 2008 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
cd463514 2009 }
57756ec5 2010 gROOT->cd();
cd463514 2011 TDirectory *cdir = gDirectory;
8c0ab8e8 2012 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
e9247450 2013 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
327eaf46 2014 if (!fInitOK) {
57756ec5 2015 Error("ExecAnalysis", "Analysis manager was not initialized !");
2016 cdir->cd();
327eaf46 2017 return;
57756ec5 2018 }
e9247450 2019 fNcalls++;
d3106602 2020 AliAnalysisTask *task;
327eaf46 2021 // Check if the top tree is active.
2022 if (fTree) {
e9247450 2023 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2024 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
327eaf46 2025 TIter next(fTasks);
2026 // De-activate all tasks
2027 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 2028 AliAnalysisDataContainer *cont = fCommonInput;
2029 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 2030 if (!cont) {
c52c2132 2031 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
57756ec5 2032 cdir->cd();
327eaf46 2033 return;
2034 }
2035 cont->SetData(fTree); // This will notify all consumers
57756ec5 2036 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 2037//
c3701689 2038// Call BeginEvent() for optional input/output and MC services
ed97dc98 2039 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2040 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2041 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 2042 gROOT->cd();
e9247450 2043 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2044 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
6bb2b24f 2045//
2046// Execute the tasks
276941c8 2047// TIter next1(cont->GetConsumers());
2048 TIter next1(fTopTasks);
096b5a2e 2049 Int_t itask = 0;
327eaf46 2050 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 2051 if (fDebug >1) {
2052 cout << " Executing task " << task->GetName() << endl;
096b5a2e 2053 }
327eaf46 2054 task->ExecuteTask(option);
57756ec5 2055 gROOT->cd();
e9247450 2056 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2057 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
096b5a2e 2058 itask++;
327eaf46 2059 }
6bb2b24f 2060//
2061// Call FinishEvent() for optional output and MC services
6073f8c9 2062 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 2063 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2064 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 2065 // Gather system information if requested
e9247450 2066 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2067 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
57756ec5 2068 cdir->cd();
327eaf46 2069 return;
2070 }
2071 // The event loop is not controlled by TSelector
6bb2b24f 2072//
c3701689 2073// Call BeginEvent() for optional input/output and MC services
ed97dc98 2074 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2075 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2076 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
57756ec5 2077 gROOT->cd();
e9247450 2078 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2079 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
327eaf46 2080 TIter next2(fTopTasks);
2081 while ((task=(AliAnalysisTask*)next2())) {
2082 task->SetActive(kTRUE);
c52c2132 2083 if (fDebug > 1) {
2084 cout << " Executing task " << task->GetName() << endl;
2085 }
d3106602 2086 task->ExecuteTask(option);
57756ec5 2087 gROOT->cd();
327eaf46 2088 }
6bb2b24f 2089//
2090// Call FinishEvent() for optional output and MC services
6073f8c9 2091 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2092 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 2093 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
e9247450 2094 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2095 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
57756ec5 2096 cdir->cd();
d3106602 2097}
2098
2099//______________________________________________________________________________
8ddad121 2100Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2101{
2102// Check if the stdout is connected to a pipe (C.Holm)
2103 Bool_t ispipe = kFALSE;
2104 out.seekp(0, std::ios_base::cur);
2105 if (out.fail()) {
2106 out.clear();
2107 if (errno == ESPIPE) ispipe = kTRUE;
2108 }
2109 return ispipe;
2110}
2111
2112//______________________________________________________________________________
61505f8b 2113void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 2114{
2115// Set the input event handler and create a container for it.
2116 fInputEventHandler = handler;
523aab8b 2117 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
60a04972 2118}
2119
2120//______________________________________________________________________________
61505f8b 2121void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 2122{
2123// Set the input event handler and create a container for it.
2124 fOutputEventHandler = handler;
523aab8b 2125 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 2126 fCommonOutput->SetSpecialOutput();
60a04972 2127}
c07b9ce2 2128
2129//______________________________________________________________________________
f03a8355 2130void AliAnalysisManager::SetDebugLevel(UInt_t level)
2131{
2132// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2133 if (TObject::TestBit(kUseProgressBar)) {
2134 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2135 return;
2136 }
2137 fDebug = level;
2138}
2139
2140//______________________________________________________________________________
2141void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2142{
2143// Enable a text mode progress bar. Resets debug level to 0.
2144 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2145 TObject::SetBit(kUseProgressBar,flag);
2146 fPBUpdateFreq = freq;
2147 fDebug = 0;
2148}
2149
2150//______________________________________________________________________________
c07b9ce2 2151void AliAnalysisManager::RegisterExtraFile(const char *fname)
2152{
2153// This method is used externally to register output files which are not
2154// connected to any output container, so that the manager can properly register,
2155// retrieve or merge them when running in distributed mode. The file names are
2156// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 2157 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 2158 if (fExtraFiles.Length()) fExtraFiles += " ";
2159 fExtraFiles += fname;
2160}
2161
2162//______________________________________________________________________________
61505f8b 2163Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 2164{
2165// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 2166 char fullPath[512];
2167 char chUrl[512];
b3e07543 2168 char tmp[1024];
c07b9ce2 2169 TObject *pof = source->FindObject(filename);
2170 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2171 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2172 return kFALSE;
2173 }
b3e07543 2174 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2175 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
61505f8b 2176 TString clientUrl(chUrl);
2177 TString fullPath_str(fullPath);
c07b9ce2 2178 if (clientUrl.Contains("localhost")){
61505f8b 2179 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 2180 TObjString *strobj = ( TObjString *)array->At(1);
2181 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2182 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 2183 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2184 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2185 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 2186 delete arrayPort;
2187 delete array;
2188 }
b3e07543 2189 else if (clientUrl.Contains("__lite__")) {
2190 // Special case for ProofLite environement - get file info and copy.
2191 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2192 fullPath_str = Form("%s/%s", tmp, fullPath);
2193 }
c07b9ce2 2194 if (fDebug > 1)
b3e07543 2195 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
61505f8b 2196 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 2197 if (!gotit)
2198 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2199 return gotit;
2200}
d29168d6 2201
2202//______________________________________________________________________________
2203void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2204{
2205// Fill analysis type in the provided string.
2206 switch (fMode) {
2207 case kLocalAnalysis:
2208 type = "local";
2209 return;
2210 case kProofAnalysis:
2211 type = "proof";
2212 return;
2213 case kGridAnalysis:
2214 type = "grid";
2215 return;
2216 case kMixingAnalysis:
2217 type = "mix";
2218 }
2219}
923e2ca5 2220
2221//______________________________________________________________________________
2222Bool_t AliAnalysisManager::ValidateOutputFiles() const
2223{
2224// Validate all output files.
2225 TIter next(fOutputs);
2226 AliAnalysisDataContainer *output;
2227 TDirectory *cdir = gDirectory;
84fcd93f 2228 TString openedFiles;
923e2ca5 2229 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 2230 if (output->IsRegisterDataset()) continue;
923e2ca5 2231 TString filename = output->GetFileName();
2232 if (filename == "default") {
2233 if (!fOutputEventHandler) continue;
2234 filename = fOutputEventHandler->GetOutputFileName();
b3685485 2235 // Main AOD may not be there
2236 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 2237 }
2238 // Check if the file is closed
84fcd93f 2239 if (openedFiles.Contains(filename)) continue;;
923e2ca5 2240 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2241 if (file) {
2242 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 2243 // Clear file list to release object ownership to user.
160e7161 2244// file->Clear();
923e2ca5 2245 file->Close();
2246 }
2247 file = TFile::Open(filename);
2248 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2249 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2250 cdir->cd();
2251 return kFALSE;
2252 }
2253 file->Close();
84fcd93f 2254 openedFiles += filename;
2255 openedFiles += " ";
923e2ca5 2256 }
2257 cdir->cd();
2258 return kTRUE;
2259}
cd11251e 2260
2261//______________________________________________________________________________
61505f8b 2262void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 2263{
2264// Implements a nice text mode progress bar.
2265 static Long64_t icount = 0;
2266 static TString oname;
2267 static TString nname;
2268 static Long64_t ocurrent = 0;
2269 static Long64_t osize = 0;
2270 static Int_t oseconds = 0;
2271 static TStopwatch *owatch = 0;
2272 static Bool_t oneoftwo = kFALSE;
2273 static Int_t nrefresh = 0;
2274 static Int_t nchecks = 0;
8ddad121 2275 static char lastChar = 0;
f03a8355 2276 const char symbol[4] = {'-','\\','|','/'};
cd11251e 2277
8ddad121 2278 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
cd11251e 2279 if (!refresh) {
2280 nrefresh = 0;
2281 if (!size) return;
2282 owatch = watch;
2283 oname = opname;
2284 ocurrent = TMath::Abs(current);
2285 osize = TMath::Abs(size);
2286 if (ocurrent > osize) ocurrent=osize;
2287 } else {
2288 nrefresh++;
2289 if (!osize) return;
2290 }
f03a8355 2291 if ((current % fPBUpdateFreq) != 0) return;
cd11251e 2292 icount++;
f03a8355 2293 char progress[11] = " ";
2294 Int_t ichar = icount%4;
cd11251e 2295 Double_t time = 0.;
2296 Int_t hours = 0;
2297 Int_t minutes = 0;
2298 Int_t seconds = 0;
2299 if (owatch && !last) {
2300 owatch->Stop();
2301 time = owatch->RealTime();
f03a8355 2302 seconds = int(time) % 60;
2303 minutes = (int(time) / 60) % 60;
2304 hours = (int(time) / 60 / 60);
cd11251e 2305 if (refresh) {
2306 if (oseconds==seconds) {
2307 owatch->Continue();
2308 return;
2309 }
2310 oneoftwo = !oneoftwo;
2311 }
2312 oseconds = seconds;
2313 }
2314 if (refresh && oneoftwo) {
2315 nname = oname;
2316 if (nchecks <= 0) nchecks = nrefresh+1;
2317 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2318 oname = Form(" == %d%% ==", pctdone);
2319 }
2320 Double_t percent = 100.0*ocurrent/osize;
2321 Int_t nchar = Int_t(percent/10);
2322 if (nchar>10) nchar=10;
2323 Int_t i;
2324 for (i=0; i<nchar; i++) progress[i] = '=';
2325 progress[nchar] = symbol[ichar];
2326 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2327 progress[10] = '\0';
2328 oname += " ";
2329 oname.Remove(20);
2330 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2331 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2332 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
f03a8355 2333 if (time>0.) {
2334 Int_t full = Int_t(ocurrent > 0 ?
2335 time * (float(osize)/ocurrent) + .5 :
2336 99*3600+59*60+59);
499b6d5d 2337 Int_t remain = Int_t(full - time);
f03a8355 2338 Int_t rsec = remain % 60;
2339 Int_t rmin = (remain / 60) % 60;
2340 Int_t rhour = (remain / 60 / 60);
8ddad121 2341 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2342 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
f03a8355 2343 }
8ddad121 2344 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
cd11251e 2345 if (refresh && oneoftwo) oname = nname;
2346 if (owatch) owatch->Continue();
2347 if (last) {
2348 icount = 0;
2349 owatch = 0;
2350 ocurrent = 0;
2351 osize = 0;
2352 oseconds = 0;
2353 oneoftwo = kFALSE;
2354 nrefresh = 0;
2355 fprintf(stderr, "\n");
2356 }
2357}
012e169c 2358
2359//______________________________________________________________________________
2360void AliAnalysisManager::DoLoadBranch(const char *name)
2361{
2362 // Get tree and load branch if needed.
c5734a4b 2363 static Long64_t crtEntry = -100;
012e169c 2364
7acc5b9d 2365 if (fAutoBranchHandling || !fTree)
012e169c 2366 return;
2367
2368 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2369 if (!br) {
2370 br = fTree->GetBranch(name);
2371 if (!br) {
979e448a 2372 Error("DoLoadBranch", "Could not find branch %s",name);
012e169c 2373 return;
2374 }
2375 fTable.Add(br);
2376 }
c5734a4b 2377 if (br->GetReadEntry()==fCurrentEntry) return;
f5cbe261 2378 Int_t ret = br->GetEntry(GetCurrentEntry());
2379 if (ret<0) {
2380 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
c5734a4b 2381 if (crtEntry != fCurrentEntry) {
2382 CountEvent(1,0,1,0);
2383 crtEntry = fCurrentEntry;
2384 }
2385 } else {
2386 if (crtEntry != fCurrentEntry) {
2387 CountEvent(1,1,0,0);
2388 crtEntry = fCurrentEntry;
2389 }
f5cbe261 2390 }
012e169c 2391}
e9247450 2392
2393//______________________________________________________________________________
c3732d79 2394void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
f5cbe261 2395{
2396// Add the statistics task to the manager.
2397 if (fStatistics) {
2398 Info("AddStatisticsTask", "Already added");
2399 return;
c3732d79 2400 }
2401 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2402 gROOT->ProcessLine(line);
f5cbe261 2403}
2404
2405//______________________________________________________________________________
2406void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2407{
2408// Bookkeep current event;
2409 if (!fStatistics) return;
2410 fStatistics->AddInput(ninput);
2411 fStatistics->AddProcessed(nprocessed);
2412 fStatistics->AddFailed(nfailed);
2413 fStatistics->AddAccepted(naccepted);
2414}
2415
2416//______________________________________________________________________________
e9247450 2417void AliAnalysisManager::AddStatisticsMsg(const char *line)
2418{
2419// Add a line in the statistics message. If available, the statistics message is written
2420// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2421// on the client.
2422 if (!strlen(line)) return;
2423 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2424 fStatisticsMsg += line;
2425}
2426
2427//______________________________________________________________________________
a99b2241 2428void AliAnalysisManager::WriteStatisticsMsg(Int_t)
e9247450 2429{
23a74fb4 2430// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
c3732d79 2431 static Bool_t done = kFALSE;
2432 if (done) return;
2433 done = kTRUE;
e296c79c 2434 if (!fStatistics) return;
e9247450 2435 ofstream out;
e296c79c 2436 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2437 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2438 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2439 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2440 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2441 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2442 fStatistics->GetNaccepted()), ios::out);
2443 out << fStatisticsMsg << endl;
e9247450 2444 out.close();
2445}
37196805 2446
2447//______________________________________________________________________________
2448const char* AliAnalysisManager::GetOADBPath()
2449{
2450// returns the path of the OADB
2451// this static function just depends on environment variables
2452
2453 static TString oadbPath;
2454
2455 if (gSystem->Getenv("OADB_PATH"))
2456 oadbPath = gSystem->Getenv("OADB_PATH");
2457 else if (gSystem->Getenv("ALICE_ROOT"))
2458 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2459 else
0a9cc013 2460 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
37196805 2461
2462 return oadbPath;
2463}
77dad4a9 2464
2465//______________________________________________________________________________
2466void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2467{
2468// Define a custom string variable mapped to a global unique name. The variable
2469// can be then retrieved by a given analysis macro via GetGlobalStr(key).
2470 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2471 if (!mgr) {
2472 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2473 return;
2474 }
2475 Bool_t valid = kFALSE;
2476 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2477 if (valid) {
2478 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2479 return;
2480 }
2481 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2482}
2483
2484//______________________________________________________________________________
2485const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2486{
2487// Static method to retrieve a global variable defined via SetGlobalStr.
2488 valid = kFALSE;
2489 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2490 if (!mgr) return 0;
2491 TObject *value = mgr->GetGlobals()->GetValue(key);
2492 if (!value) return 0;
2493 valid = kTRUE;
2494 return value->GetName();
2495}
2496
2497//______________________________________________________________________________
2498void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2499{
2500// Define a custom integer variable mapped to a global unique name. The variable
2501// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2502 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2503 if (!mgr) {
2504 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2505 return;
2506 }
2507 Bool_t valid = kFALSE;
2508 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2509 if (valid) {
2510 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2511 return;
2512 }
2513 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2514}
2515
2516//______________________________________________________________________________
2517Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2518{
2519// Static method to retrieve a global variable defined via SetGlobalInt.
2520 valid = kFALSE;
2521 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2522 if (!mgr) return 0;
2523 TObject *value = mgr->GetGlobals()->GetValue(key);
2524 if (!value) return 0;
2525 valid = kTRUE;
2526 TString s = value->GetName();
2527 return s.Atoi();
2528}
2529
2530//______________________________________________________________________________
2531void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2532{
2533// Define a custom double precision variable mapped to a global unique name. The variable
2534// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2535 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2536 if (!mgr) {
2537 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2538 return;
2539 }
2540 Bool_t valid = kFALSE;
2541 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2542 if (valid) {
2543 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2544 return;
2545 }
2546 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2547}
2548
2549//______________________________________________________________________________
2550Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2551{
2552// Static method to retrieve a global variable defined via SetGlobalDbl.
2553 valid = kFALSE;
2554 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2555 if (!mgr) return 0;
2556 TObject *value = mgr->GetGlobals()->GetValue(key);
2557 if (!value) return 0;
2558 valid = kTRUE;
2559 TString s = value->GetName();
2560 return s.Atof();
2561}
6f3e07d8 2562
2563//______________________________________________________________________________
2564void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2565{
2566// Sets Class debug level
2567
2568 if (!fDebugOptions) {
2569 fDebugOptions = new TObjArray();
2570 fDebugOptions->SetOwner(kTRUE);
2571 }
2572
2573 // substracting DebugOffset, beacuse of AliLog::SetClassDebugLevel()
2574 debugLevel -= AliLog::kDebug-1;
2575
2576 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2577 if (!debugOpt) {
2578 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel+AliLog::kDebug-1,className).Data());
2579 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2580 } else {
2581 TString oldDebugStr = debugOpt->GetTitle();
2582 Int_t oldDebug = oldDebugStr.Atoi();
2583 if (debugLevel > oldDebug) {
2584 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());
2585 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2586 } else {
2587 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());
2588 }
2589 }
2590}
2591
2592//______________________________________________________________________________
2593void AliAnalysisManager::ApplyDebugOptions()
2594{
2595// Apply debug options
2596
2597 if (!fDebugOptions) return;
2598
2599 TIter next(fDebugOptions);
2600 TNamed *debug;
2601 TString debugLevel;
2602 while ((debug=dynamic_cast<TNamed*>(next()))) {
2603 debugLevel = debug->GetTitle();
2604 AliInfo(TString::Format("ApplyDebugOptions : Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()+AliLog::kDebug-1).Data());
2605 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2606 }
2607}
2608