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