MakeProng() is called for fNProngs > 0
[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);
d3106602 92}
93
94//______________________________________________________________________________
95AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
c52c2132 96 :TNamed(other),
327eaf46 97 fTree(NULL),
8c0ab8e8 98 fInputEventHandler(NULL),
99 fOutputEventHandler(NULL),
100 fMCtruthEventHandler(NULL),
84fcd93f 101 fEventPool(NULL),
c52c2132 102 fCurrentEntry(-1),
8c0ab8e8 103 fNSysInfo(0),
c52c2132 104 fMode(other.fMode),
105 fInitOK(other.fInitOK),
106 fDebug(other.fDebug),
26f071d8 107 fSpecialOutputLocation(""),
37a26056 108 fTasks(NULL),
109 fTopTasks(NULL),
c52c2132 110 fZombies(NULL),
111 fContainers(NULL),
112 fInputs(NULL),
8d7d3b59 113 fOutputs(NULL),
60a04972 114 fCommonInput(NULL),
115 fCommonOutput(NULL),
c57f56b7 116 fSelector(NULL),
c07b9ce2 117 fGridHandler(NULL),
118 fExtraFiles()
d3106602 119{
120// Copy constructor.
37a26056 121 fTasks = new TObjArray(*other.fTasks);
122 fTopTasks = new TObjArray(*other.fTopTasks);
123 fZombies = new TObjArray(*other.fZombies);
c52c2132 124 fContainers = new TObjArray(*other.fContainers);
125 fInputs = new TObjArray(*other.fInputs);
126 fOutputs = new TObjArray(*other.fOutputs);
84fcd93f 127 fgCommonFileName = "AnalysisResults.root";
c52c2132 128 fgAnalysisManager = this;
d3106602 129}
130
131//______________________________________________________________________________
132AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
133{
134// Assignment
135 if (&other != this) {
c52c2132 136 TNamed::operator=(other);
54cff064 137 fInputEventHandler = other.fInputEventHandler;
6bb2b24f 138 fOutputEventHandler = other.fOutputEventHandler;
139 fMCtruthEventHandler = other.fMCtruthEventHandler;
c2922515 140 fEventPool = other.fEventPool;
c52c2132 141 fTree = NULL;
142 fCurrentEntry = -1;
8c0ab8e8 143 fNSysInfo = other.fNSysInfo;
c52c2132 144 fMode = other.fMode;
37a26056 145 fInitOK = other.fInitOK;
c52c2132 146 fDebug = other.fDebug;
37a26056 147 fTasks = new TObjArray(*other.fTasks);
148 fTopTasks = new TObjArray(*other.fTopTasks);
149 fZombies = new TObjArray(*other.fZombies);
c52c2132 150 fContainers = new TObjArray(*other.fContainers);
151 fInputs = new TObjArray(*other.fInputs);
152 fOutputs = new TObjArray(*other.fOutputs);
60a04972 153 fCommonInput = NULL;
154 fCommonOutput = NULL;
8d7d3b59 155 fSelector = NULL;
c57f56b7 156 fGridHandler = NULL;
c07b9ce2 157 fExtraFiles = other.fExtraFiles;
84fcd93f 158 fgCommonFileName = "AnalysisResults.root";
c52c2132 159 fgAnalysisManager = this;
d3106602 160 }
161 return *this;
162}
163
164//______________________________________________________________________________
165AliAnalysisManager::~AliAnalysisManager()
166{
167// Destructor.
d3106602 168 if (fTasks) {fTasks->Delete(); delete fTasks;}
169 if (fTopTasks) delete fTopTasks;
170 if (fZombies) delete fZombies;
c52c2132 171 if (fContainers) {fContainers->Delete(); delete fContainers;}
172 if (fInputs) delete fInputs;
173 if (fOutputs) delete fOutputs;
c57f56b7 174 if (fGridHandler) delete fGridHandler;
c52c2132 175 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
d3106602 176}
c52c2132 177
d3106602 178//______________________________________________________________________________
327eaf46 179Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
180{
181// Read one entry of the tree or a whole branch.
84fcd93f 182 if (fDebug > 0) printf("== AliAnalysisManager::GetEntry(%lld)\n", entry);
c52c2132 183 fCurrentEntry = entry;
327eaf46 184 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
185}
186
187//______________________________________________________________________________
2d626244 188Bool_t AliAnalysisManager::Init(TTree *tree)
d3106602 189{
190 // The Init() function is called when the selector needs to initialize
191 // a new tree or chain. Typically here the branch addresses of the tree
192 // will be set. It is normaly not necessary to make changes to the
193 // generated code, but the routine can be extended by the user if needed.
194 // Init() will be called many times when running with PROOF.
2d626244 195 Bool_t init = kFALSE;
196 if (!tree) return kFALSE; // Should not happen - protected in selector caller
8d7d3b59 197 if (fDebug > 0) {
84fcd93f 198 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
c52c2132 199 }
f3d59a0d 200 // Call InitTree of EventHandler
36e82a52 201 if (fOutputEventHandler) {
202 if (fMode == kProofAnalysis) {
2d626244 203 init = fOutputEventHandler->Init(0x0, "proof");
36e82a52 204 } else {
2d626244 205 init = fOutputEventHandler->Init(0x0, "local");
36e82a52 206 }
2d626244 207 if (!init) {
208 Error("Init", "Output event handler failed to initialize");
209 return kFALSE;
210 }
36e82a52 211 }
2d626244 212
fdb458ec 213 if (fInputEventHandler) {
36e82a52 214 if (fMode == kProofAnalysis) {
2d626244 215 init = fInputEventHandler->Init(tree, "proof");
36e82a52 216 } else {
2d626244 217 init = fInputEventHandler->Init(tree, "local");
36e82a52 218 }
2d626244 219 if (!init) {
220 Error("Init", "Input event handler failed to initialize tree");
221 return kFALSE;
222 }
e7ae3836 223 } else {
224 // If no input event handler we need to get the tree once
225 // for the chain
2d626244 226 if(!tree->GetTree()) {
227 Long64_t readEntry = tree->LoadTree(0);
228 if (readEntry == -2) {
229 Error("Init", "Input tree has no entry. Aborting");
230 return kFALSE;
231 }
232 }
36e82a52 233 }
234
235 if (fMCtruthEventHandler) {
236 if (fMode == kProofAnalysis) {
2d626244 237 init = fMCtruthEventHandler->Init(0x0, "proof");
36e82a52 238 } else {
2d626244 239 init = fMCtruthEventHandler->Init(0x0, "local");
36e82a52 240 }
2d626244 241 if (!init) {
242 Error("Init", "MC event handler failed to initialize");
243 return kFALSE;
244 }
fdb458ec 245 }
246
c52c2132 247 if (!fInitOK) InitAnalysis();
2d626244 248 if (!fInitOK) return kFALSE;
327eaf46 249 fTree = tree;
ce46ecc1 250 AliAnalysisDataContainer *top = fCommonInput;
251 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
c52c2132 252 if (!top) {
8d7d3b59 253 Error("Init","No top input container !");
2d626244 254 return kFALSE;
37153431 255 }
327eaf46 256 top->SetData(tree);
8d7d3b59 257 if (fDebug > 0) {
84fcd93f 258 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
981f2614 259 }
2d626244 260 return kTRUE;
d3106602 261}
262
263//______________________________________________________________________________
327eaf46 264void AliAnalysisManager::SlaveBegin(TTree *tree)
d3106602 265{
266 // The SlaveBegin() function is called after the Begin() function.
267 // When running with PROOF SlaveBegin() is called on each slave server.
268 // The tree argument is deprecated (on PROOF 0 is passed).
84fcd93f 269 if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
aee5ee44 270 static Bool_t isCalled = kFALSE;
2d626244 271 Bool_t init = kFALSE;
272 Bool_t initOK = kTRUE;
273 TString msg;
4ab472d4 274 TDirectory *curdir = gDirectory;
aee5ee44 275 // Call SlaveBegin only once in case of mixing
276 if (isCalled && fMode==kMixingAnalysis) return;
f3d59a0d 277 // Call Init of EventHandler
278 if (fOutputEventHandler) {
279 if (fMode == kProofAnalysis) {
673f68ff 280 // Merging AOD's in PROOF via TProofOutputFile
84fcd93f 281 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
673f68ff 282 init = fOutputEventHandler->Init("proof");
283 if (!init) msg = "Failed to initialize output handler on worker";
f3d59a0d 284 } else {
2d626244 285 init = fOutputEventHandler->Init("local");
673f68ff 286 if (!init) msg = "Failed to initialize output handler";
f3d59a0d 287 }
2d626244 288 initOK &= init;
289 if (!fSelector) Error("SlaveBegin", "Selector not set");
290 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 291 }
292
293 if (fInputEventHandler) {
294 fInputEventHandler->SetInputTree(tree);
295 if (fMode == kProofAnalysis) {
2d626244 296 init = fInputEventHandler->Init("proof");
297 if (!init) msg = "Failed to initialize input handler on worker";
f3d59a0d 298 } else {
2d626244 299 init = fInputEventHandler->Init("local");
300 if (!init) msg = "Failed to initialize input handler";
f3d59a0d 301 }
2d626244 302 initOK &= init;
303 if (!fSelector) Error("SlaveBegin", "Selector not set");
304 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 305 }
306
307 if (fMCtruthEventHandler) {
308 if (fMode == kProofAnalysis) {
2d626244 309 init = fMCtruthEventHandler->Init("proof");
310 if (!init) msg = "Failed to initialize MC handler on worker";
f3d59a0d 311 } else {
2d626244 312 init = fMCtruthEventHandler->Init("local");
313 if (!init) msg = "Failed to initialize MC handler";
f3d59a0d 314 }
2d626244 315 initOK &= init;
316 if (!fSelector) Error("SlaveBegin", "Selector not set");
317 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 318 }
4ab472d4 319 if (curdir) curdir->cd();
2d626244 320 isCalled = kTRUE;
321 if (!initOK) return;
c52c2132 322 TIter next(fTasks);
323 AliAnalysisTask *task;
324 // Call CreateOutputObjects for all tasks
c5a87c56 325 while ((task=(AliAnalysisTask*)next())) {
4ab472d4 326 curdir = gDirectory;
c52c2132 327 task->CreateOutputObjects();
c5a87c56 328 if (curdir) curdir->cd();
36e82a52 329 }
84fcd93f 330 if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
d3106602 331}
332
333//______________________________________________________________________________
327eaf46 334Bool_t AliAnalysisManager::Notify()
335{
336 // The Notify() function is called when a new file is opened. This
337 // can be either for a new TTree in a TChain or when when a new TTree
338 // is started when using PROOF. It is normaly not necessary to make changes
339 // to the generated code, but the routine can be extended by the
340 // user if needed. The return value is currently not used.
2d626244 341 if (!fTree) return kFALSE;
342
8d7d3b59 343 TFile *curfile = fTree->GetCurrentFile();
344 if (!curfile) {
345 Error("Notify","No current file");
346 return kFALSE;
347 }
348
84fcd93f 349 if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
8d7d3b59 350 TIter next(fTasks);
351 AliAnalysisTask *task;
352 // Call Notify for all tasks
353 while ((task=(AliAnalysisTask*)next()))
354 task->Notify();
fdb458ec 355
8d7d3b59 356 // Call Notify of the event handlers
357 if (fInputEventHandler) {
358 fInputEventHandler->Notify(curfile->GetName());
359 }
6073f8c9 360
8d7d3b59 361 if (fOutputEventHandler) {
362 fOutputEventHandler->Notify(curfile->GetName());
363 }
890126ab 364
8d7d3b59 365 if (fMCtruthEventHandler) {
366 fMCtruthEventHandler->Notify(curfile->GetName());
367 }
84fcd93f 368 if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
8d7d3b59 369 return kTRUE;
327eaf46 370}
371
372//______________________________________________________________________________
373Bool_t AliAnalysisManager::Process(Long64_t entry)
d3106602 374{
375 // The Process() function is called for each entry in the tree (or possibly
376 // keyed object in the case of PROOF) to be processed. The entry argument
377 // specifies which entry in the currently loaded tree is to be processed.
378 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
379 // to read either all or the required parts of the data. When processing
380 // keyed objects with PROOF, the object is already loaded and is available
381 // via the fObject pointer.
382 //
383 // This function should contain the "body" of the analysis. It can contain
384 // simple or elaborate selection criteria, run algorithms on the data
385 // of the event and typically fill histograms.
386
387 // WARNING when a selector is used with a TChain, you must use
388 // the pointer to the current TTree to call GetEntry(entry).
389 // The entry is always the local entry number in the current tree.
390 // Assuming that fChain is the pointer to the TChain being processed,
391 // use fChain->GetTree()->GetEntry(entry).
84fcd93f 392 if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
8d7d3b59 393
ed97dc98 394 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
395 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
396 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 397
327eaf46 398 GetEntry(entry);
399 ExecAnalysis();
84fcd93f 400 if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
327eaf46 401 return kTRUE;
d3106602 402}
403
404//______________________________________________________________________________
c52c2132 405void AliAnalysisManager::PackOutput(TList *target)
d3106602 406{
981f2614 407 // Pack all output data containers in the output list. Called at SlaveTerminate
408 // stage in PROOF case for each slave.
84fcd93f 409 if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
c52c2132 410 if (!target) {
411 Error("PackOutput", "No target. Aborting.");
412 return;
37153431 413 }
6073f8c9 414 if (fInputEventHandler) fInputEventHandler ->Terminate();
6bb2b24f 415 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
416 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
8d7d3b59 417
418 // Call FinishTaskOutput() for each event loop task (not called for
419 // post-event loop tasks - use Terminate() fo those)
420 TIter nexttask(fTasks);
421 AliAnalysisTask *task;
422 while ((task=(AliAnalysisTask*)nexttask())) {
423 if (!task->IsPostEventLoop()) {
84fcd93f 424 if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
8d7d3b59 425 task->FinishTaskOutput();
84fcd93f 426 if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
8d7d3b59 427 }
428 }
8c9485b2 429
c52c2132 430 if (fMode == kProofAnalysis) {
431 TIter next(fOutputs);
432 AliAnalysisDataContainer *output;
4ab472d4 433 Bool_t isManagedByHandler = kFALSE;
c52c2132 434 while ((output=(AliAnalysisDataContainer*)next())) {
8d7d3b59 435 // Do not consider outputs of post event loop tasks
2b83ca27 436 isManagedByHandler = kFALSE;
8d7d3b59 437 if (output->GetProducer()->IsPostEventLoop()) continue;
4ab472d4 438 const char *filename = output->GetFileName();
439 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
440 isManagedByHandler = kTRUE;
84fcd93f 441 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
4ab472d4 442 filename = fOutputEventHandler->GetOutputFileName();
443 }
8d7d3b59 444 // Check if data was posted to this container. If not, issue an error.
4ab472d4 445 if (!output->GetData() && !isManagedByHandler) {
923e2ca5 446 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
8d7d3b59 447 continue;
448 }
449 if (!output->IsSpecialOutput()) {
450 // Normal outputs
4ab472d4 451 if (strlen(filename) && !isManagedByHandler) {
8d7d3b59 452 // Backup current folder
ca78991b 453 TDirectory *opwd = gDirectory;
84fcd93f 454 // File resident outputs
455 TFile *file = AliAnalysisManager::OpenFile(output, "RECREATE", kTRUE);
ca78991b 456 // Clear file list to release object ownership to user.
ca78991b 457 file->Clear();
8d7d3b59 458 // Save data to file, then close.
1be433fc 459 if (output->GetData()->InheritsFrom(TCollection::Class())) {
460 // If data is a collection, we set the name of the collection
461 // as the one of the container and we save as a single key.
462 TCollection *coll = (TCollection*)output->GetData();
463 coll->SetName(output->GetName());
464 coll->Write(output->GetName(), TObject::kSingleKey);
465 } else {
cbc8747a 466 if (output->GetData()->InheritsFrom(TTree::Class())) {
467 TTree *tree = (TTree*)output->GetData();
21d37b6f 468 // tree->SetDirectory(file);
cbc8747a 469 tree->AutoSave();
470 } else {
471 output->GetData()->Write();
472 }
1be433fc 473 }
84fcd93f 474 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
8d7d3b59 475 if (fDebug > 2) {
84fcd93f 476 printf(" file %s listing content:\n", filename);
8d7d3b59 477 file->ls();
478 }
ca78991b 479 file->Close();
84fcd93f 480 output->SetFile(NULL);
ca78991b 481 // Restore current directory
482 if (opwd) opwd->cd();
8d7d3b59 483 } else {
484 // Memory-resident outputs
84fcd93f 485 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
4ab472d4 486 }
487 AliAnalysisDataWrapper *wrap = 0;
488 if (isManagedByHandler) {
489 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
490 wrap->SetName(output->GetName());
ca78991b 491 }
4ab472d4 492 else wrap =output->ExportData();
cbc8747a 493 // Output wrappers must NOT delete data after merging - the user owns them
494 wrap->SetDeleteData(kFALSE);
8167b1d0 495 target->Add(wrap);
4ab472d4 496 } else {
f5e61abd 497 // Special outputs. The file must be opened and connected to the container.
d0864eb4 498 TDirectory *opwd = gDirectory;
8d7d3b59 499 TFile *file = output->GetFile();
f5e61abd 500 if (!file) {
501 AliAnalysisTask *producer = output->GetProducer();
84fcd93f 502 Fatal("PackOutput",
f5e61abd 503 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
504 output->GetFileName(), output->GetName(), producer->ClassName());
505 continue;
506 }
507 TString outFilename = file->GetName();
84fcd93f 508 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
4ab472d4 509 if (isManagedByHandler) {
510 // Terminate IO for files managed by the output handler
511 if (file) file->Write();
802f90ef 512 if (file && fDebug > 2) {
84fcd93f 513 printf(" handled file %s listing content:\n", file->GetName());
802f90ef 514 file->ls();
515 }
4ab472d4 516 fOutputEventHandler->TerminateIO();
f5e61abd 517 } else {
518 file->cd();
519 // Release object ownership to users after writing data to file
520 if (output->GetData()->InheritsFrom(TCollection::Class())) {
521 // If data is a collection, we set the name of the collection
522 // as the one of the container and we save as a single key.
523 TCollection *coll = (TCollection*)output->GetData();
524 coll->SetName(output->GetName());
525 coll->Write(output->GetName(), TObject::kSingleKey);
cbc8747a 526 } else {
f5e61abd 527 if (output->GetData()->InheritsFrom(TTree::Class())) {
528 TTree *tree = (TTree*)output->GetData();
529 tree->SetDirectory(file);
530 tree->AutoSave();
531 } else {
532 output->GetData()->Write();
533 }
534 }
535 file->Clear();
536 if (fDebug > 2) {
84fcd93f 537 printf(" file %s listing content:\n", output->GetFileName());
f5e61abd 538 file->ls();
539 }
540 file->Close();
84fcd93f 541 output->SetFile(NULL);
ef73322e 542 }
8d7d3b59 543 // Restore current directory
d0864eb4 544 if (opwd) opwd->cd();
8d7d3b59 545 // Check if a special output location was provided or the output files have to be merged
13ef3bb0 546 if (strlen(fSpecialOutputLocation.Data())) {
547 TString remote = fSpecialOutputLocation;
548 remote += "/";
ef788aee 549 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
f5e61abd 550 if (remote.BeginsWith("alien://")) {
551 gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
552 remote += outFilename;
553 remote.ReplaceAll(".root", Form("_%d.root", gid));
554 } else {
555 remote += Form("%s_%d_", gSystem->HostName(), gid);
556 remote += outFilename;
557 }
558 if (fDebug > 1)
559 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
560 output->GetName(), remote.Data());
ef73322e 561 TFile::Cp ( outFilename.Data(), remote.Data() );
c9e39043 562 // Copy extra outputs
563 if (fExtraFiles.Length() && isManagedByHandler) {
564 TObjArray *arr = fExtraFiles.Tokenize(" ");
565 TObjString *os;
566 TIter nextfilename(arr);
567 while ((os=(TObjString*)nextfilename())) {
568 outFilename = os->GetString();
569 remote = fSpecialOutputLocation;
570 remote += "/";
571 if (remote.BeginsWith("alien://")) {
572 remote += outFilename;
573 remote.ReplaceAll(".root", Form("_%d.root", gid));
574 } else {
575 remote += Form("%s_%d_", gSystem->HostName(), gid);
576 remote += outFilename;
577 }
578 if (fDebug > 1)
579 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
580 outFilename.Data(), remote.Data());
581 TFile::Cp ( outFilename.Data(), remote.Data() );
582 }
583 delete arr;
584 }
ca78991b 585 } else {
8d7d3b59 586 // No special location specified-> use TProofOutputFile as merging utility
587 // The file at this output slot must be opened in CreateOutputObjects
84fcd93f 588 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
13ef3bb0 589 }
590 }
c52c2132 591 }
592 }
84fcd93f 593 if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
c52c2132 594}
595
596//______________________________________________________________________________
981f2614 597void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 598{
981f2614 599// Import data in output containers from wrappers coming in source.
84fcd93f 600 if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
327eaf46 601 TIter next(fOutputs);
981f2614 602 AliAnalysisDataContainer *cont;
603 AliAnalysisDataWrapper *wrap;
604 Int_t icont = 0;
c57f56b7 605 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
84fcd93f 606 TDirectory *cdir = gDirectory;
c52c2132 607 while ((cont=(AliAnalysisDataContainer*)next())) {
0355fc48 608 wrap = 0;
c57f56b7 609 if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
4ab472d4 610 const char *filename = cont->GetFileName();
611 Bool_t isManagedByHandler = kFALSE;
612 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
613 isManagedByHandler = kTRUE;
614 filename = fOutputEventHandler->GetOutputFileName();
615 }
c57f56b7 616 if (cont->IsSpecialOutput() || inGrid) {
f5e61abd 617 if (strlen(fSpecialOutputLocation.Data())) continue;
c57f56b7 618 // Copy merged file from PROOF scratch space.
619 // In case of grid the files are already in the current directory.
620 if (!inGrid) {
c07b9ce2 621 if (isManagedByHandler && fExtraFiles.Length()) {
622 // Copy extra registered dAOD files.
623 TObjArray *arr = fExtraFiles.Tokenize(" ");
624 TObjString *os;
625 TIter nextfilename(arr);
626 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
627 delete arr;
c57f56b7 628 }
c07b9ce2 629 if (!GetFileFromWrapper(filename, source)) continue;
c57f56b7 630 }
8d7d3b59 631 // Normally we should connect data from the copied file to the
632 // corresponding output container, but it is not obvious how to do this
633 // automatically if several objects in file...
84fcd93f 634 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
635 if (!f) f = TFile::Open(filename, "READ");
dd197a68 636 if (!f) {
637 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
0355fc48 638 continue;
dd197a68 639 }
640 TObject *obj = 0;
84fcd93f 641 // Cd to the directory pointed by the container
642 TString folder = cont->GetFolderName();
643 if (!folder.IsNull()) f->cd(folder);
644 // Try to fetch first an object having the container name.
645 obj = gDirectory->Get(cont->GetName());
dd197a68 646 if (!obj) {
84fcd93f 647 Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()",
648 cont->GetName(), filename, cont->GetFolderName());
dd197a68 649 continue;
650 }
0355fc48 651 wrap = new AliAnalysisDataWrapper(obj);
652 wrap->SetDeleteData(kFALSE);
8d7d3b59 653 }
0355fc48 654 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 655 if (!wrap) {
656 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 657 continue;
658 }
981f2614 659 icont++;
8d7d3b59 660 if (fDebug > 1) {
84fcd93f 661 printf(" Importing data for container %s\n", cont->GetName());
662 if (strlen(filename)) printf(" -> file %s\n", filename);
663 else printf("\n");
8d7d3b59 664 }
981f2614 665 cont->ImportData(wrap);
84fcd93f 666 }
667 if (cdir) cdir->cd();
668 if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 669}
670
671//______________________________________________________________________________
672void AliAnalysisManager::UnpackOutput(TList *source)
673{
ca78991b 674 // Called by AliAnalysisSelector::Terminate only on the client.
84fcd93f 675 if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 676 if (!source) {
981f2614 677 Error("UnpackOutput", "No target. Aborting.");
c52c2132 678 return;
679 }
84fcd93f 680 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
c52c2132 681
981f2614 682 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 683
981f2614 684 TIter next(fOutputs);
c52c2132 685 AliAnalysisDataContainer *output;
686 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 687 if (!output->GetData()) continue;
b1310ef5 688 // Check if there are client tasks that run post event loop
689 if (output->HasConsumers()) {
690 // Disable event loop semaphore
691 output->SetPostEventLoop(kTRUE);
692 TObjArray *list = output->GetConsumers();
693 Int_t ncons = list->GetEntriesFast();
694 for (Int_t i=0; i<ncons; i++) {
695 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
696 task->CheckNotify(kTRUE);
697 // If task is active, execute it
698 if (task->IsPostEventLoop() && task->IsActive()) {
84fcd93f 699 if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 700 task->ExecuteTask();
701 }
702 }
703 }
c52c2132 704 }
84fcd93f 705 if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 706}
707
708//______________________________________________________________________________
709void AliAnalysisManager::Terminate()
710{
711 // The Terminate() function is the last function to be called during
712 // a query. It always runs on the client, it can be used to present
c52c2132 713 // the results graphically.
84fcd93f 714 if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
327eaf46 715 AliAnalysisTask *task;
a0e2e8b1 716 AliAnalysisDataContainer *output;
c52c2132 717 TIter next(fTasks);
a0e2e8b1 718 TStopwatch timer;
327eaf46 719 // Call Terminate() for tasks
a0e2e8b1 720 while ((task=(AliAnalysisTask*)next())) {
721 // Save all the canvases produced by the Terminate
722 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
a0e2e8b1 723 task->Terminate();
724 if (TObject::TestBit(kSaveCanvases)) {
226abfec 725 if (!gROOT->IsBatch()) {
726 Warning("Terminate", "Waiting 5 sec for %s::Terminate() to finish drawing", task->ClassName());
727 timer.Start();
728 while (timer.CpuTime()<5) {
729 timer.Continue();
730 gSystem->ProcessEvents();
731 }
732 }
733 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
734 if (iend==0) continue;
a0e2e8b1 735 TCanvas *canvas;
226abfec 736 for (Int_t ipict=0; ipict<iend; ipict++) {
737 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
a0e2e8b1 738 if (!canvas) continue;
739 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
226abfec 740 }
741 gROOT->GetListOfCanvases()->Delete();
a0e2e8b1 742 }
743 }
8c9485b2 744 //
8c0ab8e8 745 TIter next1(fOutputs);
8c0ab8e8 746 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 747 // Special outputs or grid files have the files already closed and written.
748 if (fMode == kGridAnalysis) continue;
749 if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
8c0ab8e8 750 const char *filename = output->GetFileName();
751 if (!(strcmp(filename, "default"))) {
752 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1be433fc 753 TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
754 if (aodfile) {
84fcd93f 755 if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
1be433fc 756 aodfile->Write();
757 continue;
758 }
8d7d3b59 759 }
760 if (!strlen(filename)) continue;
1be433fc 761 if (!output->GetData()) continue;
8d7d3b59 762 TDirectory *opwd = gDirectory;
84fcd93f 763 TFile *file = output->GetFile();
764 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
8e6e6fe8 765 if (!file) file = new TFile(filename, "RECREATE");
84fcd93f 766 if (file->IsZombie()) {
767 Error("Terminate", "Cannot open output file %s", filename);
768 continue;
769 }
8e6e6fe8 770 output->SetFile(file);
771 file->cd();
84fcd93f 772 // Check for a folder request
773 TString dir = output->GetFolderName();
774 if (!dir.IsNull()) {
775 if (!file->GetDirectory(dir)) file->mkdir(dir);
776 file->cd(dir);
777 }
778 if (fDebug > 1) printf(" writing output data %s to file %s:%s\n", output->GetData()->GetName(), file->GetName(), output->GetFolderName());
1be433fc 779 if (output->GetData()->InheritsFrom(TCollection::Class())) {
780 // If data is a collection, we set the name of the collection
781 // as the one of the container and we save as a single key.
782 TCollection *coll = (TCollection*)output->GetData();
783 coll->SetName(output->GetName());
784 coll->Write(output->GetName(), TObject::kSingleKey);
785 } else {
cbc8747a 786 if (output->GetData()->InheritsFrom(TTree::Class())) {
787 TTree *tree = (TTree*)output->GetData();
788 tree->SetDirectory(file);
789 tree->AutoSave();
790 } else {
791 output->GetData()->Write();
792 }
1be433fc 793 }
8e6e6fe8 794 if (opwd) opwd->cd();
795 }
796 next1.Reset();
797 while ((output=(AliAnalysisDataContainer*)next1())) {
798 // Close all files at output
799 TDirectory *opwd = gDirectory;
f5e61abd 800 if (output->GetFile()) {
801 output->GetFile()->Close();
84fcd93f 802 output->SetFile(NULL);
f5e61abd 803 // Copy merged outputs in alien if requested
804 if (fSpecialOutputLocation.Length() &&
805 fSpecialOutputLocation.BeginsWith("alien://")) {
806 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
807 TFile::Cp(output->GetFile()->GetName(),
808 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
809 }
810 }
8d7d3b59 811 if (opwd) opwd->cd();
8c0ab8e8 812 }
813
1be433fc 814 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
815 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
816 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
817
8c0ab8e8 818 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
819 if (getsysInfo) {
820 TDirectory *cdir = gDirectory;
821 TFile f("syswatch.root", "RECREATE");
822 if (!f.IsZombie()) {
823 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
824 tree->SetMarkerStyle(kCircle);
825 tree->SetMarkerColor(kBlue);
826 tree->SetMarkerSize(0.5);
827 if (!gROOT->IsBatch()) {
828 tree->SetAlias("event", "id0");
6da75e0b 829 tree->SetAlias("memUSED", "mi.fMemUsed");
830 new TCanvas("SysInfo","SysInfo",10,10,800,600);
8c0ab8e8 831 tree->Draw("memUSED:event","","", 1234567890, 0);
8c0ab8e8 832 }
833 tree->Write();
834 f.Close();
835 delete tree;
836 }
837 if (cdir) cdir->cd();
923e2ca5 838 }
839 // Validate the output files
840 if (ValidateOutputFiles()) {
841 ofstream out;
842 out.open("outputs_valid", ios::out);
843 out.close();
8c0ab8e8 844 }
84fcd93f 845 if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 846}
847
848//______________________________________________________________________________
849void AliAnalysisManager::AddTask(AliAnalysisTask *task)
850{
851// Adds a user task to the global list of tasks.
8d7d3b59 852 if (fTasks->FindObject(task)) {
853 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
854 return;
855 }
d3106602 856 task->SetActive(kFALSE);
857 fTasks->Add(task);
858}
859
860//______________________________________________________________________________
861AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
862{
863// Retreive task by name.
864 if (!fTasks) return NULL;
865 return (AliAnalysisTask*)fTasks->FindObject(name);
866}
867
868//______________________________________________________________________________
869AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 870 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 871{
872// Create a data container of a certain type. Types can be:
84fcd93f 873// kExchangeContainer = 0, used to exchange data between tasks
d3106602 874// kInputContainer = 1, used to store input data
84fcd93f 875// kOutputContainer = 2, used for writing result to a file
876// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
877// the output object to a folder inside the output file
b1310ef5 878 if (fContainers->FindObject(name)) {
923e2ca5 879 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 880 return NULL;
881 }
d3106602 882 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
883 fContainers->Add(cont);
884 switch (type) {
885 case kInputContainer:
886 fInputs->Add(cont);
887 break;
888 case kOutputContainer:
889 fOutputs->Add(cont);
8c0ab8e8 890 if (filename && strlen(filename)) {
891 cont->SetFileName(filename);
892 cont->SetDataOwned(kFALSE); // data owned by the file
893 }
d3106602 894 break;
c52c2132 895 case kExchangeContainer:
d3106602 896 break;
897 }
898 return cont;
899}
900
901//______________________________________________________________________________
902Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
903 AliAnalysisDataContainer *cont)
904{
905// Connect input of an existing task to a data container.
60a04972 906 if (!task) {
907 Error("ConnectInput", "Task pointer is NULL");
908 return kFALSE;
909 }
d3106602 910 if (!fTasks->FindObject(task)) {
911 AddTask(task);
8d7d3b59 912 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 913 }
914 Bool_t connected = task->ConnectInput(islot, cont);
915 return connected;
916}
917
918//______________________________________________________________________________
919Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
920 AliAnalysisDataContainer *cont)
921{
922// Connect output of an existing task to a data container.
60a04972 923 if (!task) {
924 Error("ConnectOutput", "Task pointer is NULL");
925 return kFALSE;
926 }
d3106602 927 if (!fTasks->FindObject(task)) {
928 AddTask(task);
c52c2132 929 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 930 }
931 Bool_t connected = task->ConnectOutput(islot, cont);
932 return connected;
933}
934
935//______________________________________________________________________________
936void AliAnalysisManager::CleanContainers()
937{
938// Clean data from all containers that have already finished all client tasks.
939 TIter next(fContainers);
940 AliAnalysisDataContainer *cont;
941 while ((cont=(AliAnalysisDataContainer *)next())) {
942 if (cont->IsOwnedData() &&
943 cont->IsDataReady() &&
944 cont->ClientsExecuted()) cont->DeleteData();
945 }
946}
947
948//______________________________________________________________________________
949Bool_t AliAnalysisManager::InitAnalysis()
950{
951// Initialization of analysis chain of tasks. Should be called after all tasks
952// and data containers are properly connected
923e2ca5 953 // Reset flag and remove valid_outputs file if exists
d3106602 954 fInitOK = kFALSE;
923e2ca5 955 if (!gSystem->AccessPathName("outputs_valid"))
956 gSystem->Unlink("outputs_valid");
d3106602 957 // Check for top tasks (depending only on input data containers)
958 if (!fTasks->First()) {
c52c2132 959 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 960 return kFALSE;
961 }
962 TIter next(fTasks);
963 AliAnalysisTask *task;
964 AliAnalysisDataContainer *cont;
965 Int_t ntop = 0;
966 Int_t nzombies = 0;
327eaf46 967 Bool_t iszombie = kFALSE;
968 Bool_t istop = kTRUE;
d3106602 969 Int_t i;
970 while ((task=(AliAnalysisTask*)next())) {
327eaf46 971 istop = kTRUE;
972 iszombie = kFALSE;
d3106602 973 Int_t ninputs = task->GetNinputs();
d3106602 974 for (i=0; i<ninputs; i++) {
975 cont = task->GetInputSlot(i)->GetContainer();
976 if (!cont) {
327eaf46 977 if (!iszombie) {
d3106602 978 task->SetZombie();
979 fZombies->Add(task);
980 nzombies++;
327eaf46 981 iszombie = kTRUE;
d3106602 982 }
c52c2132 983 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
984 i, task->GetName());
d3106602 985 }
327eaf46 986 if (iszombie) continue;
d3106602 987 // Check if cont is an input container
327eaf46 988 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 989 // Connect to parent task
990 }
327eaf46 991 if (istop) {
d3106602 992 ntop++;
993 fTopTasks->Add(task);
994 }
995 }
996 if (!ntop) {
c52c2132 997 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 998 return kFALSE;
999 }
1000 // Check now if there are orphan tasks
1001 for (i=0; i<ntop; i++) {
1002 task = (AliAnalysisTask*)fTopTasks->At(i);
1003 task->SetUsed();
1004 }
1005 Int_t norphans = 0;
1006 next.Reset();
1007 while ((task=(AliAnalysisTask*)next())) {
1008 if (!task->IsUsed()) {
1009 norphans++;
c52c2132 1010 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 1011 }
1012 }
1013 // Check the task hierarchy (no parent task should depend on data provided
1014 // by a daughter task)
1015 for (i=0; i<ntop; i++) {
1016 task = (AliAnalysisTask*)fTopTasks->At(i);
1017 if (task->CheckCircularDeps()) {
c52c2132 1018 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 1019 PrintStatus("dep");
1020 return kFALSE;
1021 }
1022 }
b1310ef5 1023 // Check that all containers feeding post-event loop tasks are in the outputs list
1024 TIter nextcont(fContainers); // loop over all containers
1025 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1026 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1027 if (cont->HasConsumers()) {
1028 // Check if one of the consumers is post event loop
1029 TIter nextconsumer(cont->GetConsumers());
1030 while ((task=(AliAnalysisTask*)nextconsumer())) {
1031 if (task->IsPostEventLoop()) {
1032 fOutputs->Add(cont);
1033 break;
1034 }
1035 }
1036 }
1037 }
1038 }
8d7d3b59 1039 // Check if all special output containers have a file name provided
1040 TIter nextout(fOutputs);
1041 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1042 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1043 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1044 return kFALSE;
1045 }
1046 }
327eaf46 1047 fInitOK = kTRUE;
d3106602 1048 return kTRUE;
1049}
1050
1051//______________________________________________________________________________
1052void AliAnalysisManager::PrintStatus(Option_t *option) const
1053{
1054// Print task hierarchy.
8c0ab8e8 1055 if (!fInitOK) {
1056 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1057 return;
1058 }
1059 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1060 if (getsysInfo)
1061 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1062 TIter next(fTopTasks);
1063 AliAnalysisTask *task;
1064 while ((task=(AliAnalysisTask*)next()))
1065 task->PrintTask(option);
1066}
1067
1068//______________________________________________________________________________
1069void AliAnalysisManager::ResetAnalysis()
1070{
1071// Reset all execution flags and clean containers.
1072 CleanContainers();
1073}
1074
1075//______________________________________________________________________________
8c0ab8e8 1076void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1077{
aee5ee44 1078// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1079// MIX. Process nentries starting from firstentry
c52c2132 1080 if (!fInitOK) {
1081 Error("StartAnalysis","Analysis manager was not initialized !");
1082 return;
1083 }
84fcd93f 1084 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
c52c2132 1085 TString anaType = type;
1086 anaType.ToLower();
1087 fMode = kLocalAnalysis;
c57f56b7 1088 Bool_t runlocalinit = kTRUE;
1089 if (anaType.Contains("file")) runlocalinit = kFALSE;
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);
1356 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1357 if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1358 // Check if option "UPDATE" was preserved
1359 TString opt(option);
1360 opt.ToUpper();
1361 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1362 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1363 } else {
1364 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1365 if (fDebug > 1) printf("=== %s\n", line.Data());
1366 gROOT->ProcessLine(line);
1367 line = Form("pf->OpenFile(\"%s\");", option);
1368 gROOT->ProcessLine(line);
1369 f = gFile;
1370 if (fDebug > 1) {
8d7d3b59 1371 gROOT->ProcessLine("pf->Print()");
84fcd93f 1372 printf(" == proof file name: %s", f->GetName());
1373 }
1374 // Add to proof output list
1375 line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1376 if (fDebug > 1) printf("=== %s", line.Data());
1377 gROOT->ProcessLine(line);
1378 }
1379 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1380 cont->SetFile(f);
1381 // Cd to file
1382 f->cd();
1383 // Check for a folder request
1384 TString dir = cont->GetFolderName();
1385 if (!dir.IsNull()) {
1386 if (!f->GetDirectory(dir)) f->mkdir(dir);
1387 f->cd(dir);
1388 }
1389 return f;
1390 }
1391 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1392 cont->SetFile(NULL);
1393 return NULL;
8d7d3b59 1394}
1395
1396//______________________________________________________________________________
d3106602 1397void AliAnalysisManager::ExecAnalysis(Option_t *option)
1398{
1399// Execute analysis.
8c0ab8e8 1400 static Long64_t ncalls = 0;
1401 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1402 if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1403 ncalls++;
327eaf46 1404 if (!fInitOK) {
c52c2132 1405 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 1406 return;
1407 }
d3106602 1408 AliAnalysisTask *task;
327eaf46 1409 // Check if the top tree is active.
1410 if (fTree) {
1411 TIter next(fTasks);
1412 // De-activate all tasks
1413 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1414 AliAnalysisDataContainer *cont = fCommonInput;
1415 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1416 if (!cont) {
c52c2132 1417 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 1418 return;
1419 }
1420 cont->SetData(fTree); // This will notify all consumers
ed97dc98 1421 Long64_t entry = fTree->GetTree()->GetReadEntry();
1422
6bb2b24f 1423//
c3701689 1424// Call BeginEvent() for optional input/output and MC services
ed97dc98 1425 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1426 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1427 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 1428//
1429// Execute the tasks
276941c8 1430// TIter next1(cont->GetConsumers());
1431 TIter next1(fTopTasks);
327eaf46 1432 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1433 if (fDebug >1) {
1434 cout << " Executing task " << task->GetName() << endl;
1435 }
6bb2b24f 1436
327eaf46 1437 task->ExecuteTask(option);
1438 }
6bb2b24f 1439//
1440// Call FinishEvent() for optional output and MC services
6073f8c9 1441 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1442 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1443 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1444 // Gather system information if requested
1445 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1446 AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
327eaf46 1447 return;
1448 }
1449 // The event loop is not controlled by TSelector
6bb2b24f 1450//
c3701689 1451// Call BeginEvent() for optional input/output and MC services
ed97dc98 1452 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1453 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1454 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
327eaf46 1455 TIter next2(fTopTasks);
1456 while ((task=(AliAnalysisTask*)next2())) {
1457 task->SetActive(kTRUE);
c52c2132 1458 if (fDebug > 1) {
1459 cout << " Executing task " << task->GetName() << endl;
1460 }
d3106602 1461 task->ExecuteTask(option);
327eaf46 1462 }
6bb2b24f 1463//
1464// Call FinishEvent() for optional output and MC services
6073f8c9 1465 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1466 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1467 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 1468}
1469
1470//______________________________________________________________________________
1471void AliAnalysisManager::FinishAnalysis()
1472{
1473// Finish analysis.
1474}
60a04972 1475
1476//______________________________________________________________________________
1477void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* handler)
1478{
1479// Set the input event handler and create a container for it.
1480 fInputEventHandler = handler;
d958c3ea 1481 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ce46ecc1 1482 Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 1483}
1484
1485//______________________________________________________________________________
1486void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* handler)
1487{
1488// Set the input event handler and create a container for it.
1489 fOutputEventHandler = handler;
d958c3ea 1490 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 1491 fCommonOutput->SetSpecialOutput();
ca316909 1492 Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 1493}
c07b9ce2 1494
1495//______________________________________________________________________________
1496void AliAnalysisManager::RegisterExtraFile(const char *fname)
1497{
1498// This method is used externally to register output files which are not
1499// connected to any output container, so that the manager can properly register,
1500// retrieve or merge them when running in distributed mode. The file names are
1501// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1502 if (fExtraFiles.Length()) fExtraFiles += " ";
1503 fExtraFiles += fname;
1504}
1505
1506//______________________________________________________________________________
1507Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1508{
1509// Copy a file from the location specified ina the wrapper with the same name from the source list.
1510 char full_path[512];
1511 char ch_url[512];
1512 TObject *pof = source->FindObject(filename);
1513 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1514 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1515 return kFALSE;
1516 }
1517 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1518 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1519 TString clientUrl(ch_url);
1520 TString full_path_str(full_path);
1521 if (clientUrl.Contains("localhost")){
1522 TObjArray* array = full_path_str.Tokenize ( "//" );
1523 TObjString *strobj = ( TObjString *)array->At(1);
1524 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1525 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1526 full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1527 full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1528 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1529 delete arrayPort;
1530 delete array;
1531 }
1532 if (fDebug > 1)
1533 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1534 Bool_t gotit = TFile::Cp(full_path_str.Data(), filename);
1535 if (!gotit)
1536 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1537 return gotit;
1538}
d29168d6 1539
1540//______________________________________________________________________________
1541void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1542{
1543// Fill analysis type in the provided string.
1544 switch (fMode) {
1545 case kLocalAnalysis:
1546 type = "local";
1547 return;
1548 case kProofAnalysis:
1549 type = "proof";
1550 return;
1551 case kGridAnalysis:
1552 type = "grid";
1553 return;
1554 case kMixingAnalysis:
1555 type = "mix";
1556 }
1557}
923e2ca5 1558
1559//______________________________________________________________________________
1560Bool_t AliAnalysisManager::ValidateOutputFiles() const
1561{
1562// Validate all output files.
1563 TIter next(fOutputs);
1564 AliAnalysisDataContainer *output;
1565 TDirectory *cdir = gDirectory;
84fcd93f 1566 TString openedFiles;
923e2ca5 1567 while ((output=(AliAnalysisDataContainer*)next())) {
1568 TString filename = output->GetFileName();
1569 if (filename == "default") {
1570 if (!fOutputEventHandler) continue;
1571 filename = fOutputEventHandler->GetOutputFileName();
1572 }
1573 // Check if the file is closed
84fcd93f 1574 if (openedFiles.Contains(filename)) continue;;
923e2ca5 1575 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1576 if (file) {
1577 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1578 file->Close();
1579 }
1580 file = TFile::Open(filename);
1581 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1582 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1583 cdir->cd();
1584 return kFALSE;
1585 }
1586 file->Close();
84fcd93f 1587 openedFiles += filename;
1588 openedFiles += " ";
923e2ca5 1589 }
1590 cdir->cd();
1591 return kTRUE;
1592}