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