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