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