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