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