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