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