]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Fix for using AOD handler in CAF (JF)
[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() && 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:\", 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, Long64_t nentries, Long64_t firstentry)
1330 {
1331 // Start analysis having a grid handler.
1332    if (!fGridHandler) {
1333       Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1334       Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1335       return -1;
1336    }
1337    TTree *tree = NULL;
1338    return StartAnalysis(type, tree, nentries, firstentry);
1339 }
1340
1341 //______________________________________________________________________________
1342 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1343 {
1344 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1345 // MIX. Process nentries starting from firstentry
1346    Long64_t retv = 0;
1347    // Backup current directory and make sure gDirectory points to gROOT
1348    TDirectory *cdir = gDirectory;
1349    gROOT->cd();
1350    if (!fInitOK) {
1351       Error("StartAnalysis","Analysis manager was not initialized !");
1352       cdir->cd();
1353       return -1;
1354    }
1355    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1356    fIsRemote = kFALSE;
1357    TString anaType = type;
1358    anaType.ToLower();
1359    fMode = kLocalAnalysis;
1360    Bool_t runlocalinit = kTRUE;
1361    if (anaType.Contains("file")) {
1362       runlocalinit = kFALSE;
1363       fIsRemote = kTRUE;
1364    }   
1365    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1366    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1367    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1368
1369    if (fMode == kGridAnalysis) {
1370       fIsRemote = kTRUE;
1371       if (!anaType.Contains("terminate")) {
1372          if (!fGridHandler) {
1373             Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1374             Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1375             cdir->cd();
1376             return -1;
1377          }
1378          // Write analysis manager in the analysis file
1379          cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1380          // run local task configuration
1381          TIter nextTask(fTasks);
1382          AliAnalysisTask *task;
1383          while ((task=(AliAnalysisTask*)nextTask())) {
1384             task->LocalInit();
1385             gROOT->cd();
1386          }
1387          if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1388             Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1389             cdir->cd();
1390             return -1;
1391          }   
1392
1393          // Terminate grid analysis
1394          if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1395          if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1396          cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1397          if (!fGridHandler->MergeOutputs()) {
1398             // Return if outputs could not be merged or if it alien handler
1399             // was configured for offline mode or local testing.
1400             cdir->cd();
1401             return 0;
1402          }
1403       }   
1404       cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1405       ImportWrappers(NULL);
1406       Terminate();
1407       cdir->cd();
1408       return 0;
1409    }
1410    TString line;
1411    SetEventLoop(kFALSE);
1412    // Enable event loop mode if a tree was provided
1413    if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1414
1415    TChain *chain = 0;
1416    TString ttype = "TTree";
1417    if (tree && tree->IsA() == TChain::Class()) {
1418       chain = (TChain*)tree;
1419       if (!chain || !chain->GetListOfFiles()->First()) {
1420          Error("StartAnalysis", "Cannot process null or empty chain...");
1421          cdir->cd();
1422          return -1;
1423       }   
1424       ttype = "TChain";
1425    }   
1426
1427    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1428    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1429    // Initialize locally all tasks (happens for all modes)
1430    TIter next(fTasks);
1431    AliAnalysisTask *task;
1432    if (runlocalinit) {
1433       while ((task=(AliAnalysisTask*)next())) {
1434          task->LocalInit();
1435          gROOT->cd();
1436       }
1437       if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1438    }   
1439    
1440    switch (fMode) {
1441       case kLocalAnalysis:
1442          if (!tree && !fGridHandler) {
1443             TIter nextT(fTasks);
1444             // Call CreateOutputObjects for all tasks
1445             Int_t itask = 0;
1446             Bool_t dirStatus = TH1::AddDirectoryStatus();
1447             while ((task=(AliAnalysisTask*)nextT())) {
1448                TH1::AddDirectory(kFALSE);
1449                task->CreateOutputObjects();
1450                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1451                gROOT->cd();
1452                itask++;
1453             }   
1454             TH1::AddDirectory(dirStatus);
1455             if (IsExternalLoop()) {
1456                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1457                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1458                return 0;
1459             }
1460             ExecAnalysis();
1461             Terminate();
1462             return 0;
1463          } 
1464          fSelector = new AliAnalysisSelector(this);
1465          // Check if a plugin handler is used
1466          if (fGridHandler) {
1467             // Get the chain from the plugin
1468             TString dataType = "esdTree";
1469             if (fInputEventHandler) {
1470                dataType = fInputEventHandler->GetDataType();
1471                dataType.ToLower();
1472                dataType += "Tree";
1473             }   
1474             chain = fGridHandler->GetChainForTestMode(dataType);
1475             if (!chain) {
1476                Error("StartAnalysis", "No chain for test mode. Aborting.");
1477                return -1;
1478             }
1479             cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1480             retv = chain->Process(fSelector, "", nentries, firstentry);
1481             break;
1482          }
1483          // Run tree-based analysis via AliAnalysisSelector  
1484          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1485          retv = tree->Process(fSelector, "", nentries, firstentry);
1486          break;
1487       case kProofAnalysis:
1488          fIsRemote = kTRUE;
1489          // Check if the plugin is used
1490          if (fGridHandler) {
1491             return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1492          }
1493          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1494             Error("StartAnalysis", "No PROOF!!! Exiting.");
1495             cdir->cd();
1496             return -1;
1497          }   
1498          line = Form("gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1499          gROOT->ProcessLine(line);
1500          if (chain) {
1501             chain->SetProof();
1502             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1503             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1504          } else {
1505             Error("StartAnalysis", "No chain!!! Exiting.");
1506             cdir->cd();
1507             return -1;
1508          }      
1509          break;
1510       case kGridAnalysis:
1511          fIsRemote = kTRUE;
1512          if (!anaType.Contains("terminate")) {
1513             if (!fGridHandler) {
1514                Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1515                Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1516                cdir->cd();
1517                return -1;
1518             }
1519             // Write analysis manager in the analysis file
1520             cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1521             // Start the analysis via the handler
1522             if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1523                Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1524                cdir->cd();
1525                return -1;
1526             }   
1527
1528             // Terminate grid analysis
1529             if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1530             if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1531             cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1532             if (!fGridHandler->MergeOutputs()) {
1533                // Return if outputs could not be merged or if it alien handler
1534                // was configured for offline mode or local testing.
1535                cdir->cd();
1536                return 0;
1537             }
1538          }   
1539          cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1540          ImportWrappers(NULL);
1541          Terminate();
1542          cdir->cd();
1543          return 0;
1544       case kMixingAnalysis:   
1545          // Run event mixing analysis
1546          if (!fEventPool) {
1547             Error("StartAnalysis", "Cannot run event mixing without event pool");
1548             cdir->cd();
1549             return -1;
1550          }
1551          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1552          fSelector = new AliAnalysisSelector(this);
1553          while ((chain=fEventPool->GetNextChain())) {
1554             next.Reset();
1555             // Call NotifyBinChange for all tasks
1556             while ((task=(AliAnalysisTask*)next()))
1557                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1558             retv = chain->Process(fSelector);
1559             if (retv < 0) {
1560                Error("StartAnalysis", "Mixing analysis failed");
1561                cdir->cd();
1562                return retv;
1563             }   
1564          }
1565          PackOutput(fSelector->GetOutputList());
1566          Terminate();
1567    }
1568    cdir->cd();
1569    return retv;
1570 }   
1571
1572 //______________________________________________________________________________
1573 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1574 {
1575 // Start analysis for this manager on a given dataset. Analysis task can be: 
1576 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1577    if (!fInitOK) {
1578       Error("StartAnalysis","Analysis manager was not initialized !");
1579       return -1;
1580    }
1581    fIsRemote = kTRUE;
1582    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1583    TString anaType = type;
1584    anaType.ToLower();
1585    if (!anaType.Contains("proof")) {
1586       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1587       return -1;
1588    }   
1589    fMode = kProofAnalysis;
1590    TString line;
1591    SetEventLoop(kTRUE);
1592    // Set the dataset flag
1593    TObject::SetBit(kUseDataSet);
1594    fTree = 0;
1595    TChain *chain = 0;
1596    if (fGridHandler) {
1597       // Start proof analysis using the grid handler
1598       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1599          Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1600          return -1;
1601       }
1602       // Check if the plugin is in test mode
1603       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1604          dataset = "test_collection";
1605       } else {
1606          dataset = fGridHandler->GetProofDataSet();
1607       }
1608    }   
1609
1610    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1611       Error("StartAnalysis", "No PROOF!!! Exiting.");
1612       return -1;
1613    }   
1614
1615    // Initialize locally all tasks
1616    TIter next(fTasks);
1617    AliAnalysisTask *task;
1618    while ((task=(AliAnalysisTask*)next())) {
1619       task->LocalInit();
1620    }
1621    
1622    line = Form("gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1623    gROOT->ProcessLine(line);
1624    Long_t retv;
1625    if (chain) {
1626 //      chain->SetProof();
1627       cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON TEST CHAIN " << chain->GetName() << endl;
1628       retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1629    } else {   
1630       line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1631                   dataset, nentries, firstentry);
1632       cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1633       retv = (Long_t)gROOT->ProcessLine(line);
1634    }   
1635    return retv;
1636 }   
1637
1638 //______________________________________________________________________________
1639 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1640 {
1641 // Opens according the option the file specified by cont->GetFileName() and changes
1642 // current directory to cont->GetFolderName(). If the file was already opened, it
1643 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1644 // be optionally ignored.
1645   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1646   TString filename = cont->GetFileName();
1647   TFile *f = NULL;
1648   if (filename.IsNull()) {
1649     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1650     return NULL;
1651   }
1652   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1653       && !ignoreProof)
1654     f = mgr->OpenProofFile(cont,option);
1655   else {
1656     // Check first if the file is already opened
1657     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1658     if (f) {
1659       // Check if option "UPDATE" was preserved 
1660       TString opt(option);
1661       opt.ToUpper();
1662       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1663         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1664     } else {
1665       f = TFile::Open(filename, option);
1666     }    
1667   }   
1668   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1669     cont->SetFile(f);
1670     // Cd to file
1671     f->cd();
1672     // Check for a folder request
1673     TString dir = cont->GetFolderName(); 
1674     if (!dir.IsNull()) {
1675       if (!f->GetDirectory(dir)) f->mkdir(dir);
1676       f->cd(dir);
1677     }
1678     return f;
1679   }
1680   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1681   cont->SetFile(NULL);
1682   return NULL;
1683 }    
1684  
1685 //______________________________________________________________________________
1686 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
1687 {
1688 // Opens a special output file used in PROOF.
1689   TString line;
1690   TString filename = cont->GetFileName();
1691   if (cont == fCommonOutput) {
1692      if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1693      else Fatal("OpenProofFile","No output container. Exiting.");
1694   }   
1695   TFile *f = NULL;
1696   if (fMode!=kProofAnalysis || !fSelector) {
1697     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1698     return NULL;
1699   } 
1700   if (fSpecialOutputLocation.Length()) {
1701     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1702     if (f) {
1703       // Check if option "UPDATE" was preserved 
1704       TString opt(option);
1705       opt.ToUpper();
1706       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1707         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1708     } else {
1709       f = new TFile(filename, option);
1710     }
1711     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1712       cont->SetFile(f);
1713       // Cd to file
1714       f->cd();
1715       // Check for a folder request
1716       TString dir = cont->GetFolderName(); 
1717       if (dir.Length()) {
1718         if (!f->GetDirectory(dir)) f->mkdir(dir);
1719         f->cd(dir);
1720       }      
1721       return f;
1722     }
1723     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1724     cont->SetFile(NULL);
1725     return NULL;       
1726   }
1727   // Check if there is already a proof output file in the output list
1728   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1729   if (pof) {
1730     // Get the actual file
1731     line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1732     filename = (const char*)gROOT->ProcessLine(line);
1733     if (fDebug>1) {
1734       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1735     }  
1736     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1737     if (!f) {
1738        Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1739        return NULL;
1740     }   
1741     // Check if option "UPDATE" was preserved 
1742     TString opt(option);
1743     opt.ToUpper();
1744     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1745       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1746   } else {
1747     if (cont->IsRegisterDataset()) {
1748       TString dsetName = filename;
1749       dsetName.ReplaceAll(".root", cont->GetTitle());
1750       dsetName.ReplaceAll(":","_");
1751       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1752       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1753     } else {
1754       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1755       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1756     }
1757     if (fDebug > 1) printf("=== %s\n", line.Data());
1758     gROOT->ProcessLine(line);
1759     line = Form("pf->OpenFile(\"%s\");", option);
1760     gROOT->ProcessLine(line);
1761     f = gFile;
1762     if (fDebug > 1) {
1763       gROOT->ProcessLine("pf->Print()");
1764       printf(" == proof file name: %s", f->GetName());
1765     }   
1766     // Add to proof output list
1767     line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1768     if (fDebug > 1) printf("=== %s\n", line.Data());
1769     gROOT->ProcessLine(line);
1770   }
1771   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1772     cont->SetFile(f);
1773     // Cd to file
1774     f->cd();
1775     // Check for a folder request
1776     TString dir = cont->GetFolderName(); 
1777     if (!dir.IsNull()) {
1778       if (!f->GetDirectory(dir)) f->mkdir(dir);
1779       f->cd(dir);
1780     }
1781     return f;
1782   }
1783   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1784   cont->SetFile(NULL);  
1785   return NULL;
1786 }   
1787
1788 //______________________________________________________________________________
1789 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1790 {
1791 // Execute analysis.
1792    static Long64_t ncalls = 0;
1793    static Long64_t nentries = 0;
1794    static TTree *lastTree = 0;
1795    static TStopwatch *timer = new TStopwatch();
1796    if (fDebug > 0) printf("MGR: Processing event #%lld\n", ncalls);
1797    else {
1798       if (fTree && (fTree != lastTree)) {
1799          nentries += fTree->GetEntries();
1800          lastTree = fTree;
1801       }   
1802       if (!ncalls) timer->Start();
1803       if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", ncalls, nentries, timer, kFALSE);
1804    }
1805    gROOT->cd();
1806    TDirectory *cdir = gDirectory;
1807    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1808    if (getsysInfo && ((ncalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)ncalls);
1809    ncalls++;
1810    if (!fInitOK) {
1811       Error("ExecAnalysis", "Analysis manager was not initialized !");
1812       cdir->cd();
1813       return;
1814    }
1815    AliAnalysisTask *task;
1816    // Check if the top tree is active.
1817    if (fTree) {
1818       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1819          AliSysInfo::AddStamp("Handlers_BeginEventGroup",(Int_t)ncalls, 1002, 0);
1820       TIter next(fTasks);
1821    // De-activate all tasks
1822       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1823       AliAnalysisDataContainer *cont = fCommonInput;
1824       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1825       if (!cont) {
1826               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1827          cdir->cd();
1828          return;
1829       }   
1830       cont->SetData(fTree); // This will notify all consumers
1831       Long64_t entry = fTree->GetTree()->GetReadEntry();      
1832 //
1833 //    Call BeginEvent() for optional input/output and MC services 
1834       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1835       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1836       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1837       gROOT->cd();
1838       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1839          AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
1840 //
1841 //    Execute the tasks
1842 //      TIter next1(cont->GetConsumers());
1843       TIter next1(fTopTasks);
1844       Int_t itask = 0;
1845       while ((task=(AliAnalysisTask*)next1())) {
1846          if (fDebug >1) {
1847             cout << "    Executing task " << task->GetName() << endl;
1848          }       
1849          task->ExecuteTask(option);
1850          gROOT->cd();
1851          if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1852             AliSysInfo::AddStamp(task->ClassName(),(Int_t)ncalls, itask, 1);
1853          itask++;   
1854       }
1855 //
1856 //    Call FinishEvent() for optional output and MC services 
1857       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1858       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1859       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1860       // Gather system information if requested
1861       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1862          AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1001, 1);
1863       cdir->cd();   
1864       return;
1865    }   
1866    // The event loop is not controlled by TSelector   
1867 //
1868 //  Call BeginEvent() for optional input/output and MC services 
1869    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1870    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1871    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1872    gROOT->cd();
1873    if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1874       AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
1875    TIter next2(fTopTasks);
1876    while ((task=(AliAnalysisTask*)next2())) {
1877       task->SetActive(kTRUE);
1878       if (fDebug > 1) {
1879          cout << "    Executing task " << task->GetName() << endl;
1880       }   
1881       task->ExecuteTask(option);
1882       gROOT->cd();
1883    }   
1884 //
1885 // Call FinishEvent() for optional output and MC services 
1886    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1887    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1888    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1889    if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1890       AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1);
1891    cdir->cd();   
1892 }
1893
1894 //______________________________________________________________________________
1895 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
1896 {
1897 // Set the input event handler and create a container for it.
1898    fInputEventHandler   = handler;
1899    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1900 //   Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1901 }
1902
1903 //______________________________________________________________________________
1904 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
1905 {
1906 // Set the input event handler and create a container for it.
1907    fOutputEventHandler   = handler;
1908    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1909    fCommonOutput->SetSpecialOutput();
1910 //   Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1911 }
1912
1913 //______________________________________________________________________________
1914 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1915 {
1916 // This method is used externally to register output files which are not
1917 // connected to any output container, so that the manager can properly register,
1918 // retrieve or merge them when running in distributed mode. The file names are
1919 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1920    if (fExtraFiles.Contains(fname)) return;
1921    if (fExtraFiles.Length()) fExtraFiles += " ";
1922    fExtraFiles += fname;
1923 }
1924
1925 //______________________________________________________________________________
1926 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
1927 {
1928 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1929    char fullPath[512];
1930    char chUrl[512];
1931    TObject *pof =  source->FindObject(filename);
1932    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1933       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1934       return kFALSE;
1935    }
1936    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", (ULong_t)fullPath, (ULong_t)pof));
1937    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", (ULong_t)chUrl));
1938    TString clientUrl(chUrl);
1939    TString fullPath_str(fullPath);
1940    if (clientUrl.Contains("localhost")){
1941       TObjArray* array = fullPath_str.Tokenize ( "//" );
1942       TObjString *strobj = ( TObjString *)array->At(1);
1943       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1944       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1945       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1946       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1947       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
1948       delete arrayPort;
1949       delete array;
1950    }
1951    if (fDebug > 1) 
1952       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", fullPath_str.Data());
1953    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
1954    if (!gotit)
1955       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1956    return gotit;
1957 }
1958
1959 //______________________________________________________________________________
1960 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1961 {
1962 // Fill analysis type in the provided string.
1963    switch (fMode) {
1964       case kLocalAnalysis:
1965          type = "local";
1966          return;
1967       case kProofAnalysis:
1968          type = "proof";
1969          return;
1970       case kGridAnalysis:
1971          type = "grid";
1972          return;
1973       case kMixingAnalysis:
1974          type = "mix";
1975    }
1976 }
1977
1978 //______________________________________________________________________________
1979 Bool_t AliAnalysisManager::ValidateOutputFiles() const
1980 {
1981 // Validate all output files.
1982    TIter next(fOutputs);
1983    AliAnalysisDataContainer *output;
1984    TDirectory *cdir = gDirectory;
1985    TString openedFiles;
1986    while ((output=(AliAnalysisDataContainer*)next())) {
1987       if (output->IsRegisterDataset()) continue;
1988       TString filename = output->GetFileName();
1989       if (filename == "default") {
1990          if (!fOutputEventHandler) continue;
1991          filename = fOutputEventHandler->GetOutputFileName();
1992          // Main AOD may not be there
1993          if (gSystem->AccessPathName(filename)) continue;
1994       }
1995       // Check if the file is closed
1996       if (openedFiles.Contains(filename)) continue;;
1997       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1998       if (file) {
1999          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2000          // Clear file list to release object ownership to user.
2001 //         file->Clear();
2002          file->Close();
2003       }
2004       file = TFile::Open(filename);
2005       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2006          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2007          cdir->cd();
2008          return kFALSE;
2009       }
2010       file->Close();
2011       openedFiles += filename;
2012       openedFiles += " ";
2013    }
2014    cdir->cd();
2015    return kTRUE;
2016 }   
2017
2018 //______________________________________________________________________________
2019 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2020 {
2021 // Implements a nice text mode progress bar.
2022    static Long64_t icount = 0;
2023    static TString oname;
2024    static TString nname;
2025    static Long64_t ocurrent = 0;
2026    static Long64_t osize = 0;
2027    static Int_t oseconds = 0;
2028    static TStopwatch *owatch = 0;
2029    static Bool_t oneoftwo = kFALSE;
2030    static Int_t nrefresh = 0;
2031    static Int_t nchecks = 0;
2032    const char symbol[4] = {'=','\\','|','/'}; 
2033    char progress[11] = "          ";
2034    Int_t ichar = icount%4;
2035    
2036    if (!refresh) {
2037       nrefresh = 0;
2038       if (!size) return;
2039       owatch = watch;
2040       oname = opname;
2041       ocurrent = TMath::Abs(current);
2042       osize = TMath::Abs(size);
2043       if (ocurrent > osize) ocurrent=osize;
2044    } else {
2045       nrefresh++;
2046       if (!osize) return;
2047    }     
2048    icount++;
2049    Double_t time = 0.;
2050    Int_t hours = 0;
2051    Int_t minutes = 0;
2052    Int_t seconds = 0;
2053    if (owatch && !last) {
2054       owatch->Stop();
2055       time = owatch->RealTime();
2056       hours = (Int_t)(time/3600.);
2057       time -= 3600*hours;
2058       minutes = (Int_t)(time/60.);
2059       time -= 60*minutes;
2060       seconds = (Int_t)time;
2061       if (refresh)  {
2062          if (oseconds==seconds) {
2063             owatch->Continue();
2064             return;
2065          }
2066          oneoftwo = !oneoftwo;   
2067       }
2068       oseconds = seconds;   
2069    }
2070    if (refresh && oneoftwo) {
2071       nname = oname;
2072       if (nchecks <= 0) nchecks = nrefresh+1;
2073       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2074       oname = Form("     == %d%% ==", pctdone);
2075    }         
2076    Double_t percent = 100.0*ocurrent/osize;
2077    Int_t nchar = Int_t(percent/10);
2078    if (nchar>10) nchar=10;
2079    Int_t i;
2080    for (i=0; i<nchar; i++)  progress[i] = '=';
2081    progress[nchar] = symbol[ichar];
2082    for (i=nchar+1; i<10; i++) progress[i] = ' ';
2083    progress[10] = '\0';
2084    oname += "                    ";
2085    oname.Remove(20);
2086    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2087    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2088    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2089    if (time>0.) fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d             \r", percent, hours, minutes, seconds);
2090    else fprintf(stderr, "[%6.2f %%]\r", percent);
2091    if (refresh && oneoftwo) oname = nname;
2092    if (owatch) owatch->Continue();
2093    if (last) {
2094       icount = 0;
2095       owatch = 0;
2096       ocurrent = 0;
2097       osize = 0;
2098       oseconds = 0;
2099       oneoftwo = kFALSE;
2100       nrefresh = 0;
2101       fprintf(stderr, "\n");
2102    }   
2103 }
2104
2105 //______________________________________________________________________________
2106 void AliAnalysisManager::DoLoadBranch(const char *name) 
2107 {
2108   // Get tree and load branch if needed.
2109
2110   if (!fTree)
2111     return;
2112
2113   TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2114   if (!br) {
2115     br = fTree->GetBranch(name);
2116     if (!br) {
2117       Error("DoLoadBranch", "Could not find branch %s",name);
2118       return;
2119     }
2120     fTable.Add(br);
2121   }
2122   if (br->GetReadEntry()==GetCurrentEntry())
2123     return;
2124   br->GetEntry(GetCurrentEntry());
2125 }