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