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