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