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