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