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