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