]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - ANALYSIS/AliAnalysisManager.cxx
Fixed usage of exchange containers in a multiple producers/consumers schema.
[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// AliAnalysisManager - 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 "AliAnalysisManager.h"
29
30#include <cerrno>
31#include <Riostream.h>
32#include <TError.h>
33#include <TMap.h>
34#include <TClass.h>
35#include <TFile.h>
36#include <TTreeCache.h>
37#include <TEnv.h>
38#include <TMath.h>
39#include <TH1.h>
40#include <TMethodCall.h>
41#include <TChain.h>
42#include <TSystem.h>
43#include <TROOT.h>
44#include <TCanvas.h>
45#include <TStopwatch.h>
46
47#include "AliLog.h"
48#include "AliAnalysisSelector.h"
49#include "AliAnalysisGrid.h"
50#include "AliAnalysisTask.h"
51#include "AliAnalysisDataContainer.h"
52#include "AliAnalysisDataSlot.h"
53#include "AliVEventHandler.h"
54#include "AliVEventPool.h"
55#include "AliSysInfo.h"
56#include "AliAnalysisStatistics.h"
57
58using std::ofstream;
59using std::ios;
60using std::cout;
61using std::endl;
62ClassImp(AliAnalysisManager)
63
64AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
65TString AliAnalysisManager::fgCommonFileName = "";
66TString AliAnalysisManager::fgMacroNames = "";
67Int_t AliAnalysisManager::fPBUpdateFreq = 1;
68
69//______________________________________________________________________________
70AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
71 :TNamed(name,title),
72 fTree(0),
73 fInputEventHandler(0),
74 fOutputEventHandler(0),
75 fMCtruthEventHandler(0),
76 fEventPool(0),
77 fCurrentEntry(-1),
78 fNSysInfo(0),
79 fMode(kLocalAnalysis),
80 fInitOK(kFALSE),
81 fMustClean(kFALSE),
82 fIsRemote(kFALSE),
83 fLocked(kFALSE),
84 fMCLoop(kFALSE),
85 fDebug(0),
86 fSpecialOutputLocation(""),
87 fTasks(0),
88 fTopTasks(0),
89 fZombies(0),
90 fContainers(0),
91 fInputs(0),
92 fOutputs(0),
93 fParamCont(0),
94 fExchangeCont(0),
95 fDebugOptions(0),
96 fFileDescriptors(new TObjArray()),
97 fCurrentDescriptor(0),
98 fCommonInput(0),
99 fCommonOutput(0),
100 fSelector(0),
101 fGridHandler(0),
102 fExtraFiles(),
103 fFileInfoLog(),
104 fAutoBranchHandling(kTRUE),
105 fAsyncReading(kFALSE), // default prefetching on
106 fTable(),
107 fRunFromPath(0),
108 fNcalls(0),
109 fMaxEntries(0),
110 fCacheSize(100000000), // default 100 MB
111 fStatisticsMsg(),
112 fRequestedBranches(),
113 fStatistics(0),
114 fGlobals(0),
115 fIOTimer(0),
116 fCPUTimer(0),
117 fInitTimer(0),
118 fIOTime(0),
119 fCPUTime(0),
120 fInitTime(0)
121{
122// Default constructor.
123 fgAnalysisManager = this;
124 fgCommonFileName = "AnalysisResults.root";
125 if (TClass::IsCallingNew() != TClass::kDummyNew) {
126 fTasks = new TObjArray();
127 fTopTasks = new TObjArray();
128 fZombies = new TObjArray();
129 fContainers = new TObjArray();
130 fInputs = new TObjArray();
131 fOutputs = new TObjArray();
132 fParamCont = new TObjArray();
133 fExchangeCont = new TObjArray();
134 fGlobals = new TMap();
135 }
136 fIOTimer = new TStopwatch();
137 fCPUTimer = new TStopwatch();
138 fInitTimer = new TStopwatch();
139 SetEventLoop(kTRUE);
140}
141
142//______________________________________________________________________________
143AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
144 :TNamed(other),
145 fTree(NULL),
146 fInputEventHandler(NULL),
147 fOutputEventHandler(NULL),
148 fMCtruthEventHandler(NULL),
149 fEventPool(NULL),
150 fCurrentEntry(-1),
151 fNSysInfo(0),
152 fMode(other.fMode),
153 fInitOK(other.fInitOK),
154 fMustClean(other.fMustClean),
155 fIsRemote(other.fIsRemote),
156 fLocked(other.fLocked),
157 fMCLoop(other.fMCLoop),
158 fDebug(other.fDebug),
159 fSpecialOutputLocation(""),
160 fTasks(NULL),
161 fTopTasks(NULL),
162 fZombies(NULL),
163 fContainers(NULL),
164 fInputs(NULL),
165 fOutputs(NULL),
166 fParamCont(NULL),
167 fExchangeCont(NULL),
168 fDebugOptions(NULL),
169 fFileDescriptors(new TObjArray()),
170 fCurrentDescriptor(0),
171 fCommonInput(NULL),
172 fCommonOutput(NULL),
173 fSelector(NULL),
174 fGridHandler(NULL),
175 fExtraFiles(other.fExtraFiles),
176 fFileInfoLog(other.fFileInfoLog),
177 fAutoBranchHandling(other.fAutoBranchHandling),
178 fAsyncReading(other.fAsyncReading),
179 fTable(),
180 fRunFromPath(0),
181 fNcalls(other.fNcalls),
182 fMaxEntries(other.fMaxEntries),
183 fCacheSize(other.fCacheSize),
184 fStatisticsMsg(other.fStatisticsMsg),
185 fRequestedBranches(other.fRequestedBranches),
186 fStatistics(other.fStatistics),
187 fGlobals(other.fGlobals),
188 fIOTimer(new TStopwatch()),
189 fCPUTimer(new TStopwatch()),
190 fInitTimer(new TStopwatch()),
191 fIOTime(0),
192 fCPUTime(0),
193 fInitTime(0)
194{
195// Copy constructor.
196 fTasks = new TObjArray(*other.fTasks);
197 fTopTasks = new TObjArray(*other.fTopTasks);
198 fZombies = new TObjArray(*other.fZombies);
199 fContainers = new TObjArray(*other.fContainers);
200 fInputs = new TObjArray(*other.fInputs);
201 fOutputs = new TObjArray(*other.fOutputs);
202 fParamCont = new TObjArray(*other.fParamCont);
203 fExchangeCont = new TObjArray(*other.fExchangeCont);
204 fgCommonFileName = "AnalysisResults.root";
205 fgAnalysisManager = this;
206}
207
208//______________________________________________________________________________
209AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
210{
211// Assignment
212 if (&other != this) {
213 TNamed::operator=(other);
214 fInputEventHandler = other.fInputEventHandler;
215 fOutputEventHandler = other.fOutputEventHandler;
216 fMCtruthEventHandler = other.fMCtruthEventHandler;
217 fEventPool = other.fEventPool;
218 fTree = NULL;
219 fCurrentEntry = -1;
220 fNSysInfo = other.fNSysInfo;
221 fMode = other.fMode;
222 fInitOK = other.fInitOK;
223 fIsRemote = other.fIsRemote;
224 fLocked = other.fLocked;
225 fMCLoop = other.fMCLoop;
226 fDebug = other.fDebug;
227 fTasks = new TObjArray(*other.fTasks);
228 fTopTasks = new TObjArray(*other.fTopTasks);
229 fZombies = new TObjArray(*other.fZombies);
230 fContainers = new TObjArray(*other.fContainers);
231 fInputs = new TObjArray(*other.fInputs);
232 fOutputs = new TObjArray(*other.fOutputs);
233 fParamCont = new TObjArray(*other.fParamCont);
234 fExchangeCont = new TObjArray(*other.fExchangeCont);
235 fDebugOptions = NULL;
236 fFileDescriptors = new TObjArray();
237 fCurrentDescriptor = 0;
238 fCommonInput = NULL;
239 fCommonOutput = NULL;
240 fSelector = NULL;
241 fGridHandler = NULL;
242 fExtraFiles = other.fExtraFiles;
243 fFileInfoLog = other.fFileInfoLog;
244 fgCommonFileName = "AnalysisResults.root";
245 fgAnalysisManager = this;
246 fAutoBranchHandling = other.fAutoBranchHandling;
247 fAsyncReading = other.fAsyncReading;
248 fTable.Clear("nodelete");
249 fRunFromPath = other.fRunFromPath;
250 fNcalls = other. fNcalls;
251 fMaxEntries = other.fMaxEntries;
252 fCacheSize = other.fCacheSize;
253 fStatisticsMsg = other.fStatisticsMsg;
254 fRequestedBranches = other.fRequestedBranches;
255 fStatistics = other.fStatistics;
256 fGlobals = new TMap();
257 fIOTimer = new TStopwatch();
258 fCPUTimer = new TStopwatch();
259 fInitTimer = new TStopwatch();
260 fIOTime = 0.;
261 fCPUTime = 0.;
262 fInitTime = 0.;
263 }
264 return *this;
265}
266
267//______________________________________________________________________________
268AliAnalysisManager::~AliAnalysisManager()
269{
270// Destructor.
271 if (fTasks) {fTasks->Delete(); delete fTasks;}
272 delete fTopTasks;
273 delete fZombies;
274 if (fContainers) {fContainers->Delete(); delete fContainers;}
275 delete fInputs;
276 delete fOutputs;
277 delete fParamCont;
278 delete fExchangeCont;
279 delete fDebugOptions;
280 delete fGridHandler;
281 delete fInputEventHandler;
282 delete fOutputEventHandler;
283 delete fMCtruthEventHandler;
284 delete fEventPool;
285 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
286 if (fGlobals) {fGlobals->DeleteAll(); delete fGlobals;}
287 if (fFileDescriptors) {fFileDescriptors->Delete(); delete fFileDescriptors;}
288 delete fIOTimer;
289 delete fCPUTimer;
290 delete fInitTimer;
291}
292
293//______________________________________________________________________________
294void AliAnalysisManager::CreateReadCache()
295{
296// Create cache for reading according fCacheSize and fAsyncReading.
297 if (!fTree || !fTree->GetCurrentFile()) {
298 Error("CreateReadCache","Current tree or tree file not yet defined");
299 return;
300 }
301 if (!fCacheSize) {
302 if (fDebug) Info("CreateReadCache","=== Read caching disabled ===");
303 return;
304 }
305 gEnv->SetValue("TFile.AsyncPrefetching",(Int_t)fAsyncReading);
306 if (fAsyncReading) gEnv->SetValue("Cache.Directory",Form("file://%s/cache", gSystem->WorkingDirectory()));
307 if (fAsyncReading) gEnv->SetValue("TFile.AsyncReading",1);
308 fTree->SetCacheSize(fCacheSize);
309 TTreeCache::SetLearnEntries(1); //<<< we can take the decision after 1 entry
310 if (!fAutoBranchHandling && !fRequestedBranches.IsNull()) {
311 TObjArray *arr = fRequestedBranches.Tokenize(",");
312 TIter next(arr);
313 TObject *obj;
314 while ((obj=next()))
315 fTree->AddBranchToCache(obj->GetName(),kTRUE); //<<< add requested branches to cache
316 delete arr;
317 } else {
318 fTree->AddBranchToCache("*", kTRUE); //<<< add all branches to cache
319 }
320 if (fDebug) {
321 Info("CreateReadCache","Read cache enabled %lld bytes with async reading=%d",fCacheSize, (Int_t)fAsyncReading);
322 }
323 return;
324}
325
326//______________________________________________________________________________
327Bool_t AliAnalysisManager::EventLoop(Long64_t nevents)
328{
329// Initialize an event loop where the data producer is the input handler
330// The handler must implement MakeTree creating the tree of events (likely
331// memory resident) and generate the current event in the method BeginEvent.
332// If the tree is memory resident, the handler should never call TTree::Fill
333// method.
334 cout << "===== RUNNING IN EVENT LOOP MODE: " << GetName() << endl;
335 if (!fInputEventHandler) {
336 Error("EventLoop", "No input handler: exiting");
337 return kFALSE;
338 }
339 TTree *tree = new TTree("DummyTree", "Dummy tree for AliAnalysisManager::EventLoop");
340 SetExternalLoop(kTRUE);
341 if (!Init(tree)) return kFALSE;
342 SlaveBegin(tree);
343 for (Long64_t iev=0; iev<nevents; iev++)
344 ExecAnalysis();
345 TList dummyList;
346 PackOutput(&dummyList);
347 fIsRemote = kTRUE;
348 Terminate();
349 return kTRUE;
350}
351
352//______________________________________________________________________________
353Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
354{
355// Read one entry of the tree or a whole branch.
356 fCurrentEntry = entry;
357 if (!fAutoBranchHandling)
358 return 123456789;
359 if (!fTree || !fTree->GetTree()) return -1;
360 fIOTimer->Start(kTRUE);
361 Long64_t readbytes = fTree->GetTree()->GetEntry(entry, getall);
362 fIOTimer->Stop();
363 fIOTime += fIOTimer->RealTime();
364 return (Int_t)readbytes;
365}
366
367//______________________________________________________________________________
368Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
369{
370// Attempt to extract run number from input data path. Works only for paths to
371// alice data in alien.
372// sim: /alice/sim/<production>/run_no/...
373// data: /alice/data/year/period/000run_no/... (ESD or AOD)
374 TString type = "unknown";
375 TString s(path);
376 if (s.Contains("/alice/data")) type = "real";
377 else if (s.Contains("/alice/sim")) type = "simulated";
378 TString srun;
379 Int_t ind1, ind2;
380 ind1 = s.Index("/00");
381 if (ind1>0) {
382 ind2 = s.Index("/",ind1+1);
383 if (ind2-ind1>8) srun = s(ind1+1, ind2-ind1-1);
384 }
385 if (srun.IsNull()) {
386 ind1 = s.Index("/LHC");
387 if (ind1>0) {
388 ind1 = s.Index("/",ind1+1);
389 if (ind1>0) {
390 ind2 = s.Index("/",ind1+1);
391 if (ind2>0) srun = s(ind1+1, ind2-ind1-1);
392 }
393 }
394 }
395 Int_t run = srun.Atoi();
396 if (run>0) printf("=== GetRunFromAlienPath: run %d of %s data ===\n", run, type.Data());
397 return run;
398}
399
400//______________________________________________________________________________
401Bool_t AliAnalysisManager::Init(TTree *tree)
402{
403 // The Init() function is called when the selector needs to initialize
404 // a new tree or chain. Typically here the branch addresses of the tree
405 // will be set. It is normaly not necessary to make changes to the
406 // generated code, but the routine can be extended by the user if needed.
407 // Init() will be called many times when running with PROOF.
408 Bool_t init = kFALSE;
409 if (!tree) return kFALSE; // Should not happen - protected in selector caller
410 if (fDebug > 1) {
411 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
412 }
413 // Call InitTree of EventHandler
414 if (fOutputEventHandler) {
415 if (fMode == kProofAnalysis) {
416 init = fOutputEventHandler->Init(0x0, "proof");
417 } else {
418 init = fOutputEventHandler->Init(0x0, "local");
419 }
420 if (!init) {
421 Error("Init", "Output event handler failed to initialize");
422 return kFALSE;
423 }
424 }
425
426 if (fInputEventHandler) {
427 if (fMode == kProofAnalysis) {
428 init = fInputEventHandler->Init(tree, "proof");
429 } else {
430 init = fInputEventHandler->Init(tree, "local");
431 }
432 if (!init) {
433 Error("Init", "Input event handler failed to initialize tree");
434 return kFALSE;
435 }
436 } else {
437 // If no input event handler we need to get the tree once
438 // for the chain
439 if(!tree->GetTree()) {
440 Long64_t readEntry = tree->LoadTree(0);
441 if (readEntry == -2) {
442 Error("Init", "Input tree has no entry. Exiting");
443 return kFALSE;
444 }
445 }
446 }
447
448 if (fMCtruthEventHandler) {
449 if (fMode == kProofAnalysis) {
450 init = fMCtruthEventHandler->Init(0x0, "proof");
451 } else {
452 init = fMCtruthEventHandler->Init(0x0, "local");
453 }
454 if (!init) {
455 Error("Init", "MC event handler failed to initialize");
456 return kFALSE;
457 }
458 }
459
460 if (!fInitOK) InitAnalysis();
461 if (!fInitOK) return kFALSE;
462 fTree = tree;
463 if (fMode != kProofAnalysis) CreateReadCache();
464 else {
465 // cholm - here we should re-add to the table or branches
466 fTable.Clear();
467 }
468 AliAnalysisDataContainer *top = fCommonInput;
469 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
470 if (!top) {
471 Error("Init","No top input container !");
472 return kFALSE;
473 }
474 top->SetData(tree);
475 CheckBranches(kFALSE);
476 fTable.Rehash(100);
477 if (fDebug > 1) {
478 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
479 }
480 return kTRUE;
481}
482
483//______________________________________________________________________________
484void AliAnalysisManager::SlaveBegin(TTree *tree)
485{
486 // The SlaveBegin() function is called after the Begin() function.
487 // When running with PROOF SlaveBegin() is called on each slave server.
488 // The tree argument is deprecated (on PROOF 0 is passed).
489 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
490 // Init timer should be already started
491 // Apply debug options
492 ApplyDebugOptions();
493 if (fCacheSize &&
494 fMCtruthEventHandler &&
495 (fMode != kProofAnalysis)) fMCtruthEventHandler->SetCacheSize(fCacheSize);
496 if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded");
497 static Bool_t isCalled = kFALSE;
498 Bool_t init = kFALSE;
499 Bool_t initOK = kTRUE;
500 TString msg;
501 TDirectory *curdir = gDirectory;
502 // Call SlaveBegin only once in case of mixing
503 if (isCalled && fMode==kMixingAnalysis) return;
504 gROOT->cd();
505 // Call Init of EventHandler
506 if (fOutputEventHandler) {
507 if (fMode == kProofAnalysis) {
508 // Merging AOD's in PROOF via TProofOutputFile
509 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
510 init = fOutputEventHandler->Init("proof");
511 if (!init) msg = "Failed to initialize output handler on worker";
512 } else {
513 init = fOutputEventHandler->Init("local");
514 if (!init) msg = "Failed to initialize output handler";
515 }
516 initOK &= init;
517 if (!fSelector) Error("SlaveBegin", "Selector not set");
518 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
519 }
520 gROOT->cd();
521 if (fInputEventHandler) {
522 fInputEventHandler->SetInputTree(tree);
523 if (fMode == kProofAnalysis) {
524 init = fInputEventHandler->Init("proof");
525 if (!init) msg = "Failed to initialize input handler on worker";
526 } else {
527 init = fInputEventHandler->Init("local");
528 if (!init) msg = "Failed to initialize input handler";
529 }
530 initOK &= init;
531 if (!fSelector) Error("SlaveBegin", "Selector not set");
532 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
533 }
534 gROOT->cd();
535 if (fMCtruthEventHandler) {
536 if (fMode == kProofAnalysis) {
537 init = fMCtruthEventHandler->Init("proof");
538 if (!init) msg = "Failed to initialize MC handler on worker";
539 } else {
540 init = fMCtruthEventHandler->Init("local");
541 if (!init) msg = "Failed to initialize MC handler";
542 }
543 initOK &= init;
544 if (!fSelector) Error("SlaveBegin", "Selector not set");
545 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
546 }
547 if (curdir) curdir->cd();
548 isCalled = kTRUE;
549 if (!initOK) return;
550 TIter next(fTasks);
551 AliAnalysisTask *task;
552 // Call CreateOutputObjects for all tasks
553 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
554 Bool_t dirStatus = TH1::AddDirectoryStatus();
555 Int_t itask = 0;
556 while ((task=(AliAnalysisTask*)next())) {
557 gROOT->cd();
558 // Start with memory as current dir and make sure by default histograms do not get attached to files.
559 TH1::AddDirectory(kFALSE);
560 task->CreateOutputObjects();
561 if (!task->CheckPostData()) {
562 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
563 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
564 ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName());
565 }
566 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
567 itask++;
568 }
569 TH1::AddDirectory(dirStatus);
570 if (curdir) curdir->cd();
571 fInitTimer->Stop();
572 fInitTime += fInitTimer->RealTime();
573 fInitTimer->Continue();
574 printf("Initialization time: %g [sec]\n", fInitTime);
575 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
576}
577
578//______________________________________________________________________________
579Bool_t AliAnalysisManager::Notify()
580{
581 // The Notify() function is called when a new file is opened. This
582 // can be either for a new TTree in a TChain or when when a new TTree
583 // is started when using PROOF. It is normaly not necessary to make changes
584 // to the generated code, but the routine can be extended by the
585 // user if needed. The return value is currently not used.
586 fIOTimer->Start(kTRUE);
587 if (!fTree) return kFALSE;
588 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) return kFALSE;
589
590 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
591 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
592
593 TFile *curfile = fTree->GetCurrentFile();
594 if (!curfile) {
595 Error("Notify","No current file");
596 return kFALSE;
597 }
598 if (IsCollectThroughput()) {
599 if (fCurrentDescriptor) fCurrentDescriptor->Done();
600 fCurrentDescriptor = new AliAnalysisFileDescriptor(curfile);
601 fFileDescriptors->Add(fCurrentDescriptor);
602 }
603
604 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
605 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
606 if (run && (run != fRunFromPath)) {
607 fRunFromPath = run;
608 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
609 }
610 TIter next(fTasks);
611 AliAnalysisTask *task;
612
613 // Call Notify of the event handlers
614 if (fInputEventHandler) {
615 fInputEventHandler->Notify(curfile->GetName());
616 }
617
618 if (fOutputEventHandler) {
619 fOutputEventHandler->Notify(curfile->GetName());
620 }
621
622 if (fMCtruthEventHandler) {
623 fMCtruthEventHandler->Notify(curfile->GetName());
624 }
625
626 // Call Notify for all tasks
627 while ((task=(AliAnalysisTask*)next()))
628 task->Notify();
629
630 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
631 fIOTimer->Stop();
632 fIOTime += fIOTimer->RealTime();
633 return kTRUE;
634}
635
636//______________________________________________________________________________
637Bool_t AliAnalysisManager::Process(Long64_t)
638{
639 // The Process() function is called for each entry in the tree (or possibly
640 // keyed object in the case of PROOF) to be processed. The entry argument
641 // specifies which entry in the currently loaded tree is to be processed.
642 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
643 // to read either all or the required parts of the data. When processing
644 // keyed objects with PROOF, the object is already loaded and is available
645 // via the fObject pointer.
646 //
647 // This function should contain the "body" of the analysis. It can contain
648 // simple or elaborate selection criteria, run algorithms on the data
649 // of the event and typically fill histograms.
650
651 // WARNING when a selector is used with a TChain, you must use
652 // the pointer to the current TTree to call GetEntry(entry).
653 // The entry is always the local entry number in the current tree.
654 // Assuming that fChain is the pointer to the TChain being processed,
655 // use fChain->GetTree()->GetEntry(entry).
656
657 // This method is obsolete. ExecAnalysis is called instead.
658 return kTRUE;
659}
660
661//______________________________________________________________________________
662void AliAnalysisManager::PackOutput(TList *target)
663{
664 // Pack all output data containers in the output list. Called at SlaveTerminate
665 // stage in PROOF case for each slave.
666 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
667 fIOTimer->Start(kTRUE);
668 std::ofstream out;
669 if (IsCollectThroughput()) {
670 if (fCurrentDescriptor) fCurrentDescriptor->Done();
671 fFileDescriptors->Print();
672 if (fFileInfoLog.IsNull()) fFileInfoLog = "fileinfo.log";
673 out.open(fFileInfoLog, std::ios::app);
674 if (out.bad()) Error("SavePrimitive", "Bad file name: %s", fFileInfoLog.Data());
675 else {
676 TIter nextflog(fFileDescriptors);
677 TObject *log;
678 while ((log=nextflog())) log->SavePrimitive(out,"");
679 }
680 }
681 if (!target) {
682 Error("PackOutput", "No target. Exiting.");
683 return;
684 }
685 TDirectory *cdir = gDirectory;
686 gROOT->cd();
687 if (fInputEventHandler) fInputEventHandler ->Terminate();
688 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
689 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
690 gROOT->cd();
691
692 // Call FinishTaskOutput() for each event loop task (not called for
693 // post-event loop tasks - use Terminate() fo those)
694 TIter nexttask(fTasks);
695 AliAnalysisTask *task;
696 while ((task=(AliAnalysisTask*)nexttask())) {
697 if (!task->IsPostEventLoop()) {
698 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
699 task->FinishTaskOutput();
700 gROOT->cd();
701 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
702 }
703 }
704 // Write statistics message on the workers.
705 if (fStatistics) WriteStatisticsMsg(fNcalls);
706
707 if (fMode == kProofAnalysis) {
708 TIter next(fOutputs);
709 AliAnalysisDataContainer *output;
710 Bool_t isManagedByHandler = kFALSE;
711 TList filestmp;
712 filestmp.SetOwner();
713 while ((output=(AliAnalysisDataContainer*)next())) {
714 // Do not consider outputs of post event loop tasks
715 isManagedByHandler = kFALSE;
716 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
717 const char *filename = output->GetFileName();
718 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
719 isManagedByHandler = kTRUE;
720 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
721 filename = fOutputEventHandler->GetOutputFileName();
722 }
723 // Check if data was posted to this container. If not, issue an error.
724 if (!output->GetData() && !isManagedByHandler) {
725 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
726 continue;
727 }
728 if (!output->IsSpecialOutput()) {
729 // Normal outputs
730 if (strlen(filename) && !isManagedByHandler) {
731 // Backup current folder
732 TDirectory *opwd = gDirectory;
733 // File resident outputs.
734 // Check first if the file exists.
735 TString openoption = "RECREATE";
736 Bool_t firsttime = kTRUE;
737 if (filestmp.FindObject(output->GetFileName())) {
738 firsttime = kFALSE;
739 } else {
740 filestmp.Add(new TNamed(output->GetFileName(),""));
741 }
742 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
743// TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
744 // Save data to file, then close.
745 if (output->GetData()->InheritsFrom(TCollection::Class())) {
746 // If data is a collection, we set the name of the collection
747 // as the one of the container and we save as a single key.
748 TCollection *coll = (TCollection*)output->GetData();
749 coll->SetName(output->GetName());
750// coll->Write(output->GetName(), TObject::kSingleKey);
751 } else {
752 if (output->GetData()->InheritsFrom(TTree::Class())) {
753 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
754 // Save data to file, then close.
755 TTree *tree = (TTree*)output->GetData();
756 // Check if tree is in memory
757 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
758 tree->AutoSave();
759 file->Close();
760 } else {
761// output->GetData()->Write();
762 }
763 }
764 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
765// if (fDebug > 2) {
766// printf(" file %s listing content:\n", filename);
767// file->ls();
768// }
769 // Clear file list to release object ownership to user.
770// file->Clear();
771// file->Close();
772 output->SetFile(NULL);
773 // Restore current directory
774 if (opwd) opwd->cd();
775 } else {
776 // Memory-resident outputs
777 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
778 }
779 AliAnalysisDataWrapper *wrap = 0;
780 if (isManagedByHandler) {
781 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
782 wrap->SetName(output->GetName());
783 }
784 else wrap =output->ExportData();
785 // Output wrappers must NOT delete data after merging - the user owns them
786 wrap->SetDeleteData(kFALSE);
787 target->Add(wrap);
788 } else {
789 // Special outputs. The file must be opened and connected to the container.
790 TDirectory *opwd = gDirectory;
791 TFile *file = output->GetFile();
792 if (!file) {
793 AliAnalysisTask *producer = output->GetProducer();
794 Fatal("PackOutput",
795 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
796 output->GetFileName(), output->GetName(), producer->ClassName());
797 continue;
798 }
799 TString outFilename = file->GetName();
800 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
801 if (isManagedByHandler) {
802 // Terminate IO for files managed by the output handler
803 // file->Write() moved to AOD handler (A.G. 11.01.10)
804// if (file) file->Write();
805 if (file && fDebug > 2) {
806 printf(" handled file %s listing content:\n", file->GetName());
807 file->ls();
808 }
809 fOutputEventHandler->TerminateIO();
810 } else {
811 file->cd();
812 // Release object ownership to users after writing data to file
813 if (output->GetData()->InheritsFrom(TCollection::Class())) {
814 // If data is a collection, we set the name of the collection
815 // as the one of the container and we save as a single key.
816 TCollection *coll = (TCollection*)output->GetData();
817 coll->SetName(output->GetName());
818 coll->Write(output->GetName(), TObject::kSingleKey);
819 } else {
820 if (output->GetData()->InheritsFrom(TTree::Class())) {
821 TTree *tree = (TTree*)output->GetData();
822 tree->SetDirectory(file);
823 tree->AutoSave();
824 } else {
825 output->GetData()->Write();
826 }
827 }
828 if (fDebug > 2) {
829 printf(" file %s listing content:\n", output->GetFileName());
830 file->ls();
831 }
832 // Clear file list to release object ownership to user.
833// file->Clear();
834 file->Close();
835 output->SetFile(NULL);
836 }
837 // Restore current directory
838 if (opwd) opwd->cd();
839 // Check if a special output location was provided or the output files have to be merged
840 if (strlen(fSpecialOutputLocation.Data())) {
841 TString remote = fSpecialOutputLocation;
842 remote += "/";
843 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
844 if (remote.BeginsWith("alien:")) {
845 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
846 remote += outFilename;
847 remote.ReplaceAll(".root", Form("_%d.root", gid));
848 } else {
849 remote += Form("%s_%d_", gSystem->HostName(), gid);
850 remote += outFilename;
851 }
852 if (fDebug > 1)
853 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
854 output->GetName(), remote.Data());
855 TFile::Cp ( outFilename.Data(), remote.Data() );
856 // Copy extra outputs
857 if (fExtraFiles.Length() && isManagedByHandler) {
858 TObjArray *arr = fExtraFiles.Tokenize(" ");
859 TObjString *os;
860 TIter nextfilename(arr);
861 while ((os=(TObjString*)nextfilename())) {
862 outFilename = os->GetString();
863 remote = fSpecialOutputLocation;
864 remote += "/";
865 if (remote.BeginsWith("alien://")) {
866 remote += outFilename;
867 remote.ReplaceAll(".root", Form("_%d.root", gid));
868 } else {
869 remote += Form("%s_%d_", gSystem->HostName(), gid);
870 remote += outFilename;
871 }
872 if (fDebug > 1)
873 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
874 outFilename.Data(), remote.Data());
875 TFile::Cp ( outFilename.Data(), remote.Data() );
876 }
877 delete arr;
878 }
879 } else {
880 // No special location specified-> use TProofOutputFile as merging utility
881 // The file at this output slot must be opened in CreateOutputObjects
882 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
883 }
884 }
885 }
886 }
887 fIOTime += fIOTimer->RealTime();
888 if ((fDebug || IsCollectThroughput())) {
889 fInitTimer->Stop();
890 fInitTime = fInitTimer->RealTime()-fIOTime-fCPUTime;
891 printf("=Analysis %s= init time: %g[sec]\
892 \n I/O & data mng.: %g [sec]\
893 \n task execution: %g [sec]\
894 \n total time: CPU=%g [sec] REAL=%g[sec]\n",
895 GetName(), fInitTime, fIOTime, fCPUTime, fInitTimer->CpuTime(), fInitTimer->RealTime());
896 if (IsCollectThroughput()) {
897 out << "#summary#########################################################" << endl;
898 out << "train_name " << GetName() << endl;
899 out << "root_time " << fInitTimer->RealTime() << endl;
900 out << "root_cpu " << fInitTimer->CpuTime() << endl;
901 out << "init_time " << fInitTime << endl;
902 out << "io_mng_time " << fIOTime << endl;
903 out << "exec_time " << fCPUTime << endl;
904 TString aliensite = gSystem->Getenv("ALIEN_SITE");
905 out << "alien_site " << aliensite << endl;
906 out << "host_name ";
907 TString hostname = gSystem->Getenv("ALIEN_HOSTNAME");
908 if (hostname.IsNull()) {
909 out.close();
910 gSystem->Exec(Form("hostname -f >> %s", fFileInfoLog.Data()));
911 } else {
912 out << hostname << endl;
913 }
914 }
915 }
916
917 if (cdir) cdir->cd();
918 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
919}
920
921//______________________________________________________________________________
922void AliAnalysisManager::ImportWrappers(TList *source)
923{
924// Import data in output containers from wrappers coming in source.
925 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
926 fIOTimer->Start(kTRUE);
927 TIter next(fOutputs);
928 AliAnalysisDataContainer *cont;
929 AliAnalysisDataWrapper *wrap;
930 Int_t icont = 0;
931 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
932 TDirectory *cdir = gDirectory;
933 while ((cont=(AliAnalysisDataContainer*)next())) {
934 wrap = 0;
935 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
936 if (cont->IsRegisterDataset()) continue;
937 const char *filename = cont->GetFileName();
938 Bool_t isManagedByHandler = kFALSE;
939 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
940 isManagedByHandler = kTRUE;
941 filename = fOutputEventHandler->GetOutputFileName();
942 }
943 if (cont->IsSpecialOutput() || inGrid) {
944 if (strlen(fSpecialOutputLocation.Data())) continue;
945 // Copy merged file from PROOF scratch space.
946 // In case of grid the files are already in the current directory.
947 if (!inGrid) {
948 if (isManagedByHandler && fExtraFiles.Length()) {
949 // Copy extra registered dAOD files.
950 TObjArray *arr = fExtraFiles.Tokenize(" ");
951 TObjString *os;
952 TIter nextfilename(arr);
953 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
954 delete arr;
955 }
956 if (!GetFileFromWrapper(filename, source)) continue;
957 }
958 // Normally we should connect data from the copied file to the
959 // corresponding output container, but it is not obvious how to do this
960 // automatically if several objects in file...
961 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
962 if (!f) f = TFile::Open(filename, "READ");
963 if (!f) {
964 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
965 continue;
966 }
967 f->cd();
968 TObject *obj = 0;
969 // Cd to the directory pointed by the container
970 TString folder = cont->GetFolderName();
971 if (!folder.IsNull()) f->cd(folder);
972 // Try to fetch first an object having the container name.
973 obj = gDirectory->Get(cont->GetName());
974 if (!obj) {
975 Warning("ImportWrappers", "Could not import object of type:%s for container %s in file %s:%s.\n Object will not be available in Terminate(). Try if possible to name the output object as the container (%s) or to embed it in a TList",
976 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
977 continue;
978 }
979 wrap = new AliAnalysisDataWrapper(obj);
980 wrap->SetDeleteData(kFALSE);
981 }
982 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
983 if (!wrap) {
984 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
985 continue;
986 }
987 icont++;
988 if (fDebug > 1) {
989 printf(" Importing data for container %s\n", cont->GetName());
990 if (strlen(filename)) printf(" -> file %s\n", filename);
991 else printf("\n");
992 }
993 cont->ImportData(wrap);
994 }
995 if (cdir) cdir->cd();
996 fIOTimer->Stop();
997 fIOTime += fIOTimer->RealTime();
998 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
999}
1000
1001//______________________________________________________________________________
1002void AliAnalysisManager::UnpackOutput(TList *source)
1003{
1004 // Called by AliAnalysisSelector::Terminate only on the client.
1005 fIOTimer->Start(kTRUE);
1006 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
1007 if (!source) {
1008 Error("UnpackOutput", "No target. Exiting.");
1009 return;
1010 }
1011 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
1012
1013 if (fMode == kProofAnalysis) ImportWrappers(source);
1014
1015 TIter next(fOutputs);
1016 AliAnalysisDataContainer *output;
1017 while ((output=(AliAnalysisDataContainer*)next())) {
1018 if (!output->GetData()) continue;
1019 // Check if there are client tasks that run post event loop
1020 if (output->HasConsumers()) {
1021 // Disable event loop semaphore
1022 output->SetPostEventLoop(kTRUE);
1023 TObjArray *list = output->GetConsumers();
1024 Int_t ncons = list->GetEntriesFast();
1025 for (Int_t i=0; i<ncons; i++) {
1026 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
1027 task->CheckNotify(kTRUE);
1028 // If task is active, execute it
1029 if (task->IsPostEventLoop() && task->IsActive()) {
1030 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
1031 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
1032 task->ExecuteTask();
1033 }
1034 }
1035 if (fStatistics) fStatistics->StopTimer();
1036 }
1037 }
1038 fIOTimer->Stop();
1039 fIOTime += fIOTimer->RealTime();
1040 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
1041}
1042
1043//______________________________________________________________________________
1044void AliAnalysisManager::Terminate()
1045{
1046 // The Terminate() function is the last function to be called during
1047 // a query. It always runs on the client, it can be used to present
1048 // the results graphically.
1049 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
1050 fInitTimer->Start(kTRUE);
1051 TDirectory *cdir = gDirectory;
1052 gROOT->cd();
1053 AliAnalysisTask *task;
1054 AliAnalysisDataContainer *output;
1055 TIter next(fTasks);
1056 TStopwatch timer;
1057 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1058 // Call Terminate() for tasks
1059 Int_t itask = 0;
1060 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
1061 // Save all the canvases produced by the Terminate
1062 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
1063 task->Terminate();
1064 gROOT->cd();
1065 if (getsysInfo)
1066 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
1067 itask++;
1068 if (TObject::TestBit(kSaveCanvases)) {
1069 if (!gROOT->IsBatch()) {
1070 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
1071 timer.Start(kTRUE);
1072 while (timer.RealTime()<5) {
1073 timer.Continue();
1074 gSystem->ProcessEvents();
1075 }
1076 }
1077 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
1078 if (iend==0) continue;
1079 TCanvas *canvas;
1080 for (Int_t ipict=0; ipict<iend; ipict++) {
1081 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
1082 if (!canvas) continue;
1083 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
1084 }
1085 gROOT->GetListOfCanvases()->Delete();
1086 }
1087 }
1088 //
1089 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
1090 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
1091 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
1092 gROOT->cd();
1093 TObjArray *allOutputs = new TObjArray();
1094 Int_t icont;
1095 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
1096 if (!IsSkipTerminate())
1097 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
1098 TIter next1(allOutputs);
1099 TString handlerFile = "";
1100 TString extraOutputs = "";
1101 if (fOutputEventHandler) {
1102 handlerFile = fOutputEventHandler->GetOutputFileName();
1103 extraOutputs = fOutputEventHandler->GetExtraOutputs();
1104 }
1105 icont = 0;
1106 TList filestmp;
1107 while ((output=(AliAnalysisDataContainer*)next1())) {
1108 // Special outputs or grid files have the files already closed and written.
1109 icont++;
1110 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
1111 if (fMode == kProofAnalysis) {
1112 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
1113 }
1114 const char *filename = output->GetFileName();
1115 TString openoption = "RECREATE";
1116 if (!(strcmp(filename, "default"))) continue;
1117 if (!strlen(filename)) continue;
1118 if (!output->GetData()) continue;
1119 TDirectory *opwd = gDirectory;
1120 TFile *file = output->GetFile();
1121 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1122 if (!file) {
1123 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
1124 Bool_t firsttime = kTRUE;
1125 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
1126 firsttime = kFALSE;
1127 } else {
1128 filestmp.Add(new TNamed(filename,""));
1129 }
1130 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
1131 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
1132 file = new TFile(filename, openoption);
1133 } else {
1134 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
1135 openoption = file->GetOption();
1136 if (openoption == "READ") {
1137 if (fDebug>1) printf("...reopening in UPDATE mode\n");
1138 file->ReOpen("UPDATE");
1139 }
1140 }
1141 if (file->IsZombie()) {
1142 Error("Terminate", "Cannot open output file %s", filename);
1143 continue;
1144 }
1145 output->SetFile(file);
1146 file->cd();
1147 // Check for a folder request
1148 TString dir = output->GetFolderName();
1149 if (!dir.IsNull()) {
1150 if (!file->GetDirectory(dir)) file->mkdir(dir);
1151 file->cd(dir);
1152 }
1153 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1154 if (output->GetData()->InheritsFrom(TCollection::Class())) {
1155 // If data is a collection, we set the name of the collection
1156 // as the one of the container and we save as a single key.
1157 TCollection *coll = (TCollection*)output->GetData();
1158 coll->SetName(output->GetName());
1159 coll->Write(output->GetName(), TObject::kSingleKey);
1160 } else {
1161 if (output->GetData()->InheritsFrom(TTree::Class())) {
1162 TTree *tree = (TTree*)output->GetData();
1163 tree->SetDirectory(gDirectory);
1164 tree->AutoSave();
1165 } else {
1166 output->GetData()->Write();
1167 }
1168 }
1169 if (opwd) opwd->cd();
1170 }
1171 gROOT->cd();
1172 next1.Reset();
1173 TString copiedFiles;
1174 while ((output=(AliAnalysisDataContainer*)next1())) {
1175 // Close all files at output
1176 TDirectory *opwd = gDirectory;
1177 if (output->GetFile()) {
1178 // Clear file list to release object ownership to user.
1179// output->GetFile()->Clear();
1180 output->GetFile()->Close();
1181 // Copy merged outputs in alien if requested
1182 if (fSpecialOutputLocation.BeginsWith("alien://")) {
1183 if (copiedFiles.Contains(output->GetFile()->GetName())) {
1184 if (opwd) opwd->cd();
1185 output->SetFile(NULL);
1186 continue;
1187 }
1188 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
1189 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
1190 TFile::Cp(output->GetFile()->GetName(),
1191 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
1192 copiedFiles += output->GetFile()->GetName();
1193 }
1194 output->SetFile(NULL);
1195 }
1196 if (opwd) opwd->cd();
1197 }
1198 delete allOutputs;
1199 //Write statistics information on the client
1200 if (fStatistics) WriteStatisticsMsg(fNcalls);
1201 if (getsysInfo) {
1202 TDirectory *crtdir = gDirectory;
1203 TFile f("syswatch.root", "RECREATE");
1204 TH1 *hist;
1205 TString cut;
1206 if (!f.IsZombie()) {
1207 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
1208 tree->SetName("syswatch");
1209 tree->SetMarkerStyle(kCircle);
1210 tree->SetMarkerColor(kBlue);
1211 tree->SetMarkerSize(0.5);
1212 if (!gROOT->IsBatch()) {
1213 tree->SetAlias("event", "id0");
1214 tree->SetAlias("task", "id1");
1215 tree->SetAlias("stage", "id2");
1216 // Already defined aliases
1217 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1218 // tree->SetAlias("T","stampSec-first");
1219 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1220 // tree->SetAlias("VM","pI.fMemVirtual");
1221 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1222 Int_t npads = 1 /*COO plot for all tasks*/ +
1223 fTopTasks->GetEntries() /*Exec plot per task*/ +
1224 1 /*Terminate plot for all tasks*/ +
1225 1; /*vm plot*/
1226
1227 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1228 if (npads<iopt*(iopt+1))
1229 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1230 else
1231 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1232 Int_t ipad = 1;
1233 // draw the plot of deltaVM for Exec for each task
1234 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1235 task = (AliAnalysisTask*)fTopTasks->At(itask);
1236 canvas->cd(ipad++);
1237 cut = Form("task==%d && stage==1", itask);
1238 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1239 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1240 if (hist) {
1241 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1242 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1243 }
1244 }
1245 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1246 canvas->cd(ipad++);
1247 tree->SetMarkerStyle(kFullTriangleUp);
1248 tree->SetMarkerColor(kRed);
1249 tree->SetMarkerSize(0.8);
1250 cut = "task>=0 && task<1000 && stage==0";
1251 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1252 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1253 if (hist) {
1254 hist->SetTitle("Memory in CreateOutputObjects()");
1255 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1256 hist->GetXaxis()->SetTitle("task");
1257 }
1258 // draw the plot of deltaVM for Terminate for all tasks
1259 canvas->cd(ipad++);
1260 tree->SetMarkerStyle(kOpenSquare);
1261 tree->SetMarkerColor(kMagenta);
1262 cut = "task>=0 && task<1000 && stage==2";
1263 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1264 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1265 if (hist) {
1266 hist->SetTitle("Memory in Terminate()");
1267 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1268 hist->GetXaxis()->SetTitle("task");
1269 }
1270 // Full VM profile
1271 canvas->cd(ipad++);
1272 tree->SetMarkerStyle(kFullCircle);
1273 tree->SetMarkerColor(kGreen);
1274 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1275 tree->Draw("VM:event",cut,"", 1234567890, 0);
1276 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1277 if (hist) {
1278 hist->SetTitle("Virtual memory");
1279 hist->GetYaxis()->SetTitle("VM [MB]");
1280 }
1281 canvas->Modified();
1282 }
1283 tree->SetMarkerStyle(kCircle);
1284 tree->SetMarkerColor(kBlue);
1285 tree->SetMarkerSize(0.5);
1286 tree->Write();
1287 f.Close();
1288 delete tree;
1289 }
1290 if (crtdir) crtdir->cd();
1291 }
1292 // Validate the output files
1293 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1294 ofstream out;
1295 out.open("outputs_valid", ios::out);
1296 out.close();
1297 }
1298 if (cdir) cdir->cd();
1299 fInitTimer->Stop();
1300 if (fDebug || IsCollectThroughput()) {
1301 printf("=Analysis %s= Terminate time: %g[sec]\n", GetName(), fInitTimer->RealTime());
1302 }
1303 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1304}
1305//______________________________________________________________________________
1306void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1307{
1308// Profiles the task having the itop index in the list of top (first level) tasks.
1309 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1310 if (!task) {
1311 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1312 return;
1313 }
1314 ProfileTask(task->GetName(), option);
1315}
1316
1317//______________________________________________________________________________
1318void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1319{
1320// Profile a managed task after the execution of the analysis in case NSysInfo
1321// was used.
1322 if (gSystem->AccessPathName("syswatch.root")) {
1323 Error("ProfileTask", "No file syswatch.root found in the current directory");
1324 return;
1325 }
1326 if (gROOT->IsBatch()) return;
1327 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1328 if (!task) {
1329 Error("ProfileTask", "No top task named %s known by the manager.", name);
1330 return;
1331 }
1332 Int_t itop = fTopTasks->IndexOf(task);
1333 Int_t itask = fTasks->IndexOf(task);
1334 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1335 TDirectory *cdir = gDirectory;
1336 TFile f("syswatch.root");
1337 TTree *tree = (TTree*)f.Get("syswatch");
1338 if (!tree) {
1339 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1340 return;
1341 }
1342 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1343 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1344 canvas->Divide(2, 2, 0.01, 0.01);
1345 Int_t ipad = 1;
1346 TString cut;
1347 TH1 *hist;
1348 // VM profile for COO and Terminate methods
1349 canvas->cd(ipad++);
1350 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1351 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1352 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1353 if (hist) {
1354 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1355 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1356 hist->GetXaxis()->SetTitle("method");
1357 }
1358 // CPU profile per event
1359 canvas->cd(ipad++);
1360 cut = Form("task==%d && stage==1",itop);
1361 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1362 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1363 if (hist) {
1364 hist->SetTitle("Execution time per event");
1365 hist->GetYaxis()->SetTitle("CPU/event [s]");
1366 }
1367 // VM profile for Exec
1368 canvas->cd(ipad++);
1369 cut = Form("task==%d && stage==1",itop);
1370 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1371 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1372 if (hist) {
1373 hist->SetTitle("Alocated VM[MB] per event");
1374 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1375 }
1376 canvas->Modified();
1377 delete tree;
1378 f.Close();
1379 if (cdir) cdir->cd();
1380}
1381
1382//______________________________________________________________________________
1383void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1384{
1385// Adds a user task to the global list of tasks.
1386 if (fInitOK) {
1387 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1388 return;
1389 }
1390
1391 if (fTasks->FindObject(task)) {
1392 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1393 return;
1394 }
1395 task->SetActive(kFALSE);
1396 fTasks->Add(task);
1397}
1398
1399//______________________________________________________________________________
1400AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1401{
1402// Retreive task by name.
1403 if (!fTasks) return NULL;
1404 return (AliAnalysisTask*)fTasks->FindObject(name);
1405}
1406
1407//______________________________________________________________________________
1408Int_t AliAnalysisManager::GetTaskIndex(const AliAnalysisTask *task) const
1409{
1410// Returns task inded in the manager's list, -1 if not registered.
1411 if (!fTasks) return -1;
1412 return fTasks->IndexOf(task);
1413}
1414
1415//______________________________________________________________________________
1416AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1417 TClass *datatype, EAliAnalysisContType type, const char *filename)
1418{
1419// Create a data container of a certain type. Types can be:
1420// kExchangeContainer = 0, used to exchange data between tasks
1421// kInputContainer = 1, used to store input data
1422// kOutputContainer = 2, used for writing result to a file
1423// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1424// the output object to a folder inside the output file
1425 if (fContainers->FindObject(name)) {
1426 Error("CreateContainer","A container named %s already defined !",name);
1427 return NULL;
1428 }
1429 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1430 fContainers->Add(cont);
1431 switch (type) {
1432 case kInputContainer:
1433 fInputs->Add(cont);
1434 break;
1435 case kOutputContainer:
1436 fOutputs->Add(cont);
1437 if (filename && strlen(filename)) {
1438 cont->SetFileName(filename);
1439 cont->SetDataOwned(kFALSE); // data owned by the file
1440 }
1441 break;
1442 case kParamContainer:
1443 fParamCont->Add(cont);
1444 if (filename && strlen(filename)) {
1445 cont->SetFileName(filename);
1446 cont->SetDataOwned(kFALSE); // data owned by the file
1447 }
1448 break;
1449 case kExchangeContainer:
1450 cont->SetExchange(kTRUE);
1451 fExchangeCont->Add(cont);
1452 cont->SetDataOwned(kFALSE); // data owned by the publisher
1453 break;
1454 }
1455 return cont;
1456}
1457
1458//______________________________________________________________________________
1459Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1460 AliAnalysisDataContainer *cont)
1461{
1462// Connect input of an existing task to a data container.
1463 if (!task) {
1464 Error("ConnectInput", "Task pointer is NULL");
1465 return kFALSE;
1466 }
1467 if (!fTasks->FindObject(task)) {
1468 AddTask(task);
1469 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1470 }
1471 Bool_t connected = task->ConnectInput(islot, cont);
1472 return connected;
1473}
1474
1475//______________________________________________________________________________
1476Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1477 AliAnalysisDataContainer *cont)
1478{
1479// Connect output of an existing task to a data container.
1480 if (!task) {
1481 Error("ConnectOutput", "Task pointer is NULL");
1482 return kFALSE;
1483 }
1484 if (!fTasks->FindObject(task)) {
1485 AddTask(task);
1486 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1487 }
1488 Bool_t connected = task->ConnectOutput(islot, cont);
1489 return connected;
1490}
1491
1492//______________________________________________________________________________
1493void AliAnalysisManager::CleanContainers()
1494{
1495// Clean data from all containers that have already finished all client tasks.
1496 TIter next(fContainers);
1497 AliAnalysisDataContainer *cont;
1498 while ((cont=(AliAnalysisDataContainer *)next())) {
1499 if (cont->IsOwnedData() &&
1500 cont->IsDataReady() &&
1501 cont->ClientsExecuted()) cont->DeleteData();
1502 }
1503}
1504
1505//______________________________________________________________________________
1506Bool_t AliAnalysisManager::InitAnalysis()
1507{
1508// Initialization of analysis chain of tasks. Should be called after all tasks
1509// and data containers are properly connected
1510 // Reset flag and remove valid_outputs file if exists
1511 if (fInitOK) return kTRUE;
1512 if (!gSystem->AccessPathName("outputs_valid"))
1513 gSystem->Unlink("outputs_valid");
1514 // Check for top tasks (depending only on input data containers)
1515 if (!fTasks->First()) {
1516 Error("InitAnalysis", "Analysis has no tasks !");
1517 return kFALSE;
1518 }
1519 TIter next(fTasks);
1520 AliAnalysisTask *task;
1521 AliAnalysisDataContainer *cont;
1522 Int_t ntop = 0;
1523 Int_t nzombies = 0;
1524 Bool_t iszombie = kFALSE;
1525 Bool_t istop = kTRUE;
1526 Int_t i;
1527 while ((task=(AliAnalysisTask*)next())) {
1528 istop = kTRUE;
1529 iszombie = kFALSE;
1530 Int_t ninputs = task->GetNinputs();
1531 for (i=0; i<ninputs; i++) {
1532 cont = task->GetInputSlot(i)->GetContainer();
1533 if (!cont) {
1534 if (!iszombie) {
1535 task->SetZombie();
1536 fZombies->Add(task);
1537 nzombies++;
1538 iszombie = kTRUE;
1539 }
1540 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1541 i, task->GetName());
1542 }
1543 if (iszombie) continue;
1544 // Check if cont is an input container
1545 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1546 // Connect to parent task
1547 }
1548 if (istop) {
1549 ntop++;
1550 fTopTasks->Add(task);
1551 }
1552 }
1553 if (!ntop) {
1554 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1555 return kFALSE;
1556 }
1557 // Check now if there are orphan tasks
1558 for (i=0; i<ntop; i++) {
1559 task = (AliAnalysisTask*)fTopTasks->At(i);
1560 task->SetUsed();
1561 }
1562 Int_t norphans = 0;
1563 next.Reset();
1564 while ((task=(AliAnalysisTask*)next())) {
1565 if (!task->IsUsed()) {
1566 norphans++;
1567 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1568 }
1569 }
1570 // Check the task hierarchy (no parent task should depend on data provided
1571 // by a daughter task)
1572 for (i=0; i<ntop; i++) {
1573 task = (AliAnalysisTask*)fTopTasks->At(i);
1574 if (task->CheckCircularDeps()) {
1575 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1576 PrintStatus("dep");
1577 return kFALSE;
1578 }
1579 }
1580 // Check that all containers feeding post-event loop tasks are in the outputs list
1581 TIter nextcont(fContainers); // loop over all containers
1582 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1583 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1584 if (cont->HasConsumers()) {
1585 // Check if one of the consumers is post event loop
1586 TIter nextconsumer(cont->GetConsumers());
1587 while ((task=(AliAnalysisTask*)nextconsumer())) {
1588 if (task->IsPostEventLoop()) {
1589 fOutputs->Add(cont);
1590 break;
1591 }
1592 }
1593 }
1594 }
1595 }
1596 // Check if all special output containers have a file name provided
1597 TIter nextout(fOutputs);
1598 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1599 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1600 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1601 return kFALSE;
1602 }
1603 }
1604 // Initialize requested branch list if needed
1605 if (!fAutoBranchHandling) {
1606 next.Reset();
1607 while ((task=(AliAnalysisTask*)next())) {
1608 if (!task->HasBranches()) {
1609 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches.\nUse: fBranchNames = \"ESD:br1,br2,...,brN AOD:bra1,bra2,...,braM\"",
1610 task->GetName(), task->ClassName());
1611 return kFALSE;
1612 }
1613 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1614 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1615 return kFALSE;
1616 }
1617 TString taskbranches;
1618 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1619 if (taskbranches.IsNull()) {
1620 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1621 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1622 return kFALSE;
1623 }
1624 AddBranches(taskbranches);
1625 }
1626 }
1627 fInitOK = kTRUE;
1628 return kTRUE;
1629}
1630
1631//______________________________________________________________________________
1632void AliAnalysisManager::AddBranches(const char *branches)
1633{
1634// Add branches to the existing fRequestedBranches.
1635 TString br(branches);
1636 TObjArray *arr = br.Tokenize(",");
1637 TIter next(arr);
1638 TObject *obj;
1639 while ((obj=next())) {
1640 if (!fRequestedBranches.Contains(obj->GetName())) {
1641 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1642 fRequestedBranches += obj->GetName();
1643 }
1644 }
1645 delete arr;
1646}
1647
1648//______________________________________________________________________________
1649void AliAnalysisManager::CheckBranches(Bool_t load)
1650{
1651// The method checks the input branches to be loaded during the analysis.
1652 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1653 TObjArray *arr = fRequestedBranches.Tokenize(",");
1654 TIter next(arr);
1655 TObject *obj;
1656 while ((obj=next())) {
1657 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1658 if (!br) {
1659 br = fTree->GetBranch(obj->GetName());
1660 if (!br) {
1661 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1662 continue;
1663 }
1664 fTable.Add(br);
1665 }
1666 if (load && br->GetReadEntry()!=GetCurrentEntry()) {
1667 br->GetEntry(GetCurrentEntry());
1668 }
1669 }
1670 delete arr;
1671}
1672
1673//______________________________________________________________________________
1674Bool_t AliAnalysisManager::CheckTasks() const
1675{
1676// Check consistency of tasks.
1677 Int_t ntasks = fTasks->GetEntries();
1678 if (!ntasks) {
1679 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1680 return kFALSE;
1681 }
1682 // Get the pointer to AliAnalysisTaskSE::Class()
1683 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1684 // Loop all tasks to check if their corresponding library was loaded
1685 TIter next(fTasks);
1686 TObject *obj;
1687 while ((obj=next())) {
1688 if (obj->IsA() == badptr) {
1689 Error("CheckTasks", "##################\n \
1690 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1691 return kFALSE;
1692 }
1693 }
1694 return kTRUE;
1695}
1696
1697//______________________________________________________________________________
1698void AliAnalysisManager::PrintStatus(Option_t *option) const
1699{
1700// Print task hierarchy.
1701 if (!fInitOK) {
1702 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1703 return;
1704 }
1705 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1706 if (getsysInfo)
1707 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1708 AliAnalysisDataContainer *cont = fCommonInput;
1709 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1710 printf("=== TOP CONTAINER:\n");
1711 cont->PrintContainer(option,0);
1712 // Reset "touched" flag
1713 TIter next(fContainers);
1714 while ((cont = (AliAnalysisDataContainer*)next())) cont->SetTouched(kFALSE);
1715 TIter nextt(fTasks);
1716 AliAnalysisTask *task;
1717 while ((task=(AliAnalysisTask*)nextt()))
1718 task->SetActive(kFALSE);
1719
1720 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1721 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1722
1723 TString sopt(option);
1724 sopt.ToUpper();
1725
1726 if (sopt.Contains("ALL"))
1727 {
1728 if ( fOutputEventHandler )
1729 {
1730 cout << TString('_',78) << endl;
1731 cout << "OutputEventHandler:" << endl;
1732 fOutputEventHandler->Print(" ");
1733 }
1734 }
1735}
1736
1737//______________________________________________________________________________
1738void AliAnalysisManager::ResetAnalysis()
1739{
1740// Reset all execution flags and clean containers.
1741 TIter nextTask(fTasks);
1742 AliAnalysisTask *task;
1743 while ((task=(AliAnalysisTask*)nextTask())) {
1744 // Clean all tasks
1745 task->Reset();
1746 }
1747// CleanContainers();
1748}
1749
1750//______________________________________________________________________________
1751void AliAnalysisManager::RunLocalInit()
1752{
1753// Run LocalInit method for all tasks.
1754 TDirectory *cdir = gDirectory;
1755 if (IsTrainInitialized()) return;
1756 TIter nextTask(fTasks);
1757 AliAnalysisTask *task;
1758 while ((task=(AliAnalysisTask*)nextTask())) {
1759 gROOT->cd();
1760 task->LocalInit();
1761 }
1762 if (cdir) cdir->cd();
1763 TObject::SetBit(kTasksInitialized, kTRUE);
1764}
1765
1766//______________________________________________________________________________
1767void AliAnalysisManager::InputFileFromTree(TTree * const tree, TString &fname)
1768{
1769// Retrieves name of the file from tree
1770 fname = "";
1771 if (!tree) return;
1772 TFile *file = tree->GetCurrentFile();
1773 TString basename;
1774 if (!file) {
1775 TChain *chain = dynamic_cast<TChain*>(tree);
1776 if (!chain || !chain->GetNtrees()) return;
1777 basename = gSystem->BaseName(chain->GetListOfFiles()->First()->GetTitle());
1778 } else {
1779 basename = gSystem->BaseName(file->GetName());
1780 }
1781 Int_t index = basename.Index("#");
1782 fname = basename(index+1, basename.Length());
1783}
1784
1785//______________________________________________________________________________
1786Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1787{
1788// Start analysis having a grid handler.
1789 if (!fGridHandler) {
1790 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1791 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1792 return -1;
1793 }
1794 TTree *tree = NULL;
1795 return StartAnalysis(type, tree, nentries, firstentry);
1796}
1797
1798//______________________________________________________________________________
1799Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1800{
1801// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1802// MIX. Process nentries starting from firstentry
1803 Long64_t retv = 0;
1804 // Backup current directory and make sure gDirectory points to gROOT
1805 TDirectory *cdir = gDirectory;
1806 gROOT->cd();
1807 if (!fInitOK) {
1808 Error("StartAnalysis","Analysis manager was not initialized !");
1809 if (cdir) cdir->cd();
1810 return -1;
1811 }
1812 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1813 if (fDebug > 1) {
1814 printf("StartAnalysis %s\n",GetName());
1815 AliLog::SetGlobalLogLevel(AliLog::kInfo);
1816 }
1817 fMaxEntries = nentries;
1818 fIsRemote = kFALSE;
1819 TString anaType = type;
1820 anaType.ToLower();
1821 fMode = kLocalAnalysis;
1822 if (anaType.Contains("file")) fIsRemote = kTRUE;
1823 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1824 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1825 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1826 if (fInputEventHandler) {
1827 TString fname;
1828 InputFileFromTree(tree, fname);
1829 if (fname.Length()) fInputEventHandler->SetInputFileName(fname);
1830 }
1831
1832 if (fMode == kGridAnalysis) {
1833 fIsRemote = kTRUE;
1834 if (!anaType.Contains("terminate")) {
1835 if (!fGridHandler) {
1836 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1837 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1838 if (cdir) cdir->cd();
1839 return -1;
1840 }
1841 // Write analysis manager in the analysis file
1842 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1843 // run local task configuration
1844 RunLocalInit();
1845 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1846 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1847 if (cdir) cdir->cd();
1848 return -1;
1849 }
1850
1851 // Terminate grid analysis
1852 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1853 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1854 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1855 if (!fGridHandler->MergeOutputs()) {
1856 // Return if outputs could not be merged or if it alien handler
1857 // was configured for offline mode or local testing.
1858 if (cdir) cdir->cd();
1859 return 0;
1860 }
1861 }
1862 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1863 if (cdir) cdir->cd();
1864 ImportWrappers(NULL);
1865 Terminate();
1866 if (cdir) cdir->cd();
1867 return 0;
1868 }
1869 TString line;
1870 SetEventLoop(kFALSE);
1871 // Enable event loop mode if a tree was provided
1872 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1873
1874 TChain *chain = 0;
1875 TString ttype = "TTree";
1876 if (tree && tree->IsA() == TChain::Class()) {
1877 chain = (TChain*)tree;
1878 if (!chain || !chain->GetListOfFiles()->First()) {
1879 Error("StartAnalysis", "Cannot process null or empty chain...");
1880 if (cdir) cdir->cd();
1881 return -1;
1882 }
1883 ttype = "TChain";
1884 }
1885
1886 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1887 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1888 // Initialize locally all tasks (happens for all modes)
1889 TIter next(fTasks);
1890 AliAnalysisTask *task;
1891 RunLocalInit();
1892
1893 switch (fMode) {
1894 case kLocalAnalysis:
1895 if (!tree && !fGridHandler) {
1896 TIter nextT(fTasks);
1897 // Call CreateOutputObjects for all tasks
1898 Int_t itask = 0;
1899 Bool_t dirStatus = TH1::AddDirectoryStatus();
1900 while ((task=(AliAnalysisTask*)nextT())) {
1901 TH1::AddDirectory(kFALSE);
1902 task->CreateOutputObjects();
1903 if (!task->CheckPostData()) {
1904 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1905 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1906 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1907 }
1908 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1909 gROOT->cd();
1910 itask++;
1911 }
1912 TH1::AddDirectory(dirStatus);
1913 if (IsExternalLoop()) {
1914 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1915 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1916 return 0;
1917 }
1918 ExecAnalysis();
1919 Terminate();
1920 return 0;
1921 }
1922 fSelector = new AliAnalysisSelector(this);
1923 // Check if a plugin handler is used
1924 if (fGridHandler) {
1925 // Get the chain from the plugin
1926 TString dataType = "esdTree";
1927 if (fInputEventHandler) {
1928 dataType = fInputEventHandler->GetDataType();
1929 dataType.ToLower();
1930 dataType += "Tree";
1931 }
1932 chain = fGridHandler->GetChainForTestMode(dataType);
1933 if (!chain) {
1934 Error("StartAnalysis", "No chain for test mode. Aborting.");
1935 return -1;
1936 }
1937 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1938 retv = chain->Process(fSelector, "", nentries, firstentry);
1939 break;
1940 }
1941 // Run tree-based analysis via AliAnalysisSelector
1942 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1943 retv = tree->Process(fSelector, "", nentries, firstentry);
1944 break;
1945 case kProofAnalysis:
1946 fIsRemote = kTRUE;
1947 // Check if the plugin is used
1948 if (fGridHandler) {
1949 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1950 }
1951 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1952 Error("StartAnalysis", "No PROOF!!! Exiting.");
1953 if (cdir) cdir->cd();
1954 return -1;
1955 }
1956 line = Form("gProof->AddInput((TObject*)%p);", this);
1957 gROOT->ProcessLine(line);
1958 if (chain) {
1959 chain->SetProof();
1960 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1961 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1962 } else {
1963 Error("StartAnalysis", "No chain!!! Exiting.");
1964 if (cdir) cdir->cd();
1965 return -1;
1966 }
1967 break;
1968 case kGridAnalysis:
1969 fIsRemote = kTRUE;
1970 if (!anaType.Contains("terminate")) {
1971 if (!fGridHandler) {
1972 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1973 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1974 if (cdir) cdir->cd();
1975 return -1;
1976 }
1977 // Write analysis manager in the analysis file
1978 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1979 // Start the analysis via the handler
1980 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1981 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1982 if (cdir) cdir->cd();
1983 return -1;
1984 }
1985
1986 // Terminate grid analysis
1987 if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1988 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1989 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1990 if (!fGridHandler->MergeOutputs()) {
1991 // Return if outputs could not be merged or if it alien handler
1992 // was configured for offline mode or local testing.
1993 if (cdir) cdir->cd();
1994 return 0;
1995 }
1996 }
1997 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1998 ImportWrappers(NULL);
1999 Terminate();
2000 if (cdir) cdir->cd();
2001 return 0;
2002 case kMixingAnalysis:
2003 // Run event mixing analysis
2004 if (!fEventPool) {
2005 Error("StartAnalysis", "Cannot run event mixing without event pool");
2006 if (cdir) cdir->cd();
2007 return -1;
2008 }
2009 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
2010 fSelector = new AliAnalysisSelector(this);
2011 while ((chain=fEventPool->GetNextChain())) {
2012 next.Reset();
2013 // Call NotifyBinChange for all tasks
2014 while ((task=(AliAnalysisTask*)next()))
2015 if (!task->IsPostEventLoop()) task->NotifyBinChange();
2016 retv = chain->Process(fSelector);
2017 if (retv < 0) {
2018 Error("StartAnalysis", "Mixing analysis failed");
2019 if (cdir) cdir->cd();
2020 return retv;
2021 }
2022 }
2023 PackOutput(fSelector->GetOutputList());
2024 Terminate();
2025 }
2026 if (cdir) cdir->cd();
2027 return retv;
2028}
2029
2030//______________________________________________________________________________
2031Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
2032{
2033// Start analysis for this manager on a given dataset. Analysis task can be:
2034// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
2035 if (!fInitOK) {
2036 Error("StartAnalysis","Analysis manager was not initialized !");
2037 return -1;
2038 }
2039 fIsRemote = kTRUE;
2040 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
2041 TString anaType = type;
2042 anaType.ToLower();
2043 if (!anaType.Contains("proof")) {
2044 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
2045 return -1;
2046 }
2047 fMode = kProofAnalysis;
2048 TString line;
2049 TString proofProcessOpt;
2050 SetEventLoop(kTRUE);
2051 // Set the dataset flag
2052 TObject::SetBit(kUseDataSet);
2053 fTree = 0;
2054 if (fGridHandler) {
2055 // Start proof analysis using the grid handler
2056 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
2057 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
2058 return -1;
2059 }
2060 // Check if the plugin is in test mode
2061 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
2062 dataset = "test_collection";
2063 } else {
2064 dataset = fGridHandler->GetProofDataSet();
2065 }
2066
2067 proofProcessOpt = fGridHandler->GetProofProcessOpt();
2068 }
2069
2070 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
2071 Error("StartAnalysis", "No PROOF!!! Exiting.");
2072 return -1;
2073 }
2074
2075 // Initialize locally all tasks
2076 RunLocalInit();
2077
2078 line = Form("gProof->AddInput((TObject*)%p);", this);
2079 gROOT->ProcessLine(line);
2080 Long_t retv;
2081 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
2082 dataset,proofProcessOpt.Data(), nentries, firstentry);
2083 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
2084 retv = (Long_t)gROOT->ProcessLine(line);
2085 return retv;
2086}
2087
2088//______________________________________________________________________________
2089TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
2090{
2091// Opens according the option the file specified by cont->GetFileName() and changes
2092// current directory to cont->GetFolderName(). If the file was already opened, it
2093// checks if the option UPDATE was preserved. File open via TProofOutputFile can
2094// be optionally ignored.
2095 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2096 TString filename = cont->GetFileName();
2097 TFile *f = NULL;
2098 if (filename.IsNull()) {
2099 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2100 return NULL;
2101 }
2102 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2103 && !ignoreProof)
2104 f = mgr->OpenProofFile(cont,option);
2105 else {
2106 // Check first if the file is already opened
2107 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2108 if (f) {
2109 // Check if option "UPDATE" was preserved
2110 TString opt(option);
2111 opt.ToUpper();
2112 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2113 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2114 } else {
2115 f = TFile::Open(filename, option);
2116 }
2117 }
2118 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2119 cont->SetFile(f);
2120 // Cd to file
2121 f->cd();
2122 // Check for a folder request
2123 TString dir = cont->GetFolderName();
2124 if (!dir.IsNull()) {
2125 if (!f->GetDirectory(dir)) f->mkdir(dir);
2126 f->cd(dir);
2127 }
2128 return f;
2129 }
2130 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2131 cont->SetFile(NULL);
2132 return NULL;
2133}
2134
2135//______________________________________________________________________________
2136TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
2137{
2138// Opens a special output file used in PROOF.
2139 TString line;
2140 TString filename = cont->GetFileName();
2141 if (cont == fCommonOutput) {
2142 if (fOutputEventHandler) {
2143 if (strlen(extaod)) filename = extaod;
2144 filename = fOutputEventHandler->GetOutputFileName();
2145 }
2146 else Fatal("OpenProofFile","No output container. Exiting.");
2147 }
2148 TFile *f = NULL;
2149 if (fMode!=kProofAnalysis || !fSelector) {
2150 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2151 return NULL;
2152 }
2153 if (fSpecialOutputLocation.Length()) {
2154 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2155 if (f) {
2156 // Check if option "UPDATE" was preserved
2157 TString opt(option);
2158 opt.ToUpper();
2159 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2160 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2161 } else {
2162 f = new TFile(filename, option);
2163 }
2164 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2165 cont->SetFile(f);
2166 // Cd to file
2167 f->cd();
2168 // Check for a folder request
2169 TString dir = cont->GetFolderName();
2170 if (dir.Length()) {
2171 if (!f->GetDirectory(dir)) f->mkdir(dir);
2172 f->cd(dir);
2173 }
2174 return f;
2175 }
2176 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2177 cont->SetFile(NULL);
2178 return NULL;
2179 }
2180 // Check if there is already a proof output file in the output list
2181 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2182 if (pof) {
2183 // Get the actual file
2184 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
2185 filename = (const char*)gROOT->ProcessLine(line);
2186 if (fDebug>1) {
2187 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2188 }
2189 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2190 if (!f) {
2191 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2192 return NULL;
2193 }
2194 // Check if option "UPDATE" was preserved
2195 TString opt(option);
2196 opt.ToUpper();
2197 if ((opt=="UPDATE") && (opt!=f->GetOption()))
2198 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2199 } else {
2200 if (cont->IsRegisterDataset()) {
2201 TString dsetName = filename;
2202 dsetName.ReplaceAll(".root", cont->GetTitle());
2203 dsetName.ReplaceAll(":","_");
2204 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2205 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
2206 } else {
2207 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2208 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2209 }
2210 if (fDebug > 1) printf("=== %s\n", line.Data());
2211 gROOT->ProcessLine(line);
2212 line = Form("pf->OpenFile(\"%s\");", option);
2213 gROOT->ProcessLine(line);
2214 f = gFile;
2215 if (fDebug > 1) {
2216 gROOT->ProcessLine("pf->Print()");
2217 printf(" == proof file name: %s", f->GetName());
2218 }
2219 // Add to proof output list
2220 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
2221 if (fDebug > 1) printf("=== %s\n", line.Data());
2222 gROOT->ProcessLine(line);
2223 }
2224 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2225 cont->SetFile(f);
2226 // Cd to file
2227 f->cd();
2228 // Check for a folder request
2229 TString dir = cont->GetFolderName();
2230 if (!dir.IsNull()) {
2231 if (!f->GetDirectory(dir)) f->mkdir(dir);
2232 f->cd(dir);
2233 }
2234 return f;
2235 }
2236 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2237 cont->SetFile(NULL);
2238 return NULL;
2239}
2240
2241//______________________________________________________________________________
2242void AliAnalysisManager::ExecAnalysis(Option_t *option)
2243{
2244// Execute analysis.
2245 static Long64_t nentries = 0;
2246 static TTree *lastTree = 0;
2247 static TStopwatch *timer = new TStopwatch();
2248 // Only the first call to Process will trigger a true Notify. Other Notify
2249 // coming before is ignored.
2250 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2251 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2252 Notify();
2253 }
2254 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2255 else {
2256 if (fTree && (fTree != lastTree)) {
2257 nentries += fTree->GetEntries();
2258 lastTree = fTree;
2259 }
2260 if (!fNcalls) timer->Start();
2261 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2262 }
2263 fIOTimer->Start(kTRUE);
2264 gROOT->cd();
2265 TDirectory *cdir = gDirectory;
2266 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2267 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2268 if (!fInitOK) {
2269 Error("ExecAnalysis", "Analysis manager was not initialized !");
2270 if (cdir) cdir->cd();
2271 return;
2272 }
2273 fNcalls++;
2274 AliAnalysisTask *task;
2275 // Reset the analysis
2276 ResetAnalysis();
2277 // Check if the top tree is active.
2278 if (fTree) {
2279 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2280 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2281 TIter next(fTasks);
2282 // De-activate all tasks (not needed anymore after ResetAnalysis
2283// while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2284 AliAnalysisDataContainer *cont = fCommonInput;
2285 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2286 if (!cont) {
2287 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2288 if (cdir) cdir->cd();
2289 return;
2290 }
2291 cont->SetData(fTree); // This set activity for all tasks reading only from the top container
2292 Long64_t entry = fTree->GetTree()->GetReadEntry();
2293//
2294// Call BeginEvent() for optional input/output and MC services
2295 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2296 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2297 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2298 gROOT->cd();
2299 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2300 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2301//
2302// Execute the tasks
2303// TIter next1(cont->GetConsumers());
2304 fIOTimer->Stop();
2305 fIOTime += fIOTimer->RealTime();
2306 fCPUTimer->Start(kTRUE);
2307 TIter next1(fTopTasks);
2308 Int_t itask = 0;
2309 while ((task=(AliAnalysisTask*)next1())) {
2310 task->SetActive(kTRUE);
2311 if (fDebug >1) {
2312 cout << " Executing task " << task->GetName() << endl;
2313 }
2314 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2315 task->ExecuteTask(option);
2316 if (fStatistics) fStatistics->StopTimer();
2317 gROOT->cd();
2318 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2319 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2320 itask++;
2321 }
2322 fCPUTimer->Stop();
2323 fCPUTime += fCPUTimer->RealTime();
2324 fIOTimer->Start(kTRUE);
2325//
2326// Call FinishEvent() for optional output and MC services
2327 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2328 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2329 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2330 // Gather system information if requested
2331 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2332 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2333 if (cdir) cdir->cd();
2334 fIOTimer->Stop();
2335 fIOTime += fIOTimer->RealTime();
2336 return;
2337 }
2338 // The event loop is not controlled by TSelector
2339//
2340// Call BeginEvent() for optional input/output and MC services
2341 fIOTimer->Start(kTRUE);
2342 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2343 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2344 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2345 fIOTimer->Stop();
2346 fIOTime += fIOTimer->RealTime();
2347 gROOT->cd();
2348 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2349 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2350 fCPUTimer->Start(kTRUE);
2351 TIter next2(fTopTasks);
2352 while ((task=(AliAnalysisTask*)next2())) {
2353 task->SetActive(kTRUE);
2354 if (fDebug > 1) {
2355 cout << " Executing task " << task->GetName() << endl;
2356 }
2357 if (fStatistics) fStatistics->StartTimer(GetTaskIndex(task), task->GetName(), task->ClassName());
2358 task->ExecuteTask(option);
2359 if (fStatistics) fStatistics->StopTimer();
2360 gROOT->cd();
2361 }
2362 fCPUTimer->Stop();
2363 fCPUTime += fCPUTimer->RealTime();
2364//
2365// Call FinishEvent() for optional output and MC services
2366 fIOTimer->Start(kTRUE);
2367 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2368 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2369 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2370 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2371 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2372 if (cdir) cdir->cd();
2373 fIOTimer->Stop();
2374 fIOTime += fIOTimer->RealTime();
2375}
2376
2377//______________________________________________________________________________
2378Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2379{
2380// Check if the stdout is connected to a pipe (C.Holm)
2381 Bool_t ispipe = kFALSE;
2382 out.seekp(0, std::ios_base::cur);
2383 if (out.fail()) {
2384 out.clear();
2385 if (errno == ESPIPE) ispipe = kTRUE;
2386 }
2387 return ispipe;
2388}
2389
2390//______________________________________________________________________________
2391void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2392{
2393// Set the input event handler and create a container for it.
2394 Changed();
2395 fInputEventHandler = handler;
2396 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2397}
2398
2399//______________________________________________________________________________
2400void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2401{
2402// Set the input event handler and create a container for it.
2403 Changed();
2404 fOutputEventHandler = handler;
2405 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2406 fCommonOutput->SetSpecialOutput();
2407}
2408
2409//______________________________________________________________________________
2410void AliAnalysisManager::SetDebugLevel(UInt_t level)
2411{
2412// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2413 if (TObject::TestBit(kUseProgressBar)) {
2414 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2415 return;
2416 }
2417 fDebug = level;
2418}
2419
2420//______________________________________________________________________________
2421void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2422{
2423// Enable a text mode progress bar. Resets debug level to 0.
2424 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2425 TObject::SetBit(kUseProgressBar,flag);
2426 fPBUpdateFreq = freq;
2427 fDebug = 0;
2428}
2429
2430//______________________________________________________________________________
2431void AliAnalysisManager::RegisterExtraFile(const char *fname)
2432{
2433// This method is used externally to register output files which are not
2434// connected to any output container, so that the manager can properly register,
2435// retrieve or merge them when running in distributed mode. The file names are
2436// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2437 if (fExtraFiles.Contains(fname)) return;
2438 if (fExtraFiles.Length()) fExtraFiles += " ";
2439 fExtraFiles += fname;
2440}
2441
2442//______________________________________________________________________________
2443Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2444{
2445// Copy a file from the location specified ina the wrapper with the same name from the source list.
2446 char fullPath[512];
2447 char chUrl[512];
2448 char tmp[1024];
2449 TObject *pof = source->FindObject(filename);
2450 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2451 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2452 return kFALSE;
2453 }
2454 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2455 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2456 TString clientUrl(chUrl);
2457 TString fullPath_str(fullPath);
2458 if (clientUrl.Contains("localhost")){
2459 TObjArray* array = fullPath_str.Tokenize ( "//" );
2460 TObjString *strobj = ( TObjString *)array->At(1);
2461 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2462 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2463 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2464 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2465 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2466 delete arrayPort;
2467 delete array;
2468 }
2469 else if (clientUrl.Contains("__lite__")) {
2470 // Special case for ProofLite environement - get file info and copy.
2471 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2472 fullPath_str = Form("%s/%s", tmp, fullPath);
2473 }
2474 if (fDebug > 1)
2475 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2476 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2477 if (!gotit)
2478 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2479 return gotit;
2480}
2481
2482//______________________________________________________________________________
2483void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2484{
2485// Fill analysis type in the provided string.
2486 switch (fMode) {
2487 case kLocalAnalysis:
2488 type = "local";
2489 return;
2490 case kProofAnalysis:
2491 type = "proof";
2492 return;
2493 case kGridAnalysis:
2494 type = "grid";
2495 return;
2496 case kMixingAnalysis:
2497 type = "mix";
2498 }
2499}
2500
2501//______________________________________________________________________________
2502Bool_t AliAnalysisManager::ValidateOutputFiles() const
2503{
2504// Validate all output files.
2505 TIter next(fOutputs);
2506 AliAnalysisDataContainer *output;
2507 TDirectory *cdir = gDirectory;
2508 TString openedFiles;
2509 while ((output=(AliAnalysisDataContainer*)next())) {
2510 if (output->IsRegisterDataset()) continue;
2511 TString filename = output->GetFileName();
2512 if (filename == "default") {
2513 if (!fOutputEventHandler) continue;
2514 filename = fOutputEventHandler->GetOutputFileName();
2515 // Main AOD may not be there
2516 if (gSystem->AccessPathName(filename)) continue;
2517 }
2518 // Check if the file is closed
2519 if (openedFiles.Contains(filename)) continue;;
2520 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2521 if (file) {
2522 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2523 // Clear file list to release object ownership to user.
2524// file->Clear();
2525 file->Close();
2526 }
2527 file = TFile::Open(filename);
2528 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2529 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2530 if (cdir) cdir->cd();
2531 return kFALSE;
2532 }
2533 file->Close();
2534 openedFiles += filename;
2535 openedFiles += " ";
2536 }
2537 if (cdir) cdir->cd();
2538 return kTRUE;
2539}
2540
2541//______________________________________________________________________________
2542void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2543{
2544// Implements a nice text mode progress bar.
2545 static Long64_t icount = 0;
2546 static TString oname;
2547 static TString nname;
2548 static Long64_t ocurrent = 0;
2549 static Long64_t osize = 0;
2550 static Int_t oseconds = 0;
2551 static TStopwatch *owatch = 0;
2552 static Bool_t oneoftwo = kFALSE;
2553 static Int_t nrefresh = 0;
2554 static Int_t nchecks = 0;
2555 static char lastChar = 0;
2556 const char symbol[4] = {'-','\\','|','/'};
2557
2558 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2559 if (!refresh) {
2560 nrefresh = 0;
2561 if (!size) return;
2562 owatch = watch;
2563 oname = opname;
2564 ocurrent = TMath::Abs(current);
2565 osize = TMath::Abs(size);
2566 if (ocurrent > osize) ocurrent=osize;
2567 } else {
2568 nrefresh++;
2569 if (!osize) return;
2570 }
2571 if ((current % fPBUpdateFreq) != 0) return;
2572 icount++;
2573 char progress[11] = " ";
2574 Int_t ichar = icount%4;
2575 Double_t time = 0.;
2576 Int_t hours = 0;
2577 Int_t minutes = 0;
2578 Int_t seconds = 0;
2579 if (owatch && !last) {
2580 owatch->Stop();
2581 time = owatch->RealTime();
2582 seconds = int(time) % 60;
2583 minutes = (int(time) / 60) % 60;
2584 hours = (int(time) / 60 / 60);
2585 if (refresh) {
2586 if (oseconds==seconds) {
2587 owatch->Continue();
2588 return;
2589 }
2590 oneoftwo = !oneoftwo;
2591 }
2592 oseconds = seconds;
2593 }
2594 if (refresh && oneoftwo) {
2595 nname = oname;
2596 if (nchecks <= 0) nchecks = nrefresh+1;
2597 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2598 oname = Form(" == %d%% ==", pctdone);
2599 }
2600 Double_t percent = 100.0*ocurrent/osize;
2601 Int_t nchar = Int_t(percent/10);
2602 if (nchar>10) nchar=10;
2603 Int_t i;
2604 for (i=0; i<nchar; i++) progress[i] = '=';
2605 progress[nchar] = symbol[ichar];
2606 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2607 progress[10] = '\0';
2608 oname += " ";
2609 oname.Remove(20);
2610 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2611 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2612 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2613 if (time>0.) {
2614 Int_t full = Int_t(ocurrent > 0 ?
2615 time * (float(osize)/ocurrent) + .5 :
2616 99*3600+59*60+59);
2617 Int_t remain = Int_t(full - time);
2618 Int_t rsec = remain % 60;
2619 Int_t rmin = (remain / 60) % 60;
2620 Int_t rhour = (remain / 60 / 60);
2621 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2622 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2623 }
2624 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2625 if (refresh && oneoftwo) oname = nname;
2626 if (owatch) owatch->Continue();
2627 if (last) {
2628 icount = 0;
2629 owatch = 0;
2630 ocurrent = 0;
2631 osize = 0;
2632 oseconds = 0;
2633 oneoftwo = kFALSE;
2634 nrefresh = 0;
2635 fprintf(stderr, "\n");
2636 }
2637}
2638
2639//______________________________________________________________________________
2640void AliAnalysisManager::DoLoadBranch(const char *name)
2641{
2642 // Get tree and load branch if needed.
2643 static Long64_t crtEntry = -100;
2644
2645 if (fAutoBranchHandling || !fTree)
2646 return;
2647
2648 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2649 if (!br) {
2650 br = fTree->GetBranch(name);
2651 if (!br) {
2652 Error("DoLoadBranch", "Could not find branch %s",name);
2653 return;
2654 }
2655 fTable.Add(br);
2656 }
2657 if (br->GetReadEntry()==fCurrentEntry) return;
2658 Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2659 if (readbytes<0) {
2660 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2661 if (crtEntry != fCurrentEntry) {
2662 CountEvent(1,0,1,0);
2663 crtEntry = fCurrentEntry;
2664 }
2665 } else {
2666 if (crtEntry != fCurrentEntry) {
2667 CountEvent(1,1,0,0);
2668 crtEntry = fCurrentEntry;
2669 }
2670 }
2671}
2672
2673//______________________________________________________________________________
2674void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2675{
2676// Add the statistics task to the manager.
2677 if (fStatistics) {
2678 Info("AddStatisticsTask", "Already added");
2679 return;
2680 }
2681 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2682 gROOT->ProcessLine(line);
2683}
2684
2685//______________________________________________________________________________
2686void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2687{
2688// Bookkeep current event;
2689 if (!fStatistics) return;
2690 fStatistics->AddInput(ninput);
2691 fStatistics->AddProcessed(nprocessed);
2692 fStatistics->AddFailed(nfailed);
2693 fStatistics->AddAccepted(naccepted);
2694}
2695
2696//______________________________________________________________________________
2697void AliAnalysisManager::AddStatisticsMsg(const char *line)
2698{
2699// Add a line in the statistics message. If available, the statistics message is written
2700// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2701// on the client.
2702 if (!strlen(line)) return;
2703 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2704 fStatisticsMsg += line;
2705}
2706
2707//______________________________________________________________________________
2708void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2709{
2710// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2711 static Bool_t done = kFALSE;
2712 if (done) return;
2713 done = kTRUE;
2714 if (!fStatistics) return;
2715 ofstream out;
2716 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2717 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2718 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2719 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2720 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2721 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2722 fStatistics->GetNaccepted()), ios::out);
2723 out << fStatisticsMsg << endl;
2724 out.close();
2725}
2726
2727//______________________________________________________________________________
2728const char* AliAnalysisManager::GetOADBPath()
2729{
2730// returns the path of the OADB
2731// this static function just depends on environment variables
2732
2733 static TString oadbPath;
2734
2735 if (gSystem->Getenv("OADB_PATH"))
2736 oadbPath = gSystem->Getenv("OADB_PATH");
2737 else if (gSystem->Getenv("ALICE_ROOT"))
2738 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2739 else
2740 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2741
2742 return oadbPath;
2743}
2744
2745//______________________________________________________________________________
2746void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2747{
2748// Define a custom string variable mapped to a global unique name. The variable
2749// can be then retrieved by a given analysis macro via GetGlobalStr(key).
2750 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2751 if (!mgr) {
2752 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2753 return;
2754 }
2755 Bool_t valid = kFALSE;
2756 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2757 if (valid) {
2758 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2759 return;
2760 }
2761 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2762}
2763
2764//______________________________________________________________________________
2765const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2766{
2767// Static method to retrieve a global variable defined via SetGlobalStr.
2768 valid = kFALSE;
2769 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2770 if (!mgr) return 0;
2771 TObject *value = mgr->GetGlobals()->GetValue(key);
2772 if (!value) return 0;
2773 valid = kTRUE;
2774 return value->GetName();
2775}
2776
2777//______________________________________________________________________________
2778void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2779{
2780// Define a custom integer variable mapped to a global unique name. The variable
2781// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2782 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2783 if (!mgr) {
2784 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2785 return;
2786 }
2787 Bool_t valid = kFALSE;
2788 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2789 if (valid) {
2790 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2791 return;
2792 }
2793 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2794}
2795
2796//______________________________________________________________________________
2797Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2798{
2799// Static method to retrieve a global variable defined via SetGlobalInt.
2800 valid = kFALSE;
2801 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2802 if (!mgr) return 0;
2803 TObject *value = mgr->GetGlobals()->GetValue(key);
2804 if (!value) return 0;
2805 valid = kTRUE;
2806 TString s = value->GetName();
2807 return s.Atoi();
2808}
2809
2810//______________________________________________________________________________
2811void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2812{
2813// Define a custom double precision variable mapped to a global unique name. The variable
2814// can be then retrieved by a given analysis macro via GetGlobalInt(key).
2815 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2816 if (!mgr) {
2817 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2818 return;
2819 }
2820 Bool_t valid = kFALSE;
2821 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2822 if (valid) {
2823 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2824 return;
2825 }
2826 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2827}
2828
2829//______________________________________________________________________________
2830Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2831{
2832// Static method to retrieve a global variable defined via SetGlobalDbl.
2833 valid = kFALSE;
2834 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2835 if (!mgr) return 0;
2836 TObject *value = mgr->GetGlobals()->GetValue(key);
2837 if (!value) return 0;
2838 valid = kTRUE;
2839 TString s = value->GetName();
2840 return s.Atof();
2841}
2842
2843//______________________________________________________________________________
2844void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2845{
2846// Sets Class debug level
2847
2848 if (!fDebugOptions) {
2849 fDebugOptions = new TObjArray();
2850 fDebugOptions->SetOwner(kTRUE);
2851 }
2852
2853 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2854 if (!debugOpt) {
2855 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel,className).Data());
2856 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2857 } else {
2858 TString oldDebugStr = debugOpt->GetTitle();
2859 Int_t oldDebug = oldDebugStr.Atoi();
2860 if (debugLevel > oldDebug) {
2861 AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel,className,oldDebug).Data());
2862 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2863 } else {
2864 AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel,className,oldDebug).Data());
2865 }
2866 }
2867}
2868
2869//______________________________________________________________________________
2870void AliAnalysisManager::ApplyDebugOptions()
2871{
2872// Apply debug options
2873
2874 if (!fDebugOptions) return;
2875
2876 TIter next(fDebugOptions);
2877 TNamed *debug;
2878 TString debugLevel;
2879 while ((debug=dynamic_cast<TNamed*>(next()))) {
2880 debugLevel = debug->GetTitle();
2881 AliInfo(TString::Format("Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()).Data());
2882 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2883 }
2884}
2885
2886//______________________________________________________________________________
2887Bool_t AliAnalysisManager::IsMacroLoaded(const char * filename)
2888{
2889// Check if a macro was loaded.
2890 return fgMacroNames.Contains(filename);
2891}
2892
2893//______________________________________________________________________________
2894Int_t AliAnalysisManager::LoadMacro(const char *filename, Int_t *error, Bool_t check)
2895{
2896// Redirection of gROOT->LoadMacro which makes sure the same macro is not loaded
2897// twice
2898 TString macroName = gSystem->BaseName(filename);
2899 // Strip appended +, ++, +g, +O
2900 Int_t index = macroName.Index("+");
2901 if (index>0) macroName.Remove(index);
2902 if (fgMacroNames.Contains(macroName)) {
2903 // Macro with the same name loaded already in this root session, do
2904 // nothing
2905 error = 0;
2906 return 0;
2907 }
2908 Int_t ret = gROOT->LoadMacro(filename,error,check);
2909 // In case of error return the error code
2910 if (ret) return ret;
2911 // Append the macro name to the loaded macros list
2912 fgMacroNames += macroName;
2913 fgMacroNames += " ";
2914 return ret;
2915}
2916
2917//______________________________________________________________________________
2918void AliAnalysisManager::Lock()
2919{
2920// Security lock. This is to detect NORMAL user errors and not really to
2921// protect against intentional hacks.
2922 if (fLocked) return;
2923 fLocked = kTRUE;
2924 if (fInputEventHandler) fInputEventHandler->Lock();
2925 if (fOutputEventHandler) fOutputEventHandler->Lock();
2926 if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2927 Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2928}
2929
2930//______________________________________________________________________________
2931void AliAnalysisManager::UnLock()
2932{
2933// Verbose unlocking. Hackers will be punished ;-) ...
2934 if (!fLocked) return;
2935 fLocked = kFALSE;
2936 if (fInputEventHandler) fInputEventHandler->UnLock();
2937 if (fOutputEventHandler) fOutputEventHandler->UnLock();
2938 if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2939 Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2940}
2941
2942//______________________________________________________________________________
2943void AliAnalysisManager::Changed()
2944{
2945// All critical setters pass through the Changed method that throws an exception
2946// in case the lock was set.
2947 if (fLocked) Fatal("Changed","Critical setter called in locked mode");
2948}