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