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