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