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