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