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