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