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