]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ANALYSIS/AliAnalysisManager.cxx
Added two missing includes to allow macro compilation (thanks to Laurent for remarkin...
[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
c52c2132 30#include <TClass.h>
31#include <TFile.h>
dd197a68 32#include <TKey.h>
c52c2132 33#include <TMethodCall.h>
34#include <TChain.h>
35#include <TSystem.h>
36#include <TROOT.h>
8c0ab8e8 37#include <TCanvas.h>
d3106602 38
8d7d3b59 39#include "AliAnalysisSelector.h"
c57f56b7 40#include "AliAnalysisGrid.h"
d3106602 41#include "AliAnalysisTask.h"
42#include "AliAnalysisDataContainer.h"
43#include "AliAnalysisDataSlot.h"
d2f1d9ef 44#include "AliVEventHandler.h"
c2922515 45#include "AliVEventPool.h"
8c0ab8e8 46#include "AliSysInfo.h"
c52c2132 47#include "AliAnalysisManager.h"
d3106602 48
49ClassImp(AliAnalysisManager)
50
c52c2132 51AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
52
c52c2132 53//______________________________________________________________________________
54AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
55 :TNamed(name,title),
56 fTree(NULL),
8c0ab8e8 57 fInputEventHandler(NULL),
58 fOutputEventHandler(NULL),
59 fMCtruthEventHandler(NULL),
c57f56b7 60 fEventPool(NULL),
c52c2132 61 fCurrentEntry(-1),
8c0ab8e8 62 fNSysInfo(0),
c52c2132 63 fMode(kLocalAnalysis),
64 fInitOK(kFALSE),
65 fDebug(0),
26f071d8 66 fSpecialOutputLocation(""),
37a26056 67 fTasks(NULL),
68 fTopTasks(NULL),
c52c2132 69 fZombies(NULL),
70 fContainers(NULL),
71 fInputs(NULL),
8d7d3b59 72 fOutputs(NULL),
60a04972 73 fCommonInput(NULL),
74 fCommonOutput(NULL),
c57f56b7 75 fSelector(NULL),
c07b9ce2 76 fGridHandler(NULL),
77 fExtraFiles("")
d3106602 78{
79// Default constructor.
c52c2132 80 fgAnalysisManager = this;
81 fTasks = new TObjArray();
82 fTopTasks = new TObjArray();
83 fZombies = new TObjArray();
84 fContainers = new TObjArray();
85 fInputs = new TObjArray();
37153431 86 fOutputs = new TObjArray();
b1310ef5 87 SetEventLoop(kTRUE);
d3106602 88}
89
90//______________________________________________________________________________
91AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
c52c2132 92 :TNamed(other),
327eaf46 93 fTree(NULL),
8c0ab8e8 94 fInputEventHandler(NULL),
95 fOutputEventHandler(NULL),
96 fMCtruthEventHandler(NULL),
c2922515 97 fEventPool(NULL),
c52c2132 98 fCurrentEntry(-1),
8c0ab8e8 99 fNSysInfo(0),
c52c2132 100 fMode(other.fMode),
101 fInitOK(other.fInitOK),
102 fDebug(other.fDebug),
26f071d8 103 fSpecialOutputLocation(""),
37a26056 104 fTasks(NULL),
105 fTopTasks(NULL),
c52c2132 106 fZombies(NULL),
107 fContainers(NULL),
108 fInputs(NULL),
8d7d3b59 109 fOutputs(NULL),
60a04972 110 fCommonInput(NULL),
111 fCommonOutput(NULL),
c57f56b7 112 fSelector(NULL),
c07b9ce2 113 fGridHandler(NULL),
114 fExtraFiles()
d3106602 115{
116// Copy constructor.
37a26056 117 fTasks = new TObjArray(*other.fTasks);
118 fTopTasks = new TObjArray(*other.fTopTasks);
119 fZombies = new TObjArray(*other.fZombies);
c52c2132 120 fContainers = new TObjArray(*other.fContainers);
121 fInputs = new TObjArray(*other.fInputs);
122 fOutputs = new TObjArray(*other.fOutputs);
123 fgAnalysisManager = this;
d3106602 124}
125
126//______________________________________________________________________________
127AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
128{
129// Assignment
130 if (&other != this) {
c52c2132 131 TNamed::operator=(other);
54cff064 132 fInputEventHandler = other.fInputEventHandler;
6bb2b24f 133 fOutputEventHandler = other.fOutputEventHandler;
134 fMCtruthEventHandler = other.fMCtruthEventHandler;
c2922515 135 fEventPool = other.fEventPool;
c52c2132 136 fTree = NULL;
137 fCurrentEntry = -1;
8c0ab8e8 138 fNSysInfo = other.fNSysInfo;
c52c2132 139 fMode = other.fMode;
37a26056 140 fInitOK = other.fInitOK;
c52c2132 141 fDebug = other.fDebug;
37a26056 142 fTasks = new TObjArray(*other.fTasks);
143 fTopTasks = new TObjArray(*other.fTopTasks);
144 fZombies = new TObjArray(*other.fZombies);
c52c2132 145 fContainers = new TObjArray(*other.fContainers);
146 fInputs = new TObjArray(*other.fInputs);
147 fOutputs = new TObjArray(*other.fOutputs);
60a04972 148 fCommonInput = NULL;
149 fCommonOutput = NULL;
8d7d3b59 150 fSelector = NULL;
c57f56b7 151 fGridHandler = NULL;
c07b9ce2 152 fExtraFiles = other.fExtraFiles;
c52c2132 153 fgAnalysisManager = this;
d3106602 154 }
155 return *this;
156}
157
158//______________________________________________________________________________
159AliAnalysisManager::~AliAnalysisManager()
160{
161// Destructor.
d3106602 162 if (fTasks) {fTasks->Delete(); delete fTasks;}
163 if (fTopTasks) delete fTopTasks;
164 if (fZombies) delete fZombies;
c52c2132 165 if (fContainers) {fContainers->Delete(); delete fContainers;}
166 if (fInputs) delete fInputs;
167 if (fOutputs) delete fOutputs;
c57f56b7 168 if (fGridHandler) delete fGridHandler;
c52c2132 169 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
d3106602 170}
c52c2132 171
d3106602 172//______________________________________________________________________________
327eaf46 173Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
174{
175// Read one entry of the tree or a whole branch.
923e2ca5 176 if (fDebug > 0) Printf("== AliAnalysisManager::GetEntry(%lld)", entry);
c52c2132 177 fCurrentEntry = entry;
327eaf46 178 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
179}
180
181//______________________________________________________________________________
2d626244 182Bool_t AliAnalysisManager::Init(TTree *tree)
d3106602 183{
184 // The Init() function is called when the selector needs to initialize
185 // a new tree or chain. Typically here the branch addresses of the tree
186 // will be set. It is normaly not necessary to make changes to the
187 // generated code, but the routine can be extended by the user if needed.
188 // Init() will be called many times when running with PROOF.
2d626244 189 Bool_t init = kFALSE;
190 if (!tree) return kFALSE; // Should not happen - protected in selector caller
8d7d3b59 191 if (fDebug > 0) {
923e2ca5 192 Printf("->AliAnalysisManager::Init(%s)", tree->GetName());
c52c2132 193 }
f3d59a0d 194 // Call InitTree of EventHandler
36e82a52 195 if (fOutputEventHandler) {
196 if (fMode == kProofAnalysis) {
2d626244 197 init = fOutputEventHandler->Init(0x0, "proof");
36e82a52 198 } else {
2d626244 199 init = fOutputEventHandler->Init(0x0, "local");
36e82a52 200 }
2d626244 201 if (!init) {
202 Error("Init", "Output event handler failed to initialize");
203 return kFALSE;
204 }
36e82a52 205 }
2d626244 206
fdb458ec 207 if (fInputEventHandler) {
36e82a52 208 if (fMode == kProofAnalysis) {
2d626244 209 init = fInputEventHandler->Init(tree, "proof");
36e82a52 210 } else {
2d626244 211 init = fInputEventHandler->Init(tree, "local");
36e82a52 212 }
2d626244 213 if (!init) {
214 Error("Init", "Input event handler failed to initialize tree");
215 return kFALSE;
216 }
e7ae3836 217 } else {
218 // If no input event handler we need to get the tree once
219 // for the chain
2d626244 220 if(!tree->GetTree()) {
221 Long64_t readEntry = tree->LoadTree(0);
222 if (readEntry == -2) {
223 Error("Init", "Input tree has no entry. Aborting");
224 return kFALSE;
225 }
226 }
36e82a52 227 }
228
229 if (fMCtruthEventHandler) {
230 if (fMode == kProofAnalysis) {
2d626244 231 init = fMCtruthEventHandler->Init(0x0, "proof");
36e82a52 232 } else {
2d626244 233 init = fMCtruthEventHandler->Init(0x0, "local");
36e82a52 234 }
2d626244 235 if (!init) {
236 Error("Init", "MC event handler failed to initialize");
237 return kFALSE;
238 }
fdb458ec 239 }
240
c52c2132 241 if (!fInitOK) InitAnalysis();
2d626244 242 if (!fInitOK) return kFALSE;
327eaf46 243 fTree = tree;
ce46ecc1 244 AliAnalysisDataContainer *top = fCommonInput;
245 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
c52c2132 246 if (!top) {
8d7d3b59 247 Error("Init","No top input container !");
2d626244 248 return kFALSE;
37153431 249 }
327eaf46 250 top->SetData(tree);
8d7d3b59 251 if (fDebug > 0) {
923e2ca5 252 Printf("<-AliAnalysisManager::Init(%s)", tree->GetName());
981f2614 253 }
2d626244 254 return kTRUE;
d3106602 255}
256
d3106602 257//______________________________________________________________________________
327eaf46 258void AliAnalysisManager::SlaveBegin(TTree *tree)
d3106602 259{
260 // The SlaveBegin() function is called after the Begin() function.
261 // When running with PROOF SlaveBegin() is called on each slave server.
262 // The tree argument is deprecated (on PROOF 0 is passed).
923e2ca5 263 if (fDebug > 0) Printf("->AliAnalysisManager::SlaveBegin()");
aee5ee44 264 static Bool_t isCalled = kFALSE;
2d626244 265 Bool_t init = kFALSE;
266 Bool_t initOK = kTRUE;
267 TString msg;
4ab472d4 268 TDirectory *curdir = gDirectory;
aee5ee44 269 // Call SlaveBegin only once in case of mixing
270 if (isCalled && fMode==kMixingAnalysis) return;
f3d59a0d 271 // Call Init of EventHandler
272 if (fOutputEventHandler) {
273 if (fMode == kProofAnalysis) {
673f68ff 274 // Merging AOD's in PROOF via TProofOutputFile
923e2ca5 275 if (fDebug > 1) Printf(" Initializing AOD output file %s...", fOutputEventHandler->GetOutputFileName());
673f68ff 276 init = fOutputEventHandler->Init("proof");
277 if (!init) msg = "Failed to initialize output handler on worker";
f3d59a0d 278 } else {
2d626244 279 init = fOutputEventHandler->Init("local");
673f68ff 280 if (!init) msg = "Failed to initialize output handler";
f3d59a0d 281 }
2d626244 282 initOK &= init;
283 if (!fSelector) Error("SlaveBegin", "Selector not set");
284 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 285 }
286
287 if (fInputEventHandler) {
288 fInputEventHandler->SetInputTree(tree);
289 if (fMode == kProofAnalysis) {
2d626244 290 init = fInputEventHandler->Init("proof");
291 if (!init) msg = "Failed to initialize input handler on worker";
f3d59a0d 292 } else {
2d626244 293 init = fInputEventHandler->Init("local");
294 if (!init) msg = "Failed to initialize input handler";
f3d59a0d 295 }
2d626244 296 initOK &= init;
297 if (!fSelector) Error("SlaveBegin", "Selector not set");
298 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 299 }
300
301 if (fMCtruthEventHandler) {
302 if (fMode == kProofAnalysis) {
2d626244 303 init = fMCtruthEventHandler->Init("proof");
304 if (!init) msg = "Failed to initialize MC handler on worker";
f3d59a0d 305 } else {
2d626244 306 init = fMCtruthEventHandler->Init("local");
307 if (!init) msg = "Failed to initialize MC handler";
f3d59a0d 308 }
2d626244 309 initOK &= init;
310 if (!fSelector) Error("SlaveBegin", "Selector not set");
311 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
f3d59a0d 312 }
4ab472d4 313 if (curdir) curdir->cd();
2d626244 314 isCalled = kTRUE;
315 if (!initOK) return;
c52c2132 316 TIter next(fTasks);
317 AliAnalysisTask *task;
318 // Call CreateOutputObjects for all tasks
c5a87c56 319 while ((task=(AliAnalysisTask*)next())) {
4ab472d4 320 curdir = gDirectory;
c52c2132 321 task->CreateOutputObjects();
c5a87c56 322 if (curdir) curdir->cd();
36e82a52 323 }
923e2ca5 324 if (fDebug > 0) Printf("<-AliAnalysisManager::SlaveBegin()");
d3106602 325}
326
327//______________________________________________________________________________
327eaf46 328Bool_t AliAnalysisManager::Notify()
329{
330 // The Notify() function is called when a new file is opened. This
331 // can be either for a new TTree in a TChain or when when a new TTree
332 // is started when using PROOF. It is normaly not necessary to make changes
333 // to the generated code, but the routine can be extended by the
334 // user if needed. The return value is currently not used.
2d626244 335 if (!fTree) return kFALSE;
336
8d7d3b59 337 TFile *curfile = fTree->GetCurrentFile();
338 if (!curfile) {
339 Error("Notify","No current file");
340 return kFALSE;
341 }
342
923e2ca5 343 if (fDebug > 0) Printf("->AliAnalysisManager::Notify() file: %s", curfile->GetName());
8d7d3b59 344 TIter next(fTasks);
345 AliAnalysisTask *task;
346 // Call Notify for all tasks
347 while ((task=(AliAnalysisTask*)next()))
348 task->Notify();
fdb458ec 349
8d7d3b59 350 // Call Notify of the event handlers
351 if (fInputEventHandler) {
352 fInputEventHandler->Notify(curfile->GetName());
353 }
6073f8c9 354
8d7d3b59 355 if (fOutputEventHandler) {
356 fOutputEventHandler->Notify(curfile->GetName());
357 }
890126ab 358
8d7d3b59 359 if (fMCtruthEventHandler) {
360 fMCtruthEventHandler->Notify(curfile->GetName());
361 }
923e2ca5 362 if (fDebug > 0) Printf("<-AliAnalysisManager::Notify()");
8d7d3b59 363 return kTRUE;
327eaf46 364}
365
366//______________________________________________________________________________
367Bool_t AliAnalysisManager::Process(Long64_t entry)
d3106602 368{
369 // The Process() function is called for each entry in the tree (or possibly
370 // keyed object in the case of PROOF) to be processed. The entry argument
371 // specifies which entry in the currently loaded tree is to be processed.
372 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
373 // to read either all or the required parts of the data. When processing
374 // keyed objects with PROOF, the object is already loaded and is available
375 // via the fObject pointer.
376 //
377 // This function should contain the "body" of the analysis. It can contain
378 // simple or elaborate selection criteria, run algorithms on the data
379 // of the event and typically fill histograms.
380
381 // WARNING when a selector is used with a TChain, you must use
382 // the pointer to the current TTree to call GetEntry(entry).
383 // The entry is always the local entry number in the current tree.
384 // Assuming that fChain is the pointer to the TChain being processed,
385 // use fChain->GetTree()->GetEntry(entry).
923e2ca5 386 if (fDebug > 0) Printf("->AliAnalysisManager::Process(%lld)", entry);
8d7d3b59 387
ed97dc98 388 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
389 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
390 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 391
327eaf46 392 GetEntry(entry);
393 ExecAnalysis();
923e2ca5 394 if (fDebug > 0) Printf("<-AliAnalysisManager::Process()");
327eaf46 395 return kTRUE;
d3106602 396}
397
398//______________________________________________________________________________
c52c2132 399void AliAnalysisManager::PackOutput(TList *target)
d3106602 400{
981f2614 401 // Pack all output data containers in the output list. Called at SlaveTerminate
402 // stage in PROOF case for each slave.
923e2ca5 403 if (fDebug > 0) Printf("->AliAnalysisManager::PackOutput()");
c52c2132 404 if (!target) {
405 Error("PackOutput", "No target. Aborting.");
406 return;
37153431 407 }
6073f8c9 408 if (fInputEventHandler) fInputEventHandler ->Terminate();
6bb2b24f 409 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
410 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
8d7d3b59 411
412 // Call FinishTaskOutput() for each event loop task (not called for
413 // post-event loop tasks - use Terminate() fo those)
414 TIter nexttask(fTasks);
415 AliAnalysisTask *task;
416 while ((task=(AliAnalysisTask*)nexttask())) {
417 if (!task->IsPostEventLoop()) {
923e2ca5 418 if (fDebug > 0) Printf("->FinishTaskOutput: task %s", task->GetName());
8d7d3b59 419 task->FinishTaskOutput();
923e2ca5 420 if (fDebug > 0) Printf("<-FinishTaskOutput: task %s", task->GetName());
8d7d3b59 421 }
422 }
8c9485b2 423
c52c2132 424 if (fMode == kProofAnalysis) {
425 TIter next(fOutputs);
426 AliAnalysisDataContainer *output;
4ab472d4 427 Bool_t isManagedByHandler = kFALSE;
c52c2132 428 while ((output=(AliAnalysisDataContainer*)next())) {
8d7d3b59 429 // Do not consider outputs of post event loop tasks
2b83ca27 430 isManagedByHandler = kFALSE;
8d7d3b59 431 if (output->GetProducer()->IsPostEventLoop()) continue;
4ab472d4 432 const char *filename = output->GetFileName();
433 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
434 isManagedByHandler = kTRUE;
923e2ca5 435 Printf("#### Handler output. Extra: %s", fExtraFiles.Data());
4ab472d4 436 filename = fOutputEventHandler->GetOutputFileName();
437 }
8d7d3b59 438 // Check if data was posted to this container. If not, issue an error.
4ab472d4 439 if (!output->GetData() && !isManagedByHandler) {
923e2ca5 440 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
8d7d3b59 441 continue;
442 }
443 if (!output->IsSpecialOutput()) {
444 // Normal outputs
4ab472d4 445 if (strlen(filename) && !isManagedByHandler) {
446 // File resident outputs
8d7d3b59 447 TFile *file = output->GetFile();
448 // Backup current folder
ca78991b 449 TDirectory *opwd = gDirectory;
8d7d3b59 450 // Create file if not existing and register to container.
ca78991b 451 if (file) file->cd();
8d7d3b59 452 else file = new TFile(filename, "RECREATE");
453 if (file->IsZombie()) {
923e2ca5 454 Fatal("PackOutput", "Could not recreate file %s", filename);
8d7d3b59 455 return;
456 }
457 output->SetFile(file);
ca78991b 458 // Clear file list to release object ownership to user.
ca78991b 459 file->Clear();
8d7d3b59 460 // Save data to file, then close.
1be433fc 461 if (output->GetData()->InheritsFrom(TCollection::Class())) {
462 // If data is a collection, we set the name of the collection
463 // as the one of the container and we save as a single key.
464 TCollection *coll = (TCollection*)output->GetData();
465 coll->SetName(output->GetName());
466 coll->Write(output->GetName(), TObject::kSingleKey);
467 } else {
cbc8747a 468 if (output->GetData()->InheritsFrom(TTree::Class())) {
469 TTree *tree = (TTree*)output->GetData();
21d37b6f 470 // tree->SetDirectory(file);
cbc8747a 471 tree->AutoSave();
472 } else {
473 output->GetData()->Write();
474 }
1be433fc 475 }
923e2ca5 476 if (fDebug > 1) Printf("PackOutput %s: memory merge, file resident output", output->GetName());
8d7d3b59 477 if (fDebug > 2) {
923e2ca5 478 Printf(" file %s listing content:", filename);
8d7d3b59 479 file->ls();
480 }
ca78991b 481 file->Close();
ca78991b 482 // Restore current directory
483 if (opwd) opwd->cd();
8d7d3b59 484 } else {
485 // Memory-resident outputs
923e2ca5 486 if (fDebug > 1) Printf("PackOutput %s: memory merge memory resident output", filename);
4ab472d4 487 }
488 AliAnalysisDataWrapper *wrap = 0;
489 if (isManagedByHandler) {
490 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
491 wrap->SetName(output->GetName());
ca78991b 492 }
4ab472d4 493 else wrap =output->ExportData();
cbc8747a 494 // Output wrappers must NOT delete data after merging - the user owns them
495 wrap->SetDeleteData(kFALSE);
8167b1d0 496 target->Add(wrap);
4ab472d4 497 } else {
f5e61abd 498 // Special outputs. The file must be opened and connected to the container.
d0864eb4 499 TDirectory *opwd = gDirectory;
8d7d3b59 500 TFile *file = output->GetFile();
f5e61abd 501 if (!file) {
502 AliAnalysisTask *producer = output->GetProducer();
503 Error("PackOutput",
504 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
505 output->GetFileName(), output->GetName(), producer->ClassName());
506 continue;
507 }
508 TString outFilename = file->GetName();
923e2ca5 509 if (fDebug > 1) Printf("PackOutput %s: special output", output->GetName());
4ab472d4 510 if (isManagedByHandler) {
511 // Terminate IO for files managed by the output handler
512 if (file) file->Write();
802f90ef 513 if (file && fDebug > 2) {
923e2ca5 514 Printf(" handled file %s listing content:", file->GetName());
802f90ef 515 file->ls();
516 }
4ab472d4 517 fOutputEventHandler->TerminateIO();
f5e61abd 518 } else {
519 file->cd();
520 // Release object ownership to users after writing data to file
521 if (output->GetData()->InheritsFrom(TCollection::Class())) {
522 // If data is a collection, we set the name of the collection
523 // as the one of the container and we save as a single key.
524 TCollection *coll = (TCollection*)output->GetData();
525 coll->SetName(output->GetName());
526 coll->Write(output->GetName(), TObject::kSingleKey);
cbc8747a 527 } else {
f5e61abd 528 if (output->GetData()->InheritsFrom(TTree::Class())) {
529 TTree *tree = (TTree*)output->GetData();
530 tree->SetDirectory(file);
531 tree->AutoSave();
532 } else {
533 output->GetData()->Write();
534 }
535 }
536 file->Clear();
537 if (fDebug > 2) {
923e2ca5 538 Printf(" file %s listing content:", output->GetFileName());
f5e61abd 539 file->ls();
540 }
541 file->Close();
ef73322e 542 }
8d7d3b59 543 // Restore current directory
d0864eb4 544 if (opwd) opwd->cd();
8d7d3b59 545 // Check if a special output location was provided or the output files have to be merged
13ef3bb0 546 if (strlen(fSpecialOutputLocation.Data())) {
547 TString remote = fSpecialOutputLocation;
548 remote += "/";
ef788aee 549 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
f5e61abd 550 if (remote.BeginsWith("alien://")) {
551 gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());");
552 remote += outFilename;
553 remote.ReplaceAll(".root", Form("_%d.root", gid));
554 } else {
555 remote += Form("%s_%d_", gSystem->HostName(), gid);
556 remote += outFilename;
557 }
558 if (fDebug > 1)
559 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
560 output->GetName(), remote.Data());
ef73322e 561 TFile::Cp ( outFilename.Data(), remote.Data() );
c9e39043 562 // Copy extra outputs
563 if (fExtraFiles.Length() && isManagedByHandler) {
564 TObjArray *arr = fExtraFiles.Tokenize(" ");
565 TObjString *os;
566 TIter nextfilename(arr);
567 while ((os=(TObjString*)nextfilename())) {
568 outFilename = os->GetString();
569 remote = fSpecialOutputLocation;
570 remote += "/";
571 if (remote.BeginsWith("alien://")) {
572 remote += outFilename;
573 remote.ReplaceAll(".root", Form("_%d.root", gid));
574 } else {
575 remote += Form("%s_%d_", gSystem->HostName(), gid);
576 remote += outFilename;
577 }
578 if (fDebug > 1)
579 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
580 outFilename.Data(), remote.Data());
581 TFile::Cp ( outFilename.Data(), remote.Data() );
582 }
583 delete arr;
584 }
ca78991b 585 } else {
8d7d3b59 586 // No special location specified-> use TProofOutputFile as merging utility
587 // The file at this output slot must be opened in CreateOutputObjects
923e2ca5 588 if (fDebug > 1) Printf(" File for container %s to be merged via file merger...", output->GetName());
13ef3bb0 589 }
590 }
c52c2132 591 }
592 }
923e2ca5 593 if (fDebug > 0) Printf("<-AliAnalysisManager::PackOutput: output list contains %d containers", target->GetSize());
c52c2132 594}
595
596//______________________________________________________________________________
981f2614 597void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 598{
981f2614 599// Import data in output containers from wrappers coming in source.
923e2ca5 600 if (fDebug > 0) Printf("->AliAnalysisManager::ImportWrappers()");
327eaf46 601 TIter next(fOutputs);
981f2614 602 AliAnalysisDataContainer *cont;
603 AliAnalysisDataWrapper *wrap;
604 Int_t icont = 0;
c57f56b7 605 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
c52c2132 606 while ((cont=(AliAnalysisDataContainer*)next())) {
0355fc48 607 wrap = 0;
c57f56b7 608 if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
4ab472d4 609 const char *filename = cont->GetFileName();
610 Bool_t isManagedByHandler = kFALSE;
611 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
612 isManagedByHandler = kTRUE;
613 filename = fOutputEventHandler->GetOutputFileName();
614 }
c57f56b7 615 if (cont->IsSpecialOutput() || inGrid) {
f5e61abd 616 if (strlen(fSpecialOutputLocation.Data())) continue;
c57f56b7 617 // Copy merged file from PROOF scratch space.
618 // In case of grid the files are already in the current directory.
619 if (!inGrid) {
c07b9ce2 620 if (isManagedByHandler && fExtraFiles.Length()) {
621 // Copy extra registered dAOD files.
622 TObjArray *arr = fExtraFiles.Tokenize(" ");
623 TObjString *os;
624 TIter nextfilename(arr);
625 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
626 delete arr;
c57f56b7 627 }
c07b9ce2 628 if (!GetFileFromWrapper(filename, source)) continue;
c57f56b7 629 }
8d7d3b59 630 // Normally we should connect data from the copied file to the
631 // corresponding output container, but it is not obvious how to do this
632 // automatically if several objects in file...
dd197a68 633 TFile *f = TFile::Open(filename, "READ");
634 if (!f) {
635 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
0355fc48 636 continue;
dd197a68 637 }
638 TObject *obj = 0;
639 // Try to fetch first a list object having the container name.
640 obj = f->Get(cont->GetName());
641 if (!obj) {
642 // Fetch first object from file having the container type.
643 TIter nextkey(f->GetListOfKeys());
644 TKey *key;
645 while ((key=(TKey*)nextkey())) {
646 obj = f->Get(key->GetName());
647 if (obj && obj->IsA()->InheritsFrom(cont->GetType())) break;
648 }
0355fc48 649 }
dd197a68 650 if (!obj) {
651 Error("ImportWrappers", "Could not find object for container %s in file %s", cont->GetName(), filename);
652 continue;
653 }
0355fc48 654 wrap = new AliAnalysisDataWrapper(obj);
655 wrap->SetDeleteData(kFALSE);
8d7d3b59 656 }
0355fc48 657 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 658 if (!wrap) {
659 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 660 continue;
661 }
981f2614 662 icont++;
8d7d3b59 663 if (fDebug > 1) {
923e2ca5 664 Printf(" Importing data for container %s", cont->GetName());
665 if (strlen(filename)) Printf(" -> file %s", filename);
666 else Printf("");
8d7d3b59 667 }
981f2614 668 cont->ImportData(wrap);
c52c2132 669 }
923e2ca5 670 if (fDebug > 0) Printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported", icont);
c52c2132 671}
672
673//______________________________________________________________________________
674void AliAnalysisManager::UnpackOutput(TList *source)
675{
ca78991b 676 // Called by AliAnalysisSelector::Terminate only on the client.
923e2ca5 677 if (fDebug > 0) Printf("->AliAnalysisManager::UnpackOutput()");
c52c2132 678 if (!source) {
981f2614 679 Error("UnpackOutput", "No target. Aborting.");
c52c2132 680 return;
681 }
923e2ca5 682 if (fDebug > 1) Printf(" Source list contains %d containers", source->GetSize());
c52c2132 683
981f2614 684 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 685
981f2614 686 TIter next(fOutputs);
c52c2132 687 AliAnalysisDataContainer *output;
688 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 689 if (!output->GetData()) continue;
b1310ef5 690 // Check if there are client tasks that run post event loop
691 if (output->HasConsumers()) {
692 // Disable event loop semaphore
693 output->SetPostEventLoop(kTRUE);
694 TObjArray *list = output->GetConsumers();
695 Int_t ncons = list->GetEntriesFast();
696 for (Int_t i=0; i<ncons; i++) {
697 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
698 task->CheckNotify(kTRUE);
699 // If task is active, execute it
700 if (task->IsPostEventLoop() && task->IsActive()) {
923e2ca5 701 if (fDebug > 0) Printf("== Executing post event loop task %s", task->GetName());
b1310ef5 702 task->ExecuteTask();
703 }
704 }
705 }
c52c2132 706 }
923e2ca5 707 if (fDebug > 0) Printf("<-AliAnalysisManager::UnpackOutput()");
d3106602 708}
709
710//______________________________________________________________________________
711void AliAnalysisManager::Terminate()
712{
713 // The Terminate() function is the last function to be called during
714 // a query. It always runs on the client, it can be used to present
c52c2132 715 // the results graphically.
923e2ca5 716 if (fDebug > 0) Printf("->AliAnalysisManager::Terminate()");
327eaf46 717 AliAnalysisTask *task;
c52c2132 718 TIter next(fTasks);
327eaf46 719 // Call Terminate() for tasks
c52c2132 720 while ((task=(AliAnalysisTask*)next())) task->Terminate();
8c9485b2 721 //
8c0ab8e8 722 TIter next1(fOutputs);
723 AliAnalysisDataContainer *output;
724 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 725 // Special outputs or grid files have the files already closed and written.
726 if (fMode == kGridAnalysis) continue;
727 if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
8c0ab8e8 728 const char *filename = output->GetFileName();
729 if (!(strcmp(filename, "default"))) {
730 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1be433fc 731 TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
732 if (aodfile) {
923e2ca5 733 if (fDebug > 1) Printf("Writing output handler file: %s", filename);
1be433fc 734 aodfile->Write();
735 continue;
736 }
8d7d3b59 737 }
738 if (!strlen(filename)) continue;
1be433fc 739 if (!output->GetData()) continue;
8d7d3b59 740 TFile *file = output->GetFile();
741 TDirectory *opwd = gDirectory;
8e6e6fe8 742 file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
743 if (!file) file = new TFile(filename, "RECREATE");
744 if (file->IsZombie()) continue;
745 output->SetFile(file);
746 file->cd();
923e2ca5 747 if (fDebug > 1) Printf(" writing output data %s to file %s", output->GetData()->GetName(), file->GetName());
1be433fc 748 if (output->GetData()->InheritsFrom(TCollection::Class())) {
749 // If data is a collection, we set the name of the collection
750 // as the one of the container and we save as a single key.
751 TCollection *coll = (TCollection*)output->GetData();
752 coll->SetName(output->GetName());
753 coll->Write(output->GetName(), TObject::kSingleKey);
754 } else {
cbc8747a 755 if (output->GetData()->InheritsFrom(TTree::Class())) {
756 TTree *tree = (TTree*)output->GetData();
757 tree->SetDirectory(file);
758 tree->AutoSave();
759 } else {
760 output->GetData()->Write();
761 }
1be433fc 762 }
8e6e6fe8 763 if (opwd) opwd->cd();
764 }
765 next1.Reset();
766 while ((output=(AliAnalysisDataContainer*)next1())) {
767 // Close all files at output
768 TDirectory *opwd = gDirectory;
f5e61abd 769 if (output->GetFile()) {
770 output->GetFile()->Close();
771 // Copy merged outputs in alien if requested
772 if (fSpecialOutputLocation.Length() &&
773 fSpecialOutputLocation.BeginsWith("alien://")) {
774 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
775 TFile::Cp(output->GetFile()->GetName(),
776 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
777 }
778 }
8d7d3b59 779 if (opwd) opwd->cd();
8c0ab8e8 780 }
781
1be433fc 782 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
783 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
784 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
785
8c0ab8e8 786 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
787 if (getsysInfo) {
788 TDirectory *cdir = gDirectory;
789 TFile f("syswatch.root", "RECREATE");
790 if (!f.IsZombie()) {
791 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
792 tree->SetMarkerStyle(kCircle);
793 tree->SetMarkerColor(kBlue);
794 tree->SetMarkerSize(0.5);
795 if (!gROOT->IsBatch()) {
796 tree->SetAlias("event", "id0");
6da75e0b 797 tree->SetAlias("memUSED", "mi.fMemUsed");
798 new TCanvas("SysInfo","SysInfo",10,10,800,600);
8c0ab8e8 799 tree->Draw("memUSED:event","","", 1234567890, 0);
8c0ab8e8 800 }
801 tree->Write();
802 f.Close();
803 delete tree;
804 }
805 if (cdir) cdir->cd();
923e2ca5 806 }
807 // Validate the output files
808 if (ValidateOutputFiles()) {
809 ofstream out;
810 out.open("outputs_valid", ios::out);
811 out.close();
8c0ab8e8 812 }
923e2ca5 813 if (fDebug > 0) Printf("<-AliAnalysisManager::Terminate()");
d3106602 814}
815
816//______________________________________________________________________________
817void AliAnalysisManager::AddTask(AliAnalysisTask *task)
818{
819// Adds a user task to the global list of tasks.
8d7d3b59 820 if (fTasks->FindObject(task)) {
821 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
822 return;
823 }
d3106602 824 task->SetActive(kFALSE);
825 fTasks->Add(task);
826}
827
828//______________________________________________________________________________
829AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
830{
831// Retreive task by name.
832 if (!fTasks) return NULL;
833 return (AliAnalysisTask*)fTasks->FindObject(name);
834}
835
836//______________________________________________________________________________
837AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 838 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 839{
840// Create a data container of a certain type. Types can be:
c52c2132 841// kExchangeContainer = 0, used to exchange date between tasks
d3106602 842// kInputContainer = 1, used to store input data
843// kOutputContainer = 2, used for posting results
b1310ef5 844 if (fContainers->FindObject(name)) {
923e2ca5 845 Error("CreateContainer","A container named %s already defined !",name);
b1310ef5 846 return NULL;
847 }
d3106602 848 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
849 fContainers->Add(cont);
850 switch (type) {
851 case kInputContainer:
852 fInputs->Add(cont);
853 break;
854 case kOutputContainer:
855 fOutputs->Add(cont);
8c0ab8e8 856 if (filename && strlen(filename)) {
857 cont->SetFileName(filename);
858 cont->SetDataOwned(kFALSE); // data owned by the file
859 }
d3106602 860 break;
c52c2132 861 case kExchangeContainer:
d3106602 862 break;
863 }
864 return cont;
865}
866
867//______________________________________________________________________________
868Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
869 AliAnalysisDataContainer *cont)
870{
871// Connect input of an existing task to a data container.
60a04972 872 if (!task) {
873 Error("ConnectInput", "Task pointer is NULL");
874 return kFALSE;
875 }
d3106602 876 if (!fTasks->FindObject(task)) {
877 AddTask(task);
8d7d3b59 878 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 879 }
880 Bool_t connected = task->ConnectInput(islot, cont);
881 return connected;
882}
883
884//______________________________________________________________________________
885Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
886 AliAnalysisDataContainer *cont)
887{
888// Connect output of an existing task to a data container.
60a04972 889 if (!task) {
890 Error("ConnectOutput", "Task pointer is NULL");
891 return kFALSE;
892 }
d3106602 893 if (!fTasks->FindObject(task)) {
894 AddTask(task);
c52c2132 895 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 896 }
897 Bool_t connected = task->ConnectOutput(islot, cont);
898 return connected;
899}
900
901//______________________________________________________________________________
902void AliAnalysisManager::CleanContainers()
903{
904// Clean data from all containers that have already finished all client tasks.
905 TIter next(fContainers);
906 AliAnalysisDataContainer *cont;
907 while ((cont=(AliAnalysisDataContainer *)next())) {
908 if (cont->IsOwnedData() &&
909 cont->IsDataReady() &&
910 cont->ClientsExecuted()) cont->DeleteData();
911 }
912}
913
914//______________________________________________________________________________
915Bool_t AliAnalysisManager::InitAnalysis()
916{
917// Initialization of analysis chain of tasks. Should be called after all tasks
918// and data containers are properly connected
923e2ca5 919 // Reset flag and remove valid_outputs file if exists
d3106602 920 fInitOK = kFALSE;
923e2ca5 921 if (!gSystem->AccessPathName("outputs_valid"))
922 gSystem->Unlink("outputs_valid");
d3106602 923 // Check for top tasks (depending only on input data containers)
924 if (!fTasks->First()) {
c52c2132 925 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 926 return kFALSE;
927 }
928 TIter next(fTasks);
929 AliAnalysisTask *task;
930 AliAnalysisDataContainer *cont;
931 Int_t ntop = 0;
932 Int_t nzombies = 0;
327eaf46 933 Bool_t iszombie = kFALSE;
934 Bool_t istop = kTRUE;
d3106602 935 Int_t i;
936 while ((task=(AliAnalysisTask*)next())) {
327eaf46 937 istop = kTRUE;
938 iszombie = kFALSE;
d3106602 939 Int_t ninputs = task->GetNinputs();
d3106602 940 for (i=0; i<ninputs; i++) {
941 cont = task->GetInputSlot(i)->GetContainer();
942 if (!cont) {
327eaf46 943 if (!iszombie) {
d3106602 944 task->SetZombie();
945 fZombies->Add(task);
946 nzombies++;
327eaf46 947 iszombie = kTRUE;
d3106602 948 }
c52c2132 949 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
950 i, task->GetName());
d3106602 951 }
327eaf46 952 if (iszombie) continue;
d3106602 953 // Check if cont is an input container
327eaf46 954 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 955 // Connect to parent task
956 }
327eaf46 957 if (istop) {
d3106602 958 ntop++;
959 fTopTasks->Add(task);
960 }
961 }
962 if (!ntop) {
c52c2132 963 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 964 return kFALSE;
965 }
966 // Check now if there are orphan tasks
967 for (i=0; i<ntop; i++) {
968 task = (AliAnalysisTask*)fTopTasks->At(i);
969 task->SetUsed();
970 }
971 Int_t norphans = 0;
972 next.Reset();
973 while ((task=(AliAnalysisTask*)next())) {
974 if (!task->IsUsed()) {
975 norphans++;
c52c2132 976 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 977 }
978 }
979 // Check the task hierarchy (no parent task should depend on data provided
980 // by a daughter task)
981 for (i=0; i<ntop; i++) {
982 task = (AliAnalysisTask*)fTopTasks->At(i);
983 if (task->CheckCircularDeps()) {
c52c2132 984 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 985 PrintStatus("dep");
986 return kFALSE;
987 }
988 }
b1310ef5 989 // Check that all containers feeding post-event loop tasks are in the outputs list
990 TIter nextcont(fContainers); // loop over all containers
991 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
992 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
993 if (cont->HasConsumers()) {
994 // Check if one of the consumers is post event loop
995 TIter nextconsumer(cont->GetConsumers());
996 while ((task=(AliAnalysisTask*)nextconsumer())) {
997 if (task->IsPostEventLoop()) {
998 fOutputs->Add(cont);
999 break;
1000 }
1001 }
1002 }
1003 }
1004 }
8d7d3b59 1005 // Check if all special output containers have a file name provided
1006 TIter nextout(fOutputs);
1007 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1008 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1009 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1010 return kFALSE;
1011 }
1012 }
327eaf46 1013 fInitOK = kTRUE;
d3106602 1014 return kTRUE;
1015}
1016
1017//______________________________________________________________________________
1018void AliAnalysisManager::PrintStatus(Option_t *option) const
1019{
1020// Print task hierarchy.
8c0ab8e8 1021 if (!fInitOK) {
1022 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1023 return;
1024 }
1025 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1026 if (getsysInfo)
1027 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1028 TIter next(fTopTasks);
1029 AliAnalysisTask *task;
1030 while ((task=(AliAnalysisTask*)next()))
1031 task->PrintTask(option);
1032}
1033
1034//______________________________________________________________________________
1035void AliAnalysisManager::ResetAnalysis()
1036{
1037// Reset all execution flags and clean containers.
1038 CleanContainers();
1039}
1040
c52c2132 1041//______________________________________________________________________________
8c0ab8e8 1042void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1043{
aee5ee44 1044// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1045// MIX. Process nentries starting from firstentry
c52c2132 1046 if (!fInitOK) {
1047 Error("StartAnalysis","Analysis manager was not initialized !");
1048 return;
1049 }
923e2ca5 1050 if (fDebug > 0) Printf("StartAnalysis %s",GetName());
c52c2132 1051 TString anaType = type;
1052 anaType.ToLower();
1053 fMode = kLocalAnalysis;
c57f56b7 1054 Bool_t runlocalinit = kTRUE;
1055 if (anaType.Contains("file")) runlocalinit = kFALSE;
4ab472d4 1056 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1057 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1058 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1059
c52c2132 1060 if (fMode == kGridAnalysis) {
c57f56b7 1061 if (!fGridHandler) {
1062 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1063 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1064 return;
1065 }
1066 // Write analysis manager in the analysis file
1067 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1068 // run local task configuration
1069 TIter nextTask(fTasks);
1070 AliAnalysisTask *task;
1071 while ((task=(AliAnalysisTask*)nextTask())) {
1072 task->LocalInit();
1073 }
5513444a 1074 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1075 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1076 return;
1077 }
c57f56b7 1078
1079 // Terminate grid analysis
2d626244 1080 if (fSelector && fSelector->GetStatus() == -1) return;
c57f56b7 1081 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1082 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1083 if (!fGridHandler->MergeOutputs()) {
1084 // Return if outputs could not be merged or if it alien handler
1085 // was configured for offline mode or local testing.
1086 return;
1087 }
1088 ImportWrappers(NULL);
1089 Terminate();
1090 return;
981f2614 1091 }
d86ed856 1092 char line[256];
efd53803 1093 SetEventLoop(kFALSE);
8d7d3b59 1094 // Enable event loop mode if a tree was provided
aee5ee44 1095 if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1096
8c0ab8e8 1097 TChain *chain = 0;
1098 TString ttype = "TTree";
4ab472d4 1099 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1100 chain = (TChain*)tree;
6b742510 1101 if (!chain || !chain->GetListOfFiles()->First()) {
1102 Error("StartAnalysis", "Cannot process null or empty chain...");
1103 return;
1104 }
8c0ab8e8 1105 ttype = "TChain";
1106 }
9b33830a 1107
aee5ee44 1108 // Initialize locally all tasks (happens for all modes)
9b33830a 1109 TIter next(fTasks);
1110 AliAnalysisTask *task;
c57f56b7 1111 if (runlocalinit) {
1112 while ((task=(AliAnalysisTask*)next())) {
1113 task->LocalInit();
1114 }
1115 }
efd53803 1116
c52c2132 1117 switch (fMode) {
1118 case kLocalAnalysis:
1119 if (!tree) {
03a5cc9f 1120 TIter nextT(fTasks);
981f2614 1121 // Call CreateOutputObjects for all tasks
03a5cc9f 1122 while ((task=(AliAnalysisTask*)nextT())) {
c5a87c56 1123 TDirectory *curdir = gDirectory;
1124 task->CreateOutputObjects();
1125 if (curdir) curdir->cd();
1126 }
c52c2132 1127 ExecAnalysis();
981f2614 1128 Terminate();
c52c2132 1129 return;
1130 }
1131 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1132 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
aee5ee44 1133 fSelector = new AliAnalysisSelector(this);
1134 tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1135 break;
1136 case kProofAnalysis:
1137 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
923e2ca5 1138 Error("StartAnalysis", "No PROOF!!! Aborting.");
c52c2132 1139 return;
1140 }
1141 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1142 gROOT->ProcessLine(line);
1143 if (chain) {
1144 chain->SetProof();
1145 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
8c0ab8e8 1146 chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1147 } else {
923e2ca5 1148 Error("StartAnalysis", "No chain!!! Aborting.");
c52c2132 1149 return;
1150 }
1151 break;
1152 case kGridAnalysis:
1153 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
aee5ee44 1154 break;
1155 case kMixingAnalysis:
1156 // Run event mixing analysis
1157 if (!fEventPool) {
1158 Error("StartAnalysis", "Cannot run event mixing without event pool");
1159 return;
1160 }
1161 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1162 fSelector = new AliAnalysisSelector(this);
aee5ee44 1163 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1164 next.Reset();
aee5ee44 1165 // Call NotifyBinChange for all tasks
1166 while ((task=(AliAnalysisTask*)next()))
1167 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1168 chain->Process(fSelector);
1169 }
1170 PackOutput(fSelector->GetOutputList());
1171 Terminate();
c52c2132 1172 }
1173}
1174
d86ed856 1175//______________________________________________________________________________
1176void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1177{
1178// Start analysis for this manager on a given dataset. Analysis task can be:
1179// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1180 if (!fInitOK) {
1181 Error("StartAnalysis","Analysis manager was not initialized !");
1182 return;
1183 }
923e2ca5 1184 if (fDebug > 0) Printf("StartAnalysis %s",GetName());
d86ed856 1185 TString anaType = type;
1186 anaType.ToLower();
1187 if (!anaType.Contains("proof")) {
d140f7fb 1188 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
d86ed856 1189 return;
1190 }
1191 fMode = kProofAnalysis;
1192 char line[256];
1193 SetEventLoop(kTRUE);
1194 // Set the dataset flag
1195 TObject::SetBit(kUseDataSet);
1196 fTree = 0;
1197
1198 // Initialize locally all tasks
1199 TIter next(fTasks);
1200 AliAnalysisTask *task;
1201 while ((task=(AliAnalysisTask*)next())) {
1202 task->LocalInit();
1203 }
1204
1205 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
923e2ca5 1206 Error("StartAnalysis", "No PROOF!!! Aborting.");
d86ed856 1207 return;
1208 }
1209 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1210 gROOT->ProcessLine(line);
1211 sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1212 if (!gROOT->ProcessLine(line)) {
1213 Error("StartAnalysis", "Dataset %s not found", dataset);
1214 return;
1215 }
1216 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1217 dataset, nentries, firstentry);
1218 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1219 gROOT->ProcessLine(line);
1220}
1221
d3106602 1222//______________________________________________________________________________
8d7d3b59 1223TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1224{
1225// Opens a special output file used in PROOF.
1226 char line[256];
1227 if (fMode!=kProofAnalysis || !fSelector) {
1228 Error("OpenProofFile","Cannot open PROOF file %s",filename);
1229 return NULL;
f5e61abd 1230 }
1231 if (fSpecialOutputLocation.Length()) {
1232 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1233 if (!f) f = new TFile(filename, option);
1234 return f;
8d7d3b59 1235 }
1236 sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
923e2ca5 1237 if (fDebug > 1) Printf("=== %s", line);
8d7d3b59 1238 gROOT->ProcessLine(line);
1239 sprintf(line, "pf->OpenFile(\"%s\");", option);
1240 gROOT->ProcessLine(line);
1241 if (fDebug > 1) {
1242 gROOT->ProcessLine("pf->Print()");
923e2ca5 1243 Printf(" == proof file name: %s", gFile->GetName());
8d7d3b59 1244 }
1245 sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
923e2ca5 1246 if (fDebug > 1) Printf("=== %s", line);
8d7d3b59 1247 gROOT->ProcessLine(line);
1248 return gFile;
1249}
1250
1251//______________________________________________________________________________
d3106602 1252void AliAnalysisManager::ExecAnalysis(Option_t *option)
1253{
1254// Execute analysis.
8c0ab8e8 1255 static Long64_t ncalls = 0;
1256 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1257 if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1258 ncalls++;
327eaf46 1259 if (!fInitOK) {
c52c2132 1260 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 1261 return;
1262 }
d3106602 1263 AliAnalysisTask *task;
327eaf46 1264 // Check if the top tree is active.
1265 if (fTree) {
1266 TIter next(fTasks);
1267 // De-activate all tasks
1268 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1269 AliAnalysisDataContainer *cont = fCommonInput;
1270 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1271 if (!cont) {
c52c2132 1272 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 1273 return;
1274 }
1275 cont->SetData(fTree); // This will notify all consumers
ed97dc98 1276 Long64_t entry = fTree->GetTree()->GetReadEntry();
1277
6bb2b24f 1278//
c3701689 1279// Call BeginEvent() for optional input/output and MC services
ed97dc98 1280 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1281 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1282 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 1283//
1284// Execute the tasks
276941c8 1285// TIter next1(cont->GetConsumers());
1286 TIter next1(fTopTasks);
327eaf46 1287 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1288 if (fDebug >1) {
1289 cout << " Executing task " << task->GetName() << endl;
1290 }
6bb2b24f 1291
327eaf46 1292 task->ExecuteTask(option);
1293 }
6bb2b24f 1294//
1295// Call FinishEvent() for optional output and MC services
6073f8c9 1296 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1297 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1298 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1299 // Gather system information if requested
1300 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1301 AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
327eaf46 1302 return;
1303 }
1304 // The event loop is not controlled by TSelector
6bb2b24f 1305//
c3701689 1306// Call BeginEvent() for optional input/output and MC services
ed97dc98 1307 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1308 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1309 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
327eaf46 1310 TIter next2(fTopTasks);
1311 while ((task=(AliAnalysisTask*)next2())) {
1312 task->SetActive(kTRUE);
c52c2132 1313 if (fDebug > 1) {
1314 cout << " Executing task " << task->GetName() << endl;
1315 }
d3106602 1316 task->ExecuteTask(option);
327eaf46 1317 }
6bb2b24f 1318//
1319// Call FinishEvent() for optional output and MC services
6073f8c9 1320 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1321 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1322 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 1323}
1324
1325//______________________________________________________________________________
1326void AliAnalysisManager::FinishAnalysis()
1327{
1328// Finish analysis.
1329}
60a04972 1330
1331//______________________________________________________________________________
1332void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* handler)
1333{
1334// Set the input event handler and create a container for it.
1335 fInputEventHandler = handler;
d958c3ea 1336 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ce46ecc1 1337 Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 1338}
1339
1340//______________________________________________________________________________
1341void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* handler)
1342{
1343// Set the input event handler and create a container for it.
1344 fOutputEventHandler = handler;
d958c3ea 1345 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 1346 fCommonOutput->SetSpecialOutput();
ca316909 1347 Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 1348}
c07b9ce2 1349
1350//______________________________________________________________________________
1351void AliAnalysisManager::RegisterExtraFile(const char *fname)
1352{
1353// This method is used externally to register output files which are not
1354// connected to any output container, so that the manager can properly register,
1355// retrieve or merge them when running in distributed mode. The file names are
1356// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1357 if (fExtraFiles.Length()) fExtraFiles += " ";
1358 fExtraFiles += fname;
1359}
1360
1361//______________________________________________________________________________
1362Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1363{
1364// Copy a file from the location specified ina the wrapper with the same name from the source list.
1365 char full_path[512];
1366 char ch_url[512];
1367 TObject *pof = source->FindObject(filename);
1368 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1369 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1370 return kFALSE;
1371 }
1372 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1373 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1374 TString clientUrl(ch_url);
1375 TString full_path_str(full_path);
1376 if (clientUrl.Contains("localhost")){
1377 TObjArray* array = full_path_str.Tokenize ( "//" );
1378 TObjString *strobj = ( TObjString *)array->At(1);
1379 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1380 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1381 full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1382 full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1383 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1384 delete arrayPort;
1385 delete array;
1386 }
1387 if (fDebug > 1)
1388 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1389 Bool_t gotit = TFile::Cp(full_path_str.Data(), filename);
1390 if (!gotit)
1391 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1392 return gotit;
1393}
d29168d6 1394
1395//______________________________________________________________________________
1396void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1397{
1398// Fill analysis type in the provided string.
1399 switch (fMode) {
1400 case kLocalAnalysis:
1401 type = "local";
1402 return;
1403 case kProofAnalysis:
1404 type = "proof";
1405 return;
1406 case kGridAnalysis:
1407 type = "grid";
1408 return;
1409 case kMixingAnalysis:
1410 type = "mix";
1411 }
1412}
923e2ca5 1413
1414//______________________________________________________________________________
1415Bool_t AliAnalysisManager::ValidateOutputFiles() const
1416{
1417// Validate all output files.
1418 TIter next(fOutputs);
1419 AliAnalysisDataContainer *output;
1420 TDirectory *cdir = gDirectory;
1421 while ((output=(AliAnalysisDataContainer*)next())) {
1422 TString filename = output->GetFileName();
1423 if (filename == "default") {
1424 if (!fOutputEventHandler) continue;
1425 filename = fOutputEventHandler->GetOutputFileName();
1426 }
1427 // Check if the file is closed
1428 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1429 if (file) {
1430 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
1431 file->Close();
1432 }
1433 file = TFile::Open(filename);
1434 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
1435 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
1436 cdir->cd();
1437 return kFALSE;
1438 }
1439 file->Close();
1440 }
1441 cdir->cd();
1442 return kTRUE;
1443}