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