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