cdccc6739a951c6a6c28b517d42548aeb4b3cacd
[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       if (cont->IsRegisterDataset()) continue;
611       const char *filename = cont->GetFileName();
612       Bool_t isManagedByHandler = kFALSE;
613       if (!(strcmp(filename, "default")) && fOutputEventHandler) {
614          isManagedByHandler = kTRUE;
615          filename = fOutputEventHandler->GetOutputFileName();
616       }
617       if (cont->IsSpecialOutput() || inGrid) {
618          if (strlen(fSpecialOutputLocation.Data())) continue;
619          // Copy merged file from PROOF scratch space. 
620          // In case of grid the files are already in the current directory.
621          if (!inGrid) {
622             if (isManagedByHandler && fExtraFiles.Length()) {
623                // Copy extra registered dAOD files.
624                TObjArray *arr = fExtraFiles.Tokenize(" ");
625                TObjString *os;
626                TIter nextfilename(arr);
627                while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
628                delete arr;
629             }
630             if (!GetFileFromWrapper(filename, source)) continue;
631          }   
632          // Normally we should connect data from the copied file to the
633          // corresponding output container, but it is not obvious how to do this
634          // automatically if several objects in file...
635          TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
636          if (!f) f = TFile::Open(filename, "READ");
637          if (!f) {
638             Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
639             continue;
640          }   
641          TObject *obj = 0;
642          // Cd to the directory pointed by the container
643          TString folder = cont->GetFolderName();
644          if (!folder.IsNull()) f->cd(folder);
645          // Try to fetch first an object having the container name.
646          obj = gDirectory->Get(cont->GetName());
647          if (!obj) {
648             Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()", 
649                     cont->GetName(), filename, cont->GetFolderName());
650             continue;
651          }  
652          wrap = new AliAnalysisDataWrapper(obj);
653          wrap->SetDeleteData(kFALSE);
654       }   
655       if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
656       if (!wrap) {
657          Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
658          continue;
659       }
660       icont++;
661       if (fDebug > 1) {
662          printf("   Importing data for container %s\n", cont->GetName());
663          if (strlen(filename)) printf("    -> file %s\n", filename);
664          else printf("\n");
665       }   
666       cont->ImportData(wrap);
667    }
668    if (cdir) cdir->cd();
669    if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
670 }
671
672 //______________________________________________________________________________
673 void AliAnalysisManager::UnpackOutput(TList *source)
674 {
675   // Called by AliAnalysisSelector::Terminate only on the client.
676    if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
677    if (!source) {
678       Error("UnpackOutput", "No target. Aborting.");
679       return;
680    }
681    if (fDebug > 1) printf("   Source list contains %d containers\n", source->GetSize());
682
683    if (fMode == kProofAnalysis) ImportWrappers(source);
684
685    TIter next(fOutputs);
686    AliAnalysisDataContainer *output;
687    while ((output=(AliAnalysisDataContainer*)next())) {
688       if (!output->GetData()) continue;
689       // Check if there are client tasks that run post event loop
690       if (output->HasConsumers()) {
691          // Disable event loop semaphore
692          output->SetPostEventLoop(kTRUE);
693          TObjArray *list = output->GetConsumers();
694          Int_t ncons = list->GetEntriesFast();
695          for (Int_t i=0; i<ncons; i++) {
696             AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
697             task->CheckNotify(kTRUE);
698             // If task is active, execute it
699             if (task->IsPostEventLoop() && task->IsActive()) {
700                if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
701                task->ExecuteTask();
702             }   
703          }
704       }   
705    }
706    if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
707 }
708
709 //______________________________________________________________________________
710 void AliAnalysisManager::Terminate()
711 {
712   // The Terminate() function is the last function to be called during
713   // a query. It always runs on the client, it can be used to present
714   // the results graphically.
715    if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
716    AliAnalysisTask *task;
717    AliAnalysisDataContainer *output;
718    TIter next(fTasks);
719    TStopwatch timer;
720    // Call Terminate() for tasks
721    while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
722       // Save all the canvases produced by the Terminate
723       TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
724       task->Terminate();
725       if (TObject::TestBit(kSaveCanvases)) {
726          if (!gROOT->IsBatch()) {
727             Warning("Terminate", "Waiting 5 sec for %s::Terminate() to finish drawing", task->ClassName());
728             timer.Start();
729             while (timer.CpuTime()<5) {
730                timer.Continue();
731                gSystem->ProcessEvents();
732             }
733          }
734          Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
735          if (iend==0) continue;
736          TCanvas *canvas;
737          for (Int_t ipict=0; ipict<iend; ipict++) {
738             canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
739             if (!canvas) continue;         
740             canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
741          } 
742          gROOT->GetListOfCanvases()->Delete(); 
743       }
744    }   
745    //
746    TIter next1(fOutputs);
747    while ((output=(AliAnalysisDataContainer*)next1())) {
748       // Special outputs or grid files have the files already closed and written.
749       if (fMode == kGridAnalysis) continue;
750       if (fMode == kProofAnalysis) {
751         if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
752       }  
753       const char *filename = output->GetFileName();
754       if (!(strcmp(filename, "default"))) {
755          if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
756          TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
757          if (aodfile) {
758             if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
759             aodfile->Write();
760             continue;
761          }   
762       }      
763       if (!strlen(filename)) continue;
764       if (!output->GetData()) continue;
765       TDirectory *opwd = gDirectory;
766       TFile *file = output->GetFile();
767       if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
768       if (!file) file = new TFile(filename, "RECREATE");
769       if (file->IsZombie()) {
770          Error("Terminate", "Cannot open output file %s", filename);
771          continue;
772       }   
773       output->SetFile(file);
774       file->cd();
775       // Check for a folder request
776       TString dir = output->GetFolderName();
777       if (!dir.IsNull()) {
778          if (!file->GetDirectory(dir)) file->mkdir(dir);
779          file->cd(dir);
780       }  
781       if (fDebug > 1) printf("   writing output data %s to file %s:%s\n", output->GetData()->GetName(), file->GetName(), output->GetFolderName());
782       if (output->GetData()->InheritsFrom(TCollection::Class())) {
783       // If data is a collection, we set the name of the collection 
784       // as the one of the container and we save as a single key.
785          TCollection *coll = (TCollection*)output->GetData();
786          coll->SetName(output->GetName());
787          coll->Write(output->GetName(), TObject::kSingleKey);
788       } else {
789          if (output->GetData()->InheritsFrom(TTree::Class())) {
790             TTree *tree = (TTree*)output->GetData();
791             tree->SetDirectory(file);
792             tree->AutoSave();
793          } else {
794             output->GetData()->Write();
795          }   
796       }      
797       if (opwd) opwd->cd();
798    }   
799    next1.Reset();
800    while ((output=(AliAnalysisDataContainer*)next1())) {
801       // Close all files at output
802       TDirectory *opwd = gDirectory;
803       if (output->GetFile()) {
804          output->GetFile()->Close();
805          output->SetFile(NULL);
806          // Copy merged outputs in alien if requested
807          if (fSpecialOutputLocation.Length() && 
808              fSpecialOutputLocation.BeginsWith("alien://")) {
809             Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data()); 
810             TFile::Cp(output->GetFile()->GetName(), 
811                       Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
812          }             
813       }   
814       if (opwd) opwd->cd();
815    }   
816
817    if (fInputEventHandler)   fInputEventHandler  ->TerminateIO();
818    if (fOutputEventHandler)  fOutputEventHandler ->TerminateIO();
819    if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
820
821    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
822    if (getsysInfo) {
823       TDirectory *cdir = gDirectory;
824       TFile f("syswatch.root", "RECREATE");
825       if (!f.IsZombie()) {
826          TTree *tree = AliSysInfo::MakeTree("syswatch.log");
827          tree->SetMarkerStyle(kCircle);
828          tree->SetMarkerColor(kBlue);
829          tree->SetMarkerSize(0.5);
830          if (!gROOT->IsBatch()) {
831             tree->SetAlias("event", "id0");
832             tree->SetAlias("memUSED", "mi.fMemUsed");
833             new TCanvas("SysInfo","SysInfo",10,10,800,600);
834             tree->Draw("memUSED:event","","", 1234567890, 0);
835          }   
836          tree->Write();
837          f.Close();
838          delete tree;
839       }
840       if (cdir) cdir->cd();
841    }
842    // Validate the output files
843    if (ValidateOutputFiles()) {
844       ofstream out;
845       out.open("outputs_valid", ios::out);
846       out.close();
847    }      
848    if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
849 }
850
851 //______________________________________________________________________________
852 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
853 {
854 // Adds a user task to the global list of tasks.
855    if (fTasks->FindObject(task)) {
856       Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
857       return;
858    }   
859    task->SetActive(kFALSE);
860    fTasks->Add(task);
861 }  
862
863 //______________________________________________________________________________
864 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
865 {
866 // Retreive task by name.
867    if (!fTasks) return NULL;
868    return (AliAnalysisTask*)fTasks->FindObject(name);
869 }
870
871 //______________________________________________________________________________
872 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, 
873                                 TClass *datatype, EAliAnalysisContType type, const char *filename)
874 {
875 // Create a data container of a certain type. Types can be:
876 //   kExchangeContainer  = 0, used to exchange data between tasks
877 //   kInputContainer   = 1, used to store input data
878 //   kOutputContainer  = 2, used for writing result to a file
879 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
880 // the output object to a folder inside the output file
881    if (fContainers->FindObject(name)) {
882       Error("CreateContainer","A container named %s already defined !",name);
883       return NULL;
884    }   
885    AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
886    fContainers->Add(cont);
887    switch (type) {
888       case kInputContainer:
889          fInputs->Add(cont);
890          break;
891       case kOutputContainer:
892          fOutputs->Add(cont);
893          if (filename && strlen(filename)) {
894             cont->SetFileName(filename);
895             cont->SetDataOwned(kFALSE);  // data owned by the file
896          }   
897          break;
898       case kExchangeContainer:
899          break;   
900    }
901    return cont;
902 }
903          
904 //______________________________________________________________________________
905 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
906                                         AliAnalysisDataContainer *cont)
907 {
908 // Connect input of an existing task to a data container.
909    if (!task) {
910       Error("ConnectInput", "Task pointer is NULL");
911       return kFALSE;
912    }   
913    if (!fTasks->FindObject(task)) {
914       AddTask(task);
915       Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
916    } 
917    Bool_t connected = task->ConnectInput(islot, cont);
918    return connected;
919 }   
920
921 //______________________________________________________________________________
922 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
923                                         AliAnalysisDataContainer *cont)
924 {
925 // Connect output of an existing task to a data container.
926    if (!task) {
927       Error("ConnectOutput", "Task pointer is NULL");
928       return kFALSE;
929    }   
930    if (!fTasks->FindObject(task)) {
931       AddTask(task);
932       Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
933    } 
934    Bool_t connected = task->ConnectOutput(islot, cont);
935    return connected;
936 }   
937                                
938 //______________________________________________________________________________
939 void AliAnalysisManager::CleanContainers()
940 {
941 // Clean data from all containers that have already finished all client tasks.
942    TIter next(fContainers);
943    AliAnalysisDataContainer *cont;
944    while ((cont=(AliAnalysisDataContainer *)next())) {
945       if (cont->IsOwnedData() && 
946           cont->IsDataReady() && 
947           cont->ClientsExecuted()) cont->DeleteData();
948    }
949 }
950
951 //______________________________________________________________________________
952 Bool_t AliAnalysisManager::InitAnalysis()
953 {
954 // Initialization of analysis chain of tasks. Should be called after all tasks
955 // and data containers are properly connected
956    // Reset flag and remove valid_outputs file if exists
957    fInitOK = kFALSE;
958    if (!gSystem->AccessPathName("outputs_valid"))
959       gSystem->Unlink("outputs_valid");
960    // Check for top tasks (depending only on input data containers)
961    if (!fTasks->First()) {
962       Error("InitAnalysis", "Analysis has no tasks !");
963       return kFALSE;
964    }   
965    TIter next(fTasks);
966    AliAnalysisTask *task;
967    AliAnalysisDataContainer *cont;
968    Int_t ntop = 0;
969    Int_t nzombies = 0;
970    Bool_t iszombie = kFALSE;
971    Bool_t istop = kTRUE;
972    Int_t i;
973    while ((task=(AliAnalysisTask*)next())) {
974       istop = kTRUE;
975       iszombie = kFALSE;
976       Int_t ninputs = task->GetNinputs();
977       for (i=0; i<ninputs; i++) {
978          cont = task->GetInputSlot(i)->GetContainer();
979          if (!cont) {
980             if (!iszombie) {
981                task->SetZombie();
982                fZombies->Add(task);
983                nzombies++;
984                iszombie = kTRUE;
985             }   
986             Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...", 
987                   i, task->GetName()); 
988          }
989          if (iszombie) continue;
990          // Check if cont is an input container
991          if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
992          // Connect to parent task
993       }
994       if (istop) {
995          ntop++;
996          fTopTasks->Add(task);
997       }
998    }
999    if (!ntop) {
1000       Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1001       return kFALSE;
1002    }                        
1003    // Check now if there are orphan tasks
1004    for (i=0; i<ntop; i++) {
1005       task = (AliAnalysisTask*)fTopTasks->At(i);
1006       task->SetUsed();
1007    }
1008    Int_t norphans = 0;
1009    next.Reset();
1010    while ((task=(AliAnalysisTask*)next())) {
1011       if (!task->IsUsed()) {
1012          norphans++;
1013          Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1014       }   
1015    }          
1016    // Check the task hierarchy (no parent task should depend on data provided
1017    // by a daughter task)
1018    for (i=0; i<ntop; i++) {
1019       task = (AliAnalysisTask*)fTopTasks->At(i);
1020       if (task->CheckCircularDeps()) {
1021          Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1022          PrintStatus("dep");
1023          return kFALSE;
1024       }   
1025    }
1026    // Check that all containers feeding post-event loop tasks are in the outputs list
1027    TIter nextcont(fContainers); // loop over all containers
1028    while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1029       if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1030          if (cont->HasConsumers()) {
1031          // Check if one of the consumers is post event loop
1032             TIter nextconsumer(cont->GetConsumers());
1033             while ((task=(AliAnalysisTask*)nextconsumer())) {
1034                if (task->IsPostEventLoop()) {
1035                   fOutputs->Add(cont);
1036                   break;
1037                }
1038             }
1039          }
1040       }
1041    }   
1042    // Check if all special output containers have a file name provided
1043    TIter nextout(fOutputs);
1044    while ((cont=(AliAnalysisDataContainer*)nextout())) {
1045       if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1046          Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1047          return kFALSE;
1048       }
1049    }      
1050    fInitOK = kTRUE;
1051    return kTRUE;
1052 }   
1053
1054 //______________________________________________________________________________
1055 void AliAnalysisManager::PrintStatus(Option_t *option) const
1056 {
1057 // Print task hierarchy.
1058    if (!fInitOK) {
1059       Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1060       return;
1061    }   
1062    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1063    if (getsysInfo)
1064       Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1065    TIter next(fTopTasks);
1066    AliAnalysisTask *task;
1067    while ((task=(AliAnalysisTask*)next()))
1068       task->PrintTask(option);
1069 }
1070
1071 //______________________________________________________________________________
1072 void AliAnalysisManager::ResetAnalysis()
1073 {
1074 // Reset all execution flags and clean containers.
1075    CleanContainers();
1076 }
1077
1078 //______________________________________________________________________________
1079 void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
1080 {
1081 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1082 // MIX. Process nentries starting from firstentry
1083    if (!fInitOK) {
1084       Error("StartAnalysis","Analysis manager was not initialized !");
1085       return;
1086    }
1087    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1088    TString anaType = type;
1089    anaType.ToLower();
1090    fMode = kLocalAnalysis;
1091    Bool_t runlocalinit = kTRUE;
1092    if (anaType.Contains("file")) {
1093       runlocalinit = kFALSE;
1094       SetSkipTerminate(kTRUE);
1095    }   
1096    if (anaType.Contains("proof"))     fMode = kProofAnalysis;
1097    else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1098    else if (anaType.Contains("mix"))  fMode = kMixingAnalysis;
1099
1100    if (fMode == kGridAnalysis) {
1101       if (!fGridHandler) {
1102          Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1103          Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1104          return;
1105       }
1106       // Write analysis manager in the analysis file
1107       cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1108       // run local task configuration
1109       TIter nextTask(fTasks);
1110       AliAnalysisTask *task;
1111       while ((task=(AliAnalysisTask*)nextTask())) {
1112          task->LocalInit();
1113       }
1114       if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1115          Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1116          return;
1117       }   
1118
1119       // Terminate grid analysis
1120       if (fSelector && fSelector->GetStatus() == -1) return;
1121       if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1122       cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1123       if (!fGridHandler->MergeOutputs()) {
1124          // Return if outputs could not be merged or if it alien handler
1125          // was configured for offline mode or local testing.
1126          return;
1127       }
1128       ImportWrappers(NULL);
1129       Terminate();
1130       return;
1131    }
1132    char line[256];
1133    SetEventLoop(kFALSE);
1134    // Enable event loop mode if a tree was provided
1135    if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1136
1137    TChain *chain = 0;
1138    TString ttype = "TTree";
1139    if (tree && tree->IsA() == TChain::Class()) {
1140       chain = (TChain*)tree;
1141       if (!chain || !chain->GetListOfFiles()->First()) {
1142          Error("StartAnalysis", "Cannot process null or empty chain...");
1143          return;
1144       }   
1145       ttype = "TChain";
1146    }   
1147
1148    // Initialize locally all tasks (happens for all modes)
1149    TIter next(fTasks);
1150    AliAnalysisTask *task;
1151    if (runlocalinit) {
1152       while ((task=(AliAnalysisTask*)next())) {
1153          task->LocalInit();
1154       }
1155    }   
1156    
1157    switch (fMode) {
1158       case kLocalAnalysis:
1159          if (!tree) {
1160             TIter nextT(fTasks);
1161             // Call CreateOutputObjects for all tasks
1162             while ((task=(AliAnalysisTask*)nextT())) {
1163                TDirectory *curdir = gDirectory;
1164                task->CreateOutputObjects();
1165                if (curdir) curdir->cd();
1166             }   
1167             if (IsExternalLoop()) {
1168                Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1169                      \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1170                return;
1171             }         
1172             ExecAnalysis();
1173             Terminate();
1174             return;
1175          } 
1176          // Run tree-based analysis via AliAnalysisSelector  
1177          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1178          fSelector = new AliAnalysisSelector(this);
1179          tree->Process(fSelector, "", nentries, firstentry);
1180          break;
1181       case kProofAnalysis:
1182          if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1183             Error("StartAnalysis", "No PROOF!!! Aborting.");
1184             return;
1185          }   
1186          sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1187          gROOT->ProcessLine(line);
1188          if (chain) {
1189             chain->SetProof();
1190             cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1191             chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1192          } else {
1193             Error("StartAnalysis", "No chain!!! Aborting.");
1194             return;
1195          }      
1196          break;
1197       case kGridAnalysis:
1198          Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
1199          break;
1200       case kMixingAnalysis:   
1201          // Run event mixing analysis
1202          if (!fEventPool) {
1203             Error("StartAnalysis", "Cannot run event mixing without event pool");
1204             return;
1205          }
1206          cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1207          fSelector = new AliAnalysisSelector(this);
1208          while ((chain=fEventPool->GetNextChain())) {
1209             next.Reset();
1210             // Call NotifyBinChange for all tasks
1211             while ((task=(AliAnalysisTask*)next()))
1212                if (!task->IsPostEventLoop()) task->NotifyBinChange();
1213             chain->Process(fSelector);
1214          }
1215          PackOutput(fSelector->GetOutputList());
1216          Terminate();
1217    }   
1218 }   
1219
1220 //______________________________________________________________________________
1221 void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1222 {
1223 // Start analysis for this manager on a given dataset. Analysis task can be: 
1224 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1225    if (!fInitOK) {
1226       Error("StartAnalysis","Analysis manager was not initialized !");
1227       return;
1228    }
1229    if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
1230    TString anaType = type;
1231    anaType.ToLower();
1232    if (!anaType.Contains("proof")) {
1233       Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1234       return;
1235    }   
1236    fMode = kProofAnalysis;
1237    char line[256];
1238    SetEventLoop(kTRUE);
1239    // Set the dataset flag
1240    TObject::SetBit(kUseDataSet);
1241    fTree = 0;
1242
1243    // Initialize locally all tasks
1244    TIter next(fTasks);
1245    AliAnalysisTask *task;
1246    while ((task=(AliAnalysisTask*)next())) {
1247       task->LocalInit();
1248    }
1249    
1250    if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1251       Error("StartAnalysis", "No PROOF!!! Aborting.");
1252       return;
1253    }   
1254    sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1255    gROOT->ProcessLine(line);
1256    sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1257    if (!gROOT->ProcessLine(line)) {
1258       Error("StartAnalysis", "Dataset %s not found", dataset);
1259       return;
1260    }   
1261    sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1262            dataset, nentries, firstentry);
1263    cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1264    gROOT->ProcessLine(line);
1265 }   
1266
1267 //______________________________________________________________________________
1268 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1269 {
1270 // Opens according the option the file specified by cont->GetFileName() and changes
1271 // current directory to cont->GetFolderName(). If the file was already opened, it
1272 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1273 // be optionally ignored.
1274   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1275   TString filename = cont->GetFileName();
1276   TFile *f = NULL;
1277   if (filename.IsNull()) {
1278     ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1279     return NULL;
1280   }
1281   if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1282       && !ignoreProof)
1283     f = mgr->OpenProofFile(cont,option);
1284   else {
1285     // Check first if the file is already opened
1286     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1287     if (f) {
1288       // Check if option "UPDATE" was preserved 
1289       TString opt(option);
1290       opt.ToUpper();
1291       if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1292         ::Fatal("AliAnalysisManager::OpenFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1293     } else {
1294       f = TFile::Open(filename, option);
1295     }    
1296   }   
1297   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1298     cont->SetFile(f);
1299     // Cd to file
1300     f->cd();
1301     // Check for a folder request
1302     TString dir = cont->GetFolderName(); 
1303     if (!dir.IsNull()) {
1304       if (!f->GetDirectory(dir)) f->mkdir(dir);
1305       f->cd(dir);
1306     }
1307     return f;
1308   }
1309   ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1310   cont->SetFile(NULL);
1311   return NULL;
1312 }    
1313  
1314 //______________________________________________________________________________
1315 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
1316 {
1317 // Opens a special output file used in PROOF.
1318   TString line;
1319   TString filename = cont->GetFileName();
1320   if (cont == fCommonOutput) {
1321      if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1322      else Fatal("OpenProofFile","No output container. Aborting.");
1323   }   
1324   TFile *f = NULL;
1325   if (fMode!=kProofAnalysis || !fSelector) {
1326     Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1327     return NULL;
1328   } 
1329   if (fSpecialOutputLocation.Length()) {
1330     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1331     if (f) {
1332       // Check if option "UPDATE" was preserved 
1333       TString opt(option);
1334       opt.ToUpper();
1335       if ((opt=="UPDATE") && (opt!=f->GetOption()))
1336         Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1337     } else {
1338       f = new TFile(filename, option);
1339     }
1340     if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1341       cont->SetFile(f);
1342       // Cd to file
1343       f->cd();
1344       // Check for a folder request
1345       TString dir = cont->GetFolderName(); 
1346       if (dir.Length()) {
1347         if (!f->GetDirectory(dir)) f->mkdir(dir);
1348         f->cd(dir);
1349       }      
1350       return f;
1351     }
1352     Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1353     cont->SetFile(NULL);
1354     return NULL;       
1355   }
1356   // Check if there is already a proof output file in the output list
1357   TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1358   if (pof) {
1359     // Get the actual file
1360     line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1361     filename = (const char*)gROOT->ProcessLine(line);
1362     if (fDebug>1) {
1363       printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1364     }  
1365     f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1366     if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1367     // Check if option "UPDATE" was preserved 
1368     TString opt(option);
1369     opt.ToUpper();
1370     if ((opt=="UPDATE") && (opt!=f->GetOption())) 
1371       Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1372   } else {
1373     if (cont->IsRegisterDataset()) {
1374       TString dset_name = filename;
1375       dset_name.ReplaceAll(".root", cont->GetTitle());
1376       dset_name.ReplaceAll(":","_");
1377       if (fDebug>1) printf("Booking dataset: %s\n", dset_name.Data());
1378       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dset_name.Data());
1379     } else {
1380       if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1381       line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1382     }
1383     if (fDebug > 1) printf("=== %s\n", line.Data());
1384     gROOT->ProcessLine(line);
1385     line = Form("pf->OpenFile(\"%s\");", option);
1386     gROOT->ProcessLine(line);
1387     f = gFile;
1388     if (fDebug > 1) {
1389       gROOT->ProcessLine("pf->Print()");
1390       printf(" == proof file name: %s", f->GetName());
1391     }   
1392     // Add to proof output list
1393     line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1394     if (fDebug > 1) printf("=== %s\n", line.Data());
1395     gROOT->ProcessLine(line);
1396   }
1397   if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1398     cont->SetFile(f);
1399     // Cd to file
1400     f->cd();
1401     // Check for a folder request
1402     TString dir = cont->GetFolderName(); 
1403     if (!dir.IsNull()) {
1404       if (!f->GetDirectory(dir)) f->mkdir(dir);
1405       f->cd(dir);
1406     }
1407     return f;
1408   }
1409   Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1410   cont->SetFile(NULL);  
1411   return NULL;
1412 }   
1413
1414 //______________________________________________________________________________
1415 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1416 {
1417 // Execute analysis.
1418    static Long64_t ncalls = 0;
1419    Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1420    if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1421    ncalls++;
1422    if (!fInitOK) {
1423      Error("ExecAnalysis", "Analysis manager was not initialized !");
1424       return;
1425    }   
1426    AliAnalysisTask *task;
1427    // Check if the top tree is active.
1428    if (fTree) {
1429       TIter next(fTasks);
1430    // De-activate all tasks
1431       while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1432       AliAnalysisDataContainer *cont = fCommonInput;
1433       if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1434       if (!cont) {
1435               Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1436          return;
1437       }   
1438       cont->SetData(fTree); // This will notify all consumers
1439       Long64_t entry = fTree->GetTree()->GetReadEntry();
1440       
1441 //
1442 //    Call BeginEvent() for optional input/output and MC services 
1443       if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(entry);
1444       if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(entry);
1445       if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1446 //
1447 //    Execute the tasks
1448 //      TIter next1(cont->GetConsumers());
1449       TIter next1(fTopTasks);
1450       while ((task=(AliAnalysisTask*)next1())) {
1451          if (fDebug >1) {
1452             cout << "    Executing task " << task->GetName() << endl;
1453          }   
1454          
1455          task->ExecuteTask(option);
1456       }
1457 //
1458 //    Call FinishEvent() for optional output and MC services 
1459       if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1460       if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1461       if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1462       // Gather system information if requested
1463       if (getsysInfo && ((ncalls%fNSysInfo)==0)) 
1464          AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
1465       return;
1466    }   
1467    // The event loop is not controlled by TSelector   
1468 //
1469 //  Call BeginEvent() for optional input/output and MC services 
1470    if (fInputEventHandler)   fInputEventHandler  ->BeginEvent(-1);
1471    if (fOutputEventHandler)  fOutputEventHandler ->BeginEvent(-1);
1472    if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1473    TIter next2(fTopTasks);
1474    while ((task=(AliAnalysisTask*)next2())) {
1475       task->SetActive(kTRUE);
1476       if (fDebug > 1) {
1477          cout << "    Executing task " << task->GetName() << endl;
1478       }   
1479       task->ExecuteTask(option);
1480    }   
1481 //
1482 // Call FinishEvent() for optional output and MC services 
1483    if (fInputEventHandler)   fInputEventHandler  ->FinishEvent();
1484    if (fOutputEventHandler)  fOutputEventHandler ->FinishEvent();
1485    if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1486 }
1487
1488 //______________________________________________________________________________
1489 void AliAnalysisManager::FinishAnalysis()
1490 {
1491 // Finish analysis.
1492 }
1493
1494 //______________________________________________________________________________
1495 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler*  handler)
1496 {
1497 // Set the input event handler and create a container for it.
1498    fInputEventHandler   = handler;
1499    fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
1500    Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
1501 }
1502
1503 //______________________________________________________________________________
1504 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler*  handler)
1505 {
1506 // Set the input event handler and create a container for it.
1507    fOutputEventHandler   = handler;
1508    fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
1509    fCommonOutput->SetSpecialOutput();
1510    Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
1511 }
1512
1513 //______________________________________________________________________________
1514 void AliAnalysisManager::RegisterExtraFile(const char *fname)
1515 {
1516 // This method is used externally to register output files which are not
1517 // connected to any output container, so that the manager can properly register,
1518 // retrieve or merge them when running in distributed mode. The file names are
1519 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1520    if (fExtraFiles.Length()) fExtraFiles += " ";
1521    fExtraFiles += fname;
1522 }
1523
1524 //______________________________________________________________________________
1525 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1526 {
1527 // Copy a file from the location specified ina the wrapper with the same name from the source list.
1528    char full_path[512];
1529    char ch_url[512];
1530    TObject *pof =  source->FindObject(filename);
1531    if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1532       Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1533       return kFALSE;
1534    }
1535    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1536    gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1537    TString clientUrl(ch_url);
1538    TString full_path_str(full_path);
1539    if (clientUrl.Contains("localhost")){
1540       TObjArray* array = full_path_str.Tokenize ( "//" );
1541       TObjString *strobj = ( TObjString *)array->At(1);
1542       TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1543       TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1544       full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1545       full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1546       if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1547       delete arrayPort;
1548       delete array;
1549    }
1550    if (fDebug > 1) 
1551       Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1552    Bool_t gotit = TFile::Cp(full_path_str.Data(), filename); 
1553    if (!gotit)
1554       Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1555    return gotit;
1556 }
1557
1558 //______________________________________________________________________________
1559 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1560 {
1561 // Fill analysis type in the provided string.
1562    switch (fMode) {
1563       case kLocalAnalysis:
1564          type = "local";
1565          return;
1566       case kProofAnalysis:
1567          type = "proof";
1568          return;
1569       case kGridAnalysis:
1570          type = "grid";
1571          return;
1572       case kMixingAnalysis:
1573          type = "mix";
1574    }
1575 }
1576
1577 //______________________________________________________________________________
1578 Bool_t AliAnalysisManager::ValidateOutputFiles() const
1579 {
1580 // Validate all output files.
1581    TIter next(fOutputs);
1582    AliAnalysisDataContainer *output;
1583    TDirectory *cdir = gDirectory;
1584    TString openedFiles;
1585    while ((output=(AliAnalysisDataContainer*)next())) {
1586       if (output->IsRegisterDataset()) continue;
1587       TString filename = output->GetFileName();
1588       if (filename == "default") {
1589          if (!fOutputEventHandler) continue;
1590          filename = fOutputEventHandler->GetOutputFileName();
1591       }
1592       // Check if the file is closed
1593       if (openedFiles.Contains(filename)) continue;;
1594       TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1595       if (file) {
1596          Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1597          file->Close();
1598       }
1599       file = TFile::Open(filename);
1600       if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1601          Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1602          cdir->cd();
1603          return kFALSE;
1604       }
1605       file->Close();
1606       openedFiles += filename;
1607       openedFiles += " ";
1608    }
1609    cdir->cd();
1610    return kTRUE;
1611 }