ATLAS Offline Software
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 
16 unsigned 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 
60 namespace ActsTrk {
61 
62 namespace ScoreBasedSolverCutsImpl {
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
157 void 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
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
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
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
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
TrackSummaryContainer.h
ActsTrk::TrackContainer
Definition: TrackContainer.h:30
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
ActsTrk::ScoreBasedSolverCutsImpl::innermostPixelLayerHitsScore
void innermostPixelLayerHitsScore(const trackProxy_t &track, double &score)
Score modifier for tracks based on innermost pixel layer hits.
Definition: ScoreBasedSolverCutsImpl.cxx:185
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
ConvertOldUJHistosToNewHistos.etaBins
list etaBins
Definition: ConvertOldUJHistosToNewHistos.py:145
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
skel.it
it
Definition: skel.GENtoEVGEN.py:407
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
PUfitVar::maxEta
constexpr float maxEta
Definition: GepMETPufitAlg.cxx:13
ActsTrk::ScoreBasedSolverCutsImpl::trackContainer_t
Acts::TrackContainer< Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, Acts::detail::ValueHolder > trackContainer_t
Definition: ScoreBasedSolverCutsImpl.h:17
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
ScoreBasedSolverCutsImpl.h
xAOD::etaBin
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner setEtaMap etaBin
Definition: L2StandAloneMuon_v1.cxx:149
lumiFormat.i
int i
Definition: lumiFormat.py:85
ActsTrk::ScoreBasedSolverCutsImpl::addSummaryInformation
trackContainer_t addSummaryInformation(const ActsTrk::TrackContainer &trackContainer)
Adds summary information to the track container.
Definition: ScoreBasedSolverCutsImpl.cxx:66
python.TrackLeptonConfig.trackContainer
string trackContainer
Definition: TrackLeptonConfig.py:23
ActsTrk::ScoreBasedSolverCutsImpl::trackProxy_t
typename trackContainer_t::ConstTrackProxy trackProxy_t
Definition: ScoreBasedSolverCutsImpl.h:18
ActsTrk::ScoreBasedSolverCutsImpl::nSCTPixelHitsScore
void nSCTPixelHitsScore(const trackProxy_t &track, double &score)
Score modifier for tracks based on number of SCT and pixel hits.
Definition: ScoreBasedSolverCutsImpl.cxx:256
ActsTrk::ScoreBasedSolverCutsImpl::doubleHolesScore
void doubleHolesScore(const trackProxy_t &track, double &score)
Filter for tracks based on double holes.
Definition: ScoreBasedSolverCutsImpl.cxx:157
xAOD::score
@ score
Definition: TrackingPrimitives.h:514
LArCellBinning.step
step
Definition: LArCellBinning.py:158
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MSTrackingVolumeBuilder.cxx:24
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
python.CaloScaleNoiseConfig.ts
ts
Definition: CaloScaleNoiseConfig.py:87
ActsTrk::ScoreBasedSolverCutsImpl::etaDependentCuts
bool etaDependentCuts(const trackProxy_t &track)
Filter for tracks based on eta dependent cuts.
Definition: ScoreBasedSolverCutsImpl.cxx:288
remapLayer
unsigned int remapLayer(unsigned int iVolume, unsigned int iLayer)
Definition: ScoreBasedSolverCutsImpl.cxx:16
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
TrackContainer.h
ActsTrk::ScoreBasedSolverCutsImpl::ContribPixelLayersScore
void ContribPixelLayersScore(const trackProxy_t &track, double &score)
Score modifier for tracks based on number of contributing pixel layers.
Definition: ScoreBasedSolverCutsImpl.cxx:215