]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisManager.cxx
Update
[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 }
8c0ab8e8 797 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 798 // Special outputs or grid files have the files already closed and written.
799 if (fMode == kGridAnalysis) continue;
90a4b3ee 800 if (fMode == kProofAnalysis) {
801 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
802 }
8c0ab8e8 803 const char *filename = output->GetFileName();
61505f8b 804 TString openoption = "RECREATE";
aa399a26 805 if (!(strcmp(filename, "default"))) continue;
8d7d3b59 806 if (!strlen(filename)) continue;
1be433fc 807 if (!output->GetData()) continue;
8d7d3b59 808 TDirectory *opwd = gDirectory;
84fcd93f 809 TFile *file = output->GetFile();
810 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
f2087b52 811 if (!file) {
61505f8b 812 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
813 if (!gSystem->AccessPathName(filename)) openoption = "UPDATE";
814 if (fDebug>0) printf("Opening file: %s option=%s\n",filename, openoption.Data());
815 file = new TFile(filename, openoption);
6cd44ee0 816 } else {
817 if (fDebug>0) printf("File already opened: %s\n", filename);
818 }
84fcd93f 819 if (file->IsZombie()) {
820 Error("Terminate", "Cannot open output file %s", filename);
821 continue;
822 }
8e6e6fe8 823 output->SetFile(file);
824 file->cd();
84fcd93f 825 // Check for a folder request
826 TString dir = output->GetFolderName();
827 if (!dir.IsNull()) {
828 if (!file->GetDirectory(dir)) file->mkdir(dir);
829 file->cd(dir);
830 }
6cd44ee0 831 if (fDebug > 0) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1be433fc 832 if (output->GetData()->InheritsFrom(TCollection::Class())) {
833 // If data is a collection, we set the name of the collection
834 // as the one of the container and we save as a single key.
835 TCollection *coll = (TCollection*)output->GetData();
836 coll->SetName(output->GetName());
837 coll->Write(output->GetName(), TObject::kSingleKey);
838 } else {
cbc8747a 839 if (output->GetData()->InheritsFrom(TTree::Class())) {
840 TTree *tree = (TTree*)output->GetData();
7a151c06 841 tree->SetDirectory(gDirectory);
cbc8747a 842 tree->AutoSave();
843 } else {
844 output->GetData()->Write();
845 }
1be433fc 846 }
8e6e6fe8 847 if (opwd) opwd->cd();
57756ec5 848 }
849 gROOT->cd();
8e6e6fe8 850 next1.Reset();
851 while ((output=(AliAnalysisDataContainer*)next1())) {
852 // Close all files at output
853 TDirectory *opwd = gDirectory;
f5e61abd 854 if (output->GetFile()) {
f3c07fbd 855 // Clear file list to release object ownership to user.
160e7161 856// output->GetFile()->Clear();
f5e61abd 857 output->GetFile()->Close();
84fcd93f 858 output->SetFile(NULL);
f5e61abd 859 // Copy merged outputs in alien if requested
860 if (fSpecialOutputLocation.Length() &&
861 fSpecialOutputLocation.BeginsWith("alien://")) {
862 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
863 TFile::Cp(output->GetFile()->GetName(),
864 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
865 }
866 }
8d7d3b59 867 if (opwd) opwd->cd();
8c0ab8e8 868 }
6cd44ee0 869 delete allOutputs;
8c0ab8e8 870
8c0ab8e8 871 if (getsysInfo) {
b6db1d18 872 TDirectory *crtdir = gDirectory;
8c0ab8e8 873 TFile f("syswatch.root", "RECREATE");
096b5a2e 874 TH1 *hist;
875 TString cut;
8c0ab8e8 876 if (!f.IsZombie()) {
877 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
096b5a2e 878 tree->SetName("syswatch");
8c0ab8e8 879 tree->SetMarkerStyle(kCircle);
880 tree->SetMarkerColor(kBlue);
881 tree->SetMarkerSize(0.5);
882 if (!gROOT->IsBatch()) {
883 tree->SetAlias("event", "id0");
096b5a2e 884 tree->SetAlias("task", "id1");
885 tree->SetAlias("stage", "id2");
886 // Already defined aliases
887 // tree->SetAlias("deltaT","stampSec-stampOldSec");
888 // tree->SetAlias("T","stampSec-first");
889 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
890 // tree->SetAlias("VM","pI.fMemVirtual");
891 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
892 Int_t npads = 1 /*COO plot for all tasks*/ +
893 fTopTasks->GetEntries() /*Exec plot per task*/ +
894 1 /*Terminate plot for all tasks*/ +
895 1; /*vm plot*/
896
897 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
898 if (npads<iopt*(iopt+1))
899 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
900 else
901 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
902 Int_t ipad = 1;
903 // draw the plot of deltaVM for Exec for each task
779e9992 904 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
096b5a2e 905 task = (AliAnalysisTask*)fTopTasks->At(itask);
906 canvas->cd(ipad++);
907 cut = Form("task==%d && stage==1", itask);
908 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
909 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
910 if (hist) {
911 hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
912 hist->GetYaxis()->SetTitle("deltaVM [kB]");
913 }
914 }
915 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
916 canvas->cd(ipad++);
917 tree->SetMarkerStyle(kFullTriangleUp);
918 tree->SetMarkerColor(kRed);
919 tree->SetMarkerSize(0.8);
920 cut = "task>=0 && task<1000 && stage==0";
921 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
922 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
923 if (hist) {
924 hist->SetTitle("Memory in CreateOutputObjects()");
925 hist->GetYaxis()->SetTitle("deltaVM [kB]");
926 hist->GetXaxis()->SetTitle("task");
927 }
928 // draw the plot of deltaVM for Terminate for all tasks
929 canvas->cd(ipad++);
930 tree->SetMarkerStyle(kOpenSquare);
931 tree->SetMarkerColor(kMagenta);
932 cut = "task>=0 && task<1000 && stage==2";
933 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
934 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
935 if (hist) {
936 hist->SetTitle("Memory in Terminate()");
937 hist->GetYaxis()->SetTitle("deltaVM [kB]");
938 hist->GetXaxis()->SetTitle("task");
939 }
940 // Full VM profile
941 canvas->cd(ipad++);
942 tree->SetMarkerStyle(kFullCircle);
943 tree->SetMarkerColor(kGreen);
944 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
945 tree->Draw("VM:event",cut,"", 1234567890, 0);
946 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
947 if (hist) {
948 hist->SetTitle("Virtual memory");
949 hist->GetYaxis()->SetTitle("VM [kB]");
950 }
951 canvas->Modified();
8c0ab8e8 952 }
096b5a2e 953 tree->SetMarkerStyle(kCircle);
954 tree->SetMarkerColor(kBlue);
955 tree->SetMarkerSize(0.5);
8c0ab8e8 956 tree->Write();
957 f.Close();
958 delete tree;
959 }
b6db1d18 960 if (crtdir) crtdir->cd();
923e2ca5 961 }
962 // Validate the output files
963 if (ValidateOutputFiles()) {
964 ofstream out;
965 out.open("outputs_valid", ios::out);
966 out.close();
57756ec5 967 }
968 cdir->cd();
84fcd93f 969 if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 970}
096b5a2e 971//______________________________________________________________________________
972void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
973{
974// Profiles the task having the itop index in the list of top (first level) tasks.
975 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
976 if (!task) {
977 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
978 return;
979 }
980 ProfileTask(task->GetName(), option);
981}
982
983//______________________________________________________________________________
984void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
985{
986// Profile a managed task after the execution of the analysis in case NSysInfo
987// was used.
988 if (gSystem->AccessPathName("syswatch.root")) {
989 Error("ProfileTask", "No file syswatch.root found in the current directory");
990 return;
991 }
992 if (gROOT->IsBatch()) return;
993 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
994 if (!task) {
995 Error("ProfileTask", "No top task named %s known by the manager.", name);
996 return;
997 }
998 Int_t itop = fTopTasks->IndexOf(task);
999 Int_t itask = fTasks->IndexOf(task);
1000 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1001 TDirectory *cdir = gDirectory;
1002 TFile f("syswatch.root");
1003 TTree *tree = (TTree*)f.Get("syswatch");
1004 if (!tree) {
1005 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1006 return;
1007 }
1008 if (fDebug > 0) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1009 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1010 canvas->Divide(2, 2, 0.01, 0.01);
1011 Int_t ipad = 1;
1012 TString cut;
1013 TH1 *hist;
1014 // VM profile for COO and Terminate methods
1015 canvas->cd(ipad++);
1016 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1017 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1018 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1019 if (hist) {
1020 hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1021 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1022 hist->GetXaxis()->SetTitle("method");
1023 }
1024 // CPU profile per event
1025 canvas->cd(ipad++);
1026 cut = Form("task==%d && stage==1",itop);
1027 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1028 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1029 if (hist) {
1030 hist->SetTitle("Execution time per event");
1031 hist->GetYaxis()->SetTitle("CPU/event [s]");
1032 }
1033 // VM profile for Exec
1034 canvas->cd(ipad++);
1035 cut = Form("task==%d && stage==1",itop);
1036 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1037 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1038 if (hist) {
1039 hist->SetTitle("Alocated VM[kB] per event");
1040 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1041 }
1042 canvas->Modified();
1043 delete tree;
1044 f.Close();
1045 if (cdir) cdir->cd();
1046}
d3106602 1047
1048//______________________________________________________________________________
1049void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1050{
1051// Adds a user task to the global list of tasks.
8d7d3b59 1052 if (fTasks->FindObject(task)) {
1053 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1054 return;
1055 }
d3106602 1056 task->SetActive(kFALSE);
1057 fTasks->Add(task);
1058}
1059
1060//______________________________________________________________________________
1061AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1062{
1063// Retreive task by name.
1064 if (!fTasks) return NULL;
1065 return (AliAnalysisTask*)fTasks->FindObject(name);
1066}
1067
1068//______________________________________________________________________________
1069AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 1070 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 1071{
1072// Create a data container of a certain type. Types can be:
84fcd93f 1073// kExchangeContainer = 0, used to exchange data between tasks
d3106602 1074// kInputContainer = 1, used to store input data
84fcd93f 1075// kOutputContainer = 2, used for writing result to a file
1076// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1077// the output object to a folder inside the output file
b1310ef5 1078 if (fContainers->FindObject(name)) {
923e2ca5 1079 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 1080 return NULL;
1081 }
d3106602 1082 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1083 fContainers->Add(cont);
1084 switch (type) {
1085 case kInputContainer:
1086 fInputs->Add(cont);
1087 break;
1088 case kOutputContainer:
1089 fOutputs->Add(cont);
8c0ab8e8 1090 if (filename && strlen(filename)) {
1091 cont->SetFileName(filename);
6cd44ee0 1092 cont->SetDataOwned(kFALSE); // data owned by the file
1093 }
1094 break;
1095 case kParamContainer:
1096 fParamCont->Add(cont);
1097 if (filename && strlen(filename)) {
1098 cont->SetFileName(filename);
8c0ab8e8 1099 cont->SetDataOwned(kFALSE); // data owned by the file
1100 }
d3106602 1101 break;
c52c2132 1102 case kExchangeContainer:
d3106602 1103 break;
1104 }
1105 return cont;
1106}
1107
1108//______________________________________________________________________________
1109Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1110 AliAnalysisDataContainer *cont)
1111{
1112// Connect input of an existing task to a data container.
60a04972 1113 if (!task) {
1114 Error("ConnectInput", "Task pointer is NULL");
1115 return kFALSE;
1116 }
d3106602 1117 if (!fTasks->FindObject(task)) {
1118 AddTask(task);
8d7d3b59 1119 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 1120 }
1121 Bool_t connected = task->ConnectInput(islot, cont);
1122 return connected;
1123}
1124
1125//______________________________________________________________________________
1126Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1127 AliAnalysisDataContainer *cont)
1128{
1129// Connect output of an existing task to a data container.
60a04972 1130 if (!task) {
1131 Error("ConnectOutput", "Task pointer is NULL");
1132 return kFALSE;
1133 }
d3106602 1134 if (!fTasks->FindObject(task)) {
1135 AddTask(task);
c52c2132 1136 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 1137 }
1138 Bool_t connected = task->ConnectOutput(islot, cont);
1139 return connected;
1140}
1141
1142//______________________________________________________________________________
1143void AliAnalysisManager::CleanContainers()
1144{
1145// Clean data from all containers that have already finished all client tasks.
1146 TIter next(fContainers);
1147 AliAnalysisDataContainer *cont;
1148 while ((cont=(AliAnalysisDataContainer *)next())) {
1149 if (cont->IsOwnedData() &&
1150 cont->IsDataReady() &&
1151 cont->ClientsExecuted()) cont->DeleteData();
1152 }
1153}
1154
1155//______________________________________________________________________________
1156Bool_t AliAnalysisManager::InitAnalysis()
1157{
1158// Initialization of analysis chain of tasks. Should be called after all tasks
1159// and data containers are properly connected
923e2ca5 1160 // Reset flag and remove valid_outputs file if exists
d3106602 1161 fInitOK = kFALSE;
923e2ca5 1162 if (!gSystem->AccessPathName("outputs_valid"))
1163 gSystem->Unlink("outputs_valid");
d3106602 1164 // Check for top tasks (depending only on input data containers)
1165 if (!fTasks->First()) {
c52c2132 1166 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 1167 return kFALSE;
1168 }
1169 TIter next(fTasks);
1170 AliAnalysisTask *task;
1171 AliAnalysisDataContainer *cont;
1172 Int_t ntop = 0;
1173 Int_t nzombies = 0;
327eaf46 1174 Bool_t iszombie = kFALSE;
1175 Bool_t istop = kTRUE;
d3106602 1176 Int_t i;
1177 while ((task=(AliAnalysisTask*)next())) {
327eaf46 1178 istop = kTRUE;
1179 iszombie = kFALSE;
d3106602 1180 Int_t ninputs = task->GetNinputs();
d3106602 1181 for (i=0; i<ninputs; i++) {
1182 cont = task->GetInputSlot(i)->GetContainer();
1183 if (!cont) {
327eaf46 1184 if (!iszombie) {
d3106602 1185 task->SetZombie();
1186 fZombies->Add(task);
1187 nzombies++;
327eaf46 1188 iszombie = kTRUE;
d3106602 1189 }
c52c2132 1190 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1191 i, task->GetName());
d3106602 1192 }
327eaf46 1193 if (iszombie) continue;
d3106602 1194 // Check if cont is an input container
327eaf46 1195 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 1196 // Connect to parent task
1197 }
327eaf46 1198 if (istop) {
d3106602 1199 ntop++;
1200 fTopTasks->Add(task);
1201 }
1202 }
1203 if (!ntop) {
c52c2132 1204 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 1205 return kFALSE;
1206 }
1207 // Check now if there are orphan tasks
1208 for (i=0; i<ntop; i++) {
1209 task = (AliAnalysisTask*)fTopTasks->At(i);
1210 task->SetUsed();
1211 }
1212 Int_t norphans = 0;
1213 next.Reset();
1214 while ((task=(AliAnalysisTask*)next())) {
1215 if (!task->IsUsed()) {
1216 norphans++;
c52c2132 1217 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 1218 }
1219 }
1220 // Check the task hierarchy (no parent task should depend on data provided
1221 // by a daughter task)
1222 for (i=0; i<ntop; i++) {
1223 task = (AliAnalysisTask*)fTopTasks->At(i);
1224 if (task->CheckCircularDeps()) {
c52c2132 1225 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 1226 PrintStatus("dep");
1227 return kFALSE;
1228 }
1229 }
b1310ef5 1230 // Check that all containers feeding post-event loop tasks are in the outputs list
1231 TIter nextcont(fContainers); // loop over all containers
1232 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1233 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1234 if (cont->HasConsumers()) {
1235 // Check if one of the consumers is post event loop
1236 TIter nextconsumer(cont->GetConsumers());
1237 while ((task=(AliAnalysisTask*)nextconsumer())) {
1238 if (task->IsPostEventLoop()) {
1239 fOutputs->Add(cont);
1240 break;
1241 }
1242 }
1243 }
1244 }
1245 }
8d7d3b59 1246 // Check if all special output containers have a file name provided
1247 TIter nextout(fOutputs);
1248 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1249 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1250 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1251 return kFALSE;
1252 }
1253 }
327eaf46 1254 fInitOK = kTRUE;
d3106602 1255 return kTRUE;
1256}
1257
1258//______________________________________________________________________________
1259void AliAnalysisManager::PrintStatus(Option_t *option) const
1260{
1261// Print task hierarchy.
8c0ab8e8 1262 if (!fInitOK) {
1263 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1264 return;
1265 }
1266 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1267 if (getsysInfo)
1268 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1269 TIter next(fTopTasks);
1270 AliAnalysisTask *task;
1271 while ((task=(AliAnalysisTask*)next()))
1272 task->PrintTask(option);
1273}
1274
1275//______________________________________________________________________________
1276void AliAnalysisManager::ResetAnalysis()
1277{
1278// Reset all execution flags and clean containers.
1279 CleanContainers();
1280}
1281
c52c2132 1282//______________________________________________________________________________
61505f8b 1283Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1284{
aee5ee44 1285// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1286// MIX. Process nentries starting from firstentry
bf574918 1287 Long64_t retv = 0;
57756ec5 1288 // Backup current directory and make sure gDirectory points to gROOT
1289 TDirectory *cdir = gDirectory;
1290 gROOT->cd();
c52c2132 1291 if (!fInitOK) {
1292 Error("StartAnalysis","Analysis manager was not initialized !");
57756ec5 1293 cdir->cd();
1f87e9fb 1294 return -1;
c52c2132 1295 }
84fcd93f 1296 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
c52c2132 1297 TString anaType = type;
1298 anaType.ToLower();
1299 fMode = kLocalAnalysis;
c57f56b7 1300 Bool_t runlocalinit = kTRUE;
90a4b3ee 1301 if (anaType.Contains("file")) {
1302 runlocalinit = kFALSE;
90a4b3ee 1303 }
4ab472d4 1304 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1305 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1306 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1307
c52c2132 1308 if (fMode == kGridAnalysis) {
f866cba5 1309 if (!anaType.Contains("terminate")) {
1310 if (!fGridHandler) {
1311 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1312 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
57756ec5 1313 cdir->cd();
f866cba5 1314 return -1;
1315 }
1316 // Write analysis manager in the analysis file
1317 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1318 // run local task configuration
1319 TIter nextTask(fTasks);
1320 AliAnalysisTask *task;
1321 while ((task=(AliAnalysisTask*)nextTask())) {
1322 task->LocalInit();
57756ec5 1323 gROOT->cd();
f866cba5 1324 }
1325 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1326 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
57756ec5 1327 cdir->cd();
f866cba5 1328 return -1;
1329 }
c57f56b7 1330
f866cba5 1331 // Terminate grid analysis
57756ec5 1332 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1333 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
f866cba5 1334 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1335 if (!fGridHandler->MergeOutputs()) {
1336 // Return if outputs could not be merged or if it alien handler
1337 // was configured for offline mode or local testing.
57756ec5 1338 cdir->cd();
f866cba5 1339 return 0;
1340 }
1341 }
1342 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
c57f56b7 1343 ImportWrappers(NULL);
1344 Terminate();
57756ec5 1345 cdir->cd();
1f87e9fb 1346 return 0;
981f2614 1347 }
d86ed856 1348 char line[256];
efd53803 1349 SetEventLoop(kFALSE);
8d7d3b59 1350 // Enable event loop mode if a tree was provided
aee5ee44 1351 if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1352
8c0ab8e8 1353 TChain *chain = 0;
1354 TString ttype = "TTree";
4ab472d4 1355 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1356 chain = (TChain*)tree;
6b742510 1357 if (!chain || !chain->GetListOfFiles()->First()) {
1358 Error("StartAnalysis", "Cannot process null or empty chain...");
57756ec5 1359 cdir->cd();
1f87e9fb 1360 return -1;
6b742510 1361 }
8c0ab8e8 1362 ttype = "TChain";
1363 }
9b33830a 1364
096b5a2e 1365 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1366 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
aee5ee44 1367 // Initialize locally all tasks (happens for all modes)
9b33830a 1368 TIter next(fTasks);
1369 AliAnalysisTask *task;
c57f56b7 1370 if (runlocalinit) {
1371 while ((task=(AliAnalysisTask*)next())) {
1372 task->LocalInit();
57756ec5 1373 gROOT->cd();
c57f56b7 1374 }
096b5a2e 1375 if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
c57f56b7 1376 }
efd53803 1377
c52c2132 1378 switch (fMode) {
1379 case kLocalAnalysis:
1380 if (!tree) {
03a5cc9f 1381 TIter nextT(fTasks);
981f2614 1382 // Call CreateOutputObjects for all tasks
096b5a2e 1383 Int_t itask = 0;
03a5cc9f 1384 while ((task=(AliAnalysisTask*)nextT())) {
c5a87c56 1385 task->CreateOutputObjects();
096b5a2e 1386 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
57756ec5 1387 gROOT->cd();
096b5a2e 1388 itask++;
c5a87c56 1389 }
06a59280 1390 if (IsExternalLoop()) {
1391 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1392 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1f87e9fb 1393 return 0;
57756ec5 1394 }
c52c2132 1395 ExecAnalysis();
981f2614 1396 Terminate();
1f87e9fb 1397 return 0;
c52c2132 1398 }
1399 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1400 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
aee5ee44 1401 fSelector = new AliAnalysisSelector(this);
bf574918 1402 retv = tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1403 break;
1404 case kProofAnalysis:
1405 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1406 Error("StartAnalysis", "No PROOF!!! Exiting.");
57756ec5 1407 cdir->cd();
1f87e9fb 1408 return -1;
c52c2132 1409 }
1410 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1411 gROOT->ProcessLine(line);
1412 if (chain) {
1413 chain->SetProof();
1414 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
bf574918 1415 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1416 } else {
61505f8b 1417 Error("StartAnalysis", "No chain!!! Exiting.");
57756ec5 1418 cdir->cd();
1f87e9fb 1419 return -1;
c52c2132 1420 }
1421 break;
1422 case kGridAnalysis:
1423 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
aee5ee44 1424 break;
1425 case kMixingAnalysis:
1426 // Run event mixing analysis
1427 if (!fEventPool) {
1428 Error("StartAnalysis", "Cannot run event mixing without event pool");
57756ec5 1429 cdir->cd();
1f87e9fb 1430 return -1;
aee5ee44 1431 }
1432 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1433 fSelector = new AliAnalysisSelector(this);
aee5ee44 1434 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1435 next.Reset();
aee5ee44 1436 // Call NotifyBinChange for all tasks
1437 while ((task=(AliAnalysisTask*)next()))
1438 if (!task->IsPostEventLoop()) task->NotifyBinChange();
bf574918 1439 retv = chain->Process(fSelector);
1440 if (retv < 0) {
1441 Error("StartAnalysis", "Mixing analysis failed");
57756ec5 1442 cdir->cd();
bf574918 1443 return retv;
1444 }
aee5ee44 1445 }
1446 PackOutput(fSelector->GetOutputList());
1447 Terminate();
1f87e9fb 1448 }
57756ec5 1449 cdir->cd();
bf574918 1450 return retv;
c52c2132 1451}
1452
d86ed856 1453//______________________________________________________________________________
1f87e9fb 1454Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
d86ed856 1455{
1456// Start analysis for this manager on a given dataset. Analysis task can be:
1457// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1458 if (!fInitOK) {
1459 Error("StartAnalysis","Analysis manager was not initialized !");
1f87e9fb 1460 return -1;
d86ed856 1461 }
84fcd93f 1462 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
d86ed856 1463 TString anaType = type;
1464 anaType.ToLower();
1465 if (!anaType.Contains("proof")) {
d140f7fb 1466 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1f87e9fb 1467 return -1;
d86ed856 1468 }
1469 fMode = kProofAnalysis;
1470 char line[256];
1471 SetEventLoop(kTRUE);
1472 // Set the dataset flag
1473 TObject::SetBit(kUseDataSet);
1474 fTree = 0;
1475
1476 // Initialize locally all tasks
1477 TIter next(fTasks);
1478 AliAnalysisTask *task;
1479 while ((task=(AliAnalysisTask*)next())) {
1480 task->LocalInit();
1481 }
1482
1483 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1484 Error("StartAnalysis", "No PROOF!!! Exiting.");
1f87e9fb 1485 return -1;
d86ed856 1486 }
1487 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1488 gROOT->ProcessLine(line);
1489 sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1490 if (!gROOT->ProcessLine(line)) {
1491 Error("StartAnalysis", "Dataset %s not found", dataset);
1f87e9fb 1492 return -1;
d86ed856 1493 }
1494 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1495 dataset, nentries, firstentry);
1496 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
bf574918 1497 Long_t retv = (Long_t)gROOT->ProcessLine(line);
1498 return retv;
d86ed856 1499}
1500
d3106602 1501//______________________________________________________________________________
84fcd93f 1502TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1503{
1504// Opens according the option the file specified by cont->GetFileName() and changes
1505// current directory to cont->GetFolderName(). If the file was already opened, it
1506// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1507// be optionally ignored.
1508 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1509 TString filename = cont->GetFileName();
1510 TFile *f = NULL;
1511 if (filename.IsNull()) {
1512 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1513 return NULL;
1514 }
1515 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1516 && !ignoreProof)
1517 f = mgr->OpenProofFile(cont,option);
1518 else {
1519 // Check first if the file is already opened
0f1b50f3 1520 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 1521 if (f) {
1522 // Check if option "UPDATE" was preserved
1523 TString opt(option);
1524 opt.ToUpper();
1525 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1526 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1527 } else {
0f1b50f3 1528 f = TFile::Open(filename, option);
84fcd93f 1529 }
1530 }
1531 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1532 cont->SetFile(f);
1533 // Cd to file
1534 f->cd();
1535 // Check for a folder request
1536 TString dir = cont->GetFolderName();
1537 if (!dir.IsNull()) {
1538 if (!f->GetDirectory(dir)) f->mkdir(dir);
1539 f->cd(dir);
1540 }
1541 return f;
1542 }
1543 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1544 cont->SetFile(NULL);
1545 return NULL;
1546}
1547
1548//______________________________________________________________________________
1549TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
8d7d3b59 1550{
1551// Opens a special output file used in PROOF.
84fcd93f 1552 TString line;
1553 TString filename = cont->GetFileName();
23c9468b 1554 if (cont == fCommonOutput) {
1555 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
61505f8b 1556 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 1557 }
84fcd93f 1558 TFile *f = NULL;
1559 if (fMode!=kProofAnalysis || !fSelector) {
1560 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1561 return NULL;
1562 }
1563 if (fSpecialOutputLocation.Length()) {
1564 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1565 if (f) {
1566 // Check if option "UPDATE" was preserved
1567 TString opt(option);
1568 opt.ToUpper();
23c9468b 1569 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1570 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1571 } else {
1572 f = new TFile(filename, option);
1573 }
1574 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1575 cont->SetFile(f);
1576 // Cd to file
1577 f->cd();
1578 // Check for a folder request
1579 TString dir = cont->GetFolderName();
1580 if (dir.Length()) {
1581 if (!f->GetDirectory(dir)) f->mkdir(dir);
1582 f->cd(dir);
1583 }
f5e61abd 1584 return f;
84fcd93f 1585 }
1586 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1587 cont->SetFile(NULL);
1588 return NULL;
1589 }
1590 // Check if there is already a proof output file in the output list
1591 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1592 if (pof) {
1593 // Get the actual file
1594 line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1595 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 1596 if (fDebug>1) {
1597 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1598 }
84fcd93f 1599 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1600 if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1601 // Check if option "UPDATE" was preserved
1602 TString opt(option);
1603 opt.ToUpper();
1604 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1605 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1606 } else {
90a4b3ee 1607 if (cont->IsRegisterDataset()) {
61505f8b 1608 TString dsetName = filename;
1609 dsetName.ReplaceAll(".root", cont->GetTitle());
1610 dsetName.ReplaceAll(":","_");
1611 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1612 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 1613 } else {
1614 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1615 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1616 }
84fcd93f 1617 if (fDebug > 1) printf("=== %s\n", line.Data());
1618 gROOT->ProcessLine(line);
1619 line = Form("pf->OpenFile(\"%s\");", option);
1620 gROOT->ProcessLine(line);
1621 f = gFile;
1622 if (fDebug > 1) {
8d7d3b59 1623 gROOT->ProcessLine("pf->Print()");
84fcd93f 1624 printf(" == proof file name: %s", f->GetName());
1625 }
1626 // Add to proof output list
1627 line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
90a4b3ee 1628 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 1629 gROOT->ProcessLine(line);
1630 }
1631 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1632 cont->SetFile(f);
1633 // Cd to file
1634 f->cd();
1635 // Check for a folder request
1636 TString dir = cont->GetFolderName();
1637 if (!dir.IsNull()) {
1638 if (!f->GetDirectory(dir)) f->mkdir(dir);
1639 f->cd(dir);
1640 }
1641 return f;
1642 }
1643 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1644 cont->SetFile(NULL);
1645 return NULL;
8d7d3b59 1646}
1647
1648//______________________________________________________________________________
d3106602 1649void AliAnalysisManager::ExecAnalysis(Option_t *option)
1650{
1651// Execute analysis.
8c0ab8e8 1652 static Long64_t ncalls = 0;
096b5a2e 1653 if (fDebug > 0) printf("MGR: Processing event #%lld\n", ncalls);
57756ec5 1654 TDirectory *cdir = gDirectory;
1655 gROOT->cd();
8c0ab8e8 1656 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
096b5a2e 1657 if (getsysInfo && ((ncalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)ncalls);
8c0ab8e8 1658 ncalls++;
327eaf46 1659 if (!fInitOK) {
57756ec5 1660 Error("ExecAnalysis", "Analysis manager was not initialized !");
1661 cdir->cd();
327eaf46 1662 return;
57756ec5 1663 }
d3106602 1664 AliAnalysisTask *task;
327eaf46 1665 // Check if the top tree is active.
1666 if (fTree) {
a8bc7397 1667 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1668 AliSysInfo::AddStamp("Handlers_BeginEventGroup",(Int_t)ncalls, 1002, 0);
327eaf46 1669 TIter next(fTasks);
1670 // De-activate all tasks
1671 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1672 AliAnalysisDataContainer *cont = fCommonInput;
1673 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1674 if (!cont) {
c52c2132 1675 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
57756ec5 1676 cdir->cd();
327eaf46 1677 return;
1678 }
1679 cont->SetData(fTree); // This will notify all consumers
57756ec5 1680 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 1681//
c3701689 1682// Call BeginEvent() for optional input/output and MC services
ed97dc98 1683 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1684 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1685 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 1686 gROOT->cd();
096b5a2e 1687 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1688 AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
6bb2b24f 1689//
1690// Execute the tasks
276941c8 1691// TIter next1(cont->GetConsumers());
1692 TIter next1(fTopTasks);
096b5a2e 1693 Int_t itask = 0;
327eaf46 1694 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1695 if (fDebug >1) {
1696 cout << " Executing task " << task->GetName() << endl;
096b5a2e 1697 }
327eaf46 1698 task->ExecuteTask(option);
57756ec5 1699 gROOT->cd();
096b5a2e 1700 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1701 AliSysInfo::AddStamp(task->ClassName(),(Int_t)ncalls, itask, 1);
1702 itask++;
327eaf46 1703 }
6bb2b24f 1704//
1705// Call FinishEvent() for optional output and MC services
6073f8c9 1706 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1707 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1708 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1709 // Gather system information if requested
1710 if (getsysInfo && ((ncalls%fNSysInfo)==0))
a8bc7397 1711 AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1001, 1);
57756ec5 1712 cdir->cd();
327eaf46 1713 return;
1714 }
1715 // The event loop is not controlled by TSelector
6bb2b24f 1716//
c3701689 1717// Call BeginEvent() for optional input/output and MC services
ed97dc98 1718 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1719 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1720 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
57756ec5 1721 gROOT->cd();
096b5a2e 1722 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1723 AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
327eaf46 1724 TIter next2(fTopTasks);
1725 while ((task=(AliAnalysisTask*)next2())) {
1726 task->SetActive(kTRUE);
c52c2132 1727 if (fDebug > 1) {
1728 cout << " Executing task " << task->GetName() << endl;
1729 }
d3106602 1730 task->ExecuteTask(option);
57756ec5 1731 gROOT->cd();
327eaf46 1732 }
6bb2b24f 1733//
1734// Call FinishEvent() for optional output and MC services
6073f8c9 1735 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1736 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1737 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
096b5a2e 1738 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1739 AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1);
57756ec5 1740 cdir->cd();
d3106602 1741}
1742
1743//______________________________________________________________________________
61505f8b 1744void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 1745{
1746// Set the input event handler and create a container for it.
1747 fInputEventHandler = handler;
d958c3ea 1748 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ff92d2b1 1749// Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 1750}
1751
1752//______________________________________________________________________________
61505f8b 1753void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 1754{
1755// Set the input event handler and create a container for it.
1756 fOutputEventHandler = handler;
d958c3ea 1757 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 1758 fCommonOutput->SetSpecialOutput();
ff92d2b1 1759// Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 1760}
c07b9ce2 1761
1762//______________________________________________________________________________
1763void AliAnalysisManager::RegisterExtraFile(const char *fname)
1764{
1765// This method is used externally to register output files which are not
1766// connected to any output container, so that the manager can properly register,
1767// retrieve or merge them when running in distributed mode. The file names are
1768// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 1769 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 1770 if (fExtraFiles.Length()) fExtraFiles += " ";
1771 fExtraFiles += fname;
1772}
1773
1774//______________________________________________________________________________
61505f8b 1775Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 1776{
1777// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 1778 char fullPath[512];
1779 char chUrl[512];
c07b9ce2 1780 TObject *pof = source->FindObject(filename);
1781 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1782 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1783 return kFALSE;
1784 }
61505f8b 1785 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", fullPath, pof));
1786 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", chUrl));
1787 TString clientUrl(chUrl);
1788 TString fullPath_str(fullPath);
c07b9ce2 1789 if (clientUrl.Contains("localhost")){
61505f8b 1790 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 1791 TObjString *strobj = ( TObjString *)array->At(1);
1792 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1793 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 1794 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1795 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1796 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 1797 delete arrayPort;
1798 delete array;
1799 }
1800 if (fDebug > 1)
61505f8b 1801 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", fullPath_str.Data());
1802 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 1803 if (!gotit)
1804 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1805 return gotit;
1806}
d29168d6 1807
1808//______________________________________________________________________________
1809void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1810{
1811// Fill analysis type in the provided string.
1812 switch (fMode) {
1813 case kLocalAnalysis:
1814 type = "local";
1815 return;
1816 case kProofAnalysis:
1817 type = "proof";
1818 return;
1819 case kGridAnalysis:
1820 type = "grid";
1821 return;
1822 case kMixingAnalysis:
1823 type = "mix";
1824 }
1825}
923e2ca5 1826
1827//______________________________________________________________________________
1828Bool_t AliAnalysisManager::ValidateOutputFiles() const
1829{
1830// Validate all output files.
1831 TIter next(fOutputs);
1832 AliAnalysisDataContainer *output;
1833 TDirectory *cdir = gDirectory;
84fcd93f 1834 TString openedFiles;
923e2ca5 1835 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 1836 if (output->IsRegisterDataset()) continue;
923e2ca5 1837 TString filename = output->GetFileName();
1838 if (filename == "default") {
1839 if (!fOutputEventHandler) continue;
1840 filename = fOutputEventHandler->GetOutputFileName();
b3685485 1841 // Main AOD may not be there
1842 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 1843 }
1844 // Check if the file is closed
84fcd93f 1845 if (openedFiles.Contains(filename)) continue;;
923e2ca5 1846 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1847 if (file) {
1848 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 1849 // Clear file list to release object ownership to user.
160e7161 1850// file->Clear();
923e2ca5 1851 file->Close();
1852 }
1853 file = TFile::Open(filename);
1854 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1855 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1856 cdir->cd();
1857 return kFALSE;
1858 }
1859 file->Close();
84fcd93f 1860 openedFiles += filename;
1861 openedFiles += " ";
923e2ca5 1862 }
1863 cdir->cd();
1864 return kTRUE;
1865}
cd11251e 1866
1867//______________________________________________________________________________
61505f8b 1868void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 1869{
1870// Implements a nice text mode progress bar.
1871 static Long64_t icount = 0;
1872 static TString oname;
1873 static TString nname;
1874 static Long64_t ocurrent = 0;
1875 static Long64_t osize = 0;
1876 static Int_t oseconds = 0;
1877 static TStopwatch *owatch = 0;
1878 static Bool_t oneoftwo = kFALSE;
1879 static Int_t nrefresh = 0;
1880 static Int_t nchecks = 0;
1881 const char symbol[4] = {'=','\\','|','/'};
1882 char progress[11] = " ";
1883 Int_t ichar = icount%4;
1884
1885 if (!refresh) {
1886 nrefresh = 0;
1887 if (!size) return;
1888 owatch = watch;
1889 oname = opname;
1890 ocurrent = TMath::Abs(current);
1891 osize = TMath::Abs(size);
1892 if (ocurrent > osize) ocurrent=osize;
1893 } else {
1894 nrefresh++;
1895 if (!osize) return;
1896 }
1897 icount++;
1898 Double_t time = 0.;
1899 Int_t hours = 0;
1900 Int_t minutes = 0;
1901 Int_t seconds = 0;
1902 if (owatch && !last) {
1903 owatch->Stop();
1904 time = owatch->RealTime();
1905 hours = (Int_t)(time/3600.);
1906 time -= 3600*hours;
1907 minutes = (Int_t)(time/60.);
1908 time -= 60*minutes;
1909 seconds = (Int_t)time;
1910 if (refresh) {
1911 if (oseconds==seconds) {
1912 owatch->Continue();
1913 return;
1914 }
1915 oneoftwo = !oneoftwo;
1916 }
1917 oseconds = seconds;
1918 }
1919 if (refresh && oneoftwo) {
1920 nname = oname;
1921 if (nchecks <= 0) nchecks = nrefresh+1;
1922 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
1923 oname = Form(" == %d%% ==", pctdone);
1924 }
1925 Double_t percent = 100.0*ocurrent/osize;
1926 Int_t nchar = Int_t(percent/10);
1927 if (nchar>10) nchar=10;
1928 Int_t i;
1929 for (i=0; i<nchar; i++) progress[i] = '=';
1930 progress[nchar] = symbol[ichar];
1931 for (i=nchar+1; i<10; i++) progress[i] = ' ';
1932 progress[10] = '\0';
1933 oname += " ";
1934 oname.Remove(20);
1935 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
1936 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
1937 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
1938 if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d \r", percent, hours, minutes, seconds);
1939 else fprintf(stderr, "[%6.2f %%]\r", percent);
1940 if (refresh && oneoftwo) oname = nname;
1941 if (owatch) owatch->Continue();
1942 if (last) {
1943 icount = 0;
1944 owatch = 0;
1945 ocurrent = 0;
1946 osize = 0;
1947 oseconds = 0;
1948 oneoftwo = kFALSE;
1949 nrefresh = 0;
1950 fprintf(stderr, "\n");
1951 }
1952}