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