ATLAS Offline Software
Loading...
Searching...
No Matches
UserActionSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <mutex>
6
7// Geant4 includes
8#include "G4RunManager.hh"
9
10// Local includes
11#include "UserActionSvc.h"
12
13namespace G4UA
14{
15
16 //---------------------------------------------------------------------------
17 // Constructor
18 // I was using private tool handle arrays, but the OutputLevels weren't
19 // getting set correctly (in mig1), so I will just make them all public.
20 //---------------------------------------------------------------------------
21 UserActionSvc::UserActionSvc(const std::string& name,
22 ISvcLocator* pSvcLocator)
23 : base_class(name, pSvcLocator)
24 , m_userActionTools(this)
25 {
26 declareProperty("UserActionTools", m_userActionTools);
27 }
28
30 for (auto& tool : m_userActionTools) {
31 tool->G4RunTool(g4RunTool);
32 }
33 }
34
35 //---------------------------------------------------------------------------
36 // Initialize the service
37 //---------------------------------------------------------------------------
39 {
40 ATH_MSG_INFO("Initializing " << m_userActionTools.size() << " user action tools.");
41
42 for(const auto& action : m_userActionTools) {
43 ATH_MSG_INFO( " -> " << action.name() );
44 }
45
46 ATH_CHECK( m_userActionTools.retrieve() );
47
48 return StatusCode::SUCCESS;
49 }
50 StatusCode UserActionSvc::addActionTool(const ToolHandle<IUserActionTool>& service_tool){
51
52 if (!service_tool.isPublic()){
53 ATH_MSG_FATAL("Only public tools are allowed");
54 return StatusCode::FAILURE;
55 }
56 if (service_tool.empty()) {
57 ATH_MSG_FATAL("NO point in adding empty tool handles here.");
58 return StatusCode::FAILURE;
59 }
60 ATH_MSG_INFO(" Add new tool "<<service_tool.name());
61 m_userActionTools.push_back(service_tool);
62 return StatusCode::SUCCESS;
63 }
64
65 //---------------------------------------------------------------------------
66 // Initialize the Geant4 main thread.
67 //---------------------------------------------------------------------------
69 {
70 // Retrieve the new user actions
71 G4AtlasUserActions actions;
72 for(auto& tool : m_userActionTools) {
73 ATH_CHECK( tool->fillUserAction(actions) );
74 }
75 auto runAction = std::make_unique<G4AtlasRunAction>();
76 // Assign run plugins
77 for(auto* action : actions.runActionsMaster)
78 {
79 runAction->addRunAction(action);
80 }
81 G4RunManager::GetRunManager()->SetUserAction( runAction.release() );
82 return StatusCode::SUCCESS;
83 }
84
85 //---------------------------------------------------------------------------
86 // Initialize the user actions for the current thread.
87 // In this code, "action" refers to the G4 action classes, and "plugin"
88 // refers to the custom action objects that get assigned to the G4 action.
89 // TODO: this prototype could be cleaner
90 //---------------------------------------------------------------------------
92 {
93 // This method is called concurrently in AthenaMT during initialization.
94 // We conservatively just lock the whole thing to protect MsgStream and
95 // downstream code.
96 static std::mutex userActionMutex;
97 std::lock_guard<std::mutex> userActionLock(userActionMutex);
98
99 ATH_MSG_DEBUG("initializeActions");
100
101 // sanity check: this is to make sure there are no other instances of this
102 // svc that have been already initialized, or that nobody else in some other
103 // code has already been registering actions to the run manager, which would
104 // be a major error in the configuration checking the run action is probably
105 // enough fo multiple instances of this service, since all roles are usually
106 // set at the same time. but other code may as well have registered just one
107 // role, so it is safer to do all checks here.
108
109 if( G4RunManager::GetRunManager()->GetUserRunAction() ||
110 G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction() ||
111 G4RunManager::GetRunManager()->GetUserEventAction() ||
112 G4RunManager::GetRunManager()->GetUserStackingAction() ||
113 G4RunManager::GetRunManager()->GetUserTrackingAction() ||
114 G4RunManager::GetRunManager()->GetUserSteppingAction() )
115 {
116 ATH_MSG_FATAL("UserActionSvc has found that actions were already " <<
117 "registered to the G4RunManager. Check your code/configuration");
118 return StatusCode::FAILURE;
119 }
120
121 // Retrieve the new user actions
122 G4AtlasUserActions actions;
123 for(auto& tool : m_userActionTools) {
124 ATH_CHECK( tool->fillUserAction(actions) );
125 }
126
127 // Initialize the ATLAS run action.
128 if(m_runActions.get()) {
129 ATH_MSG_ERROR("Run action already exists for current thread!");
130 return StatusCode::FAILURE;
131 }
132 auto runAction = std::make_unique<G4AtlasRunAction>();
133 // Assign run plugins
134 for(auto* action : actions.runActions)
135 runAction->addRunAction(action);
136 G4RunManager::GetRunManager()->SetUserAction( runAction.get() );
137 m_runActions.set( std::move(runAction) );
138
139 // Initialize the ATLAS primary generator action.
140 if(m_primaryGeneratorActions.get()) {
141 ATH_MSG_ERROR("Primary generator action already exists for current thread!");
142 return StatusCode::FAILURE;
143 }
144 auto primaryGeneratorAction = std::make_unique<G4AtlasPrimaryGeneratorAction>();
145 // Assign run plugins
146 for(auto* action : actions.primaryGeneratorActions)
147 primaryGeneratorAction->addPrimaryGeneratorAction(action);
148 G4RunManager::GetRunManager()->SetUserAction( primaryGeneratorAction.get() );
149 m_primaryGeneratorActions.set( std::move(primaryGeneratorAction) );
150
151 // Initialize the ATLAS event action.
152 if(m_eventActions.get()) {
153 ATH_MSG_ERROR("Event action already exists for current thread!");
154 return StatusCode::FAILURE;
155 }
156 auto eventAction = std::make_unique<G4AtlasEventAction>();
157 // Assign event plugins
158 for(auto* action : actions.eventActions) {
159 eventAction->addEventAction(action);
160 // set the event manager
161 action->SetEventManager( G4EventManager::GetEventManager() );
162 }
163 G4RunManager::GetRunManager()->SetUserAction( eventAction.get() );
164 m_eventActions.set( std::move(eventAction) );
165
166 // Initialize the ATLAS stacking action.
167 if(m_stackingActions.get()) {
168 ATH_MSG_ERROR("Stacking action already exists for current thread!");
169 return StatusCode::FAILURE;
170 }
171 auto stackAction = std::make_unique<G4AtlasStackingAction>();
172 // Assign stacking plugins
173 for(auto* action : actions.stackingActions) {
174 stackAction->addAction(action);
175 // set the stack manager
176 action->SetStackManager( G4EventManager::GetEventManager()->GetStackManager() );
177 }
178 G4RunManager::GetRunManager()->SetUserAction( stackAction.get() );
179 m_stackingActions.set( std::move(stackAction) );
180
181 // Initialize the ATLAS tracking action.
182 if(m_trackingActions.get()) {
183 ATH_MSG_ERROR("Tracking action already exists for current thread!");
184 return StatusCode::FAILURE;
185 }
186 auto trackAction = std::make_unique<G4AtlasTrackingAction>();
187 // Assign tracking plugins
188 for(auto* action : actions.trackingActions) {
189 trackAction->addTrackAction(action);
190 // set the tracking manager
191 action->SetTrackingManagerPointer ( G4EventManager::GetEventManager()->GetTrackingManager() );
192 }
193 G4RunManager::GetRunManager()->SetUserAction( trackAction.get() );
194 m_trackingActions.set( std::move(trackAction) );
195
196 // Initialize the ATLAS stepping action.
197 if(m_steppingActions.get()) {
198 ATH_MSG_ERROR("Stepping action already exists for current thread!");
199 return StatusCode::FAILURE;
200 }
201 auto stepAction = std::make_unique<G4AtlasSteppingAction>();
202 // Assign stepping plugins
203 for(auto* action : actions.steppingActions) {
204 stepAction->addAction(action);
205 // set the stepping manager
206 action->SetSteppingManagerPointer( G4EventManager::GetEventManager()->GetTrackingManager()->GetSteppingManager() );
207 }
208 G4RunManager::GetRunManager()->SetUserAction( stepAction.get() );
209 m_steppingActions.set( std::move(stepAction) );
210
211 return StatusCode::SUCCESS;
212 }
213
214 // For ISF, get UserActions that could have stored secondary particles
215 StatusCode UserActionSvc::getSecondaryActions( std::vector< G4UserSteppingAction* >& actions ) {
216
217 // Only stepping actions can return secondaries? Maybe turn this into a templated method
218 actions = m_steppingActions.get()->getActions();
219
220 return StatusCode::SUCCESS;
221 }
222
224 {
225 for(auto& actionTool : m_userActionTools) {
226 if(actionTool->BeginOfAthenaEvent(hitCollections).isFailure()) {
227 ATH_MSG_ERROR("BeginOfAthenaEvent failed for " << actionTool->name());
228 return StatusCode::FAILURE;
229 }
230 }
231 return StatusCode::SUCCESS;
232 }
233
235 {
236 for(auto& actionTool : m_userActionTools) {
237 if(actionTool->EndOfAthenaEvent(hitCollections).isFailure()) {
238 ATH_MSG_ERROR("EndOfAthenaEvent failed for " << actionTool->name());
239 return StatusCode::FAILURE;
240 }
241 }
242 return StatusCode::SUCCESS;
243 }
244} // namespace G4UA
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
ToolHandleArray< IUserActionTool > m_userActionTools
User action tools.
StatusCode addActionTool(const ToolHandle< IUserActionTool > &service_tool) override final
ThreadActionHolder< G4AtlasEventAction > m_eventActions
Thread-local event action.
StatusCode initializeActions() override final
Initialize the user actions for the current thread.
StatusCode initializeActionsMaster() override final
Initialize the user run actions for the main thread.
StatusCode getSecondaryActions(std::vector< G4UserSteppingAction * > &actions) override final
ThreadActionHolder< G4AtlasSteppingAction > m_steppingActions
Thread-local stepping action.
StatusCode initialize() override
Initialize the service.
void G4RunTool(IG4RunTool *) override final
StatusCode EndOfAthenaEvent(HitCollectionMap &) override final
Calls EndOfAthenaEvent on each UserAction tool.
UserActionSvc(const std::string &name, ISvcLocator *pSvcLocator)
Standard constructor.
ThreadActionHolder< G4AtlasPrimaryGeneratorAction > m_primaryGeneratorActions
Thread-local primary generator action.
ThreadActionHolder< G4AtlasTrackingAction > m_trackingActions
Thread-local tracking action.
ThreadActionHolder< G4AtlasStackingAction > m_stackingActions
Thread-local stacking action.
StatusCode BeginOfAthenaEvent(HitCollectionMap &) override final
Calls BeginOfAthenaEvent on each UserAction tool.
ThreadActionHolder< G4AtlasRunAction > m_runActions
Thread-local run action.
Small wrapper around hit collection map to facilitate accessing the hit collection.
Provides an interface to interact with the Geant4 run.
Definition IG4RunTool.h:22
Struct for passing around user actions.
std::vector< G4UserRunAction * > runActionsMaster
std::vector< G4UserTrackingAction * > trackingActions
std::vector< G4UserStackingAction * > stackingActions
std::vector< G4VUserPrimaryGeneratorAction * > primaryGeneratorActions
std::vector< G4UserSteppingAction * > steppingActions
std::vector< G4UserEventAction * > eventActions
std::vector< G4UserRunAction * > runActions