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