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