]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
addition to last fix
[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       if (cdir) cdir->cd();
1615       ImportWrappers(NULL);
1616       Terminate();
1617       if (cdir) cdir->cd();
1618       return 0;
1619    }
1620    TString line;
1621    SetEventLoop(kFALSE);
1622    // Enable event loop mode if a tree was provided
1623    if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1624
1625    TChain *chain = 0;
1626    TString ttype = "TTree";
1627    if (tree && tree->IsA() == TChain::Class()) {
1628       chain = (TChain*)tree;
1629       if (!chain || !chain->GetListOfFiles()->First()) {
1630          Error("StartAnalysis", "Cannot process null or empty chain...");
1631          if (cdir) cdir->cd();
1632          return -1;
1633       }   
1634       ttype = "TChain";
1635    }   
1636
1637    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1638    if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1639    // Initialize locally all tasks (happens for all modes)
1640    TIter next(fTasks);
1641    AliAnalysisTask *task;
1642    RunLocalInit();
1643    
1644    switch (fMode) {
1645       case kLocalAnalysis:
1646          if (!tree && !fGridHandler) {
1647             TIter nextT(fTasks);
1648             // Call CreateOutputObjects for all tasks
1649             Int_t itask = 0;
1650             Bool_t dirStatus = TH1::AddDirectoryStatus();
1651             while ((task=(AliAnalysisTask*)nextT())) {
1652                TH1::AddDirectory(kFALSE);
1653                task->CreateOutputObjects();
1654                if (!task->CheckPostData()) {
1655                   Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1656                         Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1657                         ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1658                }
1659                if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1660                gROOT->cd();
1661                itask++;
1662             }   
1663             TH1::AddDirectory(dirStatus);
1664             if (IsExternalLoop()) {
1665                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1666                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1667                return 0;
1668             }
1669             ExecAnalysis();
1670             Terminate();
1671             return 0;
1672          } 
1673          fSelector = new AliAnalysisSelector(this);
1674          // Check if a plugin handler is used
1675          if (fGridHandler) {
1676             // Get the chain from the plugin
1677             TString dataType = "esdTree";
1678             if (fInputEventHandler) {
1679                dataType = fInputEventHandler->GetDataType();
1680                dataType.ToLower();
1681                dataType += "Tree";
1682             }   
1683             chain = fGridHandler->GetChainForTestMode(dataType);
1684             if (!chain) {
1685                Error("StartAnalysis", "No chain for test mode. Aborting.");
1686                return -1;
1687             }
1688             cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1689             retv = chain->Process(fSelector, "", nentries, firstentry);
1690             break;
1691          }
1692          // Run tree-based analysis via AliAnalysisSelector  
1693          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1694          retv = tree->Process(fSelector, "", nentries, firstentry);
1695          break;
1696       case kProofAnalysis:
1697          fIsRemote = kTRUE;
1698          // Check if the plugin is used
1699          if (fGridHandler) {
1700             return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1701          }
1702          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1703             Error("StartAnalysis", "No PROOF!!! Exiting.");
1704             if (cdir) cdir->cd();
1705             return -1;
1706          }   
1707          line = Form("gProof->AddInput((TObject*)%p);", this);
1708          gROOT->ProcessLine(line);
1709          if (chain) {
1710             chain->SetProof();
1711             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1712             retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1713          } else {
1714             Error("StartAnalysis", "No chain!!! Exiting.");
1715             if (cdir) cdir->cd();
1716             return -1;
1717          }      
1718          break;
1719       case kGridAnalysis:
1720          fIsRemote = kTRUE;
1721          if (!anaType.Contains("terminate")) {
1722             if (!fGridHandler) {
1723                Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1724                Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1725                if (cdir) cdir->cd();
1726                return -1;
1727             }
1728             // Write analysis manager in the analysis file
1729             cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1730             // Start the analysis via the handler
1731             if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1732                Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1733                if (cdir) cdir->cd();
1734                return -1;
1735             }   
1736
1737             // Terminate grid analysis
1738             if (fSelector && fSelector->GetStatus() == -1) {if (cdir) cdir->cd(); return -1;}
1739             if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {if (cdir) cdir->cd(); return 0;}
1740             cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1741             if (!fGridHandler->MergeOutputs()) {
1742                // Return if outputs could not be merged or if it alien handler
1743                // was configured for offline mode or local testing.
1744                if (cdir) cdir->cd();
1745                return 0;
1746             }
1747          }   
1748          cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1749          ImportWrappers(NULL);
1750          Terminate();
1751          if (cdir) cdir->cd();
1752          return 0;
1753       case kMixingAnalysis:   
1754          // Run event mixing analysis
1755          if (!fEventPool) {
1756             Error("StartAnalysis", "Cannot run event mixing without event pool");
1757             if (cdir) cdir->cd();
1758             return -1;
1759          }
1760          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1761          fSelector = new AliAnalysisSelector(this);
1762          while ((chain=fEventPool->GetNextChain())) {
1763             next.Reset();
1764             // Call NotifyBinChange for all tasks
1765             while ((task=(AliAnalysisTask*)next()))
1766                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1767             retv = chain->Process(fSelector);
1768             if (retv < 0) {
1769                Error("StartAnalysis", "Mixing analysis failed");
1770                if (cdir) cdir->cd();
1771                return retv;
1772             }   
1773          }
1774          PackOutput(fSelector->GetOutputList());
1775          Terminate();
1776    }
1777    if (cdir) cdir->cd();
1778    return retv;
1779 }   
1780
1781 //______________________________________________________________________________
1782 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1783 {
1784 // Start analysis for this manager on a given dataset. Analysis task can be: 
1785 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1786    if (!fInitOK) {
1787       Error("StartAnalysis","Analysis manager was not initialized !");
1788       return -1;
1789    }
1790    fIsRemote = kTRUE;
1791    if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1792    TString anaType = type;
1793    anaType.ToLower();
1794    if (!anaType.Contains("proof")) {
1795       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1796       return -1;
1797    }   
1798    fMode = kProofAnalysis;
1799    TString line;
1800    SetEventLoop(kTRUE);
1801    // Set the dataset flag
1802    TObject::SetBit(kUseDataSet);
1803    fTree = 0;
1804    if (fGridHandler) {
1805       // Start proof analysis using the grid handler
1806       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1807          Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1808          return -1;
1809       }
1810       // Check if the plugin is in test mode
1811       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1812          dataset = "test_collection";
1813       } else {
1814          dataset = fGridHandler->GetProofDataSet();
1815       }
1816    }   
1817
1818    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1819       Error("StartAnalysis", "No PROOF!!! Exiting.");
1820       return -1;
1821    }   
1822
1823    // Initialize locally all tasks
1824    RunLocalInit();
1825       
1826    line = Form("gProof->AddInput((TObject*)%p);", this);
1827    gROOT->ProcessLine(line);
1828    Long_t retv;
1829    line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1830                dataset, nentries, firstentry);
1831    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1832    retv = (Long_t)gROOT->ProcessLine(line);
1833    return retv;
1834 }   
1835
1836 //______________________________________________________________________________
1837 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1838 {
1839 // Opens according the option the file specified by cont->GetFileName() and changes
1840 // current directory to cont->GetFolderName(). If the file was already opened, it
1841 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1842 // be optionally ignored.
1843   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1844   TString filename = cont->GetFileName();
1845   TFile *f = NULL;
1846   if (filename.IsNull()) {
1847     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1848     return NULL;
1849   }
1850   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1851       && !ignoreProof)
1852     f = mgr->OpenProofFile(cont,option);
1853   else {
1854     // Check first if the file is already opened
1855     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1856     if (f) {
1857       // Check if option "UPDATE" was preserved 
1858       TString opt(option);
1859       opt.ToUpper();
1860       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1861         ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1862     } else {
1863       f = TFile::Open(filename, option);
1864     }    
1865   }   
1866   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1867     cont->SetFile(f);
1868     // Cd to file
1869     f->cd();
1870     // Check for a folder request
1871     TString dir = cont->GetFolderName(); 
1872     if (!dir.IsNull()) {
1873       if (!f->GetDirectory(dir)) f->mkdir(dir);
1874       f->cd(dir);
1875     }
1876     return f;
1877   }
1878   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1879   cont->SetFile(NULL);
1880   return NULL;
1881 }    
1882  
1883 //______________________________________________________________________________
1884 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1885 {
1886 // Opens a special output file used in PROOF.
1887   TString line;
1888   TString filename = cont->GetFileName();
1889   if (cont == fCommonOutput) {
1890      if (fOutputEventHandler) {
1891         if (strlen(extaod)) filename = extaod;
1892         filename = fOutputEventHandler->GetOutputFileName();
1893      }   
1894      else Fatal("OpenProofFile","No output container. Exiting.");
1895   }   
1896   TFile *f = NULL;
1897   if (fMode!=kProofAnalysis || !fSelector) {
1898     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1899     return NULL;
1900   } 
1901   if (fSpecialOutputLocation.Length()) {
1902     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1903     if (f) {
1904       // Check if option "UPDATE" was preserved 
1905       TString opt(option);
1906       opt.ToUpper();
1907       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1908         ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1909     } else {
1910       f = new TFile(filename, option);
1911     }
1912     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1913       cont->SetFile(f);
1914       // Cd to file
1915       f->cd();
1916       // Check for a folder request
1917       TString dir = cont->GetFolderName(); 
1918       if (dir.Length()) {
1919         if (!f->GetDirectory(dir)) f->mkdir(dir);
1920         f->cd(dir);
1921       }      
1922       return f;
1923     }
1924     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1925     cont->SetFile(NULL);
1926     return NULL;       
1927   }
1928   // Check if there is already a proof output file in the output list
1929   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1930   if (pof) {
1931     // Get the actual file
1932     line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
1933     filename = (const char*)gROOT->ProcessLine(line);
1934     if (fDebug>1) {
1935       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1936     }  
1937     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1938     if (!f) {
1939        Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1940        return NULL;
1941     }   
1942     // Check if option "UPDATE" was preserved 
1943     TString opt(option);
1944     opt.ToUpper();
1945     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1946       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1947   } else {
1948     if (cont->IsRegisterDataset()) {
1949       TString dsetName = filename;
1950       dsetName.ReplaceAll(".root", cont->GetTitle());
1951       dsetName.ReplaceAll(":","_");
1952       if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1953       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1954     } else {
1955       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1956       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1957     }
1958     if (fDebug > 1) printf("=== %s\n", line.Data());
1959     gROOT->ProcessLine(line);
1960     line = Form("pf->OpenFile(\"%s\");", option);
1961     gROOT->ProcessLine(line);
1962     f = gFile;
1963     if (fDebug > 1) {
1964       gROOT->ProcessLine("pf->Print()");
1965       printf(" == proof file name: %s", f->GetName());
1966     }   
1967     // Add to proof output list
1968     line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
1969     if (fDebug > 1) printf("=== %s\n", line.Data());
1970     gROOT->ProcessLine(line);
1971   }
1972   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1973     cont->SetFile(f);
1974     // Cd to file
1975     f->cd();
1976     // Check for a folder request
1977     TString dir = cont->GetFolderName(); 
1978     if (!dir.IsNull()) {
1979       if (!f->GetDirectory(dir)) f->mkdir(dir);
1980       f->cd(dir);
1981     }
1982     return f;
1983   }
1984   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1985   cont->SetFile(NULL);  
1986   return NULL;
1987 }   
1988
1989 //______________________________________________________________________________
1990 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1991 {
1992 // Execute analysis.
1993    static Long64_t nentries = 0;
1994    static TTree *lastTree = 0;
1995    static TStopwatch *timer = new TStopwatch();
1996    // Only the first call to Process will trigger a true Notify. Other Notify
1997    // coming before is ignored.
1998    if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
1999       TObject::SetBit(AliAnalysisManager::kTrueNotify);
2000       Notify();
2001    }   
2002    if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2003    else {
2004       if (fTree && (fTree != lastTree)) {
2005          nentries += fTree->GetEntries();
2006          lastTree = fTree;
2007       }   
2008       if (!fNcalls) timer->Start();
2009       if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2010    }
2011    gROOT->cd();
2012    TDirectory *cdir = gDirectory;
2013    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2014    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2015    if (!fInitOK) {
2016       Error("ExecAnalysis", "Analysis manager was not initialized !");
2017       if (cdir) cdir->cd();
2018       return;
2019    }
2020    fNcalls++;
2021    AliAnalysisTask *task;
2022    // Check if the top tree is active.
2023    if (fTree) {
2024       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2025          AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2026       TIter next(fTasks);
2027    // De-activate all tasks
2028       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2029       AliAnalysisDataContainer *cont = fCommonInput;
2030       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2031       if (!cont) {
2032               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2033          if (cdir) cdir->cd();
2034          return;
2035       }   
2036       cont->SetData(fTree); // This will notify all consumers
2037       Long64_t entry = fTree->GetTree()->GetReadEntry();      
2038 //
2039 //    Call BeginEvent() for optional input/output and MC services 
2040       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
2041       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
2042       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2043       gROOT->cd();
2044       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2045          AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2046 //
2047 //    Execute the tasks
2048 //      TIter next1(cont->GetConsumers());
2049       TIter next1(fTopTasks);
2050       Int_t itask = 0;
2051       while ((task=(AliAnalysisTask*)next1())) {
2052          if (fDebug >1) {
2053             cout << "    Executing task " << task->GetName() << endl;
2054          }       
2055          task->ExecuteTask(option);
2056          gROOT->cd();
2057          if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2058             AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2059          itask++;   
2060       }
2061 //
2062 //    Call FinishEvent() for optional output and MC services 
2063       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2064       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2065       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2066       // Gather system information if requested
2067       if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2068          AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2069       if (cdir) cdir->cd();   
2070       return;
2071    }   
2072    // The event loop is not controlled by TSelector   
2073 //
2074 //  Call BeginEvent() for optional input/output and MC services 
2075    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
2076    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
2077    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2078    gROOT->cd();
2079    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2080       AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2081    TIter next2(fTopTasks);
2082    while ((task=(AliAnalysisTask*)next2())) {
2083       task->SetActive(kTRUE);
2084       if (fDebug > 1) {
2085          cout << "    Executing task " << task->GetName() << endl;
2086       }   
2087       task->ExecuteTask(option);
2088       gROOT->cd();
2089    }   
2090 //
2091 // Call FinishEvent() for optional output and MC services 
2092    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
2093    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
2094    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2095    if (getsysInfo && ((fNcalls%fNSysInfo)==0)) 
2096       AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2097    if (cdir) cdir->cd();   
2098 }
2099
2100 //______________________________________________________________________________
2101 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2102 {
2103 // Check if the stdout is connected to a pipe (C.Holm)
2104   Bool_t ispipe = kFALSE;
2105   out.seekp(0, std::ios_base::cur);
2106   if (out.fail()) {
2107     out.clear();
2108     if (errno == ESPIPE) ispipe = kTRUE;
2109   }
2110   return ispipe;
2111 }
2112    
2113 //______________________________________________________________________________
2114 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2115 {
2116 // Set the input event handler and create a container for it.
2117    fInputEventHandler   = handler;
2118    if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2119 }
2120
2121 //______________________________________________________________________________
2122 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2123 {
2124 // Set the input event handler and create a container for it.
2125    fOutputEventHandler   = handler;
2126    if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2127    fCommonOutput->SetSpecialOutput();
2128 }
2129
2130 //______________________________________________________________________________
2131 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2132 {
2133 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2134    if (TObject::TestBit(kUseProgressBar)) {
2135       Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2136       return;
2137    }
2138    fDebug = level;
2139 }
2140    
2141 //______________________________________________________________________________
2142 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2143 {
2144 // Enable a text mode progress bar. Resets debug level to 0.
2145    Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n  ### NOTE: Debug level reset to 0 ###", freq);
2146    TObject::SetBit(kUseProgressBar,flag);
2147    fPBUpdateFreq = freq;
2148    fDebug = 0;
2149 }   
2150
2151 //______________________________________________________________________________
2152 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2153 {
2154 // This method is used externally to register output files which are not
2155 // connected to any output container, so that the manager can properly register,
2156 // retrieve or merge them when running in distributed mode. The file names are
2157 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2158    if (fExtraFiles.Contains(fname)) return;
2159    if (fExtraFiles.Length()) fExtraFiles += " ";
2160    fExtraFiles += fname;
2161 }
2162
2163 //______________________________________________________________________________
2164 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2165 {
2166 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2167    char fullPath[512];
2168    char chUrl[512];
2169    char tmp[1024];
2170    TObject *pof =  source->FindObject(filename);
2171    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2172       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2173       return kFALSE;
2174    }
2175    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2176    gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2177    TString clientUrl(chUrl);
2178    TString fullPath_str(fullPath);
2179    if (clientUrl.Contains("localhost")){
2180       TObjArray* array = fullPath_str.Tokenize ( "//" );
2181       TObjString *strobj = ( TObjString *)array->At(1);
2182       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2183       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2184       fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2185       fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2186       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2187       delete arrayPort;
2188       delete array;
2189    }
2190    else if (clientUrl.Contains("__lite__")) { 
2191      // Special case for ProofLite environement - get file info and copy. 
2192      gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2193      fullPath_str = Form("%s/%s", tmp, fullPath);
2194    }
2195    if (fDebug > 1) 
2196      Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2197    Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); 
2198    if (!gotit)
2199       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2200    return gotit;
2201 }
2202
2203 //______________________________________________________________________________
2204 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2205 {
2206 // Fill analysis type in the provided string.
2207    switch (fMode) {
2208       case kLocalAnalysis:
2209          type = "local";
2210          return;
2211       case kProofAnalysis:
2212          type = "proof";
2213          return;
2214       case kGridAnalysis:
2215          type = "grid";
2216          return;
2217       case kMixingAnalysis:
2218          type = "mix";
2219    }
2220 }
2221
2222 //______________________________________________________________________________
2223 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2224 {
2225 // Validate all output files.
2226    TIter next(fOutputs);
2227    AliAnalysisDataContainer *output;
2228    TDirectory *cdir = gDirectory;
2229    TString openedFiles;
2230    while ((output=(AliAnalysisDataContainer*)next())) {
2231       if (output->IsRegisterDataset()) continue;
2232       TString filename = output->GetFileName();
2233       if (filename == "default") {
2234          if (!fOutputEventHandler) continue;
2235          filename = fOutputEventHandler->GetOutputFileName();
2236          // Main AOD may not be there
2237          if (gSystem->AccessPathName(filename)) continue;
2238       }
2239       // Check if the file is closed
2240       if (openedFiles.Contains(filename)) continue;;
2241       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2242       if (file) {
2243          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2244          // Clear file list to release object ownership to user.
2245 //         file->Clear();
2246          file->Close();
2247       }
2248       file = TFile::Open(filename);
2249       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2250          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2251          if (cdir) cdir->cd();
2252          return kFALSE;
2253       }
2254       file->Close();
2255       openedFiles += filename;
2256       openedFiles += " ";
2257    }
2258    if (cdir) cdir->cd();
2259    return kTRUE;
2260 }   
2261
2262 //______________________________________________________________________________
2263 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2264 {
2265 // Implements a nice text mode progress bar.
2266    static Long64_t icount = 0;
2267    static TString oname;
2268    static TString nname;
2269    static Long64_t ocurrent = 0;
2270    static Long64_t osize = 0;
2271    static Int_t oseconds = 0;
2272    static TStopwatch *owatch = 0;
2273    static Bool_t oneoftwo = kFALSE;
2274    static Int_t nrefresh = 0;
2275    static Int_t nchecks = 0;
2276    static char lastChar = 0;
2277    const char symbol[4] = {'-','\\','|','/'}; 
2278    
2279    if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2280    if (!refresh) {
2281       nrefresh = 0;
2282       if (!size) return;
2283       owatch = watch;
2284       oname = opname;
2285       ocurrent = TMath::Abs(current);
2286       osize = TMath::Abs(size);
2287       if (ocurrent > osize) ocurrent=osize;
2288    } else {
2289       nrefresh++;
2290       if (!osize) return;
2291    }     
2292    if ((current % fPBUpdateFreq) != 0) return;
2293    icount++;
2294    char progress[11] = "          ";
2295    Int_t ichar = icount%4;
2296    Double_t time = 0.;
2297    Int_t hours = 0;
2298    Int_t minutes = 0;
2299    Int_t seconds = 0;
2300    if (owatch && !last) {
2301       owatch->Stop();
2302       time = owatch->RealTime();
2303       seconds   = int(time) % 60;
2304       minutes   = (int(time) / 60) % 60;
2305       hours     = (int(time) / 60 / 60);
2306       if (refresh)  {
2307          if (oseconds==seconds) {
2308             owatch->Continue();
2309             return;
2310          }
2311          oneoftwo = !oneoftwo;   
2312       }
2313       oseconds = seconds;   
2314    }
2315    if (refresh && oneoftwo) {
2316       nname = oname;
2317       if (nchecks <= 0) nchecks = nrefresh+1;
2318       Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2319       oname = Form("     == %d%% ==", pctdone);
2320    }         
2321    Double_t percent = 100.0*ocurrent/osize;
2322    Int_t nchar = Int_t(percent/10);
2323    if (nchar>10) nchar=10;
2324    Int_t i;
2325    for (i=0; i<nchar; i++)  progress[i] = '=';
2326    progress[nchar] = symbol[ichar];
2327    for (i=nchar+1; i<10; i++) progress[i] = ' ';
2328    progress[10] = '\0';
2329    oname += "                    ";
2330    oname.Remove(20);
2331    if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2332    else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2333    else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2334    if (time>0.) {
2335      Int_t full   = Int_t(ocurrent > 0 ? 
2336                           time * (float(osize)/ocurrent) + .5 : 
2337                           99*3600+59*60+59); 
2338      Int_t remain = Int_t(full - time);
2339      Int_t rsec   = remain % 60;
2340      Int_t rmin   = (remain / 60) % 60;
2341      Int_t rhour  = (remain / 60 / 60);
2342      fprintf(stderr, "[%6.2f %%]   TIME %.2d:%.2d:%.2d  ETA %.2d:%.2d:%.2d%c",
2343              percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2344    }
2345    else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2346    if (refresh && oneoftwo) oname = nname;
2347    if (owatch) owatch->Continue();
2348    if (last) {
2349       icount = 0;
2350       owatch = 0;
2351       ocurrent = 0;
2352       osize = 0;
2353       oseconds = 0;
2354       oneoftwo = kFALSE;
2355       nrefresh = 0;
2356       fprintf(stderr, "\n");
2357    }   
2358 }
2359
2360 //______________________________________________________________________________
2361 void AliAnalysisManager::DoLoadBranch(const char *name) 
2362 {
2363   // Get tree and load branch if needed.
2364   static Long64_t crtEntry = -100;
2365
2366   if (fAutoBranchHandling || !fTree)
2367     return;
2368
2369   TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2370   if (!br) {
2371     br = fTree->GetBranch(name);
2372     if (!br) {
2373       Error("DoLoadBranch", "Could not find branch %s",name);
2374       return;
2375     }
2376     fTable.Add(br);
2377   }
2378   if (br->GetReadEntry()==fCurrentEntry) return;
2379   Int_t ret = br->GetEntry(GetCurrentEntry());
2380   if (ret<0) {
2381     Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2382     if (crtEntry != fCurrentEntry) {
2383       CountEvent(1,0,1,0);
2384       crtEntry = fCurrentEntry;
2385     }  
2386   } else {
2387     if (crtEntry != fCurrentEntry) {
2388       CountEvent(1,1,0,0);
2389       crtEntry = fCurrentEntry;
2390     }
2391   }
2392 }
2393
2394 //______________________________________________________________________________
2395 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2396 {
2397 // Add the statistics task to the manager.
2398   if (fStatistics) {
2399      Info("AddStatisticsTask", "Already added");
2400      return;
2401   }
2402   TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2403   gROOT->ProcessLine(line);
2404 }  
2405
2406 //______________________________________________________________________________
2407 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2408 {
2409 // Bookkeep current event;
2410    if (!fStatistics) return;
2411    fStatistics->AddInput(ninput);
2412    fStatistics->AddProcessed(nprocessed);
2413    fStatistics->AddFailed(nfailed);
2414    fStatistics->AddAccepted(naccepted);
2415 }   
2416
2417 //______________________________________________________________________________
2418 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2419 {
2420 // Add a line in the statistics message. If available, the statistics message is written
2421 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2422 // on the client.
2423    if (!strlen(line)) return;
2424    if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2425    fStatisticsMsg += line;
2426 }
2427
2428 //______________________________________________________________________________
2429 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2430 {
2431 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2432    static Bool_t done = kFALSE;
2433    if (done) return;
2434    done = kTRUE;
2435    if (!fStatistics) return;
2436    ofstream out;
2437    AddStatisticsMsg(Form("Number of input events:        %lld",fStatistics->GetNinput()));
2438    AddStatisticsMsg(Form("Number of processed events:    %lld",fStatistics->GetNprocessed()));      
2439    AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2440    AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2441    out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2442                  fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2443                  fStatistics->GetNaccepted()), ios::out);      
2444    out << fStatisticsMsg << endl;
2445    out.close();
2446 }
2447
2448 //______________________________________________________________________________
2449 const char* AliAnalysisManager::GetOADBPath()
2450 {
2451 // returns the path of the OADB
2452 // this static function just depends on environment variables
2453
2454    static TString oadbPath;
2455
2456    if (gSystem->Getenv("OADB_PATH"))
2457       oadbPath = gSystem->Getenv("OADB_PATH");
2458    else if (gSystem->Getenv("ALICE_ROOT"))
2459       oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2460    else
2461       ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2462       
2463    return oadbPath;
2464 }
2465
2466 //______________________________________________________________________________
2467 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2468 {
2469 // Define a custom string variable mapped to a global unique name. The variable
2470 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2471    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2472    if (!mgr) {
2473       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2474       return;
2475    }   
2476    Bool_t valid = kFALSE;
2477    TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2478    if (valid) {
2479       ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2480       return;
2481    }
2482    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2483 }
2484
2485 //______________________________________________________________________________
2486 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2487 {
2488 // Static method to retrieve a global variable defined via SetGlobalStr.
2489    valid = kFALSE;
2490    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2491    if (!mgr) return 0;
2492    TObject *value = mgr->GetGlobals()->GetValue(key);
2493    if (!value) return 0;
2494    valid = kTRUE;
2495    return value->GetName();
2496 }
2497
2498 //______________________________________________________________________________
2499 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2500 {
2501 // Define a custom integer variable mapped to a global unique name. The variable
2502 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2503    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2504    if (!mgr) {
2505       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2506       return;
2507    }   
2508    Bool_t valid = kFALSE;
2509    Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2510    if (valid) {
2511       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2512       return;
2513    }
2514    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2515 }
2516
2517 //______________________________________________________________________________
2518 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2519 {
2520 // Static method to retrieve a global variable defined via SetGlobalInt.
2521    valid = kFALSE;
2522    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2523    if (!mgr) return 0;
2524    TObject *value = mgr->GetGlobals()->GetValue(key);
2525    if (!value) return 0;
2526    valid = kTRUE;
2527    TString s = value->GetName();
2528    return s.Atoi();
2529 }
2530
2531 //______________________________________________________________________________
2532 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2533 {
2534 // Define a custom double precision variable mapped to a global unique name. The variable
2535 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2536    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2537    if (!mgr) {
2538       ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2539       return;
2540    }   
2541    Bool_t valid = kFALSE;
2542    Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2543    if (valid) {
2544       ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2545       return;
2546    }
2547    mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2548 }
2549
2550 //______________________________________________________________________________
2551 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2552 {
2553 // Static method to retrieve a global variable defined via SetGlobalDbl.
2554    valid = kFALSE;
2555    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2556    if (!mgr) return 0;
2557    TObject *value = mgr->GetGlobals()->GetValue(key);
2558    if (!value) return 0;
2559    valid = kTRUE;
2560    TString s = value->GetName();
2561    return s.Atof();
2562 }
2563
2564 //______________________________________________________________________________
2565 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2566 {
2567 // Sets Class debug level
2568
2569    if (!fDebugOptions) {
2570       fDebugOptions = new TObjArray();
2571       fDebugOptions->SetOwner(kTRUE);
2572    }
2573
2574    // substracting DebugOffset, beacuse of AliLog::SetClassDebugLevel()
2575    debugLevel -= AliLog::kDebug-1;
2576
2577    TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2578    if (!debugOpt) {
2579      AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel+AliLog::kDebug-1,className).Data());
2580      fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2581    } else {
2582       TString oldDebugStr = debugOpt->GetTitle();
2583       Int_t oldDebug = oldDebugStr.Atoi();
2584       if (debugLevel > oldDebug) {
2585          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());
2586          debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2587       } else {
2588          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());
2589       }
2590    }
2591 }
2592
2593 //______________________________________________________________________________
2594 void AliAnalysisManager::ApplyDebugOptions()
2595 {
2596 // Apply debug options
2597
2598    if (!fDebugOptions) return;
2599    
2600    TIter next(fDebugOptions);
2601    TNamed *debug;
2602    TString debugLevel;
2603    while ((debug=dynamic_cast<TNamed*>(next()))) {
2604       debugLevel = debug->GetTitle();
2605       AliInfo(TString::Format("ApplyDebugOptions : Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()+AliLog::kDebug-1).Data());
2606       AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());
2607    }
2608 }
2609