X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=ANALYSIS%2FAliAnalysisManager.cxx;h=8cf718e5f7b67d951de987ddd75a18d499fd64bd;hb=d9179e4ba7753a683eebe9287da260610cb597fb;hp=02566ad4a0e393576316bcfb596f6c5fe93a66b3;hpb=b1109411ff5d827b0c4d1cc85a304dfb018302cd;p=u%2Fmrichter%2FAliRoot.git diff --git a/ANALYSIS/AliAnalysisManager.cxx b/ANALYSIS/AliAnalysisManager.cxx index 02566ad4a0e..8cf718e5f7b 100644 --- a/ANALYSIS/AliAnalysisManager.cxx +++ b/ANALYSIS/AliAnalysisManager.cxx @@ -33,39 +33,28 @@ #include #include #include +#include #include "AliAnalysisTask.h" #include "AliAnalysisDataContainer.h" #include "AliAnalysisDataSlot.h" +#include "AliVEventHandler.h" +#include "AliSysInfo.h" #include "AliAnalysisManager.h" ClassImp(AliAnalysisManager) AliAnalysisManager *AliAnalysisManager::fgAnalysisManager = NULL; -//______________________________________________________________________________ -AliAnalysisManager::AliAnalysisManager() - :TNamed(), - fTree(NULL), - fCurrentEntry(-1), - fMode(kLocalAnalysis), - fInitOK(kFALSE), - fTasks(NULL), - fTopTasks(NULL), - fZombies(NULL), - fContainers(NULL), - fInputs(NULL), - fOutputs(NULL) -{ -// Dummy constructor. - fgAnalysisManager = this; -} - //______________________________________________________________________________ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) :TNamed(name,title), fTree(NULL), + fInputEventHandler(NULL), + fOutputEventHandler(NULL), + fMCtruthEventHandler(NULL), fCurrentEntry(-1), + fNSysInfo(0), fMode(kLocalAnalysis), fInitOK(kFALSE), fDebug(0), @@ -84,13 +73,18 @@ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) fContainers = new TObjArray(); fInputs = new TObjArray(); fOutputs = new TObjArray(); + SetEventLoop(kTRUE); } //______________________________________________________________________________ AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other) :TNamed(other), fTree(NULL), + fInputEventHandler(NULL), + fOutputEventHandler(NULL), + fMCtruthEventHandler(NULL), fCurrentEntry(-1), + fNSysInfo(0), fMode(other.fMode), fInitOK(other.fInitOK), fDebug(other.fDebug), @@ -117,8 +111,12 @@ AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& othe // Assignment if (&other != this) { TNamed::operator=(other); + fInputEventHandler = other.fInputEventHandler; + fOutputEventHandler = other.fOutputEventHandler; + fMCtruthEventHandler = other.fMCtruthEventHandler; fTree = NULL; fCurrentEntry = -1; + fNSysInfo = other.fNSysInfo; fMode = other.fMode; fInitOK = other.fInitOK; fDebug = other.fDebug; @@ -167,8 +165,39 @@ void AliAnalysisManager::Init(TTree *tree) // Init() will be called many times when running with PROOF. if (!tree) return; if (fDebug > 1) { - printf("->AliAnalysisManager::Init(%s)\n", tree->GetName()); + printf("->AliAnalysisManager::InitTree(%s)\n", tree->GetName()); } + + // Call InitTree of EventHandler + if (fOutputEventHandler) { + if (fMode == kProofAnalysis) { + fOutputEventHandler->Init(0x0, "proof"); + } else { + fOutputEventHandler->Init(0x0, "local"); + } + } + + if (fInputEventHandler) { + if (fMode == kProofAnalysis) { + fInputEventHandler->Init(tree, "proof"); + } else { + fInputEventHandler->Init(tree, "local"); + } + } else { + // If no input event handler we need to get the tree once + // for the chain + if(!tree->GetTree()) tree->LoadTree(0); + } + + + if (fMCtruthEventHandler) { + if (fMode == kProofAnalysis) { + fMCtruthEventHandler->Init(0x0, "proof"); + } else { + fMCtruthEventHandler->Init(0x0, "local"); + } + } + if (!fInitOK) InitAnalysis(); if (!fInitOK) return; fTree = tree; @@ -183,18 +212,6 @@ void AliAnalysisManager::Init(TTree *tree) } } -//______________________________________________________________________________ -void AliAnalysisManager::Begin(TTree *tree) -{ - // The Begin() function is called at the start of the query. - // When running with PROOF Begin() is only called on the client. - // The tree argument is deprecated (on PROOF 0 is passed). - if (fDebug > 1) { - cout << "AliAnalysisManager::Begin()" << endl; - } - Init(tree); -} - //______________________________________________________________________________ void AliAnalysisManager::SlaveBegin(TTree *tree) { @@ -205,6 +222,32 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) cout << "->AliAnalysisManager::SlaveBegin()" << endl; } + // Call Init of EventHandler + if (fOutputEventHandler) { + if (fMode == kProofAnalysis) { + fOutputEventHandler->Init("proof"); + } else { + fOutputEventHandler->Init("local"); + } + } + + if (fInputEventHandler) { + fInputEventHandler->SetInputTree(tree); + if (fMode == kProofAnalysis) { + fInputEventHandler->Init("proof"); + } else { + fInputEventHandler->Init("local"); + } + } + + if (fMCtruthEventHandler) { + if (fMode == kProofAnalysis) { + fMCtruthEventHandler->Init("proof"); + } else { + fMCtruthEventHandler->Init("local"); + } + } + TIter next(fTasks); AliAnalysisTask *task; // Call CreateOutputObjects for all tasks @@ -212,8 +255,8 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) TDirectory *curdir = gDirectory; task->CreateOutputObjects(); if (curdir) curdir->cd(); - } - if (fMode == kLocalAnalysis) Init(tree); + } + if (fDebug > 1) { cout << "<-AliAnalysisManager::SlaveBegin()" << endl; } @@ -227,16 +270,30 @@ Bool_t AliAnalysisManager::Notify() // is started when using PROOF. It is normaly not necessary to make changes // to the generated code, but the routine can be extended by the // user if needed. The return value is currently not used. - if (fTree) { - TFile *curfile = fTree->GetCurrentFile(); - if (curfile && fDebug>1) printf("AliAnalysisManager::Notify() file: %s\n", curfile->GetName()); - TIter next(fTasks); - AliAnalysisTask *task; - // Call Notify for all tasks - while ((task=(AliAnalysisTask*)next())) - task->Notify(); - } - return kTRUE; + if (fTree) { + TFile *curfile = fTree->GetCurrentFile(); + if (curfile && fDebug>1) printf("AliAnalysisManager::Notify() file: %s\n", curfile->GetName()); + TIter next(fTasks); + AliAnalysisTask *task; + // Call Notify for all tasks + while ((task=(AliAnalysisTask*)next())) + task->Notify(); + + // Call Notify of the event handlers + if (fInputEventHandler) { + fInputEventHandler->Notify(curfile->GetName()); + } + + if (fOutputEventHandler) { + fOutputEventHandler->Notify(curfile->GetName()); + } + + if (fMCtruthEventHandler) { + fMCtruthEventHandler->Notify(curfile->GetName()); + } + + } + return kTRUE; } //______________________________________________________________________________ @@ -260,8 +317,12 @@ Bool_t AliAnalysisManager::Process(Long64_t entry) // Assuming that fChain is the pointer to the TChain being processed, // use fChain->GetTree()->GetEntry(entry). if (fDebug > 1) { - cout << "->AliAnalysisManager::Process()" << endl; + cout << "->AliAnalysisManager::Process(" << entry << ")" << endl; } + if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry); + if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry); + if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry); + GetEntry(entry); ExecAnalysis(); if (fDebug > 1) { @@ -282,13 +343,40 @@ void AliAnalysisManager::PackOutput(TList *target) Error("PackOutput", "No target. Aborting."); return; } - + if (fInputEventHandler) fInputEventHandler ->Terminate(); + if (fOutputEventHandler) fOutputEventHandler ->Terminate(); + if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate(); + if (fMode == kProofAnalysis) { TIter next(fOutputs); AliAnalysisDataContainer *output; while ((output=(AliAnalysisDataContainer*)next())) { - if (fDebug > 1) printf(" Packing container %s...\n", output->GetName()); - if (output->GetData()) target->Add(output->ExportData()); + if (output->GetData() && !output->IsSpecialOutput()) { + if (output->GetProducer()->IsPostEventLoop()) continue; + AliAnalysisDataWrapper *wrap = output->ExportData(); + // Output wrappers must delete data after merging (AG 13/11/07) + wrap->SetDeleteData(kTRUE); + if (fDebug > 1) printf(" Packing container %s...\n", output->GetName()); + target->Add(wrap); + } + // Special outputs files are closed and copied on the remote location + if (output->IsSpecialOutput() && strlen(output->GetFileName())) { + TDirectory *opwd = gDirectory; + TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(output->GetFileName()); + if (!file) continue; + file->cd(); + if (output->GetData()) output->GetData()->Write(); + file->Close(); + if (opwd) opwd->cd(); + if (strlen(fSpecialOutputLocation.Data())) { + TString remote = fSpecialOutputLocation; + remote += "/"; + Int_t gid = gROOT->ProcessLine("gProofServ->GetGroupId();"); + remote += Form("%s_%d_", gSystem->HostName(), gid); + remote += output->GetFileName(); + TFile::Cp(output->GetFileName(), remote.Data()); + } + } } } if (fDebug > 1) { @@ -308,6 +396,8 @@ void AliAnalysisManager::ImportWrappers(TList *source) AliAnalysisDataWrapper *wrap; Int_t icont = 0; while ((cont=(AliAnalysisDataContainer*)next())) { + if (cont->GetProducer()->IsPostEventLoop() || + cont->IsSpecialOutput()) continue; wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName()); if (!wrap && fDebug>1) { printf("(WW) ImportWrappers: container %s not found in analysis output !\n", cont->GetName()); @@ -345,10 +435,33 @@ void AliAnalysisManager::UnpackOutput(TList *source) AliAnalysisDataContainer *output; while ((output=(AliAnalysisDataContainer*)next())) { if (!output->GetData()) continue; + // Check if there are client tasks that run post event loop + if (output->HasConsumers()) { + // Disable event loop semaphore + output->SetPostEventLoop(kTRUE); + TObjArray *list = output->GetConsumers(); + Int_t ncons = list->GetEntriesFast(); + for (Int_t i=0; iAt(i); + task->CheckNotify(kTRUE); + // If task is active, execute it + if (task->IsPostEventLoop() && task->IsActive()) { + if (fDebug > 1) { + cout << "== Executing post event loop task " << task->GetName() << endl; + } + task->ExecuteTask(); + } + } + } // Check if the output need to be written to a file. const char *filename = output->GetFileName(); + if (!(strcmp(filename, "default"))) { + if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName(); + } + if (!filename || !strlen(filename)) continue; TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); + TDirectory *opwd = gDirectory; if (file) file->cd(); else file = new TFile(filename, "RECREATE"); if (file->IsZombie()) continue; @@ -361,17 +474,7 @@ void AliAnalysisManager::UnpackOutput(TList *source) callEnv.Execute(output->GetData()); } output->GetData()->Write(); - // Check if there are client tasks that run in single-shot mode. - if (!output->HasConsumers()) continue; - output->SetEventByEvent(kFALSE); - TObjArray *list = output->GetConsumers(); - Int_t ncons = list->GetEntriesFast(); - for (Int_t i=0; iAt(i); - task->CheckNotify(kTRUE); - // If task is active, execute it - if (task->IsActive()) task->ExecuteTask(); - } + if (opwd) opwd->cd(); } if (fDebug > 1) { cout << "<-AliAnalysisManager::UnpackOutput()" << endl; @@ -394,6 +497,51 @@ void AliAnalysisManager::Terminate() if (fDebug > 1) { cout << "<-AliAnalysisManager::Terminate()" << endl; } + // + if (fInputEventHandler) fInputEventHandler ->TerminateIO(); + if (fOutputEventHandler) fOutputEventHandler ->TerminateIO(); + if (fMCtruthEventHandler) fMCtruthEventHandler->TerminateIO(); + TIter next1(fOutputs); + AliAnalysisDataContainer *output; + while ((output=(AliAnalysisDataContainer*)next1())) { + // Close all files at output + const char *filename = output->GetFileName(); + if (!(strcmp(filename, "default"))) { + if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName(); + } + + if (!filename || !strlen(filename)) continue; + TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); + if (!file || file->IsZombie()) continue; + file->Close(); + } + + Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE; + if (getsysInfo) { + TDirectory *cdir = gDirectory; + TFile f("syswatch.root", "RECREATE"); + if (!f.IsZombie()) { + TTree *tree = AliSysInfo::MakeTree("syswatch.log"); + tree->SetMarkerStyle(kCircle); + tree->SetMarkerColor(kBlue); + tree->SetMarkerSize(0.5); + if (!gROOT->IsBatch()) { + tree->SetAlias("event", "id0"); + tree->SetAlias("memUSED", "mi.fMemUsed"); + tree->SetAlias("userCPU", "pI.fCpuUser"); + TCanvas *c = new TCanvas("SysInfo","SysInfo",10,10,800,600); + c->Divide(2,1,0.01,0.01); + c->cd(1); + tree->Draw("memUSED:event","","", 1234567890, 0); + c->cd(2); + tree->Draw("userCPU:event","","", 1234567890, 0); + } + tree->Write(); + f.Close(); + delete tree; + } + if (cdir) cdir->cd(); + } } //______________________________________________________________________________ @@ -420,6 +568,10 @@ AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, // kExchangeContainer = 0, used to exchange date between tasks // kInputContainer = 1, used to store input data // kOutputContainer = 2, used for posting results + if (fContainers->FindObject(name)) { + Error("CreateContainer","A container named %s already defined !\n",name); + return NULL; + } AliAnalysisDataContainer *cont = new AliAnalysisDataContainer(name, datatype); fContainers->Add(cont); switch (type) { @@ -427,9 +579,11 @@ AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, fInputs->Add(cont); break; case kOutputContainer: - if (fOutputs->FindObject(name)) printf("CreateContainer: warning: a container named %s existing !\n",name); fOutputs->Add(cont); - if (filename && strlen(filename)) cont->SetFileName(filename); + if (filename && strlen(filename)) { + cont->SetFileName(filename); + cont->SetDataOwned(kFALSE); // data owned by the file + } break; case kExchangeContainer: break; @@ -549,6 +703,22 @@ Bool_t AliAnalysisManager::InitAnalysis() return kFALSE; } } + // Check that all containers feeding post-event loop tasks are in the outputs list + TIter nextcont(fContainers); // loop over all containers + while ((cont=(AliAnalysisDataContainer*)nextcont())) { + if (!cont->IsPostEventLoop() && !fOutputs->FindObject(cont)) { + if (cont->HasConsumers()) { + // Check if one of the consumers is post event loop + TIter nextconsumer(cont->GetConsumers()); + while ((task=(AliAnalysisTask*)nextconsumer())) { + if (task->IsPostEventLoop()) { + fOutputs->Add(cont); + break; + } + } + } + } + } fInitOK = kTRUE; return kTRUE; } @@ -557,6 +727,13 @@ Bool_t AliAnalysisManager::InitAnalysis() void AliAnalysisManager::PrintStatus(Option_t *option) const { // Print task hierarchy. + if (!fInitOK) { + Info("PrintStatus", "Analysis manager %s not initialized : call InitAnalysis() first", GetName()); + return; + } + Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE; + if (getsysInfo) + Info("PrintStatus", "System information will be collected each %lld events", fNSysInfo); TIter next(fTopTasks); AliAnalysisTask *task; while ((task=(AliAnalysisTask*)next())) @@ -571,9 +748,10 @@ void AliAnalysisManager::ResetAnalysis() } //______________________________________________________________________________ -void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree) +void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree, Long64_t nentries, Long64_t firstentry) { // Start analysis for this manager. Analysis task can be: LOCAL, PROOF or GRID. +// Process nentries starting from firstentry if (!fInitOK) { Error("StartAnalysis","Analysis manager was not initialized !"); return; @@ -592,33 +770,32 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree) Warning("StartAnalysis", "GRID analysis mode not implemented. Running local."); fMode = kLocalAnalysis; } - char line[128]; + char line[256]; SetEventLoop(kFALSE); - // Disable by default all branches and set event loop mode + // Disable all branches if requested and set event loop mode if (tree) { -// tree->SetBranchStatus("*",0); + if (TestBit(kDisableBranches)) { + printf("Disabling all branches...\n"); +// tree->SetBranchStatus("*",0); // not yet working + } SetEventLoop(kTRUE); } - AliAnalysisDataContainer *cont = 0; - TIter nextc(fInputs); - // Force top containers have the same event loop type as the analysis - while ((cont=(AliAnalysisDataContainer*)nextc())) cont->SetEventByEvent(IsEventLoop()); - AliAnalysisDataContainer *cont_top = (AliAnalysisDataContainer*)fInputs->First(); - TChain *chain = dynamic_cast(tree); + TChain *chain = 0; + TString ttype = "TTree"; + if (tree->IsA() == TChain::Class()) { + chain = (TChain*)tree; + if (!chain || !chain->GetListOfFiles()->First()) { + Error("StartAnalysis", "Cannot process null or empty chain..."); + return; + } + ttype = "TChain"; + } // Initialize locally all tasks TIter next(fTasks); AliAnalysisTask *task; while ((task=(AliAnalysisTask*)next())) { - for (Int_t islot=0; islotGetNinputs(); islot++) { - cont = task->GetInputSlot(islot)->GetContainer(); - if (cont==cont_top) break; - cont = 0; - } - // All tasks feeding from the top containers must have the same event loop type -// if (cont) task->SetExecPerEvent(IsEventLoop()); -// else task->SetExecPerEvent(task->IsExecPerEvent()); task->LocalInit(); } @@ -638,11 +815,10 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree) return; } // Run tree-based analysis via AliAnalysisSelector - gROOT->ProcessLine(".L $ALICE_ROOT/ANALYSIS/AliAnalysisSelector.cxx+"); cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl; sprintf(line, "AliAnalysisSelector *selector = new AliAnalysisSelector((AliAnalysisManager*)0x%lx);",(ULong_t)this); gROOT->ProcessLine(line); - sprintf(line, "((TTree*)0x%lx)->Process(selector);",(ULong_t)tree); + sprintf(line, "((%s*)0x%lx)->Process(selector, \"\",%lld, %lld);",ttype.Data(),(ULong_t)tree, nentries, firstentry); gROOT->ProcessLine(line); break; case kProofAnalysis: @@ -655,7 +831,7 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree) if (chain) { chain->SetProof(); cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON CHAIN " << chain->GetName() << endl; - chain->Process(gSystem->ExpandPathName("$ALICE_ROOT/ANALYSIS/AliAnalysisSelector.cxx+")); + chain->Process("AliAnalysisSelector", "", nentries, firstentry); } else { printf("StartAnalysis: no chain\n"); return; @@ -666,10 +842,63 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree) } } +//______________________________________________________________________________ +void AliAnalysisManager::StartAnalysis(const char *type, const char *dataset, Long64_t nentries, Long64_t firstentry) +{ +// Start analysis for this manager on a given dataset. Analysis task can be: +// LOCAL, PROOF or GRID. Process nentries starting from firstentry. + if (!fInitOK) { + Error("StartAnalysis","Analysis manager was not initialized !"); + return; + } + if (fDebug>1) { + cout << "StartAnalysis: " << GetName() << endl; + } + TString anaType = type; + anaType.ToLower(); + if (!anaType.Contains("proof")) { + Error("Cannot process datasets in %s mode. Try PROOF.", type); + return; + } + fMode = kProofAnalysis; + char line[256]; + SetEventLoop(kTRUE); + // Set the dataset flag + TObject::SetBit(kUseDataSet); + fTree = 0; + + // Initialize locally all tasks + TIter next(fTasks); + AliAnalysisTask *task; + while ((task=(AliAnalysisTask*)next())) { + task->LocalInit(); + } + + if (!gROOT->GetListOfProofs() || !gROOT->GetListOfProofs()->GetEntries()) { + printf("StartAnalysis: no PROOF!!!\n"); + return; + } + sprintf(line, "gProof->AddInput((TObject*)0x%lx);", (ULong_t)this); + gROOT->ProcessLine(line); + sprintf(line, "gProof->GetDataSet(\"%s\");", dataset); + if (!gROOT->ProcessLine(line)) { + Error("StartAnalysis", "Dataset %s not found", dataset); + return; + } + sprintf(line, "gProof->Process(\"%s\", \"AliAnalysisSelector\", \"\", %lld, %lld);", + dataset, nentries, firstentry); + cout << "===== RUNNING PROOF ANALYSIS " << GetName() << " ON DATASET " << dataset << endl; + gROOT->ProcessLine(line); +} + //______________________________________________________________________________ void AliAnalysisManager::ExecAnalysis(Option_t *option) { // Execute analysis. + static Long64_t ncalls = 0; + Bool_t getsysInfo = ((fNSysInfo>0) && (fMode==kLocalAnalysis))?kTRUE:kFALSE; + if (getsysInfo && ncalls==0) AliSysInfo::AddStamp("Start", (Int_t)ncalls); + ncalls++; if (!fInitOK) { Error("ExecAnalysis", "Analysis manager was not initialized !"); return; @@ -677,9 +906,6 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) AliAnalysisTask *task; // Check if the top tree is active. if (fTree) { - if (fDebug>1) { - printf("AliAnalysisManager::ExecAnalysis\n"); - } TIter next(fTasks); // De-activate all tasks while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE); @@ -689,17 +915,40 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) return; } cont->SetData(fTree); // This will notify all consumers - TIter next1(cont->GetConsumers()); + 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); +// +// Execute the tasks +// TIter next1(cont->GetConsumers()); + TIter next1(fTopTasks); while ((task=(AliAnalysisTask*)next1())) { -// task->SetActive(kTRUE); if (fDebug >1) { cout << " Executing task " << task->GetName() << endl; } + task->ExecuteTask(option); } +// +// Call FinishEvent() for optional output and MC services + if (fInputEventHandler) fInputEventHandler ->FinishEvent(); + if (fOutputEventHandler) fOutputEventHandler ->FinishEvent(); + if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent(); + // Gather system information if requested + if (getsysInfo && ((ncalls%fNSysInfo)==0)) + AliSysInfo::AddStamp(Form("Event#%lld",ncalls),(Int_t)ncalls); return; } // The event loop is not controlled by TSelector +// +// Call BeginEvent() for optional input/output and MC services + if (fInputEventHandler) fInputEventHandler ->BeginEvent(-1); + if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(-1); + if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(-1); TIter next2(fTopTasks); while ((task=(AliAnalysisTask*)next2())) { task->SetActive(kTRUE); @@ -708,6 +957,11 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) } task->ExecuteTask(option); } +// +// Call FinishEvent() for optional output and MC services + if (fInputEventHandler) fInputEventHandler ->FinishEvent(); + if (fOutputEventHandler) fOutputEventHandler ->FinishEvent(); + if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent(); } //______________________________________________________________________________