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