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