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