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