]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ANALYSIS/AliAnalysisManager.cxx
Corrected the way that canvases are saved.
[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 <TMethodCall.h>
35 #include <TChain.h>
36 #include <TSystem.h>
37 #include <TROOT.h>
38 #include <TCanvas.h>
39 #include <TStopwatch.h>
40
41 #include "AliAnalysisSelector.h"
42 #include "AliAnalysisGrid.h"
43 #include "AliAnalysisTask.h"
44 #include "AliAnalysisDataContainer.h"
45 #include "AliAnalysisDataSlot.h"
46 #include "AliVEventHandler.h"
47 #include "AliVEventPool.h"
48 #include "AliSysInfo.h"
49 #include "AliAnalysisManager.h"
50
51 ClassImp(AliAnalysisManager)
52
53 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
54 TString AliAnalysisManager::fgCommonFileName = "";
55
56 //______________________________________________________________________________
57 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
58                    :TNamed(name,title),
59                     fTree(NULL),
60                     fInputEventHandler(NULL),
61                     fOutputEventHandler(NULL),
62                     fMCtruthEventHandler(NULL),
63                     fEventPool(NULL),
64                     fCurrentEntry(-1),
65                     fNSysInfo(0),
66                     fMode(kLocalAnalysis),
67                     fInitOK(kFALSE),
68                     fDebug(0),
69                     fSpecialOutputLocation(""), 
70                     fTasks(NULL),
71                     fTopTasks(NULL),
72                     fZombies(NULL),
73                     fContainers(NULL),
74                     fInputs(NULL),
75                     fOutputs(NULL),
76                     fCommonInput(NULL),
77                     fCommonOutput(NULL),
78                     fSelector(NULL),
79                     fGridHandler(NULL),
80                     fExtraFiles("")
81 {
82 // Default constructor.
83    fgAnalysisManager = this;
84    fgCommonFileName  = "AnalysisResults.root";
85    fTasks      = new TObjArray();
86    fTopTasks   = new TObjArray();
87    fZombies    = new TObjArray();
88    fContainers = new TObjArray();
89    fInputs     = new TObjArray();
90    fOutputs    = new TObjArray();
91    SetEventLoop(kTRUE);
92 }
93
94 //______________________________________________________________________________
95 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
96                    :TNamed(other),
97                     fTree(NULL),
98                     fInputEventHandler(NULL),
99                     fOutputEventHandler(NULL),
100                     fMCtruthEventHandler(NULL),
101                     fEventPool(NULL),
102                     fCurrentEntry(-1),
103                     fNSysInfo(0),
104                     fMode(other.fMode),
105                     fInitOK(other.fInitOK),
106                     fDebug(other.fDebug),
107                     fSpecialOutputLocation(""), 
108                     fTasks(NULL),
109                     fTopTasks(NULL),
110                     fZombies(NULL),
111                     fContainers(NULL),
112                     fInputs(NULL),
113                     fOutputs(NULL),
114                     fCommonInput(NULL),
115                     fCommonOutput(NULL),
116                     fSelector(NULL),
117                     fGridHandler(NULL),
118                     fExtraFiles()
119 {
120 // Copy constructor.
121    fTasks      = new TObjArray(*other.fTasks);
122    fTopTasks   = new TObjArray(*other.fTopTasks);
123    fZombies    = new TObjArray(*other.fZombies);
124    fContainers = new TObjArray(*other.fContainers);
125    fInputs     = new TObjArray(*other.fInputs);
126    fOutputs    = new TObjArray(*other.fOutputs);
127    fgCommonFileName  = "AnalysisResults.root";
128    fgAnalysisManager = this;
129 }
130    
131 //______________________________________________________________________________
132 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
133 {
134 // Assignment
135    if (&other != this) {
136       TNamed::operator=(other);
137       fInputEventHandler   = other.fInputEventHandler;
138       fOutputEventHandler  = other.fOutputEventHandler;
139       fMCtruthEventHandler = other.fMCtruthEventHandler;
140       fEventPool           = other.fEventPool;
141       fTree       = NULL;
142       fCurrentEntry = -1;
143       fNSysInfo   = other.fNSysInfo;
144       fMode       = other.fMode;
145       fInitOK     = other.fInitOK;
146       fDebug      = other.fDebug;
147       fTasks      = new TObjArray(*other.fTasks);
148       fTopTasks   = new TObjArray(*other.fTopTasks);
149       fZombies    = new TObjArray(*other.fZombies);
150       fContainers = new TObjArray(*other.fContainers);
151       fInputs     = new TObjArray(*other.fInputs);
152       fOutputs    = new TObjArray(*other.fOutputs);
153       fCommonInput = NULL;
154       fCommonOutput = NULL;
155       fSelector   = NULL;
156       fGridHandler = NULL;
157       fExtraFiles = other.fExtraFiles;
158       fgCommonFileName = "AnalysisResults.root";
159       fgAnalysisManager = this;
160    }
161    return *this;
162 }
163
164 //______________________________________________________________________________
165 AliAnalysisManager::~AliAnalysisManager()
166 {
167 // Destructor.
168    if (fTasks) {fTasks->Delete(); delete fTasks;}
169    if (fTopTasks) delete fTopTasks;
170    if (fZombies) delete fZombies;
171    if (fContainers) {fContainers->Delete(); delete fContainers;}
172    if (fInputs) delete fInputs;
173    if (fOutputs) delete fOutputs;
174    if (fGridHandler) delete fGridHandler;
175    if (fgAnalysisManager==this) fgAnalysisManager = NULL;
176 }
177
178 //______________________________________________________________________________
179 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
180 {
181 // Read one entry of the tree or a whole branch.
182    if (fDebug > 0) printf("== AliAnalysisManager::GetEntry(%lld)\n", entry);
183    fCurrentEntry = entry;
184    return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
185 }
186    
187 //______________________________________________________________________________
188 Bool_t AliAnalysisManager::Init(TTree *tree)
189 {
190   // The Init() function is called when the selector needs to initialize
191   // a new tree or chain. Typically here the branch addresses of the tree
192   // will be set. It is normaly not necessary to make changes to the
193   // generated code, but the routine can be extended by the user if needed.
194   // Init() will be called many times when running with PROOF.
195    Bool_t init = kFALSE;
196    if (!tree) return kFALSE; // Should not happen - protected in selector caller
197    if (fDebug > 0) {
198       printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
199    }
200    // Call InitTree of EventHandler
201    if (fOutputEventHandler) {
202       if (fMode == kProofAnalysis) {
203          init = fOutputEventHandler->Init(0x0, "proof");
204       } else {
205          init = fOutputEventHandler->Init(0x0, "local");
206       }
207       if (!init) {
208          Error("Init", "Output event handler failed to initialize");
209          return kFALSE;
210       }         
211    }
212    
213    if (fInputEventHandler) {
214       if (fMode == kProofAnalysis) {
215          init = fInputEventHandler->Init(tree, "proof");
216       } else {
217          init = fInputEventHandler->Init(tree, "local");
218       }
219       if (!init) {
220          Error("Init", "Input event handler failed to initialize tree"); 
221          return kFALSE;
222       }         
223    } else {
224       // If no input event handler we need to get the tree once
225       // for the chain
226       if(!tree->GetTree()) {
227          Long64_t readEntry = tree->LoadTree(0);
228          if (readEntry == -2) {
229             Error("Init", "Input tree has no entry. Aborting");
230             return kFALSE;
231          }
232       }   
233    }
234
235    if (fMCtruthEventHandler) {
236       if (fMode == kProofAnalysis) {
237          init = fMCtruthEventHandler->Init(0x0, "proof");
238       } else {
239          init = fMCtruthEventHandler->Init(0x0, "local");
240       }
241       if (!init) {
242          Error("Init", "MC event handler failed to initialize"); 
243          return kFALSE;
244       }         
245    }
246
247    if (!fInitOK) InitAnalysis();
248    if (!fInitOK) return kFALSE;
249    fTree = tree;
250    AliAnalysisDataContainer *top = fCommonInput;
251    if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
252    if (!top) {
253       Error("Init","No top input container !");
254       return kFALSE;
255    }
256    top->SetData(tree);
257    if (fDebug > 0) {
258       printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
259    }
260    return kTRUE;
261 }
262
263 //______________________________________________________________________________
264 void AliAnalysisManager::SlaveBegin(TTree *tree)
265 {
266   // The SlaveBegin() function is called after the Begin() function.
267   // When running with PROOF SlaveBegin() is called on each slave server.
268   // The tree argument is deprecated (on PROOF 0 is passed).
269    if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
270    static Bool_t isCalled = kFALSE;
271    Bool_t init = kFALSE;
272    Bool_t initOK = kTRUE;
273    TString msg;
274    TDirectory *curdir = gDirectory;
275    // Call SlaveBegin only once in case of mixing
276    if (isCalled && fMode==kMixingAnalysis) return;
277    // Call Init of EventHandler
278    if (fOutputEventHandler) {
279       if (fMode == kProofAnalysis) {
280          // Merging AOD's in PROOF via TProofOutputFile
281          if (fDebug > 1) printf("   Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
282          init = fOutputEventHandler->Init("proof");
283          if (!init) msg = "Failed to initialize output handler on worker";
284       } else {
285          init = fOutputEventHandler->Init("local");
286          if (!init) msg = "Failed to initialize output handler";
287       }
288       initOK &= init;
289       if (!fSelector) Error("SlaveBegin", "Selector not set");
290       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
291    }
292
293    if (fInputEventHandler) {
294       fInputEventHandler->SetInputTree(tree);
295       if (fMode == kProofAnalysis) {
296          init = fInputEventHandler->Init("proof");
297          if (!init) msg = "Failed to initialize input handler on worker";
298       } else {
299          init = fInputEventHandler->Init("local");
300          if (!init) msg = "Failed to initialize input handler";
301       }
302       initOK &= init;
303       if (!fSelector) Error("SlaveBegin", "Selector not set");      
304       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
305    }
306
307    if (fMCtruthEventHandler) {
308       if (fMode == kProofAnalysis) {
309          init = fMCtruthEventHandler->Init("proof");
310          if (!init) msg = "Failed to initialize MC handler on worker";
311       } else {
312          init = fMCtruthEventHandler->Init("local");
313          if (!init) msg = "Failed to initialize MC handler";
314       }
315       initOK &= init;
316       if (!fSelector) Error("SlaveBegin", "Selector not set");      
317       else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
318    }
319    if (curdir) curdir->cd();
320    isCalled = kTRUE;
321    if (!initOK) return;   
322    TIter next(fTasks);
323    AliAnalysisTask *task;
324    // Call CreateOutputObjects for all tasks
325    while ((task=(AliAnalysisTask*)next())) {
326       curdir = gDirectory;
327       task->CreateOutputObjects();
328       if (curdir) curdir->cd();
329    }
330    if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
331 }
332
333 //______________________________________________________________________________
334 Bool_t AliAnalysisManager::Notify()
335 {
336    // The Notify() function is called when a new file is opened. This
337    // can be either for a new TTree in a TChain or when when a new TTree
338    // is started when using PROOF. It is normaly not necessary to make changes
339    // to the generated code, but the routine can be extended by the
340    // user if needed. The return value is currently not used.
341    if (!fTree) return kFALSE;
342
343    TFile *curfile = fTree->GetCurrentFile();
344    if (!curfile) {
345       Error("Notify","No current file");
346       return kFALSE;
347    }   
348    
349    if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
350    TIter next(fTasks);
351    AliAnalysisTask *task;
352    // Call Notify for all tasks
353    while ((task=(AliAnalysisTask*)next())) 
354       task->Notify();
355         
356    // Call Notify of the event handlers
357    if (fInputEventHandler) {
358        fInputEventHandler->Notify(curfile->GetName());
359    }
360
361    if (fOutputEventHandler) {
362        fOutputEventHandler->Notify(curfile->GetName());
363    }
364
365    if (fMCtruthEventHandler) {
366        fMCtruthEventHandler->Notify(curfile->GetName());
367    }
368    if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
369    return kTRUE;
370 }    
371
372 //______________________________________________________________________________
373 Bool_t AliAnalysisManager::Process(Long64_t entry)
374 {
375   // The Process() function is called for each entry in the tree (or possibly
376   // keyed object in the case of PROOF) to be processed. The entry argument
377   // specifies which entry in the currently loaded tree is to be processed.
378   // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
379   // to read either all or the required parts of the data. When processing
380   // keyed objects with PROOF, the object is already loaded and is available
381   // via the fObject pointer.
382   //
383   // This function should contain the "body" of the analysis. It can contain
384   // simple or elaborate selection criteria, run algorithms on the data
385   // of the event and typically fill histograms.
386
387   // WARNING when a selector is used with a TChain, you must use
388   //  the pointer to the current TTree to call GetEntry(entry).
389   //  The entry is always the local entry number in the current tree.
390   //  Assuming that fChain is the pointer to the TChain being processed,
391   //  use fChain->GetTree()->GetEntry(entry).
392    if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
393
394    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
395    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
396    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
397    
398    GetEntry(entry);
399    ExecAnalysis();
400    if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
401    return kTRUE;
402 }
403
404 //______________________________________________________________________________
405 void AliAnalysisManager::PackOutput(TList *target)
406 {
407   // Pack all output data containers in the output list. Called at SlaveTerminate
408   // stage in PROOF case for each slave.
409    if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
410    if (!target) {
411       Error("PackOutput", "No target. Aborting.");
412       return;
413    }
414    if (fInputEventHandler)   fInputEventHandler  ->Terminate();
415    if (fOutputEventHandler)  fOutputEventHandler ->Terminate();
416    if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
417
418    // Call FinishTaskOutput() for each event loop task (not called for 
419    // post-event loop tasks - use Terminate() fo those)
420    TIter nexttask(fTasks);
421    AliAnalysisTask *task;
422    while ((task=(AliAnalysisTask*)nexttask())) {
423       if (!task->IsPostEventLoop()) {
424          if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
425          task->FinishTaskOutput();
426          if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
427       }
428    }      
429    
430    if (fMode == kProofAnalysis) {
431       TIter next(fOutputs);
432       AliAnalysisDataContainer *output;
433       Bool_t isManagedByHandler = kFALSE;
434       while ((output=(AliAnalysisDataContainer*)next())) {
435          // Do not consider outputs of post event loop tasks
436          isManagedByHandler = kFALSE;
437          if (output->GetProducer()->IsPostEventLoop()) continue;
438          const char *filename = output->GetFileName();
439          if (!(strcmp(filename, "default")) && fOutputEventHandler) {
440             isManagedByHandler = kTRUE;
441             printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
442             filename = fOutputEventHandler->GetOutputFileName();
443          }
444          // Check if data was posted to this container. If not, issue an error.
445          if (!output->GetData() && !isManagedByHandler) {
446             Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
447             continue;
448          }   
449          if (!output->IsSpecialOutput()) {
450             // Normal outputs
451             if (strlen(filename) && !isManagedByHandler) {
452                // Backup current folder
453                TDirectory *opwd = gDirectory;
454                // File resident outputs
455                TFile *file = AliAnalysisManager::OpenFile(output, "RECREATE", kTRUE);
456                // Clear file list to release object ownership to user.
457                file->Clear();
458                // Save data to file, then close.
459                if (output->GetData()->InheritsFrom(TCollection::Class())) {
460                   // If data is a collection, we set the name of the collection 
461                   // as the one of the container and we save as a single key.
462                   TCollection *coll = (TCollection*)output->GetData();
463                   coll->SetName(output->GetName());
464                   coll->Write(output->GetName(), TObject::kSingleKey);
465                } else {
466                   if (output->GetData()->InheritsFrom(TTree::Class())) {
467                      TTree *tree = (TTree*)output->GetData();
468                      // tree->SetDirectory(file);
469                      tree->AutoSave();
470                   } else {
471                      output->GetData()->Write();
472                   }   
473                }      
474                if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
475                if (fDebug > 2) {
476                   printf("   file %s listing content:\n", filename);
477                   file->ls();
478                }   
479                file->Close();
480                output->SetFile(NULL);
481                // Restore current directory
482                if (opwd) opwd->cd();
483             } else {
484                // Memory-resident outputs   
485                if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
486             }   
487             AliAnalysisDataWrapper *wrap = 0;
488             if (isManagedByHandler) {
489                wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
490                wrap->SetName(output->GetName());
491             }   
492             else                    wrap =output->ExportData();
493             // Output wrappers must NOT delete data after merging - the user owns them
494             wrap->SetDeleteData(kFALSE);
495             target->Add(wrap);
496          } else {
497          // Special outputs. The file must be opened and connected to the container.
498             TDirectory *opwd = gDirectory;
499             TFile *file = output->GetFile();
500             if (!file) {
501                AliAnalysisTask *producer = output->GetProducer();
502                Fatal("PackOutput", 
503                      "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
504                      output->GetFileName(), output->GetName(), producer->ClassName());
505                continue;
506             }   
507             TString outFilename = file->GetName();
508             if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
509             if (isManagedByHandler) {
510                // Terminate IO for files managed by the output handler
511                if (file) file->Write();
512                if (file && fDebug > 2) {
513                   printf("   handled file %s listing content:\n", file->GetName());
514                   file->ls();
515                }   
516                fOutputEventHandler->TerminateIO();
517             } else {               
518                file->cd();
519                // Release object ownership to users after writing data to file
520                if (output->GetData()->InheritsFrom(TCollection::Class())) {
521                   // If data is a collection, we set the name of the collection 
522                   // as the one of the container and we save as a single key.
523                   TCollection *coll = (TCollection*)output->GetData();
524                   coll->SetName(output->GetName());
525                   coll->Write(output->GetName(), TObject::kSingleKey);
526                } else {
527                   if (output->GetData()->InheritsFrom(TTree::Class())) {
528                      TTree *tree = (TTree*)output->GetData();
529                      tree->SetDirectory(file);
530                      tree->AutoSave();
531                   } else {
532                      output->GetData()->Write();
533                   }   
534                }      
535                file->Clear();
536                if (fDebug > 2) {
537                   printf("   file %s listing content:\n", output->GetFileName());
538                   file->ls();
539                }
540                file->Close();
541                output->SetFile(NULL);
542             }
543             // Restore current directory
544             if (opwd) opwd->cd();
545             // Check if a special output location was provided or the output files have to be merged
546             if (strlen(fSpecialOutputLocation.Data())) {
547                TString remote = fSpecialOutputLocation;
548                remote += "/";
549                Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
550                if (remote.BeginsWith("alien://")) {
551                   gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
552                   remote += outFilename;
553                   remote.ReplaceAll(".root", Form("_%d.root", gid));
554                } else {   
555                   remote += Form("%s_%d_", gSystem->HostName(), gid);
556                   remote += outFilename;
557                }   
558                if (fDebug > 1) 
559                   Info("PackOutput", "Output file for container %s to be copied \n   at: %s. No merging.",
560                        output->GetName(), remote.Data());
561                TFile::Cp ( outFilename.Data(), remote.Data() );
562                // Copy extra outputs
563                if (fExtraFiles.Length() && isManagedByHandler) {
564                   TObjArray *arr = fExtraFiles.Tokenize(" ");
565                   TObjString *os;
566                   TIter nextfilename(arr);
567                   while ((os=(TObjString*)nextfilename())) {
568                      outFilename = os->GetString();
569                      remote = fSpecialOutputLocation;
570                      remote += "/";
571                      if (remote.BeginsWith("alien://")) {
572                         remote += outFilename;
573                         remote.ReplaceAll(".root", Form("_%d.root", gid));
574                      } else {   
575                         remote += Form("%s_%d_", gSystem->HostName(), gid);
576                         remote += outFilename;
577                      }   
578                      if (fDebug > 1) 
579                         Info("PackOutput", "Extra AOD file %s to be copied \n   at: %s. No merging.",
580                              outFilename.Data(), remote.Data());
581                      TFile::Cp ( outFilename.Data(), remote.Data() );
582                   }   
583                   delete arr;
584                }   
585             } else {
586             // No special location specified-> use TProofOutputFile as merging utility
587             // The file at this output slot must be opened in CreateOutputObjects
588                if (fDebug > 1) printf("   File for container %s to be merged via file merger...\n", output->GetName());
589             }
590          }      
591       }
592    } 
593    if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
594 }
595
596 //______________________________________________________________________________
597 void AliAnalysisManager::ImportWrappers(TList *source)
598 {
599 // Import data in output containers from wrappers coming in source.
600    if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
601    TIter next(fOutputs);
602    AliAnalysisDataContainer *cont;
603    AliAnalysisDataWrapper   *wrap;
604    Int_t icont = 0;
605    Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
606    TDirectory *cdir = gDirectory;
607    while ((cont=(AliAnalysisDataContainer*)next())) {
608       wrap = 0;
609       if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
610       const char *filename = cont->GetFileName();
611       Bool_t isManagedByHandler = kFALSE;
612       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
613          isManagedByHandler = kTRUE;
614          filename = fOutputEventHandler->GetOutputFileName();
615       }
616       if (cont->IsSpecialOutput() || inGrid) {
617          if (strlen(fSpecialOutputLocation.Data())) continue;
618          // Copy merged file from PROOF scratch space. 
619          // In case of grid the files are already in the current directory.
620          if (!inGrid) {
621             if (isManagedByHandler && fExtraFiles.Length()) {
622                // Copy extra registered dAOD files.
623                TObjArray *arr = fExtraFiles.Tokenize(" ");
624                TObjString *os;
625                TIter nextfilename(arr);
626                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
627                delete arr;
628             }
629             if (!GetFileFromWrapper(filename, source)) continue;
630          }   
631          // Normally we should connect data from the copied file to the
632          // corresponding output container, but it is not obvious how to do this
633          // automatically if several objects in file...
634          TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
635          if (!f) f = TFile::Open(filename, "READ");
636          if (!f) {
637             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
638             continue;
639          }   
640          TObject *obj = 0;
641          // Cd to the directory pointed by the container
642          TString folder = cont->GetFolderName();
643          if (!folder.IsNull()) f->cd(folder);
644          // Try to fetch first an object having the container name.
645          obj = gDirectory->Get(cont->GetName());
646          if (!obj) {
647             Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()", 
648                     cont->GetName(), filename, cont->GetFolderName());
649             continue;
650          }  
651          wrap = new AliAnalysisDataWrapper(obj);
652          wrap->SetDeleteData(kFALSE);
653       }   
654       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
655       if (!wrap) {
656          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
657          continue;
658       }
659       icont++;
660       if (fDebug > 1) {
661          printf("   Importing data for container %s\n", cont->GetName());
662          if (strlen(filename)) printf("    -> file %s\n", filename);
663          else printf("\n");
664       }   
665       cont->ImportData(wrap);
666    }
667    if (cdir) cdir->cd();
668    if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
669 }
670
671 //______________________________________________________________________________
672 void AliAnalysisManager::UnpackOutput(TList *source)
673 {
674   // Called by AliAnalysisSelector::Terminate only on the client.
675    if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
676    if (!source) {
677       Error("UnpackOutput", "No target. Aborting.");
678       return;
679    }
680    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
681
682    if (fMode == kProofAnalysis) ImportWrappers(source);
683
684    TIter next(fOutputs);
685    AliAnalysisDataContainer *output;
686    while ((output=(AliAnalysisDataContainer*)next())) {
687       if (!output->GetData()) continue;
688       // Check if there are client tasks that run post event loop
689       if (output->HasConsumers()) {
690          // Disable event loop semaphore
691          output->SetPostEventLoop(kTRUE);
692          TObjArray *list = output->GetConsumers();
693          Int_t ncons = list->GetEntriesFast();
694          for (Int_t i=0; i<ncons; i++) {
695             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
696             task->CheckNotify(kTRUE);
697             // If task is active, execute it
698             if (task->IsPostEventLoop() && task->IsActive()) {
699                if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
700                task->ExecuteTask();
701             }   
702          }
703       }   
704    }
705    if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
706 }
707
708 //______________________________________________________________________________
709 void AliAnalysisManager::Terminate()
710 {
711   // The Terminate() function is the last function to be called during
712   // a query. It always runs on the client, it can be used to present
713   // the results graphically.
714    if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
715    AliAnalysisTask *task;
716    AliAnalysisDataContainer *output;
717    TIter next(fTasks);
718    TStopwatch timer;
719    // Call Terminate() for tasks
720    while ((task=(AliAnalysisTask*)next())) {
721       // Save all the canvases produced by the Terminate
722       TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
723       task->Terminate();
724       if (TObject::TestBit(kSaveCanvases)) {
725          if (!gROOT->IsBatch()) {
726             Warning("Terminate", "Waiting 5 sec for %s::Terminate() to finish drawing", task->ClassName());
727             timer.Start();
728             while (timer.CpuTime()<5) {
729                timer.Continue();
730                gSystem->ProcessEvents();
731             }
732          }
733          Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
734          if (iend==0) continue;
735          TCanvas *canvas;
736          for (Int_t ipict=0; ipict<iend; ipict++) {
737             canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
738             if (!canvas) continue;         
739             canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
740          } 
741          gROOT->GetListOfCanvases()->Delete(); 
742       }
743    }   
744    //
745    TIter next1(fOutputs);
746    while ((output=(AliAnalysisDataContainer*)next1())) {
747       // Special outputs or grid files have the files already closed and written.
748       if (fMode == kGridAnalysis) continue;
749       if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
750       const char *filename = output->GetFileName();
751       if (!(strcmp(filename, "default"))) {
752          if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
753          TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
754          if (aodfile) {
755             if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
756             aodfile->Write();
757             continue;
758          }   
759       }      
760       if (!strlen(filename)) continue;
761       if (!output->GetData()) continue;
762       TDirectory *opwd = gDirectory;
763       TFile *file = output->GetFile();
764       if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
765       if (!file) file = new TFile(filename, "RECREATE");
766       if (file->IsZombie()) {
767          Error("Terminate", "Cannot open output file %s", filename);
768          continue;
769       }   
770       output->SetFile(file);
771       file->cd();
772       // Check for a folder request
773       TString dir = output->GetFolderName();
774       if (!dir.IsNull()) {
775          if (!file->GetDirectory(dir)) file->mkdir(dir);
776          file->cd(dir);
777       }  
778       if (fDebug > 1) printf("   writing output data %s to file %s:%s\n", output->GetData()->GetName(), file->GetName(), output->GetFolderName());
779       if (output->GetData()->InheritsFrom(TCollection::Class())) {
780       // If data is a collection, we set the name of the collection 
781       // as the one of the container and we save as a single key.
782          TCollection *coll = (TCollection*)output->GetData();
783          coll->SetName(output->GetName());
784          coll->Write(output->GetName(), TObject::kSingleKey);
785       } else {
786          if (output->GetData()->InheritsFrom(TTree::Class())) {
787             TTree *tree = (TTree*)output->GetData();
788             tree->SetDirectory(file);
789             tree->AutoSave();
790          } else {
791             output->GetData()->Write();
792          }   
793       }      
794       if (opwd) opwd->cd();
795    }   
796    next1.Reset();
797    while ((output=(AliAnalysisDataContainer*)next1())) {
798       // Close all files at output
799       TDirectory *opwd = gDirectory;
800       if (output->GetFile()) {
801          output->GetFile()->Close();
802          output->SetFile(NULL);
803          // Copy merged outputs in alien if requested
804          if (fSpecialOutputLocation.Length() && 
805              fSpecialOutputLocation.BeginsWith("alien://")) {
806             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
807             TFile::Cp(output->GetFile()->GetName(), 
808                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
809          }             
810       }   
811       if (opwd) opwd->cd();
812    }   
813
814    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
815    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
816    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
817
818    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
819    if (getsysInfo) {
820       TDirectory *cdir = gDirectory;
821       TFile f("syswatch.root", "RECREATE");
822       if (!f.IsZombie()) {
823          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
824          tree->SetMarkerStyle(kCircle);
825          tree->SetMarkerColor(kBlue);
826          tree->SetMarkerSize(0.5);
827          if (!gROOT->IsBatch()) {
828             tree->SetAlias("event", "id0");
829             tree->SetAlias("memUSED", "mi.fMemUsed");
830             new TCanvas("SysInfo","SysInfo",10,10,800,600);
831             tree->Draw("memUSED:event","","", 1234567890, 0);
832          }   
833          tree->Write();
834          f.Close();
835          delete tree;
836       }
837       if (cdir) cdir->cd();
838    }
839    // Validate the output files
840    if (ValidateOutputFiles()) {
841       ofstream out;
842       out.open("outputs_valid", ios::out);
843       out.close();
844    }      
845    if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
846 }
847
848 //______________________________________________________________________________
849 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
850 {
851 // Adds a user task to the global list of tasks.
852    if (fTasks->FindObject(task)) {
853       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
854       return;
855    }   
856    task->SetActive(kFALSE);
857    fTasks->Add(task);
858 }  
859
860 //______________________________________________________________________________
861 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
862 {
863 // Retreive task by name.
864    if (!fTasks) return NULL;
865    return (AliAnalysisTask*)fTasks->FindObject(name);
866 }
867
868 //______________________________________________________________________________
869 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
870                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
871 {
872 // Create a data container of a certain type. Types can be:
873 //   kExchangeContainer  = 0, used to exchange data between tasks
874 //   kInputContainer   = 1, used to store input data
875 //   kOutputContainer  = 2, used for writing result to a file
876 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
877 // the output object to a folder inside the output file
878    if (fContainers->FindObject(name)) {
879       Error("CreateContainer","A container named %s already defined !",name);
880       return NULL;
881    }   
882    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
883    fContainers->Add(cont);
884    switch (type) {
885       case kInputContainer:
886          fInputs->Add(cont);
887          break;
888       case kOutputContainer:
889          fOutputs->Add(cont);
890          if (filename && strlen(filename)) {
891             cont->SetFileName(filename);
892             cont->SetDataOwned(kFALSE);  // data owned by the file
893          }   
894          break;
895       case kExchangeContainer:
896          break;   
897    }
898    return cont;
899 }
900          
901 //______________________________________________________________________________
902 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
903                                         AliAnalysisDataContainer *cont)
904 {
905 // Connect input of an existing task to a data container.
906    if (!task) {
907       Error("ConnectInput", "Task pointer is NULL");
908       return kFALSE;
909    }   
910    if (!fTasks->FindObject(task)) {
911       AddTask(task);
912       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
913    } 
914    Bool_t connected = task->ConnectInput(islot, cont);
915    return connected;
916 }   
917
918 //______________________________________________________________________________
919 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
920                                         AliAnalysisDataContainer *cont)
921 {
922 // Connect output of an existing task to a data container.
923    if (!task) {
924       Error("ConnectOutput", "Task pointer is NULL");
925       return kFALSE;
926    }   
927    if (!fTasks->FindObject(task)) {
928       AddTask(task);
929       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
930    } 
931    Bool_t connected = task->ConnectOutput(islot, cont);
932    return connected;
933 }   
934                                
935 //______________________________________________________________________________
936 void AliAnalysisManager::CleanContainers()
937 {
938 // Clean data from all containers that have already finished all client tasks.
939    TIter next(fContainers);
940    AliAnalysisDataContainer *cont;
941    while ((cont=(AliAnalysisDataContainer *)next())) {
942       if (cont->IsOwnedData() && 
943           cont->IsDataReady() && 
944           cont->ClientsExecuted()) cont->DeleteData();
945    }
946 }
947
948 //______________________________________________________________________________
949 Bool_t AliAnalysisManager::InitAnalysis()
950 {
951 // Initialization of analysis chain of tasks. Should be called after all tasks
952 // and data containers are properly connected
953    // Reset flag and remove valid_outputs file if exists
954    fInitOK = kFALSE;
955    if (!gSystem->AccessPathName("outputs_valid"))
956       gSystem->Unlink("outputs_valid");
957    // Check for top tasks (depending only on input data containers)
958    if (!fTasks->First()) {
959       Error("InitAnalysis", "Analysis has no tasks !");
960       return kFALSE;
961    }   
962    TIter next(fTasks);
963    AliAnalysisTask *task;
964    AliAnalysisDataContainer *cont;
965    Int_t ntop = 0;
966    Int_t nzombies = 0;
967    Bool_t iszombie = kFALSE;
968    Bool_t istop = kTRUE;
969    Int_t i;
970    while ((task=(AliAnalysisTask*)next())) {
971       istop = kTRUE;
972       iszombie = kFALSE;
973       Int_t ninputs = task->GetNinputs();
974       for (i=0; i<ninputs; i++) {
975          cont = task->GetInputSlot(i)->GetContainer();
976          if (!cont) {
977             if (!iszombie) {
978                task->SetZombie();
979                fZombies->Add(task);
980                nzombies++;
981                iszombie = kTRUE;
982             }   
983             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
984                   i, task->GetName()); 
985          }
986          if (iszombie) continue;
987          // Check if cont is an input container
988          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
989          // Connect to parent task
990       }
991       if (istop) {
992          ntop++;
993          fTopTasks->Add(task);
994       }
995    }
996    if (!ntop) {
997       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
998       return kFALSE;
999    }                        
1000    // Check now if there are orphan tasks
1001    for (i=0; i<ntop; i++) {
1002       task = (AliAnalysisTask*)fTopTasks->At(i);
1003       task->SetUsed();
1004    }
1005    Int_t norphans = 0;
1006    next.Reset();
1007    while ((task=(AliAnalysisTask*)next())) {
1008       if (!task->IsUsed()) {
1009          norphans++;
1010          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1011       }   
1012    }          
1013    // Check the task hierarchy (no parent task should depend on data provided
1014    // by a daughter task)
1015    for (i=0; i<ntop; i++) {
1016       task = (AliAnalysisTask*)fTopTasks->At(i);
1017       if (task->CheckCircularDeps()) {
1018          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1019          PrintStatus("dep");
1020          return kFALSE;
1021       }   
1022    }
1023    // Check that all containers feeding post-event loop tasks are in the outputs list
1024    TIter nextcont(fContainers); // loop over all containers
1025    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1026       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1027          if (cont->HasConsumers()) {
1028          // Check if one of the consumers is post event loop
1029             TIter nextconsumer(cont->GetConsumers());
1030             while ((task=(AliAnalysisTask*)nextconsumer())) {
1031                if (task->IsPostEventLoop()) {
1032                   fOutputs->Add(cont);
1033                   break;
1034                }
1035             }
1036          }
1037       }
1038    }   
1039    // Check if all special output containers have a file name provided
1040    TIter nextout(fOutputs);
1041    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1042       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1043          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1044          return kFALSE;
1045       }
1046    }      
1047    fInitOK = kTRUE;
1048    return kTRUE;
1049 }   
1050
1051 //______________________________________________________________________________
1052 void AliAnalysisManager::PrintStatus(Option_t *option) const
1053 {
1054 // Print task hierarchy.
1055    if (!fInitOK) {
1056       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1057       return;
1058    }   
1059    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1060    if (getsysInfo)
1061       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1062    TIter next(fTopTasks);
1063    AliAnalysisTask *task;
1064    while ((task=(AliAnalysisTask*)next()))
1065       task->PrintTask(option);
1066 }
1067
1068 //______________________________________________________________________________
1069 void AliAnalysisManager::ResetAnalysis()
1070 {
1071 // Reset all execution flags and clean containers.
1072    CleanContainers();
1073 }
1074
1075 //______________________________________________________________________________
1076 void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
1077 {
1078 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1079 // MIX. Process nentries starting from firstentry
1080    if (!fInitOK) {
1081       Error("StartAnalysis","Analysis manager was not initialized !");
1082       return;
1083    }
1084    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1085    TString anaType = type;
1086    anaType.ToLower();
1087    fMode = kLocalAnalysis;
1088    Bool_t runlocalinit = kTRUE;
1089    if (anaType.Contains("file")) runlocalinit = kFALSE;
1090    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1091    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1092    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1093
1094    if (fMode == kGridAnalysis) {
1095       if (!fGridHandler) {
1096          Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1097          Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1098          return;
1099       }
1100       // Write analysis manager in the analysis file
1101       cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1102       // run local task configuration
1103       TIter nextTask(fTasks);
1104       AliAnalysisTask *task;
1105       while ((task=(AliAnalysisTask*)nextTask())) {
1106          task->LocalInit();
1107       }
1108       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1109          Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1110          return;
1111       }   
1112
1113       // Terminate grid analysis
1114       if (fSelector && fSelector->GetStatus() == -1) return;
1115       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1116       cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1117       if (!fGridHandler->MergeOutputs()) {
1118          // Return if outputs could not be merged or if it alien handler
1119          // was configured for offline mode or local testing.
1120          return;
1121       }
1122       ImportWrappers(NULL);
1123       Terminate();
1124       return;
1125    }
1126    char line[256];
1127    SetEventLoop(kFALSE);
1128    // Enable event loop mode if a tree was provided
1129    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1130
1131    TChain *chain = 0;
1132    TString ttype = "TTree";
1133    if (tree && tree->IsA() == TChain::Class()) {
1134       chain = (TChain*)tree;
1135       if (!chain || !chain->GetListOfFiles()->First()) {
1136          Error("StartAnalysis", "Cannot process null or empty chain...");
1137          return;
1138       }   
1139       ttype = "TChain";
1140    }   
1141
1142    // Initialize locally all tasks (happens for all modes)
1143    TIter next(fTasks);
1144    AliAnalysisTask *task;
1145    if (runlocalinit) {
1146       while ((task=(AliAnalysisTask*)next())) {
1147          task->LocalInit();
1148       }
1149    }   
1150    
1151    switch (fMode) {
1152       case kLocalAnalysis:
1153          if (!tree) {
1154             TIter nextT(fTasks);
1155             // Call CreateOutputObjects for all tasks
1156             while ((task=(AliAnalysisTask*)nextT())) {
1157                TDirectory *curdir = gDirectory;
1158                task->CreateOutputObjects();
1159                if (curdir) curdir->cd();
1160             }   
1161             if (IsExternalLoop()) {
1162                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1163                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1164                return;
1165             }         
1166             ExecAnalysis();
1167             Terminate();
1168             return;
1169          } 
1170          // Run tree-based analysis via AliAnalysisSelector  
1171          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1172          fSelector = new AliAnalysisSelector(this);
1173          tree->Process(fSelector, "", nentries, firstentry);
1174          break;
1175       case kProofAnalysis:
1176          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1177             Error("StartAnalysis", "No PROOF!!! Aborting.");
1178             return;
1179          }   
1180          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1181          gROOT->ProcessLine(line);
1182          if (chain) {
1183             chain->SetProof();
1184             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1185             chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1186          } else {
1187             Error("StartAnalysis", "No chain!!! Aborting.");
1188             return;
1189          }      
1190          break;
1191       case kGridAnalysis:
1192          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1193          break;
1194       case kMixingAnalysis:   
1195          // Run event mixing analysis
1196          if (!fEventPool) {
1197             Error("StartAnalysis", "Cannot run event mixing without event pool");
1198             return;
1199          }
1200          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1201          fSelector = new AliAnalysisSelector(this);
1202          while ((chain=fEventPool->GetNextChain())) {
1203             next.Reset();
1204             // Call NotifyBinChange for all tasks
1205             while ((task=(AliAnalysisTask*)next()))
1206                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1207             chain->Process(fSelector);
1208          }
1209          PackOutput(fSelector->GetOutputList());
1210          Terminate();
1211    }   
1212 }   
1213
1214 //______________________________________________________________________________
1215 void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1216 {
1217 // Start analysis for this manager on a given dataset. Analysis task can be: 
1218 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1219    if (!fInitOK) {
1220       Error("StartAnalysis","Analysis manager was not initialized !");
1221       return;
1222    }
1223    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1224    TString anaType = type;
1225    anaType.ToLower();
1226    if (!anaType.Contains("proof")) {
1227       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1228       return;
1229    }   
1230    fMode = kProofAnalysis;
1231    char line[256];
1232    SetEventLoop(kTRUE);
1233    // Set the dataset flag
1234    TObject::SetBit(kUseDataSet);
1235    fTree = 0;
1236
1237    // Initialize locally all tasks
1238    TIter next(fTasks);
1239    AliAnalysisTask *task;
1240    while ((task=(AliAnalysisTask*)next())) {
1241       task->LocalInit();
1242    }
1243    
1244    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1245       Error("StartAnalysis", "No PROOF!!! Aborting.");
1246       return;
1247    }   
1248    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1249    gROOT->ProcessLine(line);
1250    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1251    if (!gROOT->ProcessLine(line)) {
1252       Error("StartAnalysis", "Dataset %s not found", dataset);
1253       return;
1254    }   
1255    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1256            dataset, nentries, firstentry);
1257    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1258    gROOT->ProcessLine(line);
1259 }   
1260
1261 //______________________________________________________________________________
1262 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1263 {
1264 // Opens according the option the file specified by cont->GetFileName() and changes
1265 // current directory to cont->GetFolderName(). If the file was already opened, it
1266 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1267 // be optionally ignored.
1268   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1269   TString filename = cont->GetFileName();
1270   TFile *f = NULL;
1271   if (filename.IsNull()) {
1272     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1273     return NULL;
1274   }
1275   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1276       && !ignoreProof)
1277     f = mgr->OpenProofFile(cont,option);
1278   else {
1279     // Check first if the file is already opened
1280     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1281     if (f) {
1282       // Check if option "UPDATE" was preserved 
1283       TString opt(option);
1284       opt.ToUpper();
1285       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1286         ::Fatal("AliAnalysisManager::OpenFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1287     } else {
1288       f = TFile::Open(filename, option);
1289     }    
1290   }   
1291   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1292     cont->SetFile(f);
1293     // Cd to file
1294     f->cd();
1295     // Check for a folder request
1296     TString dir = cont->GetFolderName(); 
1297     if (!dir.IsNull()) {
1298       if (!f->GetDirectory(dir)) f->mkdir(dir);
1299       f->cd(dir);
1300     }
1301     return f;
1302   }
1303   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1304   cont->SetFile(NULL);
1305   return NULL;
1306 }    
1307  
1308 //______________________________________________________________________________
1309 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
1310 {
1311 // Opens a special output file used in PROOF.
1312   TString line;
1313   TString filename = cont->GetFileName();
1314   if (cont == fCommonOutput) {
1315      if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1316      else Fatal("OpenProofFile","No output container. Aborting.");
1317   }   
1318   TFile *f = NULL;
1319   if (fMode!=kProofAnalysis || !fSelector) {
1320     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1321     return NULL;
1322   } 
1323   if (fSpecialOutputLocation.Length()) {
1324     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1325     if (f) {
1326       // Check if option "UPDATE" was preserved 
1327       TString opt(option);
1328       opt.ToUpper();
1329       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1330         Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1331     } else {
1332       f = new TFile(filename, option);
1333     }
1334     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1335       cont->SetFile(f);
1336       // Cd to file
1337       f->cd();
1338       // Check for a folder request
1339       TString dir = cont->GetFolderName(); 
1340       if (dir.Length()) {
1341         if (!f->GetDirectory(dir)) f->mkdir(dir);
1342         f->cd(dir);
1343       }      
1344       return f;
1345     }
1346     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1347     cont->SetFile(NULL);
1348     return NULL;       
1349   }
1350   // Check if there is already a proof output file in the output list
1351   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1352   if (pof) {
1353     // Get the actual file
1354     line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1355     filename = (const char*)gROOT->ProcessLine(line);
1356     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1357     if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1358     // Check if option "UPDATE" was preserved 
1359     TString opt(option);
1360     opt.ToUpper();
1361     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1362       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1363   } else {
1364     line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1365     if (fDebug > 1) printf("=== %s\n", line.Data());
1366     gROOT->ProcessLine(line);
1367     line = Form("pf->OpenFile(\"%s\");", option);
1368     gROOT->ProcessLine(line);
1369     f = gFile;
1370     if (fDebug > 1) {
1371       gROOT->ProcessLine("pf->Print()");
1372       printf(" == proof file name: %s", f->GetName());
1373     }   
1374     // Add to proof output list
1375     line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1376     if (fDebug > 1) printf("=== %s", line.Data());
1377     gROOT->ProcessLine(line);
1378   }
1379   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1380     cont->SetFile(f);
1381     // Cd to file
1382     f->cd();
1383     // Check for a folder request
1384     TString dir = cont->GetFolderName(); 
1385     if (!dir.IsNull()) {
1386       if (!f->GetDirectory(dir)) f->mkdir(dir);
1387       f->cd(dir);
1388     }
1389     return f;
1390   }
1391   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1392   cont->SetFile(NULL);  
1393   return NULL;
1394 }   
1395
1396 //______________________________________________________________________________
1397 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1398 {
1399 // Execute analysis.
1400    static Long64_t ncalls = 0;
1401    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1402    if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1403    ncalls++;
1404    if (!fInitOK) {
1405      Error("ExecAnalysis", "Analysis manager was not initialized !");
1406       return;
1407    }   
1408    AliAnalysisTask *task;
1409    // Check if the top tree is active.
1410    if (fTree) {
1411       TIter next(fTasks);
1412    // De-activate all tasks
1413       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1414       AliAnalysisDataContainer *cont = fCommonInput;
1415       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1416       if (!cont) {
1417               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1418          return;
1419       }   
1420       cont->SetData(fTree); // This will notify all consumers
1421       Long64_t entry = fTree->GetTree()->GetReadEntry();
1422       
1423 //
1424 //    Call BeginEvent() for optional input/output and MC services 
1425       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1426       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1427       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1428 //
1429 //    Execute the tasks
1430 //      TIter next1(cont->GetConsumers());
1431       TIter next1(fTopTasks);
1432       while ((task=(AliAnalysisTask*)next1())) {
1433          if (fDebug >1) {
1434             cout << "    Executing task " << task->GetName() << endl;
1435          }   
1436          
1437          task->ExecuteTask(option);
1438       }
1439 //
1440 //    Call FinishEvent() for optional output and MC services 
1441       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1442       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1443       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1444       // Gather system information if requested
1445       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1446          AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
1447       return;
1448    }   
1449    // The event loop is not controlled by TSelector   
1450 //
1451 //  Call BeginEvent() for optional input/output and MC services 
1452    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1453    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1454    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1455    TIter next2(fTopTasks);
1456    while ((task=(AliAnalysisTask*)next2())) {
1457       task->SetActive(kTRUE);
1458       if (fDebug > 1) {
1459          cout << "    Executing task " << task->GetName() << endl;
1460       }   
1461       task->ExecuteTask(option);
1462    }   
1463 //
1464 // Call FinishEvent() for optional output and MC services 
1465    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1466    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1467    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1468 }
1469
1470 //______________________________________________________________________________
1471 void AliAnalysisManager::FinishAnalysis()
1472 {
1473 // Finish analysis.
1474 }
1475
1476 //______________________________________________________________________________
1477 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler*  handler)
1478 {
1479 // Set the input event handler and create a container for it.
1480    fInputEventHandler   = handler;
1481    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1482    Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1483 }
1484
1485 //______________________________________________________________________________
1486 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler*  handler)
1487 {
1488 // Set the input event handler and create a container for it.
1489    fOutputEventHandler   = handler;
1490    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1491    fCommonOutput->SetSpecialOutput();
1492    Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1493 }
1494
1495 //______________________________________________________________________________
1496 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1497 {
1498 // This method is used externally to register output files which are not
1499 // connected to any output container, so that the manager can properly register,
1500 // retrieve or merge them when running in distributed mode. The file names are
1501 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1502    if (fExtraFiles.Length()) fExtraFiles += " ";
1503    fExtraFiles += fname;
1504 }
1505
1506 //______________________________________________________________________________
1507 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1508 {
1509 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1510    char full_path[512];
1511    char ch_url[512];
1512    TObject *pof =  source->FindObject(filename);
1513    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1514       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1515       return kFALSE;
1516    }
1517    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1518    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1519    TString clientUrl(ch_url);
1520    TString full_path_str(full_path);
1521    if (clientUrl.Contains("localhost")){
1522       TObjArray* array = full_path_str.Tokenize ( "//" );
1523       TObjString *strobj = ( TObjString *)array->At(1);
1524       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1525       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1526       full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1527       full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1528       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1529       delete arrayPort;
1530       delete array;
1531    }
1532    if (fDebug > 1) 
1533       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1534    Bool_t gotit = TFile::Cp(full_path_str.Data(), filename); 
1535    if (!gotit)
1536       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1537    return gotit;
1538 }
1539
1540 //______________________________________________________________________________
1541 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1542 {
1543 // Fill analysis type in the provided string.
1544    switch (fMode) {
1545       case kLocalAnalysis:
1546          type = "local";
1547          return;
1548       case kProofAnalysis:
1549          type = "proof";
1550          return;
1551       case kGridAnalysis:
1552          type = "grid";
1553          return;
1554       case kMixingAnalysis:
1555          type = "mix";
1556    }
1557 }
1558
1559 //______________________________________________________________________________
1560 Bool_t AliAnalysisManager::ValidateOutputFiles() const
1561 {
1562 // Validate all output files.
1563    TIter next(fOutputs);
1564    AliAnalysisDataContainer *output;
1565    TDirectory *cdir = gDirectory;
1566    TString openedFiles;
1567    while ((output=(AliAnalysisDataContainer*)next())) {
1568       TString filename = output->GetFileName();
1569       if (filename == "default") {
1570          if (!fOutputEventHandler) continue;
1571          filename = fOutputEventHandler->GetOutputFileName();
1572       }
1573       // Check if the file is closed
1574       if (openedFiles.Contains(filename)) continue;;
1575       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1576       if (file) {
1577          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1578          file->Close();
1579       }
1580       file = TFile::Open(filename);
1581       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1582          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1583          cdir->cd();
1584          return kFALSE;
1585       }
1586       file->Close();
1587       openedFiles += filename;
1588       openedFiles += " ";
1589    }
1590    cdir->cd();
1591    return kTRUE;
1592 }