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