]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - ANALYSIS/AliAnalysisManager.cxx
some fixes wrt to the AliAODExtension behavior (Laurent)
[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// AliAnalysisManager - 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 "AliAnalysisManager.h"
29
30#include <cerrno>
31#include <Riostream.h>
32#include <TError.h>
33#include <TClass.h>
34#include <TFile.h>
35#include <TMath.h>
36#include <TH1.h>
37#include <TMethodCall.h>
38#include <TChain.h>
39#include <TSystem.h>
40#include <TROOT.h>
41#include <TCanvas.h>
42#include <TStopwatch.h>
43
44#include "AliAnalysisSelector.h"
45#include "AliAnalysisGrid.h"
46#include "AliAnalysisTask.h"
47#include "AliAnalysisDataContainer.h"
48#include "AliAnalysisDataSlot.h"
49#include "AliVEventHandler.h"
50#include "AliVEventPool.h"
51#include "AliSysInfo.h"
52#include "AliAnalysisStatistics.h"
53
54ClassImp(AliAnalysisManager)
55
56AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
57TString AliAnalysisManager::fgCommonFileName = "";
58Int_t AliAnalysisManager::fPBUpdateFreq = 1;
59
60//______________________________________________________________________________
61AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
62 :TNamed(name,title),
63 fTree(NULL),
64 fInputEventHandler(NULL),
65 fOutputEventHandler(NULL),
66 fMCtruthEventHandler(NULL),
67 fEventPool(NULL),
68 fCurrentEntry(-1),
69 fNSysInfo(0),
70 fMode(kLocalAnalysis),
71 fInitOK(kFALSE),
72 fIsRemote(kFALSE),
73 fDebug(0),
74 fSpecialOutputLocation(""),
75 fTasks(NULL),
76 fTopTasks(NULL),
77 fZombies(NULL),
78 fContainers(NULL),
79 fInputs(NULL),
80 fOutputs(NULL),
81 fParamCont(NULL),
82 fCommonInput(NULL),
83 fCommonOutput(NULL),
84 fSelector(NULL),
85 fGridHandler(NULL),
86 fExtraFiles(""),
87 fAutoBranchHandling(kTRUE),
88 fTable(),
89 fRunFromPath(0),
90 fNcalls(0),
91 fMaxEntries(0),
92 fStatisticsMsg(),
93 fRequestedBranches(),
94 fStatistics(0)
95{
96// Default constructor.
97 fgAnalysisManager = this;
98 fgCommonFileName = "AnalysisResults.root";
99 fTasks = new TObjArray();
100 fTopTasks = new TObjArray();
101 fZombies = new TObjArray();
102 fContainers = new TObjArray();
103 fInputs = new TObjArray();
104 fOutputs = new TObjArray();
105 fParamCont = new TObjArray();
106 SetEventLoop(kTRUE);
107 TObject::SetObjectStat(kFALSE);
108}
109
110//______________________________________________________________________________
111AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
112 :TNamed(other),
113 fTree(NULL),
114 fInputEventHandler(NULL),
115 fOutputEventHandler(NULL),
116 fMCtruthEventHandler(NULL),
117 fEventPool(NULL),
118 fCurrentEntry(-1),
119 fNSysInfo(0),
120 fMode(other.fMode),
121 fInitOK(other.fInitOK),
122 fIsRemote(other.fIsRemote),
123 fDebug(other.fDebug),
124 fSpecialOutputLocation(""),
125 fTasks(NULL),
126 fTopTasks(NULL),
127 fZombies(NULL),
128 fContainers(NULL),
129 fInputs(NULL),
130 fOutputs(NULL),
131 fParamCont(NULL),
132 fCommonInput(NULL),
133 fCommonOutput(NULL),
134 fSelector(NULL),
135 fGridHandler(NULL),
136 fExtraFiles(),
137 fAutoBranchHandling(other.fAutoBranchHandling),
138 fTable(),
139 fRunFromPath(0),
140 fNcalls(other.fNcalls),
141 fMaxEntries(other.fMaxEntries),
142 fStatisticsMsg(other.fStatisticsMsg),
143 fRequestedBranches(other.fRequestedBranches),
144 fStatistics(other.fStatistics)
145{
146// Copy constructor.
147 fTasks = new TObjArray(*other.fTasks);
148 fTopTasks = new TObjArray(*other.fTopTasks);
149 fZombies = new TObjArray(*other.fZombies);
150 fContainers = new TObjArray(*other.fContainers);
151 fInputs = new TObjArray(*other.fInputs);
152 fOutputs = new TObjArray(*other.fOutputs);
153 fParamCont = new TObjArray(*other.fParamCont);
154 fgCommonFileName = "AnalysisResults.root";
155 fgAnalysisManager = this;
156 TObject::SetObjectStat(kFALSE);
157}
158
159//______________________________________________________________________________
160AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
161{
162// Assignment
163 if (&other != this) {
164 TNamed::operator=(other);
165 fInputEventHandler = other.fInputEventHandler;
166 fOutputEventHandler = other.fOutputEventHandler;
167 fMCtruthEventHandler = other.fMCtruthEventHandler;
168 fEventPool = other.fEventPool;
169 fTree = NULL;
170 fCurrentEntry = -1;
171 fNSysInfo = other.fNSysInfo;
172 fMode = other.fMode;
173 fInitOK = other.fInitOK;
174 fIsRemote = other.fIsRemote;
175 fDebug = other.fDebug;
176 fTasks = new TObjArray(*other.fTasks);
177 fTopTasks = new TObjArray(*other.fTopTasks);
178 fZombies = new TObjArray(*other.fZombies);
179 fContainers = new TObjArray(*other.fContainers);
180 fInputs = new TObjArray(*other.fInputs);
181 fOutputs = new TObjArray(*other.fOutputs);
182 fParamCont = new TObjArray(*other.fParamCont);
183 fCommonInput = NULL;
184 fCommonOutput = NULL;
185 fSelector = NULL;
186 fGridHandler = NULL;
187 fExtraFiles = other.fExtraFiles;
188 fgCommonFileName = "AnalysisResults.root";
189 fgAnalysisManager = this;
190 fAutoBranchHandling = other.fAutoBranchHandling;
191 fTable.Clear("nodelete");
192 fRunFromPath = other.fRunFromPath;
193 fNcalls = other. fNcalls;
194 fMaxEntries = other.fMaxEntries;
195 fStatisticsMsg = other.fStatisticsMsg;
196 fRequestedBranches = other.fRequestedBranches;
197 fStatistics = other.fStatistics;
198 }
199 return *this;
200}
201
202//______________________________________________________________________________
203AliAnalysisManager::~AliAnalysisManager()
204{
205// Destructor.
206 if (fTasks) {fTasks->Delete(); delete fTasks;}
207 if (fTopTasks) delete fTopTasks;
208 if (fZombies) delete fZombies;
209 if (fContainers) {fContainers->Delete(); delete fContainers;}
210 if (fInputs) delete fInputs;
211 if (fOutputs) delete fOutputs;
212 if (fParamCont) delete fParamCont;
213 if (fGridHandler) delete fGridHandler;
214 if (fInputEventHandler) delete fInputEventHandler;
215 if (fOutputEventHandler) delete fOutputEventHandler;
216 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
217 if (fEventPool) delete fEventPool;
218 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
219 TObject::SetObjectStat(kTRUE);
220}
221
222//______________________________________________________________________________
223Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
224{
225// Read one entry of the tree or a whole branch.
226 fCurrentEntry = entry;
227 if (!fAutoBranchHandling)
228 return 123456789;
229 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : -1;
230}
231
232//______________________________________________________________________________
233Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
234{
235// Attempt to extract run number from input data path. Works only for paths to
236// alice data in alien.
237// sim: /alice/sim/<production>/run_no/...
238// data: /alice/data/year/period/000run_no/... (ESD or AOD)
239 TString s(path);
240 TString srun;
241 Int_t run = 0;
242 Int_t index = s.Index("/alice/sim");
243 if (index >= 0) {
244 for (Int_t i=0; i<3; i++) {
245 index = s.Index("/", index+1);
246 if (index<0) return 0;
247 }
248 srun = s(index+1,6);
249 run = atoi(srun);
250 }
251 index = s.Index("/alice/data");
252 if (index >= 0) {
253 for (Int_t i=0; i<4; i++) {
254 index = s.Index("/", index+1);
255 if (index<0) return 0;
256 }
257 srun = s(index+1,9);
258 run = atoi(srun);
259 }
260 return run;
261}
262
263//______________________________________________________________________________
264Bool_t AliAnalysisManager::Init(TTree *tree)
265{
266 // The Init() function is called when the selector needs to initialize
267 // a new tree or chain. Typically here the branch addresses of the tree
268 // will be set. It is normaly not necessary to make changes to the
269 // generated code, but the routine can be extended by the user if needed.
270 // Init() will be called many times when running with PROOF.
271 Bool_t init = kFALSE;
272 if (!tree) return kFALSE; // Should not happen - protected in selector caller
273 if (fDebug > 1) {
274 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
275 }
276 // Call InitTree of EventHandler
277 if (fOutputEventHandler) {
278 if (fMode == kProofAnalysis) {
279 init = fOutputEventHandler->Init(0x0, "proof");
280 } else {
281 init = fOutputEventHandler->Init(0x0, "local");
282 }
283 if (!init) {
284 Error("Init", "Output event handler failed to initialize");
285 return kFALSE;
286 }
287 }
288
289 if (fInputEventHandler) {
290 if (fMode == kProofAnalysis) {
291 init = fInputEventHandler->Init(tree, "proof");
292 } else {
293 init = fInputEventHandler->Init(tree, "local");
294 }
295 if (!init) {
296 Error("Init", "Input event handler failed to initialize tree");
297 return kFALSE;
298 }
299 } else {
300 // If no input event handler we need to get the tree once
301 // for the chain
302 if(!tree->GetTree()) {
303 Long64_t readEntry = tree->LoadTree(0);
304 if (readEntry == -2) {
305 Error("Init", "Input tree has no entry. Exiting");
306 return kFALSE;
307 }
308 }
309 }
310
311 if (fMCtruthEventHandler) {
312 if (fMode == kProofAnalysis) {
313 init = fMCtruthEventHandler->Init(0x0, "proof");
314 } else {
315 init = fMCtruthEventHandler->Init(0x0, "local");
316 }
317 if (!init) {
318 Error("Init", "MC event handler failed to initialize");
319 return kFALSE;
320 }
321 }
322
323 if (!fInitOK) InitAnalysis();
324 if (!fInitOK) return kFALSE;
325 fTree = tree;
326 fTable.Rehash(100);
327 AliAnalysisDataContainer *top = fCommonInput;
328 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
329 if (!top) {
330 Error("Init","No top input container !");
331 return kFALSE;
332 }
333 top->SetData(tree);
334 CheckBranches(kFALSE);
335 if (fDebug > 1) {
336 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
337 }
338 return kTRUE;
339}
340
341//______________________________________________________________________________
342void AliAnalysisManager::SlaveBegin(TTree *tree)
343{
344 // The SlaveBegin() function is called after the Begin() function.
345 // When running with PROOF SlaveBegin() is called on each slave server.
346 // The tree argument is deprecated (on PROOF 0 is passed).
347 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
348 static Bool_t isCalled = kFALSE;
349 Bool_t init = kFALSE;
350 Bool_t initOK = kTRUE;
351 TString msg;
352 TDirectory *curdir = gDirectory;
353 // Call SlaveBegin only once in case of mixing
354 if (isCalled && fMode==kMixingAnalysis) return;
355 gROOT->cd();
356 // Call Init of EventHandler
357 if (fOutputEventHandler) {
358 if (fMode == kProofAnalysis) {
359 // Merging AOD's in PROOF via TProofOutputFile
360 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
361 init = fOutputEventHandler->Init("proof");
362 if (!init) msg = "Failed to initialize output handler on worker";
363 } else {
364 init = fOutputEventHandler->Init("local");
365 if (!init) msg = "Failed to initialize output handler";
366 }
367 initOK &= init;
368 if (!fSelector) Error("SlaveBegin", "Selector not set");
369 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
370 }
371 gROOT->cd();
372 if (fInputEventHandler) {
373 fInputEventHandler->SetInputTree(tree);
374 if (fMode == kProofAnalysis) {
375 init = fInputEventHandler->Init("proof");
376 if (!init) msg = "Failed to initialize input handler on worker";
377 } else {
378 init = fInputEventHandler->Init("local");
379 if (!init) msg = "Failed to initialize input handler";
380 }
381 initOK &= init;
382 if (!fSelector) Error("SlaveBegin", "Selector not set");
383 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
384 }
385 gROOT->cd();
386 if (fMCtruthEventHandler) {
387 if (fMode == kProofAnalysis) {
388 init = fMCtruthEventHandler->Init("proof");
389 if (!init) msg = "Failed to initialize MC handler on worker";
390 } else {
391 init = fMCtruthEventHandler->Init("local");
392 if (!init) msg = "Failed to initialize MC handler";
393 }
394 initOK &= init;
395 if (!fSelector) Error("SlaveBegin", "Selector not set");
396 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
397 }
398 if (curdir) curdir->cd();
399 isCalled = kTRUE;
400 if (!initOK) return;
401 TIter next(fTasks);
402 AliAnalysisTask *task;
403 // Call CreateOutputObjects for all tasks
404 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
405 Bool_t dirStatus = TH1::AddDirectoryStatus();
406 Int_t itask = 0;
407 while ((task=(AliAnalysisTask*)next())) {
408 gROOT->cd();
409 // Start with memory as current dir and make sure by default histograms do not get attached to files.
410 TH1::AddDirectory(kFALSE);
411 task->CreateOutputObjects();
412 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
413 itask++;
414 }
415 TH1::AddDirectory(dirStatus);
416 if (curdir) curdir->cd();
417 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
418}
419
420//______________________________________________________________________________
421Bool_t AliAnalysisManager::Notify()
422{
423 // The Notify() function is called when a new file is opened. This
424 // can be either for a new TTree in a TChain or when when a new TTree
425 // is started when using PROOF. It is normaly not necessary to make changes
426 // to the generated code, but the routine can be extended by the
427 // user if needed. The return value is currently not used.
428 if (!fTree) return kFALSE;
429
430 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
431 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
432
433 TFile *curfile = fTree->GetCurrentFile();
434 if (!curfile) {
435 Error("Notify","No current file");
436 return kFALSE;
437 }
438
439 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
440 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
441 if (run) SetRunFromPath(run);
442 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
443 TIter next(fTasks);
444 AliAnalysisTask *task;
445
446 // Call Notify of the event handlers
447 if (fInputEventHandler) {
448 fInputEventHandler->Notify(curfile->GetName());
449 }
450
451 if (fOutputEventHandler) {
452 fOutputEventHandler->Notify(curfile->GetName());
453 }
454
455 if (fMCtruthEventHandler) {
456 fMCtruthEventHandler->Notify(curfile->GetName());
457 }
458
459 // Call Notify for all tasks
460 while ((task=(AliAnalysisTask*)next()))
461 task->Notify();
462
463 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
464 return kTRUE;
465}
466
467//______________________________________________________________________________
468Bool_t AliAnalysisManager::Process(Long64_t entry)
469{
470 // The Process() function is called for each entry in the tree (or possibly
471 // keyed object in the case of PROOF) to be processed. The entry argument
472 // specifies which entry in the currently loaded tree is to be processed.
473 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
474 // to read either all or the required parts of the data. When processing
475 // keyed objects with PROOF, the object is already loaded and is available
476 // via the fObject pointer.
477 //
478 // This function should contain the "body" of the analysis. It can contain
479 // simple or elaborate selection criteria, run algorithms on the data
480 // of the event and typically fill histograms.
481
482 // WARNING when a selector is used with a TChain, you must use
483 // the pointer to the current TTree to call GetEntry(entry).
484 // The entry is always the local entry number in the current tree.
485 // Assuming that fChain is the pointer to the TChain being processed,
486 // use fChain->GetTree()->GetEntry(entry).
487 if (fDebug > 1) printf("->AliAnalysisManager::Process(%lld)\n", entry);
488
489 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
490 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
491 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
492
493 GetEntry(entry);
494
495 if (fInputEventHandler) fInputEventHandler ->GetEntry();
496
497 ExecAnalysis();
498 if (fDebug > 1) printf("<-AliAnalysisManager::Process()\n");
499 return kTRUE;
500}
501
502//______________________________________________________________________________
503void AliAnalysisManager::PackOutput(TList *target)
504{
505 // Pack all output data containers in the output list. Called at SlaveTerminate
506 // stage in PROOF case for each slave.
507 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
508 if (!target) {
509 Error("PackOutput", "No target. Exiting.");
510 return;
511 }
512 TDirectory *cdir = gDirectory;
513 gROOT->cd();
514 if (fInputEventHandler) fInputEventHandler ->Terminate();
515 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
516 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
517 gROOT->cd();
518
519 // Call FinishTaskOutput() for each event loop task (not called for
520 // post-event loop tasks - use Terminate() fo those)
521 TIter nexttask(fTasks);
522 AliAnalysisTask *task;
523 while ((task=(AliAnalysisTask*)nexttask())) {
524 if (!task->IsPostEventLoop()) {
525 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
526 task->FinishTaskOutput();
527 gROOT->cd();
528 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
529 }
530 }
531 // Write statistics message on the workers.
532 if (fStatistics) WriteStatisticsMsg(fNcalls);
533
534 if (fMode == kProofAnalysis) {
535 TIter next(fOutputs);
536 AliAnalysisDataContainer *output;
537 Bool_t isManagedByHandler = kFALSE;
538 TList filestmp;
539 filestmp.SetOwner();
540 while ((output=(AliAnalysisDataContainer*)next())) {
541 // Do not consider outputs of post event loop tasks
542 isManagedByHandler = kFALSE;
543 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
544 const char *filename = output->GetFileName();
545 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
546 isManagedByHandler = kTRUE;
547 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
548 filename = fOutputEventHandler->GetOutputFileName();
549 }
550 // Check if data was posted to this container. If not, issue an error.
551 if (!output->GetData() && !isManagedByHandler) {
552 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
553 continue;
554 }
555 if (!output->IsSpecialOutput()) {
556 // Normal outputs
557 if (strlen(filename) && !isManagedByHandler) {
558 // Backup current folder
559 TDirectory *opwd = gDirectory;
560 // File resident outputs.
561 // Check first if the file exists.
562 TString openoption = "RECREATE";
563 Bool_t firsttime = kTRUE;
564 if (filestmp.FindObject(output->GetFileName())) {
565 firsttime = kFALSE;
566 } else {
567 filestmp.Add(new TNamed(output->GetFileName(),""));
568 }
569 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
570// TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
571 // Save data to file, then close.
572 if (output->GetData()->InheritsFrom(TCollection::Class())) {
573 // If data is a collection, we set the name of the collection
574 // as the one of the container and we save as a single key.
575 TCollection *coll = (TCollection*)output->GetData();
576 coll->SetName(output->GetName());
577// coll->Write(output->GetName(), TObject::kSingleKey);
578 } else {
579 if (output->GetData()->InheritsFrom(TTree::Class())) {
580 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
581 // Save data to file, then close.
582 TTree *tree = (TTree*)output->GetData();
583 // Check if tree is in memory
584 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
585 tree->AutoSave();
586 file->Close();
587 } else {
588// output->GetData()->Write();
589 }
590 }
591 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
592// if (fDebug > 2) {
593// printf(" file %s listing content:\n", filename);
594// file->ls();
595// }
596 // Clear file list to release object ownership to user.
597// file->Clear();
598// file->Close();
599 output->SetFile(NULL);
600 // Restore current directory
601 if (opwd) opwd->cd();
602 } else {
603 // Memory-resident outputs
604 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
605 }
606 AliAnalysisDataWrapper *wrap = 0;
607 if (isManagedByHandler) {
608 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
609 wrap->SetName(output->GetName());
610 }
611 else wrap =output->ExportData();
612 // Output wrappers must NOT delete data after merging - the user owns them
613 wrap->SetDeleteData(kFALSE);
614 target->Add(wrap);
615 } else {
616 // Special outputs. The file must be opened and connected to the container.
617 TDirectory *opwd = gDirectory;
618 TFile *file = output->GetFile();
619 if (!file) {
620 AliAnalysisTask *producer = output->GetProducer();
621 Fatal("PackOutput",
622 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
623 output->GetFileName(), output->GetName(), producer->ClassName());
624 continue;
625 }
626 TString outFilename = file->GetName();
627 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
628 if (isManagedByHandler) {
629 // Terminate IO for files managed by the output handler
630 // file->Write() moved to AOD handler (A.G. 11.01.10)
631// if (file) file->Write();
632 if (file && fDebug > 2) {
633 printf(" handled file %s listing content:\n", file->GetName());
634 file->ls();
635 }
636 fOutputEventHandler->TerminateIO();
637 } else {
638 file->cd();
639 // Release object ownership to users after writing data to file
640 if (output->GetData()->InheritsFrom(TCollection::Class())) {
641 // If data is a collection, we set the name of the collection
642 // as the one of the container and we save as a single key.
643 TCollection *coll = (TCollection*)output->GetData();
644 coll->SetName(output->GetName());
645 coll->Write(output->GetName(), TObject::kSingleKey);
646 } else {
647 if (output->GetData()->InheritsFrom(TTree::Class())) {
648 TTree *tree = (TTree*)output->GetData();
649 tree->SetDirectory(file);
650 tree->AutoSave();
651 } else {
652 output->GetData()->Write();
653 }
654 }
655 if (fDebug > 2) {
656 printf(" file %s listing content:\n", output->GetFileName());
657 file->ls();
658 }
659 // Clear file list to release object ownership to user.
660// file->Clear();
661 file->Close();
662 output->SetFile(NULL);
663 }
664 // Restore current directory
665 if (opwd) opwd->cd();
666 // Check if a special output location was provided or the output files have to be merged
667 if (strlen(fSpecialOutputLocation.Data())) {
668 TString remote = fSpecialOutputLocation;
669 remote += "/";
670 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
671 if (remote.BeginsWith("alien:")) {
672 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
673 remote += outFilename;
674 remote.ReplaceAll(".root", Form("_%d.root", gid));
675 } else {
676 remote += Form("%s_%d_", gSystem->HostName(), gid);
677 remote += outFilename;
678 }
679 if (fDebug > 1)
680 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
681 output->GetName(), remote.Data());
682 TFile::Cp ( outFilename.Data(), remote.Data() );
683 // Copy extra outputs
684 if (fExtraFiles.Length() && isManagedByHandler) {
685 TObjArray *arr = fExtraFiles.Tokenize(" ");
686 TObjString *os;
687 TIter nextfilename(arr);
688 while ((os=(TObjString*)nextfilename())) {
689 outFilename = os->GetString();
690 remote = fSpecialOutputLocation;
691 remote += "/";
692 if (remote.BeginsWith("alien://")) {
693 remote += outFilename;
694 remote.ReplaceAll(".root", Form("_%d.root", gid));
695 } else {
696 remote += Form("%s_%d_", gSystem->HostName(), gid);
697 remote += outFilename;
698 }
699 if (fDebug > 1)
700 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
701 outFilename.Data(), remote.Data());
702 TFile::Cp ( outFilename.Data(), remote.Data() );
703 }
704 delete arr;
705 }
706 } else {
707 // No special location specified-> use TProofOutputFile as merging utility
708 // The file at this output slot must be opened in CreateOutputObjects
709 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
710 }
711 }
712 }
713 }
714 cdir->cd();
715 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
716}
717
718//______________________________________________________________________________
719void AliAnalysisManager::ImportWrappers(TList *source)
720{
721// Import data in output containers from wrappers coming in source.
722 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
723 TIter next(fOutputs);
724 AliAnalysisDataContainer *cont;
725 AliAnalysisDataWrapper *wrap;
726 Int_t icont = 0;
727 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
728 TDirectory *cdir = gDirectory;
729 while ((cont=(AliAnalysisDataContainer*)next())) {
730 wrap = 0;
731 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
732 if (cont->IsRegisterDataset()) continue;
733 const char *filename = cont->GetFileName();
734 Bool_t isManagedByHandler = kFALSE;
735 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
736 isManagedByHandler = kTRUE;
737 filename = fOutputEventHandler->GetOutputFileName();
738 }
739 if (cont->IsSpecialOutput() || inGrid) {
740 if (strlen(fSpecialOutputLocation.Data())) continue;
741 // Copy merged file from PROOF scratch space.
742 // In case of grid the files are already in the current directory.
743 if (!inGrid) {
744 if (isManagedByHandler && fExtraFiles.Length()) {
745 // Copy extra registered dAOD files.
746 TObjArray *arr = fExtraFiles.Tokenize(" ");
747 TObjString *os;
748 TIter nextfilename(arr);
749 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
750 delete arr;
751 }
752 if (!GetFileFromWrapper(filename, source)) continue;
753 }
754 // Normally we should connect data from the copied file to the
755 // corresponding output container, but it is not obvious how to do this
756 // automatically if several objects in file...
757 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
758 if (!f) f = TFile::Open(filename, "READ");
759 if (!f) {
760 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
761 continue;
762 }
763 TObject *obj = 0;
764 // Cd to the directory pointed by the container
765 TString folder = cont->GetFolderName();
766 if (!folder.IsNull()) f->cd(folder);
767 // Try to fetch first an object having the container name.
768 obj = gDirectory->Get(cont->GetName());
769 if (!obj) {
770 Warning("ImportWrappers", "Could not import object of type:%s for container %s in file %s:%s.\n Object will not be available in Terminate(). Try if possible to name the output object as the container (%s) or to embed it in a TList",
771 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
772 continue;
773 }
774 wrap = new AliAnalysisDataWrapper(obj);
775 wrap->SetDeleteData(kFALSE);
776 }
777 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
778 if (!wrap) {
779 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
780 continue;
781 }
782 icont++;
783 if (fDebug > 1) {
784 printf(" Importing data for container %s\n", cont->GetName());
785 if (strlen(filename)) printf(" -> file %s\n", filename);
786 else printf("\n");
787 }
788 cont->ImportData(wrap);
789 }
790 if (cdir) cdir->cd();
791 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
792}
793
794//______________________________________________________________________________
795void AliAnalysisManager::UnpackOutput(TList *source)
796{
797 // Called by AliAnalysisSelector::Terminate only on the client.
798 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
799 if (!source) {
800 Error("UnpackOutput", "No target. Exiting.");
801 return;
802 }
803 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
804
805 if (fMode == kProofAnalysis) ImportWrappers(source);
806
807 TIter next(fOutputs);
808 AliAnalysisDataContainer *output;
809 while ((output=(AliAnalysisDataContainer*)next())) {
810 if (!output->GetData()) continue;
811 // Check if there are client tasks that run post event loop
812 if (output->HasConsumers()) {
813 // Disable event loop semaphore
814 output->SetPostEventLoop(kTRUE);
815 TObjArray *list = output->GetConsumers();
816 Int_t ncons = list->GetEntriesFast();
817 for (Int_t i=0; i<ncons; i++) {
818 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
819 task->CheckNotify(kTRUE);
820 // If task is active, execute it
821 if (task->IsPostEventLoop() && task->IsActive()) {
822 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
823 task->ExecuteTask();
824 }
825 }
826 }
827 }
828 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
829}
830
831//______________________________________________________________________________
832void AliAnalysisManager::Terminate()
833{
834 // The Terminate() function is the last function to be called during
835 // a query. It always runs on the client, it can be used to present
836 // the results graphically.
837 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
838 TDirectory *cdir = gDirectory;
839 gROOT->cd();
840 AliAnalysisTask *task;
841 AliAnalysisDataContainer *output;
842 TIter next(fTasks);
843 TStopwatch timer;
844 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
845 // Call Terminate() for tasks
846 Int_t itask = 0;
847 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
848 // Save all the canvases produced by the Terminate
849 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
850 task->Terminate();
851 gROOT->cd();
852 if (getsysInfo)
853 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
854 itask++;
855 if (TObject::TestBit(kSaveCanvases)) {
856 if (!gROOT->IsBatch()) {
857 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
858 timer.Start();
859 while (timer.CpuTime()<5) {
860 timer.Continue();
861 gSystem->ProcessEvents();
862 }
863 }
864 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
865 if (iend==0) continue;
866 TCanvas *canvas;
867 for (Int_t ipict=0; ipict<iend; ipict++) {
868 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
869 if (!canvas) continue;
870 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
871 }
872 gROOT->GetListOfCanvases()->Delete();
873 }
874 }
875 //
876 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
877 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
878 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
879 gROOT->cd();
880 TObjArray *allOutputs = new TObjArray();
881 Int_t icont;
882 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
883 if (!IsSkipTerminate())
884 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
885 TIter next1(allOutputs);
886 TString handlerFile = "";
887 TString extraOutputs = "";
888 if (fOutputEventHandler) {
889 handlerFile = fOutputEventHandler->GetOutputFileName();
890 extraOutputs = fOutputEventHandler->GetExtraOutputs();
891 }
892 icont = 0;
893 TList filestmp;
894 while ((output=(AliAnalysisDataContainer*)next1())) {
895 // Special outputs or grid files have the files already closed and written.
896 icont++;
897 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
898 if (fMode == kProofAnalysis) {
899 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
900 }
901 const char *filename = output->GetFileName();
902 TString openoption = "RECREATE";
903 if (!(strcmp(filename, "default"))) continue;
904 if (!strlen(filename)) continue;
905 if (!output->GetData()) continue;
906 TDirectory *opwd = gDirectory;
907 TFile *file = output->GetFile();
908 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
909 if (!file) {
910 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
911 Bool_t firsttime = kTRUE;
912 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
913 firsttime = kFALSE;
914 } else {
915 filestmp.Add(new TNamed(filename,""));
916 }
917 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
918 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
919 file = new TFile(filename, openoption);
920 } else {
921 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
922 openoption = file->GetOption();
923 if (openoption == "READ") {
924 if (fDebug>1) printf("...reopening in UPDATE mode\n");
925 file->ReOpen("UPDATE");
926 }
927 }
928 if (file->IsZombie()) {
929 Error("Terminate", "Cannot open output file %s", filename);
930 continue;
931 }
932 output->SetFile(file);
933 file->cd();
934 // Check for a folder request
935 TString dir = output->GetFolderName();
936 if (!dir.IsNull()) {
937 if (!file->GetDirectory(dir)) file->mkdir(dir);
938 file->cd(dir);
939 }
940 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
941 if (output->GetData()->InheritsFrom(TCollection::Class())) {
942 // If data is a collection, we set the name of the collection
943 // as the one of the container and we save as a single key.
944 TCollection *coll = (TCollection*)output->GetData();
945 coll->SetName(output->GetName());
946 coll->Write(output->GetName(), TObject::kSingleKey);
947 } else {
948 if (output->GetData()->InheritsFrom(TTree::Class())) {
949 TTree *tree = (TTree*)output->GetData();
950 tree->SetDirectory(gDirectory);
951 tree->AutoSave();
952 } else {
953 output->GetData()->Write();
954 }
955 }
956 if (opwd) opwd->cd();
957 }
958 gROOT->cd();
959 next1.Reset();
960 while ((output=(AliAnalysisDataContainer*)next1())) {
961 // Close all files at output
962 TDirectory *opwd = gDirectory;
963 if (output->GetFile()) {
964 // Clear file list to release object ownership to user.
965// output->GetFile()->Clear();
966 output->GetFile()->Close();
967 output->SetFile(NULL);
968 // Copy merged outputs in alien if requested
969 if (fSpecialOutputLocation.Length() &&
970 fSpecialOutputLocation.BeginsWith("alien://")) {
971 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
972 TFile::Cp(output->GetFile()->GetName(),
973 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
974 }
975 }
976 if (opwd) opwd->cd();
977 }
978 delete allOutputs;
979 //Write statistics information on the client
980 if (fStatistics) WriteStatisticsMsg(fNcalls);
981 if (getsysInfo) {
982 TDirectory *crtdir = gDirectory;
983 TFile f("syswatch.root", "RECREATE");
984 TH1 *hist;
985 TString cut;
986 if (!f.IsZombie()) {
987 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
988 tree->SetName("syswatch");
989 tree->SetMarkerStyle(kCircle);
990 tree->SetMarkerColor(kBlue);
991 tree->SetMarkerSize(0.5);
992 if (!gROOT->IsBatch()) {
993 tree->SetAlias("event", "id0");
994 tree->SetAlias("task", "id1");
995 tree->SetAlias("stage", "id2");
996 // Already defined aliases
997 // tree->SetAlias("deltaT","stampSec-stampOldSec");
998 // tree->SetAlias("T","stampSec-first");
999 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1000 // tree->SetAlias("VM","pI.fMemVirtual");
1001 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1002 Int_t npads = 1 /*COO plot for all tasks*/ +
1003 fTopTasks->GetEntries() /*Exec plot per task*/ +
1004 1 /*Terminate plot for all tasks*/ +
1005 1; /*vm plot*/
1006
1007 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1008 if (npads<iopt*(iopt+1))
1009 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1010 else
1011 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1012 Int_t ipad = 1;
1013 // draw the plot of deltaVM for Exec for each task
1014 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1015 task = (AliAnalysisTask*)fTopTasks->At(itask);
1016 canvas->cd(ipad++);
1017 cut = Form("task==%d && stage==1", itask);
1018 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1019 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1020 if (hist) {
1021 hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
1022 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1023 }
1024 }
1025 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1026 canvas->cd(ipad++);
1027 tree->SetMarkerStyle(kFullTriangleUp);
1028 tree->SetMarkerColor(kRed);
1029 tree->SetMarkerSize(0.8);
1030 cut = "task>=0 && task<1000 && stage==0";
1031 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1032 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1033 if (hist) {
1034 hist->SetTitle("Memory in CreateOutputObjects()");
1035 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1036 hist->GetXaxis()->SetTitle("task");
1037 }
1038 // draw the plot of deltaVM for Terminate for all tasks
1039 canvas->cd(ipad++);
1040 tree->SetMarkerStyle(kOpenSquare);
1041 tree->SetMarkerColor(kMagenta);
1042 cut = "task>=0 && task<1000 && stage==2";
1043 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1044 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1045 if (hist) {
1046 hist->SetTitle("Memory in Terminate()");
1047 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1048 hist->GetXaxis()->SetTitle("task");
1049 }
1050 // Full VM profile
1051 canvas->cd(ipad++);
1052 tree->SetMarkerStyle(kFullCircle);
1053 tree->SetMarkerColor(kGreen);
1054 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1055 tree->Draw("VM:event",cut,"", 1234567890, 0);
1056 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1057 if (hist) {
1058 hist->SetTitle("Virtual memory");
1059 hist->GetYaxis()->SetTitle("VM [MB]");
1060 }
1061 canvas->Modified();
1062 }
1063 tree->SetMarkerStyle(kCircle);
1064 tree->SetMarkerColor(kBlue);
1065 tree->SetMarkerSize(0.5);
1066 tree->Write();
1067 f.Close();
1068 delete tree;
1069 }
1070 if (crtdir) crtdir->cd();
1071 }
1072 // Validate the output files
1073 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1074 ofstream out;
1075 out.open("outputs_valid", ios::out);
1076 out.close();
1077 }
1078 cdir->cd();
1079 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1080}
1081//______________________________________________________________________________
1082void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1083{
1084// Profiles the task having the itop index in the list of top (first level) tasks.
1085 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1086 if (!task) {
1087 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1088 return;
1089 }
1090 ProfileTask(task->GetName(), option);
1091}
1092
1093//______________________________________________________________________________
1094void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1095{
1096// Profile a managed task after the execution of the analysis in case NSysInfo
1097// was used.
1098 if (gSystem->AccessPathName("syswatch.root")) {
1099 Error("ProfileTask", "No file syswatch.root found in the current directory");
1100 return;
1101 }
1102 if (gROOT->IsBatch()) return;
1103 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1104 if (!task) {
1105 Error("ProfileTask", "No top task named %s known by the manager.", name);
1106 return;
1107 }
1108 Int_t itop = fTopTasks->IndexOf(task);
1109 Int_t itask = fTasks->IndexOf(task);
1110 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1111 TDirectory *cdir = gDirectory;
1112 TFile f("syswatch.root");
1113 TTree *tree = (TTree*)f.Get("syswatch");
1114 if (!tree) {
1115 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1116 return;
1117 }
1118 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1119 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1120 canvas->Divide(2, 2, 0.01, 0.01);
1121 Int_t ipad = 1;
1122 TString cut;
1123 TH1 *hist;
1124 // VM profile for COO and Terminate methods
1125 canvas->cd(ipad++);
1126 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1127 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1128 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1129 if (hist) {
1130 hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1131 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1132 hist->GetXaxis()->SetTitle("method");
1133 }
1134 // CPU profile per event
1135 canvas->cd(ipad++);
1136 cut = Form("task==%d && stage==1",itop);
1137 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1138 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1139 if (hist) {
1140 hist->SetTitle("Execution time per event");
1141 hist->GetYaxis()->SetTitle("CPU/event [s]");
1142 }
1143 // VM profile for Exec
1144 canvas->cd(ipad++);
1145 cut = Form("task==%d && stage==1",itop);
1146 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1147 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1148 if (hist) {
1149 hist->SetTitle("Alocated VM[kB] per event");
1150 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1151 }
1152 canvas->Modified();
1153 delete tree;
1154 f.Close();
1155 if (cdir) cdir->cd();
1156}
1157
1158//______________________________________________________________________________
1159void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1160{
1161// Adds a user task to the global list of tasks.
1162 if (fTasks->FindObject(task)) {
1163 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1164 return;
1165 }
1166 task->SetActive(kFALSE);
1167 fTasks->Add(task);
1168}
1169
1170//______________________________________________________________________________
1171AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1172{
1173// Retreive task by name.
1174 if (!fTasks) return NULL;
1175 return (AliAnalysisTask*)fTasks->FindObject(name);
1176}
1177
1178//______________________________________________________________________________
1179AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1180 TClass *datatype, EAliAnalysisContType type, const char *filename)
1181{
1182// Create a data container of a certain type. Types can be:
1183// kExchangeContainer = 0, used to exchange data between tasks
1184// kInputContainer = 1, used to store input data
1185// kOutputContainer = 2, used for writing result to a file
1186// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1187// the output object to a folder inside the output file
1188 if (fContainers->FindObject(name)) {
1189 Error("CreateContainer","A container named %s already defined !",name);
1190 return NULL;
1191 }
1192 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1193 fContainers->Add(cont);
1194 switch (type) {
1195 case kInputContainer:
1196 fInputs->Add(cont);
1197 break;
1198 case kOutputContainer:
1199 fOutputs->Add(cont);
1200 if (filename && strlen(filename)) {
1201 cont->SetFileName(filename);
1202 cont->SetDataOwned(kFALSE); // data owned by the file
1203 }
1204 break;
1205 case kParamContainer:
1206 fParamCont->Add(cont);
1207 if (filename && strlen(filename)) {
1208 cont->SetFileName(filename);
1209 cont->SetDataOwned(kFALSE); // data owned by the file
1210 }
1211 break;
1212 case kExchangeContainer:
1213 break;
1214 }
1215 return cont;
1216}
1217
1218//______________________________________________________________________________
1219Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1220 AliAnalysisDataContainer *cont)
1221{
1222// Connect input of an existing task to a data container.
1223 if (!task) {
1224 Error("ConnectInput", "Task pointer is NULL");
1225 return kFALSE;
1226 }
1227 if (!fTasks->FindObject(task)) {
1228 AddTask(task);
1229 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1230 }
1231 Bool_t connected = task->ConnectInput(islot, cont);
1232 return connected;
1233}
1234
1235//______________________________________________________________________________
1236Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1237 AliAnalysisDataContainer *cont)
1238{
1239// Connect output of an existing task to a data container.
1240 if (!task) {
1241 Error("ConnectOutput", "Task pointer is NULL");
1242 return kFALSE;
1243 }
1244 if (!fTasks->FindObject(task)) {
1245 AddTask(task);
1246 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1247 }
1248 Bool_t connected = task->ConnectOutput(islot, cont);
1249 return connected;
1250}
1251
1252//______________________________________________________________________________
1253void AliAnalysisManager::CleanContainers()
1254{
1255// Clean data from all containers that have already finished all client tasks.
1256 TIter next(fContainers);
1257 AliAnalysisDataContainer *cont;
1258 while ((cont=(AliAnalysisDataContainer *)next())) {
1259 if (cont->IsOwnedData() &&
1260 cont->IsDataReady() &&
1261 cont->ClientsExecuted()) cont->DeleteData();
1262 }
1263}
1264
1265//______________________________________________________________________________
1266Bool_t AliAnalysisManager::InitAnalysis()
1267{
1268// Initialization of analysis chain of tasks. Should be called after all tasks
1269// and data containers are properly connected
1270 // Reset flag and remove valid_outputs file if exists
1271 fInitOK = kFALSE;
1272 if (!gSystem->AccessPathName("outputs_valid"))
1273 gSystem->Unlink("outputs_valid");
1274 // Check for top tasks (depending only on input data containers)
1275 if (!fTasks->First()) {
1276 Error("InitAnalysis", "Analysis has no tasks !");
1277 return kFALSE;
1278 }
1279 TIter next(fTasks);
1280 AliAnalysisTask *task;
1281 AliAnalysisDataContainer *cont;
1282 Int_t ntop = 0;
1283 Int_t nzombies = 0;
1284 Bool_t iszombie = kFALSE;
1285 Bool_t istop = kTRUE;
1286 Int_t i;
1287 while ((task=(AliAnalysisTask*)next())) {
1288 istop = kTRUE;
1289 iszombie = kFALSE;
1290 Int_t ninputs = task->GetNinputs();
1291 for (i=0; i<ninputs; i++) {
1292 cont = task->GetInputSlot(i)->GetContainer();
1293 if (!cont) {
1294 if (!iszombie) {
1295 task->SetZombie();
1296 fZombies->Add(task);
1297 nzombies++;
1298 iszombie = kTRUE;
1299 }
1300 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1301 i, task->GetName());
1302 }
1303 if (iszombie) continue;
1304 // Check if cont is an input container
1305 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1306 // Connect to parent task
1307 }
1308 if (istop) {
1309 ntop++;
1310 fTopTasks->Add(task);
1311 }
1312 }
1313 if (!ntop) {
1314 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1315 return kFALSE;
1316 }
1317 // Check now if there are orphan tasks
1318 for (i=0; i<ntop; i++) {
1319 task = (AliAnalysisTask*)fTopTasks->At(i);
1320 task->SetUsed();
1321 }
1322 Int_t norphans = 0;
1323 next.Reset();
1324 while ((task=(AliAnalysisTask*)next())) {
1325 if (!task->IsUsed()) {
1326 norphans++;
1327 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1328 }
1329 }
1330 // Check the task hierarchy (no parent task should depend on data provided
1331 // by a daughter task)
1332 for (i=0; i<ntop; i++) {
1333 task = (AliAnalysisTask*)fTopTasks->At(i);
1334 if (task->CheckCircularDeps()) {
1335 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1336 PrintStatus("dep");
1337 return kFALSE;
1338 }
1339 }
1340 // Check that all containers feeding post-event loop tasks are in the outputs list
1341 TIter nextcont(fContainers); // loop over all containers
1342 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1343 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1344 if (cont->HasConsumers()) {
1345 // Check if one of the consumers is post event loop
1346 TIter nextconsumer(cont->GetConsumers());
1347 while ((task=(AliAnalysisTask*)nextconsumer())) {
1348 if (task->IsPostEventLoop()) {
1349 fOutputs->Add(cont);
1350 break;
1351 }
1352 }
1353 }
1354 }
1355 }
1356 // Check if all special output containers have a file name provided
1357 TIter nextout(fOutputs);
1358 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1359 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1360 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1361 return kFALSE;
1362 }
1363 }
1364 // Initialize requested branch list if needed
1365 if (!fAutoBranchHandling) {
1366 next.Reset();
1367 while ((task=(AliAnalysisTask*)next())) {
1368 if (!task->HasBranches()) {
1369 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches.\nUse: fBranchNames = \"ESD:br1,br2,...,brN AOD:bra1,bra2,...,braM\"",
1370 task->GetName(), task->ClassName());
1371 return kFALSE;
1372 }
1373 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1374 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1375 return kFALSE;
1376 }
1377 TString taskbranches;
1378 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1379 if (taskbranches.IsNull()) {
1380 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1381 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1382 return kFALSE;
1383 }
1384 AddBranches(taskbranches);
1385 }
1386 }
1387 fInitOK = kTRUE;
1388 return kTRUE;
1389}
1390
1391//______________________________________________________________________________
1392void AliAnalysisManager::AddBranches(const char *branches)
1393{
1394// Add branches to the existing fRequestedBranches.
1395 TString br(branches);
1396 TObjArray *arr = br.Tokenize(",");
1397 TIter next(arr);
1398 TObject *obj;
1399 while ((obj=next())) {
1400 if (!fRequestedBranches.Contains(obj->GetName())) {
1401 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1402 fRequestedBranches += obj->GetName();
1403 }
1404 }
1405 delete arr;
1406}
1407
1408//______________________________________________________________________________
1409void AliAnalysisManager::CheckBranches(Bool_t load)
1410{
1411// The method checks the input branches to be loaded during the analysis.
1412 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1413 TObjArray *arr = fRequestedBranches.Tokenize(",");
1414 TIter next(arr);
1415 TObject *obj;
1416 while ((obj=next())) {
1417 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1418 if (!br) {
1419 br = fTree->GetBranch(obj->GetName());
1420 if (!br) {
1421 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1422 continue;
1423 }
1424 }
1425 fTable.Add(br);
1426 if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry());
1427 }
1428 delete arr;
1429}
1430
1431//______________________________________________________________________________
1432void AliAnalysisManager::PrintStatus(Option_t *option) const
1433{
1434// Print task hierarchy.
1435 if (!fInitOK) {
1436 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1437 return;
1438 }
1439 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1440 if (getsysInfo)
1441 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1442 TIter next(fTopTasks);
1443 AliAnalysisTask *task;
1444 while ((task=(AliAnalysisTask*)next()))
1445 task->PrintTask(option);
1446
1447 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1448 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1449
1450 TString sopt(option);
1451 sopt.ToUpper();
1452
1453 if (sopt.Contains("ALL"))
1454 {
1455 if ( fOutputEventHandler )
1456 {
1457 cout << TString('_',78) << endl;
1458 cout << "OutputEventHandler:" << endl;
1459 fOutputEventHandler->Print(" ");
1460 }
1461 }
1462}
1463
1464//______________________________________________________________________________
1465void AliAnalysisManager::ResetAnalysis()
1466{
1467// Reset all execution flags and clean containers.
1468 CleanContainers();
1469}
1470
1471//______________________________________________________________________________
1472Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1473{
1474// Start analysis having a grid handler.
1475 if (!fGridHandler) {
1476 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1477 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1478 return -1;
1479 }
1480 TTree *tree = NULL;
1481 return StartAnalysis(type, tree, nentries, firstentry);
1482}
1483
1484//______________________________________________________________________________
1485Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1486{
1487// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1488// MIX. Process nentries starting from firstentry
1489 Long64_t retv = 0;
1490 // Backup current directory and make sure gDirectory points to gROOT
1491 TDirectory *cdir = gDirectory;
1492 gROOT->cd();
1493 if (!fInitOK) {
1494 Error("StartAnalysis","Analysis manager was not initialized !");
1495 cdir->cd();
1496 return -1;
1497 }
1498 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1499 fMaxEntries = nentries;
1500 fIsRemote = kFALSE;
1501 TString anaType = type;
1502 anaType.ToLower();
1503 fMode = kLocalAnalysis;
1504 Bool_t runlocalinit = kTRUE;
1505 if (anaType.Contains("file")) {
1506 runlocalinit = kFALSE;
1507 fIsRemote = kTRUE;
1508 }
1509 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1510 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1511 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1512
1513 if (fMode == kGridAnalysis) {
1514 fIsRemote = kTRUE;
1515 if (!anaType.Contains("terminate")) {
1516 if (!fGridHandler) {
1517 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1518 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1519 cdir->cd();
1520 return -1;
1521 }
1522 // Write analysis manager in the analysis file
1523 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1524 // run local task configuration
1525 TIter nextTask(fTasks);
1526 AliAnalysisTask *task;
1527 while ((task=(AliAnalysisTask*)nextTask())) {
1528 task->LocalInit();
1529 gROOT->cd();
1530 }
1531 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1532 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1533 cdir->cd();
1534 return -1;
1535 }
1536
1537 // Terminate grid analysis
1538 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1539 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1540 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1541 if (!fGridHandler->MergeOutputs()) {
1542 // Return if outputs could not be merged or if it alien handler
1543 // was configured for offline mode or local testing.
1544 cdir->cd();
1545 return 0;
1546 }
1547 }
1548 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1549 ImportWrappers(NULL);
1550 Terminate();
1551 cdir->cd();
1552 return 0;
1553 }
1554 TString line;
1555 SetEventLoop(kFALSE);
1556 // Enable event loop mode if a tree was provided
1557 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1558
1559 TChain *chain = 0;
1560 TString ttype = "TTree";
1561 if (tree && tree->IsA() == TChain::Class()) {
1562 chain = (TChain*)tree;
1563 if (!chain || !chain->GetListOfFiles()->First()) {
1564 Error("StartAnalysis", "Cannot process null or empty chain...");
1565 cdir->cd();
1566 return -1;
1567 }
1568 ttype = "TChain";
1569 }
1570
1571 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1572 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1573 // Initialize locally all tasks (happens for all modes)
1574 TIter next(fTasks);
1575 AliAnalysisTask *task;
1576 if (runlocalinit) {
1577 while ((task=(AliAnalysisTask*)next())) {
1578 task->LocalInit();
1579 gROOT->cd();
1580 }
1581 if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1582 }
1583
1584 switch (fMode) {
1585 case kLocalAnalysis:
1586 if (!tree && !fGridHandler) {
1587 TIter nextT(fTasks);
1588 // Call CreateOutputObjects for all tasks
1589 Int_t itask = 0;
1590 Bool_t dirStatus = TH1::AddDirectoryStatus();
1591 while ((task=(AliAnalysisTask*)nextT())) {
1592 TH1::AddDirectory(kFALSE);
1593 task->CreateOutputObjects();
1594 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1595 gROOT->cd();
1596 itask++;
1597 }
1598 TH1::AddDirectory(dirStatus);
1599 if (IsExternalLoop()) {
1600 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1601 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1602 return 0;
1603 }
1604 ExecAnalysis();
1605 Terminate();
1606 return 0;
1607 }
1608 fSelector = new AliAnalysisSelector(this);
1609 // Check if a plugin handler is used
1610 if (fGridHandler) {
1611 // Get the chain from the plugin
1612 TString dataType = "esdTree";
1613 if (fInputEventHandler) {
1614 dataType = fInputEventHandler->GetDataType();
1615 dataType.ToLower();
1616 dataType += "Tree";
1617 }
1618 chain = fGridHandler->GetChainForTestMode(dataType);
1619 if (!chain) {
1620 Error("StartAnalysis", "No chain for test mode. Aborting.");
1621 return -1;
1622 }
1623 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1624 retv = chain->Process(fSelector, "", nentries, firstentry);
1625 break;
1626 }
1627 // Run tree-based analysis via AliAnalysisSelector
1628 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1629 retv = tree->Process(fSelector, "", nentries, firstentry);
1630 break;
1631 case kProofAnalysis:
1632 fIsRemote = kTRUE;
1633 // Check if the plugin is used
1634 if (fGridHandler) {
1635 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1636 }
1637 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1638 Error("StartAnalysis", "No PROOF!!! Exiting.");
1639 cdir->cd();
1640 return -1;
1641 }
1642 line = Form("gProof->AddInput((TObject*)%p);", this);
1643 gROOT->ProcessLine(line);
1644 if (chain) {
1645 chain->SetProof();
1646 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1647 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1648 } else {
1649 Error("StartAnalysis", "No chain!!! Exiting.");
1650 cdir->cd();
1651 return -1;
1652 }
1653 break;
1654 case kGridAnalysis:
1655 fIsRemote = kTRUE;
1656 if (!anaType.Contains("terminate")) {
1657 if (!fGridHandler) {
1658 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1659 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1660 cdir->cd();
1661 return -1;
1662 }
1663 // Write analysis manager in the analysis file
1664 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1665 // Start the analysis via the handler
1666 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1667 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1668 cdir->cd();
1669 return -1;
1670 }
1671
1672 // Terminate grid analysis
1673 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1674 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1675 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1676 if (!fGridHandler->MergeOutputs()) {
1677 // Return if outputs could not be merged or if it alien handler
1678 // was configured for offline mode or local testing.
1679 cdir->cd();
1680 return 0;
1681 }
1682 }
1683 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1684 ImportWrappers(NULL);
1685 Terminate();
1686 cdir->cd();
1687 return 0;
1688 case kMixingAnalysis:
1689 // Run event mixing analysis
1690 if (!fEventPool) {
1691 Error("StartAnalysis", "Cannot run event mixing without event pool");
1692 cdir->cd();
1693 return -1;
1694 }
1695 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1696 fSelector = new AliAnalysisSelector(this);
1697 while ((chain=fEventPool->GetNextChain())) {
1698 next.Reset();
1699 // Call NotifyBinChange for all tasks
1700 while ((task=(AliAnalysisTask*)next()))
1701 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1702 retv = chain->Process(fSelector);
1703 if (retv < 0) {
1704 Error("StartAnalysis", "Mixing analysis failed");
1705 cdir->cd();
1706 return retv;
1707 }
1708 }
1709 PackOutput(fSelector->GetOutputList());
1710 Terminate();
1711 }
1712 cdir->cd();
1713 return retv;
1714}
1715
1716//______________________________________________________________________________
1717Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1718{
1719// Start analysis for this manager on a given dataset. Analysis task can be:
1720// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1721 if (!fInitOK) {
1722 Error("StartAnalysis","Analysis manager was not initialized !");
1723 return -1;
1724 }
1725 fIsRemote = kTRUE;
1726 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1727 TString anaType = type;
1728 anaType.ToLower();
1729 if (!anaType.Contains("proof")) {
1730 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1731 return -1;
1732 }
1733 fMode = kProofAnalysis;
1734 TString line;
1735 SetEventLoop(kTRUE);
1736 // Set the dataset flag
1737 TObject::SetBit(kUseDataSet);
1738 fTree = 0;
1739 if (fGridHandler) {
1740 // Start proof analysis using the grid handler
1741 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1742 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1743 return -1;
1744 }
1745 // Check if the plugin is in test mode
1746 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1747 dataset = "test_collection";
1748 } else {
1749 dataset = fGridHandler->GetProofDataSet();
1750 }
1751 }
1752
1753 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1754 Error("StartAnalysis", "No PROOF!!! Exiting.");
1755 return -1;
1756 }
1757
1758 // Initialize locally all tasks
1759 TIter next(fTasks);
1760 AliAnalysisTask *task;
1761 while ((task=(AliAnalysisTask*)next())) {
1762 task->LocalInit();
1763 }
1764
1765 line = Form("gProof->AddInput((TObject*)%p);", this);
1766 gROOT->ProcessLine(line);
1767 Long_t retv;
1768 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1769 dataset, nentries, firstentry);
1770 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1771 retv = (Long_t)gROOT->ProcessLine(line);
1772 return retv;
1773}
1774
1775//______________________________________________________________________________
1776TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1777{
1778// Opens according the option the file specified by cont->GetFileName() and changes
1779// current directory to cont->GetFolderName(). If the file was already opened, it
1780// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1781// be optionally ignored.
1782 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1783 TString filename = cont->GetFileName();
1784 TFile *f = NULL;
1785 if (filename.IsNull()) {
1786 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1787 return NULL;
1788 }
1789 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1790 && !ignoreProof)
1791 f = mgr->OpenProofFile(cont,option);
1792 else {
1793 // Check first if the file is already opened
1794 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1795 if (f) {
1796 // Check if option "UPDATE" was preserved
1797 TString opt(option);
1798 opt.ToUpper();
1799 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1800 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1801 } else {
1802 f = TFile::Open(filename, option);
1803 }
1804 }
1805 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1806 cont->SetFile(f);
1807 // Cd to file
1808 f->cd();
1809 // Check for a folder request
1810 TString dir = cont->GetFolderName();
1811 if (!dir.IsNull()) {
1812 if (!f->GetDirectory(dir)) f->mkdir(dir);
1813 f->cd(dir);
1814 }
1815 return f;
1816 }
1817 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1818 cont->SetFile(NULL);
1819 return NULL;
1820}
1821
1822//______________________________________________________________________________
1823TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1824{
1825// Opens a special output file used in PROOF.
1826 TString line;
1827 TString filename = cont->GetFileName();
1828 if (cont == fCommonOutput) {
1829 if (fOutputEventHandler) {
1830 if (strlen(extaod)) filename = extaod;
1831 filename = fOutputEventHandler->GetOutputFileName();
1832 }
1833 else Fatal("OpenProofFile","No output container. Exiting.");
1834 }
1835 TFile *f = NULL;
1836 if (fMode!=kProofAnalysis || !fSelector) {
1837 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1838 return NULL;
1839 }
1840 if (fSpecialOutputLocation.Length()) {
1841 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1842 if (f) {
1843 // Check if option "UPDATE" was preserved
1844 TString opt(option);
1845 opt.ToUpper();
1846 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1847 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1848 } else {
1849 f = new TFile(filename, option);
1850 }
1851 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1852 cont->SetFile(f);
1853 // Cd to file
1854 f->cd();
1855 // Check for a folder request
1856 TString dir = cont->GetFolderName();
1857 if (dir.Length()) {
1858 if (!f->GetDirectory(dir)) f->mkdir(dir);
1859 f->cd(dir);
1860 }
1861 return f;
1862 }
1863 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1864 cont->SetFile(NULL);
1865 return NULL;
1866 }
1867 // Check if there is already a proof output file in the output list
1868 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1869 if (pof) {
1870 // Get the actual file
1871 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
1872 filename = (const char*)gROOT->ProcessLine(line);
1873 if (fDebug>1) {
1874 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1875 }
1876 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1877 if (!f) {
1878 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1879 return NULL;
1880 }
1881 // Check if option "UPDATE" was preserved
1882 TString opt(option);
1883 opt.ToUpper();
1884 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1885 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1886 } else {
1887 if (cont->IsRegisterDataset()) {
1888 TString dsetName = filename;
1889 dsetName.ReplaceAll(".root", cont->GetTitle());
1890 dsetName.ReplaceAll(":","_");
1891 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1892 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1893 } else {
1894 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1895 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1896 }
1897 if (fDebug > 1) printf("=== %s\n", line.Data());
1898 gROOT->ProcessLine(line);
1899 line = Form("pf->OpenFile(\"%s\");", option);
1900 gROOT->ProcessLine(line);
1901 f = gFile;
1902 if (fDebug > 1) {
1903 gROOT->ProcessLine("pf->Print()");
1904 printf(" == proof file name: %s", f->GetName());
1905 }
1906 // Add to proof output list
1907 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
1908 if (fDebug > 1) printf("=== %s\n", line.Data());
1909 gROOT->ProcessLine(line);
1910 }
1911 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1912 cont->SetFile(f);
1913 // Cd to file
1914 f->cd();
1915 // Check for a folder request
1916 TString dir = cont->GetFolderName();
1917 if (!dir.IsNull()) {
1918 if (!f->GetDirectory(dir)) f->mkdir(dir);
1919 f->cd(dir);
1920 }
1921 return f;
1922 }
1923 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1924 cont->SetFile(NULL);
1925 return NULL;
1926}
1927
1928//______________________________________________________________________________
1929void AliAnalysisManager::ExecAnalysis(Option_t *option)
1930{
1931// Execute analysis.
1932 static Long64_t nentries = 0;
1933 static TTree *lastTree = 0;
1934 static TStopwatch *timer = new TStopwatch();
1935 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
1936 else {
1937 if (fTree && (fTree != lastTree)) {
1938 nentries += fTree->GetEntries();
1939 lastTree = fTree;
1940 }
1941 if (!fNcalls) timer->Start();
1942 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
1943 }
1944 gROOT->cd();
1945 TDirectory *cdir = gDirectory;
1946 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1947 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
1948 if (!fInitOK) {
1949 Error("ExecAnalysis", "Analysis manager was not initialized !");
1950 cdir->cd();
1951 return;
1952 }
1953 fNcalls++;
1954 AliAnalysisTask *task;
1955 // Check if the top tree is active.
1956 if (fTree) {
1957 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1958 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
1959 TIter next(fTasks);
1960 // De-activate all tasks
1961 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1962 AliAnalysisDataContainer *cont = fCommonInput;
1963 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1964 if (!cont) {
1965 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1966 cdir->cd();
1967 return;
1968 }
1969 cont->SetData(fTree); // This will notify all consumers
1970 Long64_t entry = fTree->GetTree()->GetReadEntry();
1971//
1972// Call BeginEvent() for optional input/output and MC services
1973 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1974 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1975 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1976 gROOT->cd();
1977 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1978 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
1979//
1980// Execute the tasks
1981// TIter next1(cont->GetConsumers());
1982 TIter next1(fTopTasks);
1983 Int_t itask = 0;
1984 while ((task=(AliAnalysisTask*)next1())) {
1985 if (fDebug >1) {
1986 cout << " Executing task " << task->GetName() << endl;
1987 }
1988 task->ExecuteTask(option);
1989 gROOT->cd();
1990 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1991 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
1992 itask++;
1993 }
1994//
1995// Call FinishEvent() for optional output and MC services
1996 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1997 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1998 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1999 // Gather system information if requested
2000 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2001 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2002 cdir->cd();
2003 return;
2004 }
2005 // The event loop is not controlled by TSelector
2006//
2007// Call BeginEvent() for optional input/output and MC services
2008 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2009 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2010 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2011 gROOT->cd();
2012 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2013 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2014 TIter next2(fTopTasks);
2015 while ((task=(AliAnalysisTask*)next2())) {
2016 task->SetActive(kTRUE);
2017 if (fDebug > 1) {
2018 cout << " Executing task " << task->GetName() << endl;
2019 }
2020 task->ExecuteTask(option);
2021 gROOT->cd();
2022 }
2023//
2024// Call FinishEvent() for optional output and MC services
2025 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2026 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2027 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2028 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2029 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2030 cdir->cd();
2031}
2032
2033//______________________________________________________________________________
2034Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2035{
2036// Check if the stdout is connected to a pipe (C.Holm)
2037 Bool_t ispipe = kFALSE;
2038 out.seekp(0, std::ios_base::cur);
2039 if (out.fail()) {
2040 out.clear();
2041 if (errno == ESPIPE) ispipe = kTRUE;
2042 }
2043 return ispipe;
2044}
2045
2046//______________________________________________________________________________
2047void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2048{
2049// Set the input event handler and create a container for it.
2050 fInputEventHandler = handler;
2051 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2052}
2053
2054//______________________________________________________________________________
2055void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2056{
2057// Set the input event handler and create a container for it.
2058 fOutputEventHandler = handler;
2059 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2060 fCommonOutput->SetSpecialOutput();
2061}
2062
2063//______________________________________________________________________________
2064void AliAnalysisManager::SetDebugLevel(UInt_t level)
2065{
2066// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2067 if (TObject::TestBit(kUseProgressBar)) {
2068 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2069 return;
2070 }
2071 fDebug = level;
2072}
2073
2074//______________________________________________________________________________
2075void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2076{
2077// Enable a text mode progress bar. Resets debug level to 0.
2078 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2079 TObject::SetBit(kUseProgressBar,flag);
2080 fPBUpdateFreq = freq;
2081 fDebug = 0;
2082}
2083
2084//______________________________________________________________________________
2085void AliAnalysisManager::RegisterExtraFile(const char *fname)
2086{
2087// This method is used externally to register output files which are not
2088// connected to any output container, so that the manager can properly register,
2089// retrieve or merge them when running in distributed mode. The file names are
2090// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2091 if (fExtraFiles.Contains(fname)) return;
2092 if (fExtraFiles.Length()) fExtraFiles += " ";
2093 fExtraFiles += fname;
2094}
2095
2096//______________________________________________________________________________
2097Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2098{
2099// Copy a file from the location specified ina the wrapper with the same name from the source list.
2100 char fullPath[512];
2101 char chUrl[512];
2102 char tmp[1024];
2103 TObject *pof = source->FindObject(filename);
2104 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2105 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2106 return kFALSE;
2107 }
2108 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2109 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2110 TString clientUrl(chUrl);
2111 TString fullPath_str(fullPath);
2112 if (clientUrl.Contains("localhost")){
2113 TObjArray* array = fullPath_str.Tokenize ( "//" );
2114 TObjString *strobj = ( TObjString *)array->At(1);
2115 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2116 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2117 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2118 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2119 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2120 delete arrayPort;
2121 delete array;
2122 }
2123 else if (clientUrl.Contains("__lite__")) {
2124 // Special case for ProofLite environement - get file info and copy.
2125 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2126 fullPath_str = Form("%s/%s", tmp, fullPath);
2127 }
2128 if (fDebug > 1)
2129 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2130 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2131 if (!gotit)
2132 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2133 return gotit;
2134}
2135
2136//______________________________________________________________________________
2137void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2138{
2139// Fill analysis type in the provided string.
2140 switch (fMode) {
2141 case kLocalAnalysis:
2142 type = "local";
2143 return;
2144 case kProofAnalysis:
2145 type = "proof";
2146 return;
2147 case kGridAnalysis:
2148 type = "grid";
2149 return;
2150 case kMixingAnalysis:
2151 type = "mix";
2152 }
2153}
2154
2155//______________________________________________________________________________
2156Bool_t AliAnalysisManager::ValidateOutputFiles() const
2157{
2158// Validate all output files.
2159 TIter next(fOutputs);
2160 AliAnalysisDataContainer *output;
2161 TDirectory *cdir = gDirectory;
2162 TString openedFiles;
2163 while ((output=(AliAnalysisDataContainer*)next())) {
2164 if (output->IsRegisterDataset()) continue;
2165 TString filename = output->GetFileName();
2166 if (filename == "default") {
2167 if (!fOutputEventHandler) continue;
2168 filename = fOutputEventHandler->GetOutputFileName();
2169 // Main AOD may not be there
2170 if (gSystem->AccessPathName(filename)) continue;
2171 }
2172 // Check if the file is closed
2173 if (openedFiles.Contains(filename)) continue;;
2174 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2175 if (file) {
2176 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2177 // Clear file list to release object ownership to user.
2178// file->Clear();
2179 file->Close();
2180 }
2181 file = TFile::Open(filename);
2182 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2183 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2184 cdir->cd();
2185 return kFALSE;
2186 }
2187 file->Close();
2188 openedFiles += filename;
2189 openedFiles += " ";
2190 }
2191 cdir->cd();
2192 return kTRUE;
2193}
2194
2195//______________________________________________________________________________
2196void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2197{
2198// Implements a nice text mode progress bar.
2199 static Long64_t icount = 0;
2200 static TString oname;
2201 static TString nname;
2202 static Long64_t ocurrent = 0;
2203 static Long64_t osize = 0;
2204 static Int_t oseconds = 0;
2205 static TStopwatch *owatch = 0;
2206 static Bool_t oneoftwo = kFALSE;
2207 static Int_t nrefresh = 0;
2208 static Int_t nchecks = 0;
2209 static char lastChar = 0;
2210 const char symbol[4] = {'-','\\','|','/'};
2211
2212 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2213 if (!refresh) {
2214 nrefresh = 0;
2215 if (!size) return;
2216 owatch = watch;
2217 oname = opname;
2218 ocurrent = TMath::Abs(current);
2219 osize = TMath::Abs(size);
2220 if (ocurrent > osize) ocurrent=osize;
2221 } else {
2222 nrefresh++;
2223 if (!osize) return;
2224 }
2225 if ((current % fPBUpdateFreq) != 0) return;
2226 icount++;
2227 char progress[11] = " ";
2228 Int_t ichar = icount%4;
2229 Double_t time = 0.;
2230 Int_t hours = 0;
2231 Int_t minutes = 0;
2232 Int_t seconds = 0;
2233 if (owatch && !last) {
2234 owatch->Stop();
2235 time = owatch->RealTime();
2236 seconds = int(time) % 60;
2237 minutes = (int(time) / 60) % 60;
2238 hours = (int(time) / 60 / 60);
2239 if (refresh) {
2240 if (oseconds==seconds) {
2241 owatch->Continue();
2242 return;
2243 }
2244 oneoftwo = !oneoftwo;
2245 }
2246 oseconds = seconds;
2247 }
2248 if (refresh && oneoftwo) {
2249 nname = oname;
2250 if (nchecks <= 0) nchecks = nrefresh+1;
2251 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2252 oname = Form(" == %d%% ==", pctdone);
2253 }
2254 Double_t percent = 100.0*ocurrent/osize;
2255 Int_t nchar = Int_t(percent/10);
2256 if (nchar>10) nchar=10;
2257 Int_t i;
2258 for (i=0; i<nchar; i++) progress[i] = '=';
2259 progress[nchar] = symbol[ichar];
2260 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2261 progress[10] = '\0';
2262 oname += " ";
2263 oname.Remove(20);
2264 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2265 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2266 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2267 if (time>0.) {
2268 Int_t full = Int_t(ocurrent > 0 ?
2269 time * (float(osize)/ocurrent) + .5 :
2270 99*3600+59*60+59);
2271 Int_t remain = full - time;
2272 Int_t rsec = remain % 60;
2273 Int_t rmin = (remain / 60) % 60;
2274 Int_t rhour = (remain / 60 / 60);
2275 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2276 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2277 }
2278 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2279 if (refresh && oneoftwo) oname = nname;
2280 if (owatch) owatch->Continue();
2281 if (last) {
2282 icount = 0;
2283 owatch = 0;
2284 ocurrent = 0;
2285 osize = 0;
2286 oseconds = 0;
2287 oneoftwo = kFALSE;
2288 nrefresh = 0;
2289 fprintf(stderr, "\n");
2290 }
2291}
2292
2293//______________________________________________________________________________
2294void AliAnalysisManager::DoLoadBranch(const char *name)
2295{
2296 // Get tree and load branch if needed.
2297 static Long64_t crtEntry = -100;
2298
2299 if (fAutoBranchHandling || !fTree)
2300 return;
2301
2302 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2303 if (!br) {
2304 br = fTree->GetBranch(name);
2305 if (!br) {
2306 Error("DoLoadBranch", "Could not find branch %s",name);
2307 return;
2308 }
2309 fTable.Add(br);
2310 }
2311 if (br->GetReadEntry()==fCurrentEntry) return;
2312 Int_t ret = br->GetEntry(GetCurrentEntry());
2313 if (ret<0) {
2314 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2315 if (crtEntry != fCurrentEntry) {
2316 CountEvent(1,0,1,0);
2317 crtEntry = fCurrentEntry;
2318 }
2319 } else {
2320 if (crtEntry != fCurrentEntry) {
2321 CountEvent(1,1,0,0);
2322 crtEntry = fCurrentEntry;
2323 }
2324 }
2325}
2326
2327//______________________________________________________________________________
2328void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2329{
2330// Add the statistics task to the manager.
2331 if (fStatistics) {
2332 Info("AddStatisticsTask", "Already added");
2333 return;
2334 }
2335 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2336 gROOT->ProcessLine(line);
2337}
2338
2339//______________________________________________________________________________
2340void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2341{
2342// Bookkeep current event;
2343 if (!fStatistics) return;
2344 fStatistics->AddInput(ninput);
2345 fStatistics->AddProcessed(nprocessed);
2346 fStatistics->AddFailed(nfailed);
2347 fStatistics->AddAccepted(naccepted);
2348}
2349
2350//______________________________________________________________________________
2351void AliAnalysisManager::AddStatisticsMsg(const char *line)
2352{
2353// Add a line in the statistics message. If available, the statistics message is written
2354// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2355// on the client.
2356 if (!strlen(line)) return;
2357 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2358 fStatisticsMsg += line;
2359}
2360
2361//______________________________________________________________________________
2362void AliAnalysisManager::WriteStatisticsMsg(Int_t nevents)
2363{
2364// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2365 static Bool_t done = kFALSE;
2366 if (done) return;
2367 done = kTRUE;
2368 if (!fStatistics) return;
2369 ofstream out;
2370 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2371 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2372 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2373 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2374 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2375 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2376 fStatistics->GetNaccepted()), ios::out);
2377 out << fStatisticsMsg << endl;
2378 out.close();
2379}
2380
2381//______________________________________________________________________________
2382const char* AliAnalysisManager::GetOADBPath()
2383{
2384// returns the path of the OADB
2385// this static function just depends on environment variables
2386
2387 static TString oadbPath;
2388
2389 if (gSystem->Getenv("OADB_PATH"))
2390 oadbPath = gSystem->Getenv("OADB_PATH");
2391 else if (gSystem->Getenv("ALICE_ROOT"))
2392 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2393 else
2394 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2395
2396 return oadbPath;
2397}