Trees should write now to the current directory
[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 //   AliAnalysysManager - 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 <Riostream.h>
29
30 #include <TError.h>
31 #include <TClass.h>
32 #include <TFile.h>
33 //#include <TKey.h>
34 #include <TMath.h>
35 #include <TH1.h>
36 #include <TMethodCall.h>
37 #include <TChain.h>
38 #include <TSystem.h>
39 #include <TROOT.h>
40 #include <TCanvas.h>
41 #include <TStopwatch.h>
42
43 #include "AliAnalysisSelector.h"
44 #include "AliAnalysisGrid.h"
45 #include "AliAnalysisTask.h"
46 #include "AliAnalysisDataContainer.h"
47 #include "AliAnalysisDataSlot.h"
48 #include "AliVEventHandler.h"
49 #include "AliVEventPool.h"
50 #include "AliSysInfo.h"
51 #include "AliAnalysisManager.h"
52
53 ClassImp(AliAnalysisManager)
54
55 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
56 TString AliAnalysisManager::fgCommonFileName = "";
57
58 //______________________________________________________________________________
59 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
60                    :TNamed(name,title),
61                     fTree(NULL),
62                     fInputEventHandler(NULL),
63                     fOutputEventHandler(NULL),
64                     fMCtruthEventHandler(NULL),
65                     fEventPool(NULL),
66                     fCurrentEntry(-1),
67                     fNSysInfo(0),
68                     fMode(kLocalAnalysis),
69                     fInitOK(kFALSE),
70                     fDebug(0),
71                     fSpecialOutputLocation(""), 
72                     fTasks(NULL),
73                     fTopTasks(NULL),
74                     fZombies(NULL),
75                     fContainers(NULL),
76                     fInputs(NULL),
77                     fOutputs(NULL),
78                     fParamCont(NULL),
79                     fCommonInput(NULL),
80                     fCommonOutput(NULL),
81                     fSelector(NULL),
82                     fGridHandler(NULL),
83                     fExtraFiles("")
84 {
85 // Default constructor.
86    fgAnalysisManager = this;
87    fgCommonFileName  = "AnalysisResults.root";
88    fTasks      = new TObjArray();
89    fTopTasks   = new TObjArray();
90    fZombies    = new TObjArray();
91    fContainers = new TObjArray();
92    fInputs     = new TObjArray();
93    fOutputs    = new TObjArray();
94    fParamCont  = new TObjArray();
95    SetEventLoop(kTRUE);
96    TObject::SetObjectStat(kFALSE);
97 }
98
99 //______________________________________________________________________________
100 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
101                    :TNamed(other),
102                     fTree(NULL),
103                     fInputEventHandler(NULL),
104                     fOutputEventHandler(NULL),
105                     fMCtruthEventHandler(NULL),
106                     fEventPool(NULL),
107                     fCurrentEntry(-1),
108                     fNSysInfo(0),
109                     fMode(other.fMode),
110                     fInitOK(other.fInitOK),
111                     fDebug(other.fDebug),
112                     fSpecialOutputLocation(""), 
113                     fTasks(NULL),
114                     fTopTasks(NULL),
115                     fZombies(NULL),
116                     fContainers(NULL),
117                     fInputs(NULL),
118                     fOutputs(NULL),
119                     fParamCont(NULL),
120                     fCommonInput(NULL),
121                     fCommonOutput(NULL),
122                     fSelector(NULL),
123                     fGridHandler(NULL),
124                     fExtraFiles()
125 {
126 // Copy constructor.
127    fTasks      = new TObjArray(*other.fTasks);
128    fTopTasks   = new TObjArray(*other.fTopTasks);
129    fZombies    = new TObjArray(*other.fZombies);
130    fContainers = new TObjArray(*other.fContainers);
131    fInputs     = new TObjArray(*other.fInputs);
132    fOutputs    = new TObjArray(*other.fOutputs);
133    fParamCont  = new TObjArray(*other.fParamCont);
134    fgCommonFileName  = "AnalysisResults.root";
135    fgAnalysisManager = this;
136    TObject::SetObjectStat(kFALSE);
137 }
138    
139 //______________________________________________________________________________
140 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
141 {
142 // Assignment
143    if (&other != this) {
144       TNamed::operator=(other);
145       fInputEventHandler   = other.fInputEventHandler;
146       fOutputEventHandler  = other.fOutputEventHandler;
147       fMCtruthEventHandler = other.fMCtruthEventHandler;
148       fEventPool           = other.fEventPool;
149       fTree       = NULL;
150       fCurrentEntry = -1;
151       fNSysInfo   = other.fNSysInfo;
152       fMode       = other.fMode;
153       fInitOK     = other.fInitOK;
154       fDebug      = other.fDebug;
155       fTasks      = new TObjArray(*other.fTasks);
156       fTopTasks   = new TObjArray(*other.fTopTasks);
157       fZombies    = new TObjArray(*other.fZombies);
158       fContainers = new TObjArray(*other.fContainers);
159       fInputs     = new TObjArray(*other.fInputs);
160       fOutputs    = new TObjArray(*other.fOutputs);
161       fParamCont  = new TObjArray(*other.fParamCont);
162       fCommonInput = NULL;
163       fCommonOutput = NULL;
164       fSelector   = NULL;
165       fGridHandler = NULL;
166       fExtraFiles = other.fExtraFiles;
167       fgCommonFileName = "AnalysisResults.root";
168       fgAnalysisManager = this;
169    }
170    return *this;
171 }
172
173 //______________________________________________________________________________
174 AliAnalysisManager::~AliAnalysisManager()
175 {
176 // Destructor.
177    if (fTasks) {fTasks->Delete(); delete fTasks;}
178    if (fTopTasks) delete fTopTasks;
179    if (fZombies) delete fZombies;
180    if (fContainers) {fContainers->Delete(); delete fContainers;}
181    if (fInputs) delete fInputs;
182    if (fOutputs) delete fOutputs;
183    if (fParamCont) delete fParamCont;
184    if (fGridHandler) delete fGridHandler;
185    if (fInputEventHandler) delete fInputEventHandler;
186    if (fOutputEventHandler) delete fOutputEventHandler;
187    if (fMCtruthEventHandler) delete fMCtruthEventHandler;
188    if (fEventPool) delete fEventPool;
189    if (fgAnalysisManager==this) fgAnalysisManager = NULL;
190    TObject::SetObjectStat(kTRUE);
191 }
192
193 //______________________________________________________________________________
194 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
195 {
196 // Read one entry of the tree or a whole branch.
197    fCurrentEntry = entry;
198    return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
199 }
200    
201 //______________________________________________________________________________
202 Bool_t AliAnalysisManager::Init(TTree *tree)
203 {
204   // The Init() function is called when the selector needs to initialize
205   // a new tree or chain. Typically here the branch addresses of the tree
206   // will be set. It is normaly not necessary to make changes to the
207   // generated code, but the routine can be extended by the user if needed.
208   // Init() will be called many times when running with PROOF.
209    Bool_t init = kFALSE;
210    if (!tree) return kFALSE; // Should not happen - protected in selector caller
211    if (fDebug > 0) {
212       printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
213    }
214    // Call InitTree of EventHandler
215    if (fOutputEventHandler) {
216       if (fMode == kProofAnalysis) {
217          init = fOutputEventHandler->Init(0x0, "proof");
218       } else {
219          init = fOutputEventHandler->Init(0x0, "local");
220       }
221       if (!init) {
222          Error("Init", "Output event handler failed to initialize");
223          return kFALSE;
224       }         
225    }
226    
227    if (fInputEventHandler) {
228       if (fMode == kProofAnalysis) {
229          init = fInputEventHandler->Init(tree, "proof");
230       } else {
231          init = fInputEventHandler->Init(tree, "local");
232       }
233       if (!init) {
234          Error("Init", "Input event handler failed to initialize tree"); 
235          return kFALSE;
236       }         
237    } else {
238       // If no input event handler we need to get the tree once
239       // for the chain
240       if(!tree->GetTree()) {
241          Long64_t readEntry = tree->LoadTree(0);
242          if (readEntry == -2) {
243             Error("Init", "Input tree has no entry. Exiting");
244             return kFALSE;
245          }
246       }   
247    }
248
249    if (fMCtruthEventHandler) {
250       if (fMode == kProofAnalysis) {
251          init = fMCtruthEventHandler->Init(0x0, "proof");
252       } else {
253          init = fMCtruthEventHandler->Init(0x0, "local");
254       }
255       if (!init) {
256          Error("Init", "MC event handler failed to initialize"); 
257          return kFALSE;
258       }         
259    }
260
261    if (!fInitOK) InitAnalysis();
262    if (!fInitOK) return kFALSE;
263    fTree = tree;
264    AliAnalysisDataContainer *top = fCommonInput;
265    if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
266    if (!top) {
267       Error("Init","No top input container !");
268       return kFALSE;
269    }
270    top->SetData(tree);
271    if (fDebug > 0) {
272       printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
273    }
274    return kTRUE;
275 }
276
277 //______________________________________________________________________________
278 void AliAnalysisManager::SlaveBegin(TTree *tree)
279 {
280   // The SlaveBegin() function is called after the Begin() function.
281   // When running with PROOF SlaveBegin() is called on each slave server.
282   // The tree argument is deprecated (on PROOF 0 is passed).
283    if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
284    static Bool_t isCalled = kFALSE;
285    Bool_t init = kFALSE;
286    Bool_t initOK = kTRUE;
287    TString msg;
288    TDirectory *curdir = gDirectory;
289    // Call SlaveBegin only once in case of mixing
290    if (isCalled && fMode==kMixingAnalysis) return;
291    // Call Init of EventHandler
292    if (fOutputEventHandler) {
293       if (fMode == kProofAnalysis) {
294          // Merging AOD's in PROOF via TProofOutputFile
295          if (fDebug > 1) printf("   Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
296          init = fOutputEventHandler->Init("proof");
297          if (!init) msg = "Failed to initialize output handler on worker";
298       } else {
299          init = fOutputEventHandler->Init("local");
300          if (!init) msg = "Failed to initialize output handler";
301       }
302       initOK &= init;
303       if (!fSelector) Error("SlaveBegin", "Selector not set");
304       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
305    }
306
307    if (fInputEventHandler) {
308       fInputEventHandler->SetInputTree(tree);
309       if (fMode == kProofAnalysis) {
310          init = fInputEventHandler->Init("proof");
311          if (!init) msg = "Failed to initialize input handler on worker";
312       } else {
313          init = fInputEventHandler->Init("local");
314          if (!init) msg = "Failed to initialize input handler";
315       }
316       initOK &= init;
317       if (!fSelector) Error("SlaveBegin", "Selector not set");      
318       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
319    }
320
321    if (fMCtruthEventHandler) {
322       if (fMode == kProofAnalysis) {
323          init = fMCtruthEventHandler->Init("proof");
324          if (!init) msg = "Failed to initialize MC handler on worker";
325       } else {
326          init = fMCtruthEventHandler->Init("local");
327          if (!init) msg = "Failed to initialize MC handler";
328       }
329       initOK &= init;
330       if (!fSelector) Error("SlaveBegin", "Selector not set");      
331       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
332    }
333    if (curdir) curdir->cd();
334    isCalled = kTRUE;
335    if (!initOK) return;   
336    TIter next(fTasks);
337    AliAnalysisTask *task;
338    // Call CreateOutputObjects for all tasks
339    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
340    Int_t itask = 0;
341    while ((task=(AliAnalysisTask*)next())) {
342       curdir = gDirectory;
343       task->CreateOutputObjects();
344       if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
345       itask++;
346       if (curdir) curdir->cd();
347    }
348    if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
349 }
350
351 //______________________________________________________________________________
352 Bool_t AliAnalysisManager::Notify()
353 {
354    // The Notify() function is called when a new file is opened. This
355    // can be either for a new TTree in a TChain or when when a new TTree
356    // is started when using PROOF. It is normaly not necessary to make changes
357    // to the generated code, but the routine can be extended by the
358    // user if needed. The return value is currently not used.
359    if (!fTree) return kFALSE;
360
361    TFile *curfile = fTree->GetCurrentFile();
362    if (!curfile) {
363       Error("Notify","No current file");
364       return kFALSE;
365    }   
366    
367    if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
368    TIter next(fTasks);
369    AliAnalysisTask *task;
370    // Call Notify for all tasks
371    while ((task=(AliAnalysisTask*)next())) 
372       task->Notify();
373         
374    // Call Notify of the event handlers
375    if (fInputEventHandler) {
376        fInputEventHandler->Notify(curfile->GetName());
377    }
378
379    if (fOutputEventHandler) {
380        fOutputEventHandler->Notify(curfile->GetName());
381    }
382
383    if (fMCtruthEventHandler) {
384        fMCtruthEventHandler->Notify(curfile->GetName());
385    }
386    if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
387    return kTRUE;
388 }    
389
390 //______________________________________________________________________________
391 Bool_t AliAnalysisManager::Process(Long64_t entry)
392 {
393   // The Process() function is called for each entry in the tree (or possibly
394   // keyed object in the case of PROOF) to be processed. The entry argument
395   // specifies which entry in the currently loaded tree is to be processed.
396   // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
397   // to read either all or the required parts of the data. When processing
398   // keyed objects with PROOF, the object is already loaded and is available
399   // via the fObject pointer.
400   //
401   // This function should contain the "body" of the analysis. It can contain
402   // simple or elaborate selection criteria, run algorithms on the data
403   // of the event and typically fill histograms.
404
405   // WARNING when a selector is used with a TChain, you must use
406   //  the pointer to the current TTree to call GetEntry(entry).
407   //  The entry is always the local entry number in the current tree.
408   //  Assuming that fChain is the pointer to the TChain being processed,
409   //  use fChain->GetTree()->GetEntry(entry).
410    if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
411
412    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
413    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
414    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
415    
416    GetEntry(entry);
417    ExecAnalysis();
418    if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
419    return kTRUE;
420 }
421
422 //______________________________________________________________________________
423 void AliAnalysisManager::PackOutput(TList *target)
424 {
425   // Pack all output data containers in the output list. Called at SlaveTerminate
426   // stage in PROOF case for each slave.
427    if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
428    if (!target) {
429       Error("PackOutput", "No target. Exiting.");
430       return;
431    }
432    TDirectory *cdir = gDirectory;
433    gROOT->cd();
434    if (fInputEventHandler)   fInputEventHandler  ->Terminate();
435    if (fOutputEventHandler)  fOutputEventHandler ->Terminate();
436    if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
437    gROOT->cd();
438
439    // Call FinishTaskOutput() for each event loop task (not called for 
440    // post-event loop tasks - use Terminate() fo those)
441    TIter nexttask(fTasks);
442    AliAnalysisTask *task;
443    while ((task=(AliAnalysisTask*)nexttask())) {
444       if (!task->IsPostEventLoop()) {
445          if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
446          task->FinishTaskOutput();
447          gROOT->cd();
448          if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
449       }
450    }      
451    
452    if (fMode == kProofAnalysis) {
453       TIter next(fOutputs);
454       AliAnalysisDataContainer *output;
455       Bool_t isManagedByHandler = kFALSE;
456       while ((output=(AliAnalysisDataContainer*)next())) {
457          // Do not consider outputs of post event loop tasks
458          isManagedByHandler = kFALSE;
459          if (output->GetProducer()->IsPostEventLoop()) continue;
460          const char *filename = output->GetFileName();
461          if (!(strcmp(filename, "default")) && fOutputEventHandler) {
462             isManagedByHandler = kTRUE;
463             printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
464             filename = fOutputEventHandler->GetOutputFileName();
465          }
466          // Check if data was posted to this container. If not, issue an error.
467          if (!output->GetData() && !isManagedByHandler) {
468             Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
469             continue;
470          }   
471          if (!output->IsSpecialOutput()) {
472             // Normal outputs
473             if (strlen(filename) && !isManagedByHandler) {
474                // Backup current folder
475                TDirectory *opwd = gDirectory;
476                // File resident outputs. 
477                // Check first if the file exists.
478                TString openoption = "RECREATE";
479                if (!gSystem->AccessPathName(output->GetFileName())) openoption = "UPDATE";
480                TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
481                // Save data to file, then close.
482                if (output->GetData()->InheritsFrom(TCollection::Class())) {
483                   // If data is a collection, we set the name of the collection 
484                   // as the one of the container and we save as a single key.
485                   TCollection *coll = (TCollection*)output->GetData();
486                   coll->SetName(output->GetName());
487                   coll->Write(output->GetName(), TObject::kSingleKey);
488                } else {
489                   if (output->GetData()->InheritsFrom(TTree::Class())) {
490                      TTree *tree = (TTree*)output->GetData();
491                      // Check if tree is in memory
492                      if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
493                      tree->AutoSave();
494                   } else {
495                      output->GetData()->Write();
496                   }   
497                }      
498                if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
499                if (fDebug > 2) {
500                   printf("   file %s listing content:\n", filename);
501                   file->ls();
502                }   
503                // Clear file list to release object ownership to user.
504 //               file->Clear();
505                file->Close();
506                output->SetFile(NULL);
507                // Restore current directory
508                if (opwd) opwd->cd();
509             } else {
510                // Memory-resident outputs   
511                if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
512             }   
513             AliAnalysisDataWrapper *wrap = 0;
514             if (isManagedByHandler) {
515                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
516                wrap->SetName(output->GetName());
517             }   
518             else                    wrap =output->ExportData();
519             // Output wrappers must NOT delete data after merging - the user owns them
520             wrap->SetDeleteData(kFALSE);
521             target->Add(wrap);
522          } else {
523          // Special outputs. The file must be opened and connected to the container.
524             TDirectory *opwd = gDirectory;
525             TFile *file = output->GetFile();
526             if (!file) {
527                AliAnalysisTask *producer = output->GetProducer();
528                Fatal("PackOutput", 
529                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
530                      output->GetFileName(), output->GetName(), producer->ClassName());
531                continue;
532             }   
533             TString outFilename = file->GetName();
534             if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
535             if (isManagedByHandler) {
536                // Terminate IO for files managed by the output handler
537                // file->Write() moved to AOD handler (A.G. 11.01.10)
538 //               if (file) file->Write();
539                if (file && fDebug > 2) {
540                   printf("   handled file %s listing content:\n", file->GetName());
541                   file->ls();
542                }   
543                fOutputEventHandler->TerminateIO();
544             } else {               
545                file->cd();
546                // Release object ownership to users after writing data to file
547                if (output->GetData()->InheritsFrom(TCollection::Class())) {
548                   // If data is a collection, we set the name of the collection 
549                   // as the one of the container and we save as a single key.
550                   TCollection *coll = (TCollection*)output->GetData();
551                   coll->SetName(output->GetName());
552                   coll->Write(output->GetName(), TObject::kSingleKey);
553                } else {
554                   if (output->GetData()->InheritsFrom(TTree::Class())) {
555                      TTree *tree = (TTree*)output->GetData();
556                      tree->SetDirectory(file);
557                      tree->AutoSave();
558                   } else {
559                      output->GetData()->Write();
560                   }   
561                }      
562                if (fDebug > 2) {
563                   printf("   file %s listing content:\n", output->GetFileName());
564                   file->ls();
565                }
566                // Clear file list to release object ownership to user.
567 //               file->Clear();
568                file->Close();
569                output->SetFile(NULL);
570             }
571             // Restore current directory
572             if (opwd) opwd->cd();
573             // Check if a special output location was provided or the output files have to be merged
574             if (strlen(fSpecialOutputLocation.Data())) {
575                TString remote = fSpecialOutputLocation;
576                remote += "/";
577                Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
578                if (remote.BeginsWith("alien://")) {
579                   gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
580                   remote += outFilename;
581                   remote.ReplaceAll(".root", Form("_%d.root", gid));
582                } else {   
583                   remote += Form("%s_%d_", gSystem->HostName(), gid);
584                   remote += outFilename;
585                }   
586                if (fDebug > 1) 
587                   Info("PackOutput", "Output file for container %s to be copied \n   at: %s. No merging.",
588                        output->GetName(), remote.Data());
589                TFile::Cp ( outFilename.Data(), remote.Data() );
590                // Copy extra outputs
591                if (fExtraFiles.Length() && isManagedByHandler) {
592                   TObjArray *arr = fExtraFiles.Tokenize(" ");
593                   TObjString *os;
594                   TIter nextfilename(arr);
595                   while ((os=(TObjString*)nextfilename())) {
596                      outFilename = os->GetString();
597                      remote = fSpecialOutputLocation;
598                      remote += "/";
599                      if (remote.BeginsWith("alien://")) {
600                         remote += outFilename;
601                         remote.ReplaceAll(".root", Form("_%d.root", gid));
602                      } else {   
603                         remote += Form("%s_%d_", gSystem->HostName(), gid);
604                         remote += outFilename;
605                      }   
606                      if (fDebug > 1) 
607                         Info("PackOutput", "Extra AOD file %s to be copied \n   at: %s. No merging.",
608                              outFilename.Data(), remote.Data());
609                      TFile::Cp ( outFilename.Data(), remote.Data() );
610                   }   
611                   delete arr;
612                }   
613             } else {
614             // No special location specified-> use TProofOutputFile as merging utility
615             // The file at this output slot must be opened in CreateOutputObjects
616                if (fDebug > 1) printf("   File for container %s to be merged via file merger...\n", output->GetName());
617             }
618          }      
619       }
620    } 
621    cdir->cd();
622    if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
623 }
624
625 //______________________________________________________________________________
626 void AliAnalysisManager::ImportWrappers(TList *source)
627 {
628 // Import data in output containers from wrappers coming in source.
629    if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
630    TIter next(fOutputs);
631    AliAnalysisDataContainer *cont;
632    AliAnalysisDataWrapper   *wrap;
633    Int_t icont = 0;
634    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
635    TDirectory *cdir = gDirectory;
636    while ((cont=(AliAnalysisDataContainer*)next())) {
637       wrap = 0;
638       if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
639       if (cont->IsRegisterDataset()) continue;
640       const char *filename = cont->GetFileName();
641       Bool_t isManagedByHandler = kFALSE;
642       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
643          isManagedByHandler = kTRUE;
644          filename = fOutputEventHandler->GetOutputFileName();
645       }
646       if (cont->IsSpecialOutput() || inGrid) {
647          if (strlen(fSpecialOutputLocation.Data())) continue;
648          // Copy merged file from PROOF scratch space. 
649          // In case of grid the files are already in the current directory.
650          if (!inGrid) {
651             if (isManagedByHandler && fExtraFiles.Length()) {
652                // Copy extra registered dAOD files.
653                TObjArray *arr = fExtraFiles.Tokenize(" ");
654                TObjString *os;
655                TIter nextfilename(arr);
656                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
657                delete arr;
658             }
659             if (!GetFileFromWrapper(filename, source)) continue;
660          }   
661          // Normally we should connect data from the copied file to the
662          // corresponding output container, but it is not obvious how to do this
663          // automatically if several objects in file...
664          TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
665          if (!f) f = TFile::Open(filename, "READ");
666          if (!f) {
667             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
668             continue;
669          }   
670          TObject *obj = 0;
671          // Cd to the directory pointed by the container
672          TString folder = cont->GetFolderName();
673          if (!folder.IsNull()) f->cd(folder);
674          // Try to fetch first an object having the container name.
675          obj = gDirectory->Get(cont->GetName());
676          if (!obj) {
677             Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()", 
678                     cont->GetName(), filename, cont->GetFolderName());
679             continue;
680          }  
681          wrap = new AliAnalysisDataWrapper(obj);
682          wrap->SetDeleteData(kFALSE);
683       }   
684       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
685       if (!wrap) {
686          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
687          continue;
688       }
689       icont++;
690       if (fDebug > 1) {
691          printf("   Importing data for container %s\n", cont->GetName());
692          if (strlen(filename)) printf("    -> file %s\n", filename);
693          else printf("\n");
694       }   
695       cont->ImportData(wrap);
696    }
697    if (cdir) cdir->cd();
698    if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
699 }
700
701 //______________________________________________________________________________
702 void AliAnalysisManager::UnpackOutput(TList *source)
703 {
704   // Called by AliAnalysisSelector::Terminate only on the client.
705    if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
706    if (!source) {
707       Error("UnpackOutput", "No target. Exiting.");
708       return;
709    }
710    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
711
712    if (fMode == kProofAnalysis) ImportWrappers(source);
713
714    TIter next(fOutputs);
715    AliAnalysisDataContainer *output;
716    while ((output=(AliAnalysisDataContainer*)next())) {
717       if (!output->GetData()) continue;
718       // Check if there are client tasks that run post event loop
719       if (output->HasConsumers()) {
720          // Disable event loop semaphore
721          output->SetPostEventLoop(kTRUE);
722          TObjArray *list = output->GetConsumers();
723          Int_t ncons = list->GetEntriesFast();
724          for (Int_t i=0; i<ncons; i++) {
725             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
726             task->CheckNotify(kTRUE);
727             // If task is active, execute it
728             if (task->IsPostEventLoop() && task->IsActive()) {
729                if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
730                task->ExecuteTask();
731             }   
732          }
733       }   
734    }
735    if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
736 }
737
738 //______________________________________________________________________________
739 void AliAnalysisManager::Terminate()
740 {
741   // The Terminate() function is the last function to be called during
742   // a query. It always runs on the client, it can be used to present
743   // the results graphically.
744    if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
745    TDirectory *cdir = gDirectory;
746    gROOT->cd();
747    AliAnalysisTask *task;
748    AliAnalysisDataContainer *output;
749    TIter next(fTasks);
750    TStopwatch timer;
751    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
752    // Call Terminate() for tasks
753    Int_t itask = 0;
754    while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
755       // Save all the canvases produced by the Terminate
756       TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
757       task->Terminate();
758       gROOT->cd();
759       if (getsysInfo) 
760          AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
761       itask++;   
762       if (TObject::TestBit(kSaveCanvases)) {
763          if (!gROOT->IsBatch()) {
764             if (fDebug>0) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...", task->ClassName());
765             timer.Start();
766             while (timer.CpuTime()<5) {
767                timer.Continue();
768                gSystem->ProcessEvents();
769             }
770          }
771          Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
772          if (iend==0) continue;
773          TCanvas *canvas;
774          for (Int_t ipict=0; ipict<iend; ipict++) {
775             canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
776             if (!canvas) continue;         
777             canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
778          } 
779          gROOT->GetListOfCanvases()->Delete(); 
780       }
781    }   
782    //
783    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
784    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
785    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
786    gROOT->cd();
787    TObjArray *allOutputs = new TObjArray();
788    Int_t icont;
789    for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
790    if (!IsSkipTerminate())
791       for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
792    TIter next1(allOutputs);
793    TString handlerFile = "";
794    if (fOutputEventHandler) {
795       handlerFile = fOutputEventHandler->GetOutputFileName();
796    }
797    while ((output=(AliAnalysisDataContainer*)next1())) {
798       // Special outputs or grid files have the files already closed and written.
799       if (fMode == kGridAnalysis) continue;
800       if (fMode == kProofAnalysis) {
801         if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
802       }  
803       const char *filename = output->GetFileName();
804       TString openoption = "RECREATE";
805       if (!(strcmp(filename, "default"))) continue;
806       if (!strlen(filename)) continue;
807       if (!output->GetData()) continue;
808       TDirectory *opwd = gDirectory;
809       TFile *file = output->GetFile();
810       if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
811       if (!file) {
812               //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
813          if (!gSystem->AccessPathName(filename)) openoption = "UPDATE";
814               if (fDebug>0) printf("Opening file: %s  option=%s\n",filename, openoption.Data());
815          file = new TFile(filename, openoption);
816       } else {
817          if (fDebug>0) printf("File already opened: %s\n", filename);
818       }   
819       if (file->IsZombie()) {
820          Error("Terminate", "Cannot open output file %s", filename);
821          continue;
822       }   
823       output->SetFile(file);
824       file->cd();
825       // Check for a folder request
826       TString dir = output->GetFolderName();
827       if (!dir.IsNull()) {
828          if (!file->GetDirectory(dir)) file->mkdir(dir);
829          file->cd(dir);
830       }  
831       if (fDebug > 0) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
832       if (output->GetData()->InheritsFrom(TCollection::Class())) {
833       // If data is a collection, we set the name of the collection 
834       // as the one of the container and we save as a single key.
835          TCollection *coll = (TCollection*)output->GetData();
836          coll->SetName(output->GetName());
837          coll->Write(output->GetName(), TObject::kSingleKey);
838       } else {
839          if (output->GetData()->InheritsFrom(TTree::Class())) {
840             TTree *tree = (TTree*)output->GetData();
841             tree->SetDirectory(gDirectory);
842             tree->AutoSave();
843          } else {
844             output->GetData()->Write();
845          }   
846       }      
847       if (opwd) opwd->cd();
848    }
849    gROOT->cd();
850    next1.Reset();
851    while ((output=(AliAnalysisDataContainer*)next1())) {
852       // Close all files at output
853       TDirectory *opwd = gDirectory;
854       if (output->GetFile()) {
855          // Clear file list to release object ownership to user.
856 //         output->GetFile()->Clear();
857          output->GetFile()->Close();
858          output->SetFile(NULL);
859          // Copy merged outputs in alien if requested
860          if (fSpecialOutputLocation.Length() && 
861              fSpecialOutputLocation.BeginsWith("alien://")) {
862             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
863             TFile::Cp(output->GetFile()->GetName(), 
864                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
865          }             
866       }   
867       if (opwd) opwd->cd();
868    }   
869    delete allOutputs;
870
871    if (getsysInfo) {
872       TDirectory *cdir = gDirectory;
873       TFile f("syswatch.root", "RECREATE");
874       TH1 *hist;
875       TString cut;
876       if (!f.IsZombie()) {
877          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
878          tree->SetName("syswatch");
879          tree->SetMarkerStyle(kCircle);
880          tree->SetMarkerColor(kBlue);
881          tree->SetMarkerSize(0.5);
882          if (!gROOT->IsBatch()) {
883             tree->SetAlias("event", "id0");
884             tree->SetAlias("task",  "id1");
885             tree->SetAlias("stage", "id2");
886             // Already defined aliases
887             // tree->SetAlias("deltaT","stampSec-stampOldSec");
888             // tree->SetAlias("T","stampSec-first");
889             // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
890             // tree->SetAlias("VM","pI.fMemVirtual");
891             TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
892             Int_t npads = 1 /*COO plot for all tasks*/ +
893                           fTopTasks->GetEntries() /*Exec plot per task*/ +
894                           1 /*Terminate plot for all tasks*/ +
895                           1; /*vm plot*/
896                           
897             Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
898             if (npads<iopt*(iopt+1))
899                canvas->Divide(iopt, iopt+1, 0.01, 0.01);
900             else
901                canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
902             Int_t ipad = 1;
903             // draw the plot of deltaVM for Exec for each task
904             for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
905                task = (AliAnalysisTask*)fTopTasks->At(itask);
906                canvas->cd(ipad++);
907                cut = Form("task==%d && stage==1", itask);
908                tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
909                hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
910                if (hist) {
911                   hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
912                   hist->GetYaxis()->SetTitle("deltaVM [kB]");
913                }   
914             }
915             // Draw the plot of deltaVM for CreateOutputObjects for all tasks
916             canvas->cd(ipad++);
917             tree->SetMarkerStyle(kFullTriangleUp);
918             tree->SetMarkerColor(kRed);
919             tree->SetMarkerSize(0.8);
920             cut = "task>=0 && task<1000 && stage==0";
921             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
922             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");            
923             if (hist) {
924                hist->SetTitle("Memory in CreateOutputObjects()");
925                hist->GetYaxis()->SetTitle("deltaVM [kB]");
926                hist->GetXaxis()->SetTitle("task");
927             }   
928             // draw the plot of deltaVM for Terminate for all tasks
929             canvas->cd(ipad++);
930             tree->SetMarkerStyle(kOpenSquare);
931             tree->SetMarkerColor(kMagenta);
932             cut = "task>=0 && task<1000 && stage==2";
933             tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
934             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
935             if (hist) {
936                hist->SetTitle("Memory in Terminate()");
937                hist->GetYaxis()->SetTitle("deltaVM [kB]");
938                hist->GetXaxis()->SetTitle("task");
939             }   
940             // Full VM profile
941             canvas->cd(ipad++);
942             tree->SetMarkerStyle(kFullCircle);
943             tree->SetMarkerColor(kGreen);
944             cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);            
945             tree->Draw("VM:event",cut,"", 1234567890, 0);
946             hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
947             if (hist) {
948                hist->SetTitle("Virtual memory");
949                hist->GetYaxis()->SetTitle("VM [kB]");
950             }
951             canvas->Modified();   
952          }   
953          tree->SetMarkerStyle(kCircle);
954          tree->SetMarkerColor(kBlue);
955          tree->SetMarkerSize(0.5);
956          tree->Write();
957          f.Close();
958          delete tree;
959       }
960       if (cdir) cdir->cd();
961    }
962    // Validate the output files
963    if (ValidateOutputFiles()) {
964       ofstream out;
965       out.open("outputs_valid", ios::out);
966       out.close();
967    }
968    cdir->cd();      
969    if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
970 }
971 //______________________________________________________________________________
972 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
973 {
974 // Profiles the task having the itop index in the list of top (first level) tasks.
975    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
976    if (!task) {
977       Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
978       return;
979    }
980    ProfileTask(task->GetName(), option);
981 }      
982
983 //______________________________________________________________________________
984 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
985 {
986 // Profile a managed task after the execution of the analysis in case NSysInfo
987 // was used.
988    if (gSystem->AccessPathName("syswatch.root")) {
989       Error("ProfileTask", "No file syswatch.root found in the current directory");
990       return;
991    }
992    if (gROOT->IsBatch()) return;
993    AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
994    if (!task) {
995       Error("ProfileTask", "No top task named %s known by the manager.", name);
996       return;
997    }
998    Int_t itop = fTopTasks->IndexOf(task);
999    Int_t itask = fTasks->IndexOf(task);
1000    // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1001    TDirectory *cdir = gDirectory;
1002    TFile f("syswatch.root");
1003    TTree *tree = (TTree*)f.Get("syswatch");
1004    if (!tree) {
1005       Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1006       return;
1007    }   
1008    if (fDebug > 0) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1009    TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1010    canvas->Divide(2, 2, 0.01, 0.01);
1011    Int_t ipad = 1;
1012    TString cut;
1013    TH1 *hist;
1014    // VM profile for COO and Terminate methods
1015    canvas->cd(ipad++);
1016    cut = Form("task==%d && (stage==0 || stage==2)",itask);
1017    tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1018    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1019    if (hist) {
1020       hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1021       hist->GetYaxis()->SetTitle("deltaVM [kB]");
1022       hist->GetXaxis()->SetTitle("method");
1023    }   
1024    // CPU profile per event
1025    canvas->cd(ipad++);
1026    cut = Form("task==%d && stage==1",itop);
1027    tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1028    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1029    if (hist) {
1030       hist->SetTitle("Execution time per event");
1031       hist->GetYaxis()->SetTitle("CPU/event [s]");
1032    }   
1033    // VM profile for Exec
1034    canvas->cd(ipad++);
1035    cut = Form("task==%d && stage==1",itop);
1036    tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1037    hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1038    if (hist) {
1039       hist->SetTitle("Alocated VM[kB] per event");
1040       hist->GetYaxis()->SetTitle("deltaVM [kB]");
1041    }   
1042    canvas->Modified();
1043    delete tree;
1044    f.Close();
1045    if (cdir) cdir->cd();
1046 }     
1047
1048 //______________________________________________________________________________
1049 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1050 {
1051 // Adds a user task to the global list of tasks.
1052    if (fTasks->FindObject(task)) {
1053       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1054       return;
1055    }   
1056    task->SetActive(kFALSE);
1057    fTasks->Add(task);
1058 }  
1059
1060 //______________________________________________________________________________
1061 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1062 {
1063 // Retreive task by name.
1064    if (!fTasks) return NULL;
1065    return (AliAnalysisTask*)fTasks->FindObject(name);
1066 }
1067
1068 //______________________________________________________________________________
1069 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
1070                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
1071 {
1072 // Create a data container of a certain type. Types can be:
1073 //   kExchangeContainer  = 0, used to exchange data between tasks
1074 //   kInputContainer   = 1, used to store input data
1075 //   kOutputContainer  = 2, used for writing result to a file
1076 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1077 // the output object to a folder inside the output file
1078    if (fContainers->FindObject(name)) {
1079       Error("CreateContainer","A container named %s already defined !",name);
1080       return NULL;
1081    }   
1082    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1083    fContainers->Add(cont);
1084    switch (type) {
1085       case kInputContainer:
1086          fInputs->Add(cont);
1087          break;
1088       case kOutputContainer:
1089          fOutputs->Add(cont);
1090          if (filename && strlen(filename)) {
1091             cont->SetFileName(filename);
1092             cont->SetDataOwned(kFALSE);  // data owned by the file
1093          }   
1094          break;
1095       case kParamContainer:
1096          fParamCont->Add(cont);
1097          if (filename && strlen(filename)) {
1098             cont->SetFileName(filename);
1099             cont->SetDataOwned(kFALSE);  // data owned by the file
1100          }   
1101          break;
1102       case kExchangeContainer:
1103          break;   
1104    }
1105    return cont;
1106 }
1107          
1108 //______________________________________________________________________________
1109 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1110                                         AliAnalysisDataContainer *cont)
1111 {
1112 // Connect input of an existing task to a data container.
1113    if (!task) {
1114       Error("ConnectInput", "Task pointer is NULL");
1115       return kFALSE;
1116    }   
1117    if (!fTasks->FindObject(task)) {
1118       AddTask(task);
1119       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1120    } 
1121    Bool_t connected = task->ConnectInput(islot, cont);
1122    return connected;
1123 }   
1124
1125 //______________________________________________________________________________
1126 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1127                                         AliAnalysisDataContainer *cont)
1128 {
1129 // Connect output of an existing task to a data container.
1130    if (!task) {
1131       Error("ConnectOutput", "Task pointer is NULL");
1132       return kFALSE;
1133    }   
1134    if (!fTasks->FindObject(task)) {
1135       AddTask(task);
1136       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1137    } 
1138    Bool_t connected = task->ConnectOutput(islot, cont);
1139    return connected;
1140 }   
1141                                
1142 //______________________________________________________________________________
1143 void AliAnalysisManager::CleanContainers()
1144 {
1145 // Clean data from all containers that have already finished all client tasks.
1146    TIter next(fContainers);
1147    AliAnalysisDataContainer *cont;
1148    while ((cont=(AliAnalysisDataContainer *)next())) {
1149       if (cont->IsOwnedData() && 
1150           cont->IsDataReady() && 
1151           cont->ClientsExecuted()) cont->DeleteData();
1152    }
1153 }
1154
1155 //______________________________________________________________________________
1156 Bool_t AliAnalysisManager::InitAnalysis()
1157 {
1158 // Initialization of analysis chain of tasks. Should be called after all tasks
1159 // and data containers are properly connected
1160    // Reset flag and remove valid_outputs file if exists
1161    fInitOK = kFALSE;
1162    if (!gSystem->AccessPathName("outputs_valid"))
1163       gSystem->Unlink("outputs_valid");
1164    // Check for top tasks (depending only on input data containers)
1165    if (!fTasks->First()) {
1166       Error("InitAnalysis", "Analysis has no tasks !");
1167       return kFALSE;
1168    }   
1169    TIter next(fTasks);
1170    AliAnalysisTask *task;
1171    AliAnalysisDataContainer *cont;
1172    Int_t ntop = 0;
1173    Int_t nzombies = 0;
1174    Bool_t iszombie = kFALSE;
1175    Bool_t istop = kTRUE;
1176    Int_t i;
1177    while ((task=(AliAnalysisTask*)next())) {
1178       istop = kTRUE;
1179       iszombie = kFALSE;
1180       Int_t ninputs = task->GetNinputs();
1181       for (i=0; i<ninputs; i++) {
1182          cont = task->GetInputSlot(i)->GetContainer();
1183          if (!cont) {
1184             if (!iszombie) {
1185                task->SetZombie();
1186                fZombies->Add(task);
1187                nzombies++;
1188                iszombie = kTRUE;
1189             }   
1190             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
1191                   i, task->GetName()); 
1192          }
1193          if (iszombie) continue;
1194          // Check if cont is an input container
1195          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1196          // Connect to parent task
1197       }
1198       if (istop) {
1199          ntop++;
1200          fTopTasks->Add(task);
1201       }
1202    }
1203    if (!ntop) {
1204       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1205       return kFALSE;
1206    }                        
1207    // Check now if there are orphan tasks
1208    for (i=0; i<ntop; i++) {
1209       task = (AliAnalysisTask*)fTopTasks->At(i);
1210       task->SetUsed();
1211    }
1212    Int_t norphans = 0;
1213    next.Reset();
1214    while ((task=(AliAnalysisTask*)next())) {
1215       if (!task->IsUsed()) {
1216          norphans++;
1217          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1218       }   
1219    }          
1220    // Check the task hierarchy (no parent task should depend on data provided
1221    // by a daughter task)
1222    for (i=0; i<ntop; i++) {
1223       task = (AliAnalysisTask*)fTopTasks->At(i);
1224       if (task->CheckCircularDeps()) {
1225          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1226          PrintStatus("dep");
1227          return kFALSE;
1228       }   
1229    }
1230    // Check that all containers feeding post-event loop tasks are in the outputs list
1231    TIter nextcont(fContainers); // loop over all containers
1232    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1233       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1234          if (cont->HasConsumers()) {
1235          // Check if one of the consumers is post event loop
1236             TIter nextconsumer(cont->GetConsumers());
1237             while ((task=(AliAnalysisTask*)nextconsumer())) {
1238                if (task->IsPostEventLoop()) {
1239                   fOutputs->Add(cont);
1240                   break;
1241                }
1242             }
1243          }
1244       }
1245    }   
1246    // Check if all special output containers have a file name provided
1247    TIter nextout(fOutputs);
1248    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1249       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1250          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1251          return kFALSE;
1252       }
1253    }      
1254    fInitOK = kTRUE;
1255    return kTRUE;
1256 }   
1257
1258 //______________________________________________________________________________
1259 void AliAnalysisManager::PrintStatus(Option_t *option) const
1260 {
1261 // Print task hierarchy.
1262    if (!fInitOK) {
1263       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1264       return;
1265    }   
1266    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1267    if (getsysInfo)
1268       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1269    TIter next(fTopTasks);
1270    AliAnalysisTask *task;
1271    while ((task=(AliAnalysisTask*)next()))
1272       task->PrintTask(option);
1273 }
1274
1275 //______________________________________________________________________________
1276 void AliAnalysisManager::ResetAnalysis()
1277 {
1278 // Reset all execution flags and clean containers.
1279    CleanContainers();
1280 }
1281
1282 //______________________________________________________________________________
1283 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1284 {
1285 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1286 // MIX. Process nentries starting from firstentry
1287    Long64_t retv = 0;
1288    // Backup current directory and make sure gDirectory points to gROOT
1289    TDirectory *cdir = gDirectory;
1290    gROOT->cd();
1291    if (!fInitOK) {
1292       Error("StartAnalysis","Analysis manager was not initialized !");
1293       cdir->cd();
1294       return -1;
1295    }
1296    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1297    TString anaType = type;
1298    anaType.ToLower();
1299    fMode = kLocalAnalysis;
1300    Bool_t runlocalinit = kTRUE;
1301    if (anaType.Contains("file")) {
1302       runlocalinit = kFALSE;
1303    }   
1304    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1305    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1306    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1307
1308    if (fMode == kGridAnalysis) {
1309       if (!anaType.Contains("terminate")) {
1310          if (!fGridHandler) {
1311             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1312             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1313             cdir->cd();
1314             return -1;
1315          }
1316          // Write analysis manager in the analysis file
1317          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1318          // run local task configuration
1319          TIter nextTask(fTasks);
1320          AliAnalysisTask *task;
1321          while ((task=(AliAnalysisTask*)nextTask())) {
1322             task->LocalInit();
1323             gROOT->cd();
1324          }
1325          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1326             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1327             cdir->cd();
1328             return -1;
1329          }   
1330
1331          // Terminate grid analysis
1332          if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1333          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1334          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1335          if (!fGridHandler->MergeOutputs()) {
1336             // Return if outputs could not be merged or if it alien handler
1337             // was configured for offline mode or local testing.
1338             cdir->cd();
1339             return 0;
1340          }
1341       }   
1342       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1343       ImportWrappers(NULL);
1344       Terminate();
1345       cdir->cd();
1346       return 0;
1347    }
1348    char line[256];
1349    SetEventLoop(kFALSE);
1350    // Enable event loop mode if a tree was provided
1351    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1352
1353    TChain *chain = 0;
1354    TString ttype = "TTree";
1355    if (tree && tree->IsA() == TChain::Class()) {
1356       chain = (TChain*)tree;
1357       if (!chain || !chain->GetListOfFiles()->First()) {
1358          Error("StartAnalysis", "Cannot process null or empty chain...");
1359          cdir->cd();
1360          return -1;
1361       }   
1362       ttype = "TChain";
1363    }   
1364
1365    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1366    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1367    // Initialize locally all tasks (happens for all modes)
1368    TIter next(fTasks);
1369    AliAnalysisTask *task;
1370    if (runlocalinit) {
1371       while ((task=(AliAnalysisTask*)next())) {
1372          task->LocalInit();
1373          gROOT->cd();
1374       }
1375       if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1376    }   
1377    
1378    switch (fMode) {
1379       case kLocalAnalysis:
1380          if (!tree) {
1381             TIter nextT(fTasks);
1382             // Call CreateOutputObjects for all tasks
1383             Int_t itask = 0;
1384             while ((task=(AliAnalysisTask*)nextT())) {
1385                task->CreateOutputObjects();
1386                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1387                gROOT->cd();
1388                itask++;
1389             }   
1390             if (IsExternalLoop()) {
1391                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1392                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1393                return 0;
1394             }
1395             ExecAnalysis();
1396             Terminate();
1397             return 0;
1398          } 
1399          // Run tree-based analysis via AliAnalysisSelector  
1400          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1401          fSelector = new AliAnalysisSelector(this);
1402          retv = tree->Process(fSelector, "", nentries, firstentry);
1403          break;
1404       case kProofAnalysis:
1405          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1406             Error("StartAnalysis", "No PROOF!!! Exiting.");
1407             cdir->cd();
1408             return -1;
1409          }   
1410          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1411          gROOT->ProcessLine(line);
1412          if (chain) {
1413             chain->SetProof();
1414             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1415             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1416          } else {
1417             Error("StartAnalysis", "No chain!!! Exiting.");
1418             cdir->cd();
1419             return -1;
1420          }      
1421          break;
1422       case kGridAnalysis:
1423          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1424          break;
1425       case kMixingAnalysis:   
1426          // Run event mixing analysis
1427          if (!fEventPool) {
1428             Error("StartAnalysis", "Cannot run event mixing without event pool");
1429             cdir->cd();
1430             return -1;
1431          }
1432          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1433          fSelector = new AliAnalysisSelector(this);
1434          while ((chain=fEventPool->GetNextChain())) {
1435             next.Reset();
1436             // Call NotifyBinChange for all tasks
1437             while ((task=(AliAnalysisTask*)next()))
1438                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1439             retv = chain->Process(fSelector);
1440             if (retv < 0) {
1441                Error("StartAnalysis", "Mixing analysis failed");
1442                cdir->cd();
1443                return retv;
1444             }   
1445          }
1446          PackOutput(fSelector->GetOutputList());
1447          Terminate();
1448    }
1449    cdir->cd();
1450    return retv;
1451 }   
1452
1453 //______________________________________________________________________________
1454 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1455 {
1456 // Start analysis for this manager on a given dataset. Analysis task can be: 
1457 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1458    if (!fInitOK) {
1459       Error("StartAnalysis","Analysis manager was not initialized !");
1460       return -1;
1461    }
1462    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1463    TString anaType = type;
1464    anaType.ToLower();
1465    if (!anaType.Contains("proof")) {
1466       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1467       return -1;
1468    }   
1469    fMode = kProofAnalysis;
1470    char line[256];
1471    SetEventLoop(kTRUE);
1472    // Set the dataset flag
1473    TObject::SetBit(kUseDataSet);
1474    fTree = 0;
1475
1476    // Initialize locally all tasks
1477    TIter next(fTasks);
1478    AliAnalysisTask *task;
1479    while ((task=(AliAnalysisTask*)next())) {
1480       task->LocalInit();
1481    }
1482    
1483    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1484       Error("StartAnalysis", "No PROOF!!! Exiting.");
1485       return -1;
1486    }   
1487    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1488    gROOT->ProcessLine(line);
1489    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1490    if (!gROOT->ProcessLine(line)) {
1491       Error("StartAnalysis", "Dataset %s not found", dataset);
1492       return -1;
1493    }   
1494    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1495            dataset, nentries, firstentry);
1496    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1497    Long_t retv = (Long_t)gROOT->ProcessLine(line);
1498    return retv;
1499 }   
1500
1501 //______________________________________________________________________________
1502 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1503 {
1504 // Opens according the option the file specified by cont->GetFileName() and changes
1505 // current directory to cont->GetFolderName(). If the file was already opened, it
1506 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1507 // be optionally ignored.
1508   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1509   TString filename = cont->GetFileName();
1510   TFile *f = NULL;
1511   if (filename.IsNull()) {
1512     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1513     return NULL;
1514   }
1515   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1516       && !ignoreProof)
1517     f = mgr->OpenProofFile(cont,option);
1518   else {
1519     // Check first if the file is already opened
1520     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1521     if (f) {
1522       // Check if option "UPDATE" was preserved 
1523       TString opt(option);
1524       opt.ToUpper();
1525       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1526         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1527     } else {
1528       f = TFile::Open(filename, option);
1529     }    
1530   }   
1531   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1532     cont->SetFile(f);
1533     // Cd to file
1534     f->cd();
1535     // Check for a folder request
1536     TString dir = cont->GetFolderName(); 
1537     if (!dir.IsNull()) {
1538       if (!f->GetDirectory(dir)) f->mkdir(dir);
1539       f->cd(dir);
1540     }
1541     return f;
1542   }
1543   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1544   cont->SetFile(NULL);
1545   return NULL;
1546 }    
1547  
1548 //______________________________________________________________________________
1549 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
1550 {
1551 // Opens a special output file used in PROOF.
1552   TString line;
1553   TString filename = cont->GetFileName();
1554   if (cont == fCommonOutput) {
1555      if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1556      else Fatal("OpenProofFile","No output container. Exiting.");
1557   }   
1558   TFile *f = NULL;
1559   if (fMode!=kProofAnalysis || !fSelector) {
1560     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1561     return NULL;
1562   } 
1563   if (fSpecialOutputLocation.Length()) {
1564     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1565     if (f) {
1566       // Check if option "UPDATE" was preserved 
1567       TString opt(option);
1568       opt.ToUpper();
1569       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1570         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1571     } else {
1572       f = new TFile(filename, option);
1573     }
1574     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1575       cont->SetFile(f);
1576       // Cd to file
1577       f->cd();
1578       // Check for a folder request
1579       TString dir = cont->GetFolderName(); 
1580       if (dir.Length()) {
1581         if (!f->GetDirectory(dir)) f->mkdir(dir);
1582         f->cd(dir);
1583       }      
1584       return f;
1585     }
1586     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1587     cont->SetFile(NULL);
1588     return NULL;       
1589   }
1590   // Check if there is already a proof output file in the output list
1591   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1592   if (pof) {
1593     // Get the actual file
1594     line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1595     filename = (const char*)gROOT->ProcessLine(line);
1596     if (fDebug>1) {
1597       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1598     }  
1599     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1600     if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1601     // Check if option "UPDATE" was preserved 
1602     TString opt(option);
1603     opt.ToUpper();
1604     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1605       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1606   } else {
1607     if (cont->IsRegisterDataset()) {
1608       TString dsetName = filename;
1609       dsetName.ReplaceAll(".root", cont->GetTitle());
1610       dsetName.ReplaceAll(":","_");
1611       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1612       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1613     } else {
1614       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1615       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1616     }
1617     if (fDebug > 1) printf("=== %s\n", line.Data());
1618     gROOT->ProcessLine(line);
1619     line = Form("pf->OpenFile(\"%s\");", option);
1620     gROOT->ProcessLine(line);
1621     f = gFile;
1622     if (fDebug > 1) {
1623       gROOT->ProcessLine("pf->Print()");
1624       printf(" == proof file name: %s", f->GetName());
1625     }   
1626     // Add to proof output list
1627     line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1628     if (fDebug > 1) printf("=== %s\n", line.Data());
1629     gROOT->ProcessLine(line);
1630   }
1631   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1632     cont->SetFile(f);
1633     // Cd to file
1634     f->cd();
1635     // Check for a folder request
1636     TString dir = cont->GetFolderName(); 
1637     if (!dir.IsNull()) {
1638       if (!f->GetDirectory(dir)) f->mkdir(dir);
1639       f->cd(dir);
1640     }
1641     return f;
1642   }
1643   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1644   cont->SetFile(NULL);  
1645   return NULL;
1646 }   
1647
1648 //______________________________________________________________________________
1649 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1650 {
1651 // Execute analysis.
1652    static Long64_t ncalls = 0;
1653    if (fDebug > 0) printf("MGR: Processing event #%lld\n", ncalls);
1654    TDirectory *cdir = gDirectory;
1655    gROOT->cd();
1656    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1657    if (getsysInfo && ((ncalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)ncalls);
1658    ncalls++;
1659    if (!fInitOK) {
1660       Error("ExecAnalysis", "Analysis manager was not initialized !");
1661       cdir->cd();
1662       return;
1663    }
1664    AliAnalysisTask *task;
1665    // Check if the top tree is active.
1666    if (fTree) {
1667       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1668          AliSysInfo::AddStamp("Handlers_BeginEventGroup",(Int_t)ncalls, 1002, 0);
1669       TIter next(fTasks);
1670    // De-activate all tasks
1671       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1672       AliAnalysisDataContainer *cont = fCommonInput;
1673       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1674       if (!cont) {
1675               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1676          cdir->cd();
1677          return;
1678       }   
1679       cont->SetData(fTree); // This will notify all consumers
1680       Long64_t entry = fTree->GetTree()->GetReadEntry();      
1681 //
1682 //    Call BeginEvent() for optional input/output and MC services 
1683       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1684       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1685       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1686       gROOT->cd();
1687       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1688          AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
1689 //
1690 //    Execute the tasks
1691 //      TIter next1(cont->GetConsumers());
1692       TIter next1(fTopTasks);
1693       Int_t itask = 0;
1694       while ((task=(AliAnalysisTask*)next1())) {
1695          if (fDebug >1) {
1696             cout << "    Executing task " << task->GetName() << endl;
1697          }       
1698          task->ExecuteTask(option);
1699          gROOT->cd();
1700          if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1701             AliSysInfo::AddStamp(task->ClassName(),(Int_t)ncalls, itask, 1);
1702          itask++;   
1703       }
1704 //
1705 //    Call FinishEvent() for optional output and MC services 
1706       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1707       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1708       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1709       // Gather system information if requested
1710       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1711          AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1001, 1);
1712       cdir->cd();   
1713       return;
1714    }   
1715    // The event loop is not controlled by TSelector   
1716 //
1717 //  Call BeginEvent() for optional input/output and MC services 
1718    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1719    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1720    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1721    gROOT->cd();
1722    if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1723       AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
1724    TIter next2(fTopTasks);
1725    while ((task=(AliAnalysisTask*)next2())) {
1726       task->SetActive(kTRUE);
1727       if (fDebug > 1) {
1728          cout << "    Executing task " << task->GetName() << endl;
1729       }   
1730       task->ExecuteTask(option);
1731       gROOT->cd();
1732    }   
1733 //
1734 // Call FinishEvent() for optional output and MC services 
1735    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1736    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1737    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1738    if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1739       AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1);
1740    cdir->cd();   
1741 }
1742
1743 //______________________________________________________________________________
1744 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
1745 {
1746 // Set the input event handler and create a container for it.
1747    fInputEventHandler   = handler;
1748    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1749 //   Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1750 }
1751
1752 //______________________________________________________________________________
1753 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
1754 {
1755 // Set the input event handler and create a container for it.
1756    fOutputEventHandler   = handler;
1757    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1758    fCommonOutput->SetSpecialOutput();
1759 //   Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1760 }
1761
1762 //______________________________________________________________________________
1763 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1764 {
1765 // This method is used externally to register output files which are not
1766 // connected to any output container, so that the manager can properly register,
1767 // retrieve or merge them when running in distributed mode. The file names are
1768 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1769    if (fExtraFiles.Contains(fname)) return;
1770    if (fExtraFiles.Length()) fExtraFiles += " ";
1771    fExtraFiles += fname;
1772 }
1773
1774 //______________________________________________________________________________
1775 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
1776 {
1777 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1778    char fullPath[512];
1779    char chUrl[512];
1780    TObject *pof =  source->FindObject(filename);
1781    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1782       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1783       return kFALSE;
1784    }
1785    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", fullPath, pof));
1786    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", chUrl));
1787    TString clientUrl(chUrl);
1788    TString fullPath_str(fullPath);
1789    if (clientUrl.Contains("localhost")){
1790       TObjArray* array = fullPath_str.Tokenize ( "//" );
1791       TObjString *strobj = ( TObjString *)array->At(1);
1792       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1793       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1794       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1795       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1796       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
1797       delete arrayPort;
1798       delete array;
1799    }
1800    if (fDebug > 1) 
1801       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", fullPath_str.Data());
1802    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
1803    if (!gotit)
1804       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1805    return gotit;
1806 }
1807
1808 //______________________________________________________________________________
1809 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1810 {
1811 // Fill analysis type in the provided string.
1812    switch (fMode) {
1813       case kLocalAnalysis:
1814          type = "local";
1815          return;
1816       case kProofAnalysis:
1817          type = "proof";
1818          return;
1819       case kGridAnalysis:
1820          type = "grid";
1821          return;
1822       case kMixingAnalysis:
1823          type = "mix";
1824    }
1825 }
1826
1827 //______________________________________________________________________________
1828 Bool_t AliAnalysisManager::ValidateOutputFiles() const
1829 {
1830 // Validate all output files.
1831    TIter next(fOutputs);
1832    AliAnalysisDataContainer *output;
1833    TDirectory *cdir = gDirectory;
1834    TString openedFiles;
1835    while ((output=(AliAnalysisDataContainer*)next())) {
1836       if (output->IsRegisterDataset()) continue;
1837       TString filename = output->GetFileName();
1838       if (filename == "default") {
1839          if (!fOutputEventHandler) continue;
1840          filename = fOutputEventHandler->GetOutputFileName();
1841          // Main AOD may not be there
1842          if (gSystem->AccessPathName(filename)) continue;
1843       }
1844       // Check if the file is closed
1845       if (openedFiles.Contains(filename)) continue;;
1846       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1847       if (file) {
1848          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1849          // Clear file list to release object ownership to user.
1850 //         file->Clear();
1851          file->Close();
1852       }
1853       file = TFile::Open(filename);
1854       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1855          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1856          cdir->cd();
1857          return kFALSE;
1858       }
1859       file->Close();
1860       openedFiles += filename;
1861       openedFiles += " ";
1862    }
1863    cdir->cd();
1864    return kTRUE;
1865 }   
1866
1867 //______________________________________________________________________________
1868 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
1869 {
1870 // Implements a nice text mode progress bar.
1871    static Long64_t icount = 0;
1872    static TString oname;
1873    static TString nname;
1874    static Long64_t ocurrent = 0;
1875    static Long64_t osize = 0;
1876    static Int_t oseconds = 0;
1877    static TStopwatch *owatch = 0;
1878    static Bool_t oneoftwo = kFALSE;
1879    static Int_t nrefresh = 0;
1880    static Int_t nchecks = 0;
1881    const char symbol[4] = {'=','\\','|','/'}; 
1882    char progress[11] = "          ";
1883    Int_t ichar = icount%4;
1884    
1885    if (!refresh) {
1886       nrefresh = 0;
1887       if (!size) return;
1888       owatch = watch;
1889       oname = opname;
1890       ocurrent = TMath::Abs(current);
1891       osize = TMath::Abs(size);
1892       if (ocurrent > osize) ocurrent=osize;
1893    } else {
1894       nrefresh++;
1895       if (!osize) return;
1896    }     
1897    icount++;
1898    Double_t time = 0.;
1899    Int_t hours = 0;
1900    Int_t minutes = 0;
1901    Int_t seconds = 0;
1902    if (owatch && !last) {
1903       owatch->Stop();
1904       time = owatch->RealTime();
1905       hours = (Int_t)(time/3600.);
1906       time -= 3600*hours;
1907       minutes = (Int_t)(time/60.);
1908       time -= 60*minutes;
1909       seconds = (Int_t)time;
1910       if (refresh)  {
1911          if (oseconds==seconds) {
1912             owatch->Continue();
1913             return;
1914          }
1915          oneoftwo = !oneoftwo;   
1916       }
1917       oseconds = seconds;   
1918    }
1919    if (refresh && oneoftwo) {
1920       nname = oname;
1921       if (nchecks <= 0) nchecks = nrefresh+1;
1922       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
1923       oname = Form("     == %d%% ==", pctdone);
1924    }         
1925    Double_t percent = 100.0*ocurrent/osize;
1926    Int_t nchar = Int_t(percent/10);
1927    if (nchar>10) nchar=10;
1928    Int_t i;
1929    for (i=0; i<nchar; i++)  progress[i] = '=';
1930    progress[nchar] = symbol[ichar];
1931    for (i=nchar+1; i<10; i++) progress[i] = ' ';
1932    progress[10] = '\0';
1933    oname += "                    ";
1934    oname.Remove(20);
1935    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
1936    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
1937    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
1938    if (time>0.) fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d             \r", percent, hours, minutes, seconds);
1939    else fprintf(stderr, "[%6.2f %%]\r", percent);
1940    if (refresh && oneoftwo) oname = nname;
1941    if (owatch) owatch->Continue();
1942    if (last) {
1943       icount = 0;
1944       owatch = 0;
1945       ocurrent = 0;
1946       osize = 0;
1947       oseconds = 0;
1948       oneoftwo = kFALSE;
1949       nrefresh = 0;
1950       fprintf(stderr, "\n");
1951    }   
1952 }