ATLAS Offline Software
OnlineEventDisplaysSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
6 #include "Gaudi/Property.h"
7 #include "GaudiKernel/IIncidentSvc.h"
8 #include "GaudiKernel/Incident.h"
9 #include "GaudiKernel/MsgStream.h"
11 #include <cstdlib> // For std::rand() and std::srand()
12 #include "Python.h"
13 
15  ISvcLocator* pSvcLocator ) :
16  AthService(name, pSvcLocator){}
17 
19 
21  if (!evt.isValid()) {
22  ATH_MSG_FATAL("Could not find event info");
23  }
24  std::vector<std::string> streams;
25 
26  m_eventNumber = evt->eventNumber();
27  m_runNumber = evt->runNumber();
28 
29  //Check what trigger streams were fired, if in list of desired
30  //streams to be reconstructed pick one randomly
31  for (const xAOD::EventInfo::StreamTag& tag : evt->streamTags()){
32  ATH_MSG_DEBUG("A trigger in stream " << tag.type() << "_" << tag.name() << " was fired in this event.");
33  std::string stream_fullname = tag.type() + "_" + tag.name();
34 
35  if (m_streamsWanted.empty()) {
36  ATH_MSG_WARNING("You have not requested any specific streams, going to allow all streams");
37  streams.emplace_back(stream_fullname);
38  }
39 
40  else{
41  //If the stream is in the list of streams requested, add it
42  if(std::find(m_streamsWanted.begin(), m_streamsWanted.end(), tag.name()) != m_streamsWanted.end()){
43  streams.emplace_back(stream_fullname);
44  }
45  bool isPublic = false;
46  //if the stream is not in the list of public streams wanted, continue
47  if(std::find(m_publicStreams.begin(), m_publicStreams.end(), tag.name()) == m_publicStreams.end()) continue;
48  // Acquire the Global Interpreter Lock (GIL) to ensure thread safety when interacting with Python objects
50  // Convert the project tag string to a Python Unicode object
51  std::string tag = m_projectTag;
52  PyObject* pProjectTag = PyUnicode_FromString(tag.c_str());
53  if (!pProjectTag) {
54  // Error handling: Print Python exception if conversion fails
55  PyErr_Print();
56  ATH_MSG_WARNING("Failed to create Python Unicode object from project tag");
57  } else {
58  // Import the Python module
59  PyObject* pHelper = PyImport_ImportModule("EventDisplaysOnline.EventDisplaysOnlineHelpers");
60  if (!pHelper) {
61  // Error handling: Print Python exception if import fails
62  PyErr_Print();
63  ATH_MSG_WARNING("Failed to import EventDisplaysOnline.EventDisplaysOnlineHelpers module");
64  } else {
65  // Get the "EventCanBeSeenByPublic" function from the module
66  PyObject* EventCanBeSeenByPublic = PyObject_GetAttrString(pHelper, "EventCanBeSeenByPublic");
67  if (!EventCanBeSeenByPublic || !PyCallable_Check(EventCanBeSeenByPublic)) {
68  // Error handling: Print warning if function not found or not callable
69  ATH_MSG_WARNING("Could not find or call EventCanBeSeenByPublic function in EventDisplaysOnline.EventDisplaysOnlineHelpers module");
70  } else {
71  // Call the "EventCanBeSeenByPublic" function with the project tag as argument
72  PyObject* result = PyObject_CallFunctionObjArgs(EventCanBeSeenByPublic, pProjectTag, NULL);
73  if (!result) {
74  PyErr_Print();
75  ATH_MSG_WARNING("Failed to call EventCanBeSeenByPublic function");
76  } else {
77  // Convert the result to a boolean value
78  isPublic = PyObject_IsTrue(result);
79  Py_DECREF(result); // Decrement reference count of the result object
80  }
81  }
82  Py_XDECREF(EventCanBeSeenByPublic);
83  Py_DECREF(pHelper);
84  }
85  Py_DECREF(pProjectTag);
86  }
87  if(isPublic){
88  streams.emplace_back("Public");
89  ATH_MSG_DEBUG("Can send event to public stream");
90  }
91  }
92  }
93  for (std::string stream : streams){
94  ATH_MSG_DEBUG("streams where a trigger fired and in your desired streams list: " << stream);
95  }
96  std::random_shuffle(streams.begin(), streams.end());
97  //Pick the first stream as the output directory
98  if(!streams.empty()){
100  }
101  else{
102  ATH_MSG_WARNING("Cannot find a stream adding to .Unknown directory");
103  m_outputStreamDir = ".Unkown";
104  }
105 
107 
108  std::string FileNamePrefix = m_entireOutputStr + "/JiveXML";
110 
111  gid_t zpgid = setOwnershipToZpGrpOrDefault();
113 }
114 
117  PyObject* pCheckPair = PyBool_FromLong(m_CheckPair);
118  PyObject* pBeamSplash = PyBool_FromLong(m_BeamSplash);
119  PyObject* pMaxEvents = PyLong_FromLong(m_maxEvents);
120  const char* cString = m_entireOutputStr.c_str();
121  PyObject* pDirectory = PyUnicode_FromString(cString);
122  PyObject* pArgs = PyTuple_Pack(4, pDirectory, pMaxEvents, pCheckPair,pBeamSplash);
123  PyObject* pModule = PyImport_ImportModule(const_cast< char* >("EventDisplaysOnline.EventUtils"));
124  if(!pCheckPair || !pBeamSplash || !pMaxEvents || !pDirectory || !pArgs){
125  PyErr_Print();
126  ATH_MSG_WARNING("Failed to create Python Unicode object");}
127  if (!pModule) {
128  PyErr_Print();
129  ATH_MSG_WARNING("Failed to import EventDisplaysOnline.EventUtils module");
130  } else {
131  ATH_MSG_DEBUG("Successfully imported EventDisplaysOnline.EventUtils module");
132 
133  // Get the "cleanDirectory" function from the module
134  PyObject* cleanDirectory = PyObject_GetAttrString(pModule, "cleanDirectory");
135  if (!cleanDirectory || !PyCallable_Check(cleanDirectory)) {
136  ATH_MSG_WARNING("Could not find or call cleanDirectory function in EventDisplaysOnline.EventUtils module");
137  } else {
138  ATH_MSG_DEBUG("Found cleanDirectory function in EventDisplaysOnline.EventUtils module");
139 
140  // Call the "cleanDirectory" function with the provided arguments
141  PyObject_CallObject(cleanDirectory, pArgs);
142  if (PyErr_Occurred()) {
143  PyErr_Print();
144  }
145  }
146  Py_DECREF(cleanDirectory);
147  }
148 
149  if(m_BeamSplash){
150  std::string JiveXMLFileName ="JiveXML_"+ std::to_string(m_runNumber)+"_"+std::to_string(m_eventNumber)+".xml";
151  const char* JiveXMLFileName_cString = JiveXMLFileName.c_str();
152  PyObject* pJiveXMLFileName = PyUnicode_FromString(JiveXMLFileName_cString);
153  PyObject* pArgs_zip = PyTuple_Pack(2, pDirectory, pJiveXMLFileName);
154  PyObject* zipXMLFile = PyObject_GetAttrString(pModule, "zipXMLFile");
155  if (!zipXMLFile) {
156  PyErr_Print();
157  ATH_MSG_WARNING("Failed to import EventDisplaysOnline.EventUtils.zipXMLFile");
158  }
159  else {
160  PyObject_CallObject(zipXMLFile, pArgs_zip);
161  }
162  Py_DECREF(pJiveXMLFileName);
163  Py_DECREF(zipXMLFile);
164  Py_DECREF(pArgs_zip);
165  }
166  Py_DECREF(pModule);
167  Py_DECREF(pArgs);
168  Py_DECREF(pCheckPair);
169  Py_DECREF(pMaxEvents);
170  Py_DECREF(pDirectory);
171 }
172 
174  return m_FileNamePrefix;
175 }
176 
178  return m_entireOutputStr;
179 }
180 
182  return m_outputStreamDir;
183 }
185 
186  const char* char_dir = directory.c_str();
187 
188  if (access(char_dir, F_OK) == 0) {
189  struct stat directoryStat;
190  if (stat(char_dir, &directoryStat) == 0 && S_ISDIR(directoryStat.st_mode) &&
191  access(char_dir, W_OK) == 0) {
192  ATH_MSG_DEBUG("Going to write file to existing directory: " << directory);
193  if (directoryStat.st_gid != zpgid) {
194  ATH_MSG_DEBUG("Setting group to 'zp' for directory: " << directory);
195  chown(char_dir, -1, zpgid);
196  }
197  } else {
198  ATH_MSG_WARNING("Directory '" << directory << "' is not usable, trying next alternative");
199  }
200  } else {
201  try {
202  mkdir(char_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
203  chown(char_dir, -1, zpgid);
204  ATH_MSG_DEBUG("Created output directory " << directory);
205  } catch (const std::system_error& err) {
206  std::cerr << "Failed to create output directory " << directory
207  << err.what() << std::endl;
208  }
209  }
210 }
211 
213  gid_t zpgid;
214  struct group* zp_group = getgrnam("zp");
215  if (zp_group != nullptr) {
216  zpgid = zp_group->gr_gid;
217  } else {
218  ATH_MSG_DEBUG("If running on private machine, zp group might not exist. Just set to the likely value 1307.");
219  zpgid = 1307;
220  }
221  return zpgid;
222 }
223 
225 
226  ATH_MSG_DEBUG("Initializing " << name());
227  IIncidentSvc* incSvc = nullptr;
228  ATH_CHECK( service("IncidentSvc",incSvc) );
229  ATH_MSG_DEBUG("You have requested to only output JiveXML and ESD files when a trigger in the following streams was fired: ");
230  for (std::string stream : m_streamsWanted){
232  }
233  if(m_BeamSplash){
234  m_CheckPair = false;
235  }
236  incSvc->addListener( this, "BeginEvent");
237  incSvc->addListener( this, "StoreCleared");
238 
240 
241  return StatusCode::SUCCESS;
242 }
243 
245 
246  ATH_MSG_DEBUG("Finalizing " << name());
247  return StatusCode::SUCCESS;
248 }
249 
250 void OnlineEventDisplaysSvc::handle( const Incident& incident ){
251  ATH_MSG_DEBUG("Received incident " << incident.type() << " from " << incident.source() );
252  if ( incident.type() == IncidentType::BeginEvent && incident.source() == "BeginIncFiringAlg" ){
253  beginEvent();
254  }
255  if ( incident.type() == "StoreCleared" && incident.source() == "StoreGateSvc" ){
256  endEvent();
257  }
258 }
259 
260 StatusCode OnlineEventDisplaysSvc::queryInterface(const InterfaceID& riid, void** ppvInterface)
261 {
262  if ( IOnlineEventDisplaysSvc::interfaceID().versionMatch(riid) ) {
263  *ppvInterface = dynamic_cast<IOnlineEventDisplaysSvc*>(this);
264  } else {
265  // Interface is not directly available : try out a base class
266  return AthService::queryInterface(riid, ppvInterface);
267  }
268  addRef();
269  return StatusCode::SUCCESS;
270 }
EventUtils.zipXMLFile
def zipXMLFile(directory, filename)
Definition: EventUtils.py:191
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
OnlineEventDisplaysSvc::m_CheckPair
Gaudi::Property< bool > m_CheckPair
Definition: OnlineEventDisplaysSvc.h:54
get_generator_info.result
result
Definition: get_generator_info.py:21
OnlineEventDisplaysSvc.h
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
plot_material.mkdir
def mkdir(path, recursive=True)
Definition: plot_material.py:16
python.outputTest_v2.streams
streams
Definition: outputTest_v2.py:55
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
OnlineEventDisplaysSvc::getEntireOutputStr
std::string getEntireOutputStr() override
Definition: OnlineEventDisplaysSvc.cxx:177
OnlineEventDisplaysSvc::m_eventNumber
long m_eventNumber
Definition: OnlineEventDisplaysSvc.h:60
EventUtils.cleanDirectory
def cleanDirectory(directory, maxevents, checkpair, isBeamSplashMode)
Definition: EventUtils.py:112
IOnlineEventDisplaysSvc::interfaceID
static const InterfaceID & interfaceID()
Definition: IOnlineEventDisplaysSvc.h:22
OnlineEventDisplaysSvc::m_outputStreamDir
std::string m_outputStreamDir
Definition: OnlineEventDisplaysSvc.h:57
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
OnlineEventDisplaysSvc::finalize
StatusCode finalize() override
Definition: OnlineEventDisplaysSvc.cxx:244
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
OnlineEventDisplaysSvc::m_outputDirectory
Gaudi::Property< std::string > m_outputDirectory
Definition: OnlineEventDisplaysSvc.h:49
OnlineEventDisplaysSvc::beginEvent
void beginEvent()
Definition: OnlineEventDisplaysSvc.cxx:18
RootUtils::PyGILStateEnsure
Definition: PyAthenaGILStateEnsure.h:20
OnlineEventDisplaysSvc::initialize
StatusCode initialize() override
Definition: OnlineEventDisplaysSvc.cxx:224
IOnlineEventDisplaysSvc
Definition: IOnlineEventDisplaysSvc.h:10
OnlineEventDisplaysSvc::setOwnershipToZpGrpOrDefault
gid_t setOwnershipToZpGrpOrDefault()
Definition: OnlineEventDisplaysSvc.cxx:212
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:193
OnlineEventDisplaysSvc::m_runNumber
int m_runNumber
Definition: OnlineEventDisplaysSvc.h:59
OnlineEventDisplaysSvc::m_maxEvents
Gaudi::Property< int > m_maxEvents
Definition: OnlineEventDisplaysSvc.h:55
DeMoScan.directory
string directory
Definition: DeMoScan.py:80
OnlineEventDisplaysSvc::endEvent
void endEvent()
Definition: OnlineEventDisplaysSvc.cxx:115
OnlineEventDisplaysSvc::OnlineEventDisplaysSvc
OnlineEventDisplaysSvc()
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthService
Definition: AthService.h:32
OnlineEventDisplaysSvc::m_entireOutputStr
std::string m_entireOutputStr
Definition: OnlineEventDisplaysSvc.h:58
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
beamspotman.stat
stat
Definition: beamspotman.py:266
python.dummyaccess.access
def access(filename, mode)
Definition: dummyaccess.py:18
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
EventInfo.h
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
OnlineEventDisplaysSvc::m_projectTag
Gaudi::Property< std::string > m_projectTag
Definition: OnlineEventDisplaysSvc.h:52
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
OnlineEventDisplaysSvc::queryInterface
StatusCode queryInterface(const InterfaceID &riid, void **ppvIf) override
Definition: OnlineEventDisplaysSvc.cxx:260
OnlineEventDisplaysSvc::createWriteableDir
void createWriteableDir(std::string directory, gid_t zpgid)
Definition: OnlineEventDisplaysSvc.cxx:184
OnlineEventDisplaysSvc::m_streamsWanted
Gaudi::Property< std::vector< std::string > > m_streamsWanted
Definition: OnlineEventDisplaysSvc.h:50
PyAthenaGILStateEnsure.h
EventDisplaysOnlineHelpers.EventCanBeSeenByPublic
def EventCanBeSeenByPublic(projectTags)
Definition: EventDisplaysOnlineHelpers.py:60
CaloCondBlobAlgs_fillNoiseFromASCII.tag
string tag
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:24
OnlineEventDisplaysSvc::m_BeamSplash
Gaudi::Property< bool > m_BeamSplash
Definition: OnlineEventDisplaysSvc.h:53
OnlineEventDisplaysSvc::m_evt
SG::ReadHandleKey< xAOD::EventInfo > m_evt
Definition: OnlineEventDisplaysSvc.h:48
OnlineEventDisplaysSvc::m_publicStreams
Gaudi::Property< std::vector< std::string > > m_publicStreams
Definition: OnlineEventDisplaysSvc.h:51
PyObject
_object PyObject
Definition: IPyComponent.h:26
OnlineEventDisplaysSvc::getFileNamePrefix
std::string getFileNamePrefix() override
Definition: OnlineEventDisplaysSvc.cxx:173
xAOD::EventInfo_v1::StreamTag
Class describing a stream tag on the event.
Definition: EventInfo_v1.h:190
OnlineEventDisplaysSvc::getStreamName
std::string getStreamName() override
Definition: OnlineEventDisplaysSvc.cxx:181
OnlineEventDisplaysSvc::handle
void handle(const Incident &incident) override
Definition: OnlineEventDisplaysSvc.cxx:250
OnlineEventDisplaysSvc::m_FileNamePrefix
std::string m_FileNamePrefix
Definition: OnlineEventDisplaysSvc.h:56
RunTileCalibRec.FileNamePrefix
FileNamePrefix
Definition: RunTileCalibRec.py:473