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