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