X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;ds=sidebyside;f=ANALYSIS%2FAliAnalysisManager.cxx;h=8f3be8618a877776040788e7774c85f1cb663c11;hb=b7980dfe7f95c317715bf8f6af9129780af1b1e0;hp=f50f7fccf8bc1c347f9a1ba9bbdcc0178a2a110c;hpb=d2f1d9efcee3d35dd60b7dc5c1b5f602af1a5a13;p=u%2Fmrichter%2FAliRoot.git diff --git a/ANALYSIS/AliAnalysisManager.cxx b/ANALYSIS/AliAnalysisManager.cxx index f50f7fccf8b..8f3be8618a8 100644 --- a/ANALYSIS/AliAnalysisManager.cxx +++ b/ANALYSIS/AliAnalysisManager.cxx @@ -33,49 +33,32 @@ #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), - fOutputEventHandler(NULL), - fMCtruthEventHandler(NULL), - fCurrentEntry(-1), - fMode(kLocalAnalysis), - fInitOK(kFALSE), - fDebug(0), - fTasks(NULL), - fTopTasks(NULL), - fZombies(NULL), - fContainers(NULL), - fInputs(NULL), - fOutputs(NULL) -{ -// Dummy constructor. - fgAnalysisManager = this; - SetEventLoop(kTRUE); -} - //______________________________________________________________________________ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) :TNamed(name,title), fTree(NULL), - fOutputEventHandler(NULL), - fMCtruthEventHandler(NULL), + fInputEventHandler(NULL), + fOutputEventHandler(NULL), + fMCtruthEventHandler(NULL), fCurrentEntry(-1), + fNSysInfo(0), fMode(kLocalAnalysis), fInitOK(kFALSE), fDebug(0), + fSpecialOutputLocation(""), fTasks(NULL), fTopTasks(NULL), fZombies(NULL), @@ -98,12 +81,15 @@ AliAnalysisManager::AliAnalysisManager(const char *name, const char *title) AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other) :TNamed(other), fTree(NULL), - fOutputEventHandler(NULL), - fMCtruthEventHandler(NULL), + fInputEventHandler(NULL), + fOutputEventHandler(NULL), + fMCtruthEventHandler(NULL), fCurrentEntry(-1), + fNSysInfo(0), fMode(other.fMode), fInitOK(other.fInitOK), fDebug(other.fDebug), + fSpecialOutputLocation(""), fTasks(NULL), fTopTasks(NULL), fZombies(NULL), @@ -127,10 +113,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; @@ -179,8 +167,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; @@ -195,18 +214,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) { @@ -216,15 +223,33 @@ void AliAnalysisManager::SlaveBegin(TTree *tree) if (fDebug > 1) { cout << "->AliAnalysisManager::SlaveBegin()" << endl; } - // Call InitIO of EventHandler + + // Call Init of EventHandler if (fOutputEventHandler) { - if (fMode == kProofAnalysis) { - fOutputEventHandler->InitIO("proof"); - } else { - fOutputEventHandler->InitIO("local"); - } + 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 @@ -232,8 +257,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; } @@ -247,23 +272,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(); - - // Call Notify of the MC truth handler - if (fMCtruthEventHandler) { - TString fileName(curfile->GetName()); - fileName.ReplaceAll("AliESDs.root", ""); - fMCtruthEventHandler->Notify(fileName.Data()); - } - } - 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; } //______________________________________________________________________________ @@ -287,11 +319,11 @@ 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 (fOutputEventHandler) fOutputEventHandler ->BeginEvent(); - if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(); + if (fInputEventHandler) fInputEventHandler ->BeginEvent(entry); + if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(entry); + if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(entry); GetEntry(entry); ExecAnalysis(); @@ -313,7 +345,7 @@ void AliAnalysisManager::PackOutput(TList *target) Error("PackOutput", "No target. Aborting."); return; } - + if (fInputEventHandler) fInputEventHandler ->Terminate(); if (fOutputEventHandler) fOutputEventHandler ->Terminate(); if (fMCtruthEventHandler) fMCtruthEventHandler->Terminate(); @@ -321,9 +353,70 @@ void AliAnalysisManager::PackOutput(TList *target) 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; + + const char *filename = output->GetFileName(); + if (!(strcmp(filename, "default"))) { + if (fOutputEventHandler) filename = fOutputEventHandler->GetOutputFileName(); + } + if (strlen(filename)) { + TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); + TDirectory *opwd = gDirectory; + if (file) file->cd(); + else file = new TFile(filename, "RECREATE"); + if (file->IsZombie()) continue; + // Clear file list to release object ownership to user. + // Save data to file, then close. + file->Clear(); + output->GetData()->Write(); + file->Close(); + // Set null directory to histograms and trees. + TMethodCall callEnv; + if (output->GetData()->IsA()) + callEnv.InitWithPrototype(output->GetData()->IsA(), "SetDirectory", "TDirectory*"); + if (callEnv.IsValid()) { + callEnv.SetParam(Long_t(0)); + callEnv.Execute(output->GetData()); + } + // Restore current directory + if (opwd) opwd->cd(); + } + 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()); + } else { + // No special location specified-> use TProofFile as merging utility + char line[256]; + sprintf(line, "((TList*)0x%lx)->Add(new TProofFile(\"%s\"));", + (ULong_t)target, output->GetFileName()); + gROOT->ProcessLine(line); + } + } } + // Cleanup tasks on each slave + TIter nexttask(fTasks); + AliAnalysisTask *task; + while ((task=(AliAnalysisTask*)nexttask())) task->Cleanup(); } if (fDebug > 1) { printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize()); @@ -342,6 +435,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()); @@ -360,8 +455,7 @@ void AliAnalysisManager::ImportWrappers(TList *source) //______________________________________________________________________________ void AliAnalysisManager::UnpackOutput(TList *source) { - // Called by AliAnalysisSelector::Terminate. Output containers should - // be in source in the same order as in fOutputs. + // Called by AliAnalysisSelector::Terminate only on the client. if (fDebug > 1) { cout << "->AliAnalysisManager::UnpackOutput()" << endl; } @@ -405,6 +499,7 @@ void AliAnalysisManager::UnpackOutput(TList *source) 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; @@ -417,6 +512,7 @@ void AliAnalysisManager::UnpackOutput(TList *source) callEnv.Execute(output->GetData()); } output->GetData()->Write(); + if (opwd) opwd->cd(); } if (fDebug > 1) { cout << "<-AliAnalysisManager::UnpackOutput()" << endl; @@ -440,7 +536,50 @@ void AliAnalysisManager::Terminate() cout << "<-AliAnalysisManager::Terminate()" << endl; } // - if (fOutputEventHandler) fOutputEventHandler->TerminateIO(); + 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(); + } } //______________________________________________________________________________ @@ -479,7 +618,10 @@ AliAnalysisDataContainer *AliAnalysisManager::CreateContainer(const char *name, break; case kOutputContainer: 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; @@ -623,6 +765,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())) @@ -637,9 +786,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; @@ -658,7 +808,7 @@ 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 all branches if requested and set event loop mode if (tree) { @@ -669,7 +819,16 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree) SetEventLoop(kTRUE); } - 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); @@ -694,11 +853,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: @@ -711,7 +869,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("AliAnalysisSelector"); + chain->Process("AliAnalysisSelector", "", nentries, firstentry); } else { printf("StartAnalysis: no chain\n"); return; @@ -722,10 +880,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; @@ -733,9 +944,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); @@ -745,13 +953,17 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) return; } cont->SetData(fTree); // This will notify all consumers + Long64_t entry = fTree->GetTree()->GetReadEntry(); + // -// Call BeginEvent() for optional output and MC services - if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(); - if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(); +// 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(cont->GetConsumers()); + TIter next1(fTopTasks); while ((task=(AliAnalysisTask*)next1())) { if (fDebug >1) { cout << " Executing task " << task->GetName() << endl; @@ -761,16 +973,20 @@ void AliAnalysisManager::ExecAnalysis(Option_t *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 output and MC services - if (fOutputEventHandler) fOutputEventHandler ->BeginEvent(); - if (fMCtruthEventHandler) fMCtruthEventHandler->BeginEvent(); +// 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); @@ -781,7 +997,8 @@ void AliAnalysisManager::ExecAnalysis(Option_t *option) } // // Call FinishEvent() for optional output and MC services - if (fOutputEventHandler) fOutputEventHandler->FinishEvent(); + if (fInputEventHandler) fInputEventHandler ->FinishEvent(); + if (fOutputEventHandler) fOutputEventHandler ->FinishEvent(); if (fMCtruthEventHandler) fMCtruthEventHandler->FinishEvent(); }