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