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