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