ATLAS Offline Software
Loading...
Searching...
No Matches
ActsMaterialTrackWriterSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include "GaudiKernel/IInterface.h"
8
9#include "TTree.h"
10#include "TFile.h"
11
12#include "Acts/Material/MaterialSlab.hpp"
13#include <Acts/Geometry/GeometryIdentifier.hpp>
14#include <Acts/Surfaces/CylinderBounds.hpp>
15#include <Acts/Surfaces/RadialBounds.hpp>
16#include <Acts/Utilities/Helpers.hpp>
17
18using namespace Acts::VectorHelpers;
19
20#include <vector>
21#include <deque>
22#include <mutex>
23#include <thread>
24
25ActsMaterialTrackWriterSvc::ActsMaterialTrackWriterSvc( const std::string& name, ISvcLocator* svc )
26: base_class(name, svc),
27 m_trackingGeometrySvc("ActsTrackingGeometrySvc", name) {
28}
29
30StatusCode
32{
33
34 std::string filePath = m_filePath;
35 std::string treeName = m_treeName;
36 p_tFile = TFile::Open(filePath.c_str(), "RECREATE");
37 p_tFile->cd();
38 p_tree = new TTree(treeName.c_str(), treeName.c_str());
39
40 p_tree->Branch("v_x", &m_v_x);
41 p_tree->Branch("v_y", &m_v_y);
42 p_tree->Branch("v_z", &m_v_z);
43 p_tree->Branch("v_px", &m_v_px);
44 p_tree->Branch("v_py", &m_v_py);
45 p_tree->Branch("v_pz", &m_v_pz);
46 p_tree->Branch("v_phi", &m_v_phi);
47 p_tree->Branch("v_eta", &m_v_eta);
48
49 p_tree->Branch("t_X0", &m_tX0);
50 p_tree->Branch("t_L0", &m_tL0);
51
52 p_tree->Branch("mat_x", &m_step_x);
53 p_tree->Branch("mat_y", &m_step_y);
54 p_tree->Branch("mat_z", &m_step_z);
55 p_tree->Branch("mat_dx", &m_step_dx);
56 p_tree->Branch("mat_dy", &m_step_dy);
57 p_tree->Branch("mat_dz", &m_step_dz);
58 p_tree->Branch("mat_step_length", &m_step_length);
59 p_tree->Branch("mat_X0", &m_step_X0);
60 p_tree->Branch("mat_L0", &m_step_L0);
61 p_tree->Branch("mat_A", &m_step_A);
62 p_tree->Branch("mat_Z", &m_step_Z);
63 p_tree->Branch("mat_rho", &m_step_rho);
64
65 if (m_storeSurface) {
66 p_tree->Branch("sur_id", &m_sur_id);
67 p_tree->Branch("sur_type", &m_sur_type);
68 p_tree->Branch("sur_x", &m_sur_x);
69 p_tree->Branch("sur_y", &m_sur_y);
70 p_tree->Branch("sur_z", &m_sur_z);
71 p_tree->Branch("sur_range_min", &m_sur_range_min);
72 p_tree->Branch("sur_range_max", &m_sur_range_max);
73 }
74 if (m_storeVolume) {
75 p_tree->Branch("vol_id", &m_vol_id);
76 }
77
78 ATH_MSG_INFO("Starting writer thread");
79 ATH_MSG_DEBUG("Maximum queue size is set to:" << m_maxQueueSize);
80 m_doEnd = false;
82
83 return StatusCode::SUCCESS;
84}
85
86StatusCode
88{
89
90 ATH_MSG_INFO("Waiting for writer thread to finish.");
91 m_doEnd = true;
92 m_writeThread.join();
93 ATH_MSG_INFO("Writer thread has terminated.");
94
95 ATH_MSG_INFO("Closing TFile");
96 p_tFile->cd();
97 p_tree->FlushBaskets();
98 p_tree->AutoSave();
99 p_tree->Write();
100 p_tFile->Write();
101 p_tFile->Close();
102
103 return StatusCode::SUCCESS;
104}
105
106void
108{
109 std::lock_guard<std::mutex> lock(m_writeMutex);
110
111 ATH_MSG_VERBOSE("Appending material track to write queue");
112 m_mTracks.push_back(mTrack);
113}
114
115void
117{
118 using namespace std::chrono_literals;
119 // wait until we have events
120 while(m_mTracks.size() == 0) {
121 std::this_thread::sleep_for(2s);
122 if (m_doEnd) return;
123 }
124
125 ATH_MSG_DEBUG("Begin regular write loop");
126 while(true) {
127 ATH_MSG_VERBOSE("Obtaining write lock");
128 std::unique_lock<std::mutex> lock(m_writeMutex);
129
130 if (m_mTracks.empty()) {
131 lock.unlock();
132 if (!m_doEnd) {
133 ATH_MSG_VERBOSE("Queue was empty, delay next execution");
134 std::this_thread::sleep_for(0.1s);
135 continue;
136 } else {
137 ATH_MSG_INFO("Writer thread caught termination signal. Shutting down.");
138
139 return;
140 }
141 }
142
143
144 if(m_mTracks.size() < m_maxQueueSize) {
145 // just pop one
146 ATH_MSG_VERBOSE("Queue at " << m_mTracks.size() << "/" << m_maxQueueSize
147 << ": Pop entry and write");
148 Acts::RecordedMaterialTrack mTrack = std::move(m_mTracks.front());
149 m_mTracks.pop_front();
150 // writing can now happen without lock
151 lock.unlock();
152 doWrite(std::move(mTrack));
153 }
154 else {
155 ATH_MSG_DEBUG("Queue at " << m_mTracks.size() << "/" << m_maxQueueSize
156 << ": Lock and write until empty");
157 while(!m_mTracks.empty()) {
158 ATH_MSG_VERBOSE("Pop entry and write");
159 // keep the lock!
160 Acts::RecordedMaterialTrack mTrack = std::move(m_mTracks.front());
161 m_mTracks.pop_front();
162 doWrite(std::move(mTrack));
163 }
164 ATH_MSG_DEBUG("Queue is empty, continue");
165
166 }
167 }
168}
169
170void
172{
173 ATH_MSG_VERBOSE("Write to tree");
174 size_t mints = mTrack.second.materialInteractions.size();
175
176 // Clearing the vector first
177 m_step_sx.clear();
178 m_step_sy.clear();
179 m_step_sz.clear();
180 m_step_x.clear();
181 m_step_y.clear();
182 m_step_z.clear();
183 m_step_ex.clear();
184 m_step_ey.clear();
185 m_step_ez.clear();
186 m_step_dx.clear();
187 m_step_dy.clear();
188 m_step_dz.clear();
189 m_step_length.clear();
190 m_step_X0.clear();
191 m_step_L0.clear();
192 m_step_A.clear();
193 m_step_Z.clear();
194 m_step_rho.clear();
195
196 if(m_storeSurface){
197 m_sur_id.clear();
198 m_sur_type.clear();
199 m_sur_x.clear();
200 m_sur_y.clear();
201 m_sur_z.clear();
202 m_sur_range_min.clear();
203 m_sur_range_max.clear();
204 }
205
206 if (m_storeVolume) {
207 m_vol_id.clear();
208 }
209 // Reserve the vector then
210 m_step_sx.reserve(mints);
211 m_step_sy.reserve(mints);
212 m_step_sz.reserve(mints);
213 m_step_x.reserve(mints);
214 m_step_y.reserve(mints);
215 m_step_ez.reserve(mints);
216 m_step_ex.reserve(mints);
217 m_step_ey.reserve(mints);
218 m_step_ez.reserve(mints);
219 m_step_dx.reserve(mints);
220 m_step_dy.reserve(mints);
221 m_step_dz.reserve(mints);
222 m_step_length.reserve(mints);
223 m_step_X0.reserve(mints);
224 m_step_L0.reserve(mints);
225 m_step_A.reserve(mints);
226 m_step_Z.reserve(mints);
227 m_step_rho.reserve(mints);
228
229 if(m_storeSurface){
230 m_sur_id.reserve(mints);
231 m_sur_type.reserve(mints);
232 m_sur_x.reserve(mints);
233 m_sur_y.reserve(mints);
234 m_sur_z.reserve(mints);
235 m_sur_range_min.reserve(mints);
236 m_sur_range_max.reserve(mints);
237 }
238 if (m_storeVolume) {
239 m_vol_id.reserve(mints);
240 }
241
242 // reset the global counter
243 m_tX0 = mTrack.second.materialInX0;
244 m_tL0 = mTrack.second.materialInL0;
245
246 // set the track information at vertex
247 m_v_x = mTrack.first.first.x();
248 m_v_y = mTrack.first.first.y();
249 m_v_z = mTrack.first.first.z();
250 m_v_px = mTrack.first.second.x();
251 m_v_py = mTrack.first.second.y();
252 m_v_pz = mTrack.first.second.z();
253 m_v_phi = phi(mTrack.first.second);
254 m_v_eta = eta(mTrack.first.second);
255
256 // an now loop over the material
257 for (auto& mint : mTrack.second.materialInteractions) {
258 // The material step position information
259 m_step_x.push_back(mint.position.x());
260 m_step_y.push_back(mint.position.y());
261 m_step_z.push_back(mint.position.z());
262 m_step_dx.push_back(mint.direction.x());
263 m_step_dy.push_back(mint.direction.y());
264 m_step_dz.push_back(mint.direction.z());
265
266 Acts::Vector3 prePos
267 = mint.position - 0.5 * mint.pathCorrection * mint.direction;
268 Acts::Vector3 posPos
269 = mint.position + 0.5 * mint.pathCorrection * mint.direction;
270 m_step_sx.push_back(prePos.x());
271 m_step_sy.push_back(prePos.y());
272 m_step_sz.push_back(prePos.z());
273 m_step_ex.push_back(posPos.x());
274 m_step_ey.push_back(posPos.y());
275 m_step_ez.push_back(posPos.z());
276
277 if (m_storeSurface) {
278 const Acts::Surface* surface = mint.surface;
279 Acts::GeometryIdentifier layerID;
280 if (surface) {
281 const ActsTrk::GeometryContext& gctx{m_trackingGeometrySvc->getNominalContext()};
282 auto sfIntersection = surface
283 ->intersect(gctx.context(), mint.position,
284 mint.direction, Acts::BoundaryTolerance::None())
285 .closest();
286 layerID = surface->geometryId();
287 m_sur_id.push_back(layerID.value());
288 m_sur_type.push_back(surface->type());
289 m_sur_x.push_back(sfIntersection.position().x());
290 m_sur_y.push_back(sfIntersection.position().y());
291 m_sur_z.push_back(sfIntersection.position().z());
292
293 const Acts::SurfaceBounds& surfaceBounds = surface->bounds();
294 const Acts::RadialBounds* radialBounds =
295 dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds);
296 const Acts::CylinderBounds* cylinderBounds =
297 dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds);
298
299 if (radialBounds) {
300 m_sur_range_min.push_back(radialBounds->rMin());
301 m_sur_range_max.push_back(radialBounds->rMax());
302 } else if (cylinderBounds) {
303 m_sur_range_min.push_back(
304 -cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ));
305 m_sur_range_max.push_back(
306 cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ));
307 } else {
308 m_sur_range_min.push_back(0);
309 m_sur_range_max.push_back(0);
310 }
311 } else {
312 m_sur_id.push_back(layerID.withVolume(0)
313 .withBoundary(0)
314 .withLayer(0)
315 .withApproach(0)
316 .withSensitive(0)
317 .value());
318 m_sur_type.push_back(-1);
319
320 m_sur_x.push_back(0);
321 m_sur_y.push_back(0);
322 m_sur_z.push_back(0);
323 m_sur_range_min.push_back(0);
324 m_sur_range_max.push_back(0);
325 }
326 }
327 // store volume information
328 if (m_storeVolume) {
329 const Acts::InteractionVolume& volume = mint.volume;
330 Acts::GeometryIdentifier vlayerID;
331 if (!volume.empty()) {
332 vlayerID = volume.geometryId();
333 m_vol_id.push_back(vlayerID.value());
334 } else {
335 m_vol_id.push_back(vlayerID.withVolume(0)
336 .withBoundary(0)
337 .withLayer(0)
338 .withApproach(0)
339 .withSensitive(0)
340 .value());
341 }
342 }
343 // the material information
344 const auto& mprops = mint.materialSlab;
345 m_step_length.push_back(mprops.thickness());
346 m_step_X0.push_back(mprops.material().X0());
347 m_step_L0.push_back(mprops.material().L0());
348 m_step_A.push_back(mprops.material().Ar());
349 m_step_Z.push_back(mprops.material().Z());
350 m_step_rho.push_back(mprops.material().massDensity());
351
352 }
353 p_tree->Fill();
354 ATH_MSG_VERBOSE("Write complete");
355}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::vector< float > m_step_length
step length
Gaudi::Property< std::string > m_treeName
ServiceHandle< ActsTrk::ITrackingGeometrySvc > m_trackingGeometrySvc
std::vector< float > m_step_X0
step material x0
ActsMaterialTrackWriterSvc(const std::string &name, ISvcLocator *svc)
std::vector< float > m_sur_y
y position of the center of the suface associated with the step
std::vector< float > m_step_sz
step z (start) position (optional)
std::vector< float > m_step_sy
step y (start) position (optional)
void doWrite(const Acts::RecordedMaterialTrack &mTrack)
std::vector< float > m_step_A
step material A
std::vector< float > m_step_ey
step y (end) position (optional)
virtual StatusCode finalize() override
std::vector< std::uint64_t > m_vol_id
ID of the volume associated with the step.
std::vector< float > m_step_L0
step material l0
virtual StatusCode initialize() override
std::vector< float > m_sur_z
z position of the center of the suface associated with the step
std::deque< Acts::RecordedMaterialTrack > m_mTracks
std::vector< float > m_step_dx
step x direction
std::vector< float > m_step_dz
step z direction
std::vector< float > m_step_ex
step x (end) position (optional)
float m_v_px
start global momentum x
std::vector< float > m_step_y
step y position
std::vector< float > m_step_Z
step material Z
std::vector< float > m_step_rho
step material rho
float m_v_py
start global momentum y
float m_v_pz
start global momentum z
Gaudi::Property< size_t > m_maxQueueSize
std::vector< float > m_step_z
step z position
std::vector< float > m_sur_x
x position of the center of the suface associated with the step
Gaudi::Property< std::string > m_filePath
std::vector< float > m_step_ez
step z (end) position (optional)
std::vector< float > m_step_x
step x position
std::vector< float > m_sur_range_max
Max range of the suface associated with the step.
std::vector< int32_t > m_sur_type
Type of the suface associated with the step.
std::vector< float > m_step_dy
step y direction
std::vector< std::uint64_t > m_sur_id
ID of the suface associated with the step.
std::vector< float > m_step_sx
step x (start) position (optional)
virtual void write(const Acts::RecordedMaterialTrack &mTrack) override
std::vector< float > m_sur_range_min
Min range of the suface associated with the step.
Acts::GeometryContext context() const
std::pair< std::pair< Acts::Vector3, Acts::Vector3 >, RecordedMaterial > RecordedMaterialTrack
Recorded material track.