ATLAS Offline Software
Loading...
Searching...
No Matches
InDetTrackSelectionTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
9#include "InDetAccessor.h"
10
11#ifndef XAOD_ANALYSIS
13#include "TrkTrack/Track.h"
14#include "VxVertex/Vertex.h"
17#endif
18
19#include <memory>
20#include <array>
21
22using namespace InDetAccessor;
23
24namespace {
25 template <unsigned int n_summary_types>
26 std::array<xAOD::SummaryType, n_summary_types> summaryArray( std::array<xAOD::SummaryType, n_summary_types> summary_types) {return summary_types; }
27
28 template <class Trk_Helper, unsigned int n_summary_types>
29 class MinTRTHitsCut {
30 public:
31 MinTRTHitsCut( double maxTrtEtaAcceptance,
32 double maxEtaForTrtHitCuts,
33 int min_n_hits,
34 std::array<xAOD::SummaryType, n_summary_types> summary_types)
35 : m_maxTrtEtaAcceptance(maxTrtEtaAcceptance),
36 m_maxEtaForTrtHitCuts(maxEtaForTrtHitCuts),
37 m_minNHits(min_n_hits),
38 m_summaryTypes(summary_types)
39 {}
40
41 uint8_t nHits(Trk_Helper helper, const asg::AsgMessaging &msgHelper) const {
42 return getSummarySum(helper,msgHelper,m_summaryTypes);
43 }
44 bool operator()(Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
45 double absEta = std::abs( helper.eta( msgHelper) );
46 return (absEta <= m_maxTrtEtaAcceptance || absEta > m_maxEtaForTrtHitCuts) || nHits(helper,msgHelper) >=m_minNHits;
47 }
48 private:
49 double m_maxTrtEtaAcceptance;
50 double m_maxEtaForTrtHitCuts;
51 int m_minNHits;
52 std::array<xAOD::SummaryType, n_summary_types> m_summaryTypes;
53 };
54
55 // return the first bin whose value is lower or equal than the given value
56 // the bins have to be in ascending order;
57 template <typename T>
58 unsigned int findBin(const std::vector<T> &bins, T value) {
59 if (bins.empty() || bins[0]>value) return bins.size();
60 unsigned int bin_i=bins.size();
61 while ( value < bins[--bin_i]) {};
62 return bin_i;
63 }
64 // return true if the given bins are in ascending order
65 template <typename T>
66 bool checkOrder(const std::vector<T> &bins) {
67 if (bins.empty()) return true;
68 for (unsigned int bin_i=1; bin_i<bins.size(); ++bin_i) {
69 if (bins[bin_i-1]>=bins[bin_i]) return false;
70 }
71 return true;
72 }
73}
74
75InDet::InDetTrackSelectionTool::InDetTrackSelectionTool(const std::string& name)
76 : asg::AsgTool(name)
77 , m_acceptInfo( "InDetTrackSelection" )
78#ifndef XAOD_ANALYSIS
79#endif // XAOD_ANALYSIS
80{
81
82 // set the cut selection: default is "no cut"
83 setCutLevelPrivate(InDet::CutLevel::NoCut);
84
85#ifndef XAOD_STANDALONE
86 declareInterface<IInDetTrackSelectionTool>(this);
87#endif
88
89}
90
91// we must define the destructor in order to use forward-declaration with unique_ptr
93
104 // Make sure we haven't already been initialized - this would be a sign of improper usage.
105 if (m_isInitialized) {
106 ATH_MSG_ERROR( "Tool has already been initialized. This is illegitimate." );
107 ATH_MSG_ERROR( "This call to initialize() will do nothing." );
108 return StatusCode::SUCCESS;
109 }
110
111 // Greet the user:
113
114 // if the CutLevel string is set to something recognizable,
115 // then do a soft set on the cuts (i.e. not overwriting those already set)
116 if (!m_cutLevel.empty()) {
117 std::unordered_map<std::string, InDet::CutLevel>::const_iterator it_mapCutLevel = s_mapCutLevel.find(m_cutLevel);
118 if ( it_mapCutLevel == s_mapCutLevel.end() ) {
119 ATH_MSG_ERROR( "The string \"" << m_cutLevel << "\" is not recognized as a cut level. No cuts will be changed." );
120 ATH_MSG_ERROR( "Cut level options are:" );
121 for (const auto& opt : s_mapCutLevel) {
122 ATH_MSG_ERROR( "\t" << opt.first );
123 }
124 } else {
125 ATH_MSG_DEBUG( "Cut level set to \"" << it_mapCutLevel->first << "\"." );
126 ATH_MSG_DEBUG( "This will not overwrite other cuts that have been set.");
127 setCutLevelPrivate( it_mapCutLevel->second, false );
128 }
129 }
130
131#ifndef XAOD_ANALYSIS
132 if (m_initTrkTools) {
134 if (!m_trackSumTool.empty()) {
135 ATH_CHECK( m_trackSumTool.retrieve() );
136 ATH_MSG_DEBUG( "Track summary tool retrieved." );
138 }
139 ATH_CHECK( m_extrapolator.retrieve() );
140 ATH_MSG_DEBUG( "Retrieved tool " << m_extrapolator );
141 } else {
142 m_extrapolator.disable();
143 m_trackSumTool.disable();
144 }
145#endif // XAOD_ANALYSIS
146
147 // Need messaging helper for cut functions
148 m_msgHelper = std::make_unique<asg::AsgMessaging>(this) ;
149
150
151#ifndef XAOD_ANALYSIS
152 // setup cut functions for Trk::Tracks
155#else
157#endif
158 // setup cut functions for xAOD::TrackParticles
159 for (const auto& cutFamily : m_trackParticleCuts) {
160 const std::string& cutFamilyName = cutFamily.first;
161 // lock(m_mutex) is not needed because this is inside of non-const initialize method.
162 m_numTracksPassedCuts.push_back(0);
163 if (m_acceptInfo.addCut( cutFamilyName, "Selection of tracks according to " + cutFamilyName ) < 0) {
164 ATH_MSG_ERROR( "Failed to add cut family " << cutFamilyName << " because the TAccept object is full." );
165 return StatusCode::FAILURE;
166 }
167 ATH_MSG_VERBOSE("Adding cut family " << cutFamilyName);
168 }
169
170 m_isInitialized = true;
171
172 return StatusCode::SUCCESS;
173}
174
175namespace {
176 template <typename T>
177 inline T sqr(T a) { return a *a;}
178}
179template <int VERBOSE, class Trk_Helper>
180StatusCode InDet::InDetTrackSelectionTool::setupCuts(std::map< std::string, std::vector< std::function<bool(Trk_Helper helper, const asg::AsgMessaging &msgHelper)> > > &trackCuts) {
181 // track parameter cuts
182 if (m_minPt > 0.) {
183 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum Pt: " << m_minPt << " MeV" );
184 trackCuts["Pt"].push_back( [minPt = m_minPt](Trk_Helper helper, const asg::AsgMessaging &msgHelper) -> bool { return helper.pt(msgHelper) >= minPt; } );
185 }
187 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum |Eta|: " << m_maxAbsEta );
188 trackCuts["Eta"].push_back( [maxAbsEta = m_maxAbsEta](Trk_Helper helper, const asg::AsgMessaging &msgHelper) { return std::abs(helper.eta(msgHelper)) <= maxAbsEta; } );
189 }
190 if (m_minP > 0.) {
191 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum P: " << m_minP << " MeV" );
192 trackCuts["P"].push_back( [maxInvP = 1./m_minP](Trk_Helper helper, const asg::AsgMessaging &msgHelper) { return std::abs(helper.qOverP(msgHelper)) <= maxInvP; } );
193 }
194 if (maxDoubleIsSet(m_maxD0)) {
195 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum d0: " << m_maxD0 << " mm" );
196 trackCuts["D0"].push_back( [maxD0 = m_maxD0](Trk_Helper helper, const asg::AsgMessaging &msgHelper) { return std::abs(helper.d0(msgHelper)) <= maxD0; } );
197 }
198 if (maxDoubleIsSet(m_maxZ0)) {
199 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum z0: " << m_maxZ0 << " mm");
200 trackCuts["Z0"].push_back( [maxZ0 = m_maxZ0](Trk_Helper helper, const asg::AsgMessaging &msgHelper) { return std::abs(helper.z0(msgHelper)) <= maxZ0; } );
201 }
203 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum z0*sin(theta): " << m_maxZ0SinTheta << " mm" );
204 trackCuts["Z0SinTheta"].push_back([maxZ0SinTheta = m_maxZ0SinTheta](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
205 return std::abs( helper.z0(msgHelper) * std::sin(helper.theta(msgHelper))) <= maxZ0SinTheta;
206 });
207 }
209 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum uncertainty on d0: " << m_maxSigmaD0 << " mm" );
210 trackCuts["D0"].push_back([maxSigmaD0Squared = sqr(m_maxSigmaD0.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
211 return getDefiningParametersCov(helper,msgHelper, InDetAccessor::d0,InDetAccessor::d0) <= maxSigmaD0Squared;
212 });
213 }
215 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum uncertainty on z0: " << m_maxSigmaZ0 << " mm" );
216 trackCuts["Z0"].push_back([maxSigmaZ0Squared = sqr(m_maxSigmaZ0.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
217 return getDefiningParametersCov(helper,msgHelper, InDetAccessor::z0,InDetAccessor::z0) <= maxSigmaZ0Squared;
218 });
219 }
221 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum uncertainty on z0*sin(theta): "
222 << m_maxSigmaZ0SinTheta << " mm" );
223 trackCuts["Z0SinTheta"].push_back([maxSigmaZ0SinThetaSquared = sqr(m_maxSigmaZ0SinTheta.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
224 double theta = helper.theta(msgHelper);
225 double sinTheta = std::sin(theta);
226 double cosTheta = std::cos(theta);
227 double z0 = helper.z0(msgHelper);
228
229 return ( sqr(z0)*sqr(cosTheta) * getDefiningParametersCov(helper,msgHelper, InDetAccessor::theta,InDetAccessor::theta)
230 + 2*z0 *sinTheta*cosTheta * getDefiningParametersCov(helper,msgHelper, InDetAccessor::theta,InDetAccessor::z0)
231 + sqr(sinTheta) * getDefiningParametersCov(helper,msgHelper, InDetAccessor::z0, InDetAccessor::z0) ) <= maxSigmaZ0SinThetaSquared;
232 });
233 }
235 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum significance on d0: " << m_maxD0overSigmaD0 );
236 trackCuts["D0"].push_back([maxD0overSigmaD0Squared = sqr(m_maxD0overSigmaD0.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
237 return sqr(helper.d0(msgHelper)) <= maxD0overSigmaD0Squared * getDefiningParametersCov(helper,msgHelper, InDetAccessor::d0,InDetAccessor::d0);
238 });
239 }
241 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum significance on z0: " << m_maxZ0overSigmaZ0 );
242 trackCuts["Z0"].push_back([maxZ0overSigmaZ0Squared = sqr(m_maxZ0overSigmaZ0.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) -> bool {
243 return sqr(helper.z0(msgHelper)) <= maxZ0overSigmaZ0Squared * getDefiningParametersCov(helper,msgHelper, InDetAccessor::z0,InDetAccessor::z0);
244 });
245 }
247 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum significance on z0*sin(theta): "
249 trackCuts["Z0SinTheta"].push_back([maxZ0SinThetaoverSigmaZ0SinThetaSquared = sqr(m_maxZ0SinThetaoverSigmaZ0SinTheta.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
250
251 double theta = helper.theta(msgHelper);
252 double sinTheta = std::sin(theta);
253 double cosTheta = std::cos(theta);
254 double z0 = helper.z0(msgHelper);
255
256 return sqr(z0*sinTheta) <=
257 maxZ0SinThetaoverSigmaZ0SinThetaSquared * ( sqr(z0)*sqr(cosTheta) * getDefiningParametersCov(helper,msgHelper, InDetAccessor::theta,InDetAccessor::theta)
258 + 2*z0 *sinTheta*cosTheta * getDefiningParametersCov(helper,msgHelper, InDetAccessor::theta,InDetAccessor::z0)
259 + sqr(sinTheta) * getDefiningParametersCov(helper,msgHelper, InDetAccessor::z0, InDetAccessor::z0));
260 });
261 }
262
263 // hit cuts
264 if (m_minNInnermostLayerHits > 0) {
265 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum hits from innermost pixel layer: " << m_minNInnermostLayerHits );
266 if constexpr(VERBOSE>0) ATH_MSG_INFO( " (Track will pass if no hit is expected.)" );
267 trackCuts["InnermostLayersHits"].push_back([minNInnermostLayerHits = m_minNInnermostLayerHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
268 return ( getSummary(helper, msgHelper, xAOD::numberOfInnermostPixelLayerHits) >= minNInnermostLayerHits
269 || getSummary(helper, msgHelper, xAOD::expectInnermostPixelLayerHit) == 0);
270 });
271 }
273 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum hits from next to innermost pixel layer: " << m_minNNextToInnermostLayerHits );
274 if constexpr(VERBOSE>0) ATH_MSG_INFO( " (Track will pass if no hit is expected.)" );
275 trackCuts["InnermostLayersHits"].push_back([minNNextToInnermostLayerHits = m_minNNextToInnermostLayerHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
276 return ( getSummary(helper, msgHelper, xAOD::numberOfNextToInnermostPixelLayerHits) >= minNNextToInnermostLayerHits
277 || getSummary(helper, msgHelper, xAOD::expectNextToInnermostPixelLayerHit) == 0);
278 });
279 }
281 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum hits from both innermost pixel layers: " << m_minNBothInnermostLayersHits );
282 if constexpr(VERBOSE>0) ATH_MSG_INFO( " (If a layer has no hits but one is not expected, the" );
283 if constexpr(VERBOSE>0) ATH_MSG_INFO( " number of hits in that layer will be taken to be 1.)" );
285 ATH_MSG_WARNING( "A value of minNBothInnermostLayersHits above 2 does not make sense." );
286 ATH_MSG_WARNING( " Use 1 for \"or\" or 2 for \"and\"." );
287 }
288 trackCuts["InnermostLayersHits"].push_back([minNBothInnermostLayersHits = m_minNBothInnermostLayersHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
289 return ( std::max( getSummary(helper, msgHelper, xAOD::numberOfInnermostPixelLayerHits),
290 static_cast<uint8_t>( !getSummary(helper, msgHelper, xAOD::expectInnermostPixelLayerHit) ))
291 +std::max( getSummary(helper, msgHelper, xAOD::numberOfNextToInnermostPixelLayerHits),
292 static_cast<uint8_t>( !getSummary(helper, msgHelper, xAOD::expectNextToInnermostPixelLayerHit )))
293 >= minNBothInnermostLayersHits);
294 });
295 }
296 if (m_useMinBiasInnermostLayersCut > 0 ) { // less than zero indicates this cut is manually turned off
297 if constexpr(VERBOSE>0) ATH_MSG_INFO( " An innermost layer hit is required if expected, otherwise" );
298 if constexpr(VERBOSE>0) ATH_MSG_INFO( " a next-to-innermost layer hit is required if it is expected." );
299 trackCuts["InnermostLayersHits"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
300 uint8_t expected_innermost_pixel_layer_hit = getSummary(helper, msgHelper, xAOD::expectInnermostPixelLayerHit);
301 return (expected_innermost_pixel_layer_hit > 0 && getSummary(helper, msgHelper, xAOD::numberOfInnermostPixelLayerHits)>=1)
302 || (expected_innermost_pixel_layer_hit == 0 && ( getSummary(helper, msgHelper, xAOD::expectNextToInnermostPixelLayerHit)==0
304 });
305 }
307 if constexpr(VERBOSE>0) ATH_MSG_INFO( " An innermost layer hit or next-to-innermost layer hit is required. If there are" );
308 if constexpr(VERBOSE>0) ATH_MSG_INFO( " no innermost layer or next-to-innermost layer hits, then zero expected" );
309 if constexpr(VERBOSE>0) ATH_MSG_INFO( " next-to-innermost layer hits is required." );
310 trackCuts["InnermostLayersHits"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
311 return (getSummary(helper, msgHelper, xAOD::numberOfInnermostPixelLayerHits)>=1)
313 || (getSummary(helper, msgHelper, xAOD::expectNextToInnermostPixelLayerHit)==0);
314 });
315 }
317 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum shared hits in innermost pixel layer: " << m_maxNInnermostLayerSharedHits );
318 trackCuts["InnermostLayersHits"].push_back([maxNInnermostLayerSharedHits = m_maxNInnermostLayerSharedHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
319 return getSummary(helper, msgHelper, xAOD::numberOfInnermostPixelLayerSharedHits) <= maxNInnermostLayerSharedHits;
320 });
321 }
322 if (m_minNPixelHits > 0) {
323 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum pixel hits: " << m_minNPixelHits );
324 trackCuts["PixelHits"].push_back( [minNPixelHits = m_minNPixelHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
325 return getSummarySum<2,Trk_Helper>(helper, msgHelper, {xAOD::numberOfPixelHits,xAOD::numberOfPixelDeadSensors}) >= minNPixelHits;
326 });
327 }
328 if (m_minNPixelHitsPhysical > 0) {
329 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum physical pixel hits (i.e. dead sensors do not count): "
331 trackCuts["PixelHits"].push_back([minNPixelHitsPhysical = m_minNPixelHitsPhysical](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
332 return getSummary(helper, msgHelper, xAOD::numberOfPixelHits) >= minNPixelHitsPhysical;
333 });
334 }
336 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum pixel holes: " << m_maxNPixelHoles );
337 trackCuts["PixelHits"].push_back([maxNPixelHoles = m_maxNPixelHoles](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
338 return getSummary(helper, msgHelper, xAOD::numberOfPixelHoles) <= maxNPixelHoles;
339 });
340 }
342 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum pixel shared hits: " << m_maxNPixelSharedHits );
343 trackCuts["PixelHits"].push_back([maxNPixelSharedHits = m_maxNPixelSharedHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
344 return getSummary(helper, msgHelper, xAOD::numberOfPixelSharedHits) <= maxNPixelSharedHits;
345 });
346 }
347 if (m_minNSctHits > 0) {
348 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum SCT hits: " << m_minNSctHits );
349 trackCuts["SctHits"].push_back( [minNSctHits = m_minNSctHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
350 return getSummarySum<2,Trk_Helper>(helper, msgHelper, {xAOD::numberOfSCTHits, xAOD::numberOfSCTDeadSensors}) >= minNSctHits;
351 });
352 }
353 if (m_minNSctHitsPhysical > 0) {
354 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum physical SCT hits (i.e. dead sensors do not count): "
356 trackCuts["SctHits"].push_back([minNSctHitsPhysical = m_minNSctHitsPhysical](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
357 return getSummary(helper, msgHelper, xAOD::numberOfSCTHits) >= minNSctHitsPhysical;
358 });
359 }
361 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum SCT holes: " << m_maxNSctHoles );
362 trackCuts["SctHits"].push_back([maxNSctHoles = m_maxNSctHoles](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
363 return getSummary(helper, msgHelper, xAOD::numberOfSCTHoles) <= maxNSctHoles;
364 });
365 }
367 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum SCT shared hits: " << m_maxNSctSharedHits );
368 trackCuts["SctHits"].push_back([maxNSctSharedHits = m_maxNSctSharedHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
369 return getSummary(helper, msgHelper, xAOD::numberOfSCTSharedHits) <= maxNSctSharedHits;
370 });
371 }
373 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum SCT double holes: " << m_maxNSctDoubleHoles );
374 trackCuts["SctHits"].push_back([maxNSctDoubleHoles = m_maxNSctDoubleHoles](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
375 return getSummary(helper, msgHelper, xAOD::numberOfSCTDoubleHoles) <= maxNSctDoubleHoles ;
376 });
377 }
378 if (m_minNSiHits > 0) {
379 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum silicon (pixel + SCT) hits: " << m_minNSiHits );
380 trackCuts["SiHits"].push_back([minNSiHits = m_minNSiHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
381 return getSummarySum<4,Trk_Helper>(helper, msgHelper, {xAOD::numberOfPixelHits,
384 xAOD::numberOfSCTDeadSensors} ) >= minNSiHits ;
385 });
386 }
387 if (m_minNSiHitsPhysical > 0) {
388 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum physical silicon hits (i.e. dead sensors do not count): "
390 trackCuts["SiHits"].push_back([minNSiHitsPhysical = m_minNSiHitsPhysical](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
391 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHits, xAOD::numberOfSCTHits} ) >= minNSiHitsPhysical ;
392 });
393 }
395 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum silicon holes: " << m_maxNSiHoles );
396 trackCuts["SiHits"].push_back([maxNSiHoles = m_maxNSiHoles](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
397 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHoles, xAOD::numberOfSCTHoles} ) <= maxNSiHoles ;
398 });
399 }
401 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum silicon shared hits: " << m_maxNSiSharedHits );
402 trackCuts["SiHits"].push_back([maxNSiSharedHits = m_maxNSiSharedHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
403 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelSharedHits, xAOD::numberOfSCTSharedHits} ) <= maxNSiSharedHits ;
404 });
405 }
407 if constexpr(VERBOSE>0) ATH_MSG_INFO( " No more than one shared module:" );
408 if constexpr(VERBOSE>0) ATH_MSG_INFO( " i.e. max 1 shared pixel hit or" );
409 if constexpr(VERBOSE>0) ATH_MSG_INFO( " 2 shared SCT hits, and not both." );
410 trackCuts["SiHits"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
411 return getSummary(helper, msgHelper,xAOD::numberOfPixelSharedHits )
412 + getSummary(helper, msgHelper,xAOD::numberOfSCTSharedHits )/2 <= 1 ;
413 });
414 }
416 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum silicon hits if the track has shared hits: "
418 trackCuts["SiHits"].push_back([minNSiHitsIfSiSharedHits = m_minNSiHitsIfSiSharedHits](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
423 xAOD::numberOfSCTDeadSensors}) >=minNSiHitsIfSiSharedHits;
424 });
425 }
428 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Require " << m_minNSiHitsAboveEtaCutoff
429 << " silicon hits above eta = " << m_minEtaForStrictNSiHitsCut );
430 trackCuts["SiHits"].push_back([minEtaForStrictNSiHitsCut = m_minEtaForStrictNSiHitsCut,
431 minNSiHitsAboveEtaCutoff = m_minNSiHitsAboveEtaCutoff](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
432 return std::abs(helper.eta(msgHelper)) <= minEtaForStrictNSiHitsCut
436 xAOD::numberOfSCTDeadSensors}) >= minNSiHitsAboveEtaCutoff;
437 });
438 }
440 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Zero pixel holes allowed, except one pix hole is allowed if there is a physical IBL hit and a BLayer hit is expected but there is no BLayer hit." );
441 trackCuts["PixHits"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
442 uint8_t pixel_holes = getSummary(helper, msgHelper,xAOD::numberOfPixelHoles);
443 return pixel_holes == 0 || ( pixel_holes<=1 && getSummary(helper, msgHelper,xAOD::numberOfInnermostPixelLayerHits) >= 1
445 && getSummary(helper, msgHelper,xAOD::numberOfNextToInnermostPixelLayerHits) == 0 );
446 });
447 }
448#ifndef XAOD_ANALYSIS
449 if (m_minNSiHitsMod > 0) {
450 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum modified Si hits (2*pix + sct) (does not include dead sensors)= "
451 << m_minNSiHitsMod );
452 trackCuts["SiHits"].push_back([minNSiHitsMod = m_minNSiHitsMod](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
454 xAOD::numberOfPixelHits, // pixel hits count twice in this definition
455 xAOD::numberOfSCTHits}) >= minNSiHitsMod;
456 });
457 }
459 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum modified Si hits in top half = "
461 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum modified Si hits in bottom half = "
463 trackCuts["SiHits"].push_back([minNSiHitsModTop = m_minNSiHitsModTop,
464 minNSiHitsModBottom = m_minNSiHitsModBottom](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
465 auto [top,bottom] = getSiHitsTopBottom(helper, msgHelper);
466 return top >= minNSiHitsModTop && bottom >= minNSiHitsModBottom;
467 });
468 }
469#endif
471 if constexpr(VERBOSE>0) ATH_MSG_INFO( " -- TRT hit cuts applied above eta = " << m_maxTrtEtaAcceptance
472 << " and below eta = " << m_maxEtaForTrtHitCuts << " --" );
473 if (m_minNTrtHits > 0) {
474 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance: " << m_minNTrtHits );
475 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,1>( m_maxTrtEtaAcceptance, m_maxEtaForTrtHitCuts, m_minNTrtHits,
477 }
479 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance including outliers: " << m_minNTrtHitsPlusOutliers );
480 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,2>( m_maxTrtEtaAcceptance,m_maxEtaForTrtHitCuts, m_minNTrtHitsPlusOutliers,
482 }
484 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance above high energy threshold: "
486 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,1>( m_maxTrtEtaAcceptance,m_maxEtaForTrtHitCuts, m_minNTrtHighThresholdHits,
488 }
490 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance above high energy threshold including outliers: "
492 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,2>( m_maxTrtEtaAcceptance,m_maxEtaForTrtHitCuts, m_minNTrtHighThresholdHitsPlusOutliers,
494 }
495 if (maxDoubleIsSet(m_maxTrtHighEFraction)) { // I think this condition could be instead that it is between 0 and 1
496 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum ratio of high threshold to regular TRT hits outside eta acceptance: "
498 trackCuts["TrtHits"].push_back([maxTrtEtaAcceptance = m_maxTrtEtaAcceptance,
499 maxEtaForTrtHitCuts = m_maxEtaForTrtHitCuts,
500 maxTrtHighEFraction = m_maxTrtHighEFraction](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
501 double absEta = std::abs( helper.eta( msgHelper) );
502 return (absEta <= maxTrtEtaAcceptance || absEta > maxEtaForTrtHitCuts)
504 <= maxTrtHighEFraction * getSummary(helper, msgHelper,xAOD::numberOfTRTHits );
505 });
506 }
508 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum ratio of high threshold to regular TRT hits above eta acceptance including outliers: "
510 trackCuts["TrtHits"].push_back([maxTrtEtaAcceptance = m_maxTrtEtaAcceptance,
511 maxEtaForTrtHitCuts = m_maxEtaForTrtHitCuts,
512 maxTrtHighEFractionWithOutliers = m_maxTrtHighEFractionWithOutliers](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
513 double absEta = std::abs( helper.eta( msgHelper) );
514 return (absEta <= maxTrtEtaAcceptance || absEta > maxEtaForTrtHitCuts)
516 <= maxTrtHighEFractionWithOutliers * ( getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfTRTHits, xAOD::numberOfTRTOutliers} ));
517 });
518 }
520 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum fraction of TRT hits that are outliers: " << m_maxTrtOutlierFraction );
521 trackCuts["TrtHits"].push_back([maxTrtEtaAcceptance = m_maxTrtEtaAcceptance,
522 maxEtaForTrtHitCuts = m_maxEtaForTrtHitCuts,
523 maxTrtOutlierFraction = m_maxTrtOutlierFraction](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
524 double absEta = std::abs( helper.eta( msgHelper) );
525 uint8_t trt_outliers = getSummary(helper, msgHelper,xAOD::numberOfTRTOutliers );
526 return ( absEta <= maxTrtEtaAcceptance || absEta > maxEtaForTrtHitCuts)
527 || trt_outliers <= maxTrtOutlierFraction * ( trt_outliers + getSummary(helper, msgHelper,xAOD::numberOfTRTHits) );
528 });
529 }
530 }
531
532 // fit quality cuts
534 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Using pre-defined eta-dependent maximum chi squared (no longer recommended)." );
535 trackCuts["FitQuality"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
536 double eta = helper.eta(msgHelper);
537 double fit_chi_square = getFitChiSquare(helper,msgHelper);
538 double fit_ndof = getFitNDoF(helper,msgHelper);
539 if (std::abs( eta) < 1.9) {
540 return fit_chi_square <= fit_ndof * ( 4.4 + 0.32*sqr(eta) );
541 }
542 else {
543 return fit_chi_square <= fit_ndof * ( 26.9 - 19.6978*std::abs(eta) + 4.4534*sqr(eta) );
544 }
545 });
546 }
548 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum chi squared: " << m_maxChiSq );
549 trackCuts["FitQuality"].push_back([maxChiSq = m_maxChiSq](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
550 return getFitChiSquare(helper,msgHelper) <= maxChiSq;
551 });
552 }
554 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum chi squared per degree of freedom: " << m_maxChiSqperNdf );
555 trackCuts["FitQuality"].push_back([maxChiSqperNdf = m_maxChiSqperNdf](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
556 return getFitChiSquare(helper,msgHelper) <= maxChiSqperNdf * getFitNDoF(helper,msgHelper);
557 });
558 }
559 if (m_minProb > 0.) {
560 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum chi squared probability: " << m_minProb );
561 trackCuts["FitQuality"].push_back([minProb = m_minProb](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
562 return TMath::Prob( getFitChiSquare(helper,msgHelper),getFitNDoF(helper,msgHelper)) >= minProb;
563 });
564 }
566 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum chi-sq probability of " << m_minProbAbovePtCutoff
567 << " above pt of " << m_minPtForProbCut*1e-3 << " GeV." );
568 trackCuts["FitQuality"].push_back([minPtForProbCut = m_minPtForProbCut,
569 minProbAbovePtCutoff = m_minProbAbovePtCutoff](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
570 return helper.pt(msgHelper) <= minPtForProbCut
571 || TMath::Prob( getFitChiSquare(helper,msgHelper),getFitNDoF(helper,msgHelper)) >= minProbAbovePtCutoff;
572 });
573 }
574
575 // dE/dx cuts
576 if (m_minNUsedHitsdEdx > 0) {
577 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum used hits for dEdx: " << m_minNUsedHitsdEdx );
578 trackCuts["dEdxHits"].push_back([minNUsedHitsdEdx = m_minNUsedHitsdEdx](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
579 return getNumberOfUsedHitsdEdx(helper,msgHelper) >= minNUsedHitsdEdx;
580 });
581 }
582 if (m_minNOverflowHitsdEdx > 0) {
583 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum IBL overflow hits for dEdx: " << m_minNOverflowHitsdEdx );
584 trackCuts["dEdxHits"].push_back([minNOverflowHitsdEdx = m_minNOverflowHitsdEdx](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
585 return getNumberOfIBLOverflowsdEdx(helper,msgHelper) >= minNOverflowHitsdEdx;
586 });
587 }
588 if (m_minEProbabilityHT > 0) {
589 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum high threshold electron probability: " << m_minEProbabilityHT );
590 if (m_eProbHTonlyForXe) {
591 if constexpr(VERBOSE>0) ATH_MSG_INFO( " (only applied on tracks where all TRT hits are Xenon)" );
592 trackCuts["eProbHT"].push_back([minEProbabilityHT = m_minEProbabilityHT](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
594 > getSummary(helper, msgHelper, xAOD::numberOfTRTXenonHits)
595 || getEProbabilityHT(helper,msgHelper) >= minEProbabilityHT;
596 });
597 } else {
598 trackCuts["eProbHT"].push_back([minEProbabilityHT = m_minEProbabilityHT](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
599 return getEProbabilityHT(helper,msgHelper) >= minEProbabilityHT;
600 });
601 }
602 }
603
604 if (!m_vecEtaCutoffsForSiHitsCut.empty() || !m_vecMinNSiHitsAboveEta.empty()) {
605 auto cutSize = m_vecEtaCutoffsForSiHitsCut.size();
606 if (cutSize != m_vecMinNSiHitsAboveEta.size()) {
607 ATH_MSG_ERROR( "Eta cutoffs and Silicon hit cuts must be vectors of the same length." );
608 return StatusCode::FAILURE;
609 }
610 if constexpr(VERBOSE>0) {
611 for (size_t i_cut=0; i_cut<cutSize-1; ++i_cut) {
613 << " < eta < " << m_vecEtaCutoffsForSiHitsCut[i_cut+1]
614 << " ,Silicon hits >= " << m_vecMinNSiHitsAboveEta[i_cut] );
615 }
616 }
617 if (!checkOrder(m_vecEtaCutoffsForSiHitsCut.value())) {
618 ATH_MSG_ERROR( "Eta values not in ascending order." );
619 return StatusCode::FAILURE;
620 }
621 if constexpr(VERBOSE>0) ATH_MSG_INFO( " for eta > " << m_vecEtaCutoffsForSiHitsCut[cutSize-1]
622 << " ,Silicon hits >= " << m_vecMinNSiHitsAboveEta[cutSize-1] );
623
624 trackCuts["SiHits"].push_back([p_vecEtaCutoffsForSiHitsCut = &std::as_const(m_vecEtaCutoffsForSiHitsCut.value()),
625 p_vecMinNSiHitsAboveEta = &std::as_const(m_vecMinNSiHitsAboveEta.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
626 double abs_eta = std::abs(helper.eta(msgHelper));
627 unsigned int bin_i = findBin(*p_vecEtaCutoffsForSiHitsCut, abs_eta);
628 return bin_i >= p_vecMinNSiHitsAboveEta->size()
629 || abs_eta>5.0
630 || getSummarySum<4,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHits,
631 xAOD::numberOfSCTHits,
632 xAOD::numberOfPixelDeadSensors,
633 xAOD::numberOfSCTDeadSensors}) >= (*p_vecMinNSiHitsAboveEta)[bin_i];
634 });
635 }
636
637 if (!m_vecEtaCutoffsForPtCut.empty() || !m_vecMinPtAboveEta.empty()) {
638 auto cutSize = m_vecEtaCutoffsForPtCut.size();
639 if (cutSize != m_vecMinPtAboveEta.size()) {
640 ATH_MSG_ERROR( "Eta cutoffs and pT cuts must be vectors of the same length." );
641 return StatusCode::FAILURE;
642 }
643 if constexpr(VERBOSE>0) {
644 for (size_t i_cut=0; i_cut<cutSize-1; ++i_cut) {
645 ATH_MSG_INFO( " for " << m_vecEtaCutoffsForPtCut[i_cut]
646 << " < eta < " << m_vecEtaCutoffsForPtCut[i_cut+1]
647 << " ,transverse momentum >= " << m_vecMinPtAboveEta[i_cut] );
648 }
649 }
650 if (!checkOrder(m_vecEtaCutoffsForPtCut.value())) {
651 ATH_MSG_ERROR( "Eta values not in ascending order." );
652 return StatusCode::FAILURE;
653 }
654 if constexpr(VERBOSE>0) ATH_MSG_INFO( " for eta > " << m_vecEtaCutoffsForPtCut[cutSize-1]
655 << " ,transverse momentum >= " << m_vecMinPtAboveEta[cutSize-1] );
656 trackCuts["Pt"].push_back([p_vecEtaCutoffsForPtCut = &std::as_const(m_vecEtaCutoffsForPtCut.value()),
657 p_vecMinPtAboveEta = &std::as_const(m_vecMinPtAboveEta.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
658 double abs_eta = std::abs(helper.eta(msgHelper));
659 unsigned int bin_i = findBin(*p_vecEtaCutoffsForPtCut, abs_eta);
660 return bin_i >= p_vecMinPtAboveEta->size() || abs_eta > 5.0 || helper.pt(msgHelper) >= (*p_vecMinPtAboveEta)[bin_i];
661 });
662 }
663
664 if (!m_vecPtCutoffsForSctHitsCut.empty() || !m_vecMinNSctHitsAbovePt.empty()) {
665 auto cutSize = m_vecPtCutoffsForSctHitsCut.size();
666 if (cutSize != m_vecMinNSctHitsAbovePt.size()) {
667 ATH_MSG_ERROR( "Pt cutoffs and SCT hit cuts must be vectors of the same length." );
668 return StatusCode::FAILURE;
669 }
670 if constexpr(VERBOSE>0) {
671 for (size_t i_cut=0; i_cut<cutSize-1; ++i_cut) {
672 ATH_MSG_INFO( " for " << m_vecPtCutoffsForSctHitsCut[i_cut]
673 << " < pt < " << m_vecPtCutoffsForSctHitsCut[i_cut+1]
674 << " MeV,\tSCT hits >= " << m_vecMinNSctHitsAbovePt[i_cut] );
675 }
676 }
677 if (!checkOrder(m_vecPtCutoffsForSctHitsCut.value())) {
678 ATH_MSG_ERROR( "Pt values not in ascending order." );
679 return StatusCode::FAILURE;
680 }
681 if constexpr(VERBOSE>0) ATH_MSG_INFO( " for pt > " << m_vecPtCutoffsForSctHitsCut[cutSize-1]
682 << " MeV,\t\tSCT hits >= " << m_vecMinNSctHitsAbovePt[cutSize-1] );
683 trackCuts["SctHits"].push_back([p_vecPtCutoffsForSctHitsCut = &std::as_const(m_vecPtCutoffsForSctHitsCut.value()),
684 p_vecMinNSctHitsAbovePt = &std::as_const(m_vecMinNSctHitsAbovePt.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
685 double pt = helper.pt(msgHelper);
686 unsigned int bin_i = findBin(*p_vecPtCutoffsForSctHitsCut, pt);
687 return bin_i >= p_vecPtCutoffsForSctHitsCut->size()
688 || getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfSCTHits,
689 xAOD::numberOfSCTDeadSensors}) >= (*p_vecMinNSctHitsAbovePt)[bin_i];
690 });
691 }
692
693 if (!m_vecPtCutoffsForZ0SinThetaCut.empty() ||
694 !m_vecEtaCutoffsForZ0SinThetaCut.empty() ||
695 !m_vecvecMaxZ0SinThetaAboveEtaPt.empty()) {
696 auto etaSize = m_vecEtaCutoffsForZ0SinThetaCut.size();
697 auto ptSize = m_vecPtCutoffsForZ0SinThetaCut.size();
698 if (etaSize != m_vecvecMaxZ0SinThetaAboveEtaPt.size()) {
699 ATH_MSG_ERROR( "Eta cutoffs and Z0SinTheta cuts must be vectors of the same length." );
700 return StatusCode::FAILURE;
701 }
702 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
703 if (ptSize != m_vecvecMaxZ0SinThetaAboveEtaPt[i_size].size()) {
704 ATH_MSG_ERROR( "Pt cutoffs and Z0SinTheta cuts must be vectors of the same length." );
705 return StatusCode::FAILURE;
706 }
707 }
708
709 std::stringstream pTRangeBuffer;
710 std::copy(m_vecPtCutoffsForZ0SinThetaCut.begin(), m_vecPtCutoffsForZ0SinThetaCut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
711 std::string pTString=pTRangeBuffer.str();
712 if constexpr(VERBOSE>0) ATH_MSG_INFO("Z0SinTheta cuts (<=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
713 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
714 {
715 std::stringstream etaRangeBuffer;
716 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForZ0SinThetaCut[i_cut_eta] << " < |#eta| < ";
717 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForZ0SinThetaCut[i_cut_eta+1];
718 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
719
720 std::stringstream cutBuffer;
721 std::copy(m_vecvecMaxZ0SinThetaAboveEtaPt[i_cut_eta].begin(), m_vecvecMaxZ0SinThetaAboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
722 std::string cutString=cutBuffer.str();
723
724 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
725 }
726
727 if (!checkOrder(m_vecEtaCutoffsForZ0SinThetaCut.value())) {
728 ATH_MSG_ERROR( "Eta values not in ascending order." );
729 return StatusCode::FAILURE;
730 }
731 if (!checkOrder(m_vecPtCutoffsForZ0SinThetaCut.value())) {
732 ATH_MSG_ERROR( "Pt values not in ascending order." );
733 return StatusCode::FAILURE;
734 }
735
736 trackCuts["Z0SinTheta"].push_back([p_vecEtaCutoffsForZ0SinThetaCut = &std::as_const(m_vecEtaCutoffsForZ0SinThetaCut.value()),
737 p_vecPtCutoffsForZ0SinThetaCut = &std::as_const(m_vecPtCutoffsForZ0SinThetaCut.value()),
738 p_vecvecMaxZ0SinThetaAboveEtaPt = &std::as_const(m_vecvecMaxZ0SinThetaAboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
739 double eta = helper.eta(msgHelper);
740 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForZ0SinThetaCut, std::fabs(eta));
741 double pt = helper.pt(msgHelper);
742 unsigned int bin_pt = findBin(*p_vecPtCutoffsForZ0SinThetaCut, pt);
743 return bin_eta >= p_vecEtaCutoffsForZ0SinThetaCut->size()
744 || bin_pt >= p_vecPtCutoffsForZ0SinThetaCut->size()
745 || std::fabs(helper.z0(msgHelper) * std::sin(helper.theta(msgHelper))) <= (*p_vecvecMaxZ0SinThetaAboveEtaPt)[bin_eta][bin_pt];
746 });
747 }
748
749 if (!m_vecPtCutoffsForD0Cut.empty() ||
750 !m_vecEtaCutoffsForD0Cut.empty() ||
751 !m_vecvecMaxD0AboveEtaPt.empty()) {
752 auto etaSize = m_vecEtaCutoffsForD0Cut.size();
753 auto ptSize = m_vecPtCutoffsForD0Cut.size();
754 if (etaSize != m_vecvecMaxD0AboveEtaPt.size()) {
755 ATH_MSG_ERROR( "Eta cutoffs and D0 cuts must be vectors of the same length." );
756 return StatusCode::FAILURE;
757 }
758 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
759 if (ptSize != m_vecvecMaxD0AboveEtaPt[i_size].size()) {
760 ATH_MSG_ERROR( "Pt cutoffs and D0 cuts must be vectors of the same length." );
761 return StatusCode::FAILURE;
762 }
763 }
764
765 std::stringstream pTRangeBuffer;
766 std::copy(m_vecPtCutoffsForD0Cut.begin(), m_vecPtCutoffsForD0Cut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
767 std::string pTString=pTRangeBuffer.str();
768 if constexpr(VERBOSE>0) ATH_MSG_INFO("D0 cuts (<=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
769 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
770 {
771 std::stringstream etaRangeBuffer;
772 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForD0Cut[i_cut_eta] << " < |#eta| < ";
773 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForD0Cut[i_cut_eta+1];
774 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
775
776 std::stringstream cutBuffer;
777 std::copy(m_vecvecMaxD0AboveEtaPt[i_cut_eta].begin(), m_vecvecMaxD0AboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
778 std::string cutString=cutBuffer.str();
779
780 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
781 }
782
783 if (!checkOrder(m_vecEtaCutoffsForD0Cut.value())) {
784 ATH_MSG_ERROR( "Eta values not in ascending order." );
785 return StatusCode::FAILURE;
786 }
787 if (!checkOrder(m_vecPtCutoffsForD0Cut.value())) {
788 ATH_MSG_ERROR( "Pt values not in ascending order." );
789 return StatusCode::FAILURE;
790 }
791
792 trackCuts["D0"].push_back([p_vecEtaCutoffsForD0Cut = &std::as_const(m_vecEtaCutoffsForD0Cut.value()),
793 p_vecPtCutoffsForD0Cut = &std::as_const(m_vecPtCutoffsForD0Cut.value()),
794 p_vecvecMaxD0AboveEtaPt = &std::as_const(m_vecvecMaxD0AboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
795 double eta = helper.eta(msgHelper);
796 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForD0Cut, std::fabs(eta));
797 double pt = helper.pt(msgHelper);
798 unsigned int bin_pt = findBin(*p_vecPtCutoffsForD0Cut, pt);
799 return bin_eta >= p_vecEtaCutoffsForD0Cut->size()
800 || bin_pt >= p_vecPtCutoffsForD0Cut->size()
801 || std::fabs(helper.d0(msgHelper)) <= (*p_vecvecMaxD0AboveEtaPt)[bin_eta][bin_pt];
802 });
803 }
804
805 if (!m_vecPtCutoffsForSctHolesCut.empty() ||
806 !m_vecEtaCutoffsForSctHolesCut.empty() ||
807 !m_vecvecMaxSctHolesAboveEtaPt.empty()) {
808 auto etaSize = m_vecEtaCutoffsForSctHolesCut.size();
809 auto ptSize = m_vecPtCutoffsForSctHolesCut.size();
810 if (etaSize != m_vecvecMaxSctHolesAboveEtaPt.size()) {
811 ATH_MSG_ERROR( "Eta cutoffs and SctHoles cuts must be vectors of the same length." );
812 return StatusCode::FAILURE;
813 }
814 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
815 if (ptSize != m_vecvecMaxSctHolesAboveEtaPt[i_size].size()) {
816 ATH_MSG_ERROR( "Pt cutoffs and SctHoles cuts must be vectors of the same length." );
817 return StatusCode::FAILURE;
818 }
819 }
820
821 std::stringstream pTRangeBuffer;
822 std::copy(m_vecPtCutoffsForSctHolesCut.begin(), m_vecPtCutoffsForSctHolesCut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
823 std::string pTString=pTRangeBuffer.str();
824 if constexpr(VERBOSE>0) ATH_MSG_INFO("SctHoles cuts (<=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
825 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
826 {
827 std::stringstream etaRangeBuffer;
828 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHolesCut[i_cut_eta] << " < |#eta| < ";
829 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHolesCut[i_cut_eta+1];
830 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
831
832 std::stringstream cutBuffer;
833 std::copy(m_vecvecMaxSctHolesAboveEtaPt[i_cut_eta].begin(), m_vecvecMaxSctHolesAboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
834 std::string cutString=cutBuffer.str();
835
836 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
837 }
838
839 if (!checkOrder(m_vecEtaCutoffsForSctHolesCut.value())) {
840 ATH_MSG_ERROR( "Eta values not in ascending order." );
841 return StatusCode::FAILURE;
842 }
843 if (!checkOrder(m_vecPtCutoffsForSctHolesCut.value())) {
844 ATH_MSG_ERROR( "Pt values not in ascending order." );
845 return StatusCode::FAILURE;
846 }
847
848 trackCuts["SctHits"].push_back([p_vecEtaCutoffsForSctHolesCut = &std::as_const(m_vecEtaCutoffsForSctHolesCut.value()),
849 p_vecPtCutoffsForSctHolesCut = &std::as_const(m_vecPtCutoffsForSctHolesCut.value()),
850 p_vecvecMaxSctHolesAboveEtaPt = &std::as_const(m_vecvecMaxSctHolesAboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
851 double eta = helper.eta(msgHelper);
852 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForSctHolesCut, std::fabs(eta));
853 double pt = helper.pt(msgHelper);
854 unsigned int bin_pt = findBin(*p_vecPtCutoffsForSctHolesCut, pt);
855 return bin_eta >= p_vecEtaCutoffsForSctHolesCut->size()
856 || bin_pt >= p_vecPtCutoffsForSctHolesCut->size()
857 || getSummary(helper, msgHelper, xAOD::numberOfSCTHoles) <= (*p_vecvecMaxSctHolesAboveEtaPt)[bin_eta][bin_pt];
858 });
859 }
860
861 if (!m_vecPtCutoffsForSctHitsPlusDeadCut.empty() ||
862 !m_vecEtaCutoffsForSctHitsPlusDeadCut.empty() ||
863 !m_vecvecMinSctHitsPlusDeadAboveEtaPt.empty()) {
864 auto etaSize = m_vecEtaCutoffsForSctHitsPlusDeadCut.size();
865 auto ptSize = m_vecPtCutoffsForSctHitsPlusDeadCut.size();
866 if (etaSize != m_vecvecMinSctHitsPlusDeadAboveEtaPt.size()) {
867 ATH_MSG_ERROR( "Eta cutoffs and SctHitsPlusDead cuts must be vectors of the same length." );
868 return StatusCode::FAILURE;
869 }
870 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
871 if (ptSize != m_vecvecMinSctHitsPlusDeadAboveEtaPt[i_size].size()) {
872 ATH_MSG_ERROR( "Pt cutoffs and SctHitsPlusDead cuts must be vectors of the same length." );
873 return StatusCode::FAILURE;
874 }
875 }
876
877 std::stringstream pTRangeBuffer;
878 std::copy(m_vecPtCutoffsForSctHitsPlusDeadCut.begin(), m_vecPtCutoffsForSctHitsPlusDeadCut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
879 std::string pTString=pTRangeBuffer.str();
880 if constexpr(VERBOSE>0) ATH_MSG_INFO("SctHitsPlusDead cuts (>=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
881 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
882 {
883 std::stringstream etaRangeBuffer;
884 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHitsPlusDeadCut[i_cut_eta] << " < |#eta| < ";
885 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHitsPlusDeadCut[i_cut_eta+1];
886 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
887
888 std::stringstream cutBuffer;
889 std::copy(m_vecvecMinSctHitsPlusDeadAboveEtaPt[i_cut_eta].begin(), m_vecvecMinSctHitsPlusDeadAboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
890 std::string cutString=cutBuffer.str();
891
892 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
893 }
894
895 if (!checkOrder(m_vecEtaCutoffsForSctHitsPlusDeadCut.value())) {
896 ATH_MSG_ERROR( "Eta values not in ascending order." );
897 return StatusCode::FAILURE;
898 }
899 if (!checkOrder(m_vecPtCutoffsForSctHitsPlusDeadCut.value())) {
900 ATH_MSG_ERROR( "Pt values not in ascending order." );
901 return StatusCode::FAILURE;
902 }
903
904 trackCuts["SctHits"].push_back([p_vecEtaCutoffsForSctHitsPlusDeadCut = &std::as_const(m_vecEtaCutoffsForSctHitsPlusDeadCut.value()),
905 p_vecPtCutoffsForSctHitsPlusDeadCut = &std::as_const(m_vecPtCutoffsForSctHitsPlusDeadCut.value()),
906 p_vecvecMinSctHitsPlusDeadAboveEtaPt = &std::as_const(m_vecvecMinSctHitsPlusDeadAboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
907 double eta = helper.eta(msgHelper);
908 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForSctHitsPlusDeadCut, std::fabs(eta));
909 double pt = helper.pt(msgHelper);
910 unsigned int bin_pt = findBin(*p_vecPtCutoffsForSctHitsPlusDeadCut, pt);
911 return bin_eta >= p_vecEtaCutoffsForSctHitsPlusDeadCut->size()
912 || bin_pt >= p_vecPtCutoffsForSctHitsPlusDeadCut->size()
913 || getSummarySum<2,Trk_Helper>(helper, msgHelper, {xAOD::numberOfSCTHits, xAOD::numberOfSCTDeadSensors}) >= (*p_vecvecMinSctHitsPlusDeadAboveEtaPt)[bin_eta][bin_pt];
914 });
915 }
916
917 return StatusCode::SUCCESS;
918}
919
920
921template <class Trk_Helper>
923 const std::map< std::string, std::vector< std::function<bool(Trk_Helper helper, const asg::AsgMessaging &msgHelper)> > > &trackCuts) const {
924 if (!m_isInitialized) {
925 if (!m_warnInit) {
926 ATH_MSG_WARNING( "Tool is not initialized! Calling accept() will not be very helpful." );
927 m_warnInit = true;
928 }
929 }
930
931 asg::AcceptData acceptData(&m_acceptInfo);
932 bool passAll = true;
933
934 // loop over all cuts
935 UShort_t cutFamilyIndex = 0;
936 for ( const auto& cutFamily : trackCuts ) {
937 bool pass = true;
938
939 for ( const auto& cut : cutFamily.second ) {
940 if (! cut(helper, *m_msgHelper) ) {
941 pass = false;
942 break;
943 }
944 }
945
946 // @TODO really always run through all cuts even if passed is false ?
947 passAll &= pass;
948 acceptData.setCutResult( cutFamilyIndex, pass );
949 cutFamilyIndex++;
950 }
951
952 {
953 // lock access to m_numTracksPassedCuts
954 std::lock_guard<std::mutex> lock(m_mutex);
955 for (unsigned int idx=0; idx < trackCuts.size(); ++idx) {
956 assert(idx<m_numTracksPassedCuts.size());
957 m_numTracksPassedCuts[idx] += acceptData.getCutResult(idx);
958 }
959 }
960 if (passAll) m_numTracksPassed++;
962
963 return acceptData;
964
965}
966
967
969{
970 if (!m_isInitialized) {
971 ATH_MSG_ERROR( "You are attempting to finalize a tool that has not been initialized()." );
972 }
973
974#ifdef XAOD_ANALYSIS
975 if (m_numTracksProcessed == 0) {
976 ATH_MSG_INFO( "No tracks processed in selection tool." );
977 return StatusCode::SUCCESS;
978 }
979
980 // Only printed out for analysis
982 << m_numTracksPassed*100./m_numTracksProcessed << "% passed all cuts." );
983 for (const auto& cutFamily : m_trackParticleCuts) {
984 // lock(m_mutex) is not needed because this is inside of non-const finalize method.
985 uint64_t numPassed = m_numTracksPassedCuts.at(m_acceptInfo.getCutPosition(cutFamily.first));
986 ATH_MSG_INFO( numPassed << " = " << numPassed*100./m_numTracksProcessed << "% passed "
987 << cutFamily.first << " cut." );
988 }
989#endif
990
991 return StatusCode::SUCCESS;
992}
993
994
1003
1004
1017{
1018
1019 asg::AcceptData acceptData(&m_acceptInfo);
1020 // Check if this is a track:
1021 if( p->type() != xAOD::Type::TrackParticle ) {
1022 ATH_MSG_ERROR( "accept(...) Function received a non-track" );
1023 return acceptData;
1024 }
1025
1026 // Cast it to a track (we have already checked its type so we do not have to dynamic_cast):
1027 const xAOD::TrackParticle* trk = static_cast< const xAOD::TrackParticle* >( p );
1028
1029 // Let the specific function do the work:
1030 return accept( *trk, nullptr );
1031}
1032
1033
1060 const xAOD::Vertex* vtx ) const
1061{
1062 asg::AcceptData acceptData(&m_acceptInfo);
1063 if (m_trackParticleCuts.empty()) {
1066 return acceptData;
1067 }
1068
1069 InDetAccessor::TrackParticleHelper track_helper(trk,vtx);
1070 return accept( track_helper, m_trackParticleCuts);
1071}
1072
1073#ifndef XAOD_ANALYSIS
1083 const Trk::Vertex* vertex ) const
1084{
1085 if (!m_isInitialized) ATH_MSG_WARNING( "Tool is not initialized! Calling accept() will not be very helpful." );
1086
1087 asg::AcceptData acceptData(&m_acceptInfo);
1088 if (m_trkTrackCuts.empty()) {
1091 return acceptData;
1092 }
1093
1094 const Trk::TrackParameters* perigee = track.perigeeParameters();
1095
1096 if ( perigee == nullptr || !perigee->covariance() ) {
1097 ATH_MSG_WARNING( "Track preselection: Zero pointer to parameterbase* received (most likely a track without perigee). This track will not pass any cuts." );
1098 return acceptData;
1099 }
1100
1101 std::unique_ptr<const Trk::TrackParameters> paramsAtVertex;
1102 if (vertex) {
1103 Trk::PerigeeSurface perigeeSurface(vertex->position());
1104 paramsAtVertex =
1105 m_extrapolator->extrapolate(Gaudi::Hive::currentContext(),
1106 *perigee,
1107 perigeeSurface,
1109 true,
1110 track.info().particleHypothesis());
1111 perigee = paramsAtVertex.get();
1112 }
1113
1114 if ( perigee == nullptr || !perigee->covariance() ) {
1115 ATH_MSG_INFO( "Track preselection: cannot make a measured perigee. This track will not pass any cuts." );
1116 if (!m_initTrkTools)
1117 ATH_MSG_INFO( "The user should set \"UseTrkTrackTools\" to true if they want the extrapolation tool to try to get a perigee." );
1118 return acceptData;
1119 }
1120
1121
1122 std::unique_ptr<Trk::TrackSummary> cleanup_summary;
1123 const Trk::TrackSummary* summary = track.trackSummary();
1124 if (summary == nullptr && m_trackSumToolAvailable) {
1125 cleanup_summary = m_trackSumTool->summary(Gaudi::Hive::currentContext(),track);
1126 summary = cleanup_summary.get();
1127 }
1128 if (summary == nullptr) {
1129 ATH_MSG_INFO( "Track preselection: cannot get a track summary. This track will not pass any cuts." );
1130 if (!m_initTrkTools)
1131 ATH_MSG_INFO( "The Trk::Track tools were not set to be initialized. The user should set the property \"UseTrkTrackTools\" to true if they wish to use the summary tool." );
1132 return acceptData;
1133 }
1134
1135 InDetAccessor::TrkTrackHelper track_helper(track,*summary, perigee);
1136 acceptData = accept( track_helper, m_trkTrackCuts);
1137 return acceptData;
1138}
1139
1140#endif // XAOD_ANALYSIS
1141
1157#ifdef __GNUC__
1158#pragma GCC diagnostic push
1159#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1160#endif
1161void InDet::InDetTrackSelectionTool::setCutLevel(InDet::CutLevel level, bool overwrite )
1162{
1163#ifndef XAOD_STANDALONE
1164 ATH_MSG_WARNING( "InDetTrackSelectionTool::setCutLevel() is not designed to be called manually in Athena." );
1165 ATH_MSG_WARNING( "It may not behave as intended. Instead, configure it in the job options through the CutLevel property." );
1166#endif // XAOD_STANDALONE
1167 if (!m_cutLevel.empty()) {
1168 ATH_MSG_WARNING( "Cut level already set to " << m_cutLevel << ". Calling setCutLevel() is not expected." );
1169 }
1170 setCutLevelPrivate(level, overwrite);
1171}
1172#ifdef __GNUC__
1173#pragma GCC diagnostic pop
1174#endif
1175
1176void InDet::InDetTrackSelectionTool::setCutLevelPrivate(InDet::CutLevel level, bool overwrite)
1177{
1178 switch (level) {
1179 case CutLevel::NoCut :
1180 if (m_isInitialized) {
1181 // this check is in here so that it only happens once per call to setCutLevel,
1182 // but will still warn if only the private version is called somehow.
1183 ATH_MSG_WARNING( "Trying to set cut level while the tool is already initialized." );
1184 ATH_MSG_WARNING( "This will almost certainly not exhibit intended behavior." );
1185 }
1186 if (overwrite) {
1187 // minimum cuts will default to -1, so if a user wishes to remove a cut
1188 // from a preset level they can do so by setting the minimum to zero.
1189 // maximum cuts can be removed from a preset level by setting them negative.
1190 m_minPt = -1.; // in MeV
1191 m_minP = -1.;
1208 m_minNPixelHits = -1;
1212 m_minNSctHits = -1;
1217 m_minNSiHits = -1;
1224 m_maxOneSharedModule = false;
1226 m_maxEtaForTrtHitCuts = -1.; // this is really a minimum eta above which cuts are not applied
1227 m_minNTrtHits = -1;
1235 m_minProb = -1.;
1240 m_minNUsedHitsdEdx = -1;
1242 m_minEProbabilityHT = -1.;
1243 m_eProbHTonlyForXe = false;
1244#ifndef XAOD_ANALYSIS
1245 m_minNSiHitsMod = -1;
1246 m_minNSiHitsModTop = -1;
1248#endif
1249 m_vecEtaCutoffsForSiHitsCut = std::vector<double>();
1250 m_vecMinNSiHitsAboveEta = std::vector<int>();
1251 m_vecEtaCutoffsForPtCut = std::vector<double>();
1252 m_vecMinPtAboveEta = std::vector<double>();
1253 m_vecPtCutoffsForSctHitsCut = std::vector<double>();
1254 m_vecMinNSctHitsAbovePt = std::vector<int>();
1255 m_vecEtaCutoffsForZ0SinThetaCut = std::vector<double>();
1256 m_vecPtCutoffsForZ0SinThetaCut = std::vector<double>();
1257 m_vecvecMaxZ0SinThetaAboveEtaPt = std::vector<std::vector<double>>();
1258 m_vecEtaCutoffsForD0Cut = std::vector<double>();
1259 m_vecPtCutoffsForD0Cut = std::vector<double>();
1260 m_vecvecMaxD0AboveEtaPt = std::vector<std::vector<double>>();
1261 m_vecEtaCutoffsForSctHolesCut = std::vector<double>();
1262 m_vecPtCutoffsForSctHolesCut = std::vector<double>();
1263 m_vecvecMaxSctHolesAboveEtaPt = std::vector<std::vector<double>>();
1264 m_vecEtaCutoffsForSctHitsPlusDeadCut = std::vector<double>();
1265 m_vecPtCutoffsForSctHitsPlusDeadCut = std::vector<double>();
1266 m_vecvecMinSctHitsPlusDeadAboveEtaPt = std::vector<std::vector<double>>();
1267 }
1268 break;
1269 case CutLevel::Loose :
1270 setCutLevelPrivate(CutLevel::NoCut, overwrite); // if hard overwrite, reset all cuts first. will do nothing if !overwrite
1271 // change the cuts if a hard overwrite is asked for or if the cuts are unset
1272 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1273 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 8;
1274 m_maxOneSharedModule = true;
1275 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1276 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 1;
1277 break;
1278 case CutLevel::LoosePrimary :
1279 setCutLevelPrivate(CutLevel::NoCut, overwrite); // implement loose cuts first
1280 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1281 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 8;
1282 m_maxOneSharedModule = true;
1283 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1284 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 1;
1285 if (overwrite || m_minNSiHitsIfSiSharedHits < 0) m_minNSiHitsIfSiSharedHits = 10;
1286 break;
1287 case CutLevel::TightPrimary :
1288 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1289 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1290 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 9;
1291 m_maxOneSharedModule = true;
1292 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1293 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 0;
1295 if (overwrite || m_minNSiHitsAboveEtaCutoff < 0) m_minNSiHitsAboveEtaCutoff = 11;
1297 break;
1298 case CutLevel::LooseMuon :
1299 setCutLevelPrivate(CutLevel::NoCut, overwrite); // reset cuts unless we are doing a soft set
1300 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1301 if (overwrite || m_minNSctHits < 0) m_minNSctHits = 5;
1302 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1304 if (overwrite || m_maxEtaForTrtHitCuts < 0.) m_maxEtaForTrtHitCuts = 1.9;
1305 if (overwrite || m_minNTrtHitsPlusOutliers < 0) m_minNTrtHitsPlusOutliers = 6;
1307 break;
1308 case CutLevel::LooseElectron :
1309 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1310 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 7;
1311 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1312 break;
1313 case CutLevel::LooseTau :
1314 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1315 if (overwrite || m_minPt < 0.0) m_minPt = 1000.0;
1316 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 7;
1317 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 2;
1318 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.0;
1319 if (overwrite || m_maxZ0 >= LOCAL_MAX_DOUBLE) m_maxZ0 = 1.5;
1320 break;
1321 case CutLevel::MinBias :
1322 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1323 if (overwrite || m_useMinBiasInnermostLayersCut >= 0) m_useMinBiasInnermostLayersCut = 1; // if this is less than 0, it is turned off
1324 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1325 if (overwrite || m_minNSctHits < 0) m_minNSctHits = 6;
1326 if (overwrite || m_minProbAbovePtCutoff < 0.) {
1327 m_minPtForProbCut = 10000.;
1329 }
1330 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.5;
1331 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.5;
1332 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1333 if (overwrite || m_minPt < 0.) m_minPt = 500.0;
1334 break;
1335 case CutLevel::HILoose:
1336 // HILoose is similar to MinBias, but not identical
1337 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1338 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1340 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1341 if (overwrite || (m_vecPtCutoffsForSctHitsCut.empty()
1342 && m_vecMinNSctHitsAbovePt.empty())) {
1343 m_vecPtCutoffsForSctHitsCut = std::vector<double>({0.0, 300.0, 400.0});
1344 m_vecMinNSctHitsAbovePt = std::vector<int>({2, 4, 6});
1345 }
1346 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.5;
1347 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.5;
1348 break;
1349 case CutLevel::HITight:
1350 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1351 // HITight is like HILoose but we require 8 SCT hits and 2 pixel hits
1352 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1353 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1355 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 2;
1356 if (overwrite || (m_vecPtCutoffsForSctHitsCut.empty()
1357 && m_vecMinNSctHitsAbovePt.empty())) {
1358 m_vecPtCutoffsForSctHitsCut = std::vector<double>({0.0, 300.0, 400.0});
1359 m_vecMinNSctHitsAbovePt = std::vector<int>({4, 6, 8});
1360 }
1361 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.0;
1362 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.0;
1363 if (overwrite || m_maxChiSqperNdf >= LOCAL_MAX_DOUBLE) m_maxChiSqperNdf = 6.0;
1364 break;
1365 case CutLevel::HILooseOptimized:
1366 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1367 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1368 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 0;
1370 if (overwrite || (m_vecEtaCutoffsForZ0SinThetaCut.empty() &&
1373 m_vecEtaCutoffsForZ0SinThetaCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1375 std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1376 2000, 2500, 3000, 5000, 8000, 12000});
1378 std::vector<std::vector<double>>({{2.10, 2.15, 6.00, 5.00, 3.10, 2.00, 1.75, 1.60, 1.43, 1.40, 1.05, 0.65, 0.60},
1379 {1.44, 1.47, 1.50, 1.55, 1.62, 1.45, 1.45, 1.78, 1.73, 1.50, 1.20, 0.97, 0.53},
1380 {1.40, 1.45, 1.50, 1.46, 1.41, 1.37, 1.25, 1.50, 1.50, 1.36, 1.10, 0.85, 0.52},
1381 {1.51, 1.70, 1.70, 1.71, 1.71, 1.53, 1.54, 1.49, 1.36, 1.20, 0.95, 0.60, 0.55}});
1382 }
1383 if (overwrite || (m_vecEtaCutoffsForD0Cut.empty() &&
1384 m_vecPtCutoffsForD0Cut.empty() &&
1385 m_vecvecMaxD0AboveEtaPt.empty())){
1386 m_vecEtaCutoffsForD0Cut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1388 std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1389 2000, 2500, 3000, 5000, 8000, 12000});
1391 std::vector<std::vector<double>>({{0.81, 0.90, 0.94, 0.92, 0.90, 0.75, 0.65, 0.63, 0.62, 0.60, 0.63, 0.50, 0.55},
1392 {1.00, 0.98, 0.98, 0.92, 0.90, 0.69, 0.67, 0.86, 0.88, 0.88, 0.88, 0.87, 1.06},
1393 {1.19, 1.15, 1.10, 1.08, 1.03, 0.94, 0.85, 0.97, 0.97, 0.96, 0.95, 0.92, 1.04},
1394 {1.33, 1.23, 1.21, 1.15, 1.15, 1.07, 0.94, 0.97, 0.97, 0.97, 0.98, 1.10, 1.10}});
1395 }
1396 break;
1397 case CutLevel::HITightOptimized:
1398 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1399 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1400 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 0;
1402 if (overwrite || (m_vecEtaCutoffsForZ0SinThetaCut.empty() &&
1405 m_vecEtaCutoffsForZ0SinThetaCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1406 m_vecPtCutoffsForZ0SinThetaCut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1407 2000, 2500, 3000, 5000, 8000, 12000});
1409 std::vector<std::vector<double>>({{0.62, 0.70, 0.82, 0.87, 0.74, 0.61, 0.50, 0.48, 0.46, 0.45, 0.30, 0.24, 0.23},
1410 {0.51, 0.53, 0.53, 0.53, 0.52, 0.43, 0.28, 0.27, 0.28, 0.30, 0.24, 0.22, 0.13},
1411 {0.91, 0.89, 0.87, 0.55, 0.59, 0.37, 0.39, 0.31, 0.34, 0.35, 0.30, 0.30, 0.20},
1412 {0.76, 0.71, 0.69, 0.48, 0.48, 0.47, 0.46, 0.42, 0.38, 0.32, 0.28, 0.20, 0.15}});
1413 }
1414 if (overwrite || (m_vecEtaCutoffsForD0Cut.empty() &&
1415 m_vecPtCutoffsForD0Cut.empty() &&
1416 m_vecvecMaxD0AboveEtaPt.empty())){
1417 m_vecEtaCutoffsForD0Cut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1418 m_vecPtCutoffsForD0Cut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1419 2000, 2500, 3000, 5000, 8000, 12000});
1421 std::vector<std::vector<double>>({{0.34, 0.39, 0.47, 0.49, 0.55, 0.47, 0.44, 0.21, 0.19, 0.17, 0.12, 0.14, 0.15},
1422 {0.32, 0.32, 0.33, 0.33, 0.33, 0.27, 0.16, 0.15, 0.13, 0.15, 0.13, 0.16, 0.20},
1423 {0.95, 0.91, 0.88, 0.35, 0.37, 0.24, 0.26, 0.22, 0.23, 0.24, 0.19, 0.19, 0.23},
1424 {0.68, 0.67, 0.65, 0.42, 0.42, 0.36, 0.35, 0.31, 0.27, 0.26, 0.27, 0.28, 0.30}});
1425 }
1426 if (overwrite || (m_vecEtaCutoffsForSctHolesCut.empty() &&
1429 m_vecEtaCutoffsForSctHolesCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1430 m_vecPtCutoffsForSctHolesCut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1431 2000, 2500, 3000, 5000, 8000, 12000});
1433 std::vector<std::vector<double>>({{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
1434 {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
1435 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1436 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}});
1437 }
1438 if (overwrite || (m_vecEtaCutoffsForSctHitsPlusDeadCut.empty() &&
1441 m_vecEtaCutoffsForSctHitsPlusDeadCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1442 m_vecPtCutoffsForSctHitsPlusDeadCut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1443 2000, 2500, 3000, 5000, 8000, 12000});
1445 std::vector<std::vector<double>>({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1446 {0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0},
1447 {8, 8, 8, 7, 7, 6, 6, 6, 6, 6, 0, 0, 0},
1448 {7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}});
1449 }
1450 break;
1451 case CutLevel::HILoosePixMod:
1452 // HILoosePixMod is similar to HILoose, but with a modified hit cut on the innermost layers
1453 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1454 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1455 if (overwrite) m_useHILoosePixModInnermostLayersCut = true;
1456 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1457 if (overwrite || m_vecPtCutoffsForSctHitsCut.empty()) m_vecPtCutoffsForSctHitsCut = std::vector<double>({0.0, 300.0, 400.0});
1458 if (overwrite || m_vecMinNSctHitsAbovePt.empty()) m_vecMinNSctHitsAbovePt = std::vector<int>({2, 4, 6});
1459 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.5;
1460 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.5;
1461 break;
1462 default:
1463 ATH_MSG_ERROR("CutLevel not recognized. Cut selection will remain unchanged.");
1464 break;
1465 }
1466}
1467
1468// initialize the map from strings to cut levels
1469const std::unordered_map<std::string, InDet::CutLevel>
1471 {
1472 {"NoCut", InDet::CutLevel::NoCut},
1473 {"Loose", InDet::CutLevel::Loose},
1474 {"LoosePrimary", InDet::CutLevel::LoosePrimary},
1475 {"TightPrimary", InDet::CutLevel::TightPrimary},
1476 {"LooseMuon", InDet::CutLevel::LooseMuon},
1477 {"LooseElectron", InDet::CutLevel::LooseElectron},
1478 {"LooseTau", InDet::CutLevel::LooseTau},
1479 {"MinBias", InDet::CutLevel::MinBias},
1480 {"HILoose", InDet::CutLevel::HILoose},
1481 {"HITight", InDet::CutLevel::HITight},
1482 {"HILooseOptimized", InDet::CutLevel::HILooseOptimized},
1483 {"HITightOptimized", InDet::CutLevel::HITightOptimized},
1484 {"HILoosePixMod", InDet::CutLevel::HILoosePixMod}
1485 };
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t a
static const std::vector< std::string > bins
static const uint32_t nHits
#define sqr(t)
void operator()(T1)
size_t size() const
Number of registered mappings.
@ top
Gaudi::Property< std::vector< double > > m_vecEtaCutoffsForSctHitsPlusDeadCut
Gaudi::Property< std::vector< double > > m_vecEtaCutoffsForSiHitsCut
Gaudi::Property< double > m_maxTrtHighEFraction
ToolHandle< Trk::ITrackSummaryTool > m_trackSumTool
Gaudi::Property< int > m_minNSiHitsAboveEtaCutoff
Gaudi::Property< bool > m_eProbHTonlyForXe
Gaudi::Property< std::vector< std::vector< double > > > m_vecvecMaxSctHolesAboveEtaPt
Gaudi::Property< double > m_minEtaForStrictNSiHitsCut
static bool maxDoubleIsSet(double cutValue)
Gaudi::Property< bool > m_useHILoosePixModInnermostLayersCut
Gaudi::Property< int > m_maxNSctDoubleHoles
std::atomic< uint64_t > m_numTracksPassed
a counter of the number of tracks that passed all cuts
virtual const asg::AcceptInfo & getAcceptInfo() const override
Get an object describing the "selection steps" of the tool.
Gaudi::Property< double > m_maxZ0SinThetaoverSigmaZ0SinTheta
Gaudi::Property< int > m_minNBothInnermostLayersHits
Gaudi::Property< std::vector< double > > m_vecEtaCutoffsForD0Cut
Gaudi::Property< double > m_maxZ0overSigmaZ0
StatusCode setupCuts(std::map< std::string, std::vector< std::function< bool(Trk_Helper helper, const asg::AsgMessaging &msgHelper)> > > &trackCuts)
Gaudi::Property< int > m_minNPixelHitsPhysical
virtual asg::AcceptData accept(const xAOD::IParticle *) const override
Get the decision using a generic IParticle pointer.
Gaudi::Property< int > m_minNSiHitsPhysical
Gaudi::Property< double > m_minPtForProbCut
Gaudi::Property< std::vector< std::vector< double > > > m_vecvecMaxZ0SinThetaAboveEtaPt
Gaudi::Property< double > m_maxSigmaZ0SinTheta
Gaudi::Property< bool > m_useExperimentalInnermostLayersCut
Gaudi::Property< double > m_maxD0overSigmaD0
Gaudi::Property< std::vector< double > > m_vecPtCutoffsForSctHitsPlusDeadCut
Gaudi::Property< std::string > m_cutLevel
The string version of the cut level so that it can be set via jobOptions.
Gaudi::Property< std::vector< double > > m_vecPtCutoffsForD0Cut
Gaudi::Property< int > m_minNSiHitsIfSiSharedHits
std::atomic< uint64_t > m_numTracksProcessed
a counter of the number of tracks proccessed
Gaudi::Property< double > m_maxSigmaD0
Gaudi::Property< std::vector< double > > m_vecPtCutoffsForSctHitsCut
Gaudi::Property< int > m_minNInnermostLayerHits
Gaudi::Property< std::vector< std::vector< double > > > m_vecvecMinSctHitsPlusDeadAboveEtaPt
virtual StatusCode finalize() override
Function finalizing the tool.
virtual StatusCode initialize() override
Function initialising the tool.
Gaudi::Property< double > m_minEProbabilityHT
Gaudi::Property< int > m_useMinBiasInnermostLayersCut
Gaudi::Property< double > m_maxEtaForTrtHitCuts
asg::AcceptInfo m_acceptInfo
Object used to store the last decision.
Gaudi::Property< int > m_minNSiHitsModBottom
ToolHandle< Trk::IExtrapolator > m_extrapolator
std::unique_ptr< asg::AsgMessaging > m_msgHelper
Gaudi::Property< int > m_maxNInnermostLayerSharedHits
Gaudi::Property< bool > m_useEtaDependentMaxChiSq
Gaudi::Property< int > m_minNOverflowHitsdEdx
Gaudi::Property< double > m_maxAbsEta
std::map< std::string, std::vector< std::function< bool(InDetAccessor::TrackParticleHelper helper, const asg::AsgMessaging &msgHelper)> > > m_trackParticleCuts
First element is the name of the cut family, second element is the set of cuts.
Gaudi::Property< bool > m_maxOneSharedModule
bool m_trackSumToolAvailable
Whether the summary tool is available.
Gaudi::Property< std::vector< double > > m_vecEtaCutoffsForPtCut
std::map< std::string, std::vector< std::function< bool(InDetAccessor::TrkTrackHelper helper, const asg::AsgMessaging &msgHelper)> > > m_trkTrackCuts
First element is the name of the cut family, second element is the set of cuts.
Gaudi::Property< std::vector< double > > m_vecEtaCutoffsForSctHolesCut
Gaudi::Property< int > m_minNSctHitsPhysical
Gaudi::Property< double > m_minProbAbovePtCutoff
Gaudi::Property< std::vector< double > > m_vecPtCutoffsForSctHolesCut
Gaudi::Property< int > m_minNTrtHighThresholdHitsPlusOutliers
Gaudi::Property< double > m_maxChiSqperNdf
Gaudi::Property< double > m_maxTrtOutlierFraction
Gaudi::Property< int > m_minNNextToInnermostLayerHits
Gaudi::Property< int > m_maxNPixelSharedHits
Gaudi::Property< double > m_maxZ0SinTheta
Gaudi::Property< int > m_minNTrtHighThresholdHits
Gaudi::Property< std::vector< double > > m_vecMinPtAboveEta
Gaudi::Property< std::vector< int > > m_vecMinNSctHitsAbovePt
static const std::unordered_map< std::string, CutLevel > s_mapCutLevel
ASG_TOOL_CLASS2(InDetTrackSelectionTool, IAsgSelectionTool, InDet::IInDetTrackSelectionTool) public ~InDetTrackSelectionTool()
Create a proper constructor for Athena.
static bool maxIntIsSet(int cutValue)
Gaudi::Property< std::vector< int > > m_vecMinNSiHitsAboveEta
Gaudi::Property< int > m_minNTrtHitsPlusOutliers
virtual void setCutLevel(InDet::CutLevel level, bool overwrite=true) override __attribute__((deprecated("For consistency with the athena interface
Function to set the cut level within standalone ROOT.
Gaudi::Property< double > m_maxTrtEtaAcceptance
Gaudi::Property< std::vector< double > > m_vecPtCutoffsForZ0SinThetaCut
Gaudi::Property< double > m_maxTrtHighEFractionWithOutliers
void setCutLevelPrivate(InDet::CutLevel level, bool overwrite=true)
Gaudi::Property< double > m_maxSigmaZ0
Gaudi::Property< std::vector< std::vector< double > > > m_vecvecMaxD0AboveEtaPt
Gaudi::Property< std::vector< double > > m_vecEtaCutoffsForZ0SinThetaCut
Class describing the Line to which the Perigee refers to.
A summary of the information contained by a track.
This class is a simplest representation of a vertex candidate.
void setCutResult(const std::string &cutName, bool cutResult)
Set the result of a cut, based on the cut name (safer).
Definition AcceptData.h:134
bool getCutResult(const std::string &cutName) const
Get the result of a cut, based on the cut name (safer).
Definition AcceptData.h:98
Class mimicking the AthMessaging class from the offline software.
virtual StatusCode initialize()
Dummy implementation of the initialisation function.
Definition AsgTool.h:133
Class providing the definition of the 4-vector interface.
Int_t getNumberOfUsedHitsdEdx(Trk_Helper &helper, const asg::AsgMessaging &msgHelper)
std::tuple< uint8_t, uint8_t > getSiHitsTopBottom(const Trk::Track &track, const asg::AsgMessaging &msgHelper)
double getFitChiSquare(const Trk_Helper &helper, const asg::AsgMessaging &msgHelper)
Int_t getNumberOfIBLOverflowsdEdx(Trk_Helper &helper, const asg::AsgMessaging &msgHelper)
uint8_t getSummarySum(const T_TrkHelper helper, const asg::AsgMessaging &msgHelper, std::array< xAOD::SummaryType, n_summary_types > sumTypes)
double getFitNDoF(const TrkHelper &helper, const asg::AsgMessaging &msgHelper)
float getEProbabilityHT(const Trk_Helper &helper, const asg::AsgMessaging &msgHelper)
uint8_t getSummary(const T_TrkHelper &helper, const asg::AsgMessaging &msgHelper, xAOD::SummaryType sumType)
bool absEta(const xAOD::TauJet &tau, float &out)
@ anyDirection
ParametersBase< TrackParametersDim, Charged > TrackParameters
@ TrackParticle
The object is a charged track particle.
Definition ObjectType.h:43
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Vertex_v1 Vertex
Define the latest version of the vertex class.
@ expectInnermostPixelLayerHit
Do we expect a 0th-layer barrel hit for this track?
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
@ numberOfTRTHighThresholdOutliers
number of TRT high threshold outliers (only xenon counted) [unit8_t].
@ numberOfInnermostPixelLayerSharedHits
number of Pixel 0th layer barrel hits shared by several tracks.
@ numberOfTRTXenonHits
number of TRT hits on track in straws with xenon [unit8_t].
@ numberOfTRTHits
number of TRT hits [unit8_t].
@ numberOfNextToInnermostPixelLayerHits
these are the hits in the 1st pixel barrel layer
@ numberOfSCTDeadSensors
number of dead SCT sensors crossed [unit8_t].
@ expectNextToInnermostPixelLayerHit
Do we expect a 1st-layer barrel hit for this track?
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfSCTDoubleHoles
number of Holes in both sides of a SCT module [unit8_t].
@ numberOfInnermostPixelLayerHits
these are the hits in the 0th pixel barrel layer
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
@ numberOfPixelSharedHits
number of Pixel all-layer hits shared by several tracks [unit8_t].
@ numberOfSCTSharedHits
number of SCT hits shared by several tracks [unit8_t].
@ numberOfTRTHighThresholdHits
number of TRT hits which pass the high threshold (only xenon counted) [unit8_t].
@ numberOfTRTOutliers
number of TRT outliers [unit8_t].
@ numberOfPixelDeadSensors
number of dead pixel sensors crossed [unit8_t].
@ numberOfSCTHoles
number of SCT holes [unit8_t].