Adding histogram for bookkeeping of the number of events that do not pass event cuts...
[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;
c52c2132 477 while ((output=(AliAnalysisDataContainer*)next())) {
8d7d3b59 478 // Do not consider outputs of post event loop tasks
2b83ca27 479 isManagedByHandler = kFALSE;
8d7d3b59 480 if (output->GetProducer()->IsPostEventLoop()) continue;
4ab472d4 481 const char *filename = output->GetFileName();
482 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
483 isManagedByHandler = kTRUE;
84fcd93f 484 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
4ab472d4 485 filename = fOutputEventHandler->GetOutputFileName();
486 }
8d7d3b59 487 // Check if data was posted to this container. If not, issue an error.
4ab472d4 488 if (!output->GetData() && !isManagedByHandler) {
923e2ca5 489 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
8d7d3b59 490 continue;
491 }
492 if (!output->IsSpecialOutput()) {
493 // Normal outputs
4ab472d4 494 if (strlen(filename) && !isManagedByHandler) {
8d7d3b59 495 // Backup current folder
ca78991b 496 TDirectory *opwd = gDirectory;
f2087b52 497 // File resident outputs.
498 // Check first if the file exists.
61505f8b 499 TString openoption = "RECREATE";
500 if (!gSystem->AccessPathName(output->GetFileName())) openoption = "UPDATE";
501 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
8d7d3b59 502 // Save data to file, then close.
1be433fc 503 if (output->GetData()->InheritsFrom(TCollection::Class())) {
504 // If data is a collection, we set the name of the collection
505 // as the one of the container and we save as a single key.
506 TCollection *coll = (TCollection*)output->GetData();
507 coll->SetName(output->GetName());
508 coll->Write(output->GetName(), TObject::kSingleKey);
509 } else {
cbc8747a 510 if (output->GetData()->InheritsFrom(TTree::Class())) {
511 TTree *tree = (TTree*)output->GetData();
57756ec5 512 // Check if tree is in memory
513 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
cbc8747a 514 tree->AutoSave();
515 } else {
516 output->GetData()->Write();
517 }
1be433fc 518 }
84fcd93f 519 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
8d7d3b59 520 if (fDebug > 2) {
84fcd93f 521 printf(" file %s listing content:\n", filename);
8d7d3b59 522 file->ls();
523 }
f3c07fbd 524 // Clear file list to release object ownership to user.
160e7161 525// file->Clear();
ca78991b 526 file->Close();
84fcd93f 527 output->SetFile(NULL);
ca78991b 528 // Restore current directory
529 if (opwd) opwd->cd();
8d7d3b59 530 } else {
531 // Memory-resident outputs
84fcd93f 532 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
4ab472d4 533 }
534 AliAnalysisDataWrapper *wrap = 0;
535 if (isManagedByHandler) {
536 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
537 wrap->SetName(output->GetName());
ca78991b 538 }
4ab472d4 539 else wrap =output->ExportData();
cbc8747a 540 // Output wrappers must NOT delete data after merging - the user owns them
541 wrap->SetDeleteData(kFALSE);
8167b1d0 542 target->Add(wrap);
4ab472d4 543 } else {
f5e61abd 544 // Special outputs. The file must be opened and connected to the container.
d0864eb4 545 TDirectory *opwd = gDirectory;
8d7d3b59 546 TFile *file = output->GetFile();
f5e61abd 547 if (!file) {
548 AliAnalysisTask *producer = output->GetProducer();
84fcd93f 549 Fatal("PackOutput",
f5e61abd 550 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
551 output->GetFileName(), output->GetName(), producer->ClassName());
552 continue;
553 }
554 TString outFilename = file->GetName();
84fcd93f 555 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
4ab472d4 556 if (isManagedByHandler) {
557 // Terminate IO for files managed by the output handler
aa399a26 558 // file->Write() moved to AOD handler (A.G. 11.01.10)
559// if (file) file->Write();
802f90ef 560 if (file && fDebug > 2) {
84fcd93f 561 printf(" handled file %s listing content:\n", file->GetName());
802f90ef 562 file->ls();
563 }
4ab472d4 564 fOutputEventHandler->TerminateIO();
f5e61abd 565 } else {
566 file->cd();
567 // Release object ownership to users after writing data to file
568 if (output->GetData()->InheritsFrom(TCollection::Class())) {
569 // If data is a collection, we set the name of the collection
570 // as the one of the container and we save as a single key.
571 TCollection *coll = (TCollection*)output->GetData();
572 coll->SetName(output->GetName());
573 coll->Write(output->GetName(), TObject::kSingleKey);
cbc8747a 574 } else {
f5e61abd 575 if (output->GetData()->InheritsFrom(TTree::Class())) {
576 TTree *tree = (TTree*)output->GetData();
577 tree->SetDirectory(file);
578 tree->AutoSave();
579 } else {
580 output->GetData()->Write();
581 }
582 }
f5e61abd 583 if (fDebug > 2) {
84fcd93f 584 printf(" file %s listing content:\n", output->GetFileName());
f5e61abd 585 file->ls();
586 }
f3c07fbd 587 // Clear file list to release object ownership to user.
160e7161 588// file->Clear();
f5e61abd 589 file->Close();
84fcd93f 590 output->SetFile(NULL);
ef73322e 591 }
8d7d3b59 592 // Restore current directory
d0864eb4 593 if (opwd) opwd->cd();
8d7d3b59 594 // Check if a special output location was provided or the output files have to be merged
13ef3bb0 595 if (strlen(fSpecialOutputLocation.Data())) {
596 TString remote = fSpecialOutputLocation;
597 remote += "/";
ef788aee 598 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
f5e61abd 599 if (remote.BeginsWith("alien://")) {
600 gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
601 remote += outFilename;
602 remote.ReplaceAll(".root", Form("_%d.root", gid));
603 } else {
604 remote += Form("%s_%d_", gSystem->HostName(), gid);
605 remote += outFilename;
606 }
607 if (fDebug > 1)
608 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
609 output->GetName(), remote.Data());
ef73322e 610 TFile::Cp ( outFilename.Data(), remote.Data() );
c9e39043 611 // Copy extra outputs
612 if (fExtraFiles.Length() && isManagedByHandler) {
613 TObjArray *arr = fExtraFiles.Tokenize(" ");
614 TObjString *os;
615 TIter nextfilename(arr);
616 while ((os=(TObjString*)nextfilename())) {
617 outFilename = os->GetString();
618 remote = fSpecialOutputLocation;
619 remote += "/";
620 if (remote.BeginsWith("alien://")) {
621 remote += outFilename;
622 remote.ReplaceAll(".root", Form("_%d.root", gid));
623 } else {
624 remote += Form("%s_%d_", gSystem->HostName(), gid);
625 remote += outFilename;
626 }
627 if (fDebug > 1)
628 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
629 outFilename.Data(), remote.Data());
630 TFile::Cp ( outFilename.Data(), remote.Data() );
631 }
632 delete arr;
633 }
ca78991b 634 } else {
8d7d3b59 635 // No special location specified-> use TProofOutputFile as merging utility
636 // The file at this output slot must be opened in CreateOutputObjects
84fcd93f 637 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
13ef3bb0 638 }
639 }
c52c2132 640 }
641 }
57756ec5 642 cdir->cd();
cd463514 643 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
c52c2132 644}
645
646//______________________________________________________________________________
981f2614 647void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 648{
981f2614 649// Import data in output containers from wrappers coming in source.
cd463514 650 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
327eaf46 651 TIter next(fOutputs);
981f2614 652 AliAnalysisDataContainer *cont;
653 AliAnalysisDataWrapper *wrap;
654 Int_t icont = 0;
c57f56b7 655 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
84fcd93f 656 TDirectory *cdir = gDirectory;
c52c2132 657 while ((cont=(AliAnalysisDataContainer*)next())) {
0355fc48 658 wrap = 0;
f3c07fbd 659 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
90a4b3ee 660 if (cont->IsRegisterDataset()) continue;
4ab472d4 661 const char *filename = cont->GetFileName();
662 Bool_t isManagedByHandler = kFALSE;
663 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
664 isManagedByHandler = kTRUE;
665 filename = fOutputEventHandler->GetOutputFileName();
666 }
c57f56b7 667 if (cont->IsSpecialOutput() || inGrid) {
f5e61abd 668 if (strlen(fSpecialOutputLocation.Data())) continue;
c57f56b7 669 // Copy merged file from PROOF scratch space.
670 // In case of grid the files are already in the current directory.
671 if (!inGrid) {
c07b9ce2 672 if (isManagedByHandler && fExtraFiles.Length()) {
673 // Copy extra registered dAOD files.
674 TObjArray *arr = fExtraFiles.Tokenize(" ");
675 TObjString *os;
676 TIter nextfilename(arr);
677 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
678 delete arr;
c57f56b7 679 }
c07b9ce2 680 if (!GetFileFromWrapper(filename, source)) continue;
c57f56b7 681 }
8d7d3b59 682 // Normally we should connect data from the copied file to the
683 // corresponding output container, but it is not obvious how to do this
684 // automatically if several objects in file...
84fcd93f 685 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
686 if (!f) f = TFile::Open(filename, "READ");
dd197a68 687 if (!f) {
688 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
0355fc48 689 continue;
dd197a68 690 }
691 TObject *obj = 0;
84fcd93f 692 // Cd to the directory pointed by the container
693 TString folder = cont->GetFolderName();
694 if (!folder.IsNull()) f->cd(folder);
695 // Try to fetch first an object having the container name.
696 obj = gDirectory->Get(cont->GetName());
dd197a68 697 if (!obj) {
84fcd93f 698 Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()",
699 cont->GetName(), filename, cont->GetFolderName());
dd197a68 700 continue;
701 }
0355fc48 702 wrap = new AliAnalysisDataWrapper(obj);
703 wrap->SetDeleteData(kFALSE);
8d7d3b59 704 }
0355fc48 705 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 706 if (!wrap) {
707 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 708 continue;
709 }
981f2614 710 icont++;
8d7d3b59 711 if (fDebug > 1) {
84fcd93f 712 printf(" Importing data for container %s\n", cont->GetName());
713 if (strlen(filename)) printf(" -> file %s\n", filename);
714 else printf("\n");
8d7d3b59 715 }
981f2614 716 cont->ImportData(wrap);
84fcd93f 717 }
718 if (cdir) cdir->cd();
cd463514 719 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 720}
721
722//______________________________________________________________________________
723void AliAnalysisManager::UnpackOutput(TList *source)
724{
ca78991b 725 // Called by AliAnalysisSelector::Terminate only on the client.
cd463514 726 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 727 if (!source) {
61505f8b 728 Error("UnpackOutput", "No target. Exiting.");
c52c2132 729 return;
730 }
84fcd93f 731 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
c52c2132 732
981f2614 733 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 734
981f2614 735 TIter next(fOutputs);
c52c2132 736 AliAnalysisDataContainer *output;
737 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 738 if (!output->GetData()) continue;
b1310ef5 739 // Check if there are client tasks that run post event loop
740 if (output->HasConsumers()) {
741 // Disable event loop semaphore
742 output->SetPostEventLoop(kTRUE);
743 TObjArray *list = output->GetConsumers();
744 Int_t ncons = list->GetEntriesFast();
745 for (Int_t i=0; i<ncons; i++) {
746 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
747 task->CheckNotify(kTRUE);
748 // If task is active, execute it
749 if (task->IsPostEventLoop() && task->IsActive()) {
cd463514 750 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 751 task->ExecuteTask();
752 }
753 }
754 }
c52c2132 755 }
cd463514 756 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 757}
758
759//______________________________________________________________________________
760void AliAnalysisManager::Terminate()
761{
762 // The Terminate() function is the last function to be called during
763 // a query. It always runs on the client, it can be used to present
c52c2132 764 // the results graphically.
cd463514 765 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
57756ec5 766 TDirectory *cdir = gDirectory;
767 gROOT->cd();
327eaf46 768 AliAnalysisTask *task;
a0e2e8b1 769 AliAnalysisDataContainer *output;
c52c2132 770 TIter next(fTasks);
a0e2e8b1 771 TStopwatch timer;
096b5a2e 772 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
327eaf46 773 // Call Terminate() for tasks
096b5a2e 774 Int_t itask = 0;
90a4b3ee 775 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
a0e2e8b1 776 // Save all the canvases produced by the Terminate
777 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
a0e2e8b1 778 task->Terminate();
57756ec5 779 gROOT->cd();
096b5a2e 780 if (getsysInfo)
781 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
782 itask++;
a0e2e8b1 783 if (TObject::TestBit(kSaveCanvases)) {
226abfec 784 if (!gROOT->IsBatch()) {
8e1f0465 785 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
226abfec 786 timer.Start();
787 while (timer.CpuTime()<5) {
788 timer.Continue();
789 gSystem->ProcessEvents();
790 }
791 }
792 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
793 if (iend==0) continue;
a0e2e8b1 794 TCanvas *canvas;
226abfec 795 for (Int_t ipict=0; ipict<iend; ipict++) {
796 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
a0e2e8b1 797 if (!canvas) continue;
798 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
226abfec 799 }
800 gROOT->GetListOfCanvases()->Delete();
a0e2e8b1 801 }
802 }
8c9485b2 803 //
aa399a26 804 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
805 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
806 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
57756ec5 807 gROOT->cd();
6cd44ee0 808 TObjArray *allOutputs = new TObjArray();
809 Int_t icont;
810 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
811 if (!IsSkipTerminate())
812 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
813 TIter next1(allOutputs);
f2087b52 814 TString handlerFile = "";
815 if (fOutputEventHandler) {
816 handlerFile = fOutputEventHandler->GetOutputFileName();
817 }
e16a394c 818 icont = 0;
8c0ab8e8 819 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 820 // Special outputs or grid files have the files already closed and written.
e16a394c 821 icont++;
822 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
90a4b3ee 823 if (fMode == kProofAnalysis) {
824 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
825 }
8c0ab8e8 826 const char *filename = output->GetFileName();
61505f8b 827 TString openoption = "RECREATE";
aa399a26 828 if (!(strcmp(filename, "default"))) continue;
8d7d3b59 829 if (!strlen(filename)) continue;
1be433fc 830 if (!output->GetData()) continue;
8d7d3b59 831 TDirectory *opwd = gDirectory;
84fcd93f 832 TFile *file = output->GetFile();
833 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
f2087b52 834 if (!file) {
61505f8b 835 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
836 if (!gSystem->AccessPathName(filename)) openoption = "UPDATE";
cd463514 837 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
61505f8b 838 file = new TFile(filename, openoption);
6cd44ee0 839 } else {
cd463514 840 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
ff07ec61 841 openoption = file->GetOption();
842 if (openoption == "READ") {
cd463514 843 if (fDebug>1) printf("...reopening in UPDATE mode\n");
ff07ec61 844 file->ReOpen("UPDATE");
845 }
6cd44ee0 846 }
84fcd93f 847 if (file->IsZombie()) {
848 Error("Terminate", "Cannot open output file %s", filename);
849 continue;
850 }
8e6e6fe8 851 output->SetFile(file);
852 file->cd();
84fcd93f 853 // Check for a folder request
854 TString dir = output->GetFolderName();
855 if (!dir.IsNull()) {
856 if (!file->GetDirectory(dir)) file->mkdir(dir);
857 file->cd(dir);
858 }
cd463514 859 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
1be433fc 860 if (output->GetData()->InheritsFrom(TCollection::Class())) {
861 // If data is a collection, we set the name of the collection
862 // as the one of the container and we save as a single key.
863 TCollection *coll = (TCollection*)output->GetData();
864 coll->SetName(output->GetName());
865 coll->Write(output->GetName(), TObject::kSingleKey);
866 } else {
cbc8747a 867 if (output->GetData()->InheritsFrom(TTree::Class())) {
868 TTree *tree = (TTree*)output->GetData();
7a151c06 869 tree->SetDirectory(gDirectory);
cbc8747a 870 tree->AutoSave();
871 } else {
872 output->GetData()->Write();
873 }
1be433fc 874 }
8e6e6fe8 875 if (opwd) opwd->cd();
57756ec5 876 }
877 gROOT->cd();
8e6e6fe8 878 next1.Reset();
879 while ((output=(AliAnalysisDataContainer*)next1())) {
880 // Close all files at output
881 TDirectory *opwd = gDirectory;
f5e61abd 882 if (output->GetFile()) {
f3c07fbd 883 // Clear file list to release object ownership to user.
160e7161 884// output->GetFile()->Clear();
f5e61abd 885 output->GetFile()->Close();
84fcd93f 886 output->SetFile(NULL);
f5e61abd 887 // Copy merged outputs in alien if requested
888 if (fSpecialOutputLocation.Length() &&
889 fSpecialOutputLocation.BeginsWith("alien://")) {
890 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
891 TFile::Cp(output->GetFile()->GetName(),
892 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
893 }
894 }
8d7d3b59 895 if (opwd) opwd->cd();
8c0ab8e8 896 }
6cd44ee0 897 delete allOutputs;
8c0ab8e8 898
8c0ab8e8 899 if (getsysInfo) {
b6db1d18 900 TDirectory *crtdir = gDirectory;
8c0ab8e8 901 TFile f("syswatch.root", "RECREATE");
096b5a2e 902 TH1 *hist;
903 TString cut;
8c0ab8e8 904 if (!f.IsZombie()) {
905 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
096b5a2e 906 tree->SetName("syswatch");
8c0ab8e8 907 tree->SetMarkerStyle(kCircle);
908 tree->SetMarkerColor(kBlue);
909 tree->SetMarkerSize(0.5);
910 if (!gROOT->IsBatch()) {
911 tree->SetAlias("event", "id0");
096b5a2e 912 tree->SetAlias("task", "id1");
913 tree->SetAlias("stage", "id2");
914 // Already defined aliases
915 // tree->SetAlias("deltaT","stampSec-stampOldSec");
916 // tree->SetAlias("T","stampSec-first");
917 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
918 // tree->SetAlias("VM","pI.fMemVirtual");
919 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
920 Int_t npads = 1 /*COO plot for all tasks*/ +
921 fTopTasks->GetEntries() /*Exec plot per task*/ +
922 1 /*Terminate plot for all tasks*/ +
923 1; /*vm plot*/
924
925 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
926 if (npads<iopt*(iopt+1))
927 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
928 else
929 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
930 Int_t ipad = 1;
931 // draw the plot of deltaVM for Exec for each task
779e9992 932 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
096b5a2e 933 task = (AliAnalysisTask*)fTopTasks->At(itask);
934 canvas->cd(ipad++);
935 cut = Form("task==%d && stage==1", itask);
936 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
937 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
938 if (hist) {
939 hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
940 hist->GetYaxis()->SetTitle("deltaVM [kB]");
941 }
942 }
943 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
944 canvas->cd(ipad++);
945 tree->SetMarkerStyle(kFullTriangleUp);
946 tree->SetMarkerColor(kRed);
947 tree->SetMarkerSize(0.8);
948 cut = "task>=0 && task<1000 && stage==0";
949 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
950 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
951 if (hist) {
952 hist->SetTitle("Memory in CreateOutputObjects()");
953 hist->GetYaxis()->SetTitle("deltaVM [kB]");
954 hist->GetXaxis()->SetTitle("task");
955 }
956 // draw the plot of deltaVM for Terminate for all tasks
957 canvas->cd(ipad++);
958 tree->SetMarkerStyle(kOpenSquare);
959 tree->SetMarkerColor(kMagenta);
960 cut = "task>=0 && task<1000 && stage==2";
961 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
962 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
963 if (hist) {
964 hist->SetTitle("Memory in Terminate()");
965 hist->GetYaxis()->SetTitle("deltaVM [kB]");
966 hist->GetXaxis()->SetTitle("task");
967 }
968 // Full VM profile
969 canvas->cd(ipad++);
970 tree->SetMarkerStyle(kFullCircle);
971 tree->SetMarkerColor(kGreen);
972 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
973 tree->Draw("VM:event",cut,"", 1234567890, 0);
974 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
975 if (hist) {
976 hist->SetTitle("Virtual memory");
977 hist->GetYaxis()->SetTitle("VM [kB]");
978 }
979 canvas->Modified();
8c0ab8e8 980 }
096b5a2e 981 tree->SetMarkerStyle(kCircle);
982 tree->SetMarkerColor(kBlue);
983 tree->SetMarkerSize(0.5);
8c0ab8e8 984 tree->Write();
985 f.Close();
986 delete tree;
987 }
b6db1d18 988 if (crtdir) crtdir->cd();
923e2ca5 989 }
990 // Validate the output files
991 if (ValidateOutputFiles()) {
992 ofstream out;
993 out.open("outputs_valid", ios::out);
994 out.close();
57756ec5 995 }
996 cdir->cd();
cd463514 997 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 998}
096b5a2e 999//______________________________________________________________________________
1000void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1001{
1002// Profiles the task having the itop index in the list of top (first level) tasks.
1003 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1004 if (!task) {
1005 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1006 return;
1007 }
1008 ProfileTask(task->GetName(), option);
1009}
1010
1011//______________________________________________________________________________
1012void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1013{
1014// Profile a managed task after the execution of the analysis in case NSysInfo
1015// was used.
1016 if (gSystem->AccessPathName("syswatch.root")) {
1017 Error("ProfileTask", "No file syswatch.root found in the current directory");
1018 return;
1019 }
1020 if (gROOT->IsBatch()) return;
1021 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1022 if (!task) {
1023 Error("ProfileTask", "No top task named %s known by the manager.", name);
1024 return;
1025 }
1026 Int_t itop = fTopTasks->IndexOf(task);
1027 Int_t itask = fTasks->IndexOf(task);
1028 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1029 TDirectory *cdir = gDirectory;
1030 TFile f("syswatch.root");
1031 TTree *tree = (TTree*)f.Get("syswatch");
1032 if (!tree) {
1033 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1034 return;
1035 }
cd463514 1036 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
096b5a2e 1037 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1038 canvas->Divide(2, 2, 0.01, 0.01);
1039 Int_t ipad = 1;
1040 TString cut;
1041 TH1 *hist;
1042 // VM profile for COO and Terminate methods
1043 canvas->cd(ipad++);
1044 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1045 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1046 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1047 if (hist) {
1048 hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1049 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1050 hist->GetXaxis()->SetTitle("method");
1051 }
1052 // CPU profile per event
1053 canvas->cd(ipad++);
1054 cut = Form("task==%d && stage==1",itop);
1055 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1056 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1057 if (hist) {
1058 hist->SetTitle("Execution time per event");
1059 hist->GetYaxis()->SetTitle("CPU/event [s]");
1060 }
1061 // VM profile for Exec
1062 canvas->cd(ipad++);
1063 cut = Form("task==%d && stage==1",itop);
1064 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1065 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1066 if (hist) {
1067 hist->SetTitle("Alocated VM[kB] per event");
1068 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1069 }
1070 canvas->Modified();
1071 delete tree;
1072 f.Close();
1073 if (cdir) cdir->cd();
1074}
d3106602 1075
1076//______________________________________________________________________________
1077void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1078{
1079// Adds a user task to the global list of tasks.
8d7d3b59 1080 if (fTasks->FindObject(task)) {
1081 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1082 return;
1083 }
d3106602 1084 task->SetActive(kFALSE);
1085 fTasks->Add(task);
1086}
1087
1088//______________________________________________________________________________
1089AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1090{
1091// Retreive task by name.
1092 if (!fTasks) return NULL;
1093 return (AliAnalysisTask*)fTasks->FindObject(name);
1094}
1095
1096//______________________________________________________________________________
1097AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 1098 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 1099{
1100// Create a data container of a certain type. Types can be:
84fcd93f 1101// kExchangeContainer = 0, used to exchange data between tasks
d3106602 1102// kInputContainer = 1, used to store input data
84fcd93f 1103// kOutputContainer = 2, used for writing result to a file
1104// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1105// the output object to a folder inside the output file
b1310ef5 1106 if (fContainers->FindObject(name)) {
923e2ca5 1107 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 1108 return NULL;
1109 }
d3106602 1110 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1111 fContainers->Add(cont);
1112 switch (type) {
1113 case kInputContainer:
1114 fInputs->Add(cont);
1115 break;
1116 case kOutputContainer:
1117 fOutputs->Add(cont);
8c0ab8e8 1118 if (filename && strlen(filename)) {
1119 cont->SetFileName(filename);
6cd44ee0 1120 cont->SetDataOwned(kFALSE); // data owned by the file
1121 }
1122 break;
1123 case kParamContainer:
1124 fParamCont->Add(cont);
1125 if (filename && strlen(filename)) {
1126 cont->SetFileName(filename);
8c0ab8e8 1127 cont->SetDataOwned(kFALSE); // data owned by the file
1128 }
d3106602 1129 break;
c52c2132 1130 case kExchangeContainer:
d3106602 1131 break;
1132 }
1133 return cont;
1134}
1135
1136//______________________________________________________________________________
1137Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1138 AliAnalysisDataContainer *cont)
1139{
1140// Connect input of an existing task to a data container.
60a04972 1141 if (!task) {
1142 Error("ConnectInput", "Task pointer is NULL");
1143 return kFALSE;
1144 }
d3106602 1145 if (!fTasks->FindObject(task)) {
1146 AddTask(task);
8d7d3b59 1147 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 1148 }
1149 Bool_t connected = task->ConnectInput(islot, cont);
1150 return connected;
1151}
1152
1153//______________________________________________________________________________
1154Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1155 AliAnalysisDataContainer *cont)
1156{
1157// Connect output of an existing task to a data container.
60a04972 1158 if (!task) {
1159 Error("ConnectOutput", "Task pointer is NULL");
1160 return kFALSE;
1161 }
d3106602 1162 if (!fTasks->FindObject(task)) {
1163 AddTask(task);
c52c2132 1164 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 1165 }
1166 Bool_t connected = task->ConnectOutput(islot, cont);
1167 return connected;
1168}
1169
1170//______________________________________________________________________________
1171void AliAnalysisManager::CleanContainers()
1172{
1173// Clean data from all containers that have already finished all client tasks.
1174 TIter next(fContainers);
1175 AliAnalysisDataContainer *cont;
1176 while ((cont=(AliAnalysisDataContainer *)next())) {
1177 if (cont->IsOwnedData() &&
1178 cont->IsDataReady() &&
1179 cont->ClientsExecuted()) cont->DeleteData();
1180 }
1181}
1182
1183//______________________________________________________________________________
1184Bool_t AliAnalysisManager::InitAnalysis()
1185{
1186// Initialization of analysis chain of tasks. Should be called after all tasks
1187// and data containers are properly connected
923e2ca5 1188 // Reset flag and remove valid_outputs file if exists
d3106602 1189 fInitOK = kFALSE;
923e2ca5 1190 if (!gSystem->AccessPathName("outputs_valid"))
1191 gSystem->Unlink("outputs_valid");
d3106602 1192 // Check for top tasks (depending only on input data containers)
1193 if (!fTasks->First()) {
c52c2132 1194 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 1195 return kFALSE;
1196 }
1197 TIter next(fTasks);
1198 AliAnalysisTask *task;
1199 AliAnalysisDataContainer *cont;
1200 Int_t ntop = 0;
1201 Int_t nzombies = 0;
327eaf46 1202 Bool_t iszombie = kFALSE;
1203 Bool_t istop = kTRUE;
d3106602 1204 Int_t i;
1205 while ((task=(AliAnalysisTask*)next())) {
327eaf46 1206 istop = kTRUE;
1207 iszombie = kFALSE;
d3106602 1208 Int_t ninputs = task->GetNinputs();
d3106602 1209 for (i=0; i<ninputs; i++) {
1210 cont = task->GetInputSlot(i)->GetContainer();
1211 if (!cont) {
327eaf46 1212 if (!iszombie) {
d3106602 1213 task->SetZombie();
1214 fZombies->Add(task);
1215 nzombies++;
327eaf46 1216 iszombie = kTRUE;
d3106602 1217 }
c52c2132 1218 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1219 i, task->GetName());
d3106602 1220 }
327eaf46 1221 if (iszombie) continue;
d3106602 1222 // Check if cont is an input container
327eaf46 1223 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 1224 // Connect to parent task
1225 }
327eaf46 1226 if (istop) {
d3106602 1227 ntop++;
1228 fTopTasks->Add(task);
1229 }
1230 }
1231 if (!ntop) {
c52c2132 1232 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 1233 return kFALSE;
1234 }
1235 // Check now if there are orphan tasks
1236 for (i=0; i<ntop; i++) {
1237 task = (AliAnalysisTask*)fTopTasks->At(i);
1238 task->SetUsed();
1239 }
1240 Int_t norphans = 0;
1241 next.Reset();
1242 while ((task=(AliAnalysisTask*)next())) {
1243 if (!task->IsUsed()) {
1244 norphans++;
c52c2132 1245 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 1246 }
1247 }
1248 // Check the task hierarchy (no parent task should depend on data provided
1249 // by a daughter task)
1250 for (i=0; i<ntop; i++) {
1251 task = (AliAnalysisTask*)fTopTasks->At(i);
1252 if (task->CheckCircularDeps()) {
c52c2132 1253 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 1254 PrintStatus("dep");
1255 return kFALSE;
1256 }
1257 }
b1310ef5 1258 // Check that all containers feeding post-event loop tasks are in the outputs list
1259 TIter nextcont(fContainers); // loop over all containers
1260 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1261 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1262 if (cont->HasConsumers()) {
1263 // Check if one of the consumers is post event loop
1264 TIter nextconsumer(cont->GetConsumers());
1265 while ((task=(AliAnalysisTask*)nextconsumer())) {
1266 if (task->IsPostEventLoop()) {
1267 fOutputs->Add(cont);
1268 break;
1269 }
1270 }
1271 }
1272 }
1273 }
8d7d3b59 1274 // Check if all special output containers have a file name provided
1275 TIter nextout(fOutputs);
1276 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1277 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1278 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1279 return kFALSE;
1280 }
1281 }
327eaf46 1282 fInitOK = kTRUE;
d3106602 1283 return kTRUE;
1284}
1285
1286//______________________________________________________________________________
1287void AliAnalysisManager::PrintStatus(Option_t *option) const
1288{
1289// Print task hierarchy.
8c0ab8e8 1290 if (!fInitOK) {
1291 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1292 return;
1293 }
1294 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1295 if (getsysInfo)
1296 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1297 TIter next(fTopTasks);
1298 AliAnalysisTask *task;
1299 while ((task=(AliAnalysisTask*)next()))
1300 task->PrintTask(option);
1301}
1302
1303//______________________________________________________________________________
1304void AliAnalysisManager::ResetAnalysis()
1305{
1306// Reset all execution flags and clean containers.
1307 CleanContainers();
1308}
1309
1310//______________________________________________________________________________
61505f8b 1311Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1312{
aee5ee44 1313// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1314// MIX. Process nentries starting from firstentry
bf574918 1315 Long64_t retv = 0;
57756ec5 1316 // Backup current directory and make sure gDirectory points to gROOT
1317 TDirectory *cdir = gDirectory;
1318 gROOT->cd();
c52c2132 1319 if (!fInitOK) {
1320 Error("StartAnalysis","Analysis manager was not initialized !");
57756ec5 1321 cdir->cd();
1f87e9fb 1322 return -1;
c52c2132 1323 }
cd463514 1324 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
8e1f0465 1325 fIsRemote = kFALSE;
c52c2132 1326 TString anaType = type;
1327 anaType.ToLower();
1328 fMode = kLocalAnalysis;
c57f56b7 1329 Bool_t runlocalinit = kTRUE;
90a4b3ee 1330 if (anaType.Contains("file")) {
1331 runlocalinit = kFALSE;
8e1f0465 1332 fIsRemote = kTRUE;
90a4b3ee 1333 }
4ab472d4 1334 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1335 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1336 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1337
c52c2132 1338 if (fMode == kGridAnalysis) {
8e1f0465 1339 fIsRemote = kTRUE;
f866cba5 1340 if (!anaType.Contains("terminate")) {
1341 if (!fGridHandler) {
1342 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1343 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
57756ec5 1344 cdir->cd();
f866cba5 1345 return -1;
1346 }
1347 // Write analysis manager in the analysis file
1348 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1349 // run local task configuration
1350 TIter nextTask(fTasks);
1351 AliAnalysisTask *task;
1352 while ((task=(AliAnalysisTask*)nextTask())) {
1353 task->LocalInit();
57756ec5 1354 gROOT->cd();
f866cba5 1355 }
1356 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1357 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
57756ec5 1358 cdir->cd();
f866cba5 1359 return -1;
1360 }
c57f56b7 1361
f866cba5 1362 // Terminate grid analysis
57756ec5 1363 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1364 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
f866cba5 1365 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1366 if (!fGridHandler->MergeOutputs()) {
1367 // Return if outputs could not be merged or if it alien handler
1368 // was configured for offline mode or local testing.
57756ec5 1369 cdir->cd();
f866cba5 1370 return 0;
1371 }
1372 }
1373 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
c57f56b7 1374 ImportWrappers(NULL);
1375 Terminate();
57756ec5 1376 cdir->cd();
1f87e9fb 1377 return 0;
981f2614 1378 }
d86ed856 1379 char line[256];
efd53803 1380 SetEventLoop(kFALSE);
8d7d3b59 1381 // Enable event loop mode if a tree was provided
aee5ee44 1382 if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1383
8c0ab8e8 1384 TChain *chain = 0;
1385 TString ttype = "TTree";
4ab472d4 1386 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1387 chain = (TChain*)tree;
6b742510 1388 if (!chain || !chain->GetListOfFiles()->First()) {
1389 Error("StartAnalysis", "Cannot process null or empty chain...");
57756ec5 1390 cdir->cd();
1f87e9fb 1391 return -1;
6b742510 1392 }
8c0ab8e8 1393 ttype = "TChain";
1394 }
9b33830a 1395
096b5a2e 1396 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1397 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
aee5ee44 1398 // Initialize locally all tasks (happens for all modes)
9b33830a 1399 TIter next(fTasks);
1400 AliAnalysisTask *task;
c57f56b7 1401 if (runlocalinit) {
1402 while ((task=(AliAnalysisTask*)next())) {
1403 task->LocalInit();
57756ec5 1404 gROOT->cd();
c57f56b7 1405 }
096b5a2e 1406 if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
c57f56b7 1407 }
efd53803 1408
c52c2132 1409 switch (fMode) {
1410 case kLocalAnalysis:
1411 if (!tree) {
03a5cc9f 1412 TIter nextT(fTasks);
981f2614 1413 // Call CreateOutputObjects for all tasks
096b5a2e 1414 Int_t itask = 0;
979e448a 1415 Bool_t dirStatus = TH1::AddDirectoryStatus();
03a5cc9f 1416 while ((task=(AliAnalysisTask*)nextT())) {
979e448a 1417 TH1::AddDirectory(kFALSE);
c5a87c56 1418 task->CreateOutputObjects();
096b5a2e 1419 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
57756ec5 1420 gROOT->cd();
096b5a2e 1421 itask++;
c5a87c56 1422 }
979e448a 1423 TH1::AddDirectory(dirStatus);
06a59280 1424 if (IsExternalLoop()) {
1425 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1426 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1f87e9fb 1427 return 0;
57756ec5 1428 }
c52c2132 1429 ExecAnalysis();
981f2614 1430 Terminate();
1f87e9fb 1431 return 0;
c52c2132 1432 }
1433 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1434 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
aee5ee44 1435 fSelector = new AliAnalysisSelector(this);
bf574918 1436 retv = tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1437 break;
1438 case kProofAnalysis:
8e1f0465 1439 fIsRemote = kTRUE;
c52c2132 1440 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1441 Error("StartAnalysis", "No PROOF!!! Exiting.");
57756ec5 1442 cdir->cd();
1f87e9fb 1443 return -1;
c52c2132 1444 }
1445 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1446 gROOT->ProcessLine(line);
1447 if (chain) {
1448 chain->SetProof();
1449 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
bf574918 1450 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1451 } else {
61505f8b 1452 Error("StartAnalysis", "No chain!!! Exiting.");
57756ec5 1453 cdir->cd();
1f87e9fb 1454 return -1;
c52c2132 1455 }
1456 break;
1457 case kGridAnalysis:
1458 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
aee5ee44 1459 break;
1460 case kMixingAnalysis:
1461 // Run event mixing analysis
1462 if (!fEventPool) {
1463 Error("StartAnalysis", "Cannot run event mixing without event pool");
57756ec5 1464 cdir->cd();
1f87e9fb 1465 return -1;
aee5ee44 1466 }
1467 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1468 fSelector = new AliAnalysisSelector(this);
aee5ee44 1469 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1470 next.Reset();
aee5ee44 1471 // Call NotifyBinChange for all tasks
1472 while ((task=(AliAnalysisTask*)next()))
1473 if (!task->IsPostEventLoop()) task->NotifyBinChange();
bf574918 1474 retv = chain->Process(fSelector);
1475 if (retv < 0) {
1476 Error("StartAnalysis", "Mixing analysis failed");
57756ec5 1477 cdir->cd();
bf574918 1478 return retv;
1479 }
aee5ee44 1480 }
1481 PackOutput(fSelector->GetOutputList());
1482 Terminate();
1f87e9fb 1483 }
57756ec5 1484 cdir->cd();
bf574918 1485 return retv;
c52c2132 1486}
1487
1488//______________________________________________________________________________
1f87e9fb 1489Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
d86ed856 1490{
1491// Start analysis for this manager on a given dataset. Analysis task can be:
1492// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1493 if (!fInitOK) {
1494 Error("StartAnalysis","Analysis manager was not initialized !");
1f87e9fb 1495 return -1;
d86ed856 1496 }
8e1f0465 1497 fIsRemote = kTRUE;
cd463514 1498 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
d86ed856 1499 TString anaType = type;
1500 anaType.ToLower();
1501 if (!anaType.Contains("proof")) {
d140f7fb 1502 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1f87e9fb 1503 return -1;
d86ed856 1504 }
1505 fMode = kProofAnalysis;
1506 char line[256];
1507 SetEventLoop(kTRUE);
1508 // Set the dataset flag
1509 TObject::SetBit(kUseDataSet);
1510 fTree = 0;
1511
1512 // Initialize locally all tasks
1513 TIter next(fTasks);
1514 AliAnalysisTask *task;
1515 while ((task=(AliAnalysisTask*)next())) {
1516 task->LocalInit();
1517 }
1518
1519 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
61505f8b 1520 Error("StartAnalysis", "No PROOF!!! Exiting.");
1f87e9fb 1521 return -1;
d86ed856 1522 }
1523 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1524 gROOT->ProcessLine(line);
bc649bfe 1525// sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1526// if (!gROOT->ProcessLine(line)) {
1527// Error("StartAnalysis", "Dataset %s not found", dataset);
1528// return -1;
1529// }
d86ed856 1530 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1531 dataset, nentries, firstentry);
1532 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
bf574918 1533 Long_t retv = (Long_t)gROOT->ProcessLine(line);
1534 return retv;
d86ed856 1535}
1536
1537//______________________________________________________________________________
84fcd93f 1538TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1539{
1540// Opens according the option the file specified by cont->GetFileName() and changes
1541// current directory to cont->GetFolderName(). If the file was already opened, it
1542// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1543// be optionally ignored.
1544 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1545 TString filename = cont->GetFileName();
1546 TFile *f = NULL;
1547 if (filename.IsNull()) {
1548 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1549 return NULL;
1550 }
1551 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1552 && !ignoreProof)
1553 f = mgr->OpenProofFile(cont,option);
1554 else {
1555 // Check first if the file is already opened
0f1b50f3 1556 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
84fcd93f 1557 if (f) {
1558 // Check if option "UPDATE" was preserved
1559 TString opt(option);
1560 opt.ToUpper();
1561 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1562 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1563 } else {
0f1b50f3 1564 f = TFile::Open(filename, option);
84fcd93f 1565 }
1566 }
1567 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1568 cont->SetFile(f);
1569 // Cd to file
1570 f->cd();
1571 // Check for a folder request
1572 TString dir = cont->GetFolderName();
1573 if (!dir.IsNull()) {
1574 if (!f->GetDirectory(dir)) f->mkdir(dir);
1575 f->cd(dir);
1576 }
1577 return f;
1578 }
1579 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1580 cont->SetFile(NULL);
1581 return NULL;
1582}
1583
1584//______________________________________________________________________________
1585TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option)
8d7d3b59 1586{
1587// Opens a special output file used in PROOF.
84fcd93f 1588 TString line;
1589 TString filename = cont->GetFileName();
23c9468b 1590 if (cont == fCommonOutput) {
1591 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
61505f8b 1592 else Fatal("OpenProofFile","No output container. Exiting.");
23c9468b 1593 }
84fcd93f 1594 TFile *f = NULL;
1595 if (fMode!=kProofAnalysis || !fSelector) {
1596 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1597 return NULL;
1598 }
1599 if (fSpecialOutputLocation.Length()) {
1600 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1601 if (f) {
1602 // Check if option "UPDATE" was preserved
1603 TString opt(option);
1604 opt.ToUpper();
23c9468b 1605 if ((opt=="UPDATE") && (opt!=f->GetOption()))
e85311b4 1606 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
84fcd93f 1607 } else {
1608 f = new TFile(filename, option);
1609 }
1610 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1611 cont->SetFile(f);
1612 // Cd to file
1613 f->cd();
1614 // Check for a folder request
1615 TString dir = cont->GetFolderName();
1616 if (dir.Length()) {
1617 if (!f->GetDirectory(dir)) f->mkdir(dir);
1618 f->cd(dir);
1619 }
f5e61abd 1620 return f;
84fcd93f 1621 }
1622 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1623 cont->SetFile(NULL);
1624 return NULL;
1625 }
1626 // Check if there is already a proof output file in the output list
1627 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1628 if (pof) {
1629 // Get the actual file
1630 line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1631 filename = (const char*)gROOT->ProcessLine(line);
90a4b3ee 1632 if (fDebug>1) {
1633 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1634 }
84fcd93f 1635 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1636 if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1637 // Check if option "UPDATE" was preserved
1638 TString opt(option);
1639 opt.ToUpper();
1640 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1641 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1642 } else {
90a4b3ee 1643 if (cont->IsRegisterDataset()) {
61505f8b 1644 TString dsetName = filename;
1645 dsetName.ReplaceAll(".root", cont->GetTitle());
1646 dsetName.ReplaceAll(":","_");
1647 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1648 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
90a4b3ee 1649 } else {
1650 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1651 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1652 }
84fcd93f 1653 if (fDebug > 1) printf("=== %s\n", line.Data());
1654 gROOT->ProcessLine(line);
1655 line = Form("pf->OpenFile(\"%s\");", option);
1656 gROOT->ProcessLine(line);
1657 f = gFile;
1658 if (fDebug > 1) {
8d7d3b59 1659 gROOT->ProcessLine("pf->Print()");
84fcd93f 1660 printf(" == proof file name: %s", f->GetName());
1661 }
1662 // Add to proof output list
1663 line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
90a4b3ee 1664 if (fDebug > 1) printf("=== %s\n", line.Data());
84fcd93f 1665 gROOT->ProcessLine(line);
1666 }
1667 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1668 cont->SetFile(f);
1669 // Cd to file
1670 f->cd();
1671 // Check for a folder request
1672 TString dir = cont->GetFolderName();
1673 if (!dir.IsNull()) {
1674 if (!f->GetDirectory(dir)) f->mkdir(dir);
1675 f->cd(dir);
1676 }
1677 return f;
1678 }
1679 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1680 cont->SetFile(NULL);
1681 return NULL;
8d7d3b59 1682}
1683
1684//______________________________________________________________________________
d3106602 1685void AliAnalysisManager::ExecAnalysis(Option_t *option)
1686{
1687// Execute analysis.
8c0ab8e8 1688 static Long64_t ncalls = 0;
cd463514 1689 static Long64_t nentries = 0;
1f04b637 1690 static TTree *lastTree = 0;
cd463514 1691 static TStopwatch *timer = new TStopwatch();
096b5a2e 1692 if (fDebug > 0) printf("MGR: Processing event #%lld\n", ncalls);
cd463514 1693 else {
1f04b637 1694 if (fTree && (fTree != lastTree)) {
1695 nentries += fTree->GetEntries();
1696 lastTree = fTree;
1697 }
cd463514 1698 if (!ncalls) timer->Start();
ff0d33e8 1699 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", ncalls, nentries, timer, kFALSE);
cd463514 1700 }
57756ec5 1701 gROOT->cd();
cd463514 1702 TDirectory *cdir = gDirectory;
8c0ab8e8 1703 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
096b5a2e 1704 if (getsysInfo && ((ncalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)ncalls);
8c0ab8e8 1705 ncalls++;
327eaf46 1706 if (!fInitOK) {
57756ec5 1707 Error("ExecAnalysis", "Analysis manager was not initialized !");
1708 cdir->cd();
327eaf46 1709 return;
57756ec5 1710 }
d3106602 1711 AliAnalysisTask *task;
327eaf46 1712 // Check if the top tree is active.
1713 if (fTree) {
a8bc7397 1714 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1715 AliSysInfo::AddStamp("Handlers_BeginEventGroup",(Int_t)ncalls, 1002, 0);
327eaf46 1716 TIter next(fTasks);
1717 // De-activate all tasks
1718 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1719 AliAnalysisDataContainer *cont = fCommonInput;
1720 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1721 if (!cont) {
c52c2132 1722 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
57756ec5 1723 cdir->cd();
327eaf46 1724 return;
1725 }
1726 cont->SetData(fTree); // This will notify all consumers
57756ec5 1727 Long64_t entry = fTree->GetTree()->GetReadEntry();
6bb2b24f 1728//
c3701689 1729// Call BeginEvent() for optional input/output and MC services
ed97dc98 1730 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1731 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1732 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
57756ec5 1733 gROOT->cd();
096b5a2e 1734 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1735 AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
6bb2b24f 1736//
1737// Execute the tasks
276941c8 1738// TIter next1(cont->GetConsumers());
1739 TIter next1(fTopTasks);
096b5a2e 1740 Int_t itask = 0;
327eaf46 1741 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1742 if (fDebug >1) {
1743 cout << " Executing task " << task->GetName() << endl;
096b5a2e 1744 }
327eaf46 1745 task->ExecuteTask(option);
57756ec5 1746 gROOT->cd();
096b5a2e 1747 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1748 AliSysInfo::AddStamp(task->ClassName(),(Int_t)ncalls, itask, 1);
1749 itask++;
327eaf46 1750 }
6bb2b24f 1751//
1752// Call FinishEvent() for optional output and MC services
6073f8c9 1753 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1754 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1755 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1756 // Gather system information if requested
1757 if (getsysInfo && ((ncalls%fNSysInfo)==0))
a8bc7397 1758 AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1001, 1);
57756ec5 1759 cdir->cd();
327eaf46 1760 return;
1761 }
1762 // The event loop is not controlled by TSelector
6bb2b24f 1763//
c3701689 1764// Call BeginEvent() for optional input/output and MC services
ed97dc98 1765 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1766 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1767 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
57756ec5 1768 gROOT->cd();
096b5a2e 1769 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1770 AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0);
327eaf46 1771 TIter next2(fTopTasks);
1772 while ((task=(AliAnalysisTask*)next2())) {
1773 task->SetActive(kTRUE);
c52c2132 1774 if (fDebug > 1) {
1775 cout << " Executing task " << task->GetName() << endl;
1776 }
d3106602 1777 task->ExecuteTask(option);
57756ec5 1778 gROOT->cd();
327eaf46 1779 }
6bb2b24f 1780//
1781// Call FinishEvent() for optional output and MC services
6073f8c9 1782 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1783 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1784 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
096b5a2e 1785 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1786 AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1);
57756ec5 1787 cdir->cd();
d3106602 1788}
1789
1790//______________________________________________________________________________
61505f8b 1791void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
60a04972 1792{
1793// Set the input event handler and create a container for it.
1794 fInputEventHandler = handler;
d958c3ea 1795 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ff92d2b1 1796// Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 1797}
1798
1799//______________________________________________________________________________
61505f8b 1800void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
60a04972 1801{
1802// Set the input event handler and create a container for it.
1803 fOutputEventHandler = handler;
d958c3ea 1804 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 1805 fCommonOutput->SetSpecialOutput();
ff92d2b1 1806// Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 1807}
c07b9ce2 1808
1809//______________________________________________________________________________
1810void AliAnalysisManager::RegisterExtraFile(const char *fname)
1811{
1812// This method is used externally to register output files which are not
1813// connected to any output container, so that the manager can properly register,
1814// retrieve or merge them when running in distributed mode. The file names are
1815// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
5b9b4998 1816 if (fExtraFiles.Contains(fname)) return;
c07b9ce2 1817 if (fExtraFiles.Length()) fExtraFiles += " ";
1818 fExtraFiles += fname;
1819}
1820
1821//______________________________________________________________________________
61505f8b 1822Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
c07b9ce2 1823{
1824// Copy a file from the location specified ina the wrapper with the same name from the source list.
61505f8b 1825 char fullPath[512];
1826 char chUrl[512];
c07b9ce2 1827 TObject *pof = source->FindObject(filename);
1828 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1829 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1830 return kFALSE;
1831 }
343691a5 1832 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", (ULong_t)fullPath, (ULong_t)pof));
1833 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", (ULong_t)chUrl));
61505f8b 1834 TString clientUrl(chUrl);
1835 TString fullPath_str(fullPath);
c07b9ce2 1836 if (clientUrl.Contains("localhost")){
61505f8b 1837 TObjArray* array = fullPath_str.Tokenize ( "//" );
c07b9ce2 1838 TObjString *strobj = ( TObjString *)array->At(1);
1839 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1840 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
61505f8b 1841 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1842 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1843 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
c07b9ce2 1844 delete arrayPort;
1845 delete array;
1846 }
1847 if (fDebug > 1)
61505f8b 1848 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", fullPath_str.Data());
1849 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
c07b9ce2 1850 if (!gotit)
1851 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1852 return gotit;
1853}
d29168d6 1854
1855//______________________________________________________________________________
1856void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1857{
1858// Fill analysis type in the provided string.
1859 switch (fMode) {
1860 case kLocalAnalysis:
1861 type = "local";
1862 return;
1863 case kProofAnalysis:
1864 type = "proof";
1865 return;
1866 case kGridAnalysis:
1867 type = "grid";
1868 return;
1869 case kMixingAnalysis:
1870 type = "mix";
1871 }
1872}
923e2ca5 1873
1874//______________________________________________________________________________
1875Bool_t AliAnalysisManager::ValidateOutputFiles() const
1876{
1877// Validate all output files.
1878 TIter next(fOutputs);
1879 AliAnalysisDataContainer *output;
1880 TDirectory *cdir = gDirectory;
84fcd93f 1881 TString openedFiles;
923e2ca5 1882 while ((output=(AliAnalysisDataContainer*)next())) {
90a4b3ee 1883 if (output->IsRegisterDataset()) continue;
923e2ca5 1884 TString filename = output->GetFileName();
1885 if (filename == "default") {
1886 if (!fOutputEventHandler) continue;
1887 filename = fOutputEventHandler->GetOutputFileName();
b3685485 1888 // Main AOD may not be there
1889 if (gSystem->AccessPathName(filename)) continue;
923e2ca5 1890 }
1891 // Check if the file is closed
84fcd93f 1892 if (openedFiles.Contains(filename)) continue;;
923e2ca5 1893 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1894 if (file) {
1895 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
f3c07fbd 1896 // Clear file list to release object ownership to user.
160e7161 1897// file->Clear();
923e2ca5 1898 file->Close();
1899 }
1900 file = TFile::Open(filename);
1901 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1902 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1903 cdir->cd();
1904 return kFALSE;
1905 }
1906 file->Close();
84fcd93f 1907 openedFiles += filename;
1908 openedFiles += " ";
923e2ca5 1909 }
1910 cdir->cd();
1911 return kTRUE;
1912}
cd11251e 1913
1914//______________________________________________________________________________
61505f8b 1915void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
cd11251e 1916{
1917// Implements a nice text mode progress bar.
1918 static Long64_t icount = 0;
1919 static TString oname;
1920 static TString nname;
1921 static Long64_t ocurrent = 0;
1922 static Long64_t osize = 0;
1923 static Int_t oseconds = 0;
1924 static TStopwatch *owatch = 0;
1925 static Bool_t oneoftwo = kFALSE;
1926 static Int_t nrefresh = 0;
1927 static Int_t nchecks = 0;
1928 const char symbol[4] = {'=','\\','|','/'};
1929 char progress[11] = " ";
1930 Int_t ichar = icount%4;
1931
1932 if (!refresh) {
1933 nrefresh = 0;
1934 if (!size) return;
1935 owatch = watch;
1936 oname = opname;
1937 ocurrent = TMath::Abs(current);
1938 osize = TMath::Abs(size);
1939 if (ocurrent > osize) ocurrent=osize;
1940 } else {
1941 nrefresh++;
1942 if (!osize) return;
1943 }
1944 icount++;
1945 Double_t time = 0.;
1946 Int_t hours = 0;
1947 Int_t minutes = 0;
1948 Int_t seconds = 0;
1949 if (owatch && !last) {
1950 owatch->Stop();
1951 time = owatch->RealTime();
1952 hours = (Int_t)(time/3600.);
1953 time -= 3600*hours;
1954 minutes = (Int_t)(time/60.);
1955 time -= 60*minutes;
1956 seconds = (Int_t)time;
1957 if (refresh) {
1958 if (oseconds==seconds) {
1959 owatch->Continue();
1960 return;
1961 }
1962 oneoftwo = !oneoftwo;
1963 }
1964 oseconds = seconds;
1965 }
1966 if (refresh && oneoftwo) {
1967 nname = oname;
1968 if (nchecks <= 0) nchecks = nrefresh+1;
1969 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
1970 oname = Form(" == %d%% ==", pctdone);
1971 }
1972 Double_t percent = 100.0*ocurrent/osize;
1973 Int_t nchar = Int_t(percent/10);
1974 if (nchar>10) nchar=10;
1975 Int_t i;
1976 for (i=0; i<nchar; i++) progress[i] = '=';
1977 progress[nchar] = symbol[ichar];
1978 for (i=nchar+1; i<10; i++) progress[i] = ' ';
1979 progress[10] = '\0';
1980 oname += " ";
1981 oname.Remove(20);
1982 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
1983 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
1984 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
1985 if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d \r", percent, hours, minutes, seconds);
1986 else fprintf(stderr, "[%6.2f %%]\r", percent);
1987 if (refresh && oneoftwo) oname = nname;
1988 if (owatch) owatch->Continue();
1989 if (last) {
1990 icount = 0;
1991 owatch = 0;
1992 ocurrent = 0;
1993 osize = 0;
1994 oseconds = 0;
1995 oneoftwo = kFALSE;
1996 nrefresh = 0;
1997 fprintf(stderr, "\n");
1998 }
1999}
012e169c 2000
2001//______________________________________________________________________________
2002void AliAnalysisManager::DoLoadBranch(const char *name)
2003{
2004 // Get tree and load branch if needed.
2005
2006 if (!fTree)
2007 return;
2008
2009 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2010 if (!br) {
2011 br = fTree->GetBranch(name);
2012 if (!br) {
979e448a 2013 Error("DoLoadBranch", "Could not find branch %s",name);
012e169c 2014 return;
2015 }
2016 fTable.Add(br);
2017 }
2018 if (br->GetReadEntry()==GetCurrentEntry())
2019 return;
2020 br->GetEntry(GetCurrentEntry());
2021}