1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 // Author: Andrei Gheata, 31/05/2006
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 //==============================================================================
26 //==============================================================================
28 #include "AliAnalysisManager.h"
31 #include <Riostream.h>
38 #include <TMethodCall.h>
43 #include <TStopwatch.h>
46 #include "AliAnalysisSelector.h"
47 #include "AliAnalysisGrid.h"
48 #include "AliAnalysisTask.h"
49 #include "AliAnalysisDataContainer.h"
50 #include "AliAnalysisDataSlot.h"
51 #include "AliVEventHandler.h"
52 #include "AliVEventPool.h"
53 #include "AliSysInfo.h"
54 #include "AliAnalysisStatistics.h"
56 ClassImp(AliAnalysisManager)
58 AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL;
59 TString AliAnalysisManager::fgCommonFileName = "";
60 Int_t AliAnalysisManager::fPBUpdateFreq = 1;
62 //______________________________________________________________________________
63 AliAnalysisManager::AliAnalysisManager(const char *name, const char *title)
66 fInputEventHandler(NULL),
67 fOutputEventHandler(NULL),
68 fMCtruthEventHandler(NULL),
72 fMode(kLocalAnalysis),
77 fSpecialOutputLocation(""),
91 fAutoBranchHandling(kTRUE),
101 // Default constructor.
102 fgAnalysisManager = this;
103 fgCommonFileName = "AnalysisResults.root";
104 if (TClass::IsCallingNew() != TClass::kDummyNew) {
105 fTasks = new TObjArray();
106 fTopTasks = new TObjArray();
107 fZombies = new TObjArray();
108 fContainers = new TObjArray();
109 fInputs = new TObjArray();
110 fOutputs = new TObjArray();
111 fParamCont = new TObjArray();
112 fGlobals = new TMap();
117 //______________________________________________________________________________
118 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
121 fInputEventHandler(NULL),
122 fOutputEventHandler(NULL),
123 fMCtruthEventHandler(NULL),
128 fInitOK(other.fInitOK),
129 fMustClean(other.fMustClean),
130 fIsRemote(other.fIsRemote),
131 fDebug(other.fDebug),
132 fSpecialOutputLocation(""),
146 fAutoBranchHandling(other.fAutoBranchHandling),
149 fNcalls(other.fNcalls),
150 fMaxEntries(other.fMaxEntries),
151 fStatisticsMsg(other.fStatisticsMsg),
152 fRequestedBranches(other.fRequestedBranches),
153 fStatistics(other.fStatistics),
154 fGlobals(other.fGlobals)
157 fTasks = new TObjArray(*other.fTasks);
158 fTopTasks = new TObjArray(*other.fTopTasks);
159 fZombies = new TObjArray(*other.fZombies);
160 fContainers = new TObjArray(*other.fContainers);
161 fInputs = new TObjArray(*other.fInputs);
162 fOutputs = new TObjArray(*other.fOutputs);
163 fParamCont = new TObjArray(*other.fParamCont);
164 fgCommonFileName = "AnalysisResults.root";
165 fgAnalysisManager = this;
168 //______________________________________________________________________________
169 AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& other)
172 if (&other != this) {
173 TNamed::operator=(other);
174 fInputEventHandler = other.fInputEventHandler;
175 fOutputEventHandler = other.fOutputEventHandler;
176 fMCtruthEventHandler = other.fMCtruthEventHandler;
177 fEventPool = other.fEventPool;
180 fNSysInfo = other.fNSysInfo;
182 fInitOK = other.fInitOK;
183 fIsRemote = other.fIsRemote;
184 fDebug = other.fDebug;
185 fTasks = new TObjArray(*other.fTasks);
186 fTopTasks = new TObjArray(*other.fTopTasks);
187 fZombies = new TObjArray(*other.fZombies);
188 fContainers = new TObjArray(*other.fContainers);
189 fInputs = new TObjArray(*other.fInputs);
190 fOutputs = new TObjArray(*other.fOutputs);
191 fParamCont = new TObjArray(*other.fParamCont);
192 fDebugOptions = NULL;
194 fCommonOutput = NULL;
197 fExtraFiles = other.fExtraFiles;
198 fgCommonFileName = "AnalysisResults.root";
199 fgAnalysisManager = this;
200 fAutoBranchHandling = other.fAutoBranchHandling;
201 fTable.Clear("nodelete");
202 fRunFromPath = other.fRunFromPath;
203 fNcalls = other. fNcalls;
204 fMaxEntries = other.fMaxEntries;
205 fStatisticsMsg = other.fStatisticsMsg;
206 fRequestedBranches = other.fRequestedBranches;
207 fStatistics = other.fStatistics;
208 fGlobals = new TMap();
213 //______________________________________________________________________________
214 AliAnalysisManager::~AliAnalysisManager()
217 if (fTasks) {fTasks->Delete(); delete fTasks;}
218 if (fTopTasks) delete fTopTasks;
219 if (fZombies) delete fZombies;
220 if (fContainers) {fContainers->Delete(); delete fContainers;}
221 if (fInputs) delete fInputs;
222 if (fOutputs) delete fOutputs;
223 if (fParamCont) delete fParamCont;
224 if (fDebugOptions) delete fDebugOptions;
225 if (fGridHandler) delete fGridHandler;
226 if (fInputEventHandler) delete fInputEventHandler;
227 if (fOutputEventHandler) delete fOutputEventHandler;
228 if (fMCtruthEventHandler) delete fMCtruthEventHandler;
229 if (fEventPool) delete fEventPool;
230 if (fgAnalysisManager==this) fgAnalysisManager = NULL;
231 if (fGlobals) {fGlobals->DeleteAll(); delete fGlobals;}
234 //______________________________________________________________________________
235 Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
237 // Read one entry of the tree or a whole branch.
238 fCurrentEntry = entry;
239 if (!fAutoBranchHandling)
241 return fTree ? fTree->GetTree()->GetEntry(entry, getall) : -1;
244 //______________________________________________________________________________
245 Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path)
247 // Attempt to extract run number from input data path. Works only for paths to
248 // alice data in alien.
249 // sim: /alice/sim/<production>/run_no/...
250 // data: /alice/data/year/period/000run_no/... (ESD or AOD)
251 TString type = "unknown";
253 if (s.Contains("/alice/data")) type = "real";
254 else if (s.Contains("/alice/sim")) type = "simulated";
257 ind1 = s.Index("/00");
259 ind2 = s.Index("/",ind1+1);
260 if (ind2-ind1>8) srun = s(ind1+1, ind2-ind1-1);
263 ind1 = s.Index("/LHC");
265 ind1 = s.Index("/",ind1+1);
267 ind2 = s.Index("/",ind1+1);
268 if (ind2>0) srun = s(ind1+1, ind2-ind1-1);
272 Int_t run = srun.Atoi();
273 if (run>0) printf("=== GetRunFromAlienPath: run %d of %s data ===\n", run, type.Data());
277 //______________________________________________________________________________
278 Bool_t AliAnalysisManager::Init(TTree *tree)
280 // The Init() function is called when the selector needs to initialize
281 // a new tree or chain. Typically here the branch addresses of the tree
282 // will be set. It is normaly not necessary to make changes to the
283 // generated code, but the routine can be extended by the user if needed.
284 // Init() will be called many times when running with PROOF.
285 Bool_t init = kFALSE;
286 if (!tree) return kFALSE; // Should not happen - protected in selector caller
288 printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
290 // Call InitTree of EventHandler
291 if (fOutputEventHandler) {
292 if (fMode == kProofAnalysis) {
293 init = fOutputEventHandler->Init(0x0, "proof");
295 init = fOutputEventHandler->Init(0x0, "local");
298 Error("Init", "Output event handler failed to initialize");
303 if (fInputEventHandler) {
304 if (fMode == kProofAnalysis) {
305 init = fInputEventHandler->Init(tree, "proof");
307 init = fInputEventHandler->Init(tree, "local");
310 Error("Init", "Input event handler failed to initialize tree");
314 // If no input event handler we need to get the tree once
316 if(!tree->GetTree()) {
317 Long64_t readEntry = tree->LoadTree(0);
318 if (readEntry == -2) {
319 Error("Init", "Input tree has no entry. Exiting");
325 if (fMCtruthEventHandler) {
326 if (fMode == kProofAnalysis) {
327 init = fMCtruthEventHandler->Init(0x0, "proof");
329 init = fMCtruthEventHandler->Init(0x0, "local");
332 Error("Init", "MC event handler failed to initialize");
337 if (!fInitOK) InitAnalysis();
338 if (!fInitOK) return kFALSE;
341 AliAnalysisDataContainer *top = fCommonInput;
342 if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0);
344 Error("Init","No top input container !");
348 CheckBranches(kFALSE);
350 printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
355 //______________________________________________________________________________
356 void AliAnalysisManager::SlaveBegin(TTree *tree)
358 // The SlaveBegin() function is called after the Begin() function.
359 // When running with PROOF SlaveBegin() is called on each slave server.
360 // The tree argument is deprecated (on PROOF 0 is passed).
361 if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n");
363 // Apply debug options
366 if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded");
367 static Bool_t isCalled = kFALSE;
368 Bool_t init = kFALSE;
369 Bool_t initOK = kTRUE;
371 TDirectory *curdir = gDirectory;
372 // Call SlaveBegin only once in case of mixing
373 if (isCalled && fMode==kMixingAnalysis) return;
375 // Call Init of EventHandler
376 if (fOutputEventHandler) {
377 if (fMode == kProofAnalysis) {
378 // Merging AOD's in PROOF via TProofOutputFile
379 if (fDebug > 1) printf(" Initializing AOD output file %s...\n", fOutputEventHandler->GetOutputFileName());
380 init = fOutputEventHandler->Init("proof");
381 if (!init) msg = "Failed to initialize output handler on worker";
383 init = fOutputEventHandler->Init("local");
384 if (!init) msg = "Failed to initialize output handler";
387 if (!fSelector) Error("SlaveBegin", "Selector not set");
388 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
391 if (fInputEventHandler) {
392 fInputEventHandler->SetInputTree(tree);
393 if (fMode == kProofAnalysis) {
394 init = fInputEventHandler->Init("proof");
395 if (!init) msg = "Failed to initialize input handler on worker";
397 init = fInputEventHandler->Init("local");
398 if (!init) msg = "Failed to initialize input handler";
401 if (!fSelector) Error("SlaveBegin", "Selector not set");
402 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
405 if (fMCtruthEventHandler) {
406 if (fMode == kProofAnalysis) {
407 init = fMCtruthEventHandler->Init("proof");
408 if (!init) msg = "Failed to initialize MC handler on worker";
410 init = fMCtruthEventHandler->Init("local");
411 if (!init) msg = "Failed to initialize MC handler";
414 if (!fSelector) Error("SlaveBegin", "Selector not set");
415 else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);}
417 if (curdir) curdir->cd();
421 AliAnalysisTask *task;
422 // Call CreateOutputObjects for all tasks
423 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
424 Bool_t dirStatus = TH1::AddDirectoryStatus();
426 while ((task=(AliAnalysisTask*)next())) {
428 // Start with memory as current dir and make sure by default histograms do not get attached to files.
429 TH1::AddDirectory(kFALSE);
430 task->CreateOutputObjects();
431 if (!task->CheckPostData()) {
432 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
433 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
434 ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName());
436 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
439 TH1::AddDirectory(dirStatus);
440 if (curdir) curdir->cd();
441 if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n");
444 //______________________________________________________________________________
445 Bool_t AliAnalysisManager::Notify()
447 // The Notify() function is called when a new file is opened. This
448 // can be either for a new TTree in a TChain or when when a new TTree
449 // is started when using PROOF. It is normaly not necessary to make changes
450 // to the generated code, but the routine can be extended by the
451 // user if needed. The return value is currently not used.
452 if (!fTree) return kFALSE;
453 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) return kFALSE;
455 fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L.
456 if (fMode == kProofAnalysis) fIsRemote = kTRUE;
458 TFile *curfile = fTree->GetCurrentFile();
460 Error("Notify","No current file");
464 if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
465 Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName());
466 if (run && (run != fRunFromPath)) {
468 if (fDebug > 1) printf(" ### run found from path: %d\n", run);
471 AliAnalysisTask *task;
473 // Call Notify of the event handlers
474 if (fInputEventHandler) {
475 fInputEventHandler->Notify(curfile->GetName());
478 if (fOutputEventHandler) {
479 fOutputEventHandler->Notify(curfile->GetName());
482 if (fMCtruthEventHandler) {
483 fMCtruthEventHandler->Notify(curfile->GetName());
486 // Call Notify for all tasks
487 while ((task=(AliAnalysisTask*)next()))
490 if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n");
494 //______________________________________________________________________________
495 Bool_t AliAnalysisManager::Process(Long64_t)
497 // The Process() function is called for each entry in the tree (or possibly
498 // keyed object in the case of PROOF) to be processed. The entry argument
499 // specifies which entry in the currently loaded tree is to be processed.
500 // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()
501 // to read either all or the required parts of the data. When processing
502 // keyed objects with PROOF, the object is already loaded and is available
503 // via the fObject pointer.
505 // This function should contain the "body" of the analysis. It can contain
506 // simple or elaborate selection criteria, run algorithms on the data
507 // of the event and typically fill histograms.
509 // WARNING when a selector is used with a TChain, you must use
510 // the pointer to the current TTree to call GetEntry(entry).
511 // The entry is always the local entry number in the current tree.
512 // Assuming that fChain is the pointer to the TChain being processed,
513 // use fChain->GetTree()->GetEntry(entry).
515 // This method is obsolete. ExecAnalysis is called instead.
519 //______________________________________________________________________________
520 void AliAnalysisManager::PackOutput(TList *target)
522 // Pack all output data containers in the output list. Called at SlaveTerminate
523 // stage in PROOF case for each slave.
524 if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n");
526 Error("PackOutput", "No target. Exiting.");
529 TDirectory *cdir = gDirectory;
531 if (fInputEventHandler) fInputEventHandler ->Terminate();
532 if (fOutputEventHandler) fOutputEventHandler ->Terminate();
533 if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate();
536 // Call FinishTaskOutput() for each event loop task (not called for
537 // post-event loop tasks - use Terminate() fo those)
538 TIter nexttask(fTasks);
539 AliAnalysisTask *task;
540 while ((task=(AliAnalysisTask*)nexttask())) {
541 if (!task->IsPostEventLoop()) {
542 if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName());
543 task->FinishTaskOutput();
545 if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName());
548 // Write statistics message on the workers.
549 if (fStatistics) WriteStatisticsMsg(fNcalls);
551 if (fMode == kProofAnalysis) {
552 TIter next(fOutputs);
553 AliAnalysisDataContainer *output;
554 Bool_t isManagedByHandler = kFALSE;
557 while ((output=(AliAnalysisDataContainer*)next())) {
558 // Do not consider outputs of post event loop tasks
559 isManagedByHandler = kFALSE;
560 if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue;
561 const char *filename = output->GetFileName();
562 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
563 isManagedByHandler = kTRUE;
564 printf("#### Handler output. Extra: %s\n", fExtraFiles.Data());
565 filename = fOutputEventHandler->GetOutputFileName();
567 // Check if data was posted to this container. If not, issue an error.
568 if (!output->GetData() && !isManagedByHandler) {
569 Error("PackOutput", "No data for output container %s. Forgot to PostData ?", output->GetName());
572 if (!output->IsSpecialOutput()) {
574 if (strlen(filename) && !isManagedByHandler) {
575 // Backup current folder
576 TDirectory *opwd = gDirectory;
577 // File resident outputs.
578 // Check first if the file exists.
579 TString openoption = "RECREATE";
580 Bool_t firsttime = kTRUE;
581 if (filestmp.FindObject(output->GetFileName())) {
584 filestmp.Add(new TNamed(output->GetFileName(),""));
586 if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE";
587 // TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
588 // Save data to file, then close.
589 if (output->GetData()->InheritsFrom(TCollection::Class())) {
590 // If data is a collection, we set the name of the collection
591 // as the one of the container and we save as a single key.
592 TCollection *coll = (TCollection*)output->GetData();
593 coll->SetName(output->GetName());
594 // coll->Write(output->GetName(), TObject::kSingleKey);
596 if (output->GetData()->InheritsFrom(TTree::Class())) {
597 TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE);
598 // Save data to file, then close.
599 TTree *tree = (TTree*)output->GetData();
600 // Check if tree is in memory
601 if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory);
605 // output->GetData()->Write();
608 if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName());
610 // printf(" file %s listing content:\n", filename);
613 // Clear file list to release object ownership to user.
616 output->SetFile(NULL);
617 // Restore current directory
618 if (opwd) opwd->cd();
620 // Memory-resident outputs
621 if (fDebug > 1) printf("PackOutput %s: memory merge memory resident output\n", filename);
623 AliAnalysisDataWrapper *wrap = 0;
624 if (isManagedByHandler) {
625 wrap = new AliAnalysisDataWrapper(fOutputEventHandler->GetTree());
626 wrap->SetName(output->GetName());
628 else wrap =output->ExportData();
629 // Output wrappers must NOT delete data after merging - the user owns them
630 wrap->SetDeleteData(kFALSE);
633 // Special outputs. The file must be opened and connected to the container.
634 TDirectory *opwd = gDirectory;
635 TFile *file = output->GetFile();
637 AliAnalysisTask *producer = output->GetProducer();
639 "File %s for special container %s was NOT opened in %s::CreateOutputObjects !!!",
640 output->GetFileName(), output->GetName(), producer->ClassName());
643 TString outFilename = file->GetName();
644 if (fDebug > 1) printf("PackOutput %s: special output\n", output->GetName());
645 if (isManagedByHandler) {
646 // Terminate IO for files managed by the output handler
647 // file->Write() moved to AOD handler (A.G. 11.01.10)
648 // if (file) file->Write();
649 if (file && fDebug > 2) {
650 printf(" handled file %s listing content:\n", file->GetName());
653 fOutputEventHandler->TerminateIO();
656 // Release object ownership to users after writing data to file
657 if (output->GetData()->InheritsFrom(TCollection::Class())) {
658 // If data is a collection, we set the name of the collection
659 // as the one of the container and we save as a single key.
660 TCollection *coll = (TCollection*)output->GetData();
661 coll->SetName(output->GetName());
662 coll->Write(output->GetName(), TObject::kSingleKey);
664 if (output->GetData()->InheritsFrom(TTree::Class())) {
665 TTree *tree = (TTree*)output->GetData();
666 tree->SetDirectory(file);
669 output->GetData()->Write();
673 printf(" file %s listing content:\n", output->GetFileName());
676 // Clear file list to release object ownership to user.
679 output->SetFile(NULL);
681 // Restore current directory
682 if (opwd) opwd->cd();
683 // Check if a special output location was provided or the output files have to be merged
684 if (strlen(fSpecialOutputLocation.Data())) {
685 TString remote = fSpecialOutputLocation;
687 Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();");
688 if (remote.BeginsWith("alien:")) {
689 gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());");
690 remote += outFilename;
691 remote.ReplaceAll(".root", Form("_%d.root", gid));
693 remote += Form("%s_%d_", gSystem->HostName(), gid);
694 remote += outFilename;
697 Info("PackOutput", "Output file for container %s to be copied \n at: %s. No merging.",
698 output->GetName(), remote.Data());
699 TFile::Cp ( outFilename.Data(), remote.Data() );
700 // Copy extra outputs
701 if (fExtraFiles.Length() && isManagedByHandler) {
702 TObjArray *arr = fExtraFiles.Tokenize(" ");
704 TIter nextfilename(arr);
705 while ((os=(TObjString*)nextfilename())) {
706 outFilename = os->GetString();
707 remote = fSpecialOutputLocation;
709 if (remote.BeginsWith("alien://")) {
710 remote += outFilename;
711 remote.ReplaceAll(".root", Form("_%d.root", gid));
713 remote += Form("%s_%d_", gSystem->HostName(), gid);
714 remote += outFilename;
717 Info("PackOutput", "Extra AOD file %s to be copied \n at: %s. No merging.",
718 outFilename.Data(), remote.Data());
719 TFile::Cp ( outFilename.Data(), remote.Data() );
724 // No special location specified-> use TProofOutputFile as merging utility
725 // The file at this output slot must be opened in CreateOutputObjects
726 if (fDebug > 1) printf(" File for container %s to be merged via file merger...\n", output->GetName());
732 if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
735 //______________________________________________________________________________
736 void AliAnalysisManager::ImportWrappers(TList *source)
738 // Import data in output containers from wrappers coming in source.
739 if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n");
740 TIter next(fOutputs);
741 AliAnalysisDataContainer *cont;
742 AliAnalysisDataWrapper *wrap;
744 Bool_t inGrid = (fMode == kGridAnalysis)?kTRUE:kFALSE;
745 TDirectory *cdir = gDirectory;
746 while ((cont=(AliAnalysisDataContainer*)next())) {
748 if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue;
749 if (cont->IsRegisterDataset()) continue;
750 const char *filename = cont->GetFileName();
751 Bool_t isManagedByHandler = kFALSE;
752 if (!(strcmp(filename, "default")) && fOutputEventHandler) {
753 isManagedByHandler = kTRUE;
754 filename = fOutputEventHandler->GetOutputFileName();
756 if (cont->IsSpecialOutput() || inGrid) {
757 if (strlen(fSpecialOutputLocation.Data())) continue;
758 // Copy merged file from PROOF scratch space.
759 // In case of grid the files are already in the current directory.
761 if (isManagedByHandler && fExtraFiles.Length()) {
762 // Copy extra registered dAOD files.
763 TObjArray *arr = fExtraFiles.Tokenize(" ");
765 TIter nextfilename(arr);
766 while ((os=(TObjString*)nextfilename())) GetFileFromWrapper(os->GetString(), source);
769 if (!GetFileFromWrapper(filename, source)) continue;
771 // Normally we should connect data from the copied file to the
772 // corresponding output container, but it is not obvious how to do this
773 // automatically if several objects in file...
774 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
775 if (!f) f = TFile::Open(filename, "READ");
777 Error("ImportWrappers", "Cannot open file %s in read-only mode", filename);
782 // Cd to the directory pointed by the container
783 TString folder = cont->GetFolderName();
784 if (!folder.IsNull()) f->cd(folder);
785 // Try to fetch first an object having the container name.
786 obj = gDirectory->Get(cont->GetName());
788 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",
789 cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName());
792 wrap = new AliAnalysisDataWrapper(obj);
793 wrap->SetDeleteData(kFALSE);
795 if (!wrap) wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
797 Error("ImportWrappers","Container %s not found in analysis output !", cont->GetName());
802 printf(" Importing data for container %s\n", cont->GetName());
803 if (strlen(filename)) printf(" -> file %s\n", filename);
806 cont->ImportData(wrap);
808 if (cdir) cdir->cd();
809 if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont);
812 //______________________________________________________________________________
813 void AliAnalysisManager::UnpackOutput(TList *source)
815 // Called by AliAnalysisSelector::Terminate only on the client.
816 if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n");
818 Error("UnpackOutput", "No target. Exiting.");
821 if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize());
823 if (fMode == kProofAnalysis) ImportWrappers(source);
825 TIter next(fOutputs);
826 AliAnalysisDataContainer *output;
827 while ((output=(AliAnalysisDataContainer*)next())) {
828 if (!output->GetData()) continue;
829 // Check if there are client tasks that run post event loop
830 if (output->HasConsumers()) {
831 // Disable event loop semaphore
832 output->SetPostEventLoop(kTRUE);
833 TObjArray *list = output->GetConsumers();
834 Int_t ncons = list->GetEntriesFast();
835 for (Int_t i=0; i<ncons; i++) {
836 AliAnalysisTask *task = (AliAnalysisTask*)list->At(i);
837 task->CheckNotify(kTRUE);
838 // If task is active, execute it
839 if (task->IsPostEventLoop() && task->IsActive()) {
840 if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName());
846 if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n");
849 //______________________________________________________________________________
850 void AliAnalysisManager::Terminate()
852 // The Terminate() function is the last function to be called during
853 // a query. It always runs on the client, it can be used to present
854 // the results graphically.
855 if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n");
856 TDirectory *cdir = gDirectory;
858 AliAnalysisTask *task;
859 AliAnalysisDataContainer *output;
862 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
863 // Call Terminate() for tasks
865 while (!IsSkipTerminate() && (task=(AliAnalysisTask*)next())) {
866 // Save all the canvases produced by the Terminate
867 TString pictname = Form("%s_%s", task->GetName(), task->ClassName());
871 AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2);
873 if (TObject::TestBit(kSaveCanvases)) {
874 if (!gROOT->IsBatch()) {
875 if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName());
877 while (timer.CpuTime()<5) {
879 gSystem->ProcessEvents();
882 Int_t iend = gROOT->GetListOfCanvases()->GetEntries();
883 if (iend==0) continue;
885 for (Int_t ipict=0; ipict<iend; ipict++) {
886 canvas = (TCanvas*)gROOT->GetListOfCanvases()->At(ipict);
887 if (!canvas) continue;
888 canvas->SaveAs(Form("%s_%02d.gif", pictname.Data(),ipict));
890 gROOT->GetListOfCanvases()->Delete();
894 if (fInputEventHandler) fInputEventHandler ->TerminateIO();
895 if (fOutputEventHandler) fOutputEventHandler ->TerminateIO();
896 if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO();
898 TObjArray *allOutputs = new TObjArray();
900 for (icont=0; icont<fOutputs->GetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont));
901 if (!IsSkipTerminate())
902 for (icont=0; icont<fParamCont->GetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont));
903 TIter next1(allOutputs);
904 TString handlerFile = "";
905 TString extraOutputs = "";
906 if (fOutputEventHandler) {
907 handlerFile = fOutputEventHandler->GetOutputFileName();
908 extraOutputs = fOutputEventHandler->GetExtraOutputs();
912 while ((output=(AliAnalysisDataContainer*)next1())) {
913 // Special outputs or grid files have the files already closed and written.
915 if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue;
916 if (fMode == kProofAnalysis) {
917 if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue;
919 const char *filename = output->GetFileName();
920 TString openoption = "RECREATE";
921 if (!(strcmp(filename, "default"))) continue;
922 if (!strlen(filename)) continue;
923 if (!output->GetData()) continue;
924 TDirectory *opwd = gDirectory;
925 TFile *file = output->GetFile();
926 if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
928 //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE";
929 Bool_t firsttime = kTRUE;
930 if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) {
933 filestmp.Add(new TNamed(filename,""));
935 if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE";
936 if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data());
937 file = new TFile(filename, openoption);
939 if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption());
940 openoption = file->GetOption();
941 if (openoption == "READ") {
942 if (fDebug>1) printf("...reopening in UPDATE mode\n");
943 file->ReOpen("UPDATE");
946 if (file->IsZombie()) {
947 Error("Terminate", "Cannot open output file %s", filename);
950 output->SetFile(file);
952 // Check for a folder request
953 TString dir = output->GetFolderName();
955 if (!file->GetDirectory(dir)) file->mkdir(dir);
958 if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName());
959 if (output->GetData()->InheritsFrom(TCollection::Class())) {
960 // If data is a collection, we set the name of the collection
961 // as the one of the container and we save as a single key.
962 TCollection *coll = (TCollection*)output->GetData();
963 coll->SetName(output->GetName());
964 coll->Write(output->GetName(), TObject::kSingleKey);
966 if (output->GetData()->InheritsFrom(TTree::Class())) {
967 TTree *tree = (TTree*)output->GetData();
968 tree->SetDirectory(gDirectory);
971 output->GetData()->Write();
974 if (opwd) opwd->cd();
979 while ((output=(AliAnalysisDataContainer*)next1())) {
980 // Close all files at output
981 TDirectory *opwd = gDirectory;
982 if (output->GetFile()) {
983 // Clear file list to release object ownership to user.
984 // output->GetFile()->Clear();
985 output->GetFile()->Close();
986 // Copy merged outputs in alien if requested
987 if (fSpecialOutputLocation.BeginsWith("alien://")) {
988 if (copiedFiles.Contains(output->GetFile()->GetName())) {
989 if (opwd) opwd->cd();
990 output->SetFile(NULL);
993 Info("Terminate", "Copy file %s to %s", output->GetFile()->GetName(),fSpecialOutputLocation.Data());
994 gROOT->ProcessLine("if (!gGrid) TGrid::Connect(\"alien:\");");
995 TFile::Cp(output->GetFile()->GetName(),
996 Form("%s/%s", fSpecialOutputLocation.Data(), output->GetFile()->GetName()));
997 copiedFiles += output->GetFile()->GetName();
999 output->SetFile(NULL);
1001 if (opwd) opwd->cd();
1004 //Write statistics information on the client
1005 if (fStatistics) WriteStatisticsMsg(fNcalls);
1007 TDirectory *crtdir = gDirectory;
1008 TFile f("syswatch.root", "RECREATE");
1011 if (!f.IsZombie()) {
1012 TTree *tree = AliSysInfo::MakeTree("syswatch.log");
1013 tree->SetName("syswatch");
1014 tree->SetMarkerStyle(kCircle);
1015 tree->SetMarkerColor(kBlue);
1016 tree->SetMarkerSize(0.5);
1017 if (!gROOT->IsBatch()) {
1018 tree->SetAlias("event", "id0");
1019 tree->SetAlias("task", "id1");
1020 tree->SetAlias("stage", "id2");
1021 // Already defined aliases
1022 // tree->SetAlias("deltaT","stampSec-stampOldSec");
1023 // tree->SetAlias("T","stampSec-first");
1024 // tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
1025 // tree->SetAlias("VM","pI.fMemVirtual");
1026 TCanvas *canvas = new TCanvas("SysInfo","SysInfo",10,10,1200,800);
1027 Int_t npads = 1 /*COO plot for all tasks*/ +
1028 fTopTasks->GetEntries() /*Exec plot per task*/ +
1029 1 /*Terminate plot for all tasks*/ +
1032 Int_t iopt = (Int_t)TMath::Sqrt((Double_t)npads);
1033 if (npads<iopt*(iopt+1))
1034 canvas->Divide(iopt, iopt+1, 0.01, 0.01);
1036 canvas->Divide(iopt+1, iopt+1, 0.01, 0.01);
1038 // draw the plot of deltaVM for Exec for each task
1039 for (itask=0; itask<fTopTasks->GetEntriesFast(); itask++) {
1040 task = (AliAnalysisTask*)fTopTasks->At(itask);
1042 cut = Form("task==%d && stage==1", itask);
1043 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1044 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1046 hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName()));
1047 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1050 // Draw the plot of deltaVM for CreateOutputObjects for all tasks
1052 tree->SetMarkerStyle(kFullTriangleUp);
1053 tree->SetMarkerColor(kRed);
1054 tree->SetMarkerSize(0.8);
1055 cut = "task>=0 && task<1000 && stage==0";
1056 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1057 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1059 hist->SetTitle("Memory in CreateOutputObjects()");
1060 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1061 hist->GetXaxis()->SetTitle("task");
1063 // draw the plot of deltaVM for Terminate for all tasks
1065 tree->SetMarkerStyle(kOpenSquare);
1066 tree->SetMarkerColor(kMagenta);
1067 cut = "task>=0 && task<1000 && stage==2";
1068 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1069 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1071 hist->SetTitle("Memory in Terminate()");
1072 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1073 hist->GetXaxis()->SetTitle("task");
1077 tree->SetMarkerStyle(kFullCircle);
1078 tree->SetMarkerColor(kGreen);
1079 cut = Form("task==%d && stage==1",fTopTasks->GetEntriesFast()-1);
1080 tree->Draw("VM:event",cut,"", 1234567890, 0);
1081 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1083 hist->SetTitle("Virtual memory");
1084 hist->GetYaxis()->SetTitle("VM [MB]");
1088 tree->SetMarkerStyle(kCircle);
1089 tree->SetMarkerColor(kBlue);
1090 tree->SetMarkerSize(0.5);
1095 if (crtdir) crtdir->cd();
1097 // Validate the output files
1098 if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) {
1100 out.open("outputs_valid", ios::out);
1104 if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n");
1106 //______________________________________________________________________________
1107 void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const
1109 // Profiles the task having the itop index in the list of top (first level) tasks.
1110 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->At(itop);
1112 Error("ProfileTask", "There are only %d top tasks in the manager", fTopTasks->GetEntries());
1115 ProfileTask(task->GetName(), option);
1118 //______________________________________________________________________________
1119 void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) const
1121 // Profile a managed task after the execution of the analysis in case NSysInfo
1123 if (gSystem->AccessPathName("syswatch.root")) {
1124 Error("ProfileTask", "No file syswatch.root found in the current directory");
1127 if (gROOT->IsBatch()) return;
1128 AliAnalysisTask *task = (AliAnalysisTask*)fTopTasks->FindObject(name);
1130 Error("ProfileTask", "No top task named %s known by the manager.", name);
1133 Int_t itop = fTopTasks->IndexOf(task);
1134 Int_t itask = fTasks->IndexOf(task);
1135 // Create canvas with 2 pads: first draw COO + Terminate, second Exec
1136 TDirectory *cdir = gDirectory;
1137 TFile f("syswatch.root");
1138 TTree *tree = (TTree*)f.Get("syswatch");
1140 Error("ProfileTask", "No tree named <syswatch> found in file syswatch.root");
1143 if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName());
1144 TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600);
1145 canvas->Divide(2, 2, 0.01, 0.01);
1149 // VM profile for COO and Terminate methods
1151 cut = Form("task==%d && (stage==0 || stage==2)",itask);
1152 tree->Draw("deltaVM:sname",cut,"", 1234567890, 0);
1153 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1155 hist->SetTitle("Alocated VM[MB] for COO and Terminate");
1156 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1157 hist->GetXaxis()->SetTitle("method");
1159 // CPU profile per event
1161 cut = Form("task==%d && stage==1",itop);
1162 tree->Draw("deltaT:event",cut,"", 1234567890, 0);
1163 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1165 hist->SetTitle("Execution time per event");
1166 hist->GetYaxis()->SetTitle("CPU/event [s]");
1168 // VM profile for Exec
1170 cut = Form("task==%d && stage==1",itop);
1171 tree->Draw("deltaVM:event",cut,"", 1234567890, 0);
1172 hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp");
1174 hist->SetTitle("Alocated VM[MB] per event");
1175 hist->GetYaxis()->SetTitle("deltaVM [MB]");
1180 if (cdir) cdir->cd();
1183 //______________________________________________________________________________
1184 void AliAnalysisManager::AddTask(AliAnalysisTask *task)
1186 // Adds a user task to the global list of tasks.
1188 Error("AddTask", "Cannot add task %s since InitAnalysis was already called", task->GetName());
1192 if (fTasks->FindObject(task)) {
1193 Warning("AddTask", "Task %s: the same object already added to the analysis manager. Not adding.", task->GetName());
1196 task->SetActive(kFALSE);
1200 //______________________________________________________________________________
1201 AliAnalysisTask *AliAnalysisManager::GetTask(const char *name) const
1203 // Retreive task by name.
1204 if (!fTasks) return NULL;
1205 return (AliAnalysisTask*)fTasks->FindObject(name);
1208 //______________________________________________________________________________
1209 AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name,
1210 TClass *datatype, EAliAnalysisContType type, const char *filename)
1212 // Create a data container of a certain type. Types can be:
1213 // kExchangeContainer = 0, used to exchange data between tasks
1214 // kInputContainer = 1, used to store input data
1215 // kOutputContainer = 2, used for writing result to a file
1216 // filename: composed by file#folder (e.g. results.root#INCLUSIVE) - will write
1217 // the output object to a folder inside the output file
1218 if (fContainers->FindObject(name)) {
1219 Error("CreateContainer","A container named %s already defined !",name);
1222 AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype);
1223 fContainers->Add(cont);
1225 case kInputContainer:
1228 case kOutputContainer:
1229 fOutputs->Add(cont);
1230 if (filename && strlen(filename)) {
1231 cont->SetFileName(filename);
1232 cont->SetDataOwned(kFALSE); // data owned by the file
1235 case kParamContainer:
1236 fParamCont->Add(cont);
1237 if (filename && strlen(filename)) {
1238 cont->SetFileName(filename);
1239 cont->SetDataOwned(kFALSE); // data owned by the file
1242 case kExchangeContainer:
1248 //______________________________________________________________________________
1249 Bool_t AliAnalysisManager::ConnectInput(AliAnalysisTask *task, Int_t islot,
1250 AliAnalysisDataContainer *cont)
1252 // Connect input of an existing task to a data container.
1254 Error("ConnectInput", "Task pointer is NULL");
1257 if (!fTasks->FindObject(task)) {
1259 Info("ConnectInput", "Task %s was not registered. Now owned by analysis manager", task->GetName());
1261 Bool_t connected = task->ConnectInput(islot, cont);
1265 //______________________________________________________________________________
1266 Bool_t AliAnalysisManager::ConnectOutput(AliAnalysisTask *task, Int_t islot,
1267 AliAnalysisDataContainer *cont)
1269 // Connect output of an existing task to a data container.
1271 Error("ConnectOutput", "Task pointer is NULL");
1274 if (!fTasks->FindObject(task)) {
1276 Warning("ConnectOutput", "Task %s not registered. Now owned by analysis manager", task->GetName());
1278 Bool_t connected = task->ConnectOutput(islot, cont);
1282 //______________________________________________________________________________
1283 void AliAnalysisManager::CleanContainers()
1285 // Clean data from all containers that have already finished all client tasks.
1286 TIter next(fContainers);
1287 AliAnalysisDataContainer *cont;
1288 while ((cont=(AliAnalysisDataContainer *)next())) {
1289 if (cont->IsOwnedData() &&
1290 cont->IsDataReady() &&
1291 cont->ClientsExecuted()) cont->DeleteData();
1295 //______________________________________________________________________________
1296 Bool_t AliAnalysisManager::InitAnalysis()
1298 // Initialization of analysis chain of tasks. Should be called after all tasks
1299 // and data containers are properly connected
1300 // Reset flag and remove valid_outputs file if exists
1301 if (fInitOK) return kTRUE;
1302 if (!gSystem->AccessPathName("outputs_valid"))
1303 gSystem->Unlink("outputs_valid");
1304 // Check for top tasks (depending only on input data containers)
1305 if (!fTasks->First()) {
1306 Error("InitAnalysis", "Analysis has no tasks !");
1310 AliAnalysisTask *task;
1311 AliAnalysisDataContainer *cont;
1314 Bool_t iszombie = kFALSE;
1315 Bool_t istop = kTRUE;
1317 while ((task=(AliAnalysisTask*)next())) {
1320 Int_t ninputs = task->GetNinputs();
1321 for (i=0; i<ninputs; i++) {
1322 cont = task->GetInputSlot(i)->GetContainer();
1326 fZombies->Add(task);
1330 Error("InitAnalysis", "Input slot %d of task %s has no container connected ! Declared zombie...",
1331 i, task->GetName());
1333 if (iszombie) continue;
1334 // Check if cont is an input container
1335 if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
1336 // Connect to parent task
1340 fTopTasks->Add(task);
1344 Error("InitAnalysis", "No top task defined. At least one task should be connected only to input containers");
1347 // Check now if there are orphan tasks
1348 for (i=0; i<ntop; i++) {
1349 task = (AliAnalysisTask*)fTopTasks->At(i);
1354 while ((task=(AliAnalysisTask*)next())) {
1355 if (!task->IsUsed()) {
1357 Warning("InitAnalysis", "Task %s is orphan", task->GetName());
1360 // Check the task hierarchy (no parent task should depend on data provided
1361 // by a daughter task)
1362 for (i=0; i<ntop; i++) {
1363 task = (AliAnalysisTask*)fTopTasks->At(i);
1364 if (task->CheckCircularDeps()) {
1365 Error("InitAnalysis", "Found illegal circular dependencies between following tasks:");
1370 // Check that all containers feeding post-event loop tasks are in the outputs list
1371 TIter nextcont(fContainers); // loop over all containers
1372 while ((cont=(AliAnalysisDataContainer*)nextcont())) {
1373 if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) {
1374 if (cont->HasConsumers()) {
1375 // Check if one of the consumers is post event loop
1376 TIter nextconsumer(cont->GetConsumers());
1377 while ((task=(AliAnalysisTask*)nextconsumer())) {
1378 if (task->IsPostEventLoop()) {
1379 fOutputs->Add(cont);
1386 // Check if all special output containers have a file name provided
1387 TIter nextout(fOutputs);
1388 while ((cont=(AliAnalysisDataContainer*)nextout())) {
1389 if (cont->IsSpecialOutput() && !strlen(cont->GetFileName())) {
1390 Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName());
1394 // Initialize requested branch list if needed
1395 if (!fAutoBranchHandling) {
1397 while ((task=(AliAnalysisTask*)next())) {
1398 if (!task->HasBranches()) {
1399 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\"",
1400 task->GetName(), task->ClassName());
1403 if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) {
1404 Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type.");
1407 TString taskbranches;
1408 task->GetBranches(fInputEventHandler->GetDataType(), taskbranches);
1409 if (taskbranches.IsNull()) {
1410 Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:",
1411 task->GetName(), task->ClassName(), fInputEventHandler->GetDataType());
1414 AddBranches(taskbranches);
1421 //______________________________________________________________________________
1422 void AliAnalysisManager::AddBranches(const char *branches)
1424 // Add branches to the existing fRequestedBranches.
1425 TString br(branches);
1426 TObjArray *arr = br.Tokenize(",");
1429 while ((obj=next())) {
1430 if (!fRequestedBranches.Contains(obj->GetName())) {
1431 if (!fRequestedBranches.IsNull()) fRequestedBranches += ",";
1432 fRequestedBranches += obj->GetName();
1438 //______________________________________________________________________________
1439 void AliAnalysisManager::CheckBranches(Bool_t load)
1441 // The method checks the input branches to be loaded during the analysis.
1442 if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return;
1443 TObjArray *arr = fRequestedBranches.Tokenize(",");
1446 while ((obj=next())) {
1447 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(obj->GetName()));
1449 br = fTree->GetBranch(obj->GetName());
1451 Error("CheckBranches", "Could not find branch %s",obj->GetName());
1456 if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry());
1461 //______________________________________________________________________________
1462 Bool_t AliAnalysisManager::CheckTasks() const
1464 // Check consistency of tasks.
1465 Int_t ntasks = fTasks->GetEntries();
1467 Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library.");
1470 // Get the pointer to AliAnalysisTaskSE::Class()
1471 TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()");
1472 // Loop all tasks to check if their corresponding library was loaded
1475 while ((obj=next())) {
1476 if (obj->IsA() == badptr) {
1477 Error("CheckTasks", "##################\n \
1478 Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName());
1485 //______________________________________________________________________________
1486 void AliAnalysisManager::PrintStatus(Option_t *option) const
1488 // Print task hierarchy.
1490 Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName());
1493 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1495 Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo);
1496 TIter next(fTopTasks);
1497 AliAnalysisTask *task;
1498 while ((task=(AliAnalysisTask*)next()))
1499 task->PrintTask(option);
1501 if (!fAutoBranchHandling && !fRequestedBranches.IsNull())
1502 printf("Requested input branches:\n%s\n", fRequestedBranches.Data());
1504 TString sopt(option);
1507 if (sopt.Contains("ALL"))
1509 if ( fOutputEventHandler )
1511 cout << TString('_',78) << endl;
1512 cout << "OutputEventHandler:" << endl;
1513 fOutputEventHandler->Print(" ");
1518 //______________________________________________________________________________
1519 void AliAnalysisManager::ResetAnalysis()
1521 // Reset all execution flags and clean containers.
1525 //______________________________________________________________________________
1526 void AliAnalysisManager::RunLocalInit()
1528 // Run LocalInit method for all tasks.
1529 TDirectory *cdir = gDirectory;
1530 if (IsTrainInitialized()) return;
1531 TIter nextTask(fTasks);
1532 AliAnalysisTask *task;
1533 while ((task=(AliAnalysisTask*)nextTask())) {
1538 TObject::SetBit(kTasksInitialized, kTRUE);
1541 //______________________________________________________________________________
1542 Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry)
1544 // Start analysis having a grid handler.
1545 if (!fGridHandler) {
1546 Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler.");
1547 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1551 return StartAnalysis(type, tree, nentries, firstentry);
1554 //______________________________________________________________________________
1555 Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry)
1557 // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or
1558 // MIX. Process nentries starting from firstentry
1560 // Backup current directory and make sure gDirectory points to gROOT
1561 TDirectory *cdir = gDirectory;
1564 Error("StartAnalysis","Analysis manager was not initialized !");
1568 if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded");
1570 printf("StartAnalysis %s\n",GetName());
1571 AliLog::SetGlobalLogLevel(AliLog::kInfo);
1573 fMaxEntries = nentries;
1575 TString anaType = type;
1577 fMode = kLocalAnalysis;
1578 if (anaType.Contains("file")) fIsRemote = kTRUE;
1579 if (anaType.Contains("proof")) fMode = kProofAnalysis;
1580 else if (anaType.Contains("grid")) fMode = kGridAnalysis;
1581 else if (anaType.Contains("mix")) fMode = kMixingAnalysis;
1583 if (fMode == kGridAnalysis) {
1585 if (!anaType.Contains("terminate")) {
1586 if (!fGridHandler) {
1587 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1588 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1592 // Write analysis manager in the analysis file
1593 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1594 // run local task configuration
1596 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1597 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1602 // Terminate grid analysis
1603 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1604 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1605 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1606 if (!fGridHandler->MergeOutputs()) {
1607 // Return if outputs could not be merged or if it alien handler
1608 // was configured for offline mode or local testing.
1613 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1614 ImportWrappers(NULL);
1620 SetEventLoop(kFALSE);
1621 // Enable event loop mode if a tree was provided
1622 if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE);
1625 TString ttype = "TTree";
1626 if (tree && tree->IsA() == TChain::Class()) {
1627 chain = (TChain*)tree;
1628 if (!chain || !chain->GetListOfFiles()->First()) {
1629 Error("StartAnalysis", "Cannot process null or empty chain...");
1636 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
1637 if (getsysInfo) AliSysInfo::AddStamp("Start", 0);
1638 // Initialize locally all tasks (happens for all modes)
1640 AliAnalysisTask *task;
1644 case kLocalAnalysis:
1645 if (!tree && !fGridHandler) {
1646 TIter nextT(fTasks);
1647 // Call CreateOutputObjects for all tasks
1649 Bool_t dirStatus = TH1::AddDirectoryStatus();
1650 while ((task=(AliAnalysisTask*)nextT())) {
1651 TH1::AddDirectory(kFALSE);
1652 task->CreateOutputObjects();
1653 if (!task->CheckPostData()) {
1654 Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\
1655 Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\
1656 ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName());
1658 if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0);
1662 TH1::AddDirectory(dirStatus);
1663 if (IsExternalLoop()) {
1664 Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\
1665 \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually");
1672 fSelector = new AliAnalysisSelector(this);
1673 // Check if a plugin handler is used
1675 // Get the chain from the plugin
1676 TString dataType = "esdTree";
1677 if (fInputEventHandler) {
1678 dataType = fInputEventHandler->GetDataType();
1682 chain = fGridHandler->GetChainForTestMode(dataType);
1684 Error("StartAnalysis", "No chain for test mode. Aborting.");
1687 cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl;
1688 retv = chain->Process(fSelector, "", nentries, firstentry);
1691 // Run tree-based analysis via AliAnalysisSelector
1692 cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
1693 retv = tree->Process(fSelector, "", nentries, firstentry);
1695 case kProofAnalysis:
1697 // Check if the plugin is used
1699 return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry);
1701 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1702 Error("StartAnalysis", "No PROOF!!! Exiting.");
1706 line = Form("gProof->AddInput((TObject*)%p);", this);
1707 gROOT->ProcessLine(line);
1710 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl;
1711 retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry);
1713 Error("StartAnalysis", "No chain!!! Exiting.");
1720 if (!anaType.Contains("terminate")) {
1721 if (!fGridHandler) {
1722 Error("StartAnalysis", "Cannot start grid analysis without a grid handler.");
1723 Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it.");
1727 // Write analysis manager in the analysis file
1728 cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl;
1729 // Start the analysis via the handler
1730 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1731 Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated");
1736 // Terminate grid analysis
1737 if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;}
1738 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;}
1739 cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl;
1740 if (!fGridHandler->MergeOutputs()) {
1741 // Return if outputs could not be merged or if it alien handler
1742 // was configured for offline mode or local testing.
1747 cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl;
1748 ImportWrappers(NULL);
1752 case kMixingAnalysis:
1753 // Run event mixing analysis
1755 Error("StartAnalysis", "Cannot run event mixing without event pool");
1759 cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl;
1760 fSelector = new AliAnalysisSelector(this);
1761 while ((chain=fEventPool->GetNextChain())) {
1763 // Call NotifyBinChange for all tasks
1764 while ((task=(AliAnalysisTask*)next()))
1765 if (!task->IsPostEventLoop()) task->NotifyBinChange();
1766 retv = chain->Process(fSelector);
1768 Error("StartAnalysis", "Mixing analysis failed");
1773 PackOutput(fSelector->GetOutputList());
1780 //______________________________________________________________________________
1781 Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry)
1783 // Start analysis for this manager on a given dataset. Analysis task can be:
1784 // LOCAL, PROOF or GRID. Process nentries starting from firstentry.
1786 Error("StartAnalysis","Analysis manager was not initialized !");
1790 if (fDebug > 1) printf("StartAnalysis %s\n",GetName());
1791 TString anaType = type;
1793 if (!anaType.Contains("proof")) {
1794 Error("StartAnalysis", "Cannot process datasets in %s mode. Try PROOF.", type);
1797 fMode = kProofAnalysis;
1799 SetEventLoop(kTRUE);
1800 // Set the dataset flag
1801 TObject::SetBit(kUseDataSet);
1804 // Start proof analysis using the grid handler
1805 if (!fGridHandler->StartAnalysis(nentries, firstentry)) {
1806 Error("StartAnalysis", "The grid plugin could not start PROOF analysis");
1809 // Check if the plugin is in test mode
1810 if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) {
1811 dataset = "test_collection";
1813 dataset = fGridHandler->GetProofDataSet();
1817 if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) {
1818 Error("StartAnalysis", "No PROOF!!! Exiting.");
1822 // Initialize locally all tasks
1825 line = Form("gProof->AddInput((TObject*)%p);", this);
1826 gROOT->ProcessLine(line);
1828 line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);",
1829 dataset, nentries, firstentry);
1830 cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl;
1831 retv = (Long_t)gROOT->ProcessLine(line);
1835 //______________________________________________________________________________
1836 TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char *option, Bool_t ignoreProof)
1838 // Opens according the option the file specified by cont->GetFileName() and changes
1839 // current directory to cont->GetFolderName(). If the file was already opened, it
1840 // checks if the option UPDATE was preserved. File open via TProofOutputFile can
1841 // be optionally ignored.
1842 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
1843 TString filename = cont->GetFileName();
1845 if (filename.IsNull()) {
1846 ::Error("AliAnalysisManager::OpenFile", "No file name specified for container %s", cont->GetName());
1849 if (mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis && cont->IsSpecialOutput()
1851 f = mgr->OpenProofFile(cont,option);
1853 // Check first if the file is already opened
1854 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1856 // Check if option "UPDATE" was preserved
1857 TString opt(option);
1859 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1860 ::Info("AliAnalysisManager::OpenFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1862 f = TFile::Open(filename, option);
1865 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1869 // Check for a folder request
1870 TString dir = cont->GetFolderName();
1871 if (!dir.IsNull()) {
1872 if (!f->GetDirectory(dir)) f->mkdir(dir);
1877 ::Fatal("AliAnalysisManager::OpenFile", "File %s could not be opened", filename.Data());
1878 cont->SetFile(NULL);
1882 //______________________________________________________________________________
1883 TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod)
1885 // Opens a special output file used in PROOF.
1887 TString filename = cont->GetFileName();
1888 if (cont == fCommonOutput) {
1889 if (fOutputEventHandler) {
1890 if (strlen(extaod)) filename = extaod;
1891 filename = fOutputEventHandler->GetOutputFileName();
1893 else Fatal("OpenProofFile","No output container. Exiting.");
1896 if (fMode!=kProofAnalysis || !fSelector) {
1897 Fatal("OpenProofFile","Cannot open PROOF file %s: no PROOF or selector",filename.Data());
1900 if (fSpecialOutputLocation.Length()) {
1901 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1903 // Check if option "UPDATE" was preserved
1904 TString opt(option);
1906 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1907 ::Info("OpenProofFile", "File %s already opened in %s mode!", cont->GetFileName(), f->GetOption());
1909 f = new TFile(filename, option);
1911 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1915 // Check for a folder request
1916 TString dir = cont->GetFolderName();
1918 if (!f->GetDirectory(dir)) f->mkdir(dir);
1923 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1924 cont->SetFile(NULL);
1927 // Check if there is already a proof output file in the output list
1928 TObject *pof = fSelector->GetOutputList()->FindObject(filename);
1930 // Get the actual file
1931 line = Form("((TProofOutputFile*)%p)->GetFileName();", pof);
1932 filename = (const char*)gROOT->ProcessLine(line);
1934 printf("File: %s already booked via TProofOutputFile\n", filename.Data());
1936 f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
1938 Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data());
1941 // Check if option "UPDATE" was preserved
1942 TString opt(option);
1944 if ((opt=="UPDATE") && (opt!=f->GetOption()))
1945 Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName());
1947 if (cont->IsRegisterDataset()) {
1948 TString dsetName = filename;
1949 dsetName.ReplaceAll(".root", cont->GetTitle());
1950 dsetName.ReplaceAll(":","_");
1951 if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data());
1952 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data());
1954 if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data());
1955 line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data());
1957 if (fDebug > 1) printf("=== %s\n", line.Data());
1958 gROOT->ProcessLine(line);
1959 line = Form("pf->OpenFile(\"%s\");", option);
1960 gROOT->ProcessLine(line);
1963 gROOT->ProcessLine("pf->Print()");
1964 printf(" == proof file name: %s", f->GetName());
1966 // Add to proof output list
1967 line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList());
1968 if (fDebug > 1) printf("=== %s\n", line.Data());
1969 gROOT->ProcessLine(line);
1971 if (f && !f->IsZombie() && !f->TestBit(TFile::kRecovered)) {
1975 // Check for a folder request
1976 TString dir = cont->GetFolderName();
1977 if (!dir.IsNull()) {
1978 if (!f->GetDirectory(dir)) f->mkdir(dir);
1983 Fatal("OpenProofFile", "File %s could not be opened", cont->GetFileName());
1984 cont->SetFile(NULL);
1988 //______________________________________________________________________________
1989 void AliAnalysisManager::ExecAnalysis(Option_t *option)
1991 // Execute analysis.
1992 static Long64_t nentries = 0;
1993 static TTree *lastTree = 0;
1994 static TStopwatch *timer = new TStopwatch();
1995 // Only the first call to Process will trigger a true Notify. Other Notify
1996 // coming before is ignored.
1997 if (!TObject::TestBit(AliAnalysisManager::kTrueNotify)) {
1998 TObject::SetBit(AliAnalysisManager::kTrueNotify);
2001 if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls);
2003 if (fTree && (fTree != lastTree)) {
2004 nentries += fTree->GetEntries();
2007 if (!fNcalls) timer->Start();
2008 if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE);
2011 TDirectory *cdir = gDirectory;
2012 Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE;
2013 if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls);
2015 Error("ExecAnalysis", "Analysis manager was not initialized !");
2020 AliAnalysisTask *task;
2021 // Check if the top tree is active.
2023 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2024 AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0);
2026 // De-activate all tasks
2027 while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
2028 AliAnalysisDataContainer *cont = fCommonInput;
2029 if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0);
2031 Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container");
2035 cont->SetData(fTree); // This will notify all consumers
2036 Long64_t entry = fTree->GetTree()->GetReadEntry();
2038 // Call BeginEvent() for optional input/output and MC services
2039 if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry);
2040 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry);
2041 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry);
2043 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2044 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2046 // Execute the tasks
2047 // TIter next1(cont->GetConsumers());
2048 TIter next1(fTopTasks);
2050 while ((task=(AliAnalysisTask*)next1())) {
2052 cout << " Executing task " << task->GetName() << endl;
2054 task->ExecuteTask(option);
2056 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2057 AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1);
2061 // Call FinishEvent() for optional output and MC services
2062 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2063 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2064 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2065 // Gather system information if requested
2066 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2067 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1);
2071 // The event loop is not controlled by TSelector
2073 // Call BeginEvent() for optional input/output and MC services
2074 if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1);
2075 if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1);
2076 if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1);
2078 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2079 AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0);
2080 TIter next2(fTopTasks);
2081 while ((task=(AliAnalysisTask*)next2())) {
2082 task->SetActive(kTRUE);
2084 cout << " Executing task " << task->GetName() << endl;
2086 task->ExecuteTask(option);
2090 // Call FinishEvent() for optional output and MC services
2091 if (fInputEventHandler) fInputEventHandler ->FinishEvent();
2092 if (fOutputEventHandler) fOutputEventHandler ->FinishEvent();
2093 if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent();
2094 if (getsysInfo && ((fNcalls%fNSysInfo)==0))
2095 AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1);
2099 //______________________________________________________________________________
2100 Bool_t AliAnalysisManager::IsPipe(std::ostream &out)
2102 // Check if the stdout is connected to a pipe (C.Holm)
2103 Bool_t ispipe = kFALSE;
2104 out.seekp(0, std::ios_base::cur);
2107 if (errno == ESPIPE) ispipe = kTRUE;
2112 //______________________________________________________________________________
2113 void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler)
2115 // Set the input event handler and create a container for it.
2116 fInputEventHandler = handler;
2117 if (!fCommonInput) fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer);
2120 //______________________________________________________________________________
2121 void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler)
2123 // Set the input event handler and create a container for it.
2124 fOutputEventHandler = handler;
2125 if (!fCommonOutput) fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default");
2126 fCommonOutput->SetSpecialOutput();
2129 //______________________________________________________________________________
2130 void AliAnalysisManager::SetDebugLevel(UInt_t level)
2132 // Set verbosity of the analysis manager. If the progress bar is used, the call is ignored
2133 if (TObject::TestBit(kUseProgressBar)) {
2134 Info("SetDebugLevel","Ignored. Disable the progress bar first.");
2140 //______________________________________________________________________________
2141 void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq)
2143 // Enable a text mode progress bar. Resets debug level to 0.
2144 Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq);
2145 TObject::SetBit(kUseProgressBar,flag);
2146 fPBUpdateFreq = freq;
2150 //______________________________________________________________________________
2151 void AliAnalysisManager::RegisterExtraFile(const char *fname)
2153 // This method is used externally to register output files which are not
2154 // connected to any output container, so that the manager can properly register,
2155 // retrieve or merge them when running in distributed mode. The file names are
2156 // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit().
2157 if (fExtraFiles.Contains(fname)) return;
2158 if (fExtraFiles.Length()) fExtraFiles += " ";
2159 fExtraFiles += fname;
2162 //______________________________________________________________________________
2163 Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source)
2165 // Copy a file from the location specified ina the wrapper with the same name from the source list.
2169 TObject *pof = source->FindObject(filename);
2170 if (!pof || !pof->InheritsFrom("TProofOutputFile")) {
2171 Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename);
2174 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof));
2175 gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl));
2176 TString clientUrl(chUrl);
2177 TString fullPath_str(fullPath);
2178 if (clientUrl.Contains("localhost")){
2179 TObjArray* array = fullPath_str.Tokenize ( "//" );
2180 TObjString *strobj = ( TObjString *)array->At(1);
2181 TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" );
2182 TObjString *strobjPort = ( TObjString *) arrayPort->At(1);
2183 fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT");
2184 fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data()));
2185 if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename);
2189 else if (clientUrl.Contains("__lite__")) {
2190 // Special case for ProofLite environement - get file info and copy.
2191 gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof));
2192 fullPath_str = Form("%s/%s", tmp, fullPath);
2195 Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename);
2196 Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename);
2198 Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename);
2202 //______________________________________________________________________________
2203 void AliAnalysisManager::GetAnalysisTypeString(TString &type) const
2205 // Fill analysis type in the provided string.
2207 case kLocalAnalysis:
2210 case kProofAnalysis:
2216 case kMixingAnalysis:
2221 //______________________________________________________________________________
2222 Bool_t AliAnalysisManager::ValidateOutputFiles() const
2224 // Validate all output files.
2225 TIter next(fOutputs);
2226 AliAnalysisDataContainer *output;
2227 TDirectory *cdir = gDirectory;
2228 TString openedFiles;
2229 while ((output=(AliAnalysisDataContainer*)next())) {
2230 if (output->IsRegisterDataset()) continue;
2231 TString filename = output->GetFileName();
2232 if (filename == "default") {
2233 if (!fOutputEventHandler) continue;
2234 filename = fOutputEventHandler->GetOutputFileName();
2235 // Main AOD may not be there
2236 if (gSystem->AccessPathName(filename)) continue;
2238 // Check if the file is closed
2239 if (openedFiles.Contains(filename)) continue;;
2240 TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
2242 Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data());
2243 // Clear file list to release object ownership to user.
2247 file = TFile::Open(filename);
2248 if (!file || file->IsZombie() || file->TestBit(TFile::kRecovered)) {
2249 Error("ValidateOutputs", "Output file <%s> was not created or invalid", filename.Data());
2254 openedFiles += filename;
2261 //______________________________________________________________________________
2262 void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh)
2264 // Implements a nice text mode progress bar.
2265 static Long64_t icount = 0;
2266 static TString oname;
2267 static TString nname;
2268 static Long64_t ocurrent = 0;
2269 static Long64_t osize = 0;
2270 static Int_t oseconds = 0;
2271 static TStopwatch *owatch = 0;
2272 static Bool_t oneoftwo = kFALSE;
2273 static Int_t nrefresh = 0;
2274 static Int_t nchecks = 0;
2275 static char lastChar = 0;
2276 const char symbol[4] = {'-','\\','|','/'};
2278 if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n';
2284 ocurrent = TMath::Abs(current);
2285 osize = TMath::Abs(size);
2286 if (ocurrent > osize) ocurrent=osize;
2291 if ((current % fPBUpdateFreq) != 0) return;
2293 char progress[11] = " ";
2294 Int_t ichar = icount%4;
2299 if (owatch && !last) {
2301 time = owatch->RealTime();
2302 seconds = int(time) % 60;
2303 minutes = (int(time) / 60) % 60;
2304 hours = (int(time) / 60 / 60);
2306 if (oseconds==seconds) {
2310 oneoftwo = !oneoftwo;
2314 if (refresh && oneoftwo) {
2316 if (nchecks <= 0) nchecks = nrefresh+1;
2317 Int_t pctdone = (Int_t)(100.*nrefresh/nchecks);
2318 oname = Form(" == %d%% ==", pctdone);
2320 Double_t percent = 100.0*ocurrent/osize;
2321 Int_t nchar = Int_t(percent/10);
2322 if (nchar>10) nchar=10;
2324 for (i=0; i<nchar; i++) progress[i] = '=';
2325 progress[nchar] = symbol[ichar];
2326 for (i=nchar+1; i<10; i++) progress[i] = ' ';
2327 progress[10] = '\0';
2330 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
2331 else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
2332 else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
2334 Int_t full = Int_t(ocurrent > 0 ?
2335 time * (float(osize)/ocurrent) + .5 :
2337 Int_t remain = Int_t(full - time);
2338 Int_t rsec = remain % 60;
2339 Int_t rmin = (remain / 60) % 60;
2340 Int_t rhour = (remain / 60 / 60);
2341 fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c",
2342 percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar);
2344 else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar);
2345 if (refresh && oneoftwo) oname = nname;
2346 if (owatch) owatch->Continue();
2355 fprintf(stderr, "\n");
2359 //______________________________________________________________________________
2360 void AliAnalysisManager::DoLoadBranch(const char *name)
2362 // Get tree and load branch if needed.
2363 static Long64_t crtEntry = -100;
2365 if (fAutoBranchHandling || !fTree)
2368 TBranch *br = dynamic_cast<TBranch*>(fTable.FindObject(name));
2370 br = fTree->GetBranch(name);
2372 Error("DoLoadBranch", "Could not find branch %s",name);
2377 if (br->GetReadEntry()==fCurrentEntry) return;
2378 Int_t ret = br->GetEntry(GetCurrentEntry());
2380 Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name);
2381 if (crtEntry != fCurrentEntry) {
2382 CountEvent(1,0,1,0);
2383 crtEntry = fCurrentEntry;
2386 if (crtEntry != fCurrentEntry) {
2387 CountEvent(1,1,0,0);
2388 crtEntry = fCurrentEntry;
2393 //______________________________________________________________________________
2394 void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask)
2396 // Add the statistics task to the manager.
2398 Info("AddStatisticsTask", "Already added");
2401 TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask);
2402 gROOT->ProcessLine(line);
2405 //______________________________________________________________________________
2406 void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted)
2408 // Bookkeep current event;
2409 if (!fStatistics) return;
2410 fStatistics->AddInput(ninput);
2411 fStatistics->AddProcessed(nprocessed);
2412 fStatistics->AddFailed(nfailed);
2413 fStatistics->AddAccepted(naccepted);
2416 //______________________________________________________________________________
2417 void AliAnalysisManager::AddStatisticsMsg(const char *line)
2419 // Add a line in the statistics message. If available, the statistics message is written
2420 // at the end of the SlaveTerminate phase on workers AND at the end of Terminate
2422 if (!strlen(line)) return;
2423 if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n";
2424 fStatisticsMsg += line;
2427 //______________________________________________________________________________
2428 void AliAnalysisManager::WriteStatisticsMsg(Int_t)
2430 // If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat
2431 static Bool_t done = kFALSE;
2434 if (!fStatistics) return;
2436 AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput()));
2437 AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed()));
2438 AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed()));
2439 AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted()));
2440 out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(),
2441 fStatistics->GetNprocessed(),fStatistics->GetNfailed(),
2442 fStatistics->GetNaccepted()), ios::out);
2443 out << fStatisticsMsg << endl;
2447 //______________________________________________________________________________
2448 const char* AliAnalysisManager::GetOADBPath()
2450 // returns the path of the OADB
2451 // this static function just depends on environment variables
2453 static TString oadbPath;
2455 if (gSystem->Getenv("OADB_PATH"))
2456 oadbPath = gSystem->Getenv("OADB_PATH");
2457 else if (gSystem->Getenv("ALICE_ROOT"))
2458 oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT"));
2460 ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!");
2465 //______________________________________________________________________________
2466 void AliAnalysisManager::SetGlobalStr(const char *key, const char *value)
2468 // Define a custom string variable mapped to a global unique name. The variable
2469 // can be then retrieved by a given analysis macro via GetGlobalStr(key).
2470 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2472 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2475 Bool_t valid = kFALSE;
2476 TString existing = AliAnalysisManager::GetGlobalStr(key, valid);
2478 ::Error("AliAnalysisManager::SetGlobalStr", "Global %s = %s already defined.", key, existing.Data());
2481 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(value));
2484 //______________________________________________________________________________
2485 const char *AliAnalysisManager::GetGlobalStr(const char *key, Bool_t &valid)
2487 // Static method to retrieve a global variable defined via SetGlobalStr.
2489 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2491 TObject *value = mgr->GetGlobals()->GetValue(key);
2492 if (!value) return 0;
2494 return value->GetName();
2497 //______________________________________________________________________________
2498 void AliAnalysisManager::SetGlobalInt(const char *key, Int_t value)
2500 // Define a custom integer variable mapped to a global unique name. The variable
2501 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2502 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2504 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2507 Bool_t valid = kFALSE;
2508 Int_t existing = AliAnalysisManager::GetGlobalInt(key, valid);
2510 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %i already defined.", key, existing);
2513 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%i",value)));
2516 //______________________________________________________________________________
2517 Int_t AliAnalysisManager::GetGlobalInt(const char *key, Bool_t &valid)
2519 // Static method to retrieve a global variable defined via SetGlobalInt.
2521 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2523 TObject *value = mgr->GetGlobals()->GetValue(key);
2524 if (!value) return 0;
2526 TString s = value->GetName();
2530 //______________________________________________________________________________
2531 void AliAnalysisManager::SetGlobalDbl(const char *key, Double_t value)
2533 // Define a custom double precision variable mapped to a global unique name. The variable
2534 // can be then retrieved by a given analysis macro via GetGlobalInt(key).
2535 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2537 ::Error("AliAnalysisManager::SetGlobalStr", "No analysis manager defined");
2540 Bool_t valid = kFALSE;
2541 Double_t existing = AliAnalysisManager::GetGlobalDbl(key, valid);
2543 ::Error("AliAnalysisManager::SetGlobalInt", "Global %s = %g already defined.", key, existing);
2546 mgr->GetGlobals()->Add(new TObjString(key), new TObjString(TString::Format("%f.16",value)));
2549 //______________________________________________________________________________
2550 Double_t AliAnalysisManager::GetGlobalDbl(const char *key, Bool_t &valid)
2552 // Static method to retrieve a global variable defined via SetGlobalDbl.
2554 AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
2556 TObject *value = mgr->GetGlobals()->GetValue(key);
2557 if (!value) return 0;
2559 TString s = value->GetName();
2563 //______________________________________________________________________________
2564 void AliAnalysisManager::AddClassDebug(const char *className, Int_t debugLevel)
2566 // Sets Class debug level
2568 if (!fDebugOptions) {
2569 fDebugOptions = new TObjArray();
2570 fDebugOptions->SetOwner(kTRUE);
2573 // substracting DebugOffset, beacuse of AliLog::SetClassDebugLevel()
2574 debugLevel -= AliLog::kDebug-1;
2576 TNamed *debugOpt = (TNamed*)fDebugOptions->FindObject(className);
2578 AliInfo(TString::Format("Adding debug level %d for class %s",debugLevel+AliLog::kDebug-1,className).Data());
2579 fDebugOptions->Add(new TNamed(className,TString::Format("%d",debugLevel).Data()));
2581 TString oldDebugStr = debugOpt->GetTitle();
2582 Int_t oldDebug = oldDebugStr.Atoi();
2583 if (debugLevel > oldDebug) {
2584 AliWarning(TString::Format("Overwriting debug level to %d class %s, because it is higher then previously set (%d).",debugLevel+AliLog::kDebug-1,className,oldDebug+AliLog::kDebug-1).Data());
2585 debugOpt->SetTitle(TString::Format("%d",debugLevel).Data());
2587 AliWarning(TString::Format("Ignoring debug level to %d class %s, because it is smaller then previously set (%d).",debugLevel+AliLog::kDebug-1,className,oldDebug+AliLog::kDebug-1).Data());
2592 //______________________________________________________________________________
2593 void AliAnalysisManager::ApplyDebugOptions()
2595 // Apply debug options
2597 if (!fDebugOptions) return;
2599 TIter next(fDebugOptions);
2602 while ((debug=dynamic_cast<TNamed*>(next()))) {
2603 debugLevel = debug->GetTitle();
2604 AliInfo(TString::Format("ApplyDebugOptions : Class=%s debulLevel=%d",debug->GetName(),debugLevel.Atoi()+AliLog::kDebug-1).Data());
2605 AliLog::SetClassDebugLevel(debug->GetName(), debugLevel.Atoi());