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