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