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