]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Correction for delta AOD handling in proof and saving in AliEn
[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             printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
436             filename = fOutputEventHandler->GetOutputFileName();
437          }
438          // Check if data was posted to this container. If not, issue an error.
439          if (!output->GetData() && !isManagedByHandler) {
440             Error("PackOutput", "No data for output container %s. Forgot to PostData ?\n", output->GetName());
441             continue;
442          }   
443          if (!output->IsSpecialOutput()) {
444             // Normal outputs
445             if (strlen(filename) && !isManagedByHandler) {
446                // File resident outputs
447                TFile *file = output->GetFile();
448                // Backup current folder
449                TDirectory *opwd = gDirectory;
450                // Create file if not existing and register to container.
451                if (file) file->cd();
452                else      file = new TFile(filename, "RECREATE"); 
453                if (file->IsZombie()) {
454                   Fatal("PackOutput", "Could not recreate file %s\n", filename);
455                   return;
456                }   
457                output->SetFile(file);
458                // Clear file list to release object ownership to user.
459                file->Clear();
460                // Save data to file, then close.
461                if (output->GetData()->InheritsFrom(TCollection::Class())) {
462                   // If data is a collection, we set the name of the collection 
463                   // as the one of the container and we save as a single key.
464                   TCollection *coll = (TCollection*)output->GetData();
465                   coll->SetName(output->GetName());
466                   coll->Write(output->GetName(), TObject::kSingleKey);
467                } else {
468                   if (output->GetData()->InheritsFrom(TTree::Class())) {
469                      TTree *tree = (TTree*)output->GetData();
470                      tree->SetDirectory(file);
471                      tree->AutoSave();
472                   } else {
473                      output->GetData()->Write();
474                   }   
475                }      
476                if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
477                if (fDebug > 2) {
478                   printf("   file %s listing content:\n", filename);
479                   file->ls();
480                }   
481                file->Close();
482                // Restore current directory
483                if (opwd) opwd->cd();
484             } else {
485                // Memory-resident outputs   
486                if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
487             }   
488             AliAnalysisDataWrapper *wrap = 0;
489             if (isManagedByHandler) {
490                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
491                wrap->SetName(output->GetName());
492             }   
493             else                    wrap =output->ExportData();
494             // Output wrappers must NOT delete data after merging - the user owns them
495             wrap->SetDeleteData(kFALSE);
496             target->Add(wrap);
497          } else {
498          // Special outputs. The file must be opened and connected to the container.
499             TDirectory *opwd = gDirectory;
500             TFile *file = output->GetFile();
501             if (!file) {
502                AliAnalysisTask *producer = output->GetProducer();
503                Error("PackOutput", 
504                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
505                      output->GetFileName(), output->GetName(), producer->ClassName());
506                continue;
507             }   
508             TString outFilename = file->GetName();
509             if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
510             if (isManagedByHandler) {
511                // Terminate IO for files managed by the output handler
512                if (file) file->Write();
513                if (file && fDebug > 2) {
514                   printf("   handled file %s listing content:\n", file->GetName());
515                   file->ls();
516                }   
517                fOutputEventHandler->TerminateIO();
518             } else {               
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                file->Close();
542             }
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                if (remote.BeginsWith("alien://")) {
551                   gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
552                   remote += outFilename;
553                   remote.ReplaceAll(".root", Form("_%d.root", gid));
554                } else {   
555                   remote += Form("%s_%d_", gSystem->HostName(), gid);
556                   remote += outFilename;
557                }   
558                if (fDebug > 1) 
559                   Info("PackOutput", "Output file for container %s to be copied \n   at: %s. No merging.",
560                        output->GetName(), remote.Data());
561                TFile::Cp ( outFilename.Data(), remote.Data() );
562                // Copy extra outputs
563                if (fExtraFiles.Length() && isManagedByHandler) {
564                   TObjArray *arr = fExtraFiles.Tokenize(" ");
565                   TObjString *os;
566                   TIter nextfilename(arr);
567                   while ((os=(TObjString*)nextfilename())) {
568                      outFilename = os->GetString();
569                      remote = fSpecialOutputLocation;
570                      remote += "/";
571                      if (remote.BeginsWith("alien://")) {
572                         remote += outFilename;
573                         remote.ReplaceAll(".root", Form("_%d.root", gid));
574                      } else {   
575                         remote += Form("%s_%d_", gSystem->HostName(), gid);
576                         remote += outFilename;
577                      }   
578                      if (fDebug > 1) 
579                         Info("PackOutput", "Extra AOD file %s to be copied \n   at: %s. No merging.",
580                              outFilename.Data(), remote.Data());
581                      TFile::Cp ( outFilename.Data(), remote.Data() );
582                   }   
583                   delete arr;
584                }   
585             } else {
586             // No special location specified-> use TProofOutputFile as merging utility
587             // The file at this output slot must be opened in CreateOutputObjects
588                if (fDebug > 1) printf("   File for container %s to be merged via file merger...\n", output->GetName());
589             }
590          }      
591       }
592    } 
593    if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
594 }
595
596 //______________________________________________________________________________
597 void AliAnalysisManager::ImportWrappers(TList *source)
598 {
599 // Import data in output containers from wrappers coming in source.
600    if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
601    TIter next(fOutputs);
602    AliAnalysisDataContainer *cont;
603    AliAnalysisDataWrapper   *wrap;
604    Int_t icont = 0;
605    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
606    while ((cont=(AliAnalysisDataContainer*)next())) {
607       wrap = 0;
608       if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
609       const char *filename = cont->GetFileName();
610       Bool_t isManagedByHandler = kFALSE;
611       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
612          isManagedByHandler = kTRUE;
613          filename = fOutputEventHandler->GetOutputFileName();
614       }
615       if (cont->IsSpecialOutput() || inGrid) {
616          if (strlen(fSpecialOutputLocation.Data())) continue;
617          // Copy merged file from PROOF scratch space. 
618          // In case of grid the files are already in the current directory.
619          if (!inGrid) {
620             if (isManagedByHandler && fExtraFiles.Length()) {
621                // Copy extra registered dAOD files.
622                TObjArray *arr = fExtraFiles.Tokenize(" ");
623                TObjString *os;
624                TIter nextfilename(arr);
625                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
626                delete arr;
627             }
628             if (!GetFileFromWrapper(filename, source)) continue;
629          }   
630          // Normally we should connect data from the copied file to the
631          // corresponding output container, but it is not obvious how to do this
632          // automatically if several objects in file...
633          TFile *f = TFile::Open(filename, "READ");
634          if (!f) {
635             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
636             continue;
637          }   
638          TObject *obj = 0;
639          // Try to fetch first a list object having the container name.
640          obj = f->Get(cont->GetName());
641          if (!obj) {
642          // Fetch first object from file having the container type.
643             TIter nextkey(f->GetListOfKeys());
644             TKey *key;
645             while ((key=(TKey*)nextkey())) {
646                obj = f->Get(key->GetName());
647                if (obj && obj->IsA()->InheritsFrom(cont->GetType())) break;
648             }                     
649          }
650          if (!obj) {
651             Error("ImportWrappers", "Could not find object for container %s in file %s", cont->GetName(), filename);
652             continue;
653          }  
654          wrap = new AliAnalysisDataWrapper(obj);
655          wrap->SetDeleteData(kFALSE);
656       }   
657       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
658       if (!wrap) {
659          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
660          continue;
661       }
662       icont++;
663       if (fDebug > 1) {
664          printf("   Importing data for container %s", cont->GetName());
665          if (strlen(filename)) printf("    -> file %s\n", filename);
666          else printf("\n");
667       }   
668       cont->ImportData(wrap);
669    }         
670    if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
671 }
672
673 //______________________________________________________________________________
674 void AliAnalysisManager::UnpackOutput(TList *source)
675 {
676   // Called by AliAnalysisSelector::Terminate only on the client.
677    if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
678    if (!source) {
679       Error("UnpackOutput", "No target. Aborting.");
680       return;
681    }
682    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
683
684    if (fMode == kProofAnalysis) ImportWrappers(source);
685
686    TIter next(fOutputs);
687    AliAnalysisDataContainer *output;
688    while ((output=(AliAnalysisDataContainer*)next())) {
689       if (!output->GetData()) continue;
690       // Check if there are client tasks that run post event loop
691       if (output->HasConsumers()) {
692          // Disable event loop semaphore
693          output->SetPostEventLoop(kTRUE);
694          TObjArray *list = output->GetConsumers();
695          Int_t ncons = list->GetEntriesFast();
696          for (Int_t i=0; i<ncons; i++) {
697             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
698             task->CheckNotify(kTRUE);
699             // If task is active, execute it
700             if (task->IsPostEventLoop() && task->IsActive()) {
701                if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
702                task->ExecuteTask();
703             }   
704          }
705       }   
706    }
707    if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
708 }
709
710 //______________________________________________________________________________
711 void AliAnalysisManager::Terminate()
712 {
713   // The Terminate() function is the last function to be called during
714   // a query. It always runs on the client, it can be used to present
715   // the results graphically.
716    if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
717    AliAnalysisTask *task;
718    TIter next(fTasks);
719    // Call Terminate() for tasks
720    while ((task=(AliAnalysisTask*)next())) task->Terminate();
721    //
722    TIter next1(fOutputs);
723    AliAnalysisDataContainer *output;
724    while ((output=(AliAnalysisDataContainer*)next1())) {
725       // Special outputs or grid files have the files already closed and written.
726       if (fMode == kGridAnalysis) continue;
727       if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
728       const char *filename = output->GetFileName();
729       if (!(strcmp(filename, "default"))) {
730          if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
731          TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
732          if (aodfile) {
733             if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
734             aodfile->Write();
735             continue;
736          }   
737       }      
738       if (!strlen(filename)) continue;
739       if (!output->GetData()) continue;
740       TFile *file = output->GetFile();
741       TDirectory *opwd = gDirectory;
742       file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
743       if (!file) file = new TFile(filename, "RECREATE");
744       if (file->IsZombie()) continue;
745       output->SetFile(file);
746       file->cd();
747       if (fDebug > 1) printf("   writing output data %s to file %s\n", output->GetData()->GetName(), file->GetName());
748       if (output->GetData()->InheritsFrom(TCollection::Class())) {
749       // If data is a collection, we set the name of the collection 
750       // as the one of the container and we save as a single key.
751          TCollection *coll = (TCollection*)output->GetData();
752          coll->SetName(output->GetName());
753          coll->Write(output->GetName(), TObject::kSingleKey);
754       } else {
755          if (output->GetData()->InheritsFrom(TTree::Class())) {
756             TTree *tree = (TTree*)output->GetData();
757             tree->SetDirectory(file);
758             tree->AutoSave();
759          } else {
760             output->GetData()->Write();
761          }   
762       }      
763       if (opwd) opwd->cd();
764    }   
765    next1.Reset();
766    while ((output=(AliAnalysisDataContainer*)next1())) {
767       // Close all files at output
768       TDirectory *opwd = gDirectory;
769       if (output->GetFile()) {
770          output->GetFile()->Close();
771          // Copy merged outputs in alien if requested
772          if (fSpecialOutputLocation.Length() && 
773              fSpecialOutputLocation.BeginsWith("alien://")) {
774             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
775             TFile::Cp(output->GetFile()->GetName(), 
776                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
777          }             
778       }   
779       if (opwd) opwd->cd();
780    }   
781
782    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
783    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
784    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
785
786    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
787    if (getsysInfo) {
788       TDirectory *cdir = gDirectory;
789       TFile f("syswatch.root", "RECREATE");
790       if (!f.IsZombie()) {
791          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
792          tree->SetMarkerStyle(kCircle);
793          tree->SetMarkerColor(kBlue);
794          tree->SetMarkerSize(0.5);
795          if (!gROOT->IsBatch()) {
796             tree->SetAlias("event", "id0");
797             tree->SetAlias("memUSED", "mi.fMemUsed");
798             new TCanvas("SysInfo","SysInfo",10,10,800,600);
799             tree->Draw("memUSED:event","","", 1234567890, 0);
800          }   
801          tree->Write();
802          f.Close();
803          delete tree;
804       }
805       if (cdir) cdir->cd();
806    }      
807    if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
808 }
809
810 //______________________________________________________________________________
811 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
812 {
813 // Adds a user task to the global list of tasks.
814    if (fTasks->FindObject(task)) {
815       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
816       return;
817    }   
818    task->SetActive(kFALSE);
819    fTasks->Add(task);
820 }  
821
822 //______________________________________________________________________________
823 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
824 {
825 // Retreive task by name.
826    if (!fTasks) return NULL;
827    return (AliAnalysisTask*)fTasks->FindObject(name);
828 }
829
830 //______________________________________________________________________________
831 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
832                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
833 {
834 // Create a data container of a certain type. Types can be:
835 //   kExchangeContainer  = 0, used to exchange date between tasks
836 //   kInputContainer   = 1, used to store input data
837 //   kOutputContainer  = 2, used for posting results
838    if (fContainers->FindObject(name)) {
839       Error("CreateContainer","A container named %s already defined !\n",name);
840       return NULL;
841    }   
842    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
843    fContainers->Add(cont);
844    switch (type) {
845       case kInputContainer:
846          fInputs->Add(cont);
847          break;
848       case kOutputContainer:
849          fOutputs->Add(cont);
850          if (filename && strlen(filename)) {
851             cont->SetFileName(filename);
852             cont->SetDataOwned(kFALSE);  // data owned by the file
853          }   
854          break;
855       case kExchangeContainer:
856          break;   
857    }
858    return cont;
859 }
860          
861 //______________________________________________________________________________
862 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
863                                         AliAnalysisDataContainer *cont)
864 {
865 // Connect input of an existing task to a data container.
866    if (!task) {
867       Error("ConnectInput", "Task pointer is NULL");
868       return kFALSE;
869    }   
870    if (!fTasks->FindObject(task)) {
871       AddTask(task);
872       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
873    } 
874    Bool_t connected = task->ConnectInput(islot, cont);
875    return connected;
876 }   
877
878 //______________________________________________________________________________
879 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
880                                         AliAnalysisDataContainer *cont)
881 {
882 // Connect output of an existing task to a data container.
883    if (!task) {
884       Error("ConnectOutput", "Task pointer is NULL");
885       return kFALSE;
886    }   
887    if (!fTasks->FindObject(task)) {
888       AddTask(task);
889       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
890    } 
891    Bool_t connected = task->ConnectOutput(islot, cont);
892    return connected;
893 }   
894                                
895 //______________________________________________________________________________
896 void AliAnalysisManager::CleanContainers()
897 {
898 // Clean data from all containers that have already finished all client tasks.
899    TIter next(fContainers);
900    AliAnalysisDataContainer *cont;
901    while ((cont=(AliAnalysisDataContainer *)next())) {
902       if (cont->IsOwnedData() && 
903           cont->IsDataReady() && 
904           cont->ClientsExecuted()) cont->DeleteData();
905    }
906 }
907
908 //______________________________________________________________________________
909 Bool_t AliAnalysisManager::InitAnalysis()
910 {
911 // Initialization of analysis chain of tasks. Should be called after all tasks
912 // and data containers are properly connected
913    // Check for input/output containers
914    fInitOK = kFALSE;
915    // Check for top tasks (depending only on input data containers)
916    if (!fTasks->First()) {
917       Error("InitAnalysis", "Analysis has no tasks !");
918       return kFALSE;
919    }   
920    TIter next(fTasks);
921    AliAnalysisTask *task;
922    AliAnalysisDataContainer *cont;
923    Int_t ntop = 0;
924    Int_t nzombies = 0;
925    Bool_t iszombie = kFALSE;
926    Bool_t istop = kTRUE;
927    Int_t i;
928    while ((task=(AliAnalysisTask*)next())) {
929       istop = kTRUE;
930       iszombie = kFALSE;
931       Int_t ninputs = task->GetNinputs();
932       for (i=0; i<ninputs; i++) {
933          cont = task->GetInputSlot(i)->GetContainer();
934          if (!cont) {
935             if (!iszombie) {
936                task->SetZombie();
937                fZombies->Add(task);
938                nzombies++;
939                iszombie = kTRUE;
940             }   
941             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
942                   i, task->GetName()); 
943          }
944          if (iszombie) continue;
945          // Check if cont is an input container
946          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
947          // Connect to parent task
948       }
949       if (istop) {
950          ntop++;
951          fTopTasks->Add(task);
952       }
953    }
954    if (!ntop) {
955       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
956       return kFALSE;
957    }                        
958    // Check now if there are orphan tasks
959    for (i=0; i<ntop; i++) {
960       task = (AliAnalysisTask*)fTopTasks->At(i);
961       task->SetUsed();
962    }
963    Int_t norphans = 0;
964    next.Reset();
965    while ((task=(AliAnalysisTask*)next())) {
966       if (!task->IsUsed()) {
967          norphans++;
968          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
969       }   
970    }          
971    // Check the task hierarchy (no parent task should depend on data provided
972    // by a daughter task)
973    for (i=0; i<ntop; i++) {
974       task = (AliAnalysisTask*)fTopTasks->At(i);
975       if (task->CheckCircularDeps()) {
976          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
977          PrintStatus("dep");
978          return kFALSE;
979       }   
980    }
981    // Check that all containers feeding post-event loop tasks are in the outputs list
982    TIter nextcont(fContainers); // loop over all containers
983    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
984       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
985          if (cont->HasConsumers()) {
986          // Check if one of the consumers is post event loop
987             TIter nextconsumer(cont->GetConsumers());
988             while ((task=(AliAnalysisTask*)nextconsumer())) {
989                if (task->IsPostEventLoop()) {
990                   fOutputs->Add(cont);
991                   break;
992                }
993             }
994          }
995       }
996    }   
997    // Check if all special output containers have a file name provided
998    TIter nextout(fOutputs);
999    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1000       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1001          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1002          return kFALSE;
1003       }
1004    }      
1005    fInitOK = kTRUE;
1006    return kTRUE;
1007 }   
1008
1009 //______________________________________________________________________________
1010 void AliAnalysisManager::PrintStatus(Option_t *option) const
1011 {
1012 // Print task hierarchy.
1013    if (!fInitOK) {
1014       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1015       return;
1016    }   
1017    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1018    if (getsysInfo)
1019       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1020    TIter next(fTopTasks);
1021    AliAnalysisTask *task;
1022    while ((task=(AliAnalysisTask*)next()))
1023       task->PrintTask(option);
1024 }
1025
1026 //______________________________________________________________________________
1027 void AliAnalysisManager::ResetAnalysis()
1028 {
1029 // Reset all execution flags and clean containers.
1030    CleanContainers();
1031 }
1032
1033 //______________________________________________________________________________
1034 void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
1035 {
1036 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1037 // MIX. Process nentries starting from firstentry
1038    if (!fInitOK) {
1039       Error("StartAnalysis","Analysis manager was not initialized !");
1040       return;
1041    }
1042    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1043    TString anaType = type;
1044    anaType.ToLower();
1045    fMode = kLocalAnalysis;
1046    Bool_t runlocalinit = kTRUE;
1047    if (anaType.Contains("file")) runlocalinit = kFALSE;
1048    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1049    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1050    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1051
1052    if (fMode == kGridAnalysis) {
1053       if (!fGridHandler) {
1054          Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1055          Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1056          return;
1057       }
1058       // Write analysis manager in the analysis file
1059       cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1060       // run local task configuration
1061       TIter nextTask(fTasks);
1062       AliAnalysisTask *task;
1063       while ((task=(AliAnalysisTask*)nextTask())) {
1064          task->LocalInit();
1065       }
1066       fGridHandler->StartAnalysis(nentries, firstentry);
1067
1068       // Terminate grid analysis
1069       if (fSelector && fSelector->GetStatus() == -1) return;
1070       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1071       cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1072       if (!fGridHandler->MergeOutputs()) {
1073          // Return if outputs could not be merged or if it alien handler
1074          // was configured for offline mode or local testing.
1075          return;
1076       }
1077       ImportWrappers(NULL);
1078       Terminate();
1079       return;
1080    }
1081    char line[256];
1082    SetEventLoop(kFALSE);
1083    // Enable event loop mode if a tree was provided
1084    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1085
1086    TChain *chain = 0;
1087    TString ttype = "TTree";
1088    if (tree && tree->IsA() == TChain::Class()) {
1089       chain = (TChain*)tree;
1090       if (!chain || !chain->GetListOfFiles()->First()) {
1091          Error("StartAnalysis", "Cannot process null or empty chain...");
1092          return;
1093       }   
1094       ttype = "TChain";
1095    }   
1096
1097    // Initialize locally all tasks (happens for all modes)
1098    TIter next(fTasks);
1099    AliAnalysisTask *task;
1100    if (runlocalinit) {
1101       while ((task=(AliAnalysisTask*)next())) {
1102          task->LocalInit();
1103       }
1104    }   
1105    
1106    switch (fMode) {
1107       case kLocalAnalysis:
1108          if (!tree) {
1109             TIter nextT(fTasks);
1110             // Call CreateOutputObjects for all tasks
1111             while ((task=(AliAnalysisTask*)nextT())) {
1112                TDirectory *curdir = gDirectory;
1113                task->CreateOutputObjects();
1114                if (curdir) curdir->cd();
1115             }   
1116             ExecAnalysis();
1117             Terminate();
1118             return;
1119          } 
1120          // Run tree-based analysis via AliAnalysisSelector  
1121          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1122          fSelector = new AliAnalysisSelector(this);
1123          tree->Process(fSelector, "", nentries, firstentry);
1124          break;
1125       case kProofAnalysis:
1126          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1127             printf("StartAnalysis: no PROOF!!!\n");
1128             return;
1129          }   
1130          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1131          gROOT->ProcessLine(line);
1132          if (chain) {
1133             chain->SetProof();
1134             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1135             chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1136          } else {
1137             printf("StartAnalysis: no chain\n");
1138             return;
1139          }      
1140          break;
1141       case kGridAnalysis:
1142          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1143          break;
1144       case kMixingAnalysis:   
1145          // Run event mixing analysis
1146          if (!fEventPool) {
1147             Error("StartAnalysis", "Cannot run event mixing without event pool");
1148             return;
1149          }
1150          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1151          fSelector = new AliAnalysisSelector(this);
1152          while ((chain=fEventPool->GetNextChain())) {
1153             next.Reset();
1154             // Call NotifyBinChange for all tasks
1155             while ((task=(AliAnalysisTask*)next()))
1156                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1157             chain->Process(fSelector);
1158          }
1159          PackOutput(fSelector->GetOutputList());
1160          Terminate();
1161    }   
1162 }   
1163
1164 //______________________________________________________________________________
1165 void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1166 {
1167 // Start analysis for this manager on a given dataset. Analysis task can be: 
1168 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1169    if (!fInitOK) {
1170       Error("StartAnalysis","Analysis manager was not initialized !");
1171       return;
1172    }
1173    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1174    TString anaType = type;
1175    anaType.ToLower();
1176    if (!anaType.Contains("proof")) {
1177       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1178       return;
1179    }   
1180    fMode = kProofAnalysis;
1181    char line[256];
1182    SetEventLoop(kTRUE);
1183    // Set the dataset flag
1184    TObject::SetBit(kUseDataSet);
1185    fTree = 0;
1186
1187    // Initialize locally all tasks
1188    TIter next(fTasks);
1189    AliAnalysisTask *task;
1190    while ((task=(AliAnalysisTask*)next())) {
1191       task->LocalInit();
1192    }
1193    
1194    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1195       printf("StartAnalysis: no PROOF!!!\n");
1196       return;
1197    }   
1198    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1199    gROOT->ProcessLine(line);
1200    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1201    if (!gROOT->ProcessLine(line)) {
1202       Error("StartAnalysis", "Dataset %s not found", dataset);
1203       return;
1204    }   
1205    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1206            dataset, nentries, firstentry);
1207    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1208    gROOT->ProcessLine(line);
1209 }   
1210
1211 //______________________________________________________________________________
1212 TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1213 {
1214 // Opens a special output file used in PROOF.
1215    char line[256];
1216    if (fMode!=kProofAnalysis || !fSelector) {
1217       Error("OpenProofFile","Cannot open PROOF file %s",filename);
1218       return NULL;
1219    } 
1220    if (fSpecialOutputLocation.Length()) {
1221       TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1222       if (!f) f = new TFile(filename, option);
1223       return f;
1224    }   
1225    sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
1226    if (fDebug > 1) printf("=== %s\n", line);
1227    gROOT->ProcessLine(line);
1228    sprintf(line, "pf->OpenFile(\"%s\");", option);
1229    gROOT->ProcessLine(line);
1230    if (fDebug > 1) {
1231       gROOT->ProcessLine("pf->Print()");
1232       printf(" == proof file name: %s\n", gFile->GetName());
1233    }   
1234    sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1235    if (fDebug > 1) printf("=== %s\n", line);
1236    gROOT->ProcessLine(line);
1237    return gFile;
1238 }   
1239
1240 //______________________________________________________________________________
1241 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1242 {
1243 // Execute analysis.
1244    static Long64_t ncalls = 0;
1245    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1246    if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1247    ncalls++;
1248    if (!fInitOK) {
1249      Error("ExecAnalysis", "Analysis manager was not initialized !");
1250       return;
1251    }   
1252    AliAnalysisTask *task;
1253    // Check if the top tree is active.
1254    if (fTree) {
1255       TIter next(fTasks);
1256    // De-activate all tasks
1257       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1258       AliAnalysisDataContainer *cont = fCommonInput;
1259       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1260       if (!cont) {
1261               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1262          return;
1263       }   
1264       cont->SetData(fTree); // This will notify all consumers
1265       Long64_t entry = fTree->GetTree()->GetReadEntry();
1266       
1267 //
1268 //    Call BeginEvent() for optional input/output and MC services 
1269       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1270       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1271       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1272 //
1273 //    Execute the tasks
1274 //      TIter next1(cont->GetConsumers());
1275       TIter next1(fTopTasks);
1276       while ((task=(AliAnalysisTask*)next1())) {
1277          if (fDebug >1) {
1278             cout << "    Executing task " << task->GetName() << endl;
1279          }   
1280          
1281          task->ExecuteTask(option);
1282       }
1283 //
1284 //    Call FinishEvent() for optional output and MC services 
1285       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1286       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1287       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1288       // Gather system information if requested
1289       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1290          AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
1291       return;
1292    }   
1293    // The event loop is not controlled by TSelector   
1294 //
1295 //  Call BeginEvent() for optional input/output and MC services 
1296    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1297    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1298    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1299    TIter next2(fTopTasks);
1300    while ((task=(AliAnalysisTask*)next2())) {
1301       task->SetActive(kTRUE);
1302       if (fDebug > 1) {
1303          cout << "    Executing task " << task->GetName() << endl;
1304       }   
1305       task->ExecuteTask(option);
1306    }   
1307 //
1308 // Call FinishEvent() for optional output and MC services 
1309    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1310    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1311    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1312 }
1313
1314 //______________________________________________________________________________
1315 void AliAnalysisManager::FinishAnalysis()
1316 {
1317 // Finish analysis.
1318 }
1319
1320 //______________________________________________________________________________
1321 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler*  handler)
1322 {
1323 // Set the input event handler and create a container for it.
1324    fInputEventHandler   = handler;
1325    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1326    Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1327 }
1328
1329 //______________________________________________________________________________
1330 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler*  handler)
1331 {
1332 // Set the input event handler and create a container for it.
1333    fOutputEventHandler   = handler;
1334    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1335    fCommonOutput->SetSpecialOutput();
1336    Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1337 }
1338
1339 //______________________________________________________________________________
1340 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1341 {
1342 // This method is used externally to register output files which are not
1343 // connected to any output container, so that the manager can properly register,
1344 // retrieve or merge them when running in distributed mode. The file names are
1345 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1346    if (fExtraFiles.Length()) fExtraFiles += " ";
1347    fExtraFiles += fname;
1348 }
1349
1350 //______________________________________________________________________________
1351 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1352 {
1353 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1354    char full_path[512];
1355    char ch_url[512];
1356    TObject *pof =  source->FindObject(filename);
1357    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1358       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1359       return kFALSE;
1360    }
1361    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1362    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1363    TString clientUrl(ch_url);
1364    TString full_path_str(full_path);
1365    if (clientUrl.Contains("localhost")){
1366       TObjArray* array = full_path_str.Tokenize ( "//" );
1367       TObjString *strobj = ( TObjString *)array->At(1);
1368       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1369       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1370       full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1371       full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1372       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1373       delete arrayPort;
1374       delete array;
1375    }
1376    if (fDebug > 1) 
1377       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1378    Bool_t gotit = TFile::Cp(full_path_str.Data(), filename); 
1379    if (!gotit)
1380       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1381    return gotit;
1382 }
1383
1384 //______________________________________________________________________________
1385 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1386 {
1387 // Fill analysis type in the provided string.
1388    switch (fMode) {
1389       case kLocalAnalysis:
1390          type = "local";
1391          return;
1392       case kProofAnalysis:
1393          type = "proof";
1394          return;
1395       case kGridAnalysis:
1396          type = "grid";
1397          return;
1398       case kMixingAnalysis:
1399          type = "mix";
1400    }
1401 }