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