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