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