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