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