Fixed most coding violations.
[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
d3106602 53//______________________________________________________________________________
c52c2132 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.
8d7d3b59 176 if (fDebug > 0) printf("== AliAnalysisManager::GetEntry(%lld)\n", 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) {
192 printf("->AliAnalysisManager::Init(%s)\n", 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) {
981f2614 252 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
253 }
2d626244 254 return kTRUE;
d3106602 255}
256
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).
8d7d3b59 263 if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n");
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
275 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
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 }
8d7d3b59 324 if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n");
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
343 if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
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 }
362 if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n");
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).
8d7d3b59 386 if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry);
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();
8d7d3b59 394 if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n");
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.
8d7d3b59 403 if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n");
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()) {
418 if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName());
419 task->FinishTaskOutput();
420 if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName());
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;
435 filename = fOutputEventHandler->GetOutputFileName();
436 }
8d7d3b59 437 // Check if data was posted to this container. If not, issue an error.
4ab472d4 438 if (!output->GetData() && !isManagedByHandler) {
8d7d3b59 439 Error("PackOutput", "No data for output container %s. Forgot to PostData ?\n", output->GetName());
440 continue;
441 }
442 if (!output->IsSpecialOutput()) {
443 // Normal outputs
4ab472d4 444 if (strlen(filename) && !isManagedByHandler) {
445 // File resident outputs
8d7d3b59 446 TFile *file = output->GetFile();
447 // Backup current folder
ca78991b 448 TDirectory *opwd = gDirectory;
8d7d3b59 449 // Create file if not existing and register to container.
ca78991b 450 if (file) file->cd();
8d7d3b59 451 else file = new TFile(filename, "RECREATE");
452 if (file->IsZombie()) {
453 Fatal("PackOutput", "Could not recreate file %s\n", filename);
454 return;
455 }
456 output->SetFile(file);
ca78991b 457 // Clear file list to release object ownership to user.
ca78991b 458 file->Clear();
8d7d3b59 459 // Save data to file, then close.
1be433fc 460 if (output->GetData()->InheritsFrom(TCollection::Class())) {
461 // If data is a collection, we set the name of the collection
462 // as the one of the container and we save as a single key.
463 TCollection *coll = (TCollection*)output->GetData();
464 coll->SetName(output->GetName());
465 coll->Write(output->GetName(), TObject::kSingleKey);
466 } else {
cbc8747a 467 if (output->GetData()->InheritsFrom(TTree::Class())) {
468 TTree *tree = (TTree*)output->GetData();
469 tree->SetDirectory(file);
470 tree->AutoSave();
471 } else {
472 output->GetData()->Write();
473 }
1be433fc 474 }
8d7d3b59 475 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
476 if (fDebug > 2) {
477 printf(" file %s listing content:\n", filename);
478 file->ls();
479 }
ca78991b 480 file->Close();
ca78991b 481 // Restore current directory
482 if (opwd) opwd->cd();
8d7d3b59 483 } else {
484 // Memory-resident outputs
4ab472d4 485 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
486 }
487 AliAnalysisDataWrapper *wrap = 0;
488 if (isManagedByHandler) {
489 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
490 wrap->SetName(output->GetName());
ca78991b 491 }
4ab472d4 492 else wrap =output->ExportData();
cbc8747a 493 // Output wrappers must NOT delete data after merging - the user owns them
494 wrap->SetDeleteData(kFALSE);
8167b1d0 495 target->Add(wrap);
4ab472d4 496 } else {
8d7d3b59 497 // Special outputs
d0864eb4 498 TDirectory *opwd = gDirectory;
8d7d3b59 499 TFile *file = output->GetFile();
802f90ef 500 if (fDebug > 1 && file) printf("PackOutput %s: file merge, special output\n", output->GetName());
4ab472d4 501 if (isManagedByHandler) {
502 // Terminate IO for files managed by the output handler
503 if (file) file->Write();
802f90ef 504 if (file && fDebug > 2) {
505 printf(" handled file %s listing content:\n", file->GetName());
506 file->ls();
507 }
4ab472d4 508 fOutputEventHandler->TerminateIO();
509 continue;
510 }
511
8d7d3b59 512 if (!file) {
513 AliAnalysisTask *producer = output->GetProducer();
514 Error("PackOutput",
515 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
516 output->GetFileName(), output->GetName(), producer->ClassName());
517 continue;
518 }
ef788aee 519 file->cd();
8d7d3b59 520 // Release object ownership to users after writing data to file
1be433fc 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);
527 } else {
cbc8747a 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 }
1be433fc 535 }
8d7d3b59 536 file->Clear();
537 if (fDebug > 2) {
538 printf(" file %s listing content:\n", output->GetFileName());
539 file->ls();
ef73322e 540 }
541 TString outFilename = file->GetName();
13ef3bb0 542 file->Close();
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();");
d0864eb4 550 remote += Form("%s_%d_", gSystem->HostName(), gid);
13ef3bb0 551 remote += output->GetFileName();
ef73322e 552 TFile::Cp ( outFilename.Data(), remote.Data() );
ca78991b 553 } else {
8d7d3b59 554 // No special location specified-> use TProofOutputFile as merging utility
555 // The file at this output slot must be opened in CreateOutputObjects
556 if (fDebug > 1) printf(" File %s to be merged...\n", output->GetFileName());
13ef3bb0 557 }
558 }
c52c2132 559 }
560 }
8d7d3b59 561 if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
c52c2132 562}
563
564//______________________________________________________________________________
981f2614 565void AliAnalysisManager::ImportWrappers(TList *source)
c52c2132 566{
981f2614 567// Import data in output containers from wrappers coming in source.
8d7d3b59 568 if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
327eaf46 569 TIter next(fOutputs);
981f2614 570 AliAnalysisDataContainer *cont;
571 AliAnalysisDataWrapper *wrap;
572 Int_t icont = 0;
c57f56b7 573 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
c52c2132 574 while ((cont=(AliAnalysisDataContainer*)next())) {
0355fc48 575 wrap = 0;
c57f56b7 576 if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
4ab472d4 577 const char *filename = cont->GetFileName();
578 Bool_t isManagedByHandler = kFALSE;
579 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
580 isManagedByHandler = kTRUE;
581 filename = fOutputEventHandler->GetOutputFileName();
582 }
c57f56b7 583 if (cont->IsSpecialOutput() || inGrid) {
4ab472d4 584 if (strlen(fSpecialOutputLocation.Data()) && !isManagedByHandler) continue;
c57f56b7 585 // Copy merged file from PROOF scratch space.
586 // In case of grid the files are already in the current directory.
587 if (!inGrid) {
c07b9ce2 588 if (isManagedByHandler && fExtraFiles.Length()) {
589 // Copy extra registered dAOD files.
590 TObjArray *arr = fExtraFiles.Tokenize(" ");
591 TObjString *os;
592 TIter nextfilename(arr);
593 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
594 delete arr;
c57f56b7 595 }
c07b9ce2 596 if (!GetFileFromWrapper(filename, source)) continue;
c57f56b7 597 }
8d7d3b59 598 // Normally we should connect data from the copied file to the
599 // corresponding output container, but it is not obvious how to do this
600 // automatically if several objects in file...
dd197a68 601 TFile *f = TFile::Open(filename, "READ");
602 if (!f) {
603 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
0355fc48 604 continue;
dd197a68 605 }
606 TObject *obj = 0;
607 // Try to fetch first a list object having the container name.
608 obj = f->Get(cont->GetName());
609 if (!obj) {
610 // Fetch first object from file having the container type.
611 TIter nextkey(f->GetListOfKeys());
612 TKey *key;
613 while ((key=(TKey*)nextkey())) {
614 obj = f->Get(key->GetName());
615 if (obj && obj->IsA()->InheritsFrom(cont->GetType())) break;
616 }
0355fc48 617 }
dd197a68 618 if (!obj) {
619 Error("ImportWrappers", "Could not find object for container %s in file %s", cont->GetName(), filename);
620 continue;
621 }
0355fc48 622 wrap = new AliAnalysisDataWrapper(obj);
623 wrap->SetDeleteData(kFALSE);
8d7d3b59 624 }
0355fc48 625 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
8d7d3b59 626 if (!wrap) {
627 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
c52c2132 628 continue;
629 }
981f2614 630 icont++;
8d7d3b59 631 if (fDebug > 1) {
632 printf(" Importing data for container %s", cont->GetName());
dd197a68 633 if (strlen(filename)) printf(" -> file %s\n", filename);
8d7d3b59 634 else printf("\n");
635 }
981f2614 636 cont->ImportData(wrap);
c52c2132 637 }
8d7d3b59 638 if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 639}
640
641//______________________________________________________________________________
642void AliAnalysisManager::UnpackOutput(TList *source)
643{
ca78991b 644 // Called by AliAnalysisSelector::Terminate only on the client.
8d7d3b59 645 if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 646 if (!source) {
981f2614 647 Error("UnpackOutput", "No target. Aborting.");
c52c2132 648 return;
649 }
8d7d3b59 650 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
c52c2132 651
981f2614 652 if (fMode == kProofAnalysis) ImportWrappers(source);
37153431 653
981f2614 654 TIter next(fOutputs);
c52c2132 655 AliAnalysisDataContainer *output;
656 while ((output=(AliAnalysisDataContainer*)next())) {
c52c2132 657 if (!output->GetData()) continue;
b1310ef5 658 // Check if there are client tasks that run post event loop
659 if (output->HasConsumers()) {
660 // Disable event loop semaphore
661 output->SetPostEventLoop(kTRUE);
662 TObjArray *list = output->GetConsumers();
663 Int_t ncons = list->GetEntriesFast();
664 for (Int_t i=0; i<ncons; i++) {
665 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
666 task->CheckNotify(kTRUE);
667 // If task is active, execute it
668 if (task->IsPostEventLoop() && task->IsActive()) {
8d7d3b59 669 if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 670 task->ExecuteTask();
671 }
672 }
673 }
c52c2132 674 }
8d7d3b59 675 if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
d3106602 676}
677
678//______________________________________________________________________________
679void AliAnalysisManager::Terminate()
680{
681 // The Terminate() function is the last function to be called during
682 // a query. It always runs on the client, it can be used to present
c52c2132 683 // the results graphically.
8d7d3b59 684 if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
327eaf46 685 AliAnalysisTask *task;
c52c2132 686 TIter next(fTasks);
327eaf46 687 // Call Terminate() for tasks
c52c2132 688 while ((task=(AliAnalysisTask*)next())) task->Terminate();
8c9485b2 689 //
8c0ab8e8 690 TIter next1(fOutputs);
691 AliAnalysisDataContainer *output;
692 while ((output=(AliAnalysisDataContainer*)next1())) {
c57f56b7 693 // Special outputs or grid files have the files already closed and written.
694 if (fMode == kGridAnalysis) continue;
695 if (output->IsSpecialOutput()&&(fMode == kProofAnalysis)) continue;
8c0ab8e8 696 const char *filename = output->GetFileName();
697 if (!(strcmp(filename, "default"))) {
698 if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName();
1be433fc 699 TFile *aodfile = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
700 if (aodfile) {
701 if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
702 aodfile->Write();
703 continue;
704 }
8d7d3b59 705 }
706 if (!strlen(filename)) continue;
1be433fc 707 if (!output->GetData()) continue;
8d7d3b59 708 TFile *file = output->GetFile();
709 TDirectory *opwd = gDirectory;
8e6e6fe8 710 file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
711 if (!file) file = new TFile(filename, "RECREATE");
712 if (file->IsZombie()) continue;
713 output->SetFile(file);
714 file->cd();
8d7d3b59 715 if (fDebug > 1) printf(" writing output data %s to file %s\n", output->GetData()->GetName(), file->GetName());
1be433fc 716 if (output->GetData()->InheritsFrom(TCollection::Class())) {
717 // If data is a collection, we set the name of the collection
718 // as the one of the container and we save as a single key.
719 TCollection *coll = (TCollection*)output->GetData();
720 coll->SetName(output->GetName());
721 coll->Write(output->GetName(), TObject::kSingleKey);
722 } else {
cbc8747a 723 if (output->GetData()->InheritsFrom(TTree::Class())) {
724 TTree *tree = (TTree*)output->GetData();
725 tree->SetDirectory(file);
726 tree->AutoSave();
727 } else {
728 output->GetData()->Write();
729 }
1be433fc 730 }
8e6e6fe8 731 if (opwd) opwd->cd();
732 }
733 next1.Reset();
734 while ((output=(AliAnalysisDataContainer*)next1())) {
735 // Close all files at output
736 TDirectory *opwd = gDirectory;
737 if (output->GetFile()) output->GetFile()->Close();
8d7d3b59 738 if (opwd) opwd->cd();
8c0ab8e8 739 }
740
1be433fc 741 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
742 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
743 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
744
8c0ab8e8 745 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
746 if (getsysInfo) {
747 TDirectory *cdir = gDirectory;
748 TFile f("syswatch.root", "RECREATE");
749 if (!f.IsZombie()) {
750 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
751 tree->SetMarkerStyle(kCircle);
752 tree->SetMarkerColor(kBlue);
753 tree->SetMarkerSize(0.5);
754 if (!gROOT->IsBatch()) {
755 tree->SetAlias("event", "id0");
6da75e0b 756 tree->SetAlias("memUSED", "mi.fMemUsed");
757 new TCanvas("SysInfo","SysInfo",10,10,800,600);
8c0ab8e8 758 tree->Draw("memUSED:event","","", 1234567890, 0);
8c0ab8e8 759 }
760 tree->Write();
761 f.Close();
762 delete tree;
763 }
764 if (cdir) cdir->cd();
765 }
8d7d3b59 766 if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 767}
768
769//______________________________________________________________________________
770void AliAnalysisManager::AddTask(AliAnalysisTask *task)
771{
772// Adds a user task to the global list of tasks.
8d7d3b59 773 if (fTasks->FindObject(task)) {
774 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
775 return;
776 }
d3106602 777 task->SetActive(kFALSE);
778 fTasks->Add(task);
779}
780
781//______________________________________________________________________________
782AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
783{
784// Retreive task by name.
785 if (!fTasks) return NULL;
786 return (AliAnalysisTask*)fTasks->FindObject(name);
787}
788
789//______________________________________________________________________________
790AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 791 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 792{
793// Create a data container of a certain type. Types can be:
c52c2132 794// kExchangeContainer = 0, used to exchange date between tasks
d3106602 795// kInputContainer = 1, used to store input data
796// kOutputContainer = 2, used for posting results
b1310ef5 797 if (fContainers->FindObject(name)) {
798 Error("CreateContainer","A container named %s already defined !\n",name);
799 return NULL;
800 }
d3106602 801 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
802 fContainers->Add(cont);
803 switch (type) {
804 case kInputContainer:
805 fInputs->Add(cont);
806 break;
807 case kOutputContainer:
808 fOutputs->Add(cont);
8c0ab8e8 809 if (filename && strlen(filename)) {
810 cont->SetFileName(filename);
811 cont->SetDataOwned(kFALSE); // data owned by the file
812 }
d3106602 813 break;
c52c2132 814 case kExchangeContainer:
d3106602 815 break;
816 }
817 return cont;
818}
819
820//______________________________________________________________________________
821Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
822 AliAnalysisDataContainer *cont)
823{
824// Connect input of an existing task to a data container.
60a04972 825 if (!task) {
826 Error("ConnectInput", "Task pointer is NULL");
827 return kFALSE;
828 }
d3106602 829 if (!fTasks->FindObject(task)) {
830 AddTask(task);
8d7d3b59 831 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 832 }
833 Bool_t connected = task->ConnectInput(islot, cont);
834 return connected;
835}
836
837//______________________________________________________________________________
838Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
839 AliAnalysisDataContainer *cont)
840{
841// Connect output of an existing task to a data container.
60a04972 842 if (!task) {
843 Error("ConnectOutput", "Task pointer is NULL");
844 return kFALSE;
845 }
d3106602 846 if (!fTasks->FindObject(task)) {
847 AddTask(task);
c52c2132 848 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 849 }
850 Bool_t connected = task->ConnectOutput(islot, cont);
851 return connected;
852}
853
854//______________________________________________________________________________
855void AliAnalysisManager::CleanContainers()
856{
857// Clean data from all containers that have already finished all client tasks.
858 TIter next(fContainers);
859 AliAnalysisDataContainer *cont;
860 while ((cont=(AliAnalysisDataContainer *)next())) {
861 if (cont->IsOwnedData() &&
862 cont->IsDataReady() &&
863 cont->ClientsExecuted()) cont->DeleteData();
864 }
865}
866
867//______________________________________________________________________________
868Bool_t AliAnalysisManager::InitAnalysis()
869{
870// Initialization of analysis chain of tasks. Should be called after all tasks
871// and data containers are properly connected
872 // Check for input/output containers
873 fInitOK = kFALSE;
d3106602 874 // Check for top tasks (depending only on input data containers)
875 if (!fTasks->First()) {
c52c2132 876 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 877 return kFALSE;
878 }
879 TIter next(fTasks);
880 AliAnalysisTask *task;
881 AliAnalysisDataContainer *cont;
882 Int_t ntop = 0;
883 Int_t nzombies = 0;
327eaf46 884 Bool_t iszombie = kFALSE;
885 Bool_t istop = kTRUE;
d3106602 886 Int_t i;
887 while ((task=(AliAnalysisTask*)next())) {
327eaf46 888 istop = kTRUE;
889 iszombie = kFALSE;
d3106602 890 Int_t ninputs = task->GetNinputs();
d3106602 891 for (i=0; i<ninputs; i++) {
892 cont = task->GetInputSlot(i)->GetContainer();
893 if (!cont) {
327eaf46 894 if (!iszombie) {
d3106602 895 task->SetZombie();
896 fZombies->Add(task);
897 nzombies++;
327eaf46 898 iszombie = kTRUE;
d3106602 899 }
c52c2132 900 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
901 i, task->GetName());
d3106602 902 }
327eaf46 903 if (iszombie) continue;
d3106602 904 // Check if cont is an input container
327eaf46 905 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 906 // Connect to parent task
907 }
327eaf46 908 if (istop) {
d3106602 909 ntop++;
910 fTopTasks->Add(task);
911 }
912 }
913 if (!ntop) {
c52c2132 914 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 915 return kFALSE;
916 }
917 // Check now if there are orphan tasks
918 for (i=0; i<ntop; i++) {
919 task = (AliAnalysisTask*)fTopTasks->At(i);
920 task->SetUsed();
921 }
922 Int_t norphans = 0;
923 next.Reset();
924 while ((task=(AliAnalysisTask*)next())) {
925 if (!task->IsUsed()) {
926 norphans++;
c52c2132 927 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 928 }
929 }
930 // Check the task hierarchy (no parent task should depend on data provided
931 // by a daughter task)
932 for (i=0; i<ntop; i++) {
933 task = (AliAnalysisTask*)fTopTasks->At(i);
934 if (task->CheckCircularDeps()) {
c52c2132 935 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 936 PrintStatus("dep");
937 return kFALSE;
938 }
939 }
b1310ef5 940 // Check that all containers feeding post-event loop tasks are in the outputs list
941 TIter nextcont(fContainers); // loop over all containers
942 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
943 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
944 if (cont->HasConsumers()) {
945 // Check if one of the consumers is post event loop
946 TIter nextconsumer(cont->GetConsumers());
947 while ((task=(AliAnalysisTask*)nextconsumer())) {
948 if (task->IsPostEventLoop()) {
949 fOutputs->Add(cont);
950 break;
951 }
952 }
953 }
954 }
955 }
8d7d3b59 956 // Check if all special output containers have a file name provided
957 TIter nextout(fOutputs);
958 while ((cont=(AliAnalysisDataContainer*)nextout())) {
959 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
960 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
961 return kFALSE;
962 }
963 }
327eaf46 964 fInitOK = kTRUE;
d3106602 965 return kTRUE;
966}
967
968//______________________________________________________________________________
969void AliAnalysisManager::PrintStatus(Option_t *option) const
970{
971// Print task hierarchy.
8c0ab8e8 972 if (!fInitOK) {
973 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
974 return;
975 }
976 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
977 if (getsysInfo)
978 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 979 TIter next(fTopTasks);
980 AliAnalysisTask *task;
981 while ((task=(AliAnalysisTask*)next()))
982 task->PrintTask(option);
983}
984
985//______________________________________________________________________________
986void AliAnalysisManager::ResetAnalysis()
987{
988// Reset all execution flags and clean containers.
989 CleanContainers();
990}
991
992//______________________________________________________________________________
8c0ab8e8 993void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
c52c2132 994{
aee5ee44 995// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
996// MIX. Process nentries starting from firstentry
c52c2132 997 if (!fInitOK) {
998 Error("StartAnalysis","Analysis manager was not initialized !");
999 return;
1000 }
8d7d3b59 1001 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
c52c2132 1002 TString anaType = type;
1003 anaType.ToLower();
1004 fMode = kLocalAnalysis;
c57f56b7 1005 Bool_t runlocalinit = kTRUE;
1006 if (anaType.Contains("file")) runlocalinit = kFALSE;
4ab472d4 1007 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1008 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1009 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1010
c52c2132 1011 if (fMode == kGridAnalysis) {
c57f56b7 1012 if (!fGridHandler) {
1013 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1014 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1015 return;
1016 }
1017 // Write analysis manager in the analysis file
1018 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1019 // run local task configuration
1020 TIter nextTask(fTasks);
1021 AliAnalysisTask *task;
1022 while ((task=(AliAnalysisTask*)nextTask())) {
1023 task->LocalInit();
1024 }
1025 fGridHandler->StartAnalysis(nentries, firstentry);
1026
1027 // Terminate grid analysis
2d626244 1028 if (fSelector && fSelector->GetStatus() == -1) return;
c57f56b7 1029 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1030 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1031 if (!fGridHandler->MergeOutputs()) {
1032 // Return if outputs could not be merged or if it alien handler
1033 // was configured for offline mode or local testing.
1034 return;
1035 }
1036 ImportWrappers(NULL);
1037 Terminate();
1038 return;
981f2614 1039 }
d86ed856 1040 char line[256];
efd53803 1041 SetEventLoop(kFALSE);
8d7d3b59 1042 // Enable event loop mode if a tree was provided
aee5ee44 1043 if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1044
8c0ab8e8 1045 TChain *chain = 0;
1046 TString ttype = "TTree";
4ab472d4 1047 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1048 chain = (TChain*)tree;
6b742510 1049 if (!chain || !chain->GetListOfFiles()->First()) {
1050 Error("StartAnalysis", "Cannot process null or empty chain...");
1051 return;
1052 }
8c0ab8e8 1053 ttype = "TChain";
1054 }
9b33830a 1055
aee5ee44 1056 // Initialize locally all tasks (happens for all modes)
9b33830a 1057 TIter next(fTasks);
1058 AliAnalysisTask *task;
c57f56b7 1059 if (runlocalinit) {
1060 while ((task=(AliAnalysisTask*)next())) {
1061 task->LocalInit();
1062 }
1063 }
efd53803 1064
c52c2132 1065 switch (fMode) {
1066 case kLocalAnalysis:
1067 if (!tree) {
03a5cc9f 1068 TIter nextT(fTasks);
981f2614 1069 // Call CreateOutputObjects for all tasks
03a5cc9f 1070 while ((task=(AliAnalysisTask*)nextT())) {
c5a87c56 1071 TDirectory *curdir = gDirectory;
1072 task->CreateOutputObjects();
1073 if (curdir) curdir->cd();
1074 }
c52c2132 1075 ExecAnalysis();
981f2614 1076 Terminate();
c52c2132 1077 return;
1078 }
1079 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1080 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
aee5ee44 1081 fSelector = new AliAnalysisSelector(this);
1082 tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1083 break;
1084 case kProofAnalysis:
1085 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1086 printf("StartAnalysis: no PROOF!!!\n");
1087 return;
1088 }
1089 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1090 gROOT->ProcessLine(line);
1091 if (chain) {
1092 chain->SetProof();
1093 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
8c0ab8e8 1094 chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1095 } else {
1096 printf("StartAnalysis: no chain\n");
1097 return;
1098 }
1099 break;
1100 case kGridAnalysis:
1101 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
aee5ee44 1102 break;
1103 case kMixingAnalysis:
1104 // Run event mixing analysis
1105 if (!fEventPool) {
1106 Error("StartAnalysis", "Cannot run event mixing without event pool");
1107 return;
1108 }
1109 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1110 fSelector = new AliAnalysisSelector(this);
aee5ee44 1111 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1112 next.Reset();
aee5ee44 1113 // Call NotifyBinChange for all tasks
1114 while ((task=(AliAnalysisTask*)next()))
1115 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1116 chain->Process(fSelector);
1117 }
1118 PackOutput(fSelector->GetOutputList());
1119 Terminate();
c52c2132 1120 }
1121}
1122
1123//______________________________________________________________________________
d86ed856 1124void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1125{
1126// Start analysis for this manager on a given dataset. Analysis task can be:
1127// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1128 if (!fInitOK) {
1129 Error("StartAnalysis","Analysis manager was not initialized !");
1130 return;
1131 }
8d7d3b59 1132 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
d86ed856 1133 TString anaType = type;
1134 anaType.ToLower();
1135 if (!anaType.Contains("proof")) {
d140f7fb 1136 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
d86ed856 1137 return;
1138 }
1139 fMode = kProofAnalysis;
1140 char line[256];
1141 SetEventLoop(kTRUE);
1142 // Set the dataset flag
1143 TObject::SetBit(kUseDataSet);
1144 fTree = 0;
1145
1146 // Initialize locally all tasks
1147 TIter next(fTasks);
1148 AliAnalysisTask *task;
1149 while ((task=(AliAnalysisTask*)next())) {
1150 task->LocalInit();
1151 }
1152
1153 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1154 printf("StartAnalysis: no PROOF!!!\n");
1155 return;
1156 }
1157 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1158 gROOT->ProcessLine(line);
1159 sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1160 if (!gROOT->ProcessLine(line)) {
1161 Error("StartAnalysis", "Dataset %s not found", dataset);
1162 return;
1163 }
1164 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1165 dataset, nentries, firstentry);
1166 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1167 gROOT->ProcessLine(line);
1168}
1169
1170//______________________________________________________________________________
8d7d3b59 1171TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1172{
1173// Opens a special output file used in PROOF.
1174 char line[256];
1175 if (fMode!=kProofAnalysis || !fSelector) {
1176 Error("OpenProofFile","Cannot open PROOF file %s",filename);
1177 return NULL;
1178 }
1179 sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
1180 if (fDebug > 1) printf("=== %s\n", line);
1181 gROOT->ProcessLine(line);
1182 sprintf(line, "pf->OpenFile(\"%s\");", option);
1183 gROOT->ProcessLine(line);
1184 if (fDebug > 1) {
1185 gROOT->ProcessLine("pf->Print()");
1186 printf(" == proof file name: %s\n", gFile->GetName());
1187 }
1188 sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1189 if (fDebug > 1) printf("=== %s\n", line);
1190 gROOT->ProcessLine(line);
1191 return gFile;
1192}
1193
1194//______________________________________________________________________________
d3106602 1195void AliAnalysisManager::ExecAnalysis(Option_t *option)
1196{
1197// Execute analysis.
8c0ab8e8 1198 static Long64_t ncalls = 0;
1199 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1200 if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1201 ncalls++;
327eaf46 1202 if (!fInitOK) {
c52c2132 1203 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 1204 return;
1205 }
d3106602 1206 AliAnalysisTask *task;
327eaf46 1207 // Check if the top tree is active.
1208 if (fTree) {
1209 TIter next(fTasks);
1210 // De-activate all tasks
1211 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1212 AliAnalysisDataContainer *cont = fCommonInput;
1213 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1214 if (!cont) {
c52c2132 1215 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 1216 return;
1217 }
1218 cont->SetData(fTree); // This will notify all consumers
ed97dc98 1219 Long64_t entry = fTree->GetTree()->GetReadEntry();
1220
6bb2b24f 1221//
c3701689 1222// Call BeginEvent() for optional input/output and MC services
ed97dc98 1223 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1224 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1225 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 1226//
1227// Execute the tasks
276941c8 1228// TIter next1(cont->GetConsumers());
1229 TIter next1(fTopTasks);
327eaf46 1230 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1231 if (fDebug >1) {
1232 cout << " Executing task " << task->GetName() << endl;
1233 }
6bb2b24f 1234
327eaf46 1235 task->ExecuteTask(option);
1236 }
6bb2b24f 1237//
1238// Call FinishEvent() for optional output and MC services
6073f8c9 1239 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1240 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1241 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1242 // Gather system information if requested
1243 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1244 AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
327eaf46 1245 return;
1246 }
1247 // The event loop is not controlled by TSelector
6bb2b24f 1248//
c3701689 1249// Call BeginEvent() for optional input/output and MC services
ed97dc98 1250 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1251 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1252 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
327eaf46 1253 TIter next2(fTopTasks);
1254 while ((task=(AliAnalysisTask*)next2())) {
1255 task->SetActive(kTRUE);
c52c2132 1256 if (fDebug > 1) {
1257 cout << " Executing task " << task->GetName() << endl;
1258 }
d3106602 1259 task->ExecuteTask(option);
327eaf46 1260 }
6bb2b24f 1261//
1262// Call FinishEvent() for optional output and MC services
6073f8c9 1263 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1264 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1265 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 1266}
1267
1268//______________________________________________________________________________
1269void AliAnalysisManager::FinishAnalysis()
1270{
1271// Finish analysis.
1272}
60a04972 1273
1274//______________________________________________________________________________
1275void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* handler)
1276{
1277// Set the input event handler and create a container for it.
1278 fInputEventHandler = handler;
d958c3ea 1279 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ce46ecc1 1280 Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 1281}
1282
1283//______________________________________________________________________________
1284void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* handler)
1285{
1286// Set the input event handler and create a container for it.
1287 fOutputEventHandler = handler;
d958c3ea 1288 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 1289 fCommonOutput->SetSpecialOutput();
ca316909 1290 Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 1291}
c07b9ce2 1292
1293//______________________________________________________________________________
1294void AliAnalysisManager::RegisterExtraFile(const char *fname)
1295{
1296// This method is used externally to register output files which are not
1297// connected to any output container, so that the manager can properly register,
1298// retrieve or merge them when running in distributed mode. The file names are
1299// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1300 if (fExtraFiles.Length()) fExtraFiles += " ";
1301 fExtraFiles += fname;
1302}
1303
1304//______________________________________________________________________________
1305Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1306{
1307// Copy a file from the location specified ina the wrapper with the same name from the source list.
1308 char full_path[512];
1309 char ch_url[512];
1310 TObject *pof = source->FindObject(filename);
1311 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1312 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1313 return kFALSE;
1314 }
1315 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1316 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1317 TString clientUrl(ch_url);
1318 TString full_path_str(full_path);
1319 if (clientUrl.Contains("localhost")){
1320 TObjArray* array = full_path_str.Tokenize ( "//" );
1321 TObjString *strobj = ( TObjString *)array->At(1);
1322 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1323 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1324 full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1325 full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1326 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1327 delete arrayPort;
1328 delete array;
1329 }
1330 if (fDebug > 1)
1331 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1332 Bool_t gotit = TFile::Cp(full_path_str.Data(), filename);
1333 if (!gotit)
1334 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1335 return gotit;
1336}