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