]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Added support for retrieving and merging dAOD's. The producer task has to call AliAna...
[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 <TClass.h>
31 #include <TFile.h>
32 #include <TKey.h>
33 #include <TMethodCall.h>
34 #include <TChain.h>
35 #include <TSystem.h>
36 #include <TROOT.h>
37 #include <TCanvas.h>
38
39 #include "AliAnalysisSelector.h"
40 #include "AliAnalysisGrid.h"
41 #include "AliAnalysisTask.h"
42 #include "AliAnalysisDataContainer.h"
43 #include "AliAnalysisDataSlot.h"
44 #include "AliVEventHandler.h"
45 #include "AliVEventPool.h"
46 #include "AliSysInfo.h"
47 #include "AliAnalysisManager.h"
48
49 ClassImp(AliAnalysisManager)
50
51 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
52
53 //______________________________________________________________________________
54 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
55                    :TNamed(name,title),
56                     fTree(NULL),
57                     fInputEventHandler(NULL),
58                     fOutputEventHandler(NULL),
59                     fMCtruthEventHandler(NULL),
60                     fEventPool(NULL),
61                     fCurrentEntry(-1),
62                     fNSysInfo(0),
63                     fMode(kLocalAnalysis),
64                     fInitOK(kFALSE),
65                     fDebug(0),
66                     fSpecialOutputLocation(""), 
67                     fTasks(NULL),
68                     fTopTasks(NULL),
69                     fZombies(NULL),
70                     fContainers(NULL),
71                     fInputs(NULL),
72                     fOutputs(NULL),
73                     fCommonInput(NULL),
74                     fCommonOutput(NULL),
75                     fSelector(NULL),
76                     fGridHandler(NULL),
77                     fExtraFiles("")
78 {
79 // Default constructor.
80    fgAnalysisManager = this;
81    fTasks      = new TObjArray();
82    fTopTasks   = new TObjArray();
83    fZombies    = new TObjArray();
84    fContainers = new TObjArray();
85    fInputs     = new TObjArray();
86    fOutputs    = new TObjArray();
87    SetEventLoop(kTRUE);
88 }
89
90 //______________________________________________________________________________
91 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
92                    :TNamed(other),
93                     fTree(NULL),
94                     fInputEventHandler(NULL),
95                     fOutputEventHandler(NULL),
96                     fMCtruthEventHandler(NULL),
97                     fEventPool(NULL),
98                     fCurrentEntry(-1),
99                     fNSysInfo(0),
100                     fMode(other.fMode),
101                     fInitOK(other.fInitOK),
102                     fDebug(other.fDebug),
103                     fSpecialOutputLocation(""), 
104                     fTasks(NULL),
105                     fTopTasks(NULL),
106                     fZombies(NULL),
107                     fContainers(NULL),
108                     fInputs(NULL),
109                     fOutputs(NULL),
110                     fCommonInput(NULL),
111                     fCommonOutput(NULL),
112                     fSelector(NULL),
113                     fGridHandler(NULL),
114                     fExtraFiles()
115 {
116 // Copy constructor.
117    fTasks      = new TObjArray(*other.fTasks);
118    fTopTasks   = new TObjArray(*other.fTopTasks);
119    fZombies    = new TObjArray(*other.fZombies);
120    fContainers = new TObjArray(*other.fContainers);
121    fInputs     = new TObjArray(*other.fInputs);
122    fOutputs    = new TObjArray(*other.fOutputs);
123    fgAnalysisManager = this;
124 }
125    
126 //______________________________________________________________________________
127 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
128 {
129 // Assignment
130    if (&other != this) {
131       TNamed::operator=(other);
132       fInputEventHandler   = other.fInputEventHandler;
133       fOutputEventHandler  = other.fOutputEventHandler;
134       fMCtruthEventHandler = other.fMCtruthEventHandler;
135       fEventPool           = other.fEventPool;
136       fTree       = NULL;
137       fCurrentEntry = -1;
138       fNSysInfo   = other.fNSysInfo;
139       fMode       = other.fMode;
140       fInitOK     = other.fInitOK;
141       fDebug      = other.fDebug;
142       fTasks      = new TObjArray(*other.fTasks);
143       fTopTasks   = new TObjArray(*other.fTopTasks);
144       fZombies    = new TObjArray(*other.fZombies);
145       fContainers = new TObjArray(*other.fContainers);
146       fInputs     = new TObjArray(*other.fInputs);
147       fOutputs    = new TObjArray(*other.fOutputs);
148       fCommonInput = NULL;
149       fCommonOutput = NULL;
150       fSelector   = NULL;
151       fGridHandler = NULL;
152       fExtraFiles = other.fExtraFiles;
153       fgAnalysisManager = this;
154    }
155    return *this;
156 }
157
158 //______________________________________________________________________________
159 AliAnalysisManager::~AliAnalysisManager()
160 {
161 // Destructor.
162    if (fTasks) {fTasks->Delete(); delete fTasks;}
163    if (fTopTasks) delete fTopTasks;
164    if (fZombies) delete fZombies;
165    if (fContainers) {fContainers->Delete(); delete fContainers;}
166    if (fInputs) delete fInputs;
167    if (fOutputs) delete fOutputs;
168    if (fGridHandler) delete fGridHandler;
169    if (fgAnalysisManager==this) fgAnalysisManager = NULL;
170 }
171
172 //______________________________________________________________________________
173 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
174 {
175 // Read one entry of the tree or a whole branch.
176    if (fDebug > 0) printf("== AliAnalysisManager::GetEntry(%lld)\n", entry);
177    fCurrentEntry = entry;
178    return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
179 }
180    
181 //______________________________________________________________________________
182 Bool_t AliAnalysisManager::Init(TTree *tree)
183 {
184   // The Init() function is called when the selector needs to initialize
185   // a new tree or chain. Typically here the branch addresses of the tree
186   // will be set. It is normaly not necessary to make changes to the
187   // generated code, but the routine can be extended by the user if needed.
188   // Init() will be called many times when running with PROOF.
189    Bool_t init = kFALSE;
190    if (!tree) return kFALSE; // Should not happen - protected in selector caller
191    if (fDebug > 0) {
192       printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
193    }
194    // Call InitTree of EventHandler
195    if (fOutputEventHandler) {
196       if (fMode == kProofAnalysis) {
197          init = fOutputEventHandler->Init(0x0, "proof");
198       } else {
199          init = fOutputEventHandler->Init(0x0, "local");
200       }
201       if (!init) {
202          Error("Init", "Output event handler failed to initialize");
203          return kFALSE;
204       }         
205    }
206    
207    if (fInputEventHandler) {
208       if (fMode == kProofAnalysis) {
209          init = fInputEventHandler->Init(tree, "proof");
210       } else {
211          init = fInputEventHandler->Init(tree, "local");
212       }
213       if (!init) {
214          Error("Init", "Input event handler failed to initialize tree"); 
215          return kFALSE;
216       }         
217    } else {
218       // If no input event handler we need to get the tree once
219       // for the chain
220       if(!tree->GetTree()) {
221          Long64_t readEntry = tree->LoadTree(0);
222          if (readEntry == -2) {
223             Error("Init", "Input tree has no entry. Aborting");
224             return kFALSE;
225          }
226       }   
227    }
228
229    if (fMCtruthEventHandler) {
230       if (fMode == kProofAnalysis) {
231          init = fMCtruthEventHandler->Init(0x0, "proof");
232       } else {
233          init = fMCtruthEventHandler->Init(0x0, "local");
234       }
235       if (!init) {
236          Error("Init", "MC event handler failed to initialize"); 
237          return kFALSE;
238       }         
239    }
240
241    if (!fInitOK) InitAnalysis();
242    if (!fInitOK) return kFALSE;
243    fTree = tree;
244    AliAnalysisDataContainer *top = fCommonInput;
245    if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
246    if (!top) {
247       Error("Init","No top input container !");
248       return kFALSE;
249    }
250    top->SetData(tree);
251    if (fDebug > 0) {
252       printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
253    }
254    return kTRUE;
255 }
256
257 //______________________________________________________________________________
258 void AliAnalysisManager::SlaveBegin(TTree *tree)
259 {
260   // The SlaveBegin() function is called after the Begin() function.
261   // When running with PROOF SlaveBegin() is called on each slave server.
262   // The tree argument is deprecated (on PROOF 0 is passed).
263    if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
264    static Bool_t isCalled = kFALSE;
265    Bool_t init = kFALSE;
266    Bool_t initOK = kTRUE;
267    TString msg;
268    TDirectory *curdir = gDirectory;
269    // Call SlaveBegin only once in case of mixing
270    if (isCalled && fMode==kMixingAnalysis) return;
271    // Call Init of EventHandler
272    if (fOutputEventHandler) {
273       if (fMode == kProofAnalysis) {
274          // Merging AOD's in PROOF via TProofOutputFile
275          if (fDebug > 1) printf("   Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
276          init = fOutputEventHandler->Init("proof");
277          if (!init) msg = "Failed to initialize output handler on worker";
278       } else {
279          init = fOutputEventHandler->Init("local");
280          if (!init) msg = "Failed to initialize output handler";
281       }
282       initOK &= init;
283       if (!fSelector) Error("SlaveBegin", "Selector not set");
284       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
285    }
286
287    if (fInputEventHandler) {
288       fInputEventHandler->SetInputTree(tree);
289       if (fMode == kProofAnalysis) {
290          init = fInputEventHandler->Init("proof");
291          if (!init) msg = "Failed to initialize input handler on worker";
292       } else {
293          init = fInputEventHandler->Init("local");
294          if (!init) msg = "Failed to initialize input handler";
295       }
296       initOK &= init;
297       if (!fSelector) Error("SlaveBegin", "Selector not set");      
298       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
299    }
300
301    if (fMCtruthEventHandler) {
302       if (fMode == kProofAnalysis) {
303          init = fMCtruthEventHandler->Init("proof");
304          if (!init) msg = "Failed to initialize MC handler on worker";
305       } else {
306          init = fMCtruthEventHandler->Init("local");
307          if (!init) msg = "Failed to initialize MC handler";
308       }
309       initOK &= init;
310       if (!fSelector) Error("SlaveBegin", "Selector not set");      
311       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
312    }
313    if (curdir) curdir->cd();
314    isCalled = kTRUE;
315    if (!initOK) return;   
316    TIter next(fTasks);
317    AliAnalysisTask *task;
318    // Call CreateOutputObjects for all tasks
319    while ((task=(AliAnalysisTask*)next())) {
320       curdir = gDirectory;
321       task->CreateOutputObjects();
322       if (curdir) curdir->cd();
323    }
324    if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
325 }
326
327 //______________________________________________________________________________
328 Bool_t AliAnalysisManager::Notify()
329 {
330    // The Notify() function is called when a new file is opened. This
331    // can be either for a new TTree in a TChain or when when a new TTree
332    // is started when using PROOF. It is normaly not necessary to make changes
333    // to the generated code, but the routine can be extended by the
334    // user if needed. The return value is currently not used.
335    if (!fTree) return kFALSE;
336
337    TFile *curfile = fTree->GetCurrentFile();
338    if (!curfile) {
339       Error("Notify","No current file");
340       return kFALSE;
341    }   
342    
343    if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
344    TIter next(fTasks);
345    AliAnalysisTask *task;
346    // Call Notify for all tasks
347    while ((task=(AliAnalysisTask*)next())) 
348       task->Notify();
349         
350    // Call Notify of the event handlers
351    if (fInputEventHandler) {
352        fInputEventHandler->Notify(curfile->GetName());
353    }
354
355    if (fOutputEventHandler) {
356        fOutputEventHandler->Notify(curfile->GetName());
357    }
358
359    if (fMCtruthEventHandler) {
360        fMCtruthEventHandler->Notify(curfile->GetName());
361    }
362    if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
363    return kTRUE;
364 }    
365
366 //______________________________________________________________________________
367 Bool_t AliAnalysisManager::Process(Long64_t entry)
368 {
369   // The Process() function is called for each entry in the tree (or possibly
370   // keyed object in the case of PROOF) to be processed. The entry argument
371   // specifies which entry in the currently loaded tree is to be processed.
372   // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
373   // to read either all or the required parts of the data. When processing
374   // keyed objects with PROOF, the object is already loaded and is available
375   // via the fObject pointer.
376   //
377   // This function should contain the "body" of the analysis. It can contain
378   // simple or elaborate selection criteria, run algorithms on the data
379   // of the event and typically fill histograms.
380
381   // WARNING when a selector is used with a TChain, you must use
382   //  the pointer to the current TTree to call GetEntry(entry).
383   //  The entry is always the local entry number in the current tree.
384   //  Assuming that fChain is the pointer to the TChain being processed,
385   //  use fChain->GetTree()->GetEntry(entry).
386    if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
387
388    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
389    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
390    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
391    
392    GetEntry(entry);
393    ExecAnalysis();
394    if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
395    return kTRUE;
396 }
397
398 //______________________________________________________________________________
399 void AliAnalysisManager::PackOutput(TList *target)
400 {
401   // Pack all output data containers in the output list. Called at SlaveTerminate
402   // stage in PROOF case for each slave.
403    if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
404    if (!target) {
405       Error("PackOutput", "No target. Aborting.");
406       return;
407    }
408    if (fInputEventHandler)   fInputEventHandler  ->Terminate();
409    if (fOutputEventHandler)  fOutputEventHandler ->Terminate();
410    if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
411
412    // Call FinishTaskOutput() for each event loop task (not called for 
413    // post-event loop tasks - use Terminate() fo those)
414    TIter nexttask(fTasks);
415    AliAnalysisTask *task;
416    while ((task=(AliAnalysisTask*)nexttask())) {
417       if (!task->IsPostEventLoop()) {
418          if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
419          task->FinishTaskOutput();
420          if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
421       }
422    }      
423    
424    if (fMode == kProofAnalysis) {
425       TIter next(fOutputs);
426       AliAnalysisDataContainer *output;
427       Bool_t isManagedByHandler = kFALSE;
428       while ((output=(AliAnalysisDataContainer*)next())) {
429          // Do not consider outputs of post event loop tasks
430          isManagedByHandler = kFALSE;
431          if (output->GetProducer()->IsPostEventLoop()) continue;
432          const char *filename = output->GetFileName();
433          if (!(strcmp(filename, "default")) && fOutputEventHandler) {
434             isManagedByHandler = kTRUE;
435             filename = fOutputEventHandler->GetOutputFileName();
436          }
437          // Check if data was posted to this container. If not, issue an error.
438          if (!output->GetData() && !isManagedByHandler) {
439             Error("PackOutput", "No data for output container %s. Forgot to PostData ?\n", output->GetName());
440             continue;
441          }   
442          if (!output->IsSpecialOutput()) {
443             // Normal outputs
444             if (strlen(filename) && !isManagedByHandler) {
445                // File resident outputs
446                TFile *file = output->GetFile();
447                // Backup current folder
448                TDirectory *opwd = gDirectory;
449                // Create file if not existing and register to container.
450                if (file) file->cd();
451                else      file = new TFile(filename, "RECREATE"); 
452                if (file->IsZombie()) {
453                   Fatal("PackOutput", "Could not recreate file %s\n", filename);
454                   return;
455                }   
456                output->SetFile(file);
457                // Clear file list to release object ownership to user.
458                file->Clear();
459                // Save data to file, then close.
460                if (output->GetData()->InheritsFrom(TCollection::Class())) {
461                   // If data is a collection, we set the name of the collection 
462                   // as the one of the container and we save as a single key.
463                   TCollection *coll = (TCollection*)output->GetData();
464                   coll->SetName(output->GetName());
465                   coll->Write(output->GetName(), TObject::kSingleKey);
466                } else {
467                   if (output->GetData()->InheritsFrom(TTree::Class())) {
468                      TTree *tree = (TTree*)output->GetData();
469                      tree->SetDirectory(file);
470                      tree->AutoSave();
471                   } else {
472                      output->GetData()->Write();
473                   }   
474                }      
475                if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
476                if (fDebug > 2) {
477                   printf("   file %s listing content:\n", filename);
478                   file->ls();
479                }   
480                file->Close();
481                // Restore current directory
482                if (opwd) opwd->cd();
483             } else {
484                // Memory-resident outputs   
485                if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
486             }   
487             AliAnalysisDataWrapper *wrap = 0;
488             if (isManagedByHandler) {
489                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
490                wrap->SetName(output->GetName());
491             }   
492             else                    wrap =output->ExportData();
493             // Output wrappers must NOT delete data after merging - the user owns them
494             wrap->SetDeleteData(kFALSE);
495             target->Add(wrap);
496          } else {
497          // Special outputs
498             TDirectory *opwd = gDirectory;
499             TFile *file = output->GetFile();
500             if (fDebug > 1 && file) printf("PackOutput %s: file merge, special output\n", output->GetName());
501             if (isManagedByHandler) {
502                // Terminate IO for files managed by the output handler
503                if (file) file->Write();
504                if (file && fDebug > 2) {
505                   printf("   handled file %s listing content:\n", file->GetName());
506                   file->ls();
507                }   
508                fOutputEventHandler->TerminateIO();
509                continue;
510             }   
511             
512             if (!file) {
513                AliAnalysisTask *producer = output->GetProducer();
514                Error("PackOutput", 
515                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
516                      output->GetFileName(), output->GetName(), producer->ClassName());
517                continue;
518             }   
519             file->cd();
520             // Release object ownership to users after writing data to file
521             if (output->GetData()->InheritsFrom(TCollection::Class())) {
522                // If data is a collection, we set the name of the collection 
523                // as the one of the container and we save as a single key.
524                TCollection *coll = (TCollection*)output->GetData();
525                coll->SetName(output->GetName());
526                coll->Write(output->GetName(), TObject::kSingleKey);
527             } else {
528                if (output->GetData()->InheritsFrom(TTree::Class())) {
529                   TTree *tree = (TTree*)output->GetData();
530                   tree->SetDirectory(file);
531                   tree->AutoSave();
532                } else {
533                   output->GetData()->Write();
534                }   
535             }      
536             file->Clear();
537             if (fDebug > 2) {
538                printf("   file %s listing content:\n", output->GetFileName());
539                file->ls();
540             }
541             TString outFilename = file->GetName();
542             file->Close();
543             // Restore current directory
544             if (opwd) opwd->cd();
545             // Check if a special output location was provided or the output files have to be merged
546             if (strlen(fSpecialOutputLocation.Data())) {
547                TString remote = fSpecialOutputLocation;
548                remote += "/";
549                Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
550                remote += Form("%s_%d_", gSystem->HostName(), gid);
551                remote += output->GetFileName();
552                TFile::Cp ( outFilename.Data(), remote.Data() );
553             } else {
554             // No special location specified-> use TProofOutputFile as merging utility
555             // The file at this output slot must be opened in CreateOutputObjects
556                if (fDebug > 1) printf("   File %s to be merged...\n", output->GetFileName());
557             }
558          }      
559       }
560    } 
561    if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
562 }
563
564 //______________________________________________________________________________
565 void AliAnalysisManager::ImportWrappers(TList *source)
566 {
567 // Import data in output containers from wrappers coming in source.
568    if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
569    TIter next(fOutputs);
570    AliAnalysisDataContainer *cont;
571    AliAnalysisDataWrapper   *wrap;
572    Int_t icont = 0;
573    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
574    while ((cont=(AliAnalysisDataContainer*)next())) {
575       wrap = 0;
576       if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
577       const char *filename = cont->GetFileName();
578       Bool_t isManagedByHandler = kFALSE;
579       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
580          isManagedByHandler = kTRUE;
581          filename = fOutputEventHandler->GetOutputFileName();
582       }
583       if (cont->IsSpecialOutput() || inGrid) {
584          if (strlen(fSpecialOutputLocation.Data()) && !isManagedByHandler) continue;
585          // Copy merged file from PROOF scratch space. 
586          // In case of grid the files are already in the current directory.
587          if (!inGrid) {
588             if (isManagedByHandler && fExtraFiles.Length()) {
589                // Copy extra registered dAOD files.
590                TObjArray *arr = fExtraFiles.Tokenize(" ");
591                TObjString *os;
592                TIter nextfilename(arr);
593                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
594                delete arr;
595             }
596             if (!GetFileFromWrapper(filename, source)) continue;
597          }   
598          // Normally we should connect data from the copied file to the
599          // corresponding output container, but it is not obvious how to do this
600          // automatically if several objects in file...
601          TFile *f = TFile::Open(filename, "READ");
602          if (!f) {
603             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
604             continue;
605          }   
606          TObject *obj = 0;
607          // Try to fetch first a list object having the container name.
608          obj = f->Get(cont->GetName());
609          if (!obj) {
610          // Fetch first object from file having the container type.
611             TIter nextkey(f->GetListOfKeys());
612             TKey *key;
613             while ((key=(TKey*)nextkey())) {
614                obj = f->Get(key->GetName());
615                if (obj && obj->IsA()->InheritsFrom(cont->GetType())) break;
616             }                     
617          }
618          if (!obj) {
619             Error("ImportWrappers", "Could not find object for container %s in file %s", cont->GetName(), filename);
620             continue;
621          }  
622          wrap = new AliAnalysisDataWrapper(obj);
623          wrap->SetDeleteData(kFALSE);
624       }   
625       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
626       if (!wrap) {
627          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
628          continue;
629       }
630       icont++;
631       if (fDebug > 1) {
632          printf("   Importing data for container %s", cont->GetName());
633          if (strlen(filename)) printf("    -> file %s\n", filename);
634          else printf("\n");
635       }   
636       cont->ImportData(wrap);
637    }         
638    if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
639 }
640
641 //______________________________________________________________________________
642 void AliAnalysisManager::UnpackOutput(TList *source)
643 {
644   // Called by AliAnalysisSelector::Terminate only on the client.
645    if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
646    if (!source) {
647       Error("UnpackOutput", "No target. Aborting.");
648       return;
649    }
650    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
651
652    if (fMode == kProofAnalysis) ImportWrappers(source);
653
654    TIter next(fOutputs);
655    AliAnalysisDataContainer *output;
656    while ((output=(AliAnalysisDataContainer*)next())) {
657       if (!output->GetData()) continue;
658       // Check if there are client tasks that run post event loop
659       if (output->HasConsumers()) {
660          // Disable event loop semaphore
661          output->SetPostEventLoop(kTRUE);
662          TObjArray *list = output->GetConsumers();
663          Int_t ncons = list->GetEntriesFast();
664          for (Int_t i=0; i<ncons; i++) {
665             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
666             task->CheckNotify(kTRUE);
667             // If task is active, execute it
668             if (task->IsPostEventLoop() && task->IsActive()) {
669                if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
670                task->ExecuteTask();
671             }   
672          }
673       }   
674    }
675    if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
676 }
677
678 //______________________________________________________________________________
679 void AliAnalysisManager::Terminate()
680 {
681   // The Terminate() function is the last function to be called during
682   // a query. It always runs on the client, it can be used to present
683   // the results graphically.
684    if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
685    AliAnalysisTask *task;
686    TIter next(fTasks);
687    // Call Terminate() for tasks
688    while ((task=(AliAnalysisTask*)next())) task->Terminate();
689    //
690    TIter next1(fOutputs);
691    AliAnalysisDataContainer *output;
692    while ((output=(AliAnalysisDataContainer*)next1())) {
693       // Special outputs or grid files have the files already closed and written.
694       if (fMode == kGridAnalysis) continue;
695       if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
696       const char *filename = output->GetFileName();
697       if (!(strcmp(filename, "default"))) {
698          if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
699          TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
700          if (aodfile) {
701             if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
702             aodfile->Write();
703             continue;
704          }   
705       }      
706       if (!strlen(filename)) continue;
707       if (!output->GetData()) continue;
708       TFile *file = output->GetFile();
709       TDirectory *opwd = gDirectory;
710       file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
711       if (!file) file = new TFile(filename, "RECREATE");
712       if (file->IsZombie()) continue;
713       output->SetFile(file);
714       file->cd();
715       if (fDebug > 1) printf("   writing output data %s to file %s\n", output->GetData()->GetName(), file->GetName());
716       if (output->GetData()->InheritsFrom(TCollection::Class())) {
717       // If data is a collection, we set the name of the collection 
718       // as the one of the container and we save as a single key.
719          TCollection *coll = (TCollection*)output->GetData();
720          coll->SetName(output->GetName());
721          coll->Write(output->GetName(), TObject::kSingleKey);
722       } else {
723          if (output->GetData()->InheritsFrom(TTree::Class())) {
724             TTree *tree = (TTree*)output->GetData();
725             tree->SetDirectory(file);
726             tree->AutoSave();
727          } else {
728             output->GetData()->Write();
729          }   
730       }      
731       if (opwd) opwd->cd();
732    }   
733    next1.Reset();
734    while ((output=(AliAnalysisDataContainer*)next1())) {
735       // Close all files at output
736       TDirectory *opwd = gDirectory;
737       if (output->GetFile()) output->GetFile()->Close();
738       if (opwd) opwd->cd();
739    }   
740
741    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
742    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
743    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
744
745    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
746    if (getsysInfo) {
747       TDirectory *cdir = gDirectory;
748       TFile f("syswatch.root", "RECREATE");
749       if (!f.IsZombie()) {
750          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
751          tree->SetMarkerStyle(kCircle);
752          tree->SetMarkerColor(kBlue);
753          tree->SetMarkerSize(0.5);
754          if (!gROOT->IsBatch()) {
755             tree->SetAlias("event", "id0");
756             tree->SetAlias("memUSED", "mi.fMemUsed");
757             new TCanvas("SysInfo","SysInfo",10,10,800,600);
758             tree->Draw("memUSED:event","","", 1234567890, 0);
759          }   
760          tree->Write();
761          f.Close();
762          delete tree;
763       }
764       if (cdir) cdir->cd();
765    }      
766    if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
767 }
768
769 //______________________________________________________________________________
770 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
771 {
772 // Adds a user task to the global list of tasks.
773    if (fTasks->FindObject(task)) {
774       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
775       return;
776    }   
777    task->SetActive(kFALSE);
778    fTasks->Add(task);
779 }  
780
781 //______________________________________________________________________________
782 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
783 {
784 // Retreive task by name.
785    if (!fTasks) return NULL;
786    return (AliAnalysisTask*)fTasks->FindObject(name);
787 }
788
789 //______________________________________________________________________________
790 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
791                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
792 {
793 // Create a data container of a certain type. Types can be:
794 //   kExchangeContainer  = 0, used to exchange date between tasks
795 //   kInputContainer   = 1, used to store input data
796 //   kOutputContainer  = 2, used for posting results
797    if (fContainers->FindObject(name)) {
798       Error("CreateContainer","A container named %s already defined !\n",name);
799       return NULL;
800    }   
801    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
802    fContainers->Add(cont);
803    switch (type) {
804       case kInputContainer:
805          fInputs->Add(cont);
806          break;
807       case kOutputContainer:
808          fOutputs->Add(cont);
809          if (filename && strlen(filename)) {
810             cont->SetFileName(filename);
811             cont->SetDataOwned(kFALSE);  // data owned by the file
812          }   
813          break;
814       case kExchangeContainer:
815          break;   
816    }
817    return cont;
818 }
819          
820 //______________________________________________________________________________
821 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
822                                         AliAnalysisDataContainer *cont)
823 {
824 // Connect input of an existing task to a data container.
825    if (!task) {
826       Error("ConnectInput", "Task pointer is NULL");
827       return kFALSE;
828    }   
829    if (!fTasks->FindObject(task)) {
830       AddTask(task);
831       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
832    } 
833    Bool_t connected = task->ConnectInput(islot, cont);
834    return connected;
835 }   
836
837 //______________________________________________________________________________
838 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
839                                         AliAnalysisDataContainer *cont)
840 {
841 // Connect output of an existing task to a data container.
842    if (!task) {
843       Error("ConnectOutput", "Task pointer is NULL");
844       return kFALSE;
845    }   
846    if (!fTasks->FindObject(task)) {
847       AddTask(task);
848       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
849    } 
850    Bool_t connected = task->ConnectOutput(islot, cont);
851    return connected;
852 }   
853                                
854 //______________________________________________________________________________
855 void AliAnalysisManager::CleanContainers()
856 {
857 // Clean data from all containers that have already finished all client tasks.
858    TIter next(fContainers);
859    AliAnalysisDataContainer *cont;
860    while ((cont=(AliAnalysisDataContainer *)next())) {
861       if (cont->IsOwnedData() && 
862           cont->IsDataReady() && 
863           cont->ClientsExecuted()) cont->DeleteData();
864    }
865 }
866
867 //______________________________________________________________________________
868 Bool_t AliAnalysisManager::InitAnalysis()
869 {
870 // Initialization of analysis chain of tasks. Should be called after all tasks
871 // and data containers are properly connected
872    // Check for input/output containers
873    fInitOK = kFALSE;
874    // Check for top tasks (depending only on input data containers)
875    if (!fTasks->First()) {
876       Error("InitAnalysis", "Analysis has no tasks !");
877       return kFALSE;
878    }   
879    TIter next(fTasks);
880    AliAnalysisTask *task;
881    AliAnalysisDataContainer *cont;
882    Int_t ntop = 0;
883    Int_t nzombies = 0;
884    Bool_t iszombie = kFALSE;
885    Bool_t istop = kTRUE;
886    Int_t i;
887    while ((task=(AliAnalysisTask*)next())) {
888       istop = kTRUE;
889       iszombie = kFALSE;
890       Int_t ninputs = task->GetNinputs();
891       for (i=0; i<ninputs; i++) {
892          cont = task->GetInputSlot(i)->GetContainer();
893          if (!cont) {
894             if (!iszombie) {
895                task->SetZombie();
896                fZombies->Add(task);
897                nzombies++;
898                iszombie = kTRUE;
899             }   
900             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
901                   i, task->GetName()); 
902          }
903          if (iszombie) continue;
904          // Check if cont is an input container
905          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
906          // Connect to parent task
907       }
908       if (istop) {
909          ntop++;
910          fTopTasks->Add(task);
911       }
912    }
913    if (!ntop) {
914       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
915       return kFALSE;
916    }                        
917    // Check now if there are orphan tasks
918    for (i=0; i<ntop; i++) {
919       task = (AliAnalysisTask*)fTopTasks->At(i);
920       task->SetUsed();
921    }
922    Int_t norphans = 0;
923    next.Reset();
924    while ((task=(AliAnalysisTask*)next())) {
925       if (!task->IsUsed()) {
926          norphans++;
927          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
928       }   
929    }          
930    // Check the task hierarchy (no parent task should depend on data provided
931    // by a daughter task)
932    for (i=0; i<ntop; i++) {
933       task = (AliAnalysisTask*)fTopTasks->At(i);
934       if (task->CheckCircularDeps()) {
935          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
936          PrintStatus("dep");
937          return kFALSE;
938       }   
939    }
940    // Check that all containers feeding post-event loop tasks are in the outputs list
941    TIter nextcont(fContainers); // loop over all containers
942    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
943       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
944          if (cont->HasConsumers()) {
945          // Check if one of the consumers is post event loop
946             TIter nextconsumer(cont->GetConsumers());
947             while ((task=(AliAnalysisTask*)nextconsumer())) {
948                if (task->IsPostEventLoop()) {
949                   fOutputs->Add(cont);
950                   break;
951                }
952             }
953          }
954       }
955    }   
956    // Check if all special output containers have a file name provided
957    TIter nextout(fOutputs);
958    while ((cont=(AliAnalysisDataContainer*)nextout())) {
959       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
960          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
961          return kFALSE;
962       }
963    }      
964    fInitOK = kTRUE;
965    return kTRUE;
966 }   
967
968 //______________________________________________________________________________
969 void AliAnalysisManager::PrintStatus(Option_t *option) const
970 {
971 // Print task hierarchy.
972    if (!fInitOK) {
973       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
974       return;
975    }   
976    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
977    if (getsysInfo)
978       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
979    TIter next(fTopTasks);
980    AliAnalysisTask *task;
981    while ((task=(AliAnalysisTask*)next()))
982       task->PrintTask(option);
983 }
984
985 //______________________________________________________________________________
986 void AliAnalysisManager::ResetAnalysis()
987 {
988 // Reset all execution flags and clean containers.
989    CleanContainers();
990 }
991
992 //______________________________________________________________________________
993 void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
994 {
995 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
996 // MIX. Process nentries starting from firstentry
997    if (!fInitOK) {
998       Error("StartAnalysis","Analysis manager was not initialized !");
999       return;
1000    }
1001    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1002    TString anaType = type;
1003    anaType.ToLower();
1004    fMode = kLocalAnalysis;
1005    Bool_t runlocalinit = kTRUE;
1006    if (anaType.Contains("file")) runlocalinit = kFALSE;
1007    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1008    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1009    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1010
1011    if (fMode == kGridAnalysis) {
1012       if (!fGridHandler) {
1013          Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1014          Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1015          return;
1016       }
1017       // Write analysis manager in the analysis file
1018       cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1019       // run local task configuration
1020       TIter nextTask(fTasks);
1021       AliAnalysisTask *task;
1022       while ((task=(AliAnalysisTask*)nextTask())) {
1023          task->LocalInit();
1024       }
1025       fGridHandler->StartAnalysis(nentries, firstentry);
1026
1027       // Terminate grid analysis
1028       if (fSelector && fSelector->GetStatus() == -1) return;
1029       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1030       cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1031       if (!fGridHandler->MergeOutputs()) {
1032          // Return if outputs could not be merged or if it alien handler
1033          // was configured for offline mode or local testing.
1034          return;
1035       }
1036       ImportWrappers(NULL);
1037       Terminate();
1038       return;
1039    }
1040    char line[256];
1041    SetEventLoop(kFALSE);
1042    // Enable event loop mode if a tree was provided
1043    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1044
1045    TChain *chain = 0;
1046    TString ttype = "TTree";
1047    if (tree && tree->IsA() == TChain::Class()) {
1048       chain = (TChain*)tree;
1049       if (!chain || !chain->GetListOfFiles()->First()) {
1050          Error("StartAnalysis", "Cannot process null or empty chain...");
1051          return;
1052       }   
1053       ttype = "TChain";
1054    }   
1055
1056    // Initialize locally all tasks (happens for all modes)
1057    TIter next(fTasks);
1058    AliAnalysisTask *task;
1059    if (runlocalinit) {
1060       while ((task=(AliAnalysisTask*)next())) {
1061          task->LocalInit();
1062       }
1063    }   
1064    
1065    switch (fMode) {
1066       case kLocalAnalysis:
1067          if (!tree) {
1068             TIter nextT(fTasks);
1069             // Call CreateOutputObjects for all tasks
1070             while ((task=(AliAnalysisTask*)nextT())) {
1071                TDirectory *curdir = gDirectory;
1072                task->CreateOutputObjects();
1073                if (curdir) curdir->cd();
1074             }   
1075             ExecAnalysis();
1076             Terminate();
1077             return;
1078          } 
1079          // Run tree-based analysis via AliAnalysisSelector  
1080          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1081          fSelector = new AliAnalysisSelector(this);
1082          tree->Process(fSelector, "", nentries, firstentry);
1083          break;
1084       case kProofAnalysis:
1085          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1086             printf("StartAnalysis: no PROOF!!!\n");
1087             return;
1088          }   
1089          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1090          gROOT->ProcessLine(line);
1091          if (chain) {
1092             chain->SetProof();
1093             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1094             chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1095          } else {
1096             printf("StartAnalysis: no chain\n");
1097             return;
1098          }      
1099          break;
1100       case kGridAnalysis:
1101          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1102          break;
1103       case kMixingAnalysis:   
1104          // Run event mixing analysis
1105          if (!fEventPool) {
1106             Error("StartAnalysis", "Cannot run event mixing without event pool");
1107             return;
1108          }
1109          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1110          fSelector = new AliAnalysisSelector(this);
1111          while ((chain=fEventPool->GetNextChain())) {
1112             next.Reset();
1113             // Call NotifyBinChange for all tasks
1114             while ((task=(AliAnalysisTask*)next()))
1115                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1116             chain->Process(fSelector);
1117          }
1118          PackOutput(fSelector->GetOutputList());
1119          Terminate();
1120    }   
1121 }   
1122
1123 //______________________________________________________________________________
1124 void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1125 {
1126 // Start analysis for this manager on a given dataset. Analysis task can be: 
1127 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1128    if (!fInitOK) {
1129       Error("StartAnalysis","Analysis manager was not initialized !");
1130       return;
1131    }
1132    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1133    TString anaType = type;
1134    anaType.ToLower();
1135    if (!anaType.Contains("proof")) {
1136       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1137       return;
1138    }   
1139    fMode = kProofAnalysis;
1140    char line[256];
1141    SetEventLoop(kTRUE);
1142    // Set the dataset flag
1143    TObject::SetBit(kUseDataSet);
1144    fTree = 0;
1145
1146    // Initialize locally all tasks
1147    TIter next(fTasks);
1148    AliAnalysisTask *task;
1149    while ((task=(AliAnalysisTask*)next())) {
1150       task->LocalInit();
1151    }
1152    
1153    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1154       printf("StartAnalysis: no PROOF!!!\n");
1155       return;
1156    }   
1157    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1158    gROOT->ProcessLine(line);
1159    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1160    if (!gROOT->ProcessLine(line)) {
1161       Error("StartAnalysis", "Dataset %s not found", dataset);
1162       return;
1163    }   
1164    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1165            dataset, nentries, firstentry);
1166    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1167    gROOT->ProcessLine(line);
1168 }   
1169
1170 //______________________________________________________________________________
1171 TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1172 {
1173 // Opens a special output file used in PROOF.
1174    char line[256];
1175    if (fMode!=kProofAnalysis || !fSelector) {
1176       Error("OpenProofFile","Cannot open PROOF file %s",filename);
1177       return NULL;
1178    }   
1179    sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
1180    if (fDebug > 1) printf("=== %s\n", line);
1181    gROOT->ProcessLine(line);
1182    sprintf(line, "pf->OpenFile(\"%s\");", option);
1183    gROOT->ProcessLine(line);
1184    if (fDebug > 1) {
1185       gROOT->ProcessLine("pf->Print()");
1186       printf(" == proof file name: %s\n", gFile->GetName());
1187    }   
1188    sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1189    if (fDebug > 1) printf("=== %s\n", line);
1190    gROOT->ProcessLine(line);
1191    return gFile;
1192 }   
1193
1194 //______________________________________________________________________________
1195 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1196 {
1197 // Execute analysis.
1198    static Long64_t ncalls = 0;
1199    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1200    if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1201    ncalls++;
1202    if (!fInitOK) {
1203      Error("ExecAnalysis", "Analysis manager was not initialized !");
1204       return;
1205    }   
1206    AliAnalysisTask *task;
1207    // Check if the top tree is active.
1208    if (fTree) {
1209       TIter next(fTasks);
1210    // De-activate all tasks
1211       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1212       AliAnalysisDataContainer *cont = fCommonInput;
1213       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1214       if (!cont) {
1215               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1216          return;
1217       }   
1218       cont->SetData(fTree); // This will notify all consumers
1219       Long64_t entry = fTree->GetTree()->GetReadEntry();
1220       
1221 //
1222 //    Call BeginEvent() for optional input/output and MC services 
1223       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1224       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1225       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1226 //
1227 //    Execute the tasks
1228 //      TIter next1(cont->GetConsumers());
1229       TIter next1(fTopTasks);
1230       while ((task=(AliAnalysisTask*)next1())) {
1231          if (fDebug >1) {
1232             cout << "    Executing task " << task->GetName() << endl;
1233          }   
1234          
1235          task->ExecuteTask(option);
1236       }
1237 //
1238 //    Call FinishEvent() for optional output and MC services 
1239       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1240       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1241       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1242       // Gather system information if requested
1243       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1244          AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
1245       return;
1246    }   
1247    // The event loop is not controlled by TSelector   
1248 //
1249 //  Call BeginEvent() for optional input/output and MC services 
1250    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1251    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1252    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1253    TIter next2(fTopTasks);
1254    while ((task=(AliAnalysisTask*)next2())) {
1255       task->SetActive(kTRUE);
1256       if (fDebug > 1) {
1257          cout << "    Executing task " << task->GetName() << endl;
1258       }   
1259       task->ExecuteTask(option);
1260    }   
1261 //
1262 // Call FinishEvent() for optional output and MC services 
1263    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1264    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1265    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1266 }
1267
1268 //______________________________________________________________________________
1269 void AliAnalysisManager::FinishAnalysis()
1270 {
1271 // Finish analysis.
1272 }
1273
1274 //______________________________________________________________________________
1275 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler*  handler)
1276 {
1277 // Set the input event handler and create a container for it.
1278    fInputEventHandler   = handler;
1279    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1280    Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1281 }
1282
1283 //______________________________________________________________________________
1284 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler*  handler)
1285 {
1286 // Set the input event handler and create a container for it.
1287    fOutputEventHandler   = handler;
1288    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1289    fCommonOutput->SetSpecialOutput();
1290    Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1291 }
1292
1293 //______________________________________________________________________________
1294 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1295 {
1296 // This method is used externally to register output files which are not
1297 // connected to any output container, so that the manager can properly register,
1298 // retrieve or merge them when running in distributed mode. The file names are
1299 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1300    if (fExtraFiles.Length()) fExtraFiles += " ";
1301    fExtraFiles += fname;
1302 }
1303
1304 //______________________________________________________________________________
1305 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1306 {
1307 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1308    char full_path[512];
1309    char ch_url[512];
1310    TObject *pof =  source->FindObject(filename);
1311    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1312       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1313       return kFALSE;
1314    }
1315    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1316    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1317    TString clientUrl(ch_url);
1318    TString full_path_str(full_path);
1319    if (clientUrl.Contains("localhost")){
1320       TObjArray* array = full_path_str.Tokenize ( "//" );
1321       TObjString *strobj = ( TObjString *)array->At(1);
1322       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1323       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1324       full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1325       full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1326       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1327       delete arrayPort;
1328       delete array;
1329    }
1330    if (fDebug > 1) 
1331       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1332    Bool_t gotit = TFile::Cp(full_path_str.Data(), filename); 
1333    if (!gotit)
1334       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1335    return gotit;
1336 }