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