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