Moving the fourieranalysis classes back to the PHOS
[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;
c9e39043 435 printf("#### Handler output. Extra: %s\n", 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) {
8d7d3b59 440 Error("PackOutput", "No data for output container %s. Forgot to PostData ?\n", output->GetName());
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()) {
454 Fatal("PackOutput", "Could not recreate file %s\n", filename);
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 }
8d7d3b59 476 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
477 if (fDebug > 2) {
478 printf(" file %s listing content:\n", filename);
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
4ab472d4 486 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
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();
509 if (fDebug > 1) printf("PackOutput %s: special output\n", 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) {
514 printf(" handled file %s listing content:\n", file->GetName());
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) {
538 printf(" file %s listing content:\n", output->GetFileName());
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
c9e39043 588 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
13ef3bb0 589 }
590 }
c52c2132 591 }
592 }
8d7d3b59 593 if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", 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.
8d7d3b59 600 if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n");
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) {
664 printf(" Importing data for container %s", cont->GetName());
dd197a68 665 if (strlen(filename)) printf(" -> file %s\n", filename);
8d7d3b59 666 else printf("\n");
667 }
981f2614 668 cont->ImportData(wrap);
c52c2132 669 }
8d7d3b59 670 if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
c52c2132 671}
672
673//______________________________________________________________________________
674void AliAnalysisManager::UnpackOutput(TList *source)
675{
ca78991b 676 // Called by AliAnalysisSelector::Terminate only on the client.
8d7d3b59 677 if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n");
c52c2132 678 if (!source) {
981f2614 679 Error("UnpackOutput", "No target. Aborting.");
c52c2132 680 return;
681 }
8d7d3b59 682 if (fDebug > 1) printf(" Source list contains %d containers\n", 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()) {
8d7d3b59 701 if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName());
b1310ef5 702 task->ExecuteTask();
703 }
704 }
705 }
c52c2132 706 }
8d7d3b59 707 if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n");
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.
8d7d3b59 716 if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n");
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) {
733 if (fDebug > 1) printf("Writing output handler file: %s\n", filename);
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();
8d7d3b59 747 if (fDebug > 1) printf(" writing output data %s to file %s\n", 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();
806 }
8d7d3b59 807 if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n");
d3106602 808}
809
810//______________________________________________________________________________
811void AliAnalysisManager::AddTask(AliAnalysisTask *task)
812{
813// Adds a user task to the global list of tasks.
8d7d3b59 814 if (fTasks->FindObject(task)) {
815 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
816 return;
817 }
d3106602 818 task->SetActive(kFALSE);
819 fTasks->Add(task);
820}
821
822//______________________________________________________________________________
823AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
824{
825// Retreive task by name.
826 if (!fTasks) return NULL;
827 return (AliAnalysisTask*)fTasks->FindObject(name);
828}
829
830//______________________________________________________________________________
831AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
c52c2132 832 TClass *datatype, EAliAnalysisContType type, const char *filename)
d3106602 833{
834// Create a data container of a certain type. Types can be:
c52c2132 835// kExchangeContainer = 0, used to exchange date between tasks
d3106602 836// kInputContainer = 1, used to store input data
837// kOutputContainer = 2, used for posting results
b1310ef5 838 if (fContainers->FindObject(name)) {
839 Error("CreateContainer","A container named %s already defined !\n",name);
840 return NULL;
841 }
d3106602 842 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
843 fContainers->Add(cont);
844 switch (type) {
845 case kInputContainer:
846 fInputs->Add(cont);
847 break;
848 case kOutputContainer:
849 fOutputs->Add(cont);
8c0ab8e8 850 if (filename && strlen(filename)) {
851 cont->SetFileName(filename);
852 cont->SetDataOwned(kFALSE); // data owned by the file
853 }
d3106602 854 break;
c52c2132 855 case kExchangeContainer:
d3106602 856 break;
857 }
858 return cont;
859}
860
861//______________________________________________________________________________
862Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
863 AliAnalysisDataContainer *cont)
864{
865// Connect input of an existing task to a data container.
60a04972 866 if (!task) {
867 Error("ConnectInput", "Task pointer is NULL");
868 return kFALSE;
869 }
d3106602 870 if (!fTasks->FindObject(task)) {
871 AddTask(task);
8d7d3b59 872 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
d3106602 873 }
874 Bool_t connected = task->ConnectInput(islot, cont);
875 return connected;
876}
877
878//______________________________________________________________________________
879Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
880 AliAnalysisDataContainer *cont)
881{
882// Connect output of an existing task to a data container.
60a04972 883 if (!task) {
884 Error("ConnectOutput", "Task pointer is NULL");
885 return kFALSE;
886 }
d3106602 887 if (!fTasks->FindObject(task)) {
888 AddTask(task);
c52c2132 889 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
d3106602 890 }
891 Bool_t connected = task->ConnectOutput(islot, cont);
892 return connected;
893}
894
895//______________________________________________________________________________
896void AliAnalysisManager::CleanContainers()
897{
898// Clean data from all containers that have already finished all client tasks.
899 TIter next(fContainers);
900 AliAnalysisDataContainer *cont;
901 while ((cont=(AliAnalysisDataContainer *)next())) {
902 if (cont->IsOwnedData() &&
903 cont->IsDataReady() &&
904 cont->ClientsExecuted()) cont->DeleteData();
905 }
906}
907
908//______________________________________________________________________________
909Bool_t AliAnalysisManager::InitAnalysis()
910{
911// Initialization of analysis chain of tasks. Should be called after all tasks
912// and data containers are properly connected
913 // Check for input/output containers
914 fInitOK = kFALSE;
d3106602 915 // Check for top tasks (depending only on input data containers)
916 if (!fTasks->First()) {
c52c2132 917 Error("InitAnalysis", "Analysis has no tasks !");
d3106602 918 return kFALSE;
919 }
920 TIter next(fTasks);
921 AliAnalysisTask *task;
922 AliAnalysisDataContainer *cont;
923 Int_t ntop = 0;
924 Int_t nzombies = 0;
327eaf46 925 Bool_t iszombie = kFALSE;
926 Bool_t istop = kTRUE;
d3106602 927 Int_t i;
928 while ((task=(AliAnalysisTask*)next())) {
327eaf46 929 istop = kTRUE;
930 iszombie = kFALSE;
d3106602 931 Int_t ninputs = task->GetNinputs();
d3106602 932 for (i=0; i<ninputs; i++) {
933 cont = task->GetInputSlot(i)->GetContainer();
934 if (!cont) {
327eaf46 935 if (!iszombie) {
d3106602 936 task->SetZombie();
937 fZombies->Add(task);
938 nzombies++;
327eaf46 939 iszombie = kTRUE;
d3106602 940 }
c52c2132 941 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
942 i, task->GetName());
d3106602 943 }
327eaf46 944 if (iszombie) continue;
d3106602 945 // Check if cont is an input container
327eaf46 946 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
d3106602 947 // Connect to parent task
948 }
327eaf46 949 if (istop) {
d3106602 950 ntop++;
951 fTopTasks->Add(task);
952 }
953 }
954 if (!ntop) {
c52c2132 955 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
d3106602 956 return kFALSE;
957 }
958 // Check now if there are orphan tasks
959 for (i=0; i<ntop; i++) {
960 task = (AliAnalysisTask*)fTopTasks->At(i);
961 task->SetUsed();
962 }
963 Int_t norphans = 0;
964 next.Reset();
965 while ((task=(AliAnalysisTask*)next())) {
966 if (!task->IsUsed()) {
967 norphans++;
c52c2132 968 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
d3106602 969 }
970 }
971 // Check the task hierarchy (no parent task should depend on data provided
972 // by a daughter task)
973 for (i=0; i<ntop; i++) {
974 task = (AliAnalysisTask*)fTopTasks->At(i);
975 if (task->CheckCircularDeps()) {
c52c2132 976 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
d3106602 977 PrintStatus("dep");
978 return kFALSE;
979 }
980 }
b1310ef5 981 // Check that all containers feeding post-event loop tasks are in the outputs list
982 TIter nextcont(fContainers); // loop over all containers
983 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
984 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
985 if (cont->HasConsumers()) {
986 // Check if one of the consumers is post event loop
987 TIter nextconsumer(cont->GetConsumers());
988 while ((task=(AliAnalysisTask*)nextconsumer())) {
989 if (task->IsPostEventLoop()) {
990 fOutputs->Add(cont);
991 break;
992 }
993 }
994 }
995 }
996 }
8d7d3b59 997 // Check if all special output containers have a file name provided
998 TIter nextout(fOutputs);
999 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1000 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1001 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1002 return kFALSE;
1003 }
1004 }
327eaf46 1005 fInitOK = kTRUE;
d3106602 1006 return kTRUE;
1007}
1008
1009//______________________________________________________________________________
1010void AliAnalysisManager::PrintStatus(Option_t *option) const
1011{
1012// Print task hierarchy.
8c0ab8e8 1013 if (!fInitOK) {
1014 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1015 return;
1016 }
1017 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1018 if (getsysInfo)
1019 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
d3106602 1020 TIter next(fTopTasks);
1021 AliAnalysisTask *task;
1022 while ((task=(AliAnalysisTask*)next()))
1023 task->PrintTask(option);
1024}
1025
1026//______________________________________________________________________________
1027void AliAnalysisManager::ResetAnalysis()
1028{
1029// Reset all execution flags and clean containers.
1030 CleanContainers();
1031}
1032
1033//______________________________________________________________________________
8c0ab8e8 1034void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry)
c52c2132 1035{
aee5ee44 1036// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1037// MIX. Process nentries starting from firstentry
c52c2132 1038 if (!fInitOK) {
1039 Error("StartAnalysis","Analysis manager was not initialized !");
1040 return;
1041 }
8d7d3b59 1042 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
c52c2132 1043 TString anaType = type;
1044 anaType.ToLower();
1045 fMode = kLocalAnalysis;
c57f56b7 1046 Bool_t runlocalinit = kTRUE;
1047 if (anaType.Contains("file")) runlocalinit = kFALSE;
4ab472d4 1048 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1049 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1050 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1051
c52c2132 1052 if (fMode == kGridAnalysis) {
c57f56b7 1053 if (!fGridHandler) {
1054 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1055 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1056 return;
1057 }
1058 // Write analysis manager in the analysis file
1059 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1060 // run local task configuration
1061 TIter nextTask(fTasks);
1062 AliAnalysisTask *task;
1063 while ((task=(AliAnalysisTask*)nextTask())) {
1064 task->LocalInit();
1065 }
5513444a 1066 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1067 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1068 return;
1069 }
c57f56b7 1070
1071 // Terminate grid analysis
2d626244 1072 if (fSelector && fSelector->GetStatus() == -1) return;
c57f56b7 1073 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return;
1074 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1075 if (!fGridHandler->MergeOutputs()) {
1076 // Return if outputs could not be merged or if it alien handler
1077 // was configured for offline mode or local testing.
1078 return;
1079 }
1080 ImportWrappers(NULL);
1081 Terminate();
1082 return;
981f2614 1083 }
d86ed856 1084 char line[256];
efd53803 1085 SetEventLoop(kFALSE);
8d7d3b59 1086 // Enable event loop mode if a tree was provided
aee5ee44 1087 if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
efd53803 1088
8c0ab8e8 1089 TChain *chain = 0;
1090 TString ttype = "TTree";
4ab472d4 1091 if (tree && tree->IsA() == TChain::Class()) {
8c0ab8e8 1092 chain = (TChain*)tree;
6b742510 1093 if (!chain || !chain->GetListOfFiles()->First()) {
1094 Error("StartAnalysis", "Cannot process null or empty chain...");
1095 return;
1096 }
8c0ab8e8 1097 ttype = "TChain";
1098 }
9b33830a 1099
aee5ee44 1100 // Initialize locally all tasks (happens for all modes)
9b33830a 1101 TIter next(fTasks);
1102 AliAnalysisTask *task;
c57f56b7 1103 if (runlocalinit) {
1104 while ((task=(AliAnalysisTask*)next())) {
1105 task->LocalInit();
1106 }
1107 }
efd53803 1108
c52c2132 1109 switch (fMode) {
1110 case kLocalAnalysis:
1111 if (!tree) {
03a5cc9f 1112 TIter nextT(fTasks);
981f2614 1113 // Call CreateOutputObjects for all tasks
03a5cc9f 1114 while ((task=(AliAnalysisTask*)nextT())) {
c5a87c56 1115 TDirectory *curdir = gDirectory;
1116 task->CreateOutputObjects();
1117 if (curdir) curdir->cd();
1118 }
c52c2132 1119 ExecAnalysis();
981f2614 1120 Terminate();
c52c2132 1121 return;
1122 }
1123 // Run tree-based analysis via AliAnalysisSelector
c52c2132 1124 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
aee5ee44 1125 fSelector = new AliAnalysisSelector(this);
1126 tree->Process(fSelector, "", nentries, firstentry);
c52c2132 1127 break;
1128 case kProofAnalysis:
1129 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1130 printf("StartAnalysis: no PROOF!!!\n");
1131 return;
1132 }
1133 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1134 gROOT->ProcessLine(line);
1135 if (chain) {
1136 chain->SetProof();
1137 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
8c0ab8e8 1138 chain->Process("AliAnalysisSelector", "", nentries, firstentry);
c52c2132 1139 } else {
1140 printf("StartAnalysis: no chain\n");
1141 return;
1142 }
1143 break;
1144 case kGridAnalysis:
1145 Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
aee5ee44 1146 break;
1147 case kMixingAnalysis:
1148 // Run event mixing analysis
1149 if (!fEventPool) {
1150 Error("StartAnalysis", "Cannot run event mixing without event pool");
1151 return;
1152 }
1153 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1154 fSelector = new AliAnalysisSelector(this);
aee5ee44 1155 while ((chain=fEventPool->GetNextChain())) {
d1e79f9e 1156 next.Reset();
aee5ee44 1157 // Call NotifyBinChange for all tasks
1158 while ((task=(AliAnalysisTask*)next()))
1159 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1160 chain->Process(fSelector);
1161 }
1162 PackOutput(fSelector->GetOutputList());
1163 Terminate();
c52c2132 1164 }
1165}
1166
1167//______________________________________________________________________________
d86ed856 1168void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1169{
1170// Start analysis for this manager on a given dataset. Analysis task can be:
1171// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1172 if (!fInitOK) {
1173 Error("StartAnalysis","Analysis manager was not initialized !");
1174 return;
1175 }
8d7d3b59 1176 if (fDebug > 0) printf("StartAnalysis %s\n",GetName());
d86ed856 1177 TString anaType = type;
1178 anaType.ToLower();
1179 if (!anaType.Contains("proof")) {
d140f7fb 1180 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
d86ed856 1181 return;
1182 }
1183 fMode = kProofAnalysis;
1184 char line[256];
1185 SetEventLoop(kTRUE);
1186 // Set the dataset flag
1187 TObject::SetBit(kUseDataSet);
1188 fTree = 0;
1189
1190 // Initialize locally all tasks
1191 TIter next(fTasks);
1192 AliAnalysisTask *task;
1193 while ((task=(AliAnalysisTask*)next())) {
1194 task->LocalInit();
1195 }
1196
1197 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1198 printf("StartAnalysis: no PROOF!!!\n");
1199 return;
1200 }
1201 sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1202 gROOT->ProcessLine(line);
1203 sprintf(line, "gProof->GetDataSet(\"%s\");", dataset);
1204 if (!gROOT->ProcessLine(line)) {
1205 Error("StartAnalysis", "Dataset %s not found", dataset);
1206 return;
1207 }
1208 sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1209 dataset, nentries, firstentry);
1210 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1211 gROOT->ProcessLine(line);
1212}
1213
1214//______________________________________________________________________________
8d7d3b59 1215TFile *AliAnalysisManager::OpenProofFile(const char *filename, const char *option)
1216{
1217// Opens a special output file used in PROOF.
1218 char line[256];
1219 if (fMode!=kProofAnalysis || !fSelector) {
1220 Error("OpenProofFile","Cannot open PROOF file %s",filename);
1221 return NULL;
f5e61abd 1222 }
1223 if (fSpecialOutputLocation.Length()) {
1224 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1225 if (!f) f = new TFile(filename, option);
1226 return f;
8d7d3b59 1227 }
1228 sprintf(line, "TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename);
1229 if (fDebug > 1) printf("=== %s\n", line);
1230 gROOT->ProcessLine(line);
1231 sprintf(line, "pf->OpenFile(\"%s\");", option);
1232 gROOT->ProcessLine(line);
1233 if (fDebug > 1) {
1234 gROOT->ProcessLine("pf->Print()");
1235 printf(" == proof file name: %s\n", gFile->GetName());
1236 }
1237 sprintf(line, "((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1238 if (fDebug > 1) printf("=== %s\n", line);
1239 gROOT->ProcessLine(line);
1240 return gFile;
1241}
1242
1243//______________________________________________________________________________
d3106602 1244void AliAnalysisManager::ExecAnalysis(Option_t *option)
1245{
1246// Execute analysis.
8c0ab8e8 1247 static Long64_t ncalls = 0;
1248 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1249 if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls);
1250 ncalls++;
327eaf46 1251 if (!fInitOK) {
c52c2132 1252 Error("ExecAnalysis", "Analysis manager was not initialized !");
327eaf46 1253 return;
1254 }
d3106602 1255 AliAnalysisTask *task;
327eaf46 1256 // Check if the top tree is active.
1257 if (fTree) {
1258 TIter next(fTasks);
1259 // De-activate all tasks
1260 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
ce46ecc1 1261 AliAnalysisDataContainer *cont = fCommonInput;
1262 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
327eaf46 1263 if (!cont) {
c52c2132 1264 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
327eaf46 1265 return;
1266 }
1267 cont->SetData(fTree); // This will notify all consumers
ed97dc98 1268 Long64_t entry = fTree->GetTree()->GetReadEntry();
1269
6bb2b24f 1270//
c3701689 1271// Call BeginEvent() for optional input/output and MC services
ed97dc98 1272 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1273 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1274 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
6bb2b24f 1275//
1276// Execute the tasks
276941c8 1277// TIter next1(cont->GetConsumers());
1278 TIter next1(fTopTasks);
327eaf46 1279 while ((task=(AliAnalysisTask*)next1())) {
c52c2132 1280 if (fDebug >1) {
1281 cout << " Executing task " << task->GetName() << endl;
1282 }
6bb2b24f 1283
327eaf46 1284 task->ExecuteTask(option);
1285 }
6bb2b24f 1286//
1287// Call FinishEvent() for optional output and MC services
6073f8c9 1288 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
6bb2b24f 1289 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1290 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
8c0ab8e8 1291 // Gather system information if requested
1292 if (getsysInfo && ((ncalls%fNSysInfo)==0))
1293 AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls);
327eaf46 1294 return;
1295 }
1296 // The event loop is not controlled by TSelector
6bb2b24f 1297//
c3701689 1298// Call BeginEvent() for optional input/output and MC services
ed97dc98 1299 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1300 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1301 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
327eaf46 1302 TIter next2(fTopTasks);
1303 while ((task=(AliAnalysisTask*)next2())) {
1304 task->SetActive(kTRUE);
c52c2132 1305 if (fDebug > 1) {
1306 cout << " Executing task " << task->GetName() << endl;
1307 }
d3106602 1308 task->ExecuteTask(option);
327eaf46 1309 }
6bb2b24f 1310//
1311// Call FinishEvent() for optional output and MC services
6073f8c9 1312 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1313 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
6bb2b24f 1314 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
d3106602 1315}
1316
1317//______________________________________________________________________________
1318void AliAnalysisManager::FinishAnalysis()
1319{
1320// Finish analysis.
1321}
60a04972 1322
1323//______________________________________________________________________________
1324void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* handler)
1325{
1326// Set the input event handler and create a container for it.
1327 fInputEventHandler = handler;
d958c3ea 1328 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
ce46ecc1 1329 Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
60a04972 1330}
1331
1332//______________________________________________________________________________
1333void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* handler)
1334{
1335// Set the input event handler and create a container for it.
1336 fOutputEventHandler = handler;
d958c3ea 1337 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
673f68ff 1338 fCommonOutput->SetSpecialOutput();
ca316909 1339 Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
60a04972 1340}
c07b9ce2 1341
1342//______________________________________________________________________________
1343void AliAnalysisManager::RegisterExtraFile(const char *fname)
1344{
1345// This method is used externally to register output files which are not
1346// connected to any output container, so that the manager can properly register,
1347// retrieve or merge them when running in distributed mode. The file names are
1348// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
1349 if (fExtraFiles.Length()) fExtraFiles += " ";
1350 fExtraFiles += fname;
1351}
1352
1353//______________________________________________________________________________
1354Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source)
1355{
1356// Copy a file from the location specified ina the wrapper with the same name from the source list.
1357 char full_path[512];
1358 char ch_url[512];
1359 TObject *pof = source->FindObject(filename);
1360 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
1361 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
1362 return kFALSE;
1363 }
1364 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof));
1365 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url));
1366 TString clientUrl(ch_url);
1367 TString full_path_str(full_path);
1368 if (clientUrl.Contains("localhost")){
1369 TObjArray* array = full_path_str.Tokenize ( "//" );
1370 TObjString *strobj = ( TObjString *)array->At(1);
1371 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
1372 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
1373 full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
1374 full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
1375 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename);
1376 delete arrayPort;
1377 delete array;
1378 }
1379 if (fDebug > 1)
1380 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data());
1381 Bool_t gotit = TFile::Cp(full_path_str.Data(), filename);
1382 if (!gotit)
1383 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
1384 return gotit;
1385}
d29168d6 1386
1387//______________________________________________________________________________
1388void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
1389{
1390// Fill analysis type in the provided string.
1391 switch (fMode) {
1392 case kLocalAnalysis:
1393 type = "local";
1394 return;
1395 case kProofAnalysis:
1396 type = "proof";
1397 return;
1398 case kGridAnalysis:
1399 type = "grid";
1400 return;
1401 case kMixingAnalysis:
1402 type = "mix";
1403 }
1404}