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