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