Updated to use new AOD class
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisManager.cxx
... / ...
CommitLineData
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// AliAnalysisManager - Manager analysis class. Allows creation of several
21// analysis tasks and data containers storing their input/output. Allows
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
28#include <Riostream.h>
29
30#include <TError.h>
31#include <TClass.h>
32#include <TFile.h>
33//#include <TKey.h>
34#include <TMath.h>
35#include <TH1.h>
36#include <TMethodCall.h>
37#include <TChain.h>
38#include <TSystem.h>
39#include <TROOT.h>
40#include <TCanvas.h>
41#include <TStopwatch.h>
42
43#include "AliAnalysisSelector.h"
44#include "AliAnalysisGrid.h"
45#include "AliAnalysisTask.h"
46#include "AliAnalysisDataContainer.h"
47#include "AliAnalysisDataSlot.h"
48#include "AliVEventHandler.h"
49#include "AliVEventPool.h"
50#include "AliSysInfo.h"
51#include "AliAnalysisManager.h"
52
53ClassImp(AliAnalysisManager)
54
55AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
56TString AliAnalysisManager::fgCommonFileName = "";
57
58//______________________________________________________________________________
59AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
60 :TNamed(name,title),
61 fTree(NULL),
62 fInputEventHandler(NULL),
63 fOutputEventHandler(NULL),
64 fMCtruthEventHandler(NULL),
65 fEventPool(NULL),
66 fCurrentEntry(-1),
67 fNSysInfo(0),
68 fMode(kLocalAnalysis),
69 fInitOK(kFALSE),
70 fIsRemote(kFALSE),
71 fDebug(0),
72 fSpecialOutputLocation(""),
73 fTasks(NULL),
74 fTopTasks(NULL),
75 fZombies(NULL),
76 fContainers(NULL),
77 fInputs(NULL),
78 fOutputs(NULL),
79 fParamCont(NULL),
80 fCommonInput(NULL),
81 fCommonOutput(NULL),
82 fSelector(NULL),
83 fGridHandler(NULL),
84 fExtraFiles(""),
85 fAutoBranchHandling(kTRUE),
86 fTable(),
87 fRunFromPath(0),
88 fNcalls(0),
89 fStatisticsMsg(),
90 fRequestedBranches()
91{
92// Default constructor.
93 fgAnalysisManager = this;
94 fgCommonFileName = "AnalysisResults.root";
95 fTasks = new TObjArray();
96 fTopTasks = new TObjArray();
97 fZombies = new TObjArray();
98 fContainers = new TObjArray();
99 fInputs = new TObjArray();
100 fOutputs = new TObjArray();
101 fParamCont = new TObjArray();
102 SetEventLoop(kTRUE);
103 TObject::SetObjectStat(kFALSE);
104}
105
106//______________________________________________________________________________
107AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
108 :TNamed(other),
109 fTree(NULL),
110 fInputEventHandler(NULL),
111 fOutputEventHandler(NULL),
112 fMCtruthEventHandler(NULL),
113 fEventPool(NULL),
114 fCurrentEntry(-1),
115 fNSysInfo(0),
116 fMode(other.fMode),
117 fInitOK(other.fInitOK),
118 fIsRemote(other.fIsRemote),
119 fDebug(other.fDebug),
120 fSpecialOutputLocation(""),
121 fTasks(NULL),
122 fTopTasks(NULL),
123 fZombies(NULL),
124 fContainers(NULL),
125 fInputs(NULL),
126 fOutputs(NULL),
127 fParamCont(NULL),
128 fCommonInput(NULL),
129 fCommonOutput(NULL),
130 fSelector(NULL),
131 fGridHandler(NULL),
132 fExtraFiles(),
133 fAutoBranchHandling(other.fAutoBranchHandling),
134 fTable(),
135 fRunFromPath(0),
136 fNcalls(other.fNcalls),
137 fStatisticsMsg(other.fStatisticsMsg),
138 fRequestedBranches(other.fRequestedBranches)
139{
140// Copy constructor.
141 fTasks = new TObjArray(*other.fTasks);
142 fTopTasks = new TObjArray(*other.fTopTasks);
143 fZombies = new TObjArray(*other.fZombies);
144 fContainers = new TObjArray(*other.fContainers);
145 fInputs = new TObjArray(*other.fInputs);
146 fOutputs = new TObjArray(*other.fOutputs);
147 fParamCont = new TObjArray(*other.fParamCont);
148 fgCommonFileName = "AnalysisResults.root";
149 fgAnalysisManager = this;
150 TObject::SetObjectStat(kFALSE);
151}
152
153//______________________________________________________________________________
154AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
155{
156// Assignment
157 if (&other != this) {
158 TNamed::operator=(other);
159 fInputEventHandler = other.fInputEventHandler;
160 fOutputEventHandler = other.fOutputEventHandler;
161 fMCtruthEventHandler = other.fMCtruthEventHandler;
162 fEventPool = other.fEventPool;
163 fTree = NULL;
164 fCurrentEntry = -1;
165 fNSysInfo = other.fNSysInfo;
166 fMode = other.fMode;
167 fInitOK = other.fInitOK;
168 fIsRemote = other.fIsRemote;
169 fDebug = other.fDebug;
170 fTasks = new TObjArray(*other.fTasks);
171 fTopTasks = new TObjArray(*other.fTopTasks);
172 fZombies = new TObjArray(*other.fZombies);
173 fContainers = new TObjArray(*other.fContainers);
174 fInputs = new TObjArray(*other.fInputs);
175 fOutputs = new TObjArray(*other.fOutputs);
176 fParamCont = new TObjArray(*other.fParamCont);
177 fCommonInput = NULL;
178 fCommonOutput = NULL;
179 fSelector = NULL;
180 fGridHandler = NULL;
181 fExtraFiles = other.fExtraFiles;
182 fgCommonFileName = "AnalysisResults.root";
183 fgAnalysisManager = this;
184 fAutoBranchHandling = other.fAutoBranchHandling;
185 fTable.Clear("nodelete");
186 fRunFromPath = other.fRunFromPath;
187 fNcalls = other. fNcalls;
188 fStatisticsMsg = other.fStatisticsMsg;
189 fRequestedBranches = other.fRequestedBranches;
190 }
191 return *this;
192}
193
194//______________________________________________________________________________
195AliAnalysisManager::~AliAnalysisManager()
196{
197// Destructor.
198 if (fTasks) {fTasks->Delete(); delete fTasks;}
199 if (fTopTasks) delete fTopTasks;
200 if (fZombies) delete fZombies;
201 if (fContainers) {fContainers->Delete(); delete fContainers;}
202 if (fInputs) delete fInputs;
203 if (fOutputs) delete fOutputs;
204 if (fParamCont) delete fParamCont;
205 if (fGridHandler) delete fGridHandler;
206 if (fInputEventHandler) delete fInputEventHandler;
207 if (fOutputEventHandler) delete fOutputEventHandler;
208 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
209 if (fEventPool) delete fEventPool;
210 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
211 TObject::SetObjectStat(kTRUE);
212}
213
214//______________________________________________________________________________
215Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
216{
217// Read one entry of the tree or a whole branch.
218 fCurrentEntry = entry;
219 if (!fAutoBranchHandling)
220 return entry;
221 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
222}
223
224//______________________________________________________________________________
225Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
226{
227// Attempt to extract run number from input data path. Works only for paths to
228// alice data in alien.
229// sim: /alice/sim/<production>/run_no/...
230// data: /alice/data/year/period/000run_no/... (ESD or AOD)
231 TString s(path);
232 TString srun;
233 Int_t run = 0;
234 Int_t index = s.Index("/alice/sim");
235 if (index >= 0) {
236 for (Int_t i=0; i<3; i++) {
237 index = s.Index("/", index+1);
238 if (index<0) return 0;
239 }
240 srun = s(index+1,6);
241 run = atoi(srun);
242 }
243 index = s.Index("/alice/data");
244 if (index >= 0) {
245 for (Int_t i=0; i<4; i++) {
246 index = s.Index("/", index+1);
247 if (index<0) return 0;
248 }
249 srun = s(index+1,9);
250 run = atoi(srun);
251 }
252 return run;
253}
254
255//______________________________________________________________________________
256Bool_t AliAnalysisManager::Init(TTree *tree)
257{
258 // The Init() function is called when the selector needs to initialize
259 // a new tree or chain. Typically here the branch addresses of the tree
260 // will be set. It is normaly not necessary to make changes to the
261 // generated code, but the routine can be extended by the user if needed.
262 // Init() will be called many times when running with PROOF.
263 Bool_t init = kFALSE;
264 if (!tree) return kFALSE; // Should not happen - protected in selector caller
265 if (fDebug > 1) {
266 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
267 }
268 // Call InitTree of EventHandler
269 if (fOutputEventHandler) {
270 if (fMode == kProofAnalysis) {
271 init = fOutputEventHandler->Init(0x0, "proof");
272 } else {
273 init = fOutputEventHandler->Init(0x0, "local");
274 }
275 if (!init) {
276 Error("Init", "Output event handler failed to initialize");
277 return kFALSE;
278 }
279 }
280
281 if (fInputEventHandler) {
282 if (fMode == kProofAnalysis) {
283 init = fInputEventHandler->Init(tree, "proof");
284 } else {
285 init = fInputEventHandler->Init(tree, "local");
286 }
287 if (!init) {
288 Error("Init", "Input event handler failed to initialize tree");
289 return kFALSE;
290 }
291 } else {
292 // If no input event handler we need to get the tree once
293 // for the chain
294 if(!tree->GetTree()) {
295 Long64_t readEntry = tree->LoadTree(0);
296 if (readEntry == -2) {
297 Error("Init", "Input tree has no entry. Exiting");
298 return kFALSE;
299 }
300 }
301 }
302
303 if (fMCtruthEventHandler) {
304 if (fMode == kProofAnalysis) {
305 init = fMCtruthEventHandler->Init(0x0, "proof");
306 } else {
307 init = fMCtruthEventHandler->Init(0x0, "local");
308 }
309 if (!init) {
310 Error("Init", "MC event handler failed to initialize");
311 return kFALSE;
312 }
313 }
314
315 if (!fInitOK) InitAnalysis();
316 if (!fInitOK) return kFALSE;
317 fTree = tree;
318 fTable.Rehash(100);
319 AliAnalysisDataContainer *top = fCommonInput;
320 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
321 if (!top) {
322 Error("Init","No top input container !");
323 return kFALSE;
324 }
325 top->SetData(tree);
326 CheckBranches(kFALSE);
327 if (fDebug > 1) {
328 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
329 }
330 return kTRUE;
331}
332
333//______________________________________________________________________________
334void AliAnalysisManager::SlaveBegin(TTree *tree)
335{
336 // The SlaveBegin() function is called after the Begin() function.
337 // When running with PROOF SlaveBegin() is called on each slave server.
338 // The tree argument is deprecated (on PROOF 0 is passed).
339 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
340 static Bool_t isCalled = kFALSE;
341 Bool_t init = kFALSE;
342 Bool_t initOK = kTRUE;
343 TString msg;
344 TDirectory *curdir = gDirectory;
345 // Call SlaveBegin only once in case of mixing
346 if (isCalled && fMode==kMixingAnalysis) return;
347 gROOT->cd();
348 // Call Init of EventHandler
349 if (fOutputEventHandler) {
350 if (fMode == kProofAnalysis) {
351 // Merging AOD's in PROOF via TProofOutputFile
352 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
353 init = fOutputEventHandler->Init("proof");
354 if (!init) msg = "Failed to initialize output handler on worker";
355 } else {
356 init = fOutputEventHandler->Init("local");
357 if (!init) msg = "Failed to initialize output handler";
358 }
359 initOK &= init;
360 if (!fSelector) Error("SlaveBegin", "Selector not set");
361 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
362 }
363 gROOT->cd();
364 if (fInputEventHandler) {
365 fInputEventHandler->SetInputTree(tree);
366 if (fMode == kProofAnalysis) {
367 init = fInputEventHandler->Init("proof");
368 if (!init) msg = "Failed to initialize input handler on worker";
369 } else {
370 init = fInputEventHandler->Init("local");
371 if (!init) msg = "Failed to initialize input handler";
372 }
373 initOK &= init;
374 if (!fSelector) Error("SlaveBegin", "Selector not set");
375 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
376 }
377 gROOT->cd();
378 if (fMCtruthEventHandler) {
379 if (fMode == kProofAnalysis) {
380 init = fMCtruthEventHandler->Init("proof");
381 if (!init) msg = "Failed to initialize MC handler on worker";
382 } else {
383 init = fMCtruthEventHandler->Init("local");
384 if (!init) msg = "Failed to initialize MC handler";
385 }
386 initOK &= init;
387 if (!fSelector) Error("SlaveBegin", "Selector not set");
388 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
389 }
390 if (curdir) curdir->cd();
391 isCalled = kTRUE;
392 if (!initOK) return;
393 TIter next(fTasks);
394 AliAnalysisTask *task;
395 // Call CreateOutputObjects for all tasks
396 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
397 Bool_t dirStatus = TH1::AddDirectoryStatus();
398 Int_t itask = 0;
399 while ((task=(AliAnalysisTask*)next())) {
400 gROOT->cd();
401 // Start with memory as current dir and make sure by default histograms do not get attached to files.
402 TH1::AddDirectory(kFALSE);
403 task->CreateOutputObjects();
404 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
405 itask++;
406 }
407 TH1::AddDirectory(dirStatus);
408 if (curdir) curdir->cd();
409 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
410}
411
412//______________________________________________________________________________
413Bool_t AliAnalysisManager::Notify()
414{
415 // The Notify() function is called when a new file is opened. This
416 // can be either for a new TTree in a TChain or when when a new TTree
417 // is started when using PROOF. It is normaly not necessary to make changes
418 // to the generated code, but the routine can be extended by the
419 // user if needed. The return value is currently not used.
420 if (!fTree) return kFALSE;
421
422 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
423 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
424
425 TFile *curfile = fTree->GetCurrentFile();
426 if (!curfile) {
427 Error("Notify","No current file");
428 return kFALSE;
429 }
430
431 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
432 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
433 if (run) SetRunFromPath(run);
434 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
435 TIter next(fTasks);
436 AliAnalysisTask *task;
437
438 // Call Notify of the event handlers
439 if (fInputEventHandler) {
440 fInputEventHandler->Notify(curfile->GetName());
441 }
442
443 if (fOutputEventHandler) {
444 fOutputEventHandler->Notify(curfile->GetName());
445 }
446
447 if (fMCtruthEventHandler) {
448 fMCtruthEventHandler->Notify(curfile->GetName());
449 }
450
451 // Call Notify for all tasks
452 while ((task=(AliAnalysisTask*)next()))
453 task->Notify();
454
455 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
456 return kTRUE;
457}
458
459//______________________________________________________________________________
460Bool_t AliAnalysisManager::Process(Long64_t entry)
461{
462 // The Process() function is called for each entry in the tree (or possibly
463 // keyed object in the case of PROOF) to be processed. The entry argument
464 // specifies which entry in the currently loaded tree is to be processed.
465 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
466 // to read either all or the required parts of the data. When processing
467 // keyed objects with PROOF, the object is already loaded and is available
468 // via the fObject pointer.
469 //
470 // This function should contain the "body" of the analysis. It can contain
471 // simple or elaborate selection criteria, run algorithms on the data
472 // of the event and typically fill histograms.
473
474 // WARNING when a selector is used with a TChain, you must use
475 // the pointer to the current TTree to call GetEntry(entry).
476 // The entry is always the local entry number in the current tree.
477 // Assuming that fChain is the pointer to the TChain being processed,
478 // use fChain->GetTree()->GetEntry(entry).
479 if (fDebug > 1) printf("->AliAnalysisManager::Process(%lld)\n", entry);
480
481 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
482 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
483 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
484
485 GetEntry(entry);
486
487 if (fInputEventHandler) fInputEventHandler ->GetEntry();
488
489 ExecAnalysis();
490 if (fDebug > 1) printf("<-AliAnalysisManager::Process()\n");
491 return kTRUE;
492}
493
494//______________________________________________________________________________
495void AliAnalysisManager::PackOutput(TList *target)
496{
497 // Pack all output data containers in the output list. Called at SlaveTerminate
498 // stage in PROOF case for each slave.
499 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
500 if (!target) {
501 Error("PackOutput", "No target. Exiting.");
502 return;
503 }
504 TDirectory *cdir = gDirectory;
505 gROOT->cd();
506 if (fInputEventHandler) fInputEventHandler ->Terminate();
507 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
508 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
509 gROOT->cd();
510
511 // Call FinishTaskOutput() for each event loop task (not called for
512 // post-event loop tasks - use Terminate() fo those)
513 TIter nexttask(fTasks);
514 AliAnalysisTask *task;
515 while ((task=(AliAnalysisTask*)nexttask())) {
516 if (!task->IsPostEventLoop()) {
517 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
518 task->FinishTaskOutput();
519 gROOT->cd();
520 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
521 }
522 }
523 // Write statistics message on the workers.
524 WriteStatisticsMsg(fNcalls);
525
526 if (fMode == kProofAnalysis) {
527 TIter next(fOutputs);
528 AliAnalysisDataContainer *output;
529 Bool_t isManagedByHandler = kFALSE;
530 TList filestmp;
531 filestmp.SetOwner();
532 while ((output=(AliAnalysisDataContainer*)next())) {
533 // Do not consider outputs of post event loop tasks
534 isManagedByHandler = kFALSE;
535 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
536 const char *filename = output->GetFileName();
537 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
538 isManagedByHandler = kTRUE;
539 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
540 filename = fOutputEventHandler->GetOutputFileName();
541 }
542 // Check if data was posted to this container. If not, issue an error.
543 if (!output->GetData() && !isManagedByHandler) {
544 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
545 continue;
546 }
547 if (!output->IsSpecialOutput()) {
548 // Normal outputs
549 if (strlen(filename) && !isManagedByHandler) {
550 // Backup current folder
551 TDirectory *opwd = gDirectory;
552 // File resident outputs.
553 // Check first if the file exists.
554 TString openoption = "RECREATE";
555 Bool_t firsttime = kTRUE;
556 if (filestmp.FindObject(output->GetFileName())) {
557 firsttime = kFALSE;
558 } else {
559 filestmp.Add(new TNamed(output->GetFileName(),""));
560 }
561 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
562// TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
563 // Save data to file, then close.
564 if (output->GetData()->InheritsFrom(TCollection::Class())) {
565 // If data is a collection, we set the name of the collection
566 // as the one of the container and we save as a single key.
567 TCollection *coll = (TCollection*)output->GetData();
568 coll->SetName(output->GetName());
569// coll->Write(output->GetName(), TObject::kSingleKey);
570 } else {
571 if (output->GetData()->InheritsFrom(TTree::Class())) {
572 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
573 // Save data to file, then close.
574 TTree *tree = (TTree*)output->GetData();
575 // Check if tree is in memory
576 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
577 tree->AutoSave();
578 file->Close();
579 } else {
580// output->GetData()->Write();
581 }
582 }
583 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
584// if (fDebug > 2) {
585// printf(" file %s listing content:\n", filename);
586// file->ls();
587// }
588 // Clear file list to release object ownership to user.
589// file->Clear();
590// file->Close();
591 output->SetFile(NULL);
592 // Restore current directory
593 if (opwd) opwd->cd();
594 } else {
595 // Memory-resident outputs
596 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
597 }
598 AliAnalysisDataWrapper *wrap = 0;
599 if (isManagedByHandler) {
600 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
601 wrap->SetName(output->GetName());
602 }
603 else wrap =output->ExportData();
604 // Output wrappers must NOT delete data after merging - the user owns them
605 wrap->SetDeleteData(kFALSE);
606 target->Add(wrap);
607 } else {
608 // Special outputs. The file must be opened and connected to the container.
609 TDirectory *opwd = gDirectory;
610 TFile *file = output->GetFile();
611 if (!file) {
612 AliAnalysisTask *producer = output->GetProducer();
613 Fatal("PackOutput",
614 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
615 output->GetFileName(), output->GetName(), producer->ClassName());
616 continue;
617 }
618 TString outFilename = file->GetName();
619 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
620 if (isManagedByHandler) {
621 // Terminate IO for files managed by the output handler
622 // file->Write() moved to AOD handler (A.G. 11.01.10)
623// if (file) file->Write();
624 if (file && fDebug > 2) {
625 printf(" handled file %s listing content:\n", file->GetName());
626 file->ls();
627 }
628 fOutputEventHandler->TerminateIO();
629 } else {
630 file->cd();
631 // Release object ownership to users after writing data to file
632 if (output->GetData()->InheritsFrom(TCollection::Class())) {
633 // If data is a collection, we set the name of the collection
634 // as the one of the container and we save as a single key.
635 TCollection *coll = (TCollection*)output->GetData();
636 coll->SetName(output->GetName());
637 coll->Write(output->GetName(), TObject::kSingleKey);
638 } else {
639 if (output->GetData()->InheritsFrom(TTree::Class())) {
640 TTree *tree = (TTree*)output->GetData();
641 tree->SetDirectory(file);
642 tree->AutoSave();
643 } else {
644 output->GetData()->Write();
645 }
646 }
647 if (fDebug > 2) {
648 printf(" file %s listing content:\n", output->GetFileName());
649 file->ls();
650 }
651 // Clear file list to release object ownership to user.
652// file->Clear();
653 file->Close();
654 output->SetFile(NULL);
655 }
656 // Restore current directory
657 if (opwd) opwd->cd();
658 // Check if a special output location was provided or the output files have to be merged
659 if (strlen(fSpecialOutputLocation.Data())) {
660 TString remote = fSpecialOutputLocation;
661 remote += "/";
662 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
663 if (remote.BeginsWith("alien:")) {
664 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
665 remote += outFilename;
666 remote.ReplaceAll(".root", Form("_%d.root", gid));
667 } else {
668 remote += Form("%s_%d_", gSystem->HostName(), gid);
669 remote += outFilename;
670 }
671 if (fDebug > 1)
672 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
673 output->GetName(), remote.Data());
674 TFile::Cp ( outFilename.Data(), remote.Data() );
675 // Copy extra outputs
676 if (fExtraFiles.Length() && isManagedByHandler) {
677 TObjArray *arr = fExtraFiles.Tokenize(" ");
678 TObjString *os;
679 TIter nextfilename(arr);
680 while ((os=(TObjString*)nextfilename())) {
681 outFilename = os->GetString();
682 remote = fSpecialOutputLocation;
683 remote += "/";
684 if (remote.BeginsWith("alien://")) {
685 remote += outFilename;
686 remote.ReplaceAll(".root", Form("_%d.root", gid));
687 } else {
688 remote += Form("%s_%d_", gSystem->HostName(), gid);
689 remote += outFilename;
690 }
691 if (fDebug > 1)
692 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
693 outFilename.Data(), remote.Data());
694 TFile::Cp ( outFilename.Data(), remote.Data() );
695 }
696 delete arr;
697 }
698 } else {
699 // No special location specified-> use TProofOutputFile as merging utility
700 // The file at this output slot must be opened in CreateOutputObjects
701 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
702 }
703 }
704 }
705 }
706 cdir->cd();
707 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
708}
709
710//______________________________________________________________________________
711void AliAnalysisManager::ImportWrappers(TList *source)
712{
713// Import data in output containers from wrappers coming in source.
714 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
715 TIter next(fOutputs);
716 AliAnalysisDataContainer *cont;
717 AliAnalysisDataWrapper *wrap;
718 Int_t icont = 0;
719 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
720 TDirectory *cdir = gDirectory;
721 while ((cont=(AliAnalysisDataContainer*)next())) {
722 wrap = 0;
723 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
724 if (cont->IsRegisterDataset()) continue;
725 const char *filename = cont->GetFileName();
726 Bool_t isManagedByHandler = kFALSE;
727 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
728 isManagedByHandler = kTRUE;
729 filename = fOutputEventHandler->GetOutputFileName();
730 }
731 if (cont->IsSpecialOutput() || inGrid) {
732 if (strlen(fSpecialOutputLocation.Data())) continue;
733 // Copy merged file from PROOF scratch space.
734 // In case of grid the files are already in the current directory.
735 if (!inGrid) {
736 if (isManagedByHandler && fExtraFiles.Length()) {
737 // Copy extra registered dAOD files.
738 TObjArray *arr = fExtraFiles.Tokenize(" ");
739 TObjString *os;
740 TIter nextfilename(arr);
741 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
742 delete arr;
743 }
744 if (!GetFileFromWrapper(filename, source)) continue;
745 }
746 // Normally we should connect data from the copied file to the
747 // corresponding output container, but it is not obvious how to do this
748 // automatically if several objects in file...
749 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
750 if (!f) f = TFile::Open(filename, "READ");
751 if (!f) {
752 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
753 continue;
754 }
755 TObject *obj = 0;
756 // Cd to the directory pointed by the container
757 TString folder = cont->GetFolderName();
758 if (!folder.IsNull()) f->cd(folder);
759 // Try to fetch first an object having the container name.
760 obj = gDirectory->Get(cont->GetName());
761 if (!obj) {
762 Warning("ImportWrappers", "Could not import object of type:%s for container %s in file %s:%s.\n Object will not be available in Terminate(). Try if possible to name the output object as the container (%s) or to embed it in a TList",
763 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
764 continue;
765 }
766 wrap = new AliAnalysisDataWrapper(obj);
767 wrap->SetDeleteData(kFALSE);
768 }
769 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
770 if (!wrap) {
771 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
772 continue;
773 }
774 icont++;
775 if (fDebug > 1) {
776 printf(" Importing data for container %s\n", cont->GetName());
777 if (strlen(filename)) printf(" -> file %s\n", filename);
778 else printf("\n");
779 }
780 cont->ImportData(wrap);
781 }
782 if (cdir) cdir->cd();
783 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
784}
785
786//______________________________________________________________________________
787void AliAnalysisManager::UnpackOutput(TList *source)
788{
789 // Called by AliAnalysisSelector::Terminate only on the client.
790 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
791 if (!source) {
792 Error("UnpackOutput", "No target. Exiting.");
793 return;
794 }
795 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
796
797 if (fMode == kProofAnalysis) ImportWrappers(source);
798
799 TIter next(fOutputs);
800 AliAnalysisDataContainer *output;
801 while ((output=(AliAnalysisDataContainer*)next())) {
802 if (!output->GetData()) continue;
803 // Check if there are client tasks that run post event loop
804 if (output->HasConsumers()) {
805 // Disable event loop semaphore
806 output->SetPostEventLoop(kTRUE);
807 TObjArray *list = output->GetConsumers();
808 Int_t ncons = list->GetEntriesFast();
809 for (Int_t i=0; i<ncons; i++) {
810 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
811 task->CheckNotify(kTRUE);
812 // If task is active, execute it
813 if (task->IsPostEventLoop() && task->IsActive()) {
814 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
815 task->ExecuteTask();
816 }
817 }
818 }
819 }
820 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
821}
822
823//______________________________________________________________________________
824void AliAnalysisManager::Terminate()
825{
826 // The Terminate() function is the last function to be called during
827 // a query. It always runs on the client, it can be used to present
828 // the results graphically.
829 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
830 TDirectory *cdir = gDirectory;
831 gROOT->cd();
832 AliAnalysisTask *task;
833 AliAnalysisDataContainer *output;
834 TIter next(fTasks);
835 TStopwatch timer;
836 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
837 // Call Terminate() for tasks
838 Int_t itask = 0;
839 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
840 // Save all the canvases produced by the Terminate
841 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
842 task->Terminate();
843 gROOT->cd();
844 if (getsysInfo)
845 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
846 itask++;
847 if (TObject::TestBit(kSaveCanvases)) {
848 if (!gROOT->IsBatch()) {
849 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
850 timer.Start();
851 while (timer.CpuTime()<5) {
852 timer.Continue();
853 gSystem->ProcessEvents();
854 }
855 }
856 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
857 if (iend==0) continue;
858 TCanvas *canvas;
859 for (Int_t ipict=0; ipict<iend; ipict++) {
860 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
861 if (!canvas) continue;
862 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
863 }
864 gROOT->GetListOfCanvases()->Delete();
865 }
866 }
867 //
868 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
869 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
870 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
871 gROOT->cd();
872 TObjArray *allOutputs = new TObjArray();
873 Int_t icont;
874 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
875 if (!IsSkipTerminate())
876 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
877 TIter next1(allOutputs);
878 TString handlerFile = "";
879 TString extraOutputs = "";
880 if (fOutputEventHandler) {
881 handlerFile = fOutputEventHandler->GetOutputFileName();
882 extraOutputs = fOutputEventHandler->GetExtraOutputs();
883 }
884 icont = 0;
885 TList filestmp;
886 while ((output=(AliAnalysisDataContainer*)next1())) {
887 // Special outputs or grid files have the files already closed and written.
888 icont++;
889 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
890 if (fMode == kProofAnalysis) {
891 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
892 }
893 const char *filename = output->GetFileName();
894 TString openoption = "RECREATE";
895 if (!(strcmp(filename, "default"))) continue;
896 if (!strlen(filename)) continue;
897 if (!output->GetData()) continue;
898 TDirectory *opwd = gDirectory;
899 TFile *file = output->GetFile();
900 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
901 if (!file) {
902 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
903 Bool_t firsttime = kTRUE;
904 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
905 firsttime = kFALSE;
906 } else {
907 filestmp.Add(new TNamed(filename,""));
908 }
909 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
910 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
911 file = new TFile(filename, openoption);
912 } else {
913 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
914 openoption = file->GetOption();
915 if (openoption == "READ") {
916 if (fDebug>1) printf("...reopening in UPDATE mode\n");
917 file->ReOpen("UPDATE");
918 }
919 }
920 if (file->IsZombie()) {
921 Error("Terminate", "Cannot open output file %s", filename);
922 continue;
923 }
924 output->SetFile(file);
925 file->cd();
926 // Check for a folder request
927 TString dir = output->GetFolderName();
928 if (!dir.IsNull()) {
929 if (!file->GetDirectory(dir)) file->mkdir(dir);
930 file->cd(dir);
931 }
932 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
933 if (output->GetData()->InheritsFrom(TCollection::Class())) {
934 // If data is a collection, we set the name of the collection
935 // as the one of the container and we save as a single key.
936 TCollection *coll = (TCollection*)output->GetData();
937 coll->SetName(output->GetName());
938 coll->Write(output->GetName(), TObject::kSingleKey);
939 } else {
940 if (output->GetData()->InheritsFrom(TTree::Class())) {
941 TTree *tree = (TTree*)output->GetData();
942 tree->SetDirectory(gDirectory);
943 tree->AutoSave();
944 } else {
945 output->GetData()->Write();
946 }
947 }
948 if (opwd) opwd->cd();
949 }
950 gROOT->cd();
951 next1.Reset();
952 while ((output=(AliAnalysisDataContainer*)next1())) {
953 // Close all files at output
954 TDirectory *opwd = gDirectory;
955 if (output->GetFile()) {
956 // Clear file list to release object ownership to user.
957// output->GetFile()->Clear();
958 output->GetFile()->Close();
959 output->SetFile(NULL);
960 // Copy merged outputs in alien if requested
961 if (fSpecialOutputLocation.Length() &&
962 fSpecialOutputLocation.BeginsWith("alien://")) {
963 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
964 TFile::Cp(output->GetFile()->GetName(),
965 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
966 }
967 }
968 if (opwd) opwd->cd();
969 }
970 delete allOutputs;
971 //Write statistics information on the client
972 WriteStatisticsMsg(fNcalls);
973 if (getsysInfo) {
974 TDirectory *crtdir = gDirectory;
975 TFile f("syswatch.root", "RECREATE");
976 TH1 *hist;
977 TString cut;
978 if (!f.IsZombie()) {
979 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
980 tree->SetName("syswatch");
981 tree->SetMarkerStyle(kCircle);
982 tree->SetMarkerColor(kBlue);
983 tree->SetMarkerSize(0.5);
984 if (!gROOT->IsBatch()) {
985 tree->SetAlias("event", "id0");
986 tree->SetAlias("task", "id1");
987 tree->SetAlias("stage", "id2");
988 // Already defined aliases
989 // tree->SetAlias("deltaT","stampSec-stampOldSec");
990 // tree->SetAlias("T","stampSec-first");
991 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
992 // tree->SetAlias("VM","pI.fMemVirtual");
993 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
994 Int_t npads = 1 /*COO plot for all tasks*/ +
995 fTopTasks->GetEntries() /*Exec plot per task*/ +
996 1 /*Terminate plot for all tasks*/ +
997 1; /*vm plot*/
998
999 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1000 if (npads<iopt*(iopt+1))
1001 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1002 else
1003 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1004 Int_t ipad = 1;
1005 // draw the plot of deltaVM for Exec for each task
1006 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1007 task = (AliAnalysisTask*)fTopTasks->At(itask);
1008 canvas->cd(ipad++);
1009 cut = Form("task==%d && stage==1", itask);
1010 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1011 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1012 if (hist) {
1013 hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName()));
1014 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1015 }
1016 }
1017 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1018 canvas->cd(ipad++);
1019 tree->SetMarkerStyle(kFullTriangleUp);
1020 tree->SetMarkerColor(kRed);
1021 tree->SetMarkerSize(0.8);
1022 cut = "task>=0 && task<1000 && stage==0";
1023 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1024 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1025 if (hist) {
1026 hist->SetTitle("Memory in CreateOutputObjects()");
1027 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1028 hist->GetXaxis()->SetTitle("task");
1029 }
1030 // draw the plot of deltaVM for Terminate for all tasks
1031 canvas->cd(ipad++);
1032 tree->SetMarkerStyle(kOpenSquare);
1033 tree->SetMarkerColor(kMagenta);
1034 cut = "task>=0 && task<1000 && stage==2";
1035 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1036 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1037 if (hist) {
1038 hist->SetTitle("Memory in Terminate()");
1039 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1040 hist->GetXaxis()->SetTitle("task");
1041 }
1042 // Full VM profile
1043 canvas->cd(ipad++);
1044 tree->SetMarkerStyle(kFullCircle);
1045 tree->SetMarkerColor(kGreen);
1046 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1047 tree->Draw("VM:event",cut,"", 1234567890, 0);
1048 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1049 if (hist) {
1050 hist->SetTitle("Virtual memory");
1051 hist->GetYaxis()->SetTitle("VM [kB]");
1052 }
1053 canvas->Modified();
1054 }
1055 tree->SetMarkerStyle(kCircle);
1056 tree->SetMarkerColor(kBlue);
1057 tree->SetMarkerSize(0.5);
1058 tree->Write();
1059 f.Close();
1060 delete tree;
1061 }
1062 if (crtdir) crtdir->cd();
1063 }
1064 // Validate the output files
1065 if (ValidateOutputFiles()) {
1066 ofstream out;
1067 out.open("outputs_valid", ios::out);
1068 out.close();
1069 }
1070 cdir->cd();
1071 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1072}
1073//______________________________________________________________________________
1074void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1075{
1076// Profiles the task having the itop index in the list of top (first level) tasks.
1077 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1078 if (!task) {
1079 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1080 return;
1081 }
1082 ProfileTask(task->GetName(), option);
1083}
1084
1085//______________________________________________________________________________
1086void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1087{
1088// Profile a managed task after the execution of the analysis in case NSysInfo
1089// was used.
1090 if (gSystem->AccessPathName("syswatch.root")) {
1091 Error("ProfileTask", "No file syswatch.root found in the current directory");
1092 return;
1093 }
1094 if (gROOT->IsBatch()) return;
1095 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1096 if (!task) {
1097 Error("ProfileTask", "No top task named %s known by the manager.", name);
1098 return;
1099 }
1100 Int_t itop = fTopTasks->IndexOf(task);
1101 Int_t itask = fTasks->IndexOf(task);
1102 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1103 TDirectory *cdir = gDirectory;
1104 TFile f("syswatch.root");
1105 TTree *tree = (TTree*)f.Get("syswatch");
1106 if (!tree) {
1107 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1108 return;
1109 }
1110 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1111 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1112 canvas->Divide(2, 2, 0.01, 0.01);
1113 Int_t ipad = 1;
1114 TString cut;
1115 TH1 *hist;
1116 // VM profile for COO and Terminate methods
1117 canvas->cd(ipad++);
1118 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1119 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1120 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1121 if (hist) {
1122 hist->SetTitle("Alocated VM[kB] for COO and Terminate");
1123 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1124 hist->GetXaxis()->SetTitle("method");
1125 }
1126 // CPU profile per event
1127 canvas->cd(ipad++);
1128 cut = Form("task==%d && stage==1",itop);
1129 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1130 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1131 if (hist) {
1132 hist->SetTitle("Execution time per event");
1133 hist->GetYaxis()->SetTitle("CPU/event [s]");
1134 }
1135 // VM profile for Exec
1136 canvas->cd(ipad++);
1137 cut = Form("task==%d && stage==1",itop);
1138 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1139 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1140 if (hist) {
1141 hist->SetTitle("Alocated VM[kB] per event");
1142 hist->GetYaxis()->SetTitle("deltaVM [kB]");
1143 }
1144 canvas->Modified();
1145 delete tree;
1146 f.Close();
1147 if (cdir) cdir->cd();
1148}
1149
1150//______________________________________________________________________________
1151void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1152{
1153// Adds a user task to the global list of tasks.
1154 if (fTasks->FindObject(task)) {
1155 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1156 return;
1157 }
1158 task->SetActive(kFALSE);
1159 fTasks->Add(task);
1160}
1161
1162//______________________________________________________________________________
1163AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1164{
1165// Retreive task by name.
1166 if (!fTasks) return NULL;
1167 return (AliAnalysisTask*)fTasks->FindObject(name);
1168}
1169
1170//______________________________________________________________________________
1171AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1172 TClass *datatype, EAliAnalysisContType type, const char *filename)
1173{
1174// Create a data container of a certain type. Types can be:
1175// kExchangeContainer = 0, used to exchange data between tasks
1176// kInputContainer = 1, used to store input data
1177// kOutputContainer = 2, used for writing result to a file
1178// filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1179// the output object to a folder inside the output file
1180 if (fContainers->FindObject(name)) {
1181 Error("CreateContainer","A container named %s already defined !",name);
1182 return NULL;
1183 }
1184 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1185 fContainers->Add(cont);
1186 switch (type) {
1187 case kInputContainer:
1188 fInputs->Add(cont);
1189 break;
1190 case kOutputContainer:
1191 fOutputs->Add(cont);
1192 if (filename && strlen(filename)) {
1193 cont->SetFileName(filename);
1194 cont->SetDataOwned(kFALSE); // data owned by the file
1195 }
1196 break;
1197 case kParamContainer:
1198 fParamCont->Add(cont);
1199 if (filename && strlen(filename)) {
1200 cont->SetFileName(filename);
1201 cont->SetDataOwned(kFALSE); // data owned by the file
1202 }
1203 break;
1204 case kExchangeContainer:
1205 break;
1206 }
1207 return cont;
1208}
1209
1210//______________________________________________________________________________
1211Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1212 AliAnalysisDataContainer *cont)
1213{
1214// Connect input of an existing task to a data container.
1215 if (!task) {
1216 Error("ConnectInput", "Task pointer is NULL");
1217 return kFALSE;
1218 }
1219 if (!fTasks->FindObject(task)) {
1220 AddTask(task);
1221 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1222 }
1223 Bool_t connected = task->ConnectInput(islot, cont);
1224 return connected;
1225}
1226
1227//______________________________________________________________________________
1228Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1229 AliAnalysisDataContainer *cont)
1230{
1231// Connect output of an existing task to a data container.
1232 if (!task) {
1233 Error("ConnectOutput", "Task pointer is NULL");
1234 return kFALSE;
1235 }
1236 if (!fTasks->FindObject(task)) {
1237 AddTask(task);
1238 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1239 }
1240 Bool_t connected = task->ConnectOutput(islot, cont);
1241 return connected;
1242}
1243
1244//______________________________________________________________________________
1245void AliAnalysisManager::CleanContainers()
1246{
1247// Clean data from all containers that have already finished all client tasks.
1248 TIter next(fContainers);
1249 AliAnalysisDataContainer *cont;
1250 while ((cont=(AliAnalysisDataContainer *)next())) {
1251 if (cont->IsOwnedData() &&
1252 cont->IsDataReady() &&
1253 cont->ClientsExecuted()) cont->DeleteData();
1254 }
1255}
1256
1257//______________________________________________________________________________
1258Bool_t AliAnalysisManager::InitAnalysis()
1259{
1260// Initialization of analysis chain of tasks. Should be called after all tasks
1261// and data containers are properly connected
1262 // Reset flag and remove valid_outputs file if exists
1263 fInitOK = kFALSE;
1264 if (!gSystem->AccessPathName("outputs_valid"))
1265 gSystem->Unlink("outputs_valid");
1266 // Check for top tasks (depending only on input data containers)
1267 if (!fTasks->First()) {
1268 Error("InitAnalysis", "Analysis has no tasks !");
1269 return kFALSE;
1270 }
1271 TIter next(fTasks);
1272 AliAnalysisTask *task;
1273 AliAnalysisDataContainer *cont;
1274 Int_t ntop = 0;
1275 Int_t nzombies = 0;
1276 Bool_t iszombie = kFALSE;
1277 Bool_t istop = kTRUE;
1278 Int_t i;
1279 while ((task=(AliAnalysisTask*)next())) {
1280 istop = kTRUE;
1281 iszombie = kFALSE;
1282 Int_t ninputs = task->GetNinputs();
1283 for (i=0; i<ninputs; i++) {
1284 cont = task->GetInputSlot(i)->GetContainer();
1285 if (!cont) {
1286 if (!iszombie) {
1287 task->SetZombie();
1288 fZombies->Add(task);
1289 nzombies++;
1290 iszombie = kTRUE;
1291 }
1292 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1293 i, task->GetName());
1294 }
1295 if (iszombie) continue;
1296 // Check if cont is an input container
1297 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1298 // Connect to parent task
1299 }
1300 if (istop) {
1301 ntop++;
1302 fTopTasks->Add(task);
1303 }
1304 }
1305 if (!ntop) {
1306 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1307 return kFALSE;
1308 }
1309 // Check now if there are orphan tasks
1310 for (i=0; i<ntop; i++) {
1311 task = (AliAnalysisTask*)fTopTasks->At(i);
1312 task->SetUsed();
1313 }
1314 Int_t norphans = 0;
1315 next.Reset();
1316 while ((task=(AliAnalysisTask*)next())) {
1317 if (!task->IsUsed()) {
1318 norphans++;
1319 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1320 }
1321 }
1322 // Check the task hierarchy (no parent task should depend on data provided
1323 // by a daughter task)
1324 for (i=0; i<ntop; i++) {
1325 task = (AliAnalysisTask*)fTopTasks->At(i);
1326 if (task->CheckCircularDeps()) {
1327 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1328 PrintStatus("dep");
1329 return kFALSE;
1330 }
1331 }
1332 // Check that all containers feeding post-event loop tasks are in the outputs list
1333 TIter nextcont(fContainers); // loop over all containers
1334 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1335 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1336 if (cont->HasConsumers()) {
1337 // Check if one of the consumers is post event loop
1338 TIter nextconsumer(cont->GetConsumers());
1339 while ((task=(AliAnalysisTask*)nextconsumer())) {
1340 if (task->IsPostEventLoop()) {
1341 fOutputs->Add(cont);
1342 break;
1343 }
1344 }
1345 }
1346 }
1347 }
1348 // Check if all special output containers have a file name provided
1349 TIter nextout(fOutputs);
1350 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1351 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1352 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1353 return kFALSE;
1354 }
1355 }
1356 // Initialize requested branch list if needed
1357 if (!fAutoBranchHandling) {
1358 next.Reset();
1359 while ((task=(AliAnalysisTask*)next())) {
1360 if (!task->HasBranches()) {
1361 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches.\nUse: fBranchNames = \"ESD:br1,br2,...,brN AOD:bra1,bra2,...,braM\"",
1362 task->GetName(), task->ClassName());
1363 return kFALSE;
1364 }
1365 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1366 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1367 return kFALSE;
1368 }
1369 TString taskbranches;
1370 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1371 if (taskbranches.IsNull()) {
1372 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1373 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1374 return kFALSE;
1375 }
1376 AddBranches(taskbranches);
1377 }
1378 }
1379 fInitOK = kTRUE;
1380 return kTRUE;
1381}
1382
1383//______________________________________________________________________________
1384void AliAnalysisManager::AddBranches(const char *branches)
1385{
1386// Add branches to the existing fRequestedBranches.
1387 TString br(branches);
1388 TObjArray *arr = br.Tokenize(",");
1389 TIter next(arr);
1390 TObject *obj;
1391 while ((obj=next())) {
1392 if (!fRequestedBranches.Contains(obj->GetName())) {
1393 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1394 fRequestedBranches += obj->GetName();
1395 }
1396 }
1397 if (arr) delete arr;
1398}
1399
1400//______________________________________________________________________________
1401void AliAnalysisManager::CheckBranches(Bool_t load)
1402{
1403// The method checks the input branches to be loaded during the analysis.
1404 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1405 TObjArray *arr = fRequestedBranches.Tokenize(",");
1406 TIter next(arr);
1407 TObject *obj;
1408 while ((obj=next())) {
1409 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1410 if (!br) {
1411 br = fTree->GetBranch(obj->GetName());
1412 if (!br) {
1413 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1414 continue;
1415 }
1416 }
1417 fTable.Add(br);
1418 if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry());
1419 }
1420}
1421
1422//______________________________________________________________________________
1423void AliAnalysisManager::PrintStatus(Option_t *option) const
1424{
1425// Print task hierarchy.
1426 if (!fInitOK) {
1427 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1428 return;
1429 }
1430 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1431 if (getsysInfo)
1432 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1433 TIter next(fTopTasks);
1434 AliAnalysisTask *task;
1435 while ((task=(AliAnalysisTask*)next()))
1436 task->PrintTask(option);
1437 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1438 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1439}
1440
1441//______________________________________________________________________________
1442void AliAnalysisManager::ResetAnalysis()
1443{
1444// Reset all execution flags and clean containers.
1445 CleanContainers();
1446}
1447
1448//______________________________________________________________________________
1449Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1450{
1451// Start analysis having a grid handler.
1452 if (!fGridHandler) {
1453 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1454 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1455 return -1;
1456 }
1457 TTree *tree = NULL;
1458 return StartAnalysis(type, tree, nentries, firstentry);
1459}
1460
1461//______________________________________________________________________________
1462Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1463{
1464// Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1465// MIX. Process nentries starting from firstentry
1466 Long64_t retv = 0;
1467 // Backup current directory and make sure gDirectory points to gROOT
1468 TDirectory *cdir = gDirectory;
1469 gROOT->cd();
1470 if (!fInitOK) {
1471 Error("StartAnalysis","Analysis manager was not initialized !");
1472 cdir->cd();
1473 return -1;
1474 }
1475 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1476 fIsRemote = kFALSE;
1477 TString anaType = type;
1478 anaType.ToLower();
1479 fMode = kLocalAnalysis;
1480 Bool_t runlocalinit = kTRUE;
1481 if (anaType.Contains("file")) {
1482 runlocalinit = kFALSE;
1483 fIsRemote = kTRUE;
1484 }
1485 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1486 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1487 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1488
1489 if (fMode == kGridAnalysis) {
1490 fIsRemote = kTRUE;
1491 if (!anaType.Contains("terminate")) {
1492 if (!fGridHandler) {
1493 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1494 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1495 cdir->cd();
1496 return -1;
1497 }
1498 // Write analysis manager in the analysis file
1499 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1500 // run local task configuration
1501 TIter nextTask(fTasks);
1502 AliAnalysisTask *task;
1503 while ((task=(AliAnalysisTask*)nextTask())) {
1504 task->LocalInit();
1505 gROOT->cd();
1506 }
1507 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1508 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1509 cdir->cd();
1510 return -1;
1511 }
1512
1513 // Terminate grid analysis
1514 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1515 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1516 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1517 if (!fGridHandler->MergeOutputs()) {
1518 // Return if outputs could not be merged or if it alien handler
1519 // was configured for offline mode or local testing.
1520 cdir->cd();
1521 return 0;
1522 }
1523 }
1524 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1525 ImportWrappers(NULL);
1526 Terminate();
1527 cdir->cd();
1528 return 0;
1529 }
1530 TString line;
1531 SetEventLoop(kFALSE);
1532 // Enable event loop mode if a tree was provided
1533 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1534
1535 TChain *chain = 0;
1536 TString ttype = "TTree";
1537 if (tree && tree->IsA() == TChain::Class()) {
1538 chain = (TChain*)tree;
1539 if (!chain || !chain->GetListOfFiles()->First()) {
1540 Error("StartAnalysis", "Cannot process null or empty chain...");
1541 cdir->cd();
1542 return -1;
1543 }
1544 ttype = "TChain";
1545 }
1546
1547 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1548 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1549 // Initialize locally all tasks (happens for all modes)
1550 TIter next(fTasks);
1551 AliAnalysisTask *task;
1552 if (runlocalinit) {
1553 while ((task=(AliAnalysisTask*)next())) {
1554 task->LocalInit();
1555 gROOT->cd();
1556 }
1557 if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0);
1558 }
1559
1560 switch (fMode) {
1561 case kLocalAnalysis:
1562 if (!tree && !fGridHandler) {
1563 TIter nextT(fTasks);
1564 // Call CreateOutputObjects for all tasks
1565 Int_t itask = 0;
1566 Bool_t dirStatus = TH1::AddDirectoryStatus();
1567 while ((task=(AliAnalysisTask*)nextT())) {
1568 TH1::AddDirectory(kFALSE);
1569 task->CreateOutputObjects();
1570 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1571 gROOT->cd();
1572 itask++;
1573 }
1574 TH1::AddDirectory(dirStatus);
1575 if (IsExternalLoop()) {
1576 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1577 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1578 return 0;
1579 }
1580 ExecAnalysis();
1581 Terminate();
1582 return 0;
1583 }
1584 fSelector = new AliAnalysisSelector(this);
1585 // Check if a plugin handler is used
1586 if (fGridHandler) {
1587 // Get the chain from the plugin
1588 TString dataType = "esdTree";
1589 if (fInputEventHandler) {
1590 dataType = fInputEventHandler->GetDataType();
1591 dataType.ToLower();
1592 dataType += "Tree";
1593 }
1594 chain = fGridHandler->GetChainForTestMode(dataType);
1595 if (!chain) {
1596 Error("StartAnalysis", "No chain for test mode. Aborting.");
1597 return -1;
1598 }
1599 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1600 retv = chain->Process(fSelector, "", nentries, firstentry);
1601 break;
1602 }
1603 // Run tree-based analysis via AliAnalysisSelector
1604 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1605 retv = tree->Process(fSelector, "", nentries, firstentry);
1606 break;
1607 case kProofAnalysis:
1608 fIsRemote = kTRUE;
1609 // Check if the plugin is used
1610 if (fGridHandler) {
1611 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1612 }
1613 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1614 Error("StartAnalysis", "No PROOF!!! Exiting.");
1615 cdir->cd();
1616 return -1;
1617 }
1618 line = Form("gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1619 gROOT->ProcessLine(line);
1620 if (chain) {
1621 chain->SetProof();
1622 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1623 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1624 } else {
1625 Error("StartAnalysis", "No chain!!! Exiting.");
1626 cdir->cd();
1627 return -1;
1628 }
1629 break;
1630 case kGridAnalysis:
1631 fIsRemote = kTRUE;
1632 if (!anaType.Contains("terminate")) {
1633 if (!fGridHandler) {
1634 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1635 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1636 cdir->cd();
1637 return -1;
1638 }
1639 // Write analysis manager in the analysis file
1640 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1641 // Start the analysis via the handler
1642 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1643 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1644 cdir->cd();
1645 return -1;
1646 }
1647
1648 // Terminate grid analysis
1649 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1650 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1651 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1652 if (!fGridHandler->MergeOutputs()) {
1653 // Return if outputs could not be merged or if it alien handler
1654 // was configured for offline mode or local testing.
1655 cdir->cd();
1656 return 0;
1657 }
1658 }
1659 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1660 ImportWrappers(NULL);
1661 Terminate();
1662 cdir->cd();
1663 return 0;
1664 case kMixingAnalysis:
1665 // Run event mixing analysis
1666 if (!fEventPool) {
1667 Error("StartAnalysis", "Cannot run event mixing without event pool");
1668 cdir->cd();
1669 return -1;
1670 }
1671 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1672 fSelector = new AliAnalysisSelector(this);
1673 while ((chain=fEventPool->GetNextChain())) {
1674 next.Reset();
1675 // Call NotifyBinChange for all tasks
1676 while ((task=(AliAnalysisTask*)next()))
1677 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1678 retv = chain->Process(fSelector);
1679 if (retv < 0) {
1680 Error("StartAnalysis", "Mixing analysis failed");
1681 cdir->cd();
1682 return retv;
1683 }
1684 }
1685 PackOutput(fSelector->GetOutputList());
1686 Terminate();
1687 }
1688 cdir->cd();
1689 return retv;
1690}
1691
1692//______________________________________________________________________________
1693Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1694{
1695// Start analysis for this manager on a given dataset. Analysis task can be:
1696// LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1697 if (!fInitOK) {
1698 Error("StartAnalysis","Analysis manager was not initialized !");
1699 return -1;
1700 }
1701 fIsRemote = kTRUE;
1702 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1703 TString anaType = type;
1704 anaType.ToLower();
1705 if (!anaType.Contains("proof")) {
1706 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1707 return -1;
1708 }
1709 fMode = kProofAnalysis;
1710 TString line;
1711 SetEventLoop(kTRUE);
1712 // Set the dataset flag
1713 TObject::SetBit(kUseDataSet);
1714 fTree = 0;
1715 TChain *chain = 0;
1716 if (fGridHandler) {
1717 // Start proof analysis using the grid handler
1718 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1719 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1720 return -1;
1721 }
1722 // Check if the plugin is in test mode
1723 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1724 dataset = "test_collection";
1725 } else {
1726 dataset = fGridHandler->GetProofDataSet();
1727 }
1728 }
1729
1730 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1731 Error("StartAnalysis", "No PROOF!!! Exiting.");
1732 return -1;
1733 }
1734
1735 // Initialize locally all tasks
1736 TIter next(fTasks);
1737 AliAnalysisTask *task;
1738 while ((task=(AliAnalysisTask*)next())) {
1739 task->LocalInit();
1740 }
1741
1742 line = Form("gProof->AddInput((TObject*)0x%lx);", (ULong_t)this);
1743 gROOT->ProcessLine(line);
1744 Long_t retv;
1745 if (chain) {
1746// chain->SetProof();
1747 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON TEST CHAIN " << chain->GetName() << endl;
1748 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1749 } else {
1750 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1751 dataset, nentries, firstentry);
1752 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1753 retv = (Long_t)gROOT->ProcessLine(line);
1754 }
1755 return retv;
1756}
1757
1758//______________________________________________________________________________
1759TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1760{
1761// Opens according the option the file specified by cont->GetFileName() and changes
1762// current directory to cont->GetFolderName(). If the file was already opened, it
1763// checks if the option UPDATE was preserved. File open via TProofOutputFile can
1764// be optionally ignored.
1765 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1766 TString filename = cont->GetFileName();
1767 TFile *f = NULL;
1768 if (filename.IsNull()) {
1769 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1770 return NULL;
1771 }
1772 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1773 && !ignoreProof)
1774 f = mgr->OpenProofFile(cont,option);
1775 else {
1776 // Check first if the file is already opened
1777 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1778 if (f) {
1779 // Check if option "UPDATE" was preserved
1780 TString opt(option);
1781 opt.ToUpper();
1782 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1783 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1784 } else {
1785 f = TFile::Open(filename, option);
1786 }
1787 }
1788 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1789 cont->SetFile(f);
1790 // Cd to file
1791 f->cd();
1792 // Check for a folder request
1793 TString dir = cont->GetFolderName();
1794 if (!dir.IsNull()) {
1795 if (!f->GetDirectory(dir)) f->mkdir(dir);
1796 f->cd(dir);
1797 }
1798 return f;
1799 }
1800 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1801 cont->SetFile(NULL);
1802 return NULL;
1803}
1804
1805//______________________________________________________________________________
1806TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1807{
1808// Opens a special output file used in PROOF.
1809 TString line;
1810 TString filename = cont->GetFileName();
1811 if (cont == fCommonOutput) {
1812 if (fOutputEventHandler) {
1813 if (strlen(extaod)) filename = extaod;
1814 filename = fOutputEventHandler->GetOutputFileName();
1815 }
1816 else Fatal("OpenProofFile","No output container. Exiting.");
1817 }
1818 TFile *f = NULL;
1819 if (fMode!=kProofAnalysis || !fSelector) {
1820 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1821 return NULL;
1822 }
1823 if (fSpecialOutputLocation.Length()) {
1824 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1825 if (f) {
1826 // Check if option "UPDATE" was preserved
1827 TString opt(option);
1828 opt.ToUpper();
1829 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1830 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1831 } else {
1832 f = new TFile(filename, option);
1833 }
1834 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1835 cont->SetFile(f);
1836 // Cd to file
1837 f->cd();
1838 // Check for a folder request
1839 TString dir = cont->GetFolderName();
1840 if (dir.Length()) {
1841 if (!f->GetDirectory(dir)) f->mkdir(dir);
1842 f->cd(dir);
1843 }
1844 return f;
1845 }
1846 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1847 cont->SetFile(NULL);
1848 return NULL;
1849 }
1850 // Check if there is already a proof output file in the output list
1851 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1852 if (pof) {
1853 // Get the actual file
1854 line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof);
1855 filename = (const char*)gROOT->ProcessLine(line);
1856 if (fDebug>1) {
1857 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1858 }
1859 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1860 if (!f) {
1861 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1862 return NULL;
1863 }
1864 // Check if option "UPDATE" was preserved
1865 TString opt(option);
1866 opt.ToUpper();
1867 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1868 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1869 } else {
1870 if (cont->IsRegisterDataset()) {
1871 TString dsetName = filename;
1872 dsetName.ReplaceAll(".root", cont->GetTitle());
1873 dsetName.ReplaceAll(":","_");
1874 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1875 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1876 } else {
1877 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1878 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1879 }
1880 if (fDebug > 1) printf("=== %s\n", line.Data());
1881 gROOT->ProcessLine(line);
1882 line = Form("pf->OpenFile(\"%s\");", option);
1883 gROOT->ProcessLine(line);
1884 f = gFile;
1885 if (fDebug > 1) {
1886 gROOT->ProcessLine("pf->Print()");
1887 printf(" == proof file name: %s", f->GetName());
1888 }
1889 // Add to proof output list
1890 line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList());
1891 if (fDebug > 1) printf("=== %s\n", line.Data());
1892 gROOT->ProcessLine(line);
1893 }
1894 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1895 cont->SetFile(f);
1896 // Cd to file
1897 f->cd();
1898 // Check for a folder request
1899 TString dir = cont->GetFolderName();
1900 if (!dir.IsNull()) {
1901 if (!f->GetDirectory(dir)) f->mkdir(dir);
1902 f->cd(dir);
1903 }
1904 return f;
1905 }
1906 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1907 cont->SetFile(NULL);
1908 return NULL;
1909}
1910
1911//______________________________________________________________________________
1912void AliAnalysisManager::ExecAnalysis(Option_t *option)
1913{
1914// Execute analysis.
1915 static Long64_t nentries = 0;
1916 static TTree *lastTree = 0;
1917 static TStopwatch *timer = new TStopwatch();
1918 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
1919 else {
1920 if (fTree && (fTree != lastTree)) {
1921 nentries += fTree->GetEntries();
1922 lastTree = fTree;
1923 }
1924 if (!fNcalls) timer->Start();
1925 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, nentries, timer, kFALSE);
1926 }
1927 gROOT->cd();
1928 TDirectory *cdir = gDirectory;
1929 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1930 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
1931 if (!fInitOK) {
1932 Error("ExecAnalysis", "Analysis manager was not initialized !");
1933 cdir->cd();
1934 return;
1935 }
1936 fNcalls++;
1937 AliAnalysisTask *task;
1938 // Check if the top tree is active.
1939 if (fTree) {
1940 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1941 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
1942 TIter next(fTasks);
1943 // De-activate all tasks
1944 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
1945 AliAnalysisDataContainer *cont = fCommonInput;
1946 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
1947 if (!cont) {
1948 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
1949 cdir->cd();
1950 return;
1951 }
1952 cont->SetData(fTree); // This will notify all consumers
1953 Long64_t entry = fTree->GetTree()->GetReadEntry();
1954//
1955// Call BeginEvent() for optional input/output and MC services
1956 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
1957 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
1958 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
1959 gROOT->cd();
1960 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1961 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
1962//
1963// Execute the tasks
1964// TIter next1(cont->GetConsumers());
1965 TIter next1(fTopTasks);
1966 Int_t itask = 0;
1967 while ((task=(AliAnalysisTask*)next1())) {
1968 if (fDebug >1) {
1969 cout << " Executing task " << task->GetName() << endl;
1970 }
1971 task->ExecuteTask(option);
1972 gROOT->cd();
1973 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1974 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
1975 itask++;
1976 }
1977//
1978// Call FinishEvent() for optional output and MC services
1979 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
1980 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
1981 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
1982 // Gather system information if requested
1983 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1984 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
1985 cdir->cd();
1986 return;
1987 }
1988 // The event loop is not controlled by TSelector
1989//
1990// Call BeginEvent() for optional input/output and MC services
1991 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
1992 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
1993 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
1994 gROOT->cd();
1995 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
1996 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
1997 TIter next2(fTopTasks);
1998 while ((task=(AliAnalysisTask*)next2())) {
1999 task->SetActive(kTRUE);
2000 if (fDebug > 1) {
2001 cout << " Executing task " << task->GetName() << endl;
2002 }
2003 task->ExecuteTask(option);
2004 gROOT->cd();
2005 }
2006//
2007// Call FinishEvent() for optional output and MC services
2008 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2009 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2010 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2011 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2012 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2013 cdir->cd();
2014}
2015
2016//______________________________________________________________________________
2017void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2018{
2019// Set the input event handler and create a container for it.
2020 fInputEventHandler = handler;
2021 fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2022// Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it.");
2023}
2024
2025//______________________________________________________________________________
2026void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2027{
2028// Set the input event handler and create a container for it.
2029 fOutputEventHandler = handler;
2030 fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2031 fCommonOutput->SetSpecialOutput();
2032// Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it.");
2033}
2034
2035//______________________________________________________________________________
2036void AliAnalysisManager::RegisterExtraFile(const char *fname)
2037{
2038// This method is used externally to register output files which are not
2039// connected to any output container, so that the manager can properly register,
2040// retrieve or merge them when running in distributed mode. The file names are
2041// separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2042 if (fExtraFiles.Contains(fname)) return;
2043 if (fExtraFiles.Length()) fExtraFiles += " ";
2044 fExtraFiles += fname;
2045}
2046
2047//______________________________________________________________________________
2048Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2049{
2050// Copy a file from the location specified ina the wrapper with the same name from the source list.
2051 char fullPath[512];
2052 char chUrl[512];
2053 TObject *pof = source->FindObject(filename);
2054 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2055 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2056 return kFALSE;
2057 }
2058 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", (ULong_t)fullPath, (ULong_t)pof));
2059 gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", (ULong_t)chUrl));
2060 TString clientUrl(chUrl);
2061 TString fullPath_str(fullPath);
2062 if (clientUrl.Contains("localhost")){
2063 TObjArray* array = fullPath_str.Tokenize ( "//" );
2064 TObjString *strobj = ( TObjString *)array->At(1);
2065 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2066 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2067 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2068 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2069 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2070 delete arrayPort;
2071 delete array;
2072 }
2073 if (fDebug > 1)
2074 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", fullPath_str.Data());
2075 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2076 if (!gotit)
2077 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2078 return gotit;
2079}
2080
2081//______________________________________________________________________________
2082void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2083{
2084// Fill analysis type in the provided string.
2085 switch (fMode) {
2086 case kLocalAnalysis:
2087 type = "local";
2088 return;
2089 case kProofAnalysis:
2090 type = "proof";
2091 return;
2092 case kGridAnalysis:
2093 type = "grid";
2094 return;
2095 case kMixingAnalysis:
2096 type = "mix";
2097 }
2098}
2099
2100//______________________________________________________________________________
2101Bool_t AliAnalysisManager::ValidateOutputFiles() const
2102{
2103// Validate all output files.
2104 TIter next(fOutputs);
2105 AliAnalysisDataContainer *output;
2106 TDirectory *cdir = gDirectory;
2107 TString openedFiles;
2108 while ((output=(AliAnalysisDataContainer*)next())) {
2109 if (output->IsRegisterDataset()) continue;
2110 TString filename = output->GetFileName();
2111 if (filename == "default") {
2112 if (!fOutputEventHandler) continue;
2113 filename = fOutputEventHandler->GetOutputFileName();
2114 // Main AOD may not be there
2115 if (gSystem->AccessPathName(filename)) continue;
2116 }
2117 // Check if the file is closed
2118 if (openedFiles.Contains(filename)) continue;;
2119 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2120 if (file) {
2121 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2122 // Clear file list to release object ownership to user.
2123// file->Clear();
2124 file->Close();
2125 }
2126 file = TFile::Open(filename);
2127 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2128 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2129 cdir->cd();
2130 return kFALSE;
2131 }
2132 file->Close();
2133 openedFiles += filename;
2134 openedFiles += " ";
2135 }
2136 cdir->cd();
2137 return kTRUE;
2138}
2139
2140//______________________________________________________________________________
2141void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2142{
2143// Implements a nice text mode progress bar.
2144 static Long64_t icount = 0;
2145 static TString oname;
2146 static TString nname;
2147 static Long64_t ocurrent = 0;
2148 static Long64_t osize = 0;
2149 static Int_t oseconds = 0;
2150 static TStopwatch *owatch = 0;
2151 static Bool_t oneoftwo = kFALSE;
2152 static Int_t nrefresh = 0;
2153 static Int_t nchecks = 0;
2154 const char symbol[4] = {'=','\\','|','/'};
2155 char progress[11] = " ";
2156 Int_t ichar = icount%4;
2157
2158 if (!refresh) {
2159 nrefresh = 0;
2160 if (!size) return;
2161 owatch = watch;
2162 oname = opname;
2163 ocurrent = TMath::Abs(current);
2164 osize = TMath::Abs(size);
2165 if (ocurrent > osize) ocurrent=osize;
2166 } else {
2167 nrefresh++;
2168 if (!osize) return;
2169 }
2170 icount++;
2171 Double_t time = 0.;
2172 Int_t hours = 0;
2173 Int_t minutes = 0;
2174 Int_t seconds = 0;
2175 if (owatch && !last) {
2176 owatch->Stop();
2177 time = owatch->RealTime();
2178 hours = (Int_t)(time/3600.);
2179 time -= 3600*hours;
2180 minutes = (Int_t)(time/60.);
2181 time -= 60*minutes;
2182 seconds = (Int_t)time;
2183 if (refresh) {
2184 if (oseconds==seconds) {
2185 owatch->Continue();
2186 return;
2187 }
2188 oneoftwo = !oneoftwo;
2189 }
2190 oseconds = seconds;
2191 }
2192 if (refresh && oneoftwo) {
2193 nname = oname;
2194 if (nchecks <= 0) nchecks = nrefresh+1;
2195 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2196 oname = Form(" == %d%% ==", pctdone);
2197 }
2198 Double_t percent = 100.0*ocurrent/osize;
2199 Int_t nchar = Int_t(percent/10);
2200 if (nchar>10) nchar=10;
2201 Int_t i;
2202 for (i=0; i<nchar; i++) progress[i] = '=';
2203 progress[nchar] = symbol[ichar];
2204 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2205 progress[10] = '\0';
2206 oname += " ";
2207 oname.Remove(20);
2208 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2209 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2210 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2211 if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d \r", percent, hours, minutes, seconds);
2212 else fprintf(stderr, "[%6.2f %%]\r", percent);
2213 if (refresh && oneoftwo) oname = nname;
2214 if (owatch) owatch->Continue();
2215 if (last) {
2216 icount = 0;
2217 owatch = 0;
2218 ocurrent = 0;
2219 osize = 0;
2220 oseconds = 0;
2221 oneoftwo = kFALSE;
2222 nrefresh = 0;
2223 fprintf(stderr, "\n");
2224 }
2225}
2226
2227//______________________________________________________________________________
2228void AliAnalysisManager::DoLoadBranch(const char *name)
2229{
2230 // Get tree and load branch if needed.
2231
2232 if (fAutoBranchHandling || !fTree)
2233 return;
2234
2235 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2236 if (!br) {
2237 br = fTree->GetBranch(name);
2238 if (!br) {
2239 Error("DoLoadBranch", "Could not find branch %s",name);
2240 return;
2241 }
2242 fTable.Add(br);
2243 }
2244 if (br->GetReadEntry()==GetCurrentEntry()) return;
2245 br->GetEntry(GetCurrentEntry());
2246}
2247
2248//______________________________________________________________________________
2249void AliAnalysisManager::AddStatisticsMsg(const char *line)
2250{
2251// Add a line in the statistics message. If available, the statistics message is written
2252// at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2253// on the client.
2254 if (!strlen(line)) return;
2255 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2256 fStatisticsMsg += line;
2257}
2258
2259//______________________________________________________________________________
2260void AliAnalysisManager::WriteStatisticsMsg(Int_t nevents)
2261{
2262// Write the statistics message in a file named <nevents.stat>
2263 if (!nevents) return;
2264 ofstream out;
2265 out.open(Form("%09d.stat", nevents), ios::out);
2266 if (!fStatisticsMsg.IsNull()) out << fStatisticsMsg << endl;
2267 out.close();
2268}