ATLAS Offline Software
Loading...
Searching...
No Matches
ScoreBasedSolverCutsImpl.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7// ACTS
8#include "Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.hpp"
9#include "Acts/Definitions/Units.hpp"
10#include "Acts/EventData/VectorMultiTrajectory.hpp"
11#include "Acts/EventData/VectorTrackContainer.hpp"
12#include "Acts/Utilities/HashedString.hpp"
15
16unsigned int remapLayer(unsigned int iVolume, unsigned int iLayer) {
17
18 // Barrel region inner + outer
19 if ((iVolume == 9) || (iVolume == 16)) {
20 return iVolume * 100 + iLayer;
21 }
22
23 unsigned int outerEndsCapVolumes[6] = {13, 14, 15, 18, 19, 20};
24
25 // endcap outer
26 if (std::find(std::begin(outerEndsCapVolumes), std::end(outerEndsCapVolumes),
27 iVolume) != std::end(outerEndsCapVolumes)) {
28 return iVolume * 100;
29 }
30
31 unsigned int innerEndsCapVolumes[2] = {8, 10};
32
33 // TODO : check if the bins a re correct.
34 unsigned int layerIDBins[4] = {0, 30, 40, 60};
35
36 // endcap inner
37 // TODO : replace this logic with one that depend on radius.
38 if (std::find(std::begin(innerEndsCapVolumes), std::end(innerEndsCapVolumes),
39 iVolume) != std::end(innerEndsCapVolumes)) {
40 auto it = std::upper_bound(std::begin(layerIDBins), std::end(layerIDBins),
41 iLayer);
42
43 // Handle edge cases
44 if (it == std::begin(layerIDBins)) {
45 // iLayer is less than the first bin (0)
46 return iVolume * 100; // Use the first bin (0)
47 }
48 if (it == std::end(layerIDBins)) {
49 // iLayer is greater than the last bin (100)
50 return iVolume * 100 + (std::size(layerIDBins) - 1); // Use the last bin
51 }
52
53 // iLayer is within the range of layerIDBins
54 std::size_t layerIDBin = std::distance(std::begin(layerIDBins), it) - 1;
55 return iVolume * 100 + layerIDBin;
56 }
57 return 0;
58}
59
60namespace ActsTrk {
61
63// Add the summary information to the track container for OptionalCuts, This
64// likely needs to be moved outside ambiguity resolution
67{
68 Acts::VectorTrackContainer updatedTrackBackend;
69 Acts::VectorMultiTrajectory updatedTrackStateBackend;
70 Acts::TrackContainer<Acts::VectorTrackContainer,
71 Acts::VectorMultiTrajectory,
72 Acts::detail::ValueHolder> updatedTracksContainer( std::move(updatedTrackBackend),
73 std::move(updatedTrackStateBackend) );
74
75 // need centralized function here
76 updatedTracksContainer.ensureDynamicColumns(trackContainer);
77
78 updatedTracksContainer.addColumn<unsigned int>("nInnermostPixelLayerHits");
79 updatedTracksContainer.addColumn<unsigned int>("nSCTDoubleHoles");
80 updatedTracksContainer.addColumn<unsigned int>("nContribPixelLayers");
81
82 for (auto track : trackContainer) {
83 auto iTrack = track.index();
84 auto destProxy = updatedTracksContainer.getTrack(updatedTracksContainer.addTrack());
85 destProxy.copyFrom(trackContainer.getTrack(iTrack));
86 }
87
88 std::vector<unsigned int> pixelBarrelLayerIDs = {9, 16};
89
90 unsigned int innermostPixelVolumeID = 9;
91 unsigned int innermostPixelLayerID = 2;
92
93 for (auto track : updatedTracksContainer) {
94 bool doubleFlag = false;
95 int nDoubleHoles = 0;
96 int nInnermostPixelLayerHits = 0;
97 int nContribPixelLayers = 0;
98
99 std::vector<unsigned int> contribPixelLayers = {};
100
101 for (const auto ts : track.trackStatesReversed()) {
102 if (!ts.hasReferenceSurface()) {
103 continue;
104 }
105
106 if (ts.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) {
107
108 // Check if the volume is the innermost pixel volume
109 // Compute the number of hits in the innermost pixel layer
110 auto iVolume = ts.referenceSurface().geometryId().volume();
111 auto iLayer = ts.referenceSurface().geometryId().layer();
112 // 9 is the volume id for the innermost pixel layer in the barrel
113 if (iVolume == innermostPixelVolumeID) {
114 if (iLayer == innermostPixelLayerID) {
115 nInnermostPixelLayerHits++;
116 }
117 }
118
119 unsigned int remappedLayer = remapLayer(iVolume, iLayer);
120 if (remappedLayer != 0) {
121 contribPixelLayers.push_back(remappedLayer);
122 }
123 }
124
125 std::set<unsigned int> uniqueSet(contribPixelLayers.begin(),
126 contribPixelLayers.end());
127 nContribPixelLayers = uniqueSet.size();
128 // Check if the track state has a hole flag
129 // Compute the number of double holes
130 auto iTypeFlags = ts.typeFlags();
131 if (!iTypeFlags.test(Acts::TrackStateFlag::HoleFlag)) {
132 doubleFlag = false;
133 }
134 if (iTypeFlags.test(Acts::TrackStateFlag::HoleFlag)) {
135 if (doubleFlag) {
136 nDoubleHoles++;
137 doubleFlag = false;
138 } else {
139 doubleFlag = true;
140 }
141 }
142 }
143
144 track.template component<unsigned int>(Acts::hashString(
145 "nInnermostPixelLayerHits")) = nInnermostPixelLayerHits;
146 track.template component<unsigned int>(
147 Acts::hashString("nSCTDoubleHoles")) = nDoubleHoles;
148 track.template component<unsigned int>(
149 Acts::hashString("nContribPixelLayers")) = nContribPixelLayers;
150 }
151
152 return updatedTracksContainer;
153}
154
155// This optionalCut removes tracks that have a number of SCT double holes
156// greater than 2
157void doubleHolesScore(const trackProxy_t &track, double &score) {
158 int iDblHoles = 0;
159 std::vector<double> factorDblHoles;
160
161 const int maxDblHoles = 3;
162 const double goodDblHoles[maxDblHoles + 1] = {1., 0.03, 0.007, 0.0003};
163 const double fakeDblHoles[maxDblHoles + 1] = {1., 0.09, 0.09, 0.008};
164
165 for (int i = 0; i <= maxDblHoles; ++i) {
166 factorDblHoles.push_back(goodDblHoles[i] / fakeDblHoles[i]);
167 }
168
169 Acts::HashedString hash_nMeasSubDet = Acts::hashString("nSCTDoubleHoles");
170 if (track.container().hasColumn(hash_nMeasSubDet)) {
171 iDblHoles = track.component<unsigned int>(hash_nMeasSubDet);
172
173 if (iDblHoles > -1 && maxDblHoles > 0) {
174 if (iDblHoles > maxDblHoles) {
175 score /= (iDblHoles - maxDblHoles + 1); // holes are bad !
176 iDblHoles = maxDblHoles;
177 }
178 score *= factorDblHoles[iDblHoles];
179 }
180 }
181}
182
183// This optional score modifies the score based on the number of hits in the
184// innermost pixel layer
185void innermostPixelLayerHitsScore(const trackProxy_t &track, double &score) {
186 int bLayerHits = 0;
187 const int maxB_LayerHitsITk = 8;
188 auto maxB_LayerHits = maxB_LayerHitsITk;
189 const double blayModi[maxB_LayerHitsITk + 1] = {0.25, 4.0, 4.5, 5.0, 5.5,
190 6.0, 6.5, 7.0, 7.5};
191
192 std::vector<double> factorB_LayerHits;
193
194 for (int i = 0; i <= maxB_LayerHits; ++i)
195 factorB_LayerHits.push_back(blayModi[i]);
196 Acts::HashedString hash_nMeasSubDet =
197 Acts::hashString("nInnermostPixelLayerHits");
198 if (track.container().hasColumn(hash_nMeasSubDet)) {
199 bLayerHits = track.component<unsigned int>(hash_nMeasSubDet);
200 } else {
201 return;
202 }
203
204 if (bLayerHits > -1 && maxB_LayerHits > 0) {
205 if (bLayerHits > maxB_LayerHits) {
206 score *= (bLayerHits - maxB_LayerHits + 1); // hits are good !
207 bLayerHits = maxB_LayerHits;
208 }
209 score *= factorB_LayerHits[bLayerHits];
210 }
211}
212
213// This optional score modifies the score based on the number of contributing
214// pixel layers
215void ContribPixelLayersScore(const trackProxy_t &track, double &score) {
216
217 const int maxPixLay = 16;
218 double maxScore = 30.0;
219 double minScore = 5.00;
220 int maxBarrel = 10;
221 int minBarrel = 3;
222 int minEnd = 5;
223
224 std::vector<double> factorPixLay;
225
226 double step[2] = {(maxScore - minScore) / (maxBarrel - minBarrel),
227 (maxScore - minScore) / (maxPixLay - minEnd)};
228
229 for (int i = 0; i <= maxPixLay; i++) {
230 if (i < minEnd)
231 factorPixLay.push_back(0.01 + (i * 0.33));
232 else
233 factorPixLay.push_back(minScore + ((i - minEnd) * step[1]));
234 }
235
236 int iPixLay = 0;
237
238 Acts::HashedString hash_nMeasSubDet = Acts::hashString("nContribPixelLayers");
239 if (track.container().hasColumn(hash_nMeasSubDet)) {
240 iPixLay = track.component<unsigned int>(hash_nMeasSubDet);
241 } else {
242 return;
243 }
244
245 if (iPixLay > -1 && maxPixLay > 0) {
246 if (iPixLay > maxPixLay) {
247 score *= (iPixLay - maxPixLay + 1); // layers are good !
248 iPixLay = maxPixLay;
249 }
250 score *= factorPixLay[iPixLay];
251 }
252}
253
254// This optional score modifies the score based on the number of SCT and pixel
255// hits
256void nSCTPixelHitsScore(const trackProxy_t &track, double &score) {
257
258 const int maxHits = 26;
259 double maxScore = 40.0;
260 double minScore = 5.00;
261 int maxBarrel = 25;
262 int minBarrel = 9;
263 int minEnd = 12;
264
265 int iHits = track.nMeasurements(); // This includes SCT, Pixel and HGTD hits
266
267 std::vector<double> factorHits;
268
269 double step[2] = {(maxScore - minScore) / (maxBarrel - minBarrel),
270 (maxScore - minScore) / (maxHits - minEnd)};
271
272 for (int i = 0; i <= maxHits; i++) {
273 if (i < minEnd)
274 factorHits.push_back(0.01 + (i * 1.0 / minEnd));
275 else
276 factorHits.push_back(minScore + ((i - minEnd) * step[1]));
277 }
278 if (iHits > -1 && maxHits > 0) {
279 if (iHits > maxHits) {
280 score *= (iHits - maxHits + 1); // hits are good !
281 iHits = maxHits;
282 }
283 score *= factorHits[iHits];
284 }
285}
286
287// This optional cut removes tracks based on the eta dependent cuts
288bool etaDependentCuts(const trackProxy_t &track) {
289 auto eta = Acts::VectorHelpers::eta(track.momentum());
290 auto parm = track.parameters();
291
292 std::vector<double> etaBins = {-4.0, -2.6, -2.0, 0.0, 2.0, 2.6, 4.0};
293 std::vector<double> maxD0 = {10.0, 2.0, 2.0, 2.0, 2.0, 10.0};
294 std::vector<double> maxZ0 = {200, 200, 200, 200, 200, 200};
295 std::vector<unsigned int> maxDoubleHoles = {2, 2, 2, 2, 2, 2};
296 std::vector<unsigned int> minSiClusters = {9, 8, 4, 4, 8, 9};
297
298 double maxEta = 4.0;
299
300 auto it = std::upper_bound(etaBins.begin(), etaBins.end(), eta);
301 if (it == etaBins.begin() || it == etaBins.end()) {
302 return false; // eta out of range
303 }
304 std::size_t etaBin = std::distance(etaBins.begin(), it) - 1;
305
306 if (std::abs(eta) > maxEta) {
307 return true;
308 }
309
310 if (std::abs(parm[Acts::BoundIndices::eBoundLoc1]) > maxZ0[etaBin]) {
311 return true;
312 }
313
314 if (std::abs(parm[Acts::BoundIndices::eBoundLoc0]) > maxD0[etaBin]) {
315 return true;
316 }
317
318 unsigned int numSiClusters = track.nMeasurements();
319
320 if (numSiClusters < minSiClusters[etaBin]) {
321 return true;
322 }
323
324 unsigned int numSCTDoubleHoles = 0;
325 Acts::HashedString hash_nMeasSubDet = Acts::hashString("nSCTDoubleHoles");
326 if (track.container().hasColumn(hash_nMeasSubDet)) {
327 numSCTDoubleHoles = track.component<unsigned int>(hash_nMeasSubDet);
328 }
329
330 if (numSCTDoubleHoles > maxDoubleHoles[etaBin]) {
331 return true;
332 }
333
334 return false;
335}
336
337} // namespace ScoreBasedSolverCutsImpl
338
339} // namespace ActsTrk
Scalar eta() const
pseudorapidity method
unsigned int remapLayer(unsigned int iVolume, unsigned int iLayer)
int ts
Definition globals.cxx:24
void innermostPixelLayerHitsScore(const trackProxy_t &track, double &score)
Score modifier for tracks based on innermost pixel layer hits.
bool etaDependentCuts(const trackProxy_t &track)
Filter for tracks based on eta dependent cuts.
Acts::TrackContainer< Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, Acts::detail::ValueHolder > trackContainer_t
typename trackContainer_t::ConstTrackProxy trackProxy_t
void nSCTPixelHitsScore(const trackProxy_t &track, double &score)
Score modifier for tracks based on number of SCT and pixel hits.
void doubleHolesScore(const trackProxy_t &track, double &score)
Filter for tracks based on double holes.
void ContribPixelLayersScore(const trackProxy_t &track, double &score)
Score modifier for tracks based on number of contributing pixel layers.
trackContainer_t addSummaryInformation(const ActsTrk::TrackContainer &trackContainer)
Adds summary information to the track container.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...