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