]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
4db5d2b48f56f5734897d23442221981a2eee149
[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 void AliAnalysisManager::InputFileFromTree(TTree * const tree, TString &fname)
1694 {
1695 // Retrieves name of the file from tree
1696    fname = "";
1697    if (!tree) return;
1698    TFile *file = tree->GetCurrentFile();
1699    TString basename;
1700    if (!file) {
1701       TChain *chain = dynamic_cast<TChain*>(tree);
1702       if (!chain || !chain->GetNtrees()) return;
1703       basename = gSystem->BaseName(chain->GetListOfFiles()->First()->GetTitle());
1704    } else {   
1705       basename = gSystem->BaseName(file->GetName());
1706    }   
1707    Int_t index = basename.Index("#");
1708    fname = basename(index+1, basename.Length());
1709 }   
1710
1711 //______________________________________________________________________________
1712 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1713 {
1714 // Start analysis having a grid handler.
1715    if (!fGridHandler) {
1716       Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1717       Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1718       return -1;
1719    }
1720    TTree *tree = NULL;
1721    return StartAnalysis(type, tree, nentries, firstentry);
1722 }
1723
1724 //______________________________________________________________________________
1725 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1726 {
1727 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1728 // MIX. Process nentries starting from firstentry
1729    Long64_t retv = 0;
1730    // Backup current directory and make sure gDirectory points to gROOT
1731    TDirectory *cdir = gDirectory;
1732    gROOT->cd();
1733    if (!fInitOK) {
1734       Error("StartAnalysis","Analysis manager was not initialized !");
1735       if (cdir) cdir->cd();
1736       return -1;
1737    }
1738    if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1739    if (fDebug > 1) {
1740       printf("StartAnalysis %s\n",GetName());
1741       AliLog::SetGlobalLogLevel(AliLog::kInfo);
1742    }
1743    fMaxEntries = nentries;
1744    fIsRemote = kFALSE;
1745    TString anaType = type;
1746    anaType.ToLower();
1747    fMode = kLocalAnalysis;
1748    if (anaType.Contains("file"))      fIsRemote = kTRUE;
1749    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1750    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1751    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1752    if (fInputEventHandler) {
1753       TString fname;
1754       InputFileFromTree(tree, fname);
1755       if (fname.Length()) fInputEventHandler->SetInputFileName(fname);
1756    }
1757
1758    if (fMode == kGridAnalysis) {
1759       fIsRemote = kTRUE;
1760       if (!anaType.Contains("terminate")) {
1761          if (!fGridHandler) {
1762             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1763             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1764             if (cdir) cdir->cd();
1765             return -1;
1766          }
1767          // Write analysis manager in the analysis file
1768          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1769          // run local task configuration
1770          RunLocalInit();
1771          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1772             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1773             if (cdir) cdir->cd();
1774             return -1;
1775          }   
1776
1777          // Terminate grid analysis
1778          if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1779          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1780          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1781          if (!fGridHandler->MergeOutputs()) {
1782             // Return if outputs could not be merged or if it alien handler
1783             // was configured for offline mode or local testing.
1784             if (cdir) cdir->cd();
1785             return 0;
1786          }
1787       }   
1788       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1789       if (cdir) cdir->cd();
1790       ImportWrappers(NULL);
1791       Terminate();
1792       if (cdir) cdir->cd();
1793       return 0;
1794    }
1795    TString line;
1796    SetEventLoop(kFALSE);
1797    // Enable event loop mode if a tree was provided
1798    if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1799
1800    TChain *chain = 0;
1801    TString ttype = "TTree";
1802    if (tree && tree->IsA() == TChain::Class()) {
1803       chain = (TChain*)tree;
1804       if (!chain || !chain->GetListOfFiles()->First()) {
1805          Error("StartAnalysis", "Cannot process null or empty chain...");
1806          if (cdir) cdir->cd();
1807          return -1;
1808       }   
1809       ttype = "TChain";
1810    }   
1811
1812    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1813    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1814    // Initialize locally all tasks (happens for all modes)
1815    TIter next(fTasks);
1816    AliAnalysisTask *task;
1817    RunLocalInit();
1818    
1819    switch (fMode) {
1820       case kLocalAnalysis:
1821          if (!tree && !fGridHandler) {
1822             TIter nextT(fTasks);
1823             // Call CreateOutputObjects for all tasks
1824             Int_t itask = 0;
1825             Bool_t dirStatus = TH1::AddDirectoryStatus();
1826             while ((task=(AliAnalysisTask*)nextT())) {
1827                TH1::AddDirectory(kFALSE);
1828                task->CreateOutputObjects();
1829                if (!task->CheckPostData()) {
1830                   Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1831                         Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1832                         ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1833                }
1834                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1835                gROOT->cd();
1836                itask++;
1837             }   
1838             TH1::AddDirectory(dirStatus);
1839             if (IsExternalLoop()) {
1840                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1841                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1842                return 0;
1843             }
1844             ExecAnalysis();
1845             Terminate();
1846             return 0;
1847          } 
1848          fSelector = new AliAnalysisSelector(this);
1849          // Check if a plugin handler is used
1850          if (fGridHandler) {
1851             // Get the chain from the plugin
1852             TString dataType = "esdTree";
1853             if (fInputEventHandler) {
1854                dataType = fInputEventHandler->GetDataType();
1855                dataType.ToLower();
1856                dataType += "Tree";
1857             }   
1858             chain = fGridHandler->GetChainForTestMode(dataType);
1859             if (!chain) {
1860                Error("StartAnalysis", "No chain for test mode. Aborting.");
1861                return -1;
1862             }
1863             cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1864             retv = chain->Process(fSelector, "", nentries, firstentry);
1865             break;
1866          }
1867          // Run tree-based analysis via AliAnalysisSelector  
1868          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1869          retv = tree->Process(fSelector, "", nentries, firstentry);
1870          break;
1871       case kProofAnalysis:
1872          fIsRemote = kTRUE;
1873          // Check if the plugin is used
1874          if (fGridHandler) {
1875             return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1876          }
1877          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1878             Error("StartAnalysis", "No PROOF!!! Exiting.");
1879             if (cdir) cdir->cd();
1880             return -1;
1881          }   
1882          line = Form("gProof->AddInput((TObject*)%p);", this);
1883          gROOT->ProcessLine(line);
1884          if (chain) {
1885             chain->SetProof();
1886             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1887             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1888          } else {
1889             Error("StartAnalysis", "No chain!!! Exiting.");
1890             if (cdir) cdir->cd();
1891             return -1;
1892          }      
1893          break;
1894       case kGridAnalysis:
1895          fIsRemote = kTRUE;
1896          if (!anaType.Contains("terminate")) {
1897             if (!fGridHandler) {
1898                Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1899                Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1900                if (cdir) cdir->cd();
1901                return -1;
1902             }
1903             // Write analysis manager in the analysis file
1904             cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1905             // Start the analysis via the handler
1906             if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1907                Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1908                if (cdir) cdir->cd();
1909                return -1;
1910             }   
1911
1912             // Terminate grid analysis
1913             if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1914             if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1915             cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1916             if (!fGridHandler->MergeOutputs()) {
1917                // Return if outputs could not be merged or if it alien handler
1918                // was configured for offline mode or local testing.
1919                if (cdir) cdir->cd();
1920                return 0;
1921             }
1922          }   
1923          cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1924          ImportWrappers(NULL);
1925          Terminate();
1926          if (cdir) cdir->cd();
1927          return 0;
1928       case kMixingAnalysis:   
1929          // Run event mixing analysis
1930          if (!fEventPool) {
1931             Error("StartAnalysis", "Cannot run event mixing without event pool");
1932             if (cdir) cdir->cd();
1933             return -1;
1934          }
1935          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1936          fSelector = new AliAnalysisSelector(this);
1937          while ((chain=fEventPool->GetNextChain())) {
1938             next.Reset();
1939             // Call NotifyBinChange for all tasks
1940             while ((task=(AliAnalysisTask*)next()))
1941                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1942             retv = chain->Process(fSelector);
1943             if (retv < 0) {
1944                Error("StartAnalysis", "Mixing analysis failed");
1945                if (cdir) cdir->cd();
1946                return retv;
1947             }   
1948          }
1949          PackOutput(fSelector->GetOutputList());
1950          Terminate();
1951    }
1952    if (cdir) cdir->cd();
1953    return retv;
1954 }   
1955
1956 //______________________________________________________________________________
1957 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1958 {
1959 // Start analysis for this manager on a given dataset. Analysis task can be: 
1960 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1961    if (!fInitOK) {
1962       Error("StartAnalysis","Analysis manager was not initialized !");
1963       return -1;
1964    }
1965    fIsRemote = kTRUE;
1966    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1967    TString anaType = type;
1968    anaType.ToLower();
1969    if (!anaType.Contains("proof")) {
1970       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1971       return -1;
1972    }   
1973    fMode = kProofAnalysis;
1974    TString line;
1975    TString proofProcessOpt;
1976    SetEventLoop(kTRUE);
1977    // Set the dataset flag
1978    TObject::SetBit(kUseDataSet);
1979    fTree = 0;
1980    if (fGridHandler) {
1981       // Start proof analysis using the grid handler
1982       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1983          Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1984          return -1;
1985       }
1986       // Check if the plugin is in test mode
1987       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1988          dataset = "test_collection";
1989       } else {
1990          dataset = fGridHandler->GetProofDataSet();
1991       }
1992
1993       proofProcessOpt = fGridHandler->GetProofProcessOpt();
1994    }   
1995
1996    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1997       Error("StartAnalysis", "No PROOF!!! Exiting.");
1998       return -1;
1999    }   
2000
2001    // Initialize locally all tasks
2002    RunLocalInit();
2003       
2004    line = Form("gProof->AddInput((TObject*)%p);", this);
2005    gROOT->ProcessLine(line);
2006    Long_t retv;
2007    line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"%s\", %lld, %lld);",
2008                dataset,proofProcessOpt.Data(), nentries, firstentry);
2009    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
2010    retv = (Long_t)gROOT->ProcessLine(line);
2011    return retv;
2012 }   
2013
2014 //______________________________________________________________________________
2015 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
2016 {
2017 // Opens according the option the file specified by cont->GetFileName() and changes
2018 // current directory to cont->GetFolderName(). If the file was already opened, it
2019 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
2020 // be optionally ignored.
2021   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2022   TString filename = cont->GetFileName();
2023   TFile *f = NULL;
2024   if (filename.IsNull()) {
2025     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
2026     return NULL;
2027   }
2028   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
2029       && !ignoreProof)
2030     f = mgr->OpenProofFile(cont,option);
2031   else {
2032     // Check first if the file is already opened
2033     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2034     if (f) {
2035       // Check if option "UPDATE" was preserved 
2036       TString opt(option);
2037       opt.ToUpper();
2038       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
2039         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2040     } else {
2041       f = TFile::Open(filename, option);
2042     }    
2043   }   
2044   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2045     cont->SetFile(f);
2046     // Cd to file
2047     f->cd();
2048     // Check for a folder request
2049     TString dir = cont->GetFolderName(); 
2050     if (!dir.IsNull()) {
2051       if (!f->GetDirectory(dir)) f->mkdir(dir);
2052       f->cd(dir);
2053     }
2054     return f;
2055   }
2056   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
2057   cont->SetFile(NULL);
2058   return NULL;
2059 }    
2060  
2061 //______________________________________________________________________________
2062 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
2063 {
2064 // Opens a special output file used in PROOF.
2065   TString line;
2066   TString filename = cont->GetFileName();
2067   if (cont == fCommonOutput) {
2068      if (fOutputEventHandler) {
2069         if (strlen(extaod)) filename = extaod;
2070         filename = fOutputEventHandler->GetOutputFileName();
2071      }   
2072      else Fatal("OpenProofFile","No output container. Exiting.");
2073   }   
2074   TFile *f = NULL;
2075   if (fMode!=kProofAnalysis || !fSelector) {
2076     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
2077     return NULL;
2078   } 
2079   if (fSpecialOutputLocation.Length()) {
2080     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2081     if (f) {
2082       // Check if option "UPDATE" was preserved 
2083       TString opt(option);
2084       opt.ToUpper();
2085       if ((opt=="UPDATE") && (opt!=f->GetOption()))
2086         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
2087     } else {
2088       f = new TFile(filename, option);
2089     }
2090     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2091       cont->SetFile(f);
2092       // Cd to file
2093       f->cd();
2094       // Check for a folder request
2095       TString dir = cont->GetFolderName(); 
2096       if (dir.Length()) {
2097         if (!f->GetDirectory(dir)) f->mkdir(dir);
2098         f->cd(dir);
2099       }      
2100       return f;
2101     }
2102     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2103     cont->SetFile(NULL);
2104     return NULL;       
2105   }
2106   // Check if there is already a proof output file in the output list
2107   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
2108   if (pof) {
2109     // Get the actual file
2110     line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
2111     filename = (const char*)gROOT->ProcessLine(line);
2112     if (fDebug>1) {
2113       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
2114     }  
2115     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2116     if (!f) {
2117        Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
2118        return NULL;
2119     }   
2120     // Check if option "UPDATE" was preserved 
2121     TString opt(option);
2122     opt.ToUpper();
2123     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
2124       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
2125   } else {
2126     if (cont->IsRegisterDataset()) {
2127       TString dsetName = filename;
2128       dsetName.ReplaceAll(".root", cont->GetTitle());
2129       dsetName.ReplaceAll(":","_");
2130       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
2131       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
2132     } else {
2133       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
2134       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
2135     }
2136     if (fDebug > 1) printf("=== %s\n", line.Data());
2137     gROOT->ProcessLine(line);
2138     line = Form("pf->OpenFile(\"%s\");", option);
2139     gROOT->ProcessLine(line);
2140     f = gFile;
2141     if (fDebug > 1) {
2142       gROOT->ProcessLine("pf->Print()");
2143       printf(" == proof file name: %s", f->GetName());
2144     }   
2145     // Add to proof output list
2146     line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
2147     if (fDebug > 1) printf("=== %s\n", line.Data());
2148     gROOT->ProcessLine(line);
2149   }
2150   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
2151     cont->SetFile(f);
2152     // Cd to file
2153     f->cd();
2154     // Check for a folder request
2155     TString dir = cont->GetFolderName(); 
2156     if (!dir.IsNull()) {
2157       if (!f->GetDirectory(dir)) f->mkdir(dir);
2158       f->cd(dir);
2159     }
2160     return f;
2161   }
2162   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
2163   cont->SetFile(NULL);  
2164   return NULL;
2165 }   
2166
2167 //______________________________________________________________________________
2168 void AliAnalysisManager::ExecAnalysis(Option_t *option)
2169 {
2170 // Execute analysis.
2171    static Long64_t nentries = 0;
2172    static TTree *lastTree = 0;
2173    static TStopwatch *timer = new TStopwatch();
2174    // Only the first call to Process will trigger a true Notify. Other Notify
2175    // coming before is ignored.
2176    if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
2177       TObject::SetBit(AliAnalysisManager::kTrueNotify);
2178       Notify();
2179    }   
2180    if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2181    else {
2182       if (fTree && (fTree != lastTree)) {
2183          nentries += fTree->GetEntries();
2184          lastTree = fTree;
2185       }   
2186       if (!fNcalls) timer->Start();
2187       if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2188    }
2189    fIOTimer->Start(kTRUE);
2190    gROOT->cd();
2191    TDirectory *cdir = gDirectory;
2192    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2193    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2194    if (!fInitOK) {
2195       Error("ExecAnalysis", "Analysis manager was not initialized !");
2196       if (cdir) cdir->cd();
2197       return;
2198    }
2199    fNcalls++;
2200    AliAnalysisTask *task;
2201    // Check if the top tree is active.
2202    if (fTree) {
2203       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2204          AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2205       TIter next(fTasks);
2206    // De-activate all tasks
2207       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2208       AliAnalysisDataContainer *cont = fCommonInput;
2209       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2210       if (!cont) {
2211               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2212          if (cdir) cdir->cd();
2213          return;
2214       }   
2215       cont->SetData(fTree); // This will notify all consumers
2216       Long64_t entry = fTree->GetTree()->GetReadEntry();      
2217 //
2218 //    Call BeginEvent() for optional input/output and MC services 
2219       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
2220       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
2221       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2222       gROOT->cd();
2223       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2224          AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2225 //
2226 //    Execute the tasks
2227 //      TIter next1(cont->GetConsumers());
2228       fIOTimer->Stop();
2229       fIOTime += fIOTimer->RealTime();
2230       fCPUTimer->Start(kTRUE);
2231       TIter next1(fTopTasks);
2232       Int_t itask = 0;
2233       while ((task=(AliAnalysisTask*)next1())) {
2234          if (fDebug >1) {
2235             cout << "    Executing task " << task->GetName() << endl;
2236          }       
2237          task->ExecuteTask(option);
2238          gROOT->cd();
2239          if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2240             AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2241          itask++;   
2242       }
2243       fCPUTimer->Stop();
2244       fCPUTime += fCPUTimer->RealTime();
2245       fIOTimer->Start(kTRUE);
2246 //
2247 //    Call FinishEvent() for optional output and MC services 
2248       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2249       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2250       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2251       // Gather system information if requested
2252       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2253          AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2254       if (cdir) cdir->cd();   
2255       fIOTimer->Stop();
2256       fIOTime += fIOTimer->RealTime();
2257       return;
2258    }   
2259    // The event loop is not controlled by TSelector   
2260 //
2261 //  Call BeginEvent() for optional input/output and MC services 
2262    fIOTimer->Start(kTRUE);
2263    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
2264    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
2265    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2266    fIOTimer->Stop();
2267    fIOTime += fIOTimer->RealTime();
2268    gROOT->cd();
2269    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2270       AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2271    fCPUTimer->Start(kTRUE);
2272    TIter next2(fTopTasks);
2273    while ((task=(AliAnalysisTask*)next2())) {
2274       task->SetActive(kTRUE);
2275       if (fDebug > 1) {
2276          cout << "    Executing task " << task->GetName() << endl;
2277       }   
2278       task->ExecuteTask(option);
2279       gROOT->cd();
2280    }   
2281    fCPUTimer->Stop();
2282    fCPUTime += fCPUTimer->RealTime();
2283 //
2284 // Call FinishEvent() for optional output and MC services 
2285    fIOTimer->Start(kTRUE);
2286    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2287    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2288    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2289    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2290       AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2291    if (cdir) cdir->cd();   
2292    fIOTimer->Stop();
2293    fIOTime += fIOTimer->RealTime();
2294 }
2295
2296 //______________________________________________________________________________
2297 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2298 {
2299 // Check if the stdout is connected to a pipe (C.Holm)
2300   Bool_t ispipe = kFALSE;
2301   out.seekp(0, std::ios_base::cur);
2302   if (out.fail()) {
2303     out.clear();
2304     if (errno == ESPIPE) ispipe = kTRUE;
2305   }
2306   return ispipe;
2307 }
2308    
2309 //______________________________________________________________________________
2310 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2311 {
2312 // Set the input event handler and create a container for it.
2313    Changed();
2314    fInputEventHandler   = handler;
2315    if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2316 }
2317
2318 //______________________________________________________________________________
2319 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2320 {
2321 // Set the input event handler and create a container for it.
2322    Changed();
2323    fOutputEventHandler   = handler;
2324    if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2325    fCommonOutput->SetSpecialOutput();
2326 }
2327
2328 //______________________________________________________________________________
2329 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2330 {
2331 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2332    if (TObject::TestBit(kUseProgressBar)) {
2333       Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2334       return;
2335    }
2336    fDebug = level;
2337 }
2338    
2339 //______________________________________________________________________________
2340 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2341 {
2342 // Enable a text mode progress bar. Resets debug level to 0.
2343    Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n  ### NOTE: Debug level reset to 0 ###", freq);
2344    TObject::SetBit(kUseProgressBar,flag);
2345    fPBUpdateFreq = freq;
2346    fDebug = 0;
2347 }   
2348
2349 //______________________________________________________________________________
2350 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2351 {
2352 // This method is used externally to register output files which are not
2353 // connected to any output container, so that the manager can properly register,
2354 // retrieve or merge them when running in distributed mode. The file names are
2355 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2356    if (fExtraFiles.Contains(fname)) return;
2357    if (fExtraFiles.Length()) fExtraFiles += " ";
2358    fExtraFiles += fname;
2359 }
2360
2361 //______________________________________________________________________________
2362 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2363 {
2364 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2365    char fullPath[512];
2366    char chUrl[512];
2367    char tmp[1024];
2368    TObject *pof =  source->FindObject(filename);
2369    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2370       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2371       return kFALSE;
2372    }
2373    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2374    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2375    TString clientUrl(chUrl);
2376    TString fullPath_str(fullPath);
2377    if (clientUrl.Contains("localhost")){
2378       TObjArray* array = fullPath_str.Tokenize ( "//" );
2379       TObjString *strobj = ( TObjString *)array->At(1);
2380       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2381       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2382       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2383       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2384       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2385       delete arrayPort;
2386       delete array;
2387    }
2388    else if (clientUrl.Contains("__lite__")) { 
2389      // Special case for ProofLite environement - get file info and copy. 
2390      gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2391      fullPath_str = Form("%s/%s", tmp, fullPath);
2392    }
2393    if (fDebug > 1) 
2394      Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2395    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
2396    if (!gotit)
2397       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2398    return gotit;
2399 }
2400
2401 //______________________________________________________________________________
2402 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2403 {
2404 // Fill analysis type in the provided string.
2405    switch (fMode) {
2406       case kLocalAnalysis:
2407          type = "local";
2408          return;
2409       case kProofAnalysis:
2410          type = "proof";
2411          return;
2412       case kGridAnalysis:
2413          type = "grid";
2414          return;
2415       case kMixingAnalysis:
2416          type = "mix";
2417    }
2418 }
2419
2420 //______________________________________________________________________________
2421 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2422 {
2423 // Validate all output files.
2424    TIter next(fOutputs);
2425    AliAnalysisDataContainer *output;
2426    TDirectory *cdir = gDirectory;
2427    TString openedFiles;
2428    while ((output=(AliAnalysisDataContainer*)next())) {
2429       if (output->IsRegisterDataset()) continue;
2430       TString filename = output->GetFileName();
2431       if (filename == "default") {
2432          if (!fOutputEventHandler) continue;
2433          filename = fOutputEventHandler->GetOutputFileName();
2434          // Main AOD may not be there
2435          if (gSystem->AccessPathName(filename)) continue;
2436       }
2437       // Check if the file is closed
2438       if (openedFiles.Contains(filename)) continue;;
2439       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2440       if (file) {
2441          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2442          // Clear file list to release object ownership to user.
2443 //         file->Clear();
2444          file->Close();
2445       }
2446       file = TFile::Open(filename);
2447       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2448          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2449          if (cdir) cdir->cd();
2450          return kFALSE;
2451       }
2452       file->Close();
2453       openedFiles += filename;
2454       openedFiles += " ";
2455    }
2456    if (cdir) cdir->cd();
2457    return kTRUE;
2458 }   
2459
2460 //______________________________________________________________________________
2461 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2462 {
2463 // Implements a nice text mode progress bar.
2464    static Long64_t icount = 0;
2465    static TString oname;
2466    static TString nname;
2467    static Long64_t ocurrent = 0;
2468    static Long64_t osize = 0;
2469    static Int_t oseconds = 0;
2470    static TStopwatch *owatch = 0;
2471    static Bool_t oneoftwo = kFALSE;
2472    static Int_t nrefresh = 0;
2473    static Int_t nchecks = 0;
2474    static char lastChar = 0;
2475    const char symbol[4] = {'-','\\','|','/'}; 
2476    
2477    if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2478    if (!refresh) {
2479       nrefresh = 0;
2480       if (!size) return;
2481       owatch = watch;
2482       oname = opname;
2483       ocurrent = TMath::Abs(current);
2484       osize = TMath::Abs(size);
2485       if (ocurrent > osize) ocurrent=osize;
2486    } else {
2487       nrefresh++;
2488       if (!osize) return;
2489    }     
2490    if ((current % fPBUpdateFreq) != 0) return;
2491    icount++;
2492    char progress[11] = "          ";
2493    Int_t ichar = icount%4;
2494    Double_t time = 0.;
2495    Int_t hours = 0;
2496    Int_t minutes = 0;
2497    Int_t seconds = 0;
2498    if (owatch && !last) {
2499       owatch->Stop();
2500       time = owatch->RealTime();
2501       seconds   = int(time) % 60;
2502       minutes   = (int(time) / 60) % 60;
2503       hours     = (int(time) / 60 / 60);
2504       if (refresh)  {
2505          if (oseconds==seconds) {
2506             owatch->Continue();
2507             return;
2508          }
2509          oneoftwo = !oneoftwo;   
2510       }
2511       oseconds = seconds;   
2512    }
2513    if (refresh && oneoftwo) {
2514       nname = oname;
2515       if (nchecks <= 0) nchecks = nrefresh+1;
2516       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2517       oname = Form("     == %d%% ==", pctdone);
2518    }         
2519    Double_t percent = 100.0*ocurrent/osize;
2520    Int_t nchar = Int_t(percent/10);
2521    if (nchar>10) nchar=10;
2522    Int_t i;
2523    for (i=0; i<nchar; i++)  progress[i] = '=';
2524    progress[nchar] = symbol[ichar];
2525    for (i=nchar+1; i<10; i++) progress[i] = ' ';
2526    progress[10] = '\0';
2527    oname += "                    ";
2528    oname.Remove(20);
2529    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2530    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2531    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2532    if (time>0.) {
2533      Int_t full   = Int_t(ocurrent > 0 ? 
2534                           time * (float(osize)/ocurrent) + .5 : 
2535                           99*3600+59*60+59); 
2536      Int_t remain = Int_t(full - time);
2537      Int_t rsec   = remain % 60;
2538      Int_t rmin   = (remain / 60) % 60;
2539      Int_t rhour  = (remain / 60 / 60);
2540      fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d  ETA %.2d:%.2d:%.2d%c",
2541              percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2542    }
2543    else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2544    if (refresh && oneoftwo) oname = nname;
2545    if (owatch) owatch->Continue();
2546    if (last) {
2547       icount = 0;
2548       owatch = 0;
2549       ocurrent = 0;
2550       osize = 0;
2551       oseconds = 0;
2552       oneoftwo = kFALSE;
2553       nrefresh = 0;
2554       fprintf(stderr, "\n");
2555    }   
2556 }
2557
2558 //______________________________________________________________________________
2559 void AliAnalysisManager::DoLoadBranch(const char *name) 
2560 {
2561   // Get tree and load branch if needed.
2562   static Long64_t crtEntry = -100;
2563
2564   if (fAutoBranchHandling || !fTree)
2565     return;
2566
2567   TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2568   if (!br) {
2569     br = fTree->GetBranch(name);
2570     if (!br) {
2571       Error("DoLoadBranch", "Could not find branch %s",name);
2572       return;
2573     }
2574     fTable.Add(br);
2575   }
2576   if (br->GetReadEntry()==fCurrentEntry) return;
2577   Long64_t readbytes = br->GetEntry(GetCurrentEntry());
2578   if (readbytes<0) {
2579     Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2580     if (crtEntry != fCurrentEntry) {
2581       CountEvent(1,0,1,0);
2582       crtEntry = fCurrentEntry;
2583     }  
2584   } else {
2585     if (crtEntry != fCurrentEntry) {
2586       CountEvent(1,1,0,0);
2587       crtEntry = fCurrentEntry;
2588     }
2589   }
2590 }
2591
2592 //______________________________________________________________________________
2593 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2594 {
2595 // Add the statistics task to the manager.
2596   if (fStatistics) {
2597      Info("AddStatisticsTask", "Already added");
2598      return;
2599   }
2600   TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2601   gROOT->ProcessLine(line);
2602 }  
2603
2604 //______________________________________________________________________________
2605 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2606 {
2607 // Bookkeep current event;
2608    if (!fStatistics) return;
2609    fStatistics->AddInput(ninput);
2610    fStatistics->AddProcessed(nprocessed);
2611    fStatistics->AddFailed(nfailed);
2612    fStatistics->AddAccepted(naccepted);
2613 }   
2614
2615 //______________________________________________________________________________
2616 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2617 {
2618 // Add a line in the statistics message. If available, the statistics message is written
2619 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2620 // on the client.
2621    if (!strlen(line)) return;
2622    if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2623    fStatisticsMsg += line;
2624 }
2625
2626 //______________________________________________________________________________
2627 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2628 {
2629 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2630    static Bool_t done = kFALSE;
2631    if (done) return;
2632    done = kTRUE;
2633    if (!fStatistics) return;
2634    ofstream out;
2635    AddStatisticsMsg(Form("Number of input events:        %lld",fStatistics->GetNinput()));
2636    AddStatisticsMsg(Form("Number of processed events:    %lld",fStatistics->GetNprocessed()));      
2637    AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2638    AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2639    out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2640                  fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2641                  fStatistics->GetNaccepted()), ios::out);      
2642    out << fStatisticsMsg << endl;
2643    out.close();
2644 }
2645
2646 //______________________________________________________________________________
2647 const char* AliAnalysisManager::GetOADBPath()
2648 {
2649 // returns the path of the OADB
2650 // this static function just depends on environment variables
2651
2652    static TString oadbPath;
2653
2654    if (gSystem->Getenv("OADB_PATH"))
2655       oadbPath = gSystem->Getenv("OADB_PATH");
2656    else if (gSystem->Getenv("ALICE_ROOT"))
2657       oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2658    else
2659       ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2660       
2661    return oadbPath;
2662 }
2663
2664 //______________________________________________________________________________
2665 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2666 {
2667 // Define a custom string variable mapped to a global unique name. The variable
2668 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2669    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2670    if (!mgr) {
2671       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2672       return;
2673    }   
2674    Bool_t valid = kFALSE;
2675    TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2676    if (valid) {
2677       ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2678       return;
2679    }
2680    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2681 }
2682
2683 //______________________________________________________________________________
2684 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2685 {
2686 // Static method to retrieve a global variable defined via SetGlobalStr.
2687    valid = kFALSE;
2688    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2689    if (!mgr) return 0;
2690    TObject *value = mgr->GetGlobals()->GetValue(key);
2691    if (!value) return 0;
2692    valid = kTRUE;
2693    return value->GetName();
2694 }
2695
2696 //______________________________________________________________________________
2697 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2698 {
2699 // Define a custom integer variable mapped to a global unique name. The variable
2700 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2701    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2702    if (!mgr) {
2703       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2704       return;
2705    }   
2706    Bool_t valid = kFALSE;
2707    Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2708    if (valid) {
2709       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2710       return;
2711    }
2712    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2713 }
2714
2715 //______________________________________________________________________________
2716 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2717 {
2718 // Static method to retrieve a global variable defined via SetGlobalInt.
2719    valid = kFALSE;
2720    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2721    if (!mgr) return 0;
2722    TObject *value = mgr->GetGlobals()->GetValue(key);
2723    if (!value) return 0;
2724    valid = kTRUE;
2725    TString s = value->GetName();
2726    return s.Atoi();
2727 }
2728
2729 //______________________________________________________________________________
2730 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2731 {
2732 // Define a custom double precision variable mapped to a global unique name. The variable
2733 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2734    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2735    if (!mgr) {
2736       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2737       return;
2738    }   
2739    Bool_t valid = kFALSE;
2740    Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2741    if (valid) {
2742       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2743       return;
2744    }
2745    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2746 }
2747
2748 //______________________________________________________________________________
2749 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2750 {
2751 // Static method to retrieve a global variable defined via SetGlobalDbl.
2752    valid = kFALSE;
2753    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2754    if (!mgr) return 0;
2755    TObject *value = mgr->GetGlobals()->GetValue(key);
2756    if (!value) return 0;
2757    valid = kTRUE;
2758    TString s = value->GetName();
2759    return s.Atof();
2760 }
2761
2762 //______________________________________________________________________________
2763 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2764 {
2765 // Sets Class debug level
2766
2767    if (!fDebugOptions) {
2768       fDebugOptions = new TObjArray();
2769       fDebugOptions->SetOwner(kTRUE);
2770    }
2771
2772    TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2773    if (!debugOpt) {
2774      AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel,className).Data());
2775      fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2776    } else {
2777       TString oldDebugStr = debugOpt->GetTitle();
2778       Int_t oldDebug = oldDebugStr.Atoi();
2779       if (debugLevel > oldDebug) {
2780          AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel,className,oldDebug).Data());
2781          debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2782       } else {
2783          AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel,className,oldDebug).Data());
2784       }
2785    }
2786 }
2787
2788 //______________________________________________________________________________
2789 void AliAnalysisManager::ApplyDebugOptions()
2790 {
2791 // Apply debug options
2792
2793    if (!fDebugOptions) return;
2794    
2795    TIter next(fDebugOptions);
2796    TNamed *debug;
2797    TString debugLevel;
2798    while ((debug=dynamic_cast<TNamed*>(next()))) {
2799       debugLevel = debug->GetTitle();
2800       AliInfo(TString::Format("Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()).Data());
2801       AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2802    }
2803 }
2804
2805 //______________________________________________________________________________
2806 Bool_t AliAnalysisManager::IsMacroLoaded(const char filename)
2807 {
2808 // Check if a macro was loaded.
2809    return fgMacroNames.Contains(filename);
2810 }
2811    
2812 //______________________________________________________________________________
2813 Int_t AliAnalysisManager::LoadMacro(const char *filename, Int_t *error, Bool_t check)
2814 {
2815 // Redirection of gROOT->LoadMacro which makes sure the same macro is not loaded 
2816 // twice
2817    TString macroName = gSystem->BaseName(filename);
2818    // Strip appended +, ++, +g, +O
2819    Int_t index = macroName.Index("+");
2820    if (index>0) macroName.Remove(index);
2821    if (fgMacroNames.Contains(macroName)) {
2822       // Macro with the same name loaded already in this root session, do 
2823       // nothing
2824       error = 0;
2825       return 0;
2826    }
2827    Int_t ret = gROOT->LoadMacro(filename,error,check);
2828    // In case of error return the error code
2829    if (ret) return ret;
2830    // Append the macro name to the loaded macros list
2831    fgMacroNames += macroName;
2832    fgMacroNames += " ";
2833    return ret;
2834 }   
2835
2836 //______________________________________________________________________________
2837 void AliAnalysisManager::Lock()
2838 {
2839 // Security lock. This is to detect NORMAL user errors and not really to
2840 // protect against intentional hacks.
2841    if (fLocked) return;
2842    fLocked = kTRUE;
2843    if (fInputEventHandler)  fInputEventHandler->Lock();
2844    if (fOutputEventHandler) fOutputEventHandler->Lock();
2845    if (fMCtruthEventHandler) fMCtruthEventHandler->Lock();
2846    Info("Lock","====== ANALYSIS MANAGER LOCKED ======");
2847 }
2848
2849 //______________________________________________________________________________
2850 void AliAnalysisManager::UnLock()
2851 {
2852 // Verbose unlocking. Hackers will be punished ;-) ... 
2853    if (!fLocked) return;
2854    fLocked = kFALSE;
2855    if (fInputEventHandler)  fInputEventHandler->UnLock();
2856    if (fOutputEventHandler) fOutputEventHandler->UnLock();
2857    if (fMCtruthEventHandler) fMCtruthEventHandler->UnLock();
2858    Info("UnLock", "====== ANALYSIS MANAGER UNLOCKED ======");
2859 }
2860
2861 //______________________________________________________________________________
2862 void AliAnalysisManager::Changed()
2863 {
2864 // All critical setters pass through the Changed method that throws an exception 
2865 // in case the lock was set.
2866    if (fLocked) Fatal("Changed","Critical setter called in locked mode");
2867 }