X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=ANALYSIS%2FAliAnalysisManager.cxx;h=4799fa59f3071b6b2253afb476374f678e74fd0a;hb=d759b4a464a594727296c2548257ae5ba5878f5b;hp=dedff7dd4aca41778f2cd6f653241a9d3342a5fd;hpb=096b5a2e0678c89d427cee88d6c69e7f030cac2c;p=u%2Fmrichter%2FAliRoot.git diff --git a/ANALYSIS/AliAnalysisManager.cxx b/ANALYSIS/AliAnalysisManager.cxx index dedff7dd4ac..4799fa59f30 100644 --- a/ANALYSIS/AliAnalysisManager.cxx +++ b/ANALYSIS/AliAnalysisManager.cxx @@ -17,7 +17,7 @@ // Author: Andrei Gheata, 31/05/2006 //============================================================================== -// AliAnalysysManager - Manager analysis class. Allows creation of several +// AliAnalysisManager - Manager analysis class. Allows creation of several // analysis tasks and data containers storing their input/output. Allows // connecting/chaining tasks via shared data containers. Serializes the current // event for all tasks depending only on initial input data. @@ -25,12 +25,13 @@ // //============================================================================== -#include +#include "AliAnalysisManager.h" +#include +#include #include #include #include -#include #include #include #include @@ -48,12 +49,13 @@ #include "AliVEventHandler.h" #include "AliVEventPool.h" #include "AliSysInfo.h" -#include "AliAnalysisManager.h" +#include "AliAnalysisStatistics.h" ClassImp(AliAnalysisManager) AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL; TString AliAnalysisManager::fgCommonFileName = ""; +Int_t AliAnalysisManager::fPBUpdateFreq = 1; //______________________________________________________________________________ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) @@ -67,6 +69,7 @@ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) fNSysInfo(0), fMode(kLocalAnalysis), fInitOK(kFALSE), + fIsRemote(kFALSE), fDebug(0), fSpecialOutputLocation(""), fTasks(NULL), @@ -75,11 +78,20 @@ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) fContainers(NULL), fInputs(NULL), fOutputs(NULL), + fParamCont(NULL), fCommonInput(NULL), fCommonOutput(NULL), fSelector(NULL), fGridHandler(NULL), - fExtraFiles("") + fExtraFiles(""), + fAutoBranchHandling(kTRUE), + fTable(), + fRunFromPath(0), + fNcalls(0), + fMaxEntries(0), + fStatisticsMsg(), + fRequestedBranches(), + fStatistics(0) { // Default constructor. fgAnalysisManager = this; @@ -90,6 +102,7 @@ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) fContainers = new TObjArray(); fInputs = new TObjArray(); fOutputs = new TObjArray(); + fParamCont = new TObjArray(); SetEventLoop(kTRUE); TObject::SetObjectStat(kFALSE); } @@ -106,6 +119,7 @@ AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other) fNSysInfo(0), fMode(other.fMode), fInitOK(other.fInitOK), + fIsRemote(other.fIsRemote), fDebug(other.fDebug), fSpecialOutputLocation(""), fTasks(NULL), @@ -114,11 +128,20 @@ AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other) fContainers(NULL), fInputs(NULL), fOutputs(NULL), + fParamCont(NULL), fCommonInput(NULL), fCommonOutput(NULL), fSelector(NULL), fGridHandler(NULL), - fExtraFiles() + fExtraFiles(), + fAutoBranchHandling(other.fAutoBranchHandling), + fTable(), + fRunFromPath(0), + fNcalls(other.fNcalls), + fMaxEntries(other.fMaxEntries), + fStatisticsMsg(other.fStatisticsMsg), + fRequestedBranches(other.fRequestedBranches), + fStatistics(other.fStatistics) { // Copy constructor. fTasks = new TObjArray(*other.fTasks); @@ -127,6 +150,7 @@ AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other) fContainers = new TObjArray(*other.fContainers); fInputs = new TObjArray(*other.fInputs); fOutputs = new TObjArray(*other.fOutputs); + fParamCont = new TObjArray(*other.fParamCont); fgCommonFileName = "AnalysisResults.root"; fgAnalysisManager = this; TObject::SetObjectStat(kFALSE); @@ -147,6 +171,7 @@ AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& othe fNSysInfo = other.fNSysInfo; fMode = other.fMode; fInitOK = other.fInitOK; + fIsRemote = other.fIsRemote; fDebug = other.fDebug; fTasks = new TObjArray(*other.fTasks); fTopTasks = new TObjArray(*other.fTopTasks); @@ -154,6 +179,7 @@ AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& othe fContainers = new TObjArray(*other.fContainers); fInputs = new TObjArray(*other.fInputs); fOutputs = new TObjArray(*other.fOutputs); + fParamCont = new TObjArray(*other.fParamCont); fCommonInput = NULL; fCommonOutput = NULL; fSelector = NULL; @@ -161,6 +187,14 @@ AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& othe fExtraFiles = other.fExtraFiles; fgCommonFileName = "AnalysisResults.root"; fgAnalysisManager = this; + fAutoBranchHandling = other.fAutoBranchHandling; + fTable.Clear("nodelete"); + fRunFromPath = other.fRunFromPath; + fNcalls = other. fNcalls; + fMaxEntries = other.fMaxEntries; + fStatisticsMsg = other.fStatisticsMsg; + fRequestedBranches = other.fRequestedBranches; + fStatistics = other.fStatistics; } return *this; } @@ -175,7 +209,12 @@ AliAnalysisManager::~AliAnalysisManager() if (fContainers) {fContainers->Delete(); delete fContainers;} if (fInputs) delete fInputs; if (fOutputs) delete fOutputs; + if (fParamCont) delete fParamCont; if (fGridHandler) delete fGridHandler; + if (fInputEventHandler) delete fInputEventHandler; + if (fOutputEventHandler) delete fOutputEventHandler; + if (fMCtruthEventHandler) delete fMCtruthEventHandler; + if (fEventPool) delete fEventPool; if (fgAnalysisManager==this) fgAnalysisManager = NULL; TObject::SetObjectStat(kTRUE); } @@ -185,9 +224,42 @@ Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall) { // Read one entry of the tree or a whole branch. fCurrentEntry = entry; - return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0; + if (!fAutoBranchHandling) + return 123456789; + return fTree ? fTree->GetTree()->GetEntry(entry, getall) : -1; } - + +//______________________________________________________________________________ +Int_t AliAnalysisManager::GetRunFromAlienPath(const char *path) +{ +// Attempt to extract run number from input data path. Works only for paths to +// alice data in alien. +// sim: /alice/sim//run_no/... +// data: /alice/data/year/period/000run_no/... (ESD or AOD) + TString s(path); + TString srun; + Int_t run = 0; + Int_t index = s.Index("/alice/sim"); + if (index >= 0) { + for (Int_t i=0; i<3; i++) { + index = s.Index("/", index+1); + if (index<0) return 0; + } + srun = s(index+1,6); + run = atoi(srun); + } + index = s.Index("/alice/data"); + if (index >= 0) { + for (Int_t i=0; i<4; i++) { + index = s.Index("/", index+1); + if (index<0) return 0; + } + srun = s(index+1,9); + run = atoi(srun); + } + return run; +} + //______________________________________________________________________________ Bool_t AliAnalysisManager::Init(TTree *tree) { @@ -198,7 +270,7 @@ Bool_t AliAnalysisManager::Init(TTree *tree) // Init() will be called many times when running with PROOF. Bool_t init = kFALSE; if (!tree) return kFALSE; // Should not happen - protected in selector caller - if (fDebug > 0) { + if (fDebug > 1) { printf("->AliAnalysisManager::Init(%s)\n", tree->GetName()); } // Call InitTree of EventHandler @@ -230,7 +302,7 @@ Bool_t AliAnalysisManager::Init(TTree *tree) if(!tree->GetTree()) { Long64_t readEntry = tree->LoadTree(0); if (readEntry == -2) { - Error("Init", "Input tree has no entry. Aborting"); + Error("Init", "Input tree has no entry. Exiting"); return kFALSE; } } @@ -251,6 +323,7 @@ Bool_t AliAnalysisManager::Init(TTree *tree) if (!fInitOK) InitAnalysis(); if (!fInitOK) return kFALSE; fTree = tree; + fTable.Rehash(100); AliAnalysisDataContainer *top = fCommonInput; if (!top) top = (AliAnalysisDataContainer*)fInputs->At(0); if (!top) { @@ -258,7 +331,8 @@ Bool_t AliAnalysisManager::Init(TTree *tree) return kFALSE; } top->SetData(tree); - if (fDebug > 0) { + CheckBranches(kFALSE); + if (fDebug > 1) { printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName()); } return kTRUE; @@ -270,7 +344,8 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) // The SlaveBegin() function is called after the Begin() function. // When running with PROOF SlaveBegin() is called on each slave server. // The tree argument is deprecated (on PROOF 0 is passed). - if (fDebug > 0) printf("->AliAnalysisManager::SlaveBegin()\n"); + if (fDebug > 1) printf("->AliAnalysisManager::SlaveBegin()\n"); + if (!CheckTasks()) Fatal("SlaveBegin", "Not all needed libraries were loaded"); static Bool_t isCalled = kFALSE; Bool_t init = kFALSE; Bool_t initOK = kTRUE; @@ -278,6 +353,7 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) TDirectory *curdir = gDirectory; // Call SlaveBegin only once in case of mixing if (isCalled && fMode==kMixingAnalysis) return; + gROOT->cd(); // Call Init of EventHandler if (fOutputEventHandler) { if (fMode == kProofAnalysis) { @@ -293,7 +369,7 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) if (!fSelector) Error("SlaveBegin", "Selector not set"); else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);} } - + gROOT->cd(); if (fInputEventHandler) { fInputEventHandler->SetInputTree(tree); if (fMode == kProofAnalysis) { @@ -307,7 +383,7 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) if (!fSelector) Error("SlaveBegin", "Selector not set"); else if (!init) {fSelector->Abort(msg); fSelector->SetStatus(-1);} } - + gROOT->cd(); if (fMCtruthEventHandler) { if (fMode == kProofAnalysis) { init = fMCtruthEventHandler->Init("proof"); @@ -327,15 +403,24 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) AliAnalysisTask *task; // Call CreateOutputObjects for all tasks Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE; + Bool_t dirStatus = TH1::AddDirectoryStatus(); Int_t itask = 0; while ((task=(AliAnalysisTask*)next())) { - curdir = gDirectory; + gROOT->cd(); + // Start with memory as current dir and make sure by default histograms do not get attached to files. + TH1::AddDirectory(kFALSE); task->CreateOutputObjects(); + if (!task->CheckPostData()) { + Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\ + Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\ + ####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", task->GetName(), task->ClassName()); + } if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0); itask++; - if (curdir) curdir->cd(); } - if (fDebug > 0) printf("<-AliAnalysisManager::SlaveBegin()\n"); + TH1::AddDirectory(dirStatus); + if (curdir) curdir->cd(); + if (fDebug > 1) printf("<-AliAnalysisManager::SlaveBegin()\n"); } //______________________________________________________________________________ @@ -348,18 +433,21 @@ Bool_t AliAnalysisManager::Notify() // user if needed. The return value is currently not used. if (!fTree) return kFALSE; + fTable.Clear("nodelete"); // clearing the hash table may not be needed -> C.L. + if (fMode == kProofAnalysis) fIsRemote = kTRUE; + TFile *curfile = fTree->GetCurrentFile(); if (!curfile) { Error("Notify","No current file"); return kFALSE; } - if (fDebug > 0) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName()); + if (fDebug > 1) printf("->AliAnalysisManager::Notify() file: %s\n", curfile->GetName()); + Int_t run = AliAnalysisManager::GetRunFromAlienPath(curfile->GetName()); + if (run) SetRunFromPath(run); + if (fDebug > 1) printf(" ### run found from path: %d\n", run); TIter next(fTasks); AliAnalysisTask *task; - // Call Notify for all tasks - while ((task=(AliAnalysisTask*)next())) - task->Notify(); // Call Notify of the event handlers if (fInputEventHandler) { @@ -373,7 +461,12 @@ Bool_t AliAnalysisManager::Notify() if (fMCtruthEventHandler) { fMCtruthEventHandler->Notify(curfile->GetName()); } - if (fDebug > 0) printf("<-AliAnalysisManager::Notify()\n"); + + // Call Notify for all tasks + while ((task=(AliAnalysisTask*)next())) + task->Notify(); + + if (fDebug > 1) printf("<-AliAnalysisManager::Notify()\n"); return kTRUE; } @@ -397,15 +490,18 @@ Bool_t AliAnalysisManager::Process(Long64_t entry) // The entry is always the local entry number in the current tree. // Assuming that fChain is the pointer to the TChain being processed, // use fChain->GetTree()->GetEntry(entry). - if (fDebug > 0) printf("->AliAnalysisManager::Process(%lld)\n", entry); + if (fDebug > 1) printf("->AliAnalysisManager::Process(%lld)\n", entry); if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry); if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry); if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry); GetEntry(entry); + + if (fInputEventHandler) fInputEventHandler ->GetEntry(); + ExecAnalysis(); - if (fDebug > 0) printf("<-AliAnalysisManager::Process()\n"); + if (fDebug > 1) printf("<-AliAnalysisManager::Process()\n"); return kTRUE; } @@ -414,14 +510,17 @@ void AliAnalysisManager::PackOutput(TList *target) { // Pack all output data containers in the output list. Called at SlaveTerminate // stage in PROOF case for each slave. - if (fDebug > 0) printf("->AliAnalysisManager::PackOutput()\n"); + if (fDebug > 1) printf("->AliAnalysisManager::PackOutput()\n"); if (!target) { - Error("PackOutput", "No target. Aborting."); + Error("PackOutput", "No target. Exiting."); return; } + TDirectory *cdir = gDirectory; + gROOT->cd(); if (fInputEventHandler) fInputEventHandler ->Terminate(); if (fOutputEventHandler) fOutputEventHandler ->Terminate(); if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate(); + gROOT->cd(); // Call FinishTaskOutput() for each event loop task (not called for // post-event loop tasks - use Terminate() fo those) @@ -429,20 +528,25 @@ void AliAnalysisManager::PackOutput(TList *target) AliAnalysisTask *task; while ((task=(AliAnalysisTask*)nexttask())) { if (!task->IsPostEventLoop()) { - if (fDebug > 0) printf("->FinishTaskOutput: task %s\n", task->GetName()); + if (fDebug > 1) printf("->FinishTaskOutput: task %s\n", task->GetName()); task->FinishTaskOutput(); - if (fDebug > 0) printf("<-FinishTaskOutput: task %s\n", task->GetName()); + gROOT->cd(); + if (fDebug > 1) printf("<-FinishTaskOutput: task %s\n", task->GetName()); } - } + } + // Write statistics message on the workers. + if (fStatistics) WriteStatisticsMsg(fNcalls); if (fMode == kProofAnalysis) { TIter next(fOutputs); AliAnalysisDataContainer *output; Bool_t isManagedByHandler = kFALSE; + TList filestmp; + filestmp.SetOwner(); while ((output=(AliAnalysisDataContainer*)next())) { // Do not consider outputs of post event loop tasks isManagedByHandler = kFALSE; - if (output->GetProducer()->IsPostEventLoop()) continue; + if (output->GetProducer() && output->GetProducer()->IsPostEventLoop()) continue; const char *filename = output->GetFileName(); if (!(strcmp(filename, "default")) && fOutputEventHandler) { isManagedByHandler = kTRUE; @@ -461,33 +565,43 @@ void AliAnalysisManager::PackOutput(TList *target) TDirectory *opwd = gDirectory; // File resident outputs. // Check first if the file exists. - TString open_option = "RECREATE"; - if (!gSystem->AccessPathName(output->GetFileName())) open_option = "UPDATE"; - TFile *file = AliAnalysisManager::OpenFile(output, open_option, kTRUE); - // Clear file list to release object ownership to user. - file->Clear(); + TString openoption = "RECREATE"; + Bool_t firsttime = kTRUE; + if (filestmp.FindObject(output->GetFileName())) { + firsttime = kFALSE; + } else { + filestmp.Add(new TNamed(output->GetFileName(),"")); + } + if (!gSystem->AccessPathName(output->GetFileName()) && !firsttime) openoption = "UPDATE"; +// TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE); // Save data to file, then close. if (output->GetData()->InheritsFrom(TCollection::Class())) { // If data is a collection, we set the name of the collection // as the one of the container and we save as a single key. TCollection *coll = (TCollection*)output->GetData(); coll->SetName(output->GetName()); - coll->Write(output->GetName(), TObject::kSingleKey); +// coll->Write(output->GetName(), TObject::kSingleKey); } else { if (output->GetData()->InheritsFrom(TTree::Class())) { + TFile *file = AliAnalysisManager::OpenFile(output, openoption, kTRUE); + // Save data to file, then close. TTree *tree = (TTree*)output->GetData(); - // tree->SetDirectory(file); + // Check if tree is in memory + if (tree->GetDirectory()==gROOT) tree->SetDirectory(gDirectory); tree->AutoSave(); + file->Close(); } else { - output->GetData()->Write(); +// output->GetData()->Write(); } } if (fDebug > 1) printf("PackOutput %s: memory merge, file resident output\n", output->GetName()); - if (fDebug > 2) { - printf(" file %s listing content:\n", filename); - file->ls(); - } - file->Close(); +// if (fDebug > 2) { +// printf(" file %s listing content:\n", filename); +// file->ls(); +// } + // Clear file list to release object ownership to user. +// file->Clear(); +// file->Close(); output->SetFile(NULL); // Restore current directory if (opwd) opwd->cd(); @@ -544,11 +658,12 @@ void AliAnalysisManager::PackOutput(TList *target) output->GetData()->Write(); } } - file->Clear(); if (fDebug > 2) { printf(" file %s listing content:\n", output->GetFileName()); file->ls(); } + // Clear file list to release object ownership to user. +// file->Clear(); file->Close(); output->SetFile(NULL); } @@ -559,8 +674,8 @@ void AliAnalysisManager::PackOutput(TList *target) TString remote = fSpecialOutputLocation; remote += "/"; Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();"); - if (remote.BeginsWith("alien://")) { - gROOT->ProcessLine("TGrid::Connect(\"alien://pcapiserv01.cern.ch:10000\", gProofServ->GetUser());"); + if (remote.BeginsWith("alien:")) { + gROOT->ProcessLine("TGrid::Connect(\"alien:\", gProofServ->GetUser());"); remote += outFilename; remote.ReplaceAll(".root", Form("_%d.root", gid)); } else { @@ -602,14 +717,15 @@ void AliAnalysisManager::PackOutput(TList *target) } } } - if (fDebug > 0) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize()); + cdir->cd(); + if (fDebug > 1) printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize()); } //______________________________________________________________________________ void AliAnalysisManager::ImportWrappers(TList *source) { // Import data in output containers from wrappers coming in source. - if (fDebug > 0) printf("->AliAnalysisManager::ImportWrappers()\n"); + if (fDebug > 1) printf("->AliAnalysisManager::ImportWrappers()\n"); TIter next(fOutputs); AliAnalysisDataContainer *cont; AliAnalysisDataWrapper *wrap; @@ -618,7 +734,7 @@ void AliAnalysisManager::ImportWrappers(TList *source) TDirectory *cdir = gDirectory; while ((cont=(AliAnalysisDataContainer*)next())) { wrap = 0; - if (cont->GetProducer()->IsPostEventLoop() && !inGrid) continue; + if (cont->GetProducer() && cont->GetProducer()->IsPostEventLoop() && !inGrid) continue; if (cont->IsRegisterDataset()) continue; const char *filename = cont->GetFileName(); Bool_t isManagedByHandler = kFALSE; @@ -657,8 +773,8 @@ void AliAnalysisManager::ImportWrappers(TList *source) // Try to fetch first an object having the container name. obj = gDirectory->Get(cont->GetName()); if (!obj) { - Warning("ImportWrappers", "Could not import object for container %s in file %s:%s.\n Object will not be available in Terminate()", - cont->GetName(), filename, cont->GetFolderName()); + 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", + cont->GetType()->GetName(), cont->GetName(), filename, cont->GetFolderName(), cont->GetName()); continue; } wrap = new AliAnalysisDataWrapper(obj); @@ -678,16 +794,16 @@ void AliAnalysisManager::ImportWrappers(TList *source) cont->ImportData(wrap); } if (cdir) cdir->cd(); - if (fDebug > 0) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont); + if (fDebug > 1) printf("<-AliAnalysisManager::ImportWrappers(): %d containers imported\n", icont); } //______________________________________________________________________________ void AliAnalysisManager::UnpackOutput(TList *source) { // Called by AliAnalysisSelector::Terminate only on the client. - if (fDebug > 0) printf("->AliAnalysisManager::UnpackOutput()\n"); + if (fDebug > 1) printf("->AliAnalysisManager::UnpackOutput()\n"); if (!source) { - Error("UnpackOutput", "No target. Aborting."); + Error("UnpackOutput", "No target. Exiting."); return; } if (fDebug > 1) printf(" Source list contains %d containers\n", source->GetSize()); @@ -709,13 +825,13 @@ void AliAnalysisManager::UnpackOutput(TList *source) task->CheckNotify(kTRUE); // If task is active, execute it if (task->IsPostEventLoop() && task->IsActive()) { - if (fDebug > 0) printf("== Executing post event loop task %s\n", task->GetName()); + if (fDebug > 1) printf("== Executing post event loop task %s\n", task->GetName()); task->ExecuteTask(); } } } } - if (fDebug > 0) printf("<-AliAnalysisManager::UnpackOutput()\n"); + if (fDebug > 1) printf("<-AliAnalysisManager::UnpackOutput()\n"); } //______________________________________________________________________________ @@ -724,7 +840,9 @@ void AliAnalysisManager::Terminate() // The Terminate() function is the last function to be called during // a query. It always runs on the client, it can be used to present // the results graphically. - if (fDebug > 0) printf("->AliAnalysisManager::Terminate()\n"); + if (fDebug > 1) printf("->AliAnalysisManager::Terminate()\n"); + TDirectory *cdir = gDirectory; + gROOT->cd(); AliAnalysisTask *task; AliAnalysisDataContainer *output; TIter next(fTasks); @@ -736,12 +854,13 @@ void AliAnalysisManager::Terminate() // Save all the canvases produced by the Terminate TString pictname = Form("%s_%s", task->GetName(), task->ClassName()); task->Terminate(); + gROOT->cd(); if (getsysInfo) AliSysInfo::AddStamp(Form("%s_TERMINATE",task->ClassName()),0, itask, 2); itask++; if (TObject::TestBit(kSaveCanvases)) { if (!gROOT->IsBatch()) { - if (fDebug>0) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...", task->ClassName()); + if (fDebug>1) printf("Waiting 5 sec for %s::Terminate() to finish drawing ...\n", task->ClassName()); timer.Start(); while (timer.CpuTime()<5) { timer.Continue(); @@ -763,19 +882,30 @@ void AliAnalysisManager::Terminate() if (fInputEventHandler) fInputEventHandler ->TerminateIO(); if (fOutputEventHandler) fOutputEventHandler ->TerminateIO(); if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO(); - TIter next1(fOutputs); + gROOT->cd(); + TObjArray *allOutputs = new TObjArray(); + Int_t icont; + for (icont=0; icontGetEntriesFast(); icont++) allOutputs->Add(fOutputs->At(icont)); + if (!IsSkipTerminate()) + for (icont=0; icontGetEntriesFast(); icont++) allOutputs->Add(fParamCont->At(icont)); + TIter next1(allOutputs); TString handlerFile = ""; + TString extraOutputs = ""; if (fOutputEventHandler) { handlerFile = fOutputEventHandler->GetOutputFileName(); + extraOutputs = fOutputEventHandler->GetExtraOutputs(); } + icont = 0; + TList filestmp; while ((output=(AliAnalysisDataContainer*)next1())) { // Special outputs or grid files have the files already closed and written. - if (fMode == kGridAnalysis) continue; + icont++; + if (fMode == kGridAnalysis && icont<=fOutputs->GetEntriesFast()) continue; if (fMode == kProofAnalysis) { if (output->IsSpecialOutput() || output->IsRegisterDataset()) continue; } const char *filename = output->GetFileName(); - TString open_option = "RECREATE"; + TString openoption = "RECREATE"; if (!(strcmp(filename, "default"))) continue; if (!strlen(filename)) continue; if (!output->GetData()) continue; @@ -783,11 +913,24 @@ void AliAnalysisManager::Terminate() TFile *file = output->GetFile(); if (!file) file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); if (!file) { - printf("Terminate : handlerFile = %s, filename = %s\n",handlerFile.Data(),filename); - //if (handlerFile == filename && !gSystem->AccessPathName(filename)) open_option = "UPDATE"; - if (!gSystem->AccessPathName(filename)) open_option = "UPDATE"; - file = new TFile(filename, open_option); - } + //if (handlerFile == filename && !gSystem->AccessPathName(filename)) openoption = "UPDATE"; + Bool_t firsttime = kTRUE; + if (filestmp.FindObject(filename) || extraOutputs.Contains(filename)) { + firsttime = kFALSE; + } else { + filestmp.Add(new TNamed(filename,"")); + } + if (!gSystem->AccessPathName(filename) && !firsttime) openoption = "UPDATE"; + if (fDebug>1) printf("Opening file: %s option=%s\n",filename, openoption.Data()); + file = new TFile(filename, openoption); + } else { + if (fDebug>1) printf("File <%s> already opened with option: <%s> \n", filename, file->GetOption()); + openoption = file->GetOption(); + if (openoption == "READ") { + if (fDebug>1) printf("...reopening in UPDATE mode\n"); + file->ReOpen("UPDATE"); + } + } if (file->IsZombie()) { Error("Terminate", "Cannot open output file %s", filename); continue; @@ -800,7 +943,7 @@ void AliAnalysisManager::Terminate() if (!file->GetDirectory(dir)) file->mkdir(dir); file->cd(dir); } - if (fDebug > 1) printf(" writing output data %s to file %s:%s\n", output->GetData()->GetName(), file->GetName(), output->GetFolderName()); + if (fDebug > 1) printf("...writing container %s to file %s:%s\n", output->GetName(), file->GetName(), output->GetFolderName()); if (output->GetData()->InheritsFrom(TCollection::Class())) { // If data is a collection, we set the name of the collection // as the one of the container and we save as a single key. @@ -810,19 +953,22 @@ void AliAnalysisManager::Terminate() } else { if (output->GetData()->InheritsFrom(TTree::Class())) { TTree *tree = (TTree*)output->GetData(); - tree->SetDirectory(file); + tree->SetDirectory(gDirectory); tree->AutoSave(); } else { output->GetData()->Write(); } } if (opwd) opwd->cd(); - } + } + gROOT->cd(); next1.Reset(); while ((output=(AliAnalysisDataContainer*)next1())) { // Close all files at output TDirectory *opwd = gDirectory; if (output->GetFile()) { + // Clear file list to release object ownership to user. +// output->GetFile()->Clear(); output->GetFile()->Close(); output->SetFile(NULL); // Copy merged outputs in alien if requested @@ -835,9 +981,11 @@ void AliAnalysisManager::Terminate() } if (opwd) opwd->cd(); } - + delete allOutputs; + //Write statistics information on the client + if (fStatistics) WriteStatisticsMsg(fNcalls); if (getsysInfo) { - TDirectory *cdir = gDirectory; + TDirectory *crtdir = gDirectory; TFile f("syswatch.root", "RECREATE"); TH1 *hist; TString cut; @@ -869,15 +1017,15 @@ void AliAnalysisManager::Terminate() canvas->Divide(iopt+1, iopt+1, 0.01, 0.01); Int_t ipad = 1; // draw the plot of deltaVM for Exec for each task - for (Int_t itask=0; itaskGetEntriesFast(); itask++) { + for (itask=0; itaskGetEntriesFast(); itask++) { task = (AliAnalysisTask*)fTopTasks->At(itask); canvas->cd(ipad++); cut = Form("task==%d && stage==1", itask); tree->Draw("deltaVM:event",cut,"", 1234567890, 0); hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp"); if (hist) { - hist->SetTitle(Form("%s: Exec dVM[kB]/event", task->GetName())); - hist->GetYaxis()->SetTitle("deltaVM [kB]"); + hist->SetTitle(Form("%s: Exec dVM[MB]/event", task->GetName())); + hist->GetYaxis()->SetTitle("deltaVM [MB]"); } } // Draw the plot of deltaVM for CreateOutputObjects for all tasks @@ -890,7 +1038,7 @@ void AliAnalysisManager::Terminate() hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp"); if (hist) { hist->SetTitle("Memory in CreateOutputObjects()"); - hist->GetYaxis()->SetTitle("deltaVM [kB]"); + hist->GetYaxis()->SetTitle("deltaVM [MB]"); hist->GetXaxis()->SetTitle("task"); } // draw the plot of deltaVM for Terminate for all tasks @@ -902,7 +1050,7 @@ void AliAnalysisManager::Terminate() hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp"); if (hist) { hist->SetTitle("Memory in Terminate()"); - hist->GetYaxis()->SetTitle("deltaVM [kB]"); + hist->GetYaxis()->SetTitle("deltaVM [MB]"); hist->GetXaxis()->SetTitle("task"); } // Full VM profile @@ -914,7 +1062,7 @@ void AliAnalysisManager::Terminate() hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp"); if (hist) { hist->SetTitle("Virtual memory"); - hist->GetYaxis()->SetTitle("VM [kB]"); + hist->GetYaxis()->SetTitle("VM [MB]"); } canvas->Modified(); } @@ -925,15 +1073,16 @@ void AliAnalysisManager::Terminate() f.Close(); delete tree; } - if (cdir) cdir->cd(); + if (crtdir) crtdir->cd(); } // Validate the output files - if (ValidateOutputFiles()) { + if (ValidateOutputFiles() && fIsRemote && fMode!=kProofAnalysis) { ofstream out; out.open("outputs_valid", ios::out); out.close(); - } - if (fDebug > 0) printf("<-AliAnalysisManager::Terminate()\n"); + } + cdir->cd(); + if (fDebug > 1) printf("<-AliAnalysisManager::Terminate()\n"); } //______________________________________________________________________________ void AliAnalysisManager::ProfileTask(Int_t itop, const char *option) const @@ -972,7 +1121,7 @@ void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) c Error("ProfileTask", "No tree named found in file syswatch.root"); return; } - if (fDebug > 0) printf("=== Profiling task %s (class %s)\n", name, task->ClassName()); + if (fDebug > 1) printf("=== Profiling task %s (class %s)\n", name, task->ClassName()); TCanvas *canvas = new TCanvas(Form("profile_%d",itop),Form("Profile of task %s (class %s)",name,task->ClassName()),10,10,800,600); canvas->Divide(2, 2, 0.01, 0.01); Int_t ipad = 1; @@ -984,8 +1133,8 @@ void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) c tree->Draw("deltaVM:sname",cut,"", 1234567890, 0); hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp"); if (hist) { - hist->SetTitle("Alocated VM[kB] for COO and Terminate"); - hist->GetYaxis()->SetTitle("deltaVM [kB]"); + hist->SetTitle("Alocated VM[MB] for COO and Terminate"); + hist->GetYaxis()->SetTitle("deltaVM [MB]"); hist->GetXaxis()->SetTitle("method"); } // CPU profile per event @@ -1003,8 +1152,8 @@ void AliAnalysisManager::ProfileTask(const char *name, const char */*option*/) c tree->Draw("deltaVM:event",cut,"", 1234567890, 0); hist = (TH1*)gPad->GetListOfPrimitives()->FindObject("htemp"); if (hist) { - hist->SetTitle("Alocated VM[kB] per event"); - hist->GetYaxis()->SetTitle("deltaVM [kB]"); + hist->SetTitle("Alocated VM[MB] per event"); + hist->GetYaxis()->SetTitle("deltaVM [MB]"); } canvas->Modified(); delete tree; @@ -1059,6 +1208,13 @@ AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, cont->SetDataOwned(kFALSE); // data owned by the file } break; + case kParamContainer: + fParamCont->Add(cont); + if (filename && strlen(filename)) { + cont->SetFileName(filename); + cont->SetDataOwned(kFALSE); // data owned by the file + } + break; case kExchangeContainer: break; } @@ -1210,11 +1366,98 @@ Bool_t AliAnalysisManager::InitAnalysis() Error("InitAnalysis", "Wrong container %s : a file name MUST be provided for special outputs", cont->GetName()); return kFALSE; } - } + } + // Initialize requested branch list if needed + if (!fAutoBranchHandling) { + next.Reset(); + while ((task=(AliAnalysisTask*)next())) { + if (!task->HasBranches()) { + 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\"", + task->GetName(), task->ClassName()); + return kFALSE; + } + if (!fInputEventHandler || !strlen(fInputEventHandler->GetDataType())) { + Error("InitAnalysis", "Manual branch loading requested but no input handler defined or handler does not define data type."); + return kFALSE; + } + TString taskbranches; + task->GetBranches(fInputEventHandler->GetDataType(), taskbranches); + if (taskbranches.IsNull()) { + Error("InitAnalysis", "Manual branch loading requested but task %s of type %s does not define branches of type %s:", + task->GetName(), task->ClassName(), fInputEventHandler->GetDataType()); + return kFALSE; + } + AddBranches(taskbranches); + } + } fInitOK = kTRUE; return kTRUE; } +//______________________________________________________________________________ +void AliAnalysisManager::AddBranches(const char *branches) +{ +// Add branches to the existing fRequestedBranches. + TString br(branches); + TObjArray *arr = br.Tokenize(","); + TIter next(arr); + TObject *obj; + while ((obj=next())) { + if (!fRequestedBranches.Contains(obj->GetName())) { + if (!fRequestedBranches.IsNull()) fRequestedBranches += ","; + fRequestedBranches += obj->GetName(); + } + } + delete arr; +} + +//______________________________________________________________________________ +void AliAnalysisManager::CheckBranches(Bool_t load) +{ +// The method checks the input branches to be loaded during the analysis. + if (fAutoBranchHandling || fRequestedBranches.IsNull() || !fTree) return; + TObjArray *arr = fRequestedBranches.Tokenize(","); + TIter next(arr); + TObject *obj; + while ((obj=next())) { + TBranch *br = dynamic_cast(fTable.FindObject(obj->GetName())); + if (!br) { + br = fTree->GetBranch(obj->GetName()); + if (!br) { + Error("CheckBranches", "Could not find branch %s",obj->GetName()); + continue; + } + } + fTable.Add(br); + if (load && br->GetReadEntry()!=GetCurrentEntry()) br->GetEntry(GetCurrentEntry()); + } + delete arr; +} + +//______________________________________________________________________________ +Bool_t AliAnalysisManager::CheckTasks() const +{ +// Check consistency of tasks. + Int_t ntasks = fTasks->GetEntries(); + if (!ntasks) { + Error("CheckTasks", "No tasks connected to the manager. This may be due to forgetting to compile the task or to load their library."); + return kFALSE; + } + // Get the pointer to AliAnalysisTaskSE::Class() + TClass *badptr = (TClass*)gROOT->ProcessLine("AliAnalysisTaskSE::Class()"); + // Loop all tasks to check if their corresponding library was loaded + TIter next(fTasks); + TObject *obj; + while ((obj=next())) { + if (obj->IsA() == badptr) { + Error("CheckTasks", "##################\n \ + Class for task %s NOT loaded. You probably forgot to load the library for this task (or compile it dynamically).\n###########################\n",obj->GetName()); + return kFALSE; + } + } + return kTRUE; +} + //______________________________________________________________________________ void AliAnalysisManager::PrintStatus(Option_t *option) const { @@ -1230,6 +1473,22 @@ void AliAnalysisManager::PrintStatus(Option_t *option) const AliAnalysisTask *task; while ((task=(AliAnalysisTask*)next())) task->PrintTask(option); + + if (!fAutoBranchHandling && !fRequestedBranches.IsNull()) + printf("Requested input branches:\n%s\n", fRequestedBranches.Data()); + + TString sopt(option); + sopt.ToUpper(); + + if (sopt.Contains("ALL")) + { + if ( fOutputEventHandler ) + { + cout << TString('_',78) << endl; + cout << "OutputEventHandler:" << endl; + fOutputEventHandler->Print(" "); + } + } } //______________________________________________________________________________ @@ -1240,63 +1499,93 @@ void AliAnalysisManager::ResetAnalysis() } //______________________________________________________________________________ -Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry) +Long64_t AliAnalysisManager::StartAnalysis(const char *type, Long64_t nentries, Long64_t firstentry) +{ +// Start analysis having a grid handler. + if (!fGridHandler) { + Error("StartAnalysis", "Cannot start analysis providing just the analysis type without a grid handler."); + Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it."); + return -1; + } + TTree *tree = NULL; + return StartAnalysis(type, tree, nentries, firstentry); +} + +//______________________________________________________________________________ +Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree * const tree, Long64_t nentries, Long64_t firstentry) { // Start analysis for this manager. Analysis task can be: LOCAL, PROOF, GRID or // MIX. Process nentries starting from firstentry Long64_t retv = 0; + // Backup current directory and make sure gDirectory points to gROOT + TDirectory *cdir = gDirectory; + gROOT->cd(); if (!fInitOK) { Error("StartAnalysis","Analysis manager was not initialized !"); + cdir->cd(); return -1; } - if (fDebug > 0) printf("StartAnalysis %s\n",GetName()); + if (!CheckTasks()) Fatal("StartAnalysis", "Not all needed libraries were loaded"); + if (fDebug > 1) printf("StartAnalysis %s\n",GetName()); + fMaxEntries = nentries; + fIsRemote = kFALSE; TString anaType = type; anaType.ToLower(); fMode = kLocalAnalysis; Bool_t runlocalinit = kTRUE; if (anaType.Contains("file")) { runlocalinit = kFALSE; + fIsRemote = kTRUE; } if (anaType.Contains("proof")) fMode = kProofAnalysis; else if (anaType.Contains("grid")) fMode = kGridAnalysis; else if (anaType.Contains("mix")) fMode = kMixingAnalysis; if (fMode == kGridAnalysis) { - if (!fGridHandler) { - Error("StartAnalysis", "Cannot start grid analysis without a grid handler."); - Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it."); - return -1; - } - // Write analysis manager in the analysis file - cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl; - // run local task configuration - TIter nextTask(fTasks); - AliAnalysisTask *task; - while ((task=(AliAnalysisTask*)nextTask())) { - task->LocalInit(); - } - if (!fGridHandler->StartAnalysis(nentries, firstentry)) { - Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated"); - return -1; - } + fIsRemote = kTRUE; + if (!anaType.Contains("terminate")) { + if (!fGridHandler) { + Error("StartAnalysis", "Cannot start grid analysis without a grid handler."); + Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it."); + cdir->cd(); + return -1; + } + // Write analysis manager in the analysis file + cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl; + // run local task configuration + TIter nextTask(fTasks); + AliAnalysisTask *task; + while ((task=(AliAnalysisTask*)nextTask())) { + task->LocalInit(); + gROOT->cd(); + } + if (!fGridHandler->StartAnalysis(nentries, firstentry)) { + Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated"); + cdir->cd(); + return -1; + } - // Terminate grid analysis - if (fSelector && fSelector->GetStatus() == -1) return -1; - if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) return 0; - cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl; - if (!fGridHandler->MergeOutputs()) { - // Return if outputs could not be merged or if it alien handler - // was configured for offline mode or local testing. - return 0; - } + // Terminate grid analysis + if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;} + if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;} + cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl; + if (!fGridHandler->MergeOutputs()) { + // Return if outputs could not be merged or if it alien handler + // was configured for offline mode or local testing. + cdir->cd(); + return 0; + } + } + cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl; ImportWrappers(NULL); Terminate(); + cdir->cd(); return 0; } - char line[256]; + TString line; SetEventLoop(kFALSE); // Enable event loop mode if a tree was provided - if (tree || fMode==kMixingAnalysis) SetEventLoop(kTRUE); + if (tree || fGridHandler || fMode==kMixingAnalysis) SetEventLoop(kTRUE); TChain *chain = 0; TString ttype = "TTree"; @@ -1304,6 +1593,7 @@ Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64 chain = (TChain*)tree; if (!chain || !chain->GetListOfFiles()->First()) { Error("StartAnalysis", "Cannot process null or empty chain..."); + cdir->cd(); return -1; } ttype = "TChain"; @@ -1317,60 +1607,125 @@ Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64 if (runlocalinit) { while ((task=(AliAnalysisTask*)next())) { task->LocalInit(); + gROOT->cd(); } if (getsysInfo) AliSysInfo::AddStamp("LocalInit_all", 0); } switch (fMode) { case kLocalAnalysis: - if (!tree) { + if (!tree && !fGridHandler) { TIter nextT(fTasks); // Call CreateOutputObjects for all tasks Int_t itask = 0; + Bool_t dirStatus = TH1::AddDirectoryStatus(); while ((task=(AliAnalysisTask*)nextT())) { - TDirectory *curdir = gDirectory; + TH1::AddDirectory(kFALSE); task->CreateOutputObjects(); + if (!task->CheckPostData()) { + Error("SlaveBegin","####### IMPORTANT! ####### \n\n\n\ + Task %s (%s) did not call PostData() for all its outputs in (User)CreateOutputObjects()\n\n\ + ########### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ###########", task->GetName(), task->ClassName()); + } if (getsysInfo) AliSysInfo::AddStamp(Form("%s_CREATEOUTOBJ",task->ClassName()), 0, itask, 0); - if (curdir) curdir->cd(); + gROOT->cd(); itask++; } + TH1::AddDirectory(dirStatus); if (IsExternalLoop()) { Info("StartAnalysis", "Initialization done. Event loop is controlled externally.\ \nSetData for top container, call ExecAnalysis in a loop and then Terminate manually"); return 0; - } + } ExecAnalysis(); Terminate(); return 0; } + fSelector = new AliAnalysisSelector(this); + // Check if a plugin handler is used + if (fGridHandler) { + // Get the chain from the plugin + TString dataType = "esdTree"; + if (fInputEventHandler) { + dataType = fInputEventHandler->GetDataType(); + dataType.ToLower(); + dataType += "Tree"; + } + chain = fGridHandler->GetChainForTestMode(dataType); + if (!chain) { + Error("StartAnalysis", "No chain for test mode. Aborting."); + return -1; + } + cout << "===== RUNNING LOCAL ANALYSIS" << GetName() << " ON CHAIN " << chain->GetName() << endl; + retv = chain->Process(fSelector, "", nentries, firstentry); + break; + } // Run tree-based analysis via AliAnalysisSelector cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl; - fSelector = new AliAnalysisSelector(this); retv = tree->Process(fSelector, "", nentries, firstentry); break; case kProofAnalysis: + fIsRemote = kTRUE; + // Check if the plugin is used + if (fGridHandler) { + return StartAnalysis(type, fGridHandler->GetProofDataSet(), nentries, firstentry); + } if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) { - Error("StartAnalysis", "No PROOF!!! Aborting."); + Error("StartAnalysis", "No PROOF!!! Exiting."); + cdir->cd(); return -1; } - sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this); + line = Form("gProof->AddInput((TObject*)%p);", this); gROOT->ProcessLine(line); if (chain) { chain->SetProof(); cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl; retv = chain->Process("AliAnalysisSelector", "", nentries, firstentry); } else { - Error("StartAnalysis", "No chain!!! Aborting."); + Error("StartAnalysis", "No chain!!! Exiting."); + cdir->cd(); return -1; } break; case kGridAnalysis: - Warning("StartAnalysis", "GRID analysis mode not implemented. Running local."); - break; + fIsRemote = kTRUE; + if (!anaType.Contains("terminate")) { + if (!fGridHandler) { + Error("StartAnalysis", "Cannot start grid analysis without a grid handler."); + Info("===", "Add an AliAnalysisAlien object as plugin for this manager and configure it."); + cdir->cd(); + return -1; + } + // Write analysis manager in the analysis file + cout << "===== RUNNING GRID ANALYSIS: " << GetName() << endl; + // Start the analysis via the handler + if (!fGridHandler->StartAnalysis(nentries, firstentry)) { + Info("StartAnalysis", "Grid analysis was stopped and cannot be terminated"); + cdir->cd(); + return -1; + } + + // Terminate grid analysis + if (fSelector && fSelector->GetStatus() == -1) {cdir->cd(); return -1;} + if (fGridHandler->GetRunMode() == AliAnalysisGrid::kOffline) {cdir->cd(); return 0;} + cout << "===== MERGING OUTPUTS REGISTERED BY YOUR ANALYSIS JOB: " << GetName() << endl; + if (!fGridHandler->MergeOutputs()) { + // Return if outputs could not be merged or if it alien handler + // was configured for offline mode or local testing. + cdir->cd(); + return 0; + } + } + cout << "===== TERMINATING GRID ANALYSIS JOB: " << GetName() << endl; + ImportWrappers(NULL); + Terminate(); + cdir->cd(); + return 0; case kMixingAnalysis: // Run event mixing analysis if (!fEventPool) { Error("StartAnalysis", "Cannot run event mixing without event pool"); + cdir->cd(); return -1; } cout << "===== RUNNING EVENT MIXING ANALYSIS " << GetName() << endl; @@ -1383,12 +1738,14 @@ Long64_t AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64 retv = chain->Process(fSelector); if (retv < 0) { Error("StartAnalysis", "Mixing analysis failed"); + cdir->cd(); return retv; } } PackOutput(fSelector->GetOutputList()); Terminate(); } + cdir->cd(); return retv; } @@ -1401,7 +1758,8 @@ Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset Error("StartAnalysis","Analysis manager was not initialized !"); return -1; } - if (fDebug > 0) printf("StartAnalysis %s\n",GetName()); + fIsRemote = kTRUE; + if (fDebug > 1) printf("StartAnalysis %s\n",GetName()); TString anaType = type; anaType.ToLower(); if (!anaType.Contains("proof")) { @@ -1409,11 +1767,29 @@ Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset return -1; } fMode = kProofAnalysis; - char line[256]; + TString line; SetEventLoop(kTRUE); // Set the dataset flag TObject::SetBit(kUseDataSet); fTree = 0; + if (fGridHandler) { + // Start proof analysis using the grid handler + if (!fGridHandler->StartAnalysis(nentries, firstentry)) { + Error("StartAnalysis", "The grid plugin could not start PROOF analysis"); + return -1; + } + // Check if the plugin is in test mode + if (fGridHandler->GetRunMode() == AliAnalysisGrid::kTest) { + dataset = "test_collection"; + } else { + dataset = fGridHandler->GetProofDataSet(); + } + } + + if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) { + Error("StartAnalysis", "No PROOF!!! Exiting."); + return -1; + } // Initialize locally all tasks TIter next(fTasks); @@ -1422,21 +1798,13 @@ Long64_t AliAnalysisManager::StartAnalysis(const char *type, const char *dataset task->LocalInit(); } - if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) { - Error("StartAnalysis", "No PROOF!!! Aborting."); - return -1; - } - sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this); + line = Form("gProof->AddInput((TObject*)%p);", this); gROOT->ProcessLine(line); - sprintf(line, "gProof->GetDataSet(\"%s\");", dataset); - if (!gROOT->ProcessLine(line)) { - Error("StartAnalysis", "Dataset %s not found", dataset); - return -1; - } - sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);", - dataset, nentries, firstentry); + Long_t retv; + line = Form("gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);", + dataset, nentries, firstentry); cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl; - Long_t retv = (Long_t)gROOT->ProcessLine(line); + retv = (Long_t)gROOT->ProcessLine(line); return retv; } @@ -1488,14 +1856,17 @@ TFile *AliAnalysisManager::OpenFile(AliAnalysisDataContainer *cont, const char * } //______________________________________________________________________________ -TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option) +TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const char *option, const char *extaod) { // Opens a special output file used in PROOF. TString line; TString filename = cont->GetFileName(); if (cont == fCommonOutput) { - if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName(); - else Fatal("OpenProofFile","No output container. Aborting."); + if (fOutputEventHandler) { + if (strlen(extaod)) filename = extaod; + filename = fOutputEventHandler->GetOutputFileName(); + } + else Fatal("OpenProofFile","No output container. Exiting."); } TFile *f = NULL; if (fMode!=kProofAnalysis || !fSelector) { @@ -1533,13 +1904,16 @@ TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const c TObject *pof = fSelector->GetOutputList()->FindObject(filename); if (pof) { // Get the actual file - line = Form("((TProofOutputFile*)0x%lx)->GetFileName();", (ULong_t)pof); + line = Form("((TProofOutputFile*)%p)->GetFileName();", pof); filename = (const char*)gROOT->ProcessLine(line); if (fDebug>1) { printf("File: %s already booked via TProofOutputFile\n", filename.Data()); } f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); - if (!f) Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data()); + if (!f) { + Fatal("OpenProofFile", "Proof output file found but no file opened for %s", filename.Data()); + return NULL; + } // Check if option "UPDATE" was preserved TString opt(option); opt.ToUpper(); @@ -1547,11 +1921,11 @@ TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const c Fatal("OpenProofFile", "File %s already opened, but not in UPDATE mode!", cont->GetFileName()); } else { if (cont->IsRegisterDataset()) { - TString dset_name = filename; - dset_name.ReplaceAll(".root", cont->GetTitle()); - dset_name.ReplaceAll(":","_"); - if (fDebug>1) printf("Booking dataset: %s\n", dset_name.Data()); - line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dset_name.Data()); + TString dsetName = filename; + dsetName.ReplaceAll(".root", cont->GetTitle()); + dsetName.ReplaceAll(":","_"); + if (fDebug>1) printf("Booking dataset: %s\n", dsetName.Data()); + line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\", \"DROV\", \"%s\");", filename.Data(), dsetName.Data()); } else { if (fDebug>1) printf("Booking TProofOutputFile: %s to be merged\n", filename.Data()); line = Form("TProofOutputFile *pf = new TProofOutputFile(\"%s\");", filename.Data()); @@ -1566,7 +1940,7 @@ TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const c printf(" == proof file name: %s", f->GetName()); } // Add to proof output list - line = Form("((TList*)0x%lx)->Add(pf);",(ULong_t)fSelector->GetOutputList()); + line = Form("((TList*)%p)->Add(pf);",fSelector->GetOutputList()); if (fDebug > 1) printf("=== %s\n", line.Data()); gROOT->ProcessLine(line); } @@ -1591,18 +1965,33 @@ TFile *AliAnalysisManager::OpenProofFile(AliAnalysisDataContainer *cont, const c void AliAnalysisManager::ExecAnalysis(Option_t *option) { // Execute analysis. - static Long64_t ncalls = 0; - if (fDebug > 0) printf("MGR: Processing event #%lld\n", ncalls); + static Long64_t nentries = 0; + static TTree *lastTree = 0; + static TStopwatch *timer = new TStopwatch(); + if (fDebug > 0) printf("MGR: Processing event #%d\n", fNcalls); + else { + if (fTree && (fTree != lastTree)) { + nentries += fTree->GetEntries(); + lastTree = fTree; + } + if (!fNcalls) timer->Start(); + if (!fIsRemote && TObject::TestBit(kUseProgressBar)) ProgressBar("Processing event", fNcalls, TMath::Min(fMaxEntries,nentries), timer, kFALSE); + } + gROOT->cd(); + TDirectory *cdir = gDirectory; Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE; - if (getsysInfo && ((ncalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)ncalls); - ncalls++; + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) AliSysInfo::AddStamp("Exec_start", (Int_t)fNcalls); if (!fInitOK) { - Error("ExecAnalysis", "Analysis manager was not initialized !"); + Error("ExecAnalysis", "Analysis manager was not initialized !"); + cdir->cd(); return; - } + } + fNcalls++; AliAnalysisTask *task; // Check if the top tree is active. if (fTree) { + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) + AliSysInfo::AddStamp("Handlers_BeginEventGroup",fNcalls, 1002, 0); TIter next(fTasks); // De-activate all tasks while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE); @@ -1610,18 +1999,19 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) if (!cont) cont = (AliAnalysisDataContainer*)fInputs->At(0); if (!cont) { Error("ExecAnalysis","Cannot execute analysis in TSelector mode without at least one top container"); + cdir->cd(); return; } cont->SetData(fTree); // This will notify all consumers - Long64_t entry = fTree->GetTree()->GetReadEntry(); - + Long64_t entry = fTree->GetTree()->GetReadEntry(); // // Call BeginEvent() for optional input/output and MC services if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry); if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry); if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry); - if (getsysInfo && ((ncalls%fNSysInfo)==0)) - AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0); + gROOT->cd(); + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) + AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0); // // Execute the tasks // TIter next1(cont->GetConsumers()); @@ -1632,8 +2022,9 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) cout << " Executing task " << task->GetName() << endl; } task->ExecuteTask(option); - if (getsysInfo && ((ncalls%fNSysInfo)==0)) - AliSysInfo::AddStamp(task->ClassName(),(Int_t)ncalls, itask, 1); + gROOT->cd(); + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) + AliSysInfo::AddStamp(task->ClassName(), fNcalls, itask, 1); itask++; } // @@ -1642,8 +2033,9 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) if (fOutputEventHandler) fOutputEventHandler ->FinishEvent(); if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent(); // Gather system information if requested - if (getsysInfo && ((ncalls%fNSysInfo)==0)) - AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1); + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) + AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1001, 1); + cdir->cd(); return; } // The event loop is not controlled by TSelector @@ -1652,8 +2044,9 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1); if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1); if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1); - if (getsysInfo && ((ncalls%fNSysInfo)==0)) - AliSysInfo::AddStamp("Handlers_BeginEvent",(Int_t)ncalls, 1000, 0); + gROOT->cd(); + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) + AliSysInfo::AddStamp("Handlers_BeginEvent",fNcalls, 1000, 0); TIter next2(fTopTasks); while ((task=(AliAnalysisTask*)next2())) { task->SetActive(kTRUE); @@ -1661,41 +2054,69 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) cout << " Executing task " << task->GetName() << endl; } task->ExecuteTask(option); + gROOT->cd(); } // // Call FinishEvent() for optional output and MC services if (fInputEventHandler) fInputEventHandler ->FinishEvent(); if (fOutputEventHandler) fOutputEventHandler ->FinishEvent(); if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent(); - if (getsysInfo && ((ncalls%fNSysInfo)==0)) - AliSysInfo::AddStamp("Handlers_FinishEvent",(Int_t)ncalls, 1000, 1); + if (getsysInfo && ((fNcalls%fNSysInfo)==0)) + AliSysInfo::AddStamp("Handlers_FinishEvent",fNcalls, 1000, 1); + cdir->cd(); } //______________________________________________________________________________ -void AliAnalysisManager::FinishAnalysis() +Bool_t AliAnalysisManager::IsPipe(std::ostream &out) { -// Finish analysis. +// Check if the stdout is connected to a pipe (C.Holm) + Bool_t ispipe = kFALSE; + out.seekp(0, std::ios_base::cur); + if (out.fail()) { + out.clear(); + if (errno == ESPIPE) ispipe = kTRUE; + } + return ispipe; } - + //______________________________________________________________________________ -void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* handler) +void AliAnalysisManager::SetInputEventHandler(AliVEventHandler* const handler) { // Set the input event handler and create a container for it. fInputEventHandler = handler; fCommonInput = CreateContainer("cAUTO_INPUT", TChain::Class(), AliAnalysisManager::kInputContainer); -// Warning("SetInputEventHandler", " An automatic input container for the input chain was created.\nPlease use: mgr->GetCommonInputContainer() to access it."); } //______________________________________________________________________________ -void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* handler) +void AliAnalysisManager::SetOutputEventHandler(AliVEventHandler* const handler) { // Set the input event handler and create a container for it. fOutputEventHandler = handler; fCommonOutput = CreateContainer("cAUTO_OUTPUT", TTree::Class(), AliAnalysisManager::kOutputContainer, "default"); fCommonOutput->SetSpecialOutput(); -// Warning("SetOutputEventHandler", " An automatic output container for the output tree was created.\nPlease use: mgr->GetCommonOutputContainer() to access it."); } +//______________________________________________________________________________ +void AliAnalysisManager::SetDebugLevel(UInt_t level) +{ +// Set verbosity of the analysis manager. If the progress bar is used, the call is ignored + if (TObject::TestBit(kUseProgressBar)) { + Info("SetDebugLevel","Ignored. Disable the progress bar first."); + return; + } + fDebug = level; +} + +//______________________________________________________________________________ +void AliAnalysisManager::SetUseProgressBar(Bool_t flag, Int_t freq) +{ +// Enable a text mode progress bar. Resets debug level to 0. + Info("SetUseProgressBar", "Progress bar enabled, updated every %d events.\n ### NOTE: Debug level reset to 0 ###", freq); + TObject::SetBit(kUseProgressBar,flag); + fPBUpdateFreq = freq; + fDebug = 0; +} + //______________________________________________________________________________ void AliAnalysisManager::RegisterExtraFile(const char *fname) { @@ -1703,39 +2124,46 @@ void AliAnalysisManager::RegisterExtraFile(const char *fname) // connected to any output container, so that the manager can properly register, // retrieve or merge them when running in distributed mode. The file names are // separated by blancs. The method has to be called in MyAnalysisTask::LocalInit(). + if (fExtraFiles.Contains(fname)) return; if (fExtraFiles.Length()) fExtraFiles += " "; fExtraFiles += fname; } //______________________________________________________________________________ -Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, TList *source) +Bool_t AliAnalysisManager::GetFileFromWrapper(const char *filename, const TList *source) { // Copy a file from the location specified ina the wrapper with the same name from the source list. - char full_path[512]; - char ch_url[512]; + char fullPath[512]; + char chUrl[512]; + char tmp[1024]; TObject *pof = source->FindObject(filename); if (!pof || !pof->InheritsFrom("TProofOutputFile")) { Error("GetFileFromWrapper", "TProofOutputFile object not found in output list for file %s", filename); return kFALSE; } - gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", ((TProofOutputFile*)0x%lx)->GetOutputFileName();)", full_path, pof)); - gROOT->ProcessLine(Form("sprintf((char*)0x%lx, \"%%s\", gProof->GetUrl();)", ch_url)); - TString clientUrl(ch_url); - TString full_path_str(full_path); + gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", ((TProofOutputFile*)%p)->GetOutputFileName());", fullPath, pof)); + gROOT->ProcessLine(Form("sprintf((char*)%p, \"%%s\", gProof->GetUrl());",chUrl)); + TString clientUrl(chUrl); + TString fullPath_str(fullPath); if (clientUrl.Contains("localhost")){ - TObjArray* array = full_path_str.Tokenize ( "//" ); + TObjArray* array = fullPath_str.Tokenize ( "//" ); TObjString *strobj = ( TObjString *)array->At(1); TObjArray* arrayPort = strobj->GetString().Tokenize ( ":" ); TObjString *strobjPort = ( TObjString *) arrayPort->At(1); - full_path_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT"); - full_path_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data())); - if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",full_path_str.Data(),filename); + fullPath_str.ReplaceAll(strobj->GetString().Data(),"localhost:PORT"); + fullPath_str.ReplaceAll(":PORT",Form(":%s",strobjPort->GetString().Data())); + if (fDebug > 1) Info("GetFileFromWrapper","Using tunnel from %s to %s",fullPath_str.Data(),filename); delete arrayPort; delete array; } + else if (clientUrl.Contains("__lite__")) { + // Special case for ProofLite environement - get file info and copy. + gROOT->ProcessLine(Form("sprintf((char*)%p,\"%%s\",((TProofOutputFile*)%p)->GetDir());", tmp, pof)); + fullPath_str = Form("%s/%s", tmp, fullPath); + } if (fDebug > 1) - Info("GetFileFromWrapper","Copying file %s from PROOF scratch space", full_path_str.Data()); - Bool_t gotit = TFile::Cp(full_path_str.Data(), filename); + Info("GetFileFromWrapper","Copying file %s from PROOF scratch space to %s", fullPath_str.Data(),filename); + Bool_t gotit = TFile::Cp(fullPath_str.Data(), filename); if (!gotit) Error("GetFileFromWrapper", "Could not get file %s from proof scratch space", filename); return gotit; @@ -1782,6 +2210,8 @@ Bool_t AliAnalysisManager::ValidateOutputFiles() const TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); if (file) { Warning("ValidateOutputs", "File %s was not closed. Closing.", filename.Data()); + // Clear file list to release object ownership to user. +// file->Clear(); file->Close(); } file = TFile::Open(filename); @@ -1799,7 +2229,7 @@ Bool_t AliAnalysisManager::ValidateOutputFiles() const } //______________________________________________________________________________ -void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch *watch, Bool_t last, Bool_t refresh) +void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long64_t size, TStopwatch * const watch, Bool_t last, Bool_t refresh) { // Implements a nice text mode progress bar. static Long64_t icount = 0; @@ -1812,10 +2242,10 @@ void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long6 static Bool_t oneoftwo = kFALSE; static Int_t nrefresh = 0; static Int_t nchecks = 0; - const char symbol[4] = {'=','\\','|','/'}; - char progress[11] = " "; - Int_t ichar = icount%4; + static char lastChar = 0; + const char symbol[4] = {'-','\\','|','/'}; + if (!lastChar) lastChar = (IsPipe(std::cerr))?'\r':'\n'; if (!refresh) { nrefresh = 0; if (!size) return; @@ -1828,7 +2258,10 @@ void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long6 nrefresh++; if (!osize) return; } + if ((current % fPBUpdateFreq) != 0) return; icount++; + char progress[11] = " "; + Int_t ichar = icount%4; Double_t time = 0.; Int_t hours = 0; Int_t minutes = 0; @@ -1836,11 +2269,9 @@ void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long6 if (owatch && !last) { owatch->Stop(); time = owatch->RealTime(); - hours = (Int_t)(time/3600.); - time -= 3600*hours; - minutes = (Int_t)(time/60.); - time -= 60*minutes; - seconds = (Int_t)time; + seconds = int(time) % 60; + minutes = (int(time) / 60) % 60; + hours = (int(time) / 60 / 60); if (refresh) { if (oseconds==seconds) { owatch->Continue(); @@ -1869,8 +2300,18 @@ void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long6 if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent); else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent); else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent); - if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d \r", percent, hours, minutes, seconds); - else fprintf(stderr, "[%6.2f %%]\r", percent); + if (time>0.) { + Int_t full = Int_t(ocurrent > 0 ? + time * (float(osize)/ocurrent) + .5 : + 99*3600+59*60+59); + Int_t remain = Int_t(full - time); + Int_t rsec = remain % 60; + Int_t rmin = (remain / 60) % 60; + Int_t rhour = (remain / 60 / 60); + fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d ETA %.2d:%.2d:%.2d%c", + percent, hours, minutes, seconds, rhour, rmin, rsec, lastChar); + } + else fprintf(stderr, "[%6.2f %%]%c", percent, lastChar); if (refresh && oneoftwo) oname = nname; if (owatch) owatch->Continue(); if (last) { @@ -1884,3 +2325,109 @@ void AliAnalysisManager::ProgressBar(const char *opname, Long64_t current, Long6 fprintf(stderr, "\n"); } } + +//______________________________________________________________________________ +void AliAnalysisManager::DoLoadBranch(const char *name) +{ + // Get tree and load branch if needed. + static Long64_t crtEntry = -100; + + if (fAutoBranchHandling || !fTree) + return; + + TBranch *br = dynamic_cast(fTable.FindObject(name)); + if (!br) { + br = fTree->GetBranch(name); + if (!br) { + Error("DoLoadBranch", "Could not find branch %s",name); + return; + } + fTable.Add(br); + } + if (br->GetReadEntry()==fCurrentEntry) return; + Int_t ret = br->GetEntry(GetCurrentEntry()); + if (ret<0) { + Error("DoLoadBranch", "Could not load entry %lld from branch %s",GetCurrentEntry(), name); + if (crtEntry != fCurrentEntry) { + CountEvent(1,0,1,0); + crtEntry = fCurrentEntry; + } + } else { + if (crtEntry != fCurrentEntry) { + CountEvent(1,1,0,0); + crtEntry = fCurrentEntry; + } + } +} + +//______________________________________________________________________________ +void AliAnalysisManager::AddStatisticsTask(UInt_t offlineMask) +{ +// Add the statistics task to the manager. + if (fStatistics) { + Info("AddStatisticsTask", "Already added"); + return; + } + TString line = Form("AliAnalysisTaskStat::AddToManager(%u);", offlineMask); + gROOT->ProcessLine(line); +} + +//______________________________________________________________________________ +void AliAnalysisManager::CountEvent(Int_t ninput, Int_t nprocessed, Int_t nfailed, Int_t naccepted) +{ +// Bookkeep current event; + if (!fStatistics) return; + fStatistics->AddInput(ninput); + fStatistics->AddProcessed(nprocessed); + fStatistics->AddFailed(nfailed); + fStatistics->AddAccepted(naccepted); +} + +//______________________________________________________________________________ +void AliAnalysisManager::AddStatisticsMsg(const char *line) +{ +// Add a line in the statistics message. If available, the statistics message is written +// at the end of the SlaveTerminate phase on workers AND at the end of Terminate +// on the client. + if (!strlen(line)) return; + if (!fStatisticsMsg.IsNull()) fStatisticsMsg += "\n"; + fStatisticsMsg += line; +} + +//______________________________________________________________________________ +void AliAnalysisManager::WriteStatisticsMsg(Int_t) +{ +// If fStatistics is present, write the file in the format ninput_nprocessed_nfailed_naccepted.stat + static Bool_t done = kFALSE; + if (done) return; + done = kTRUE; + if (!fStatistics) return; + ofstream out; + AddStatisticsMsg(Form("Number of input events: %lld",fStatistics->GetNinput())); + AddStatisticsMsg(Form("Number of processed events: %lld",fStatistics->GetNprocessed())); + AddStatisticsMsg(Form("Number of failed events (I/O): %lld",fStatistics->GetNfailed())); + AddStatisticsMsg(Form("Number of accepted events for mask %s: %lld", AliAnalysisStatistics::GetMaskAsString(fStatistics->GetOfflineMask()), fStatistics->GetNaccepted())); + out.open(Form("%lld_%lld_%lld_%lld.stat",fStatistics->GetNinput(), + fStatistics->GetNprocessed(),fStatistics->GetNfailed(), + fStatistics->GetNaccepted()), ios::out); + out << fStatisticsMsg << endl; + out.close(); +} + +//______________________________________________________________________________ +const char* AliAnalysisManager::GetOADBPath() +{ +// returns the path of the OADB +// this static function just depends on environment variables + + static TString oadbPath; + + if (gSystem->Getenv("OADB_PATH")) + oadbPath = gSystem->Getenv("OADB_PATH"); + else if (gSystem->Getenv("ALICE_ROOT")) + oadbPath.Form("%s/OADB", gSystem->Getenv("ALICE_ROOT")); + else + ::Fatal("AliAnalysisManager::GetOADBPath", "Cannot figure out AODB path. Define ALICE_ROOT or OADB_PATH!"); + + return oadbPath; +}