From e1d7f1f3705837358e565ac5167a316bdb5908d8 Mon Sep 17 00:00:00 2001
From: Melissa Yexley <m.yexley@cern.ch>
Date: Mon, 12 Feb 2024 14:32:00 +0100
Subject: [PATCH] moving the OnlineEventDisplays service to c++ from python and
 too many other things

---
 graphics/EventDisplaysOnline/CMakeLists.txt   |  19 +-
 .../IOnlineEventDisplaysSvc.h                 |  31 +++
 .../OnlineEventDisplaysSvc.h                  |  66 +++++
 .../python/EventDisplaysOnlineConfig.py       | 153 ++++++------
 .../EventDisplaysOnline/python/EventUtils.py  |  41 ++--
 .../python/OnlineEventDisplaysSvc.py          | 228 ------------------
 .../src/IOnlineEventDisplaysSvc.cxx           |   7 +
 .../src/OnlineEventDisplaysSvc.cxx            | 208 ++++++++++++++++
 .../EventDisplaysOnline_entries.cxx           |   3 +
 graphics/JiveXML/CMakeLists.txt               |   6 +-
 graphics/JiveXML/JiveXML/AlgoJiveXML.h        |   8 -
 graphics/JiveXML/JiveXML/StreamToFileTool.h   |  29 ++-
 graphics/JiveXML/JiveXML/StreamToServerTool.h |  25 +-
 graphics/JiveXML/python/JiveXMLConfig.py      |   2 -
 graphics/JiveXML/src/AlgoJiveXML.cxx          |  34 +--
 graphics/JiveXML/src/StreamToFileTool.cxx     |  52 ++--
 graphics/JiveXML/src/StreamToServerTool.cxx   |  20 +-
 graphics/VP1/VP1AlgsEventProd/CMakeLists.txt  |   2 +-
 .../VP1AlgsEventProd/VP1EventProd.h           |   7 +
 .../VP1/VP1AlgsEventProd/src/VP1EventProd.cxx |  70 +++---
 .../VP1/VP1UtilsBase/src/VP1FileUtilities.cxx |   2 +-
 21 files changed, 555 insertions(+), 458 deletions(-)
 create mode 100644 graphics/EventDisplaysOnline/EventDisplaysOnline/IOnlineEventDisplaysSvc.h
 create mode 100644 graphics/EventDisplaysOnline/EventDisplaysOnline/OnlineEventDisplaysSvc.h
 delete mode 100644 graphics/EventDisplaysOnline/python/OnlineEventDisplaysSvc.py
 create mode 100644 graphics/EventDisplaysOnline/src/IOnlineEventDisplaysSvc.cxx
 create mode 100644 graphics/EventDisplaysOnline/src/OnlineEventDisplaysSvc.cxx
 create mode 100644 graphics/EventDisplaysOnline/src/components/EventDisplaysOnline_entries.cxx

diff --git a/graphics/EventDisplaysOnline/CMakeLists.txt b/graphics/EventDisplaysOnline/CMakeLists.txt
index b5650338bb96..bbc6762dce9e 100644
--- a/graphics/EventDisplaysOnline/CMakeLists.txt
+++ b/graphics/EventDisplaysOnline/CMakeLists.txt
@@ -1,10 +1,25 @@
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 
 # Declare the package name:
 atlas_subdir( EventDisplaysOnline )
 
+find_package( Python COMPONENTS Development )
+
+atlas_add_library(EventDisplaysOnlineLib
+  INTERFACE
+  EventDisplaysOnline/*.h
+  src/*.cxx
+  PUBLIC_HEADERS EventDisplaysOnline
+  INCLUDE_DIRS ${Python_INCLUDE_DIRS}
+  LINK_LIBRARIES ${Python_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel xAODEventInfo RootUtils)
+
+atlas_add_component( EventDisplaysOnline
+  EventDisplaysOnline/*.h
+  src/*.cxx
+  src/components/*.cxx
+  LINK_LIBRARIES EventDisplaysOnlineLib )
+
 # Install files from the package:
 atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
 atlas_install_joboptions( share/*.py )
 atlas_install_scripts( scripts/*.sh )
-
diff --git a/graphics/EventDisplaysOnline/EventDisplaysOnline/IOnlineEventDisplaysSvc.h b/graphics/EventDisplaysOnline/EventDisplaysOnline/IOnlineEventDisplaysSvc.h
new file mode 100644
index 000000000000..cc57dff5b34a
--- /dev/null
+++ b/graphics/EventDisplaysOnline/EventDisplaysOnline/IOnlineEventDisplaysSvc.h
@@ -0,0 +1,31 @@
+
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef IONLINEEVENTDISPLAYSSVC_H
+#define IONLINEEVENTDISPLAYSSVC_H
+
+#include "GaudiKernel/IService.h"
+
+
+class IOnlineEventDisplaysSvc : virtual public IService {
+
+public:
+
+  virtual ~IOnlineEventDisplaysSvc();
+   
+  static const InterfaceID& interfaceID();
+  virtual std::string getFileNamePrefix() = 0;
+  virtual std::string getStreamName() = 0;
+  virtual std::string getEntireOutputStr() = 0;
+};
+
+inline const InterfaceID& IOnlineEventDisplaysSvc::interfaceID()
+{ 
+  static const InterfaceID IID_IOnlineEventDisplaysSvc("IOnlineEventDisplaysSvc", 1, 0);
+  return IID_IOnlineEventDisplaysSvc; 
+}
+
+#endif
+
diff --git a/graphics/EventDisplaysOnline/EventDisplaysOnline/OnlineEventDisplaysSvc.h b/graphics/EventDisplaysOnline/EventDisplaysOnline/OnlineEventDisplaysSvc.h
new file mode 100644
index 000000000000..4c19ea07442e
--- /dev/null
+++ b/graphics/EventDisplaysOnline/EventDisplaysOnline/OnlineEventDisplaysSvc.h
@@ -0,0 +1,66 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ONLINEEVENTDISPLAYSSVC_H
+#define ONLINEEVENTDISPLAYSSVC_H
+
+#include "AthenaBaseComps/AthService.h"
+#include "EventDisplaysOnline/IOnlineEventDisplaysSvc.h"
+#include "GaudiKernel/IIncidentListener.h"
+#include "StoreGate/ReadHandle.h"
+#include "xAODEventInfo/EventInfo.h"
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <grp.h>
+
+template <class TYPE> class SvcFactory;
+
+class OnlineEventDisplaysSvc : public AthService, virtual public IOnlineEventDisplaysSvc, virtual public IIncidentListener {
+
+protected:
+  friend class SvcFactory<OnlineEventDisplaysSvc>;
+  
+public:
+
+  OnlineEventDisplaysSvc( const std::string& name, ISvcLocator* pSvcLocator );
+  virtual ~OnlineEventDisplaysSvc();
+   
+  static const InterfaceID& interfaceID();
+
+  //To allow access to the IOnlineEventDisplaysSvc interface
+  StatusCode queryInterface( const InterfaceID& riid, void** ppvIf );
+
+  StatusCode initialize();
+  StatusCode finalize();
+  void beginEvent();
+  void endEvent();
+  void handle(const Incident& incident );       
+  void createWriteableDir(std::string directory, gid_t zpgid);
+  gid_t setOwnershipToZpGrpOrDefault();
+  std::string getFileNamePrefix() override;
+  std::string getEntireOutputStr() override;
+  std::string getStreamName() override;
+  
+private:
+  OnlineEventDisplaysSvc();
+  SG::ReadHandleKey<xAOD::EventInfo> m_evt{this, "EventInfo", "EventInfo", "Input event information"};
+  Gaudi::Property<std::string> m_outputDirectory {this, "OutputDirectory", "/atlas/EventDisplayEvents", "Output Directory"};
+  Gaudi::Property<std::vector<std::string>> m_streamsWanted {this, "StreamsWanted", {}, "Desired trigger streams"};
+  Gaudi::Property<std::vector<std::string>> m_publicStreams {this, "PublicStreams", {}, "Desired public streams"};
+  Gaudi::Property<bool> m_sendToPublicStream {this, "SendToPublicStream", false, "Allowed to be seen by the public on atlas live"};
+  Gaudi::Property<int> m_maxEvents {this, "MaxEvents", 200, "Number of events to keep per stream"};
+  std::string m_FileNamePrefix = "JiveXML";
+  std::string m_outputStreamDir = ".Unknown";
+  std::string m_entireOutputStr = ".";
+};
+
+inline const InterfaceID& OnlineEventDisplaysSvc::interfaceID()
+{ 
+  return IOnlineEventDisplaysSvc::interfaceID();
+}
+
+#endif
+
diff --git a/graphics/EventDisplaysOnline/python/EventDisplaysOnlineConfig.py b/graphics/EventDisplaysOnline/python/EventDisplaysOnlineConfig.py
index d4f3fda412d0..b78cbb2f1757 100644
--- a/graphics/EventDisplaysOnline/python/EventDisplaysOnlineConfig.py
+++ b/graphics/EventDisplaysOnline/python/EventDisplaysOnlineConfig.py
@@ -3,13 +3,36 @@
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
 from EventDisplaysOnline.EventDisplaysOnlineHelpers import GetRunType, GetBFields, WaitForPartition
-from AthenaCommon.Constants import INFO, DEBUG
 
 isHIMode = False #TODO
 #TODO isBeamSplashMode = False
 isOfflineTest = True
 testWithoutPartition = True
 
+# An explicit list for nominal data taking to exclude some high rate streams
+# Empty list to read all
+# 'MinBias' for beam splashes
+streamsWanted = ['express','ZeroBias','CosmicCalo','IDCosmic','CosmicMuons','Background','Standby','L1Calo','Main']
+
+# if testing at p1, write out to /tmp/ to see output
+outputDirectory="/atlas/EventDisplayEvents/"
+
+if isOfflineTest:
+    outputDirectory="/afs/cern.ch/user/m/myexley/WorkSpace/hackTest/run/output/"
+
+if isHIMode:
+    maxEvents=200
+    projectTags=['data24_hi']
+    projectName='data24_hi'
+    publicStreams=['MinBias']
+else:
+    maxEvents=100 # Number of events to keep per stream
+    projectTags=['data23_13p6TeV']
+    projectName='data24_13p6TeV'
+    publicStreams=['Main']
+
+sendToPublicStream = True # Gets set later, overwrite here to True to test it
+
 ##----------------------------------------------------------------------##
 ## When the ATLAS partition is not running you can use two test         ##
 ## partitions that serve events from a raw data file.                   ##
@@ -21,26 +44,12 @@ testWithoutPartition = True
 ## /det/dqm/GlobalMonitoring/GMTestPartition_oks/tdaq-10-00-00/         ##
 ## without_gatherer/GMTestPartition.data.xml                            ##
 ##----------------------------------------------------------------------##
-partitionName = 'GMTestPartition' # ''ATLAS', 'GMTestPartitionT9' or 'GMTestPartition' 
+partitionName = 'GMTestPartition' # 'ATLAS', 'GMTestPartitionT9' or 'GMTestPartition'
 
 # Pause this thread until the partition is up
 if not testWithoutPartition or not isOfflineTest:
     WaitForPartition(partitionName)
 
-# outputDirectory="/atlas/EventDisplayEvents/"
-outputDirectory="/afs/cern.ch/user/m/myexley/WorkSpace/testCA/run/output/"
-
-if isHIMode:
-    maxEvents=200
-    projectTags=['data23_hi']
-    projectName='data23_hi'
-    publicStreams=['physics_MinBias']
-else:
-    maxEvents=100
-    projectTags=['data23_13p6TeV']
-    projectName='data23_13p6TeV'
-    publicStreams=['physics_Main']
-
 # Setup unique output files (so that multiple Athena jobs on the same machine don't interfere)
 import os
 jobId = os.environ.get('TDAQ_APPLICATION_NAME', '').split(':')
@@ -70,7 +79,7 @@ flags.GeoModel.Layout="atlas"
 flags.GeoModel.AtlasVersion = 'ATLAS-R3S-2021-03-02-00' # Geometry tag
 
 if isHIMode:
-    flags.Beam.BunchSpacing = 100 # ns    
+    flags.Beam.BunchSpacing = 100 # ns
 else:
     flags.Beam.BunchSpacing = 25 # ns
 flags.Trigger.triggerConfig='DB'
@@ -86,14 +95,16 @@ else:
 flags.Output.doWriteESD = True
 #flags.Output.doJiveXML = True
 
-if testWithoutPartition or isOfflineTest:
-    #flags.Input.Files = ['/detwork/dqm/EventDisplays_test_data/data23_13p6TeV.00454188.physics_Main.daq.RAW._lb0633._SFO-12._0002.data']
+if testWithoutPartition:
+    flags.Input.Files = ['/detwork/dqm/EventDisplays_test_data/data23_13p6TeV.00454188.physics_Main.daq.RAW._lb0633._SFO-12._0002.data']
+if isOfflineTest:
     flags.Input.Files = ['/eos/home-m/myexley/sharedWithATLASauthors/data23_13p6TeV.00454188.physics_Main.daq.RAW._lb0633._SFO-12._0002.data']
 else:
     flags.Input.Files = [] # Files are read from the ATLAS (or GM test) partition
 
 flags.Reco.EnableTrigger = False # TODO test True
 flags.LAr.doHVCorr = False # ATLASRECTS-6823
+from AthenaCommon.Constants import INFO
 flags.Exec.OutputLevel = INFO
 flags.Concurrency.NumThreads = 0
 
@@ -106,12 +117,23 @@ if partitionName == 'ATLAS' and not testWithoutPartition and not isOfflineTest:
     # Read run number from the partition
     # For beam plashes when LAr running in 32 samples mode, the current run number to LAr config is needed
     # IS stands for Information Service
-    from ispy import ISObject, IPCPartition
-    RunParams = ISObject(IPCPartition(partitionName), 'RunParams.RunParams', 'RunParams')
+    from ispy import ISObject, IPCPartition, ISInfoAny, ISInfoDictionary
+    part = IPCPartition(partitionName)
+    RunParams = ISObject(part, 'RunParams.RunParams', 'RunParams')
     RunParams.checkout()
     flags.Input.OverrideRunNumber =True
     flags.Input.RunNumbers = [RunParams.run_number]
-    
+
+    # Is the data allowed to be seen by the general public on atlas live
+    ready4physics = ISInfoAny()
+    ISInfoDictionary(part).getValue('RunParams.Ready4Physics', ready4physics)
+    print("Ready for physics: %s " % ready4physics.get())
+    physicsReady = ISObject(part, 'RunParams.Ready4Physics','Ready4PhysicsInfo')
+    physicsReady.checkout()
+    print("Ready for physics: %r" % (physicsReady.ready4physics))
+    if physicsReady.ready4physics and RunParams.T0_project_tag in projectTags:
+        sendToPublicStream = True
+
     # Get the B field
     (solenoidOn,toroidOn)=GetBFields()
     flags.BField.override = True
@@ -121,7 +143,7 @@ if partitionName == 'ATLAS' and not testWithoutPartition and not isOfflineTest:
 
 # GM test partition needs to be given the below info
 if (partitionName == 'GMTestPartition' or partitionName == 'GMTestPartitionT9') and not testWithoutPartition:
-    flags.Input.OverrideRunNumber =True
+    flags.Input.OverrideRunNumber = True
     flags.Input.RunNumbers = [412343]
     flags.Input.LumiBlockNumbers = [1]
     flags.Input.ProjectName = projectName
@@ -137,20 +159,9 @@ flags.dump()
 from RecJobTransforms.RecoSteering import RecoSteering
 acc = RecoSteering(flags)
 
-#from IOVDbSvc.IOVDbSvcConfig import addOverride
-#if isOfflineTest:
-#    acc.merge(addOverride(flags,"/TRT/Calib/PID_NN", "TRTCalibPID_NN_v1"))
-#else:
-#    acc.merge(addOverride(flags, "/TRT/Onl/Calib/PID_NN", "TRTCalibPID_NN_v2"))
-
-if isHIMode:
-    maxEvents=200
-    projectTags=['data23_hi']
-    publicStreams=['physics_MinBias']
-else:
-    maxEvents=100
-    projectTags=['data23_13p6TeV']
-    publicStreams=['physics_Main']
+from IOVDbSvc.IOVDbSvcConfig import addOverride
+if not isOfflineTest:
+    acc.merge(addOverride(flags, "/TRT/Onl/Calib/PID_NN", "TRTCalibPID_NN_v2"))
 
 if not testWithoutPartition:
     bytestreamConversion = CompFactory.ByteStreamCnvSvc()
@@ -169,70 +180,49 @@ if not testWithoutPartition:
     bytestreamInput.UpdatePeriod = 200
     bytestreamInput.BufferSize = 10 # three times of keycount for beam splashes
     bytestreamInput.ISServer = '' # Disable histogramming
-    # Empty stream name list to read all streams
-    # 'MinBias' for beam splashes
-    # An explicit list for nominal data taking to exclude some high rate streams
-    bytestreamInput.StreamNames = ['ZeroBias:CosmicCalo:IDCosmic:CosmicMuons:Background:Standby:L1Calo:Main']
-    bytestreamInput.StreamType = "physics"
+    bytestreamInput.StreamNames = streamsWanted
+    #bytestreamInput.StreamType = "physics" #comment out for all streams, e.g. if you also want claibration streams
     bytestreamInput.StreamLogic = "Or"
 
     if partitionName != 'ATLAS':
         bytestreamInput.KeyValue = [ 'Test_emon_push' ]
         bytestreamInput.KeyCount = 1
 
+onlineEventDisplaysSvc = CompFactory.OnlineEventDisplaysSvc(
+    name = "OnlineEventDisplaysSvc",
+    MaxEvents = maxEvents,                   # Number of events to keep per stream
+    OutputDirectory = outputDirectory,       # Base directory for streams
+    SendToPublicStream = sendToPublicStream, # Allowed to be made public
+    PublicStreams = publicStreams,           # These streams go into public stream when Ready4Physics
+    StreamsWanted = streamsWanted,
+)
+acc.addService(onlineEventDisplaysSvc, create=True)
+
 def StreamToFileToolCfg(flags, name='StreamToFileTool',**kwargs):
     result = ComponentAccumulator()
-    #prefixFileName = "%s/.Unknown/JiveXMLtest" % outputDirectory
-    #kwargs.setdefault("FileNamePrefix", prefixFileName)
-    kwargs.setdefault("MyTest", "EDOcofig")
+    kwargs.setdefault("OnlineEventDisplaysSvc", acc.getService("OnlineEventDisplaysSvc"))
+    kwargs.setdefault("IsOnline", True)
     the_tool = CompFactory.JiveXML.StreamToFileTool(**kwargs)
     result.setPrivateTools(the_tool)
     return result
 streamToFileTool = acc.popToolsAndMerge(StreamToFileToolCfg(flags))
 
+streamToServerTool = None
 if not isOfflineTest:
     def StreamToServerToolCfg(flags, name="StreamToServerTool",**kwargs):
         result = ComponentAccumulator()
+        kwargs.setdefault("OnlineEventDisplaysSvc", acc.getService("OnlineEventDisplaysSvc"))
         serverService = CompFactory.JiveXML.ExternalONCRPCServerSvc(name="ExternalONCRPCServerSvc", Hostname = "pc-tdq-mon-29")
         result.addService(serverService)
         kwargs.setdefault("ServerService",serverService)
-        kwargs.setdefault("StreamName","Unknown")
+        kwargs.setdefault("StreamName",".Unknown")
         the_tool = CompFactory.JiveXML.StreamToServerTool(name,**kwargs)
-        result.addPublicTool(the_tool)
+        result.setPrivateTools(the_tool)
         return result
-    acc.merge(StreamToServerToolCfg(flags))
-print('type in ED: ', type(streamToFileTool))
-print('StreamToFileTool in ED',getattr(streamToFileTool,'MyTest'))
-from JiveXML.JiveXMLConfig import AlgoJiveXMLCfg
-acc.merge(AlgoJiveXMLCfg(flags,StreamToFileTool=streamToFileTool))
-
-# This creates an ESD file per event which is renamed and moved to the desired output
-# dir in the VP1 Event Prod alg
-from AthenaServices.OutputStreamSequencerSvcConfig import OutputStreamSequencerSvcCfg
-acc.merge(OutputStreamSequencerSvcCfg(flags,incidentName="EndEvent"))
+    streamToServerTool = acc.popToolsAndMerge(StreamToServerToolCfg(flags))
 
-StreamESD = acc.getEventAlgo("OutputStreamESD")
-print('StreamESD',type(StreamESD))
-vp1Alg = CompFactory.VP1EventProd(name="VP1EventProd", InputPoolFile = StreamESD.OutputFile)
-acc.addEventAlgo(vp1Alg)
-
-from EventDisplaysOnline.OnlineEventDisplaysSvc import OnlineEventDisplaysSvc
-svc = OnlineEventDisplaysSvc(
-    name = "OnlineEventDisplaysSvc",
-    OutputLevel = DEBUG,               # Verbosity
-    MaxEvents = maxEvents,             # Number of events to keep per stream
-    OutputDirectory = outputDirectory, # Base directory for streams
-    ProjectTags = projectTags,         # Project tags that are allowed to be made public
-    Public = publicStreams,            # These streams go into public stream when Ready4Physics
-    StreamToFileTool = streamToFileTool,
-    VP1EventProducer = vp1Alg,
-)
-acc.addService(svc, create=True)
-
-# This creates an ESD file per event which is renamed and moved to the desired output
-# dir in the VP1 Event Prod alg
-from AthenaServices.OutputStreamSequencerSvcConfig import OutputStreamSequencerSvcCfg
-acc.merge(OutputStreamSequencerSvcCfg(flags,incidentName="EndEvent"))
+from JiveXML.JiveXMLConfig import AlgoJiveXMLCfg
+acc.merge(AlgoJiveXMLCfg(flags,StreamToFileTool=streamToFileTool,StreamToServerTool=streamToServerTool))
 
 # This creates an ESD file per event which is renamed and moved to the desired output
 # dir in the VP1 Event Prod alg
@@ -240,7 +230,10 @@ from AthenaServices.OutputStreamSequencerSvcConfig import OutputStreamSequencerS
 acc.merge(OutputStreamSequencerSvcCfg(flags,incidentName="EndEvent"))
 
 StreamESD = acc.getEventAlgo("OutputStreamESD")
-vp1Alg = CompFactory.VP1EventProd(name="VP1EventProd", InputPoolFile = StreamESD.OutputFile)
+vp1Alg = CompFactory.VP1EventProd(name="VP1EventProd",
+                                  InputPoolFile = StreamESD.OutputFile,
+                                  IsOnline = True,
+                                  OnlineEventDisplaysSvc = onlineEventDisplaysSvc)
 acc.addEventAlgo(vp1Alg)
 
 acc.getService("PoolSvc").WriteCatalog = "xmlcatalog_file:PoolFileCatalog_%s_%s.xml" % (jobId[3], jobId[4])
diff --git a/graphics/EventDisplaysOnline/python/EventUtils.py b/graphics/EventDisplaysOnline/python/EventUtils.py
index f9f4b55dcef4..dfb0488f8135 100644
--- a/graphics/EventDisplaysOnline/python/EventUtils.py
+++ b/graphics/EventDisplaysOnline/python/EventUtils.py
@@ -1,8 +1,9 @@
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 
 import os, re, time, glob, shutil
 from pathlib import Path
 from zipfile import ZipFile, ZIP_DEFLATED
+from AthenaCommon.Logging import logging
 
 # This method reads the files in the given directory, sorts them by run/event number,
 # finds atlantis and vp1 files belonging to the same event and returns a list of events
@@ -10,7 +11,8 @@ from zipfile import ZipFile, ZIP_DEFLATED
 # checkpair=True and remove=True, remove the files that do not form an atlanits-vp1 pair
 # checkpair=True and remove=False, generate event list for atlantis-vp1 pairs
 # checkpair=False, generate event list without checking for valid pairs
-def getEventlist(msg, directory, checkpair, remove=True, patternAtlantis='.xml', patternVP1='.pool.root'):
+def getEventlist(directory, checkpair, remove=True, patternAtlantis='.xml', patternVP1='.pool.root'):
+    msg = logging.getLogger( 'EventUtils' )
     msg.verbose('%s begin get event list', time.ctime(time.time()))
     filelist = []
     files = os.listdir(directory)
@@ -61,7 +63,8 @@ def getEventlist(msg, directory, checkpair, remove=True, patternAtlantis='.xml',
     return eventlist
 
 # Prune events in the given directory if the number exceeds the specified number
-def pruneEvents(msg, directory, maxevents, eventlist):
+def pruneEvents(directory, maxevents, eventlist):
+    msg = logging.getLogger( 'EventUtils' )
     msg.verbose('%s begin prune events', time.ctime(time.time()))
     i = 0
     numevents = len(eventlist)
@@ -86,7 +89,8 @@ def pruneEvents(msg, directory, maxevents, eventlist):
     msg.verbose('%s end prune events', time.ctime(time.time()))
 
 # Build the event.list file that is used by atlas-live.cern.ch for synchronizing events
-def writeEventlist(msg, directory, eventlist, listname='event'):
+def writeEventlist(directory, eventlist, listname='event'):
+    msg = logging.getLogger( 'EventUtils' )
     msg.verbose('%s begin write event list', time.ctime(time.time()))
     pid = os.getpid()
     try:
@@ -105,20 +109,23 @@ def writeEventlist(msg, directory, eventlist, listname='event'):
     msg.verbose('%s end write event list', time.ctime(time.time()))
 
 # Perform all of these in one command
-def cleanDirectory(msg, directory, maxevents, checkpair):
+def cleanDirectory(directory, maxevents, checkpair):
+    msg = logging.getLogger( 'EventUtils' )
+    print('In cleanDirectory!')
     msg.verbose('%s begin clean directory', time.ctime(time.time()))
-    eventlist = getEventlist(msg, directory, checkpair)
+    eventlist = getEventlist(directory, checkpair)
     if maxevents>0:
-        pruneEvents(msg, directory, maxevents, eventlist)
-    writeEventlist(msg, directory, eventlist)
+        pruneEvents(directory, maxevents, eventlist)
+    writeEventlist(directory, eventlist)
 
     # disable this for beam splashes. Call zipXMLFile directly in OnlineEventDisplaysSvc.py to transfer every event.
     if len(eventlist)>0:
-        prepareFilesForTransfer(msg, directory, eventlist, pair=checkpair, timeinterval=60)
+        prepareFilesForTransfer(directory, eventlist, pair=checkpair, timeinterval=60)
 
     msg.verbose('%s end clean directory', time.ctime(time.time()))
 
-def prepareFilesForTransfer(msg, directory, eventlist, pair, timeinterval):
+def prepareFilesForTransfer(directory, eventlist, pair, timeinterval):
+    msg = logging.getLogger( 'EventUtils' )
     """Preparing the list of files for CastorScript to transfer to EOS
 
     CastorScript is configured to look for *.zip and *.online.pool.root files to transfer.
@@ -132,7 +139,7 @@ def prepareFilesForTransfer(msg, directory, eventlist, pair, timeinterval):
     timeinterval: time interval between two events in the transfer list (in seconds).
     """
     msg.verbose('%s begin prepare files for transfer', time.ctime(time.time()))
-    transferlist = getEventlist(msg, directory, checkpair=pair, remove=False, patternAtlantis='.zip', patternVP1='.online.pool.root')
+    transferlist = getEventlist(directory, checkpair=pair, remove=False, patternAtlantis='.zip', patternVP1='.online.pool.root')
     if len(transferlist)>0 and eventlist[-1][0] == transferlist[-1][0] and eventlist[-1][1] == transferlist[-1][1]:
         msg.debug("Last event already in transfer list. No new event to transfer.")
         return
@@ -162,17 +169,18 @@ def prepareFilesForTransfer(msg, directory, eventlist, pair, timeinterval):
 
     # Handle atlantis files
     msg.debug('%s going to zip file %s', time.ctime(time.time()), atlantis)
-    zipXMLFile(msg, directory, atlantis)
+    zipXMLFile(directory, atlantis)
 
     # Handle VP1 files
     if pair:
         msg.debug('%s going to rename ESD file %s', time.ctime(time.time()), vp1)
-        renameESDFile(msg, directory, vp1)
+        renameESDFile(directory, vp1)
 
-    writeEventlist(msg, directory, transferlist, listname='transfer')
+    writeEventlist(directory, transferlist, listname='transfer')
     msg.verbose('%s end prepare files for transfer', time.ctime(time.time()))
 
-def zipXMLFile(msg, directory, filename):
+def zipXMLFile(directory, filename):
+    msg = logging.getLogger( 'EventUtils' )
     """Zip the JiveXML file for the specified event.
 
     Looks for a JiveXML file with the required filename in the given directory,
@@ -201,7 +209,8 @@ def zipXMLFile(msg, directory, filename):
             msg.warning("Could not zip %s: %s", filename, err)
     msg.verbose('%s end of zipXMLFile', time.ctime(time.time()))
 
-def renameESDFile(msg, directory, filename):
+def renameESDFile(directory, filename):
+    msg = logging.getLogger( 'EventUtils' )
     """Rename the ESD for the specified event.
 
     Looks for an ESD file with the required filename in the given directory,
diff --git a/graphics/EventDisplaysOnline/python/OnlineEventDisplaysSvc.py b/graphics/EventDisplaysOnline/python/OnlineEventDisplaysSvc.py
deleted file mode 100644
index 59770277165e..000000000000
--- a/graphics/EventDisplaysOnline/python/OnlineEventDisplaysSvc.py
+++ /dev/null
@@ -1,228 +0,0 @@
-# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
-
-__doc__ = """This service runs in the online Athena event display threads. It
-manages the distribution of incoming events to the right event display streams.
-In order to do that it connects to the different Atlantis and VP1 event output
-algorithms/tools and manipulates their job options during the run.
-"""
-__version__ = "0.1"
-__author__  = "Eric Jansen <eric.jansen@cern.ch>"
-
-import os, grp, stat, random
-from ipc import IPCPartition
-from ispy import ISInfoDictionary, ISInfoAny, ISObject
-from AthenaPython import PyAthena
-from AthenaPython.PyAthena import StatusCode
-from PyAnalysisCore import PyEventTools
-from EventDisplaysOnline import EventUtils
-
-class OnlineEventDisplaysSvc( PyAthena.Svc ):
-
-        def __init__(self, name = 'OnlineEventDisplaysSvc', **kw):
-                kw['name'] = name
-                self.output = kw.get('OutputDirectory')
-                self.maxevents = kw.get('MaxEvents')
-                self.public = kw.get('Public')
-                self.projecttags = kw.get('ProjectTags')
-
-                self.zpgid = None
-                self.partition = None
-                self.StreamToFileTool = kw.get('StreamToFileTool')
-                self.StreamToServerTool = None
-                self.VP1EventProducer = None#kw.get('VP1EventProducer')
-                
-                self.run = 0
-                self.event = 0
-                self.stream = ''
-                self.directory = ''
-
-                super(OnlineEventDisplaysSvc,self).__init__(**kw)
-
-        def initialize(self):
-                incidentSvc = PyAthena.py_svc('IncidentSvc', iface='IIncidentSvc')
-                incidentSvc.addListener(self, 'BeginEvent')
-                incidentSvc.addListener(self, 'StoreCleared')
-
-                self.partition = IPCPartition('ATLAS')
-                self.dict = ISInfoDictionary(self.partition)
-                try:
-                        self.zpgid = grp.getgrnam("zp").gr_gid
-                except:
-                        # If running on private machine, zp group might not exist. 
-                        # Just set to the likely value
-                        self.zpgid = 1307 
-                return StatusCode.Success
-
-        def finalize(self):
-                return StatusCode.Success
-
-        def getJobOptions(self):
-                self.StreamToFileTool = PyAthena.py_tool(self.StreamToFileTool.getFullName(), iface='IProperty')#createIf=False
-                self.StreamToServerTool = PyAthena.py_tool('JiveXML::StreamToServerTool', iface='IProperty')
-                
-                # Some casting magic is needed to access algorithm properties
-                from GaudiPython.Bindings import gbl, InterfaceCast
-                vp1alg = PyAthena.py_alg('VP1EventProd')
-                self.VP1EventProducer = InterfaceCast(gbl.IProperty).cast(vp1alg)
-
-                self.msg.info("StreamToFileTool: %s", self.StreamToFileTool)
-                self.msg.info("StreamToServerTool: %s", self.StreamToServerTool)
-                self.msg.info("VP1EventProducer: %s", self.VP1EventProducer)
-                                
-        def beginEvent(self):
-                if not (self.StreamToFileTool and self.StreamToServerTool and self.VP1EventProducer):
-                        self.getJobOptions()
-
-                try:
-                        eventInfo = PyEventTools.getEventInfo('EventInfo')
-                except LookupError as err:
-                        self.msg.error("Could not retrieve EventInfo: %s", err)
-                        return StatusCode.Recoverable
-
-                try:
-                        # Read event info
-                        self.run = eventInfo.runNumber()
-                        self.event = eventInfo.eventNumber()
-
-                        # Retrieve trigger info
-                        streamTags = eventInfo.streamTags()
-                except Exception as err:
-                        self.msg.error("Exception occured while reading event/trigger info: %s", err)
-                        return StatusCode.Recoverable
-
-                # Retrieve the physics stream names from the trigger info
-                streams = []
-                for tag in streamTags:
-                        
-                        ## Added 08/03/15 - sjiggins - Wanted to see if events had physics stream tag or was from random trigger
-                        if tag.name():
-                                self.msg.debug("Event %d/%d has the corresponding streamTags: %s", self.run, self.event, tag.type())
-                        ##################################################################################
-                        if tag.type() == 'express' and tag.name():
-                                streams += [tag.type()+'_'+tag.name()]
-
-                        if tag.type() == 'physics' and tag.name():
-                                streams += [tag.type()+'_'+tag.name()]
-
-                # Add special streams to the list Public
-                """
-                try:
-                        for stream in streams:
-                                if stream in self.public:
-                                        ready4physics = ISInfoAny()
-                                        self.dict.getValue('RunParams.Ready4Physics', ready4physics)
-                                        print("Ready for physics: %s " % ready4physics.get())
-                                        runparams = ISObject(self.partition, 'RunParams.RunParams','RunParams')
-                                        runparams.checkout()
-                                        physicsReady = ISObject(self.partition, 'RunParams.Ready4Physics','Ready4PhysicsInfo')
-                                        physicsReady.checkout()
-                                        print("Ready for physics: %r" % (physicsReady.ready4physics))
-                                        #if ready4physics.get() and physicsReady.ready4physics and runparams.T0_project_tag in self.projecttags:
-                                        if physicsReady.ready4physics and runparams.T0_project_tag in self.projecttags:
-                                                streams += ['Public']
-                                        else:
-                                                self.msg.debug("RunParams.Ready4Physics is not set, run number is not set, or T0_project_tag is not set to any of %s", ", ".join(self.projecttags))
-                                                break
-                except Exception as err:
-                        self.msg.error("Exception occured while reading RunParams.Ready4Physics: %s", err)
-                """
-                # Randomize list of streams
-                random.shuffle(streams)
-                self.msg.debug("Event %d/%d has event display stream tags: %s", self.run, self.event, ", ".join(streams))
-
-                ## for beam splash, give priority to MinBias
-                #if 'physics_MinBias' in streams:
-                #       streams = ['physics_MinBias']
-                #       self.msg.debug("Modified stream tag: %s", ", ".join(streams))
-
-                # Start from the beginning and send the event to the first stream that passes our directory checks
-                self.directory = ''
-                for self.stream in streams:
-                        self.directory = "%s/%s" % (self.output, self.stream)
-                        if os.access(self.directory, os.F_OK):
-                                if os.path.isdir(self.directory) and os.access(self.directory, os.W_OK):
-                                        self.msg.debug("Going to write file to existing directory: %s", self.directory)
-                                        if os.stat(self.directory).st_gid != self.zpgid:
-                                                self.msg.debug("Setting group to 'zp' for directory: %s", self.directory)
-                                                os.chown(self.directory, -1, self.zpgid)
-                                        break
-                                else:
-                                        self.msg.warning("Directory \'%s\' is not usable, trying next alternative", self.directory)
-                                        self.directory = ''
-                        else:
-                                try:
-                                        os.mkdir(self.directory)
-                                        os.chmod(self.directory, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH)
-                                        os.chown(self.directory, -1, self.zpgid)
-                                        self.msg.info("Created output directory \'%s\' for stream \'%s\'", self.directory, self.stream)
-                                        break
-                                except OSError as err:
-                                        self.msg.warning("Failed to create output directory \'%s\' for stream \'%s\': %s", (self.directory, self.stream, err.strerror))
-                                        self.directory = ''
-
-                # Check if a suitable directory was found
-                if self.directory:
-                        self.msg.debug("Event %d/%d will be streamed to: %s", self.run, self.event, self.stream)
-                        self.msg.debug("Directory: %s", self.directory)
-                else:
-                        # This event is hopelessly lost, send StatusCode.Recoverable in an attempt to abort.
-                        # But if Athena chooses to ignore that, set the output to the "Unknown" trashcan stream.
-                        self.stream = 'Unknown'
-                        self.directory = "%s/.Unknown" % self.output
-                try:
-                        # Set output stream for JiveXML event streaming (file and server)
-                        print('stream name and file name prefix:',"%s" % self.stream, "%s/JiveXML" % self.directory)
-                        self.StreamToServerTool.getProperty('StreamName').setValue("%s" % self.stream)
-                
-                        print('before changing my test in online svc:',self.StreamToFileTool.getProperty("MyTest").value())
-                        self.StreamToFileTool.getProperty('FileNamePrefix').setValue("%s/JiveXML" % self.directory)
-                        self.StreamToFileTool.getProperty("MyTest").setValue("updatedinOsvc")
-                        print(self.StreamToFileTool.getProperty("MyTest").value())
-                        
-                        self.msg.debug("Directory in try: %s", self.directory)
-                except Exception as err:
-                        self.msg.error("Exception occured while setting job options: %s", err)
-                        return StatusCode.Failure
-
-                if not self.directory:
-                        return StatusCode.Recoverable
-
-        def endEvent(self):
-                # VP1 copied its ESD file of the previous event to the destination directory.
-                # So we set the directory of the current event in endEvent to pass it to the next event.
-                if self.VP1EventProducer:
-                        self.VP1EventProducer.getProperty('DestinationDirectory').setValue(self.directory)
-                        #print(getattr(self.VP1EventProducer,'DestinationDirectory'))
-                        #setattr(self.VP1EventProducer, 'DestinationDirectory', self.directory)
-                        #print(getattr(self.VP1EventProducer,'DestinationDirectory'))
-
-                # Prune events and make index file for atlas-live.cern.ch
-                if self.directory:
-                        # If VP1 event producer is missing, skip the pair check to make cleanup/sync work
-                        if self.VP1EventProducer:
-                                EventUtils.cleanDirectory(self.msg, self.directory, self.maxevents, checkpair=True)
-                        else:
-                                EventUtils.cleanDirectory(self.msg, self.directory, self.maxevents, checkpair=False)
-
-                        ## for beam splashes, disable prepareFilesForTransfer() in EventUtils.py
-                        ## Activate these lines to zip and transfer every JiveXML file.
-                        #event = "%05d" % int(self.event)
-                        #EventUtils.zipXMLFile(self.msg, self.directory, f'JiveXML_{self.run}_{event}.xml')
-
-                # And cleanup the variables
-                self.run = 0
-                self.event = 0
-                self.stream = ''
-                self.directory = ''
-
-        def handle(self, incident):
-                self.msg.verbose("Received incident %s from %s" % (incident.type(), incident.source()))
-
-                # Event and trigger info present, decide stream
-                if incident.type() == 'BeginEvent' and incident.source() == 'BeginIncFiringAlg':
-                        self.beginEvent()
-
-                # VP1 writes its file at EndEvent, so we can do cleanup at StoreCleared
-                if incident.type() == 'StoreCleared' and incident.source() == 'StoreGateSvc':
-                        self.endEvent()
-
diff --git a/graphics/EventDisplaysOnline/src/IOnlineEventDisplaysSvc.cxx b/graphics/EventDisplaysOnline/src/IOnlineEventDisplaysSvc.cxx
new file mode 100644
index 000000000000..8327bb0c6fd3
--- /dev/null
+++ b/graphics/EventDisplaysOnline/src/IOnlineEventDisplaysSvc.cxx
@@ -0,0 +1,7 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+#include "EventDisplaysOnline/IOnlineEventDisplaysSvc.h"
+
+IOnlineEventDisplaysSvc::~IOnlineEventDisplaysSvc()
+{}
diff --git a/graphics/EventDisplaysOnline/src/OnlineEventDisplaysSvc.cxx b/graphics/EventDisplaysOnline/src/OnlineEventDisplaysSvc.cxx
new file mode 100644
index 000000000000..3a6145d53a77
--- /dev/null
+++ b/graphics/EventDisplaysOnline/src/OnlineEventDisplaysSvc.cxx
@@ -0,0 +1,208 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+#include "EventDisplaysOnline/OnlineEventDisplaysSvc.h"
+#include "RootUtils/PyAthenaGILStateEnsure.h"
+#include "Gaudi/Property.h"
+#include "GaudiKernel/IIncidentSvc.h"
+#include "GaudiKernel/Incident.h"
+#include "GaudiKernel/MsgStream.h"
+#include "xAODEventInfo/EventInfo.h"
+#include <cstdlib>  // For std::rand() and std::srand()
+#include "Python.h"
+
+OnlineEventDisplaysSvc::OnlineEventDisplaysSvc( const std::string& name, 
+			  ISvcLocator* pSvcLocator ) : 
+  AthService(name, pSvcLocator){}
+
+OnlineEventDisplaysSvc::~OnlineEventDisplaysSvc(){}
+
+void OnlineEventDisplaysSvc::beginEvent(){
+
+  SG::ReadHandle<xAOD::EventInfo> evt (m_evt);
+  if (!evt.isValid()) {
+    ATH_MSG_FATAL("Could not find event info");
+  }
+  std::vector<std::string> streams;
+
+  ATH_MSG_INFO("You have requested to only output JiveXML and ESD files when a trigger in the following streams was fired: ");
+  for (std::string stream : m_streamsWanted){
+    ATH_MSG_INFO(stream);
+  }
+  
+  //Check what trigger streams were fired, if in list of desired
+  //streams to be reconstructed pick one randomly 
+  for (const xAOD::EventInfo::StreamTag& tag : evt->streamTags()){
+    ATH_MSG_INFO ("A trigger in stream " << tag.type() << "_" << tag.name() << " was fired in this event.");
+    std::string stream_fullname = tag.type() + "_" + tag.name();
+
+    if (m_streamsWanted.empty()) {
+      ATH_MSG_INFO ("You have not requested any specific streams, going to allow all streams");
+      streams.emplace_back(stream_fullname);
+    }
+    
+    else{
+      //If the stream is in the list of streams requested, add it
+      if(std::find(m_streamsWanted.begin(), m_streamsWanted.end(), tag.name()) != m_streamsWanted.end()){
+	streams.emplace_back(stream_fullname);
+      }
+
+      bool isPublicStream = std::find(m_publicStreams.begin(), m_publicStreams.end(), tag.name()) != m_publicStreams.end();
+      if(m_sendToPublicStream && isPublicStream){
+	streams.emplace_back("Public");
+      }
+      
+    }
+  }
+
+  for (std::string stream : streams){
+    ATH_MSG_INFO("streams where a trigger fired and in your desired streams list: " << stream);
+  }
+
+  std::random_shuffle(streams.begin(), streams.end());
+
+  //Pick the first stream as the output directory
+  if(!m_outputStreamDir.empty()){
+    m_outputStreamDir = streams[0];
+  }
+  else{
+    ATH_MSG_WARNING("Cannot find a stream adding to .Unknown directory");
+    m_outputStreamDir = ".Unkown";
+  }
+  
+  gid_t zpgid = setOwnershipToZpGrpOrDefault();
+
+  m_entireOutputStr = m_outputDirectory + "/" + m_outputStreamDir;
+  createWriteableDir(m_outputDirectory, zpgid);
+  createWriteableDir(m_entireOutputStr, zpgid);
+  
+  std::string FileNamePrefix = m_entireOutputStr + "/JiveXML";
+  m_FileNamePrefix = FileNamePrefix;
+  ATH_MSG_INFO("in begin: " << m_entireOutputStr);
+}
+
+void OnlineEventDisplaysSvc::endEvent(){
+  //set vp1 dir
+  // if don't do vp1 set checkPair to false
+  ATH_MSG_INFO("in end: " << m_entireOutputStr);
+  
+  RootUtils::PyGILStateEnsure ensure;
+  PyObject* pCheckPair = PyBool_FromLong(0); // Use 0 for False
+  PyObject* pMaxEvents = PyLong_FromLong(m_maxEvents);
+  const char* cString = m_entireOutputStr.c_str();
+  PyObject* pDirectory = PyUnicode_FromString(cString);
+
+  PyObject* pArgs = PyTuple_Pack(3, pDirectory, pMaxEvents, pCheckPair);
+  
+  PyObject* pModule = PyImport_ImportModule("EventDisplaysOnline.EventUtils");
+  if ( pModule ) {
+    PyObject* cleanDirectory = PyObject_GetAttrString(pModule, "cleanDirectory");
+    if ( cleanDirectory ) {
+      ATH_MSG_INFO("About to clean the ED directories");
+      PyObject_CallObject(cleanDirectory, pArgs);
+    }
+    Py_DECREF(cleanDirectory);
+  }
+  else {
+    ATH_MSG_WARNING("Could not import EventDisplaysOnline.EventUtils.cleanDirectory");
+  }
+  Py_DECREF(pModule);
+  Py_DECREF(pArgs);
+  Py_DECREF(pCheckPair);
+  Py_DECREF(pMaxEvents);
+  Py_DECREF(pDirectory);
+}
+
+std::string OnlineEventDisplaysSvc::getFileNamePrefix(){
+  return m_FileNamePrefix;
+}
+
+std::string OnlineEventDisplaysSvc::getEntireOutputStr(){
+  return m_entireOutputStr;
+}
+
+std::string OnlineEventDisplaysSvc::getStreamName(){
+  return m_outputStreamDir;
+}
+void OnlineEventDisplaysSvc::createWriteableDir(std::string directory, gid_t zpgid){
+
+  const char* char_dir = directory.c_str();
+  
+  if (access(char_dir, F_OK) == 0) {
+    struct stat directoryStat;
+    if (stat(char_dir, &directoryStat) == 0 && S_ISDIR(directoryStat.st_mode) &&
+	access(char_dir, W_OK) == 0) {
+      ATH_MSG_INFO("Going to write file to existing directory: " << directory);
+      if (directoryStat.st_gid != zpgid) {
+	ATH_MSG_INFO("Setting group to 'zp' for directory: " << directory);
+	chown(char_dir, -1, zpgid);
+      }
+    } else {
+      ATH_MSG_INFO("Directory '" << directory << "' is not usable, trying next alternative");
+    }
+  } else {
+    try {
+      mkdir(char_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+      chown(char_dir, -1, zpgid);
+      ATH_MSG_INFO("Created output directory " << directory);
+    } catch (const std::system_error& err) {
+      std::cerr << "Failed to create output directory " << directory
+		<< err.what() << std::endl;
+    }
+  }
+}
+
+gid_t OnlineEventDisplaysSvc::setOwnershipToZpGrpOrDefault(){
+  gid_t zpgid;
+  struct group* zp_group = getgrnam("zp");
+  if (zp_group != nullptr) {
+    zpgid = zp_group->gr_gid;
+  } else {
+    ATH_MSG_INFO("If running on private machine, zp group might not exist. Just set to the likely value 1307.");
+    zpgid = 1307;
+  }
+  return zpgid;
+}
+
+StatusCode OnlineEventDisplaysSvc::initialize(){
+
+  ATH_MSG_INFO("Initializing " << name());
+  IIncidentSvc* incSvc = nullptr;
+  ATH_CHECK( service("IncidentSvc",incSvc) );
+
+  incSvc->addListener( this, "BeginEvent");
+  incSvc->addListener( this, "StoreCleared");
+
+  ATH_CHECK( m_evt.initialize() );
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode OnlineEventDisplaysSvc::finalize(){
+
+  ATH_MSG_INFO("Finalizing " << name());
+  return StatusCode::SUCCESS;
+}
+
+void OnlineEventDisplaysSvc::handle( const Incident& incident ){
+  ATH_MSG_INFO("Received incident " << incident.type() << " from " << incident.source() );
+  if ( incident.type() == IncidentType::BeginEvent && incident.source() == "BeginIncFiringAlg" ){
+    beginEvent();
+    
+  }
+  if ( incident.type() == "StoreCleared" && incident.source() == "StoreGateSvc" ){
+    endEvent();
+  }
+}
+
+StatusCode OnlineEventDisplaysSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) 
+{
+  if ( IOnlineEventDisplaysSvc::interfaceID().versionMatch(riid) ) {
+    *ppvInterface = dynamic_cast<IOnlineEventDisplaysSvc*>(this);
+  } else {
+    // Interface is not directly available : try out a base class
+    return AthService::queryInterface(riid, ppvInterface);
+  }
+  addRef();
+  return StatusCode::SUCCESS;
+}
diff --git a/graphics/EventDisplaysOnline/src/components/EventDisplaysOnline_entries.cxx b/graphics/EventDisplaysOnline/src/components/EventDisplaysOnline_entries.cxx
new file mode 100644
index 000000000000..7f4065bff60f
--- /dev/null
+++ b/graphics/EventDisplaysOnline/src/components/EventDisplaysOnline_entries.cxx
@@ -0,0 +1,3 @@
+#include "EventDisplaysOnline/OnlineEventDisplaysSvc.h"
+
+DECLARE_COMPONENT( OnlineEventDisplaysSvc )
diff --git a/graphics/JiveXML/CMakeLists.txt b/graphics/JiveXML/CMakeLists.txt
index 81c299eb06a7..b2129b3ce052 100644
--- a/graphics/JiveXML/CMakeLists.txt
+++ b/graphics/JiveXML/CMakeLists.txt
@@ -16,20 +16,20 @@ if ( RPC_FOUND )
    JiveXML/*.h src/*.cxx
    PUBLIC_HEADERS JiveXML
    INCLUDE_DIRS ${RPC_INCLUDE_DIRS}
-   LINK_LIBRARIES ${RPC_LIBRARIES} AthenaBaseComps CxxUtils GaudiKernel
+   LINK_LIBRARIES ${RPC_LIBRARIES} AthenaBaseComps CxxUtils GaudiKernel EventDisplaysOnlineLib
    PRIVATE_LINK_LIBRARIES xAODEventInfo )
 else()
   atlas_add_library( JiveXMLLib
    JiveXML/*.h src/*.cxx
    PUBLIC_HEADERS JiveXML
    INCLUDE_DIRS ${RPC_INCLUDE_DIRS}
-   LINK_LIBRARIES AthenaBaseComps CxxUtils GaudiKernel
+   LINK_LIBRARIES AthenaBaseComps CxxUtils GaudiKernel EventDisplaysOnlineLib
    PRIVATE_LINK_LIBRARIES xAODEventInfo ) 
 endif() 
 
 atlas_add_component( JiveXML
                      src/components/*.cxx
-                     LINK_LIBRARIES JiveXMLLib )
+                     LINK_LIBRARIES JiveXMLLib)
 
 # Install files from the package:
 atlas_install_joboptions( share/*.py )
diff --git a/graphics/JiveXML/JiveXML/AlgoJiveXML.h b/graphics/JiveXML/JiveXML/AlgoJiveXML.h
index d73c8dd54d5a..9416c0f6becf 100755
--- a/graphics/JiveXML/JiveXML/AlgoJiveXML.h
+++ b/graphics/JiveXML/JiveXML/AlgoJiveXML.h
@@ -42,14 +42,6 @@ namespace JiveXML {
       StatusCode finalize();
     private:
 
-      StatusCode chooseStream(const std::vector< xAOD::EventInfo::StreamTag >);
-
-      //Configurable properties
-      Gaudi::Property<bool> m_wantPublicStreams {this, "WantPublicStreams", false, "If running online, is the Public stream wanted."};
-      Gaudi::Property<bool> m_wantCalibrationStreams {this, "WantCalibrationStreams", false, "If running online, are the calibration streams wanted."};
-      Gaudi::Property<bool> m_wantMonitoringStreams {this, "WantMonitoringStreams", false, "If running online, are the monitoring streams wanted."};
-      Gaudi::Property<bool> m_wantPhysicsStreams {this, "WantPhysicsStreams", true, "If running online, are the physics streams wanted."};
-
       Gaudi::Property<std::string> m_AtlasRelease {this, "AtlasRelease", "unknown", "The Athena release number"};
       Gaudi::Property<std::vector<std::string>> m_dataTypes {this, "DataTypes", {}, "List of data retriever names to be run"}; 
       Gaudi::Property<bool> m_writeToFile {this, "WriteToFile", true, "Whether XML files shall be produced"};
diff --git a/graphics/JiveXML/JiveXML/StreamToFileTool.h b/graphics/JiveXML/JiveXML/StreamToFileTool.h
index 868a179cc2ff..a4ed1c52ed4c 100644
--- a/graphics/JiveXML/JiveXML/StreamToFileTool.h
+++ b/graphics/JiveXML/JiveXML/StreamToFileTool.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef JIVEXML__STREAMTOFILETOOL_H
@@ -8,6 +8,8 @@
 //IAlgTool interface
 #include "JiveXML/IStreamTool.h"
 #include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "EventDisplaysOnline/IOnlineEventDisplaysSvc.h"
 
 namespace JiveXML {
   
@@ -35,21 +37,24 @@ namespace JiveXML {
 
     private:
 
-      Gaudi::Property<std::string> m_mytest {this, "MyTest", "fail", "My test"};
-      /** Prefix put in front of file name */
-      std::string m_FileNamePrefix;
+    ServiceHandle<IOnlineEventDisplaysSvc> m_onlineEDsvc{this, "OnlineEventDisplaysSvc", "Online Event Displays Service"};
+
+    Gaudi::Property<bool> m_isOnline {this, "IsOnline", false, "If running at point 1"};
+
+    /** Prefix put in front of JiveXML file name */
+    std::string m_FileNamePrefix;
       
-      /** Suffix put at the end of the file name (including type)*/
-      std::string m_FileNameSuffix;
+    /** Suffix put at the end of the file name (including type)*/
+    std::string m_FileNameSuffix;
       
-      /** Generate a file name */
-      std::string MakeFileName( const unsigned long EventNumber, const unsigned int RunNumber ) const;
+    /** Generate a file name */
+    std::string MakeFileName( const unsigned long EventNumber, const unsigned int RunNumber ) const;
       
-      /** Creates a new output stream to write XML to */
-      StatusCode NewFile( const unsigned long EventNumber, const unsigned  int RunNumber, std::ofstream *& outFile ) const ;
+    /** Creates a new output stream to write XML to */
+    StatusCode NewFile( const unsigned long EventNumber, const unsigned  int RunNumber, std::ofstream *& outFile ) const ;
 
-      /** Closes output stream */
-      StatusCode CloseFile( std::ofstream *& outFile ) const ;
+    /** Closes output stream */
+    StatusCode CloseFile( std::ofstream *& outFile ) const ;
       
   };
 
diff --git a/graphics/JiveXML/JiveXML/StreamToServerTool.h b/graphics/JiveXML/JiveXML/StreamToServerTool.h
index 88525d7d8fcf..588d584989af 100644
--- a/graphics/JiveXML/JiveXML/StreamToServerTool.h
+++ b/graphics/JiveXML/JiveXML/StreamToServerTool.h
@@ -11,6 +11,7 @@
 #include "JiveXML/EventStream.h"
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "GaudiKernel/ServiceHandle.h"
+#include "EventDisplaysOnline/IOnlineEventDisplaysSvc.h"
 
 namespace JiveXML {
   
@@ -25,27 +26,27 @@ namespace JiveXML {
 
     public:
       
-      /// Constructor
-      StreamToServerTool( const std::string&, const std::string&, const IInterface*);
+    /// Constructor
+    StreamToServerTool( const std::string&, const std::string&, const IInterface*);
 
-      /// Initialize
-      virtual StatusCode initialize();
+    /// Initialize
+    virtual StatusCode initialize();
       
-      /// Finalize
-      virtual StatusCode finalize();
+    /// Finalize
+    virtual StatusCode finalize();
 
-      /// Stream one event
-      virtual StatusCode StreamEvent( const unsigned long EventNumber, const unsigned int RunNumber, const std::ostringstream* const EventBuffer ) ;
+    /// Stream one event
+    virtual StatusCode StreamEvent( const unsigned long EventNumber, const unsigned int RunNumber, const std::ostringstream* const EventBuffer ) ;
 
     protected:
 
       /// Handle to the server that this tools shall stream events to
-      ServiceHandle<IServerSvc> m_ServerSvc;
-
+    ServiceHandle<IServerSvc> m_ServerSvc;
+    ServiceHandle<IOnlineEventDisplaysSvc> m_onlineEDsvc{this, "OnlineEventDisplaysSvc", "Online Event Displays Service"};
     private:
 
-      /** Stream name under which these events shall appear */
-      std::string m_StreamName;
+    /** Stream name under which these events shall appear */
+    std::string m_StreamName;
 
   };
 
diff --git a/graphics/JiveXML/python/JiveXMLConfig.py b/graphics/JiveXML/python/JiveXMLConfig.py
index 94ac8f8751b7..006420fe887e 100644
--- a/graphics/JiveXML/python/JiveXMLConfig.py
+++ b/graphics/JiveXML/python/JiveXMLConfig.py
@@ -415,8 +415,6 @@ def AlgoJiveXMLCfg(flags, name="AlgoJiveXML", **kwargs):
     # JiveXML_RecEx_config.py
     # JiveXML_jobOptionBase.py
     result = ComponentAccumulator()
-    stft=kwargs.get('StreamToFileTool')
-    print('StreamToFileTool',type(stft), getattr(stft,'MyTest'))
     kwargs.setdefault("AtlasRelease", getATLASVersion())
     kwargs.setdefault("WriteToFile", True)
     kwargs.setdefault("OnlineMode", False)
diff --git a/graphics/JiveXML/src/AlgoJiveXML.cxx b/graphics/JiveXML/src/AlgoJiveXML.cxx
index 3ec5de498ca2..b14afd2a1b78 100755
--- a/graphics/JiveXML/src/AlgoJiveXML.cxx
+++ b/graphics/JiveXML/src/AlgoJiveXML.cxx
@@ -19,10 +19,7 @@
 namespace JiveXML{
 
   AlgoJiveXML::AlgoJiveXML(const std::string& name, ISvcLocator* pSvcLocator) :
-    AthAlgorithm(name, pSvcLocator) {
-
-    
-  }
+    AthAlgorithm(name, pSvcLocator) {}
 
   /**
    * Initialize - called once in the beginning
@@ -92,8 +89,6 @@ namespace JiveXML{
       ATH_CHECK(m_StreamToFileTool.retrieve());
    }
 
-  
-
     /**
      * Get the IDataRetrievers requested in the m_dataTypes list from the toolSvc 
      * and store them in the ToolHandleArray
@@ -123,10 +118,6 @@ namespace JiveXML{
     ATH_MSG_INFO("Retrieving data from " << m_DataRetrievers.size() << " tools" );
 
     ATH_MSG_INFO("List property settings: ");
-    ATH_MSG_INFO("WantPublicStreams: " << m_wantPublicStreams);
-    ATH_MSG_INFO("WantCalibrationStreams: " << m_wantCalibrationStreams);
-    ATH_MSG_INFO("WantMonitoringStreams: " << m_wantMonitoringStreams);
-    ATH_MSG_INFO("WantPhysicsStreams: " << m_wantPhysicsStreams);
     ATH_MSG_INFO("AtlasRelease: " << m_AtlasRelease);
     ATH_MSG_INFO("DataTypes: " << m_dataTypes );
     ATH_MSG_INFO("WriteToFile: " << m_writeToFile);
@@ -329,27 +320,4 @@ namespace JiveXML{
     
     return StatusCode::SUCCESS;
   }
-
-  StatusCode AlgoJiveXML::chooseStream(const std::vector< xAOD::EventInfo::StreamTag > evtStreamTags){
-    std::vector<std::string> wantedStreamTypes;
-    if (m_wantPublicStreams){
-      wantedStreamTypes.emplace_back("Public");
-    }
-    if (m_wantCalibrationStreams){
-      wantedStreamTypes.emplace_back("calibration");
-    }
-    if (m_wantMonitoringStreams){
-      wantedStreamTypes.emplace_back("monitoring");
-    }
-    if (m_wantPhysicsStreams){
-      wantedStreamTypes.emplace_back("physics");
-    }
-      std::vector< xAOD::EventInfo::StreamTag > goodStreams;
-    for (const auto& evtStreamTag : evtStreamTags) {
-      ATH_MSG_INFO( "Stream Tag in function: " << evtStreamTag.type() << "_" << evtStreamTag.name());
-      // if evtStreamTag.type() is in wantedStreamTypes add to goodStreams
-    }
-    //randomize goodStreams and return first value as choosen Stream
-    return StatusCode::SUCCESS;
-  }
 } //namespace
diff --git a/graphics/JiveXML/src/StreamToFileTool.cxx b/graphics/JiveXML/src/StreamToFileTool.cxx
index 9c419cf0f367..a409436aee3a 100644
--- a/graphics/JiveXML/src/StreamToFileTool.cxx
+++ b/graphics/JiveXML/src/StreamToFileTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #include <JiveXML/StreamToFileTool.h>
@@ -10,13 +10,13 @@
 namespace JiveXML {
 
   /**
-   * Constructor 
+   * Constructor
    * - setup message service
    * - initialize properties
    */
   StreamToFileTool::StreamToFileTool( const std::string& type , const std::string& name, const IInterface* p):
     AthAlgTool(type,name,p){
-    
+
     //Provide interface
     declareInterface<IStreamTool>(this);
 
@@ -24,7 +24,7 @@ namespace JiveXML {
     declareProperty("FileNamePrefix", m_FileNamePrefix = "JiveXML");
     /// The file name suffix
     declareProperty("FileNameSuffix", m_FileNameSuffix = ".xml");
-    
+
   }
 
   /**
@@ -32,6 +32,12 @@ namespace JiveXML {
    */
   StatusCode StreamToFileTool::initialize(){
     return StatusCode::SUCCESS;
+    if(m_isOnline){
+      if( m_onlineEDsvc.retrieve().isFailure()){
+	ATH_MSG_ERROR("Could not locate the online event displays service");
+	return StatusCode::FAILURE;
+      }
+    }
   }
 
   /**
@@ -47,26 +53,26 @@ namespace JiveXML {
    * @param RunNumber the run number
    * @param EventBuffer the string holding the complete event
    */
-   StatusCode StreamToFileTool::StreamEvent( const unsigned long EventNumber, const unsigned int RunNumber, const std::ostringstream* EventBuffer ) { 
-     if (msgLvl(MSG::INFO)) msg(MSG::INFO) << " m_FileNamePrefix: " << m_FileNamePrefix << " my test: " << m_mytest << endmsg;
+   StatusCode StreamToFileTool::StreamEvent( const unsigned long EventNumber, const unsigned int RunNumber, const std::ostringstream* EventBuffer ) {
+     if(m_isOnline){
+       m_FileNamePrefix = m_onlineEDsvc->getFileNamePrefix();
+     }
      /// Get a pointer to a new file
      std::ofstream* outFile;
      StatusCode sc = NewFile(EventNumber,RunNumber,outFile);
      if (sc.isFailure()){
-        if (msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Could not open file for event " 
-           << EventNumber << " from run " << RunNumber << endmsg;
+       ATH_MSG_WARNING("Could not open file for event " << EventNumber << " from run " << RunNumber);
        return sc;
      }
-     /// Stream this event into the file 
+     /// Stream this event into the file
      (*outFile) << EventBuffer->str();
      outFile->flush();
      /// Check wether we could write the event
      if (!outFile->good()){
-       if (msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Could not write event " 
-           << EventNumber << " from run " << RunNumber << endmsg;
+       ATH_MSG_WARNING("Could not open file for event " << EventNumber << " from run " << RunNumber);
        return StatusCode::FAILURE;
      }
-     
+
      /// Finally close the file
      sc = CloseFile(outFile);
      return sc;
@@ -78,24 +84,24 @@ namespace JiveXML {
    * @param EventNumber the event number
    * @param RunNumber the run number
    */
-   std::string StreamToFileTool::MakeFileName( const unsigned long EventNumber, const unsigned int RunNumber) const {
+   std::string StreamToFileTool::MakeFileName(const unsigned long EventNumber, const unsigned int RunNumber) const {
 
      //Generate a the return string with file prefix
      std::ostringstream name;
-     
+
      //Assemble file name
      name << m_FileNamePrefix << std::setfill('0');
      name << "_" << std::setw(5) << RunNumber;
      name << "_" << std::setw(5) << EventNumber;
-     name << m_FileNameSuffix; 
+     name << m_FileNameSuffix;
      return name.str();
    }
 
-   /** 
+   /**
     * Open a new file
     */
    StatusCode StreamToFileTool::NewFile( const unsigned long EventNumber, const unsigned int RunNumber, std::ofstream *& outputFile) const {
-      
+
       // Generate the file name
       std::string filename = MakeFileName(EventNumber,RunNumber);
 
@@ -104,24 +110,24 @@ namespace JiveXML {
 
       // check if it worked
       if ( !(outputFile->good()) ){
-        if (msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Unable to create output file with name " << filename << endmsg;
-        return StatusCode::FAILURE;
+	ATH_MSG_WARNING("Unable to create output file with name " << filename);
+	return StatusCode::FAILURE;
       }
 
       return StatusCode::SUCCESS;
     }
 
    /**
-    * Close the file 
-    */   
+    * Close the file
+    */
    StatusCode StreamToFileTool::CloseFile( std::ofstream *& outputFile ) const {
 
     //Try to close the file
     outputFile->close();
-    
+
     //See if it worked
     if (!outputFile->good()){
-      if (msgLvl(MSG::WARNING)) msg(MSG::WARNING)  << "Unable to close file" << endmsg;
+      ATH_MSG_WARNING("Unable to close file");
     }
 
     //In any case delete object
diff --git a/graphics/JiveXML/src/StreamToServerTool.cxx b/graphics/JiveXML/src/StreamToServerTool.cxx
index 8917a9358b40..40ebbd76b1e7 100644
--- a/graphics/JiveXML/src/StreamToServerTool.cxx
+++ b/graphics/JiveXML/src/StreamToServerTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #include <JiveXML/StreamToServerTool.h>
@@ -29,12 +29,17 @@ namespace JiveXML {
    */
   StatusCode StreamToServerTool::initialize(){
 
-    //Make sure we can get hold of the server
+    //Make sure we can get hold of the server and the online event displays service
     if (m_ServerSvc.retrieve().isFailure()){
-      if (msgLvl(MSG::ERROR)) msg(MSG::ERROR) << "Unable to initialize server service with name " << m_ServerSvc.name() << endmsg;
+      ATH_MSG_ERROR("Unable to initialize server service with name " << m_ServerSvc.name());
       return StatusCode::FAILURE;
     }
 
+    if( m_onlineEDsvc.retrieve().isFailure()){
+      ATH_MSG_ERROR("Could not locate the online event displays service");
+      return StatusCode::FAILURE;
+    }
+    
     return StatusCode::SUCCESS;
   }
 
@@ -54,10 +59,11 @@ namespace JiveXML {
    StatusCode StreamToServerTool::StreamEvent( const unsigned long EventNumber, 
 					       const unsigned int RunNumber, 
 					       const std::ostringstream* const EventBuffer ) { 
-     if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Streaming event Nr. " << EventNumber 
-                         << " from run Nr. " << RunNumber
-                         << " to stream " << m_StreamName
-                         << " on " << m_ServerSvc.name() << " service" << endmsg;
+     m_StreamName = m_onlineEDsvc->getStreamName();
+     ATH_MSG_VERBOSE("Streaming event Number " << EventNumber 
+		     << " from run Number " << RunNumber
+		     << " to stream " << m_StreamName
+		     << " on " << m_ServerSvc.name() << " service");
 
      /// Create an EventStreamID for this event
      EventStreamID evtStreamID(EventNumber,RunNumber,m_StreamName);
diff --git a/graphics/VP1/VP1AlgsEventProd/CMakeLists.txt b/graphics/VP1/VP1AlgsEventProd/CMakeLists.txt
index a85ce8aeb703..32098e04f519 100644
--- a/graphics/VP1/VP1AlgsEventProd/CMakeLists.txt
+++ b/graphics/VP1/VP1AlgsEventProd/CMakeLists.txt
@@ -7,4 +7,4 @@ atlas_subdir( VP1AlgsEventProd )
 atlas_add_component( VP1AlgsEventProd
    VP1AlgsEventProd/*.h src/*.cxx src/components/*.cxx
    LINK_LIBRARIES AthenaBaseComps GaudiKernel PathResolver
-   VP1UtilsBase )
+   VP1UtilsBase EventDisplaysOnlineLib)
diff --git a/graphics/VP1/VP1AlgsEventProd/VP1AlgsEventProd/VP1EventProd.h b/graphics/VP1/VP1AlgsEventProd/VP1AlgsEventProd/VP1EventProd.h
index 49ac9fba42c1..3f352e2b975b 100755
--- a/graphics/VP1/VP1AlgsEventProd/VP1AlgsEventProd/VP1EventProd.h
+++ b/graphics/VP1/VP1AlgsEventProd/VP1AlgsEventProd/VP1EventProd.h
@@ -24,6 +24,9 @@
 
 #include "AthenaBaseComps/AthAlgorithm.h"
 #include "GaudiKernel/IIncidentListener.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "EventDisplaysOnline/IOnlineEventDisplaysSvc.h"
+
 #include <string>
 
 class VP1EventProd: public AthAlgorithm,
@@ -40,6 +43,10 @@ class VP1EventProd: public AthAlgorithm,
   void handle(const Incident& inc);
 
  private:
+  
+  Gaudi::Property<bool> m_isOnline {this, "IsOnline", false, "If running at point 1"};
+  ServiceHandle<IOnlineEventDisplaysSvc> m_onlineEDsvc{this, "OnlineEventDisplaysSvc", "Online Event Displays Service"};
+  
   // run/event number to be used in the vp1 event file name
   unsigned long m_runNumber;
   unsigned long long  m_eventNumber;
diff --git a/graphics/VP1/VP1AlgsEventProd/src/VP1EventProd.cxx b/graphics/VP1/VP1AlgsEventProd/src/VP1EventProd.cxx
index 37fa9467b57c..761b77f6c1b5 100755
--- a/graphics/VP1/VP1AlgsEventProd/src/VP1EventProd.cxx
+++ b/graphics/VP1/VP1AlgsEventProd/src/VP1EventProd.cxx
@@ -61,6 +61,12 @@ StatusCode VP1EventProd::initialize()
   else
     incsvc->addListener(this, "BeginEvent", 0);
 
+  if(m_isOnline){
+    if( m_onlineEDsvc.retrieve().isFailure()){
+      ATH_MSG_ERROR("Could not locate the online event displays service");
+      return StatusCode::FAILURE;
+    }
+  }
   return result;
 }
 
@@ -75,6 +81,11 @@ StatusCode VP1EventProd::finalize()
 {
   ATH_MSG_INFO("in finalize() ");
 
+  if(m_isOnline){
+    m_destinationDir = m_onlineEDsvc->getEntireOutputStr();
+  }
+
+  ATH_MSG_INFO("VP1ALG m_destinationDir " << m_destinationDir);
   // handle the output of the last event
   if(m_nEvent) {
 
@@ -87,31 +98,31 @@ StatusCode VP1EventProd::finalize()
 
     std::string inputFileName = ostri.str();
     ATH_MSG_DEBUG("copying the input file: '"<< inputFileName << "'...");
-    
+    ATH_MSG_DEBUG("VP1 alg event number: " << m_eventNumber);
     try {
 
-        /* clean the output directory if m_maxProducedFiles == 0
-         * or keep up to 'm_maxProducedFiles' output files
-         */
-        VP1FileUtilities fileUtil(".", m_maxProducedFiles, m_destinationDir, m_createDestinationDir, m_removeTempInputFiles); // inputDir, fileLimit, outputDir, forceMakeOutputDir, removeInputFile
+	/* clean the output directory if m_maxProducedFiles == 0
+	 * or keep up to 'm_maxProducedFiles' output files
+	 */
+	VP1FileUtilities fileUtil(".", m_maxProducedFiles, m_destinationDir, m_createDestinationDir, m_removeTempInputFiles); // inputDir, fileLimit, outputDir, forceMakeOutputDir, removeInputFile
 
-        if (m_outputFileType != "")
-            fileUtil.produceNewFile(inputFileName, m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp+"."+m_outputFileType); // with UNIX and human-readable timestamp
-        else
-            fileUtil.produceNewFile(inputFileName, m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp); // with UNIX timestamp
+	if (m_outputFileType != "")
+	    fileUtil.produceNewFile(inputFileName, m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp+"."+m_outputFileType); // with UNIX and human-readable timestamp
+	else
+	    fileUtil.produceNewFile(inputFileName, m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp); // with UNIX timestamp
     }
     catch(std::runtime_error& err) {
       ATH_MSG_WARNING("Exception caught: " << err.what());
       ATH_MSG_WARNING("In finalize() -- Unable to produce new VP1 event file");
     }
   }
-  
+
   return StatusCode::SUCCESS;
 }
 
 
 
-void VP1EventProd::handle(const Incident& inc) 
+void VP1EventProd::handle(const Incident& inc)
 {
   ATH_MSG_INFO("in handle()... ");
   ATH_MSG_INFO("Handling incident '" << inc.type() << "'");
@@ -126,7 +137,7 @@ void VP1EventProd::handle(const Incident& inc)
    unsigned  int nLastFile = m_nEvent - 1; // we copy the file produced while processing the previous event, so we need a file number of (current - 1)
 
     ATH_MSG_INFO("--> Input POOL file: " << m_inputPoolFile);
-
+    ATH_MSG_INFO("VP1 event number: " << m_eventNumber );
     std::ostringstream ostri;
     ostri << m_inputPoolFile << "._" << std::setw(4) << std::setfill('0') << nLastFile;
 
@@ -135,15 +146,15 @@ void VP1EventProd::handle(const Incident& inc)
 
     try {
 
-        /* clean the output directory if m_maxProducedFiles == 0
-         * or keep up to 'm_maxProducedFiles' output files
-         */
-        VP1FileUtilities fileUtil(".", m_maxProducedFiles, m_destinationDir, m_createDestinationDir, m_removeTempInputFiles); // inputDir, fileLimit, outputDir, forceMakeOutputDir, removeInputFile
+	/* clean the output directory if m_maxProducedFiles == 0
+	 * or keep up to 'm_maxProducedFiles' output files
+	 */
+	VP1FileUtilities fileUtil(".", m_maxProducedFiles, m_destinationDir, m_createDestinationDir, m_removeTempInputFiles); // inputDir, fileLimit, outputDir, forceMakeOutputDir, removeInputFile
 
-        if (m_outputFileType != "")
-            fileUtil.produceNewFile(ostri.str(), m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp+"."+m_outputFileType); // with UNIX and human-readable timestamp
-        else
-            fileUtil.produceNewFile(ostri.str(), m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp); // with UNIX timestamp
+	if (m_outputFileType != "")
+	    fileUtil.produceNewFile(ostri.str(), m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp+"."+m_outputFileType); // with UNIX and human-readable timestamp
+	else
+	    fileUtil.produceNewFile(ostri.str(), m_runNumber, m_eventNumber, m_timeStamp, m_humanTimestamp); // with UNIX timestamp
 
     }
     catch(std::runtime_error& err) {
@@ -172,8 +183,8 @@ void VP1EventProd::handle(const Incident& inc)
   m_timeStamp = context.eventID().time_stamp();
 
   ATH_MSG_DEBUG(" Got run number = " << m_runNumber
-          << ", event number = " << m_eventNumber
-          << ", UNIX timestamp = " << m_timeStamp);
+	  << ", event number = " << m_eventNumber
+	  << ", UNIX timestamp = " << m_timeStamp);
 
   time_t t_timestamp = m_timeStamp;
   struct tm ltm;
@@ -181,19 +192,18 @@ void VP1EventProd::handle(const Incident& inc)
 
   // print various components of tm structure.
   ATH_MSG_DEBUG("Year: "<< 1900 + ltm.tm_year
-          << " - " << "Month: "<< 1 + ltm.tm_mon<< " - "  // tm_mon is in the range [0, 11], so 1 must be added to get real months
-          << "Day: "<<  ltm.tm_mday
-          << " - " "Time: "<< ltm.tm_hour << ":" << ltm.tm_min << ":" << ltm.tm_sec << "CEST"
-         );
+	  << " - " << "Month: "<< 1 + ltm.tm_mon<< " - "  // tm_mon is in the range [0, 11], so 1 must be added to get real months
+	  << "Day: "<<  ltm.tm_mday
+	  << " - " "Time: "<< ltm.tm_hour << ":" << ltm.tm_min << ":" << ltm.tm_sec << "CEST"
+	 );
 
   std::ostringstream ostri;
   ostri  << 1900 + ltm.tm_year
-          << "-" << 1 + ltm.tm_mon  // tm_mon is in the range [0, 11], so 1 must be added to get real months
-          << "-" << ltm.tm_mday
-          << "T" << ltm.tm_hour << "-" << ltm.tm_min << "-" << ltm.tm_sec << "CEST";
+	  << "-" << 1 + ltm.tm_mon  // tm_mon is in the range [0, 11], so 1 must be added to get real months
+	  << "-" << ltm.tm_mday
+	  << "T" << ltm.tm_hour << "-" << ltm.tm_min << "-" << ltm.tm_sec << "CEST";
 
   m_humanTimestamp = ostri.str();
   ATH_MSG_DEBUG("'human readable' timestamp: " << m_humanTimestamp);
 
 }
-
diff --git a/graphics/VP1/VP1UtilsBase/src/VP1FileUtilities.cxx b/graphics/VP1/VP1UtilsBase/src/VP1FileUtilities.cxx
index 5279d310f5c8..0feb26ab5cfc 100644
--- a/graphics/VP1/VP1UtilsBase/src/VP1FileUtilities.cxx
+++ b/graphics/VP1/VP1UtilsBase/src/VP1FileUtilities.cxx
@@ -73,7 +73,7 @@ void VP1FileUtilities::produceNewFile(const std::string& sourceFile,
   // Check if the sourceFile exists
   QString srcName(sourceFile.c_str());
   QFile srcFile(srcName);
-  std::cout << "VP1FileUtilities melissa: " <<  sourceFile << std::endl;
+  std::cout << "VP1FileUtilities melissa: " <<  m_outputDirectory << std::endl;
   if(!srcFile.exists())
     throw std::runtime_error("Source file does not exist!");
 
-- 
GitLab