ATLAS Offline Software
Loading...
Searching...
No Matches
VertexTimeAlg.cxx
Go to the documentation of this file.
1
10
11#include "VertexTimeAlg.h"
12
13// Athena includes
19
20// Standard library includes
21#include <cmath>
22
23namespace HGTD {
24
25VertexTimeAlg::VertexTimeAlg(const std::string& name, ISvcLocator* pSvcLocator)
26 : AthReentrantAlgorithm(name, pSvcLocator) {}
27
29
30 // Initialize keys for event data access
31 ATH_CHECK(m_primVxCont_key.initialize());
32 ATH_CHECK(m_trackCont_key.initialize());
33 ATH_CHECK(m_vxHasTime_key.initialize());
34 ATH_CHECK(m_vxTime_key.initialize());
35 ATH_CHECK(m_vxTimeRes_key.initialize());
36 ATH_CHECK(m_trackValidTime_key.initialize());
37 ATH_CHECK(m_trackTime_key.initialize());
38 ATH_CHECK(m_trackTimeRes_key.initialize());
39
40 // Initialize the BDT
41 for (auto& bdt : m_BDT) {
42
43 bdt.reader = std::make_unique<TMVA::Reader>("!Color:!Silent");
44
45 bdt.reader->AddVariable("m_delta_z", &bdt.delta_z);
46 bdt.reader->AddVariable("m_z_sigma", &bdt.z_sigma);
47 bdt.reader->AddVariable("m_q_over_p", &bdt.q_over_p);
48 bdt.reader->AddVariable("m_q_over_p_sigma", &bdt.q_over_p_sigma);
49 bdt.reader->AddVariable("m_delta_z_resunits", &bdt.delta_z_resunits);
50 bdt.reader->AddVariable("m_cluster_sumpt2", &bdt.cluster_sumpt2);
51 bdt.reader->AddVariable("m_d0", &bdt.d0);
52 bdt.reader->AddVariable("m_d0_sigma", &bdt.d0_sigma);
53
54 const std::string weightFile {
55 PathResolver::find_file("TMVA.VBFinv.mu200.Step3p1.8var.weights.xml", "DATAPATH")
56 };
57
58 bdt.reader->BookMVA("BDT", weightFile);
59 }
60
61 return StatusCode::SUCCESS;
62}
63
64StatusCode VertexTimeAlg::execute(const EventContext& ctx) const {
65
68
70 m_vxHasTime_key, ctx);
72 m_vxTime_key, ctx);
74 m_vxTimeRes_key, ctx);
75
76
77 for (const auto vx : *primVxCont) {
78
79 if (vx->vertexType() == xAOD::VxType::VertexType::PriVtx) {
80
81 std::vector<const xAOD::TrackParticle*> hgtdTracks {
82 vertexAssociatedHGTDTracks(vx, trackCont.cptr(), 1.0 * Gaudi::Units::GeV)
83 };
84
85 std::vector<HGTD::Cluster<const xAOD::TrackParticle*>> trackClusters {
86 clusterTracksInTime(ctx, hgtdTracks, 3.0)
87 };
88
89 // Get the cluster that was determined as HS by the BDT
91 getHScluster(ctx, trackClusters, vx)
92 };
93
94 if (HS_cluster.getEntries().size() > 0) {
95 // HS cluster was found
96
97 vxHasTime(*vx) = 1;
98 vxTime(*vx) = HS_cluster.getValues().at(0);
99 vxTimeRes(*vx) = HS_cluster.getSigmas().at(0);
100
101 } else {
102 // No cluster was chosen as HS
103
104 vxHasTime(*vx) = 0;
105 vxTime(*vx) = m_default_vxTime;
106 vxTimeRes(*vx) = m_default_vxTimeRes;
107 }
108
109 } else {
110 // Pileup vertices do not have a time
111
112 vxHasTime(*vx) = 0;
113 vxTime(*vx) = m_default_vxTime;
114 vxTimeRes(*vx) = m_default_vxTimeRes;
115 }
116 }
117
118 return StatusCode::SUCCESS;
119}
120
121std::vector<const xAOD::TrackParticle*>
123 const xAOD::Vertex* vertex, const xAOD::TrackParticleContainer* tracks,
124 double min_trk_pt) const {
125
126 std::vector<const xAOD::TrackParticle*> good_tracks { };
127
128 for (const auto trk : *tracks) {
129 if (std::abs(trk->eta()) < 2.4 || std::abs(trk->eta()) > 4.0) {
130 // Track is not within HGTD acceptance
131 continue;
132 }
133 if (trk->pt() < 1.0 * Gaudi::Units::GeV) {
134 continue;
135 }
136 if (passTrackVertexAssociation(trk, vertex, min_trk_pt)) {
137 good_tracks.push_back(trk);
138 }
139 }
140
141 return good_tracks;
142}
143
145 const xAOD::TrackParticle* track, const xAOD::Vertex* vertex,
146 double min_trk_pt, const double significance_cut) const {
147
148 if (track->pt() < min_trk_pt || std::abs(track->eta()) > 4.0) {
149 return false;
150 }
151
152 const double vx_z { vertex->z() };
153 const double vx_z_variance { vertex->covariancePosition()(2, 2) };
154
155 const double trk_z { track->vz() + track->z0() };
156 const double trk_z_variance { track->definingParametersCovMatrix()(1, 1) };
157
158 if (std::abs(trk_z - vx_z) / std::sqrt(trk_z_variance + vx_z_variance)
159 < significance_cut) {
160 return true;
161 } else {
162 return false;
163 }
164}
165
166std::vector<HGTD::Cluster<const xAOD::TrackParticle*>>
168 const EventContext& ctx,
169 const std::vector<const xAOD::TrackParticle*>& tracks,
170 double cluster_distance) const {
171
174
176 m_trackTime_key, ctx);
177
179 m_trackTimeRes_key, ctx);
180
181
183
184 for (const auto& track : tracks) {
185
186 if (trackValidTime(*track)) {
187 double time { trackTime(*track) };
188 double timeResolution { trackTimeResolution(*track) };
189
191 {time}, {timeResolution}, track);
192
193 collection.addCluster(cluster);
194 }
195 }
196
197 collection.updateDistanceCut(cluster_distance);
199
200 return collection.getClusters();
201}
202
204 const EventContext& ctx,
205 const std::vector<HGTD::Cluster<const xAOD::TrackParticle*>>& clusters,
206 const xAOD::Vertex* vertex) const {
207
209 float max_BDT_score { -1.0f };
210
211 for (const auto& cluster : clusters) {
212
213 // HS cluster has an additional requirement to have at least 3 tracks
214 if (cluster.getEntries().size() < 3) {
215 continue;
216 }
217
218 const float cluster_score { scoreCluster(ctx, cluster, vertex) };
219
220 if (cluster_score > m_bdt_cutvalue && cluster_score > max_BDT_score) {
221
222 max_BDT_score = cluster_score;
223 HS_cluster = cluster;
224 }
225 }
226
227 // If no cluster passes the HS criteria, the return value will be an empty
228 // cluster
229 return HS_cluster;
230}
231
233 const EventContext& ctx,
235 const xAOD::Vertex* vertex) const {
236
237 std::pair<float, float> cluster_z { getZOfCluster(cluster) };
238 std::pair<float, float> cluster_oneover_p { getOneOverPOfCluster(cluster) };
239 std::pair<float, float> cluster_d0 { getDOfCluster(cluster) };
240 double vertex_z_variance { vertex->covariancePosition()(2, 2) };
241
242 auto& bdt { *m_BDT.get(ctx) };
243
244 bdt.delta_z = cluster_z.first - vertex->z();
245 bdt.z_sigma = cluster_z.second;
246 bdt.q_over_p = cluster_oneover_p.first;
247 bdt.q_over_p_sigma = cluster_oneover_p.second;
248 bdt.d0 = cluster_d0.first;
249 bdt.d0_sigma = cluster_d0.second;
250 bdt.cluster_sumpt2 = getSumPt2OfCluster(cluster);
251 bdt.delta_z_resunits = (cluster_z.first - vertex->z()) /
252 std::sqrt(std::pow(cluster_z.second, 2.0) + vertex_z_variance);
253
254 return bdt.reader->EvaluateMVA("BDT");
255}
256
257std::pair<float, float> VertexTimeAlg::getZOfCluster(
258 const HGTD::Cluster<const xAOD::TrackParticle*>& cluster) const {
259
260 std::vector<const xAOD::TrackParticle*> tracks { cluster.getEntries() };
261
262 float num { 0.0f };
263 float denom { 0.0f };
264
265 for (const auto& track : tracks) {
266
267 float z0 { track->z0() };
268 float z0_variance {
269 static_cast<float>(track->definingParametersCovMatrix()(1, 1))
270 };
271
272 num += z0 / z0_variance;
273 denom += 1.0f / z0_variance;
274 }
275
276 float avg_z0 = num / denom;
277 float avg_z0_sigma = std::sqrt(1.0f / denom);
278
279 return {avg_z0, avg_z0_sigma};
280}
281
283 const HGTD::Cluster<const xAOD::TrackParticle*>& cluster) const {
284
285 std::vector<const xAOD::TrackParticle*> tracks { cluster.getEntries() };
286
287 float num { 0.0f };
288 float denom { 0.0f };
289
290 for (const auto& track : tracks) {
291
292 float one_over_p { std::abs(track->qOverP()) };
293 float one_over_p_variance {
294 static_cast<float>(track->definingParametersCovMatrix()(4, 4))
295 };
296
297 num += one_over_p / one_over_p_variance;
298 denom += 1.0f / one_over_p_variance;
299 }
300
301 float avg_oneover_p = num / denom;
302 float avg_oneover_p_sigma = std::sqrt(1.0f / denom);
303
304 return {avg_oneover_p, avg_oneover_p_sigma};
305}
306
307std::pair<float, float> VertexTimeAlg::getDOfCluster(
308 const HGTD::Cluster<const xAOD::TrackParticle*>& cluster) const {
309
310 std::vector<const xAOD::TrackParticle*> tracks { cluster.getEntries() };
311
312 float num { 0.0f };
313 float denom { 0.0f };
314
315 for (const auto& track : tracks) {
316
317 float d0 { track->d0() };
318 float d0_variance {
319 static_cast<float>(track->definingParametersCovMatrix()(0, 0))
320 };
321
322 num += d0 / d0_variance;
323 denom += 1.0f / d0_variance;
324 }
325
326 float avg_z0 = num / denom;
327 float avg_z0_sigma = std::sqrt(1.0f / denom);
328
329 return {avg_z0, avg_z0_sigma};
330}
331
333 const HGTD::Cluster<const xAOD::TrackParticle*>& cluster) const {
334
335 std::vector<const xAOD::TrackParticle*> tracks { cluster.getEntries() };
336
337 float sumpt2 { 0.0f };
338
339 for (const auto& track : tracks) {
340 sumpt2 += std::pow(track->pt(), 2.0);
341 }
342
343 return sumpt2;
344}
345
346} // namespace HGTD
#define ATH_CHECK
Evaluate an expression and check for errors.
Handle class for reading a decoration on an object.
Handle class for reading from StoreGate.
Handle class for adding a decoration to an object.
Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
An algorithm that can be simultaneously executed in multiple threads.
void doClustering(ClusterAlgo algo)
Definition Clustering.h:368
void updateDistanceCut(double cut_value)
Set the distance cut.
Definition Clustering.h:270
void addCluster(const Cluster< T > &vx)
Definition Clustering.h:274
const std::vector< Cluster< T > > & getClusters() const
Definition Clustering.h:506
const std::vector< T > & getEntries() const
Return the objects that are part of the Cluster.
Definition Clustering.h:210
std::vector< double > getValues() const
Return the N-dimensional value of the Cluster.
Definition Clustering.h:228
const std::vector< double > & getSigmas() const
Return the N-dimensional resolution of the Cluster.
Definition Clustering.h:240
std::pair< float, float > getDOfCluster(const HGTD::Cluster< const xAOD::TrackParticle * > &cluster) const
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackCont_key
Gaudi::Property< float > m_default_vxTime
std::vector< const xAOD::TrackParticle * > vertexAssociatedHGTDTracks(const xAOD::Vertex *vertex, const xAOD::TrackParticleContainer *tracks, double min_trk_pt) const
std::pair< float, float > getOneOverPOfCluster(const HGTD::Cluster< const xAOD::TrackParticle * > &cluster) const
SG::ReadHandleKey< xAOD::VertexContainer > m_primVxCont_key
Gaudi::Property< float > m_bdt_cutvalue
std::pair< float, float > getZOfCluster(const HGTD::Cluster< const xAOD::TrackParticle * > &cluster) const
HGTD::Cluster< const xAOD::TrackParticle * > getHScluster(const EventContext &ctx, const std::vector< HGTD::Cluster< const xAOD::TrackParticle * > > &clusters, const xAOD::Vertex *vertex) const
bool passTrackVertexAssociation(const xAOD::TrackParticle *track, const xAOD::Vertex *vertex, double min_trk_pt, const double significance_cut=2.5) const
std::vector< HGTD::Cluster< const xAOD::TrackParticle * > > clusterTracksInTime(const EventContext &ctx, const std::vector< const xAOD::TrackParticle * > &tracks, double cluster_distance) const
SG::WriteDecorHandleKey< xAOD::VertexContainer > m_vxTimeRes_key
VertexTimeAlg(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< float > m_default_vxTimeRes
float scoreCluster(const EventContext &ctx, const HGTD::Cluster< const xAOD::TrackParticle * > &cluster, const xAOD::Vertex *vertex) const
SG::ReadDecorHandleKey< xAOD::TrackParticleContainer > m_trackValidTime_key
SG::ReadDecorHandleKey< xAOD::TrackParticleContainer > m_trackTime_key
SG::WriteDecorHandleKey< xAOD::VertexContainer > m_vxHasTime_key
StatusCode initialize() override final
float getSumPt2OfCluster(const HGTD::Cluster< const xAOD::TrackParticle * > &cluster) const
SG::ReadDecorHandleKey< xAOD::TrackParticleContainer > m_trackTimeRes_key
SG::WriteDecorHandleKey< xAOD::VertexContainer > m_vxTime_key
StatusCode execute(const EventContext &ctx) const override final
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
Handle class for reading a decoration on an object.
const_pointer_type cptr()
Dereference the pointer.
Handle class for adding a decoration to an object.
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
@ PriVtx
Primary vertex.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Vertex_v1 Vertex
Define the latest version of the vertex class.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".