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