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