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