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