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