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