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